Polymer data binding across elements not working in Chrome dev / canary - polymer

I've been happily developing an app in Polymer. All is going well, but some fairly basic stuff isn't working in Chrome Dev and Chrome Canary, is this expected?
Here's a reduction of what I'm seeing [codepen to try it out yourself]:
<script src="http://www.polymer-project.org/platform.js"></script></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<my-app></my-app>
<polymer-element name='my-app'>
<template>
<my-processor input='{{input}}' output='{{output}}'>
<input value='{{input}}'> <br>
Input: {{input}} <br>
Processed: {{output}}
</template>
<script>
Polymer('my-app', { 'input': 'hello world', });
</script>
</polymer-element>
<polymer-element name='my-processor' attributes='input output'>
<script>
Polymer('my-processor', {
inputChanged: function() {
this.output = this.input + ' (processed)';
}
});
</script>
</polymer-element>
In Chrome Dev and Canary the processed output is never displayed. I've used the debugger to see that inputChanged does fire on the my-processor element, but my-app never gets the updated output value.
In Chrome 34, Safari and Firefox everything works as expected and the processed output is displayed as expected.

As per the warning in the console, it's important that the the my-processor definitions comes prior to my-app that uses it. my-processor needs to be registered first for the bindings to be picked up properly.
http://jsbin.com/xovegoga/3/edit

Related

Handling of loading indicator for multiple ajax calls in Polymer

