Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Add support for one way filters
Browse files Browse the repository at this point in the history
Filters are written as:

<template bind>
  {{ user.age | filter1 | filter2() | filter3(21, 'Hi') }}
</template>

To register a filter do:

PolymerExpressions.filters.filter3 = function(n, s) {
  return {
    toDOM: function(value) {
      if (value >= n)
        return s + '! Have a beer.';
      return 'Come back in ' + (n - value) + ' years';
    }
  };
};

BUG=
R=rafaelw@chromium.org

Review URL: https://codereview.appspot.com/12926044
  • Loading branch information
arv committed Aug 16, 2013
1 parent 1c31d44 commit 91b6035
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 12 deletions.
36 changes: 31 additions & 5 deletions src/polymer-expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@
// is that ECMAScript indentifiers are more limited than CSS classnames.
var resolveFn = delegate.labeledStatements.length ?
newLabeledResolve(delegate.labeledStatements) :
resolveFn = delegate.expression;
delegate.expression;

delegate.filters.forEach(function(filter) {
resolveFn = filter.toDOM(resolveFn);
});

var paths = [];
for (var prop in delegate.deps) {
Expand Down Expand Up @@ -180,8 +184,31 @@
function Filter(name, args) {
this.name = name;
this.args = args;
this.object_ = null;
}

Filter.prototype = {
get object() {
if (this.object_)
return this.object_;

var f = PolymerExpressions.filters[this.name];
var argumentValues = this.args.map(function(arg) {
var fn = getFn(arg);
return fn();
});
return this.object_ = f.apply(null, argumentValues);
},

toDOM: function(fn) {
var object = this.object;
return function(values) {
var value = fn(values);
return object.toDOM(value);
}
}
};

function ASTDelegate() {
this.expression = null;
this.filters = [];
Expand Down Expand Up @@ -316,10 +343,7 @@
},

createFilter: function(name, args) {
var argValues = args.map(function(f) {
return f();
});
this.filters.push(new Filter(name, argValues));
this.filters.push(new Filter(name, args));
},

createTopLevel: function(expression) {
Expand All @@ -331,6 +355,8 @@

function PolymerExpressions() {}

PolymerExpressions.filters = Object.create(null);

PolymerExpressions.prototype = {
getBinding: function(model, pathString, name, node) {
pathString = pathString.trim();
Expand Down
72 changes: 65 additions & 7 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ suite('PolymerExpressions', function() {
unbindAll(testDiv);
Platform.performMicrotaskCheckpoint();
assert.strictEqual(4, Observer._allObserversCount);

delete PolymerExpressions.filters.hex;
delete PolymerExpressions.filters.toFixed;
delete PolymerExpressions.filters.upperCase;
});

function hasClass(node, className) {
Expand Down Expand Up @@ -75,6 +79,33 @@ suite('PolymerExpressions', function() {
});
}

function hex() {
return {
toDOM: function(value) {
return Number(value).toString(16);
},
toModel: function(value) {
return parseInt(value, 16);
}
};
}

function toFixed(fractions) {
return {
toDOM: function(value) {
return Number(value).toFixed(fractions);
}
};
}

function upperCase() {
return {
toDOM: function(value) {
return String(value).toUpperCase();
}
};
}

test('ClassName Singular', function() {
var div = createTestHtml(
'<template bind><div class="{{ foo: bar }}">' +
Expand Down Expand Up @@ -530,6 +561,8 @@ suite('PolymerExpressions', function() {
});

test('filter without arguments', function() {
PolymerExpressions.filters.upperCase = upperCase;

var div = createTestHtml(
'<template bind="{{ }}">' +
'{{ bar | upperCase }}' +
Expand All @@ -542,30 +575,55 @@ suite('PolymerExpressions', function() {

recursivelySetTemplateModel(div, model);
Platform.performMicrotaskCheckpoint();
assert.equal('batbat', div.childNodes[1].textContent);
assert.equal('BATBAT', div.childNodes[1].textContent);

model.bar = 'blat';
Platform.performMicrotaskCheckpoint();
assert.equal('blatblat', div.childNodes[1].textContent);
assert.equal('BLATBLAT', div.childNodes[1].textContent);
});

test('filter with arguments', function() {
PolymerExpressions.filters.toFixed = toFixed;

var div = createTestHtml(
'<template bind="{{ }}">' +
'{{ bar | toFixed(2) }}' +
'{{ bar | toFixed(4) }}' +
'</template>');

var model = {
bar: 'bat'
bar: 1.23456789
};

recursivelySetTemplateModel(div, model);
Platform.performMicrotaskCheckpoint();
assert.equal('bat', div.childNodes[1].textContent);
assert.equal('1.2346', div.childNodes[1].textContent);

model.bar = 'blat';
model.bar = 9.87654321;
Platform.performMicrotaskCheckpoint();
assert.equal('9.8765', div.childNodes[1].textContent);
});

test('chained filters', function() {
PolymerExpressions.filters.hex = hex;
PolymerExpressions.filters.toFixed = toFixed;
PolymerExpressions.filters.upperCase = upperCase;

var div = createTestHtml(
'<template bind="{{ }}">' +
'{{ bar | toFixed(0) | hex | upperCase }}' +
'</template>');

var model = {
bar: 12.34
};

recursivelySetTemplateModel(div, model);
Platform.performMicrotaskCheckpoint();
assert.equal('C', div.childNodes[1].textContent);

model.bar = 14.56;
Platform.performMicrotaskCheckpoint();
assert.equal('blat', div.childNodes[1].textContent);
assert.equal('F', div.childNodes[1].textContent);
});

test('filter unexpected EOF', function() {
Expand Down

0 comments on commit 91b6035

Please sign in to comment.