From b9bead5efe0e7f7e704f365b7c55901416d69a3c Mon Sep 17 00:00:00 2001 From: Rafael Weinstein Date: Mon, 13 Jan 2014 16:04:08 -0800 Subject: [PATCH] add on- event bindings R=arv BUG= Review URL: https://codereview.appspot.com/51740043 --- src/polymer-expressions.js | 47 ++++++++++++++++++++++++++++++ tests/tests.js | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/polymer-expressions.js b/src/polymer-expressions.js index 45e4547..21ac3f6 100644 --- a/src/polymer-expressions.js +++ b/src/polymer-expressions.js @@ -444,6 +444,43 @@ }); } + function isEventHandler(name) { + return name[0] === 'o' && + name[1] === 'n' && + name[2] === '-'; + } + + function prepareEventBinding(path, name) { + var eventType = name.substring(3); + + return function(model, node, oneTime) { + var fn = path.getValueFrom(model); + + function handler() { + if (!oneTime) + fn = path.getValueFrom(model); + fn.apply(model, arguments); + } + + node.addEventListener(eventType, handler); + + if (oneTime) + return; + + function bindingValue() { + return '{{ ' + path + ' }}'; + } + + return { + open: bindingValue, + discardChanges: bindingValue, + close: function() { + node.removeEventListener(eventType, handler); + } + }; + } + } + function PolymerExpressions() {} PolymerExpressions.prototype = { @@ -477,6 +514,16 @@ }, prepareBinding: function(pathString, name, node) { + if (isEventHandler(name)) { + var path = Path.get(pathString); + if (!path.valid) { + console.error('on-* bindings must be simple path expressions'); + return; + } + + return prepareEventBinding(path, name); + } + if (Path.get(pathString).valid) return; // bail out early if pathString is simple path. diff --git a/tests/tests.js b/tests/tests.js index e9103ae..dcdf170 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -1544,6 +1544,64 @@ suite('PolymerExpressions', function() { }); }); + test('on-* event bindings', function(done) { + var div = createTestHtml( + ''); + + var model = { + callCount: 0, + receiverValue: undefined, + handleFoo: function() { + this.callCount++; + this.receiverValue = 'foo'; + }, + bar: { + handleBar: function() { + this.callCount++; + this.receiverValue = 'bar'; + } + }, + handleBaz: function() { + this.callCount++; + this.receiverValue = 'baz'; + } + }; + + recursivelySetTemplateModel(div, model); + + then(function() { + var target = div.childNodes[1]; + + dispatchEvent('foo', target); + assert.strictEqual(1, model.callCount); + assert.strictEqual('foo', model.receiverValue); + + dispatchEvent('bar', target); + assert.strictEqual(2, model.callCount); + assert.strictEqual('bar', model.receiverValue); + + dispatchEvent('baz', target); + assert.strictEqual(3, model.callCount); + assert.strictEqual('baz', model.receiverValue); + + // should be ignored because of one-time binding + model.handleBaz = function() { + this.receiverValue = 'newBaz'; + }; + + dispatchEvent('baz', target); + assert.strictEqual(4, model.callCount); + assert.strictEqual('baz', model.receiverValue); + + done(); + }); + }); + test('Non-model path expressions', function() { assert.isFalse(getExpression_('a + b').nonModelPath); assert.isFalse(getExpression_('a + b > 3 + hello["kitty"]').nonModelPath);