diff --git a/src/features/micro/attributes.html b/src/features/micro/attributes.html
index c8206454..98550331 100644
--- a/src/features/micro/attributes.html
+++ b/src/features/micro/attributes.html
@@ -127,29 +127,32 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
- // Convert value to string based on type
- // Return undefined to indicate attribute should be removed
- serialize: function(name, value, type) {
- switch (type) {
- case Object:
- case Array:
- return value ? JSON.stringify(value) : undefined;
-
- case Boolean:
+ serialize: function(value) {
+ switch (typeof value) {
+ case 'boolean':
return value ? '' : undefined;
-
+ case 'object':
+ if (value instanceof Date) {
+ return value;
+ } else {
+ return value ? JSON.stringify(value) : undefined;
+ }
default:
return value != null ? value : undefined;
}
},
reflectPropertyToAttribute: function(name) {
- var type = this.getPublishedPropertyType(name);
- var value = this.serialize(name, this[name], type);
+ this.serializeValueToAttribute(this[name], name);
+ },
+
+ serializeValueToAttribute: function(value, attribute, node) {
+ node = node || this;
+ value = this.serialize(value);
if (value !== undefined) {
- this.setAttribute(name, value);
+ node.setAttribute(attribute, value);
} else {
- this.removeAttribute(name);
+ node.removeAttribute(attribute);
}
}
diff --git a/src/features/standard/notify-path.html b/src/features/standard/notify-path.html
index a302048c..087fa3bd 100644
--- a/src/features/standard/notify-path.html
+++ b/src/features/standard/notify-path.html
@@ -97,9 +97,8 @@ using('Base', function(Base) {
if (parts.length > 1) {
var last = parts.pop();
var prop = this;
- while (parts.length && (prop=prop[parts.shift()])) {
- // TODO(sjmiles): can't ever get here if !prop because of the
- // while conditional
+ while (parts.length) {
+ prop = prop[parts.shift()];
if (!prop) {
return;
}
@@ -118,7 +117,8 @@ using('Base', function(Base) {
var parts = path.split('.');
var last = parts.pop();
var prop = this;
- while (parts.length && (prop=prop[parts.shift()])) {
+ while (parts.length) {
+ prop = prop[parts.shift()];
if (!prop) {
return;
}
@@ -146,10 +146,14 @@ using('Base', function(Base) {
var effect = x.effect;
var n = this._nodeForBinding(effect);
if (n) {
- if (effect.value === path) {
- n[effect.name || 'textContent'] = effect.negate ? !value : value;
- } else if (effect.value.indexOf(path + '.') == 0) {
- n[effect.name || 'textContent'] = this.getPath(effect.value);
+ if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
+ var v = (effect.value === path) ? value : this.getPath(effect.value);
+ v = effect.negate ? !v : v;
+ if (effect.kind == 'property') {
+ n[effect.name || 'textContent'] = v;
+ } else { // attribute
+ this.serializeValueToAttribute(v, effect.name, n);
+ }
// path == item.stuff.count
// value == item.stuff
// name == zizz
diff --git a/src/lib/annotations/annotations.html b/src/lib/annotations/annotations.html
index 56ebc89e..5b38f6c7 100644
--- a/src/lib/annotations/annotations.html
+++ b/src/lib/annotations/annotations.html
@@ -174,22 +174,29 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_parseNodeAttributeAnnotation: function(node, n, v) {
- var mode = '', escape = v.slice(0, 2);
+ var mode = '', escape = v.slice(0, 2), name = n;
if (escape === '{{' || escape === '[[') {
+ // Mode (one-way or two)
mode = escape[0];
v = v.slice(2, -2);
- }
- var not = false;
- if (v[0] == '!') {
- v = v.substring(1);
- not = true;
- }
- if (mode) {
+ // Negate
+ var not = false;
+ if (v[0] == '!') {
+ v = v.substring(1);
+ not = true;
+ }
+ // Attribute or property
+ var attr = false;
+ if (n[n.length-1] == '$') {
+ name = n.slice(0, -1);
+ attr = true;
+ }
+ // Remove annotation
node.removeAttribute(n);
return {
- kind: 'property',
+ kind: attr ? 'attribute' : 'property',
mode: mode,
- name: n,
+ name: name,
value: v,
negate: not
};
diff --git a/src/lib/bind/bind-effects.html b/src/lib/bind/bind-effects.html
index d84e2e4a..6656f9d8 100644
--- a/src/lib/bind/bind-effects.html
+++ b/src/lib/bind/bind-effects.html
@@ -27,7 +27,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
};
Bind._shouldAddListener = function(info) {
- return info.name && info.mode === '{' && !info.negate;
+ return info.name &&
+ info.mode === '{' &&
+ !info.negate &&
+ info.kind != 'attribute';
};
Bind.addBuilders({
@@ -125,8 +128,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
;
value = 'val';
}
- return setData + 'this._nodes[' + info.index + '].' + property + ' = '
- + (info.negate ? '!' : '') + value + ';';
+ value = (info.negate ? '!' : '') + value;
+ var node = 'this._nodes[' + info.index + ']';
+ if (info.kind == 'property') {
+ return setData + node + '.' + property + ' = ' + value + ';';
+ } else {
+ return setData + 'this.serializeValueToAttribute(' + value + ',' +
+ '\'' + property + '\',' + node + ');';
+ }
}
});
diff --git a/test/unit/bind-elements.html b/test/unit/bind-elements.html
index e2afa607..9fba1023 100644
--- a/test/unit/bind-elements.html
+++ b/test/unit/bind-elements.html
@@ -1,5 +1,5 @@
-
+
diff --git a/test/unit/notify-path-elements.html b/test/unit/notify-path-elements.html
index c765ba70..9eb7396b 100644
--- a/test/unit/notify-path-elements.html
+++ b/test/unit/notify-path-elements.html
@@ -11,9 +11,9 @@
-
-
-
+
+
+
-
+
diff --git a/test/unit/notify-path.html b/test/unit/notify-path.html
index 476bf785..658e13dd 100644
--- a/test/unit/notify-path.html
+++ b/test/unit/notify-path.html
@@ -64,6 +64,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.forward.$.compose.obj, nested.obj);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from basic element property change', function() {
@@ -94,6 +99,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from composed element property change', function() {
@@ -124,6 +134,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from forward\'s composed element property change', function() {
@@ -154,6 +169,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from setPath in top element', function() {
@@ -184,6 +204,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from setPath in composed element', function() {
@@ -214,6 +239,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from setPath in forward element', function() {
@@ -244,6 +274,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from setPath in forward\'s composed element', function() {
@@ -274,6 +309,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from object change in compose element', function() {
@@ -308,6 +348,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from object change in forward element', function() {
@@ -342,6 +387,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('notification from object change in forward\'s compose element', function() {
@@ -376,6 +426,11 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic2.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, 42);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, 42);
+ assert.equal(el.$.basic.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.compose.$.basic2.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic1.getAttribute('attrvalue'), '42');
+ assert.equal(el.$.forward.$.compose.$.basic2.getAttribute('attrvalue'), '42');
});
test('negation', function() {
@@ -391,6 +446,14 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic3.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, false);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, false);
+ assert.equal(el.$.forward.$.compose.$.basic3.notifyingvalue, true);
+ assert.equal(el.$.basic.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), true);
el.$.basic.notifyingvalue = true;
assert.equal(el.$.basic.notifyingvalue, true);
@@ -399,6 +462,14 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic3.notifyingvalue, false);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, true);
+ assert.equal(el.$.forward.$.compose.$.basic3.notifyingvalue, false);
+ assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);
el.$.forward.$.compose.$.basic1.notifyingvalue = false;
assert.equal(el.$.basic.notifyingvalue, false);
@@ -407,6 +478,14 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic3.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, false);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, false);
+ assert.equal(el.$.forward.$.compose.$.basic3.notifyingvalue, true);
+ assert.equal(el.$.basic.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), true);
el.setPath('nested.obj.value', true);
assert.equal(el.$.basic.notifyingvalue, true);
@@ -415,6 +494,14 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic3.notifyingvalue, false);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, true);
+ assert.equal(el.$.forward.$.compose.$.basic3.notifyingvalue, false);
+ assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);
// no two way binding through negation
el.$.compose.$.basic3.notifyingvalue = true;
@@ -424,6 +511,14 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic3.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingvalue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingvalue, true);
+ assert.equal(el.$.forward.$.compose.$.basic3.notifyingvalue, false);
+ assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
+ assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
+ assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);
});
@@ -445,6 +540,47 @@ suite('basic path bindings', function() {
assert.equal(el.$.compose.$.basic1.othervalue, 98);
});
+ test('getPath', function() {
+ el.simple = 11;
+ el.nested = {
+ again: {
+ again: {
+ wayOverThere: 99
+ },
+ there: 55
+ },
+ here: 42
+ };
+ assert.equal(el.getPath('simple'), 11);
+ assert.equal(el.getPath('nested'), el.nested);
+ assert.equal(el.getPath('nested.here'), 42);
+ assert.equal(el.getPath('nested.again'), el.nested.again);
+ assert.equal(el.getPath('nested.again.there'), 55);
+ assert.equal(el.getPath('nested.again.again'), el.nested.again.again);
+ assert.equal(el.getPath('nested.again.again.wayOverThere'), 99);
+ });
+
+ test('setPath', function() {
+ el.setPath('simple', 11);
+ el.setPath('nested', {});
+ el.setPath('nested.here', 42);
+ el.setPath('nested.again', {});
+ el.setPath('nested.again.there', 55);
+ el.setPath('nested.again.again', {});
+ el.setPath('nested.again.again.wayOverThere', 99);
+ assert.equal(el.simple, 11);
+ assert.equal(el.getPath('simple'), 11);
+ assert.equal(el.getPath('nested'), el.nested);
+ assert.equal(el.nested.here, 42);
+ assert.equal(el.getPath('nested.here'), 42);
+ assert.equal(el.getPath('nested.again'), el.nested.again);
+ assert.equal(el.nested.again.there, 55);
+ assert.equal(el.getPath('nested.again.there'), 55);
+ assert.equal(el.getPath('nested.again.again'), el.nested.again.again);
+ assert.equal(el.nested.again.again.wayOverThere, 99);
+ assert.equal(el.getPath('nested.again.again.wayOverThere'), 99);
+ });
+
});