I'm using Polymer 1.0 to create a web application.
I have various elements doing one or more iron-ajax calls and I have another element for showing the loading-overlay. But in my current sollution I have added the loading-overlay, with its logic to show or not, to every element doing ajax calls.
<dom-module id="backend-call-application">
<template>
<iron-ajax id='loadA' loading="{{_loadingA}}" ...></iron-ajax>
<iron-ajax id='loadB' loading="{{_loadingB}}" ...></iron-ajax>
<loading-overlay id="loadingOverlay" with-backdrop></loading-overlay>
</template>
<script>
Polymer({
is: 'backend-call-application',
observers:[
"_isXhrLoading(_loadingA,_loadingB,....)"
],
_isXhrLoading: function() {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i]) {
this.$.loadingOverlay.open()
return;
}
}
this.$.loadingOverlay.close()
}
});
</script>
</dom-module>
Now my question is, what is the best way to show such a loading-overlay?
One idea of mine would be, to have something like an observer in the loading overlay. So every element doing requests will bind its properties to the observer. These properties could be stored in an array and everytime on change, the loading-overlay checks if at least one have loading properties set to true. When one or more properties are true the loading-overlay will be opened and when all requests finished loading it will be closed.
Another idea was to use events to tell the loading-overlay when a element starts/stops loading. But here will be the problem, that I have more than one request at the same time (The first request closes the overlay, but the page hasn't finished loading).
Edit:
The loading-overlay is an element containing the IronOverlayBehavior.
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-overlay-behavior/iron-overlay-behavior.html">
<link rel="import" href="../../../bower_components/paper-spinner/paper-spinner.html">
<dom-module id="loading-overlay">
<template>
<paper-spinner active="true"></paper-spinner>
</template>
<script>
Polymer({
is: 'loading-overlay',
behaviors: [
Polymer.IronOverlayBehavior
]
});
</script>
</dom-module>
use one property for loading instead of 2!!
<iron-ajax id='loadA' loading="{{_loading}}" ...></iron-ajax>
<iron-ajax id='loadB' loading="{{_loading}}" ...></iron-ajax>
bind loading value to loading-overlay with some attribute and when loading is true display loader
<loading-overlay id="loadingOverlay" is-loading="[[_loading]]" with-backdrop></loading-overlay>
so each time any ajax is made then _loading will become true so displays loader
I think the only thing you could shorten is the _isXhrLoading observer.
_isXhrLoading: function() {
if(Array.from(arguments).indexOf(true) >= 0) {
this.$.loadingOverlay.open()
} else {
this.$.loadingOverlay.close()
}
}

Using polymer with external js files

I want to use trumbowyg.js in my polymer element, it includes jquery.js and trumbowyg.js. It works fine in Firefox but not in chrome.
It gives error, may be because shadow dom lookup/separation in chrome. The error happens where ever trumbowyg.js uses "this".
Whats going wrong here? What should I do differently?
I am using Polymer 2.0
error:
Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
at trumbowyg.js:1544
my-notes.html
<link rel="import" href="../polymer/polymer-element.html">
<link rel="import" href="../bower_components/trumbowyg/trumbowyg.html">
<dom-module id="my-notes">
<template>
<link rel="stylesheet" href="../bower_components/trumbowyg/dist/ui/trumbowyg.min.css">
<firebase-auth user="{{user}}" signed-in="{{signedIn}}"></firebase-auth>
<div class="card">
<div id="trumbowygd">hello</div>
</div>
</template>
<script>
class MyNotes extends Polymer.Element {
static get is() { return 'my-notes'; }
static get properties() {
return {
user: {
type: Object,
observer: '_shownotearea'
},
};
}
_shownotearea(){
var myFineElement = this.$.trumbowygd;
myFineElement.innerHTML="hello nice meeting you";
$(myFineElement).trumbowyg({});
}
</script>
</dom-module>
trumbowyg.html
<script src="../jquery/dist/jquery.min.js"></script>
<script src="dist/trumbowyg.js"></script>
This doesnt seem to be working
jQuery plugins and Polymer elements
The short answer is this plugin probably won't work with native Shadow DOM.
Likely trumbowyg is trying to query the document to look for some element. Shadow DOM creates markup encapsulation so you can't use $() or document.querySelector to look for things inside of shadow roots. In general I recommend not using jQuery plugins inside of Shadow DOM for this reason.

How to force Polymer to use polyfill

Since Polymer 1.0 release I start to get a different initialization order between Chrome and other browsers (Firefox, barebone WebKit). Although the 1.0 docs say "there are no guarantees with regard to initialization timing", in version 0.5 I didn't have such issue.
index.html:
<script src="components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="name-tag.html">
<body onload="console.log('body onload');">
<name-tag></name-tag>
</body>
name-tag.html:
<link rel="import" href="components/polymer/polymer.html">
<dom-module id="name-tag">
<template></template>
<script>
Polymer({
is: "name-tag",
ready: function() {
console.log("polymer ready");
}
});
</script>
</dom-module>
Chrome 44:
polymer ready
body onload
Firefox 39, QWebView (Qt5.4, WebKit):
body onload
polymer ready
What I have already tried:
window.WebComponents = {flags: {register: true, polyfill: true}}; (register used to be in Polymer)
window.Polymer.Settings = {useNativeShadow: false};
attached callback with this.async()
window.Polymer.dom = 'shadow' forces Polymer to use the shadow DOM by default (either the polyfilled one if you used webcomponents.js or natively if you used webcomponents-lite.js instead).

Polymer: how to parse the index to the elements using template repeat

I've been trying to use Polymer for a project I'm working on. And although I enjoyed it quite a lot so far, I ran into a problem I just can't solve.
I dumped it down to a simple example. Basically it's just a list element (item-list) that contains item elements (item-card) and i want to parse the items position to the element via the attribute pos. But for some reason the items attribute is allways undefined! Is this because the attribute is bound to the variable i, which dies after the template repeat? If so, how do I work around it? Is there a different approach I should be using here?
SOLUTION: You can find the solution by reading through all the comments, but to sum it up: apperantly there was a timing issue and the attribute wasn't ready at the ready callback. But I found out about the domReady callback (polymer lifecycle documentation). Using domReady it works just fine! Thanks to Günter Zöchbauer for the help!
This is the item-list.html:
<link rel="import" href="components/polymer/polymer.html">
<link rel="import" href="item-card.html">
<polymer-element name="item-list">
<template>
<style>
</style>
<template repeat="{{values, i in data.data}}">
<item-card pos="{{i}}"></item-card>
</template>
</template>
<script>
Polymer({
created: function()
{
this.num = 123456;
this.data = { "data":
[
{
"value":999
},
{
"value":666
},
{
"value":555
},
{
"value":222
}
]
};
}
});
</script>
</polymer-element>
This is the item-card.html
<link rel="import" href="components/polymer/polymer.html">
<polymer-element name="item-card" attributes="pos">
<template>
<style>
</style>
</template>
<script>
Polymer({
ready: function()
{
console.log("ready: " + this.pos);
}
});
</script>
</polymer-element>
I didn't bother putting the index.html in, since it just containts one item-list element.
Thanks alot!!
I think you need a pos field in <item-card> in addition to the attributes="pos" declaration.
The repeated element also references the bound model which can be accessed like querySelector('item-card').templateInstance.model property.
See https://github.com/PolymerLabs/polymer-selector/blob/master/polymer-selector.html#L286 for an example.
Info:
According to the comments it turned out to be a timing issue. The value wasn't yet assigned when the ready callback was called but using domReady worked.

Fabric.js canvas not catching mouse events on Google Chrome

Googled this a lot and didn't get any useful hint/solution.
I have this simple html page including some CSS styles, jQuery, jQuery-ui and obviously Fabric.js; on document.ready I launch an ajax call and render something on the canvas. Until now everything seems fine but when a I need to catch some mouse events I get nothing. This behaviour is shown only on Chrome (current version 25.0.1364.97); everything works fine on Firefox or Internet Explorer (v. 9).
Here's some of the js code:
$(document).ready(function() {
//setup canvas etc.
eCanvas = new fabric.Canvas('EViewport', {
backgroundColor: 'rgba(255, 50, 50, .3)',
selection: true,
selectionColor: 'blue',
selectionLineWidth: 2
});
EViewport = $("#CanvasContainer");
viewW = EViewport.width();
viewH = EViewport.height();
eCanvas.setWidth(viewW);
eCanvas.setHeight(viewH);
eCanvas.observe('object:selected', function(options) {
if (options.target) {
console.log('an object was selected! ', options.target.type);
}
});
eCanvas.observe('mouse:down', function() {
console.log('mouse click! ');
});
eCanvas.on('mouse:down', function() {
console.log('mouse click! ');
});
eCanvas.on('mousedown', function() {
console.log('mouse click! ');
});
//... render some rectangles and stuff...
});
And here's the html structure (notice that Eviewport.js file contains previously pasted code):
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="baseCss/jquery-ui.css" type="text/css">
<script type="text/javascript" src="baseJs/jquery.js"></script>
<script type="text/javascript" src="baseJs/jquery-ui.js"></script>
<script type="text/javascript" src="Eviewport.js"></script>
<link type="text/css" rel="stylesheet" href="Eviewport.css">
<script type="text/javascript" src="baseJs/Fabric.js"></script>
</head>
<body>
<div id="MainContainer">
<div id="CanvasContainer">
<canvas id="EViewport">
Canvas is not supported
</canvas>
</div>
</div>
</body>
</html>
Selection features don't work with chrome either while they work on IE and Firefox.
I tried many things (as you can see I tried changing canvas.observe with canvas.on), changed jQuery and jQueryui versions but nothing changed.
Using developer tools on Google Chrome doesn't show much.
There's no z-index on html elements given by CSS, and I tried disabling different js and CSS but that didn't solve the problem.
I noticed that the problem shows also shows on the demo page of Fabric.js (just tried http://fabricjs.com/stickman/); render works, effects also but no mouse events or selection working.
Is this a bug?
Ok, finally found what's not working.
I have a Wacom device attached and looks like latest Chrome version sets a flag about "touch enabled device" and that's breaking my code.
A simple solution can be changing chrome flags (chrome://flags/)
Related posts:
https://github.com/kangax/fabric.js/issues/450