Merge branch 'master' into style-fixes

This commit is contained in:
Steven Orvell 2016-02-11 10:26:28 -08:00
commit a61028ea49
29 changed files with 1730 additions and 1702 deletions

5
.eslintignore Normal file
View File

@ -0,0 +1,5 @@
node_modules/*
bower_components/*
test/*
src/**/demo/*
src/**/experimental/*

17
.eslintrc.json Normal file
View File

@ -0,0 +1,17 @@
{
"extends": "eslint:recommended",
"rules": {
"no-console": 0
},
"env": {
"browser": true
},
"plugins": [
"html"
],
"globals": {
"CustomElements": true,
"HTMLImports": true,
"Polymer": true
}
}

View File

@ -15,6 +15,7 @@ before_script:
- npm install -g bower - npm install -g bower
- bower install - bower install
script: script:
- gulp lint
- xvfb-run wct - xvfb-run wct
- "if [ \"${TRAVIS_PULL_REQUEST}\" = \"false\" ]; then wct -s 'default'; fi" - "if [ \"${TRAVIS_PULL_REQUEST}\" = \"false\" ]; then wct -s 'default'; fi"
env: env:

View File

@ -20,6 +20,7 @@ var runseq = require('run-sequence');
var lazypipe = require('lazypipe'); var lazypipe = require('lazypipe');
var polyclean = require('polyclean'); var polyclean = require('polyclean');
var del = require('del'); var del = require('del');
var eslint = require('gulp-eslint');
var path = require('path'); var path = require('path');
@ -124,3 +125,10 @@ gulp.task('audit', function() {
gulp.task('release', function(cb) { gulp.task('release', function(cb) {
runseq('default', ['copy-bower-json', 'audit'], cb); runseq('default', ['copy-bower-json', 'audit'], cb);
}); });
gulp.task('lint', function() {
return gulp.src('src/**/*.html')
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});

View File

@ -9,8 +9,10 @@
}, },
"devDependencies": { "devDependencies": {
"del": "^1.1.1", "del": "^1.1.1",
"eslint-plugin-html": "^1.3.0",
"gulp": "^3.8.11", "gulp": "^3.8.11",
"gulp-audit": "^1.0.0", "gulp-audit": "^1.0.0",
"gulp-eslint": "^1.1.1",
"gulp-rename": "^1.2.2", "gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.3", "gulp-replace": "^0.5.3",
"gulp-vulcanize": "^6.0.1", "gulp-vulcanize": "^6.0.1",
@ -21,7 +23,7 @@
}, },
"scripts": { "scripts": {
"build": "gulp", "build": "gulp",
"test": "wct", "test": "gulp lint && wct",
"test-build": "gulp switch && wct && gulp restore" "test-build": "gulp switch && wct && gulp restore"
}, },
"repository": { "repository": {

View File

@ -1,391 +1,391 @@
<!-- <!--
@license @license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved. Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--> -->
<link rel="import" href="../case-map.html"> <link rel="import" href="../case-map.html">
<script> <script>
/** /**
* Scans a template to produce an annotation list that that associates * Scans a template to produce an annotation list that that associates
* metadata culled from markup with tree locations * metadata culled from markup with tree locations
* metadata and information to associate the metadata with nodes in an instance. * metadata and information to associate the metadata with nodes in an instance.
* *
* Supported expressions include: * Supported expressions include:
* *
* Double-mustache annotations in text content. The annotation must be the only * Double-mustache annotations in text content. The annotation must be the only
* content in the tag, compound expressions are not supported. * content in the tag, compound expressions are not supported.
* *
* <[tag]>{{annotation}}<[tag]> * <[tag]>{{annotation}}<[tag]>
* *
* Double-escaped annotations in an attribute, either {{}} or [[]]. * Double-escaped annotations in an attribute, either {{}} or [[]].
* *
* <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]> * <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]>
* *
* `on-` style event declarations. * `on-` style event declarations.
* *
* <[tag] on-<event-name>="annotation"><[tag]> * <[tag] on-<event-name>="annotation"><[tag]>
* *
* Note that the `annotations` feature does not implement any behaviors * Note that the `annotations` feature does not implement any behaviors
* associated with these expressions, it only captures the data. * associated with these expressions, it only captures the data.
* *
* Generated data-structure: * Generated data-structure:
* *
* [ * [
* { * {
* id: '<id>', * id: '<id>',
* events: [ * events: [
* { * {
* name: '<name>' * name: '<name>'
* value: '<annotation>' * value: '<annotation>'
* }, ... * }, ...
* ], * ],
* bindings: [ * bindings: [
* { * {
* kind: ['text'|'attribute'], * kind: ['text'|'attribute'],
* mode: ['{'|'['], * mode: ['{'|'['],
* name: '<name>' * name: '<name>'
* value: '<annotation>' * value: '<annotation>'
* }, ... * }, ...
* ], * ],
* // TODO(sjmiles): this is annotation-parent, not node-parent * // TODO(sjmiles): this is annotation-parent, not node-parent
* parent: <reference to parent annotation object>, * parent: <reference to parent annotation object>,
* index: <integer index in parent's childNodes collection> * index: <integer index in parent's childNodes collection>
* }, * },
* ... * ...
* ] * ]
* *
* @class Template feature * @class Template feature
*/ */
// null-array (shared empty array to avoid null-checks) // null-array (shared empty array to avoid null-checks)
Polymer.nar = []; Polymer.nar = [];
Polymer.Annotations = { Polymer.Annotations = {
// preprocess-time // preprocess-time
// construct and return a list of annotation records // construct and return a list of annotation records
// by scanning `template`'s content // by scanning `template`'s content
// //
parseAnnotations: function(template) { parseAnnotations: function(template) {
var list = []; var list = [];
var content = template._content || template.content; var content = template._content || template.content;
this._parseNodeAnnotations(content, list, this._parseNodeAnnotations(content, list,
template.hasAttribute('strip-whitespace')); template.hasAttribute('strip-whitespace'));
return list; return list;
}, },
// add annotations gleaned from subtree at `node` to `list` // add annotations gleaned from subtree at `node` to `list`
_parseNodeAnnotations: function(node, list, stripWhiteSpace) { _parseNodeAnnotations: function(node, list, stripWhiteSpace) {
return node.nodeType === Node.TEXT_NODE ? return node.nodeType === Node.TEXT_NODE ?
this._parseTextNodeAnnotation(node, list) : this._parseTextNodeAnnotation(node, list) :
// TODO(sjmiles): are there other nodes we may encounter // TODO(sjmiles): are there other nodes we may encounter
// that are not TEXT_NODE but also not ELEMENT? // that are not TEXT_NODE but also not ELEMENT?
this._parseElementAnnotations(node, list, stripWhiteSpace); this._parseElementAnnotations(node, list, stripWhiteSpace);
}, },
_bindingRegex: (function() { _bindingRegex: (function() {
var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$-*]*' + ')'; var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$-*]*' + ')';
var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')'; var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')'; var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')'; var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')'; var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')'; var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')'; var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
var ARGUMENT_LIST = '(?:' + '\\(\\s*' + var ARGUMENT_LIST = '(?:' + '\\(\\s*' +
'(?:' + ARGUMENTS + '?' + ')' + '(?:' + ARGUMENTS + '?' + ')' +
'\\)\\s*' + ')'; '\\)\\s*' + ')';
var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')'; // Group 3 var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')'; // Group 3
var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*'; var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
var CLOSE_BRACKET = '(?:]]|}})'; var CLOSE_BRACKET = '(?:]]|}})';
var NEGATE = '(?:(!)\\s*)?'; // Group 2 var NEGATE = '(?:(!)\\s*)?'; // Group 2
var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET; var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
return new RegExp(EXPRESSION, "g"); return new RegExp(EXPRESSION, "g");
})(), })(),
// TODO(kschaaf): We could modify this to allow an escape mechanism by // TODO(kschaaf): We could modify this to allow an escape mechanism by
// looking for the escape sequence in each of the matches and converting // looking for the escape sequence in each of the matches and converting
// the part back to a literal type, and then bailing if only literals // the part back to a literal type, and then bailing if only literals
// were found // were found
_parseBindings: function(text) { _parseBindings: function(text) {
var re = this._bindingRegex; var re = this._bindingRegex;
var parts = []; var parts = [];
var lastIndex = 0; var lastIndex = 0;
var m; var m;
// Example: "literal1{{prop}}literal2[[!compute(foo,bar)]]final" // Example: "literal1{{prop}}literal2[[!compute(foo,bar)]]final"
// Regex matches: // Regex matches:
// Iteration 1: Iteration 2: // Iteration 1: Iteration 2:
// m[1]: '{{' '[[' // m[1]: '{{' '[['
// m[2]: '' '!' // m[2]: '' '!'
// m[3]: 'prop' 'compute(foo,bar)' // m[3]: 'prop' 'compute(foo,bar)'
while ((m = re.exec(text)) !== null) { while ((m = re.exec(text)) !== null) {
// Add literal part // Add literal part
if (m.index > lastIndex) { if (m.index > lastIndex) {
parts.push({literal: text.slice(lastIndex, m.index)}); parts.push({literal: text.slice(lastIndex, m.index)});
} }
// Add binding part // Add binding part
// Mode (one-way or two) // Mode (one-way or two)
var mode = m[1][0]; var mode = m[1][0];
var negate = Boolean(m[2]); var negate = Boolean(m[2]);
var value = m[3].trim(); var value = m[3].trim();
var customEvent, notifyEvent, colon; var customEvent, notifyEvent, colon;
if (mode == '{' && (colon = value.indexOf('::')) > 0) { if (mode == '{' && (colon = value.indexOf('::')) > 0) {
notifyEvent = value.substring(colon + 2); notifyEvent = value.substring(colon + 2);
value = value.substring(0, colon); value = value.substring(0, colon);
customEvent = true; customEvent = true;
} }
parts.push({ parts.push({
compoundIndex: parts.length, compoundIndex: parts.length,
value: value, value: value,
mode: mode, mode: mode,
negate: negate, negate: negate,
event: notifyEvent, event: notifyEvent,
customEvent: customEvent customEvent: customEvent
}); });
lastIndex = re.lastIndex; lastIndex = re.lastIndex;
} }
// Add a final literal part // Add a final literal part
if (lastIndex && lastIndex < text.length) { if (lastIndex && lastIndex < text.length) {
var literal = text.substring(lastIndex); var literal = text.substring(lastIndex);
if (literal) { if (literal) {
parts.push({ parts.push({
literal: literal literal: literal
}); });
} }
} }
if (parts.length) { if (parts.length) {
return parts; return parts;
} }
}, },
_literalFromParts: function(parts) { _literalFromParts: function(parts) {
var s = ''; var s = '';
for (var i=0; i<parts.length; i++) { for (var i=0; i<parts.length; i++) {
var literal = parts[i].literal; var literal = parts[i].literal;
s += literal || ''; s += literal || '';
} }
return s; return s;
}, },
// add annotations gleaned from TextNode `node` to `list` // add annotations gleaned from TextNode `node` to `list`
_parseTextNodeAnnotation: function(node, list) { _parseTextNodeAnnotation: function(node, list) {
var parts = this._parseBindings(node.textContent); var parts = this._parseBindings(node.textContent);
if (parts) { if (parts) {
// Initialize the textContent with any literal parts // Initialize the textContent with any literal parts
// NOTE: default to a space here so the textNode remains; some browsers // NOTE: default to a space here so the textNode remains; some browsers
// (IE) evacipate an empty textNode following cloneNode/importNode. // (IE) evacipate an empty textNode following cloneNode/importNode.
node.textContent = this._literalFromParts(parts) || ' '; node.textContent = this._literalFromParts(parts) || ' ';
var annote = { var annote = {
bindings: [{ bindings: [{
kind: 'text', kind: 'text',
name: 'textContent', name: 'textContent',
parts: parts, parts: parts,
isCompound: parts.length !== 1 isCompound: parts.length !== 1
}] }]
}; };
list.push(annote); list.push(annote);
return annote; return annote;
} }
}, },
// add annotations gleaned from Element `node` to `list` // add annotations gleaned from Element `node` to `list`
_parseElementAnnotations: function(element, list, stripWhiteSpace) { _parseElementAnnotations: function(element, list, stripWhiteSpace) {
var annote = { var annote = {
bindings: [], bindings: [],
events: [] events: []
}; };
if (element.localName === 'content') { if (element.localName === 'content') {
list._hasContent = true; list._hasContent = true;
} }
this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace); this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace);
// TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should // TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should
// change the contract of this method, or filter these out above. // change the contract of this method, or filter these out above.
if (element.attributes) { if (element.attributes) {
this._parseNodeAttributeAnnotations(element, annote, list); this._parseNodeAttributeAnnotations(element, annote, list);
// TODO(sorvell): ad hoc callback for doing work on elements while // TODO(sorvell): ad hoc callback for doing work on elements while
// leveraging annotator's tree walk. // leveraging annotator's tree walk.
// Consider adding an node callback registry and moving specific // Consider adding an node callback registry and moving specific
// processing out of this module. // processing out of this module.
if (this.prepElement) { if (this.prepElement) {
this.prepElement(element); this.prepElement(element);
} }
} }
if (annote.bindings.length || annote.events.length || annote.id) { if (annote.bindings.length || annote.events.length || annote.id) {
list.push(annote); list.push(annote);
} }
return annote; return annote;
}, },
// add annotations gleaned from children of `root` to `list`, `root`'s // add annotations gleaned from children of `root` to `list`, `root`'s
// `annote` is supplied as it is the annote.parent of added annotations // `annote` is supplied as it is the annote.parent of added annotations
_parseChildNodesAnnotations: function(root, annote, list, stripWhiteSpace) { _parseChildNodesAnnotations: function(root, annote, list, stripWhiteSpace) {
if (root.firstChild) { if (root.firstChild) {
var node = root.firstChild; var node = root.firstChild;
var i = 0; var i = 0;
while (node) { while (node) {
var next = node.nextSibling; var next = node.nextSibling;
if (node.localName === 'template' && if (node.localName === 'template' &&
!node.hasAttribute('preserve-content')) { !node.hasAttribute('preserve-content')) {
this._parseTemplate(node, i, list, annote); this._parseTemplate(node, i, list, annote);
} }
// collapse adjacent textNodes: fixes an IE issue that can cause // collapse adjacent textNodes: fixes an IE issue that can cause
// text nodes to be inexplicably split =( // text nodes to be inexplicably split =(
// note that root.normalize() should work but does not so we do this // note that root.normalize() should work but does not so we do this
// manually. // manually.
if (node.nodeType === Node.TEXT_NODE) { if (node.nodeType === Node.TEXT_NODE) {
var n = next; var n = next;
while (n && (n.nodeType === Node.TEXT_NODE)) { while (n && (n.nodeType === Node.TEXT_NODE)) {
node.textContent += n.textContent; node.textContent += n.textContent;
next = n.nextSibling; next = n.nextSibling;
root.removeChild(n); root.removeChild(n);
n = next; n = next;
} }
// optionally strip whitespace // optionally strip whitespace
if (stripWhiteSpace && !node.textContent.trim()) { if (stripWhiteSpace && !node.textContent.trim()) {
root.removeChild(node); root.removeChild(node);
// decrement index since node is removed // decrement index since node is removed
i--; i--;
} }
} }
// if this node didn't get evacipated, parse it. // if this node didn't get evacipated, parse it.
if (node.parentNode) { if (node.parentNode) {
var childAnnotation = this._parseNodeAnnotations(node, list, var childAnnotation = this._parseNodeAnnotations(node, list,
stripWhiteSpace); stripWhiteSpace);
if (childAnnotation) { if (childAnnotation) {
childAnnotation.parent = annote; childAnnotation.parent = annote;
childAnnotation.index = i; childAnnotation.index = i;
} }
} }
node = next; node = next;
i++; i++;
} }
} }
}, },
// 1. Parse annotations from the template and memoize them on // 1. Parse annotations from the template and memoize them on
// content._notes (recurses into nested templates) // content._notes (recurses into nested templates)
// 2. Remove template.content and store it in annotation list, where it // 2. Remove template.content and store it in annotation list, where it
// will be the responsibility of the host to set it back to the template // will be the responsibility of the host to set it back to the template
// (this is both an optimization to avoid re-stamping nested template // (this is both an optimization to avoid re-stamping nested template
// children and avoids a bug in Chrome where nested template children // children and avoids a bug in Chrome where nested template children
// upgrade) // upgrade)
_parseTemplate: function(node, index, list, parent) { _parseTemplate: function(node, index, list, parent) {
// TODO(sjmiles): simply altering the .content reference didn't // TODO(sjmiles): simply altering the .content reference didn't
// work (there was some confusion, might need verification) // work (there was some confusion, might need verification)
var content = document.createDocumentFragment(); var content = document.createDocumentFragment();
content._notes = this.parseAnnotations(node); content._notes = this.parseAnnotations(node);
content.appendChild(node.content); content.appendChild(node.content);
// TODO(sjmiles): using `nar` to avoid unnecessary allocation; // TODO(sjmiles): using `nar` to avoid unnecessary allocation;
// in general the handling of these arrays needs some cleanup // in general the handling of these arrays needs some cleanup
// in this module // in this module
list.push({ list.push({
bindings: Polymer.nar, bindings: Polymer.nar,
events: Polymer.nar, events: Polymer.nar,
templateContent: content, templateContent: content,
parent: parent, parent: parent,
index: index index: index
}); });
}, },
// add annotation data from attributes to the `annotation` for node `node` // add annotation data from attributes to the `annotation` for node `node`
// TODO(sjmiles): the distinction between an `annotation` and // TODO(sjmiles): the distinction between an `annotation` and
// `annotation data` is not as clear as it could be // `annotation data` is not as clear as it could be
_parseNodeAttributeAnnotations: function(node, annotation) { _parseNodeAttributeAnnotations: function(node, annotation) {
// Make copy of original attribute list, since the order may change // Make copy of original attribute list, since the order may change
// as attributes are added and removed // as attributes are added and removed
var attrs = Array.prototype.slice.call(node.attributes); var attrs = Array.prototype.slice.call(node.attributes);
for (var i=attrs.length-1, a; (a=attrs[i]); i--) { for (var i=attrs.length-1, a; (a=attrs[i]); i--) {
var n = a.name; var n = a.name;
var v = a.value; var v = a.value;
var b; var b;
// events (on-*) // events (on-*)
if (n.slice(0, 3) === 'on-') { if (n.slice(0, 3) === 'on-') {
node.removeAttribute(n); node.removeAttribute(n);
annotation.events.push({ annotation.events.push({
name: n.slice(3), name: n.slice(3),
value: v value: v
}); });
} }
// bindings (other attributes) // bindings (other attributes)
else if (b = this._parseNodeAttributeAnnotation(node, n, v)) { else if ((b = this._parseNodeAttributeAnnotation(node, n, v))) {
annotation.bindings.push(b); annotation.bindings.push(b);
} }
// static id // static id
else if (n === 'id') { else if (n === 'id') {
annotation.id = v; annotation.id = v;
} }
} }
}, },
// construct annotation data from a generic attribute, or undefined // construct annotation data from a generic attribute, or undefined
_parseNodeAttributeAnnotation: function(node, name, value) { _parseNodeAttributeAnnotation: function(node, name, value) {
var parts = this._parseBindings(value); var parts = this._parseBindings(value);
if (parts) { if (parts) {
// Attribute or property // Attribute or property
var origName = name; var origName = name;
var kind = 'property'; var kind = 'property';
if (name[name.length-1] == '$') { if (name[name.length-1] == '$') {
name = name.slice(0, -1); name = name.slice(0, -1);
kind = 'attribute'; kind = 'attribute';
} }
// Initialize attribute bindings with any literal parts // Initialize attribute bindings with any literal parts
var literal = this._literalFromParts(parts); var literal = this._literalFromParts(parts);
if (literal && kind == 'attribute') { if (literal && kind == 'attribute') {
node.setAttribute(name, literal); node.setAttribute(name, literal);
} }
// Clear attribute before removing, since IE won't allow removing // Clear attribute before removing, since IE won't allow removing
// `value` attribute if it previously had a value (can't // `value` attribute if it previously had a value (can't
// unconditionally set '' before removing since attributes with `$` // unconditionally set '' before removing since attributes with `$`
// can't be set using setAttribute) // can't be set using setAttribute)
if (node.localName === 'input' && origName === 'value') { if (node.localName === 'input' && origName === 'value') {
node.setAttribute(origName, ''); node.setAttribute(origName, '');
} }
// Remove annotation // Remove annotation
node.removeAttribute(origName); node.removeAttribute(origName);
// Case hackery: attributes are lower-case, but bind targets // Case hackery: attributes are lower-case, but bind targets
// (properties) are case sensitive. Gambit is to map dash-case to // (properties) are case sensitive. Gambit is to map dash-case to
// camel-case: `foo-bar` becomes `fooBar`. // camel-case: `foo-bar` becomes `fooBar`.
// Attribute bindings are excepted. // Attribute bindings are excepted.
var propertyName = Polymer.CaseMap.dashToCamelCase(name); var propertyName = Polymer.CaseMap.dashToCamelCase(name);
if (kind === 'property') { if (kind === 'property') {
name = propertyName; name = propertyName;
} }
return { return {
kind: kind, kind: kind,
name: name, name: name,
propertyName: propertyName, propertyName: propertyName,
parts: parts, parts: parts,
literal: literal, literal: literal,
isCompound: parts.length !== 1 isCompound: parts.length !== 1
}; };
} }
}, },
// instance-time // instance-time
findAnnotatedNode: function(root, annote) { findAnnotatedNode: function(root, annote) {
// recursively ascend tree until we hit root // recursively ascend tree until we hit root
var parent = annote.parent && var parent = annote.parent &&
Polymer.Annotations.findAnnotatedNode(root, annote.parent); Polymer.Annotations.findAnnotatedNode(root, annote.parent);
// unwind the stack, returning the indexed node at each level // unwind the stack, returning the indexed node at each level
if (parent) { if (parent) {
// note: marginally faster than indexing via childNodes // note: marginally faster than indexing via childNodes
// (http://jsperf.com/childnodes-lookup) // (http://jsperf.com/childnodes-lookup)
for (var n=parent.firstChild, i=0; n; n=n.nextSibling) { for (var n=parent.firstChild, i=0; n; n=n.nextSibling) {
if (annote.index === i++) { if (annote.index === i++) {
return n; return n;
} }
} }
} else { } else {
return root; return root;
} }
} }
}; };
</script> </script>

View File

@ -10,7 +10,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<script> <script>
Polymer.ArraySplice = (function() { Polymer.ArraySplice = (function() {
function newSplice(index, removed, addedCount) { function newSplice(index, removed, addedCount) {
return { return {
index: index, index: index,
@ -56,8 +56,8 @@ Polymer.ArraySplice = (function() {
for (var j = 0; j < columnCount; j++) for (var j = 0; j < columnCount; j++)
distances[0][j] = j; distances[0][j] = j;
for (var i = 1; i < rowCount; i++) { for (i = 1; i < rowCount; i++) {
for (var j = 1; j < columnCount; j++) { for (j = 1; j < columnCount; j++) {
if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
distances[i][j] = distances[i - 1][j - 1]; distances[i][j] = distances[i - 1][j - 1];
else { else {
@ -181,7 +181,7 @@ Polymer.ArraySplice = (function() {
this.calcEditDistances(current, currentStart, currentEnd, this.calcEditDistances(current, currentStart, currentEnd,
old, oldStart, oldEnd)); old, oldStart, oldEnd));
var splice = undefined; splice = undefined;
var splices = []; var splices = [];
var index = currentStart; var index = currentStart;
var oldIndex = oldStart; var oldIndex = oldStart;
@ -259,4 +259,4 @@ Polymer.ArraySplice = (function() {
return new ArraySplice(); return new ArraySplice();
})(); })();
</script> </script>

View File

@ -23,7 +23,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_notifyChange: function(source, event, value) { _notifyChange: function(source, event, value) {
value = value === undefined ? this[source] : value; value = value === undefined ? this[source] : value;
event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed'; event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed';
this.fire(event, {value: value}, this.fire(event, {value: value},
{bubbles: false, cancelable: false, _useCache: true}); {bubbles: false, cancelable: false, _useCache: true});
}, },
@ -221,8 +221,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
} else { } else {
// TODO(sorvell): even though we have a `value` argument, we *must* // TODO(sorvell): even though we have a `value` argument, we *must*
// lookup the current value of the property. Multiple listeners and // lookup the current value of the property. Multiple listeners and
// queued events during configuration can theoretically lead to // queued events during configuration can theoretically lead to
// divergence of the passed value from the current value, but we // divergence of the passed value from the current value, but we
// really need to track down a specific case where this happens. // really need to track down a specific case where this happens.
value = target[property]; value = target[property];
if (!isStructured) { if (!isStructured) {
@ -256,7 +256,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
//if (node._prepParentProperties || !node._propertyInfo || (p && p.notify)) { //if (node._prepParentProperties || !node._propertyInfo || (p && p.notify)) {
this._addNotifyListener(node, inst, info.event, info.changedFn); this._addNotifyListener(node, inst, info.event, info.changedFn);
//} //}
}; }
}, },
// TODO(sorvell): note, adding these synchronously may impact performance, // TODO(sorvell): note, adding these synchronously may impact performance,

View File

@ -50,7 +50,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
removeKey: function(key) { removeKey: function(key) {
if (key = this._parseKey(key)) { if ((key = this._parseKey(key))) {
this._removeFromMap(this.store[key]); this._removeFromMap(this.store[key]);
delete this.store[key]; delete this.store[key];
} }
@ -95,7 +95,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
setItem: function(key, item) { setItem: function(key, item) {
if (key = this._parseKey(key)) { if ((key = this._parseKey(key))) {
var old = this.store[key]; var old = this.store[key];
if (old) { if (old) {
this._removeFromMap(old); this._removeFromMap(old);
@ -110,7 +110,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
getItem: function(key) { getItem: function(key) {
if (key = this._parseKey(key)) { if ((key = this._parseKey(key))) {
return this.store[key]; return this.store[key];
} }
}, },
@ -140,7 +140,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
key = this.getKey(s.removed[j]); key = this.getKey(s.removed[j]);
keyMap[key] = keyMap[key] ? null : -1; keyMap[key] = keyMap[key] ? null : -1;
} }
for (var j=0; j<s.addedCount; j++) { for (j=0; j<s.addedCount; j++) {
var item = this.userArray[s.index + j]; var item = this.userArray[s.index + j];
key = this.getKey(item); key = this.getKey(item);
key = (key === undefined) ? this.add(item) : key; key = (key === undefined) ? this.add(item) : key;
@ -154,7 +154,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// Convert added/removed key map to added/removed arrays // Convert added/removed key map to added/removed arrays
var removed = []; var removed = [];
var added = []; var added = [];
for (var key in keyMap) { for (key in keyMap) {
if (keyMap[key] < 0) { if (keyMap[key] < 0) {
this.removeKey(key); this.removeKey(key);
removed.push(key); removed.push(key);

View File

@ -71,7 +71,6 @@ Note, all features of `custom-style` are available when defining styles as part
<script> <script>
(function() { (function() {
var nativeShadow = Polymer.Settings.useNativeShadow;
var propertyUtils = Polymer.StyleProperties; var propertyUtils = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil; var styleUtil = Polymer.StyleUtil;
var cssParse = Polymer.CssParse; var cssParse = Polymer.CssParse;

View File

@ -1,268 +1,264 @@
<!-- <!--
@license @license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved. Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--> -->
<link rel="import" href="settings.html"> <link rel="import" href="settings.html">
<script> <script>
(function() { (function() {
'use strict'; 'use strict';
var DomApi = Polymer.DomApi.ctor; var DomApi = Polymer.DomApi.ctor;
var Settings = Polymer.Settings; var Settings = Polymer.Settings;
var hasDomApi = Polymer.DomApi.hasDomApi;
/**
/** * DomApi.EffectiveNodesObserver tracks changes to an element's
* DomApi.EffectiveNodesObserver tracks changes to an element's * effective child nodes, the same list returned from
* effective child nodes, the same list returned from * `Polymer.dom(node).getEffectiveChildNodes()`.
* `Polymer.dom(node).getEffectiveChildNodes()`. * It is not meant to be used directly; it is used by
* It is not meant to be used directly; it is used by * `Polymer.dom(node).observeNodes(callback)` to observe changes.
* `Polymer.dom(node).observeNodes(callback)` to observe changes. */
*/ DomApi.EffectiveNodesObserver = function(domApi) {
DomApi.EffectiveNodesObserver = function(domApi) { this.domApi = domApi;
this.domApi = domApi; this.node = this.domApi.node;
this.node = this.domApi.node; this._listeners = [];
this._listeners = []; };
};
DomApi.EffectiveNodesObserver.prototype = {
DomApi.EffectiveNodesObserver.prototype = {
addListener: function(callback) {
addListener: function(callback) { if (!this._isSetup) {
if (!this._isSetup) { this._setup();
this._setup(); this._isSetup = true;
this._isSetup = true; }
} var listener = {fn: callback, _nodes: []};
var listener = {fn: callback, _nodes: []}; this._listeners.push(listener);
this._listeners.push(listener); this._scheduleNotify();
this._scheduleNotify(); return listener;
return listener; },
},
removeListener: function(handle) {
removeListener: function(handle) { var i = this._listeners.indexOf(handle);
var i = this._listeners.indexOf(handle); if (i >= 0) {
if (i >= 0) { this._listeners.splice(i, 1);
this._listeners.splice(i, 1); handle._nodes = [];
handle._nodes = []; }
} if (!this._hasListeners()) {
if (!this._hasListeners()) { this._cleanup();
this._cleanup(); this._isSetup = false;
this._isSetup = false; }
} },
},
_setup: function() {
_setup: function() { this._observeContentElements(this.domApi.childNodes);
this._observeContentElements(this.domApi.childNodes); },
},
_cleanup: function() {
_cleanup: function() { this._unobserveContentElements(this.domApi.childNodes);
this._unobserveContentElements(this.domApi.childNodes); },
},
_hasListeners: function() {
_hasListeners: function() { return Boolean(this._listeners.length);
return Boolean(this._listeners.length); },
},
_scheduleNotify: function() {
_scheduleNotify: function() { if (this._debouncer) {
if (this._debouncer) { this._debouncer.stop();
this._debouncer.stop(); }
} this._debouncer = Polymer.Debounce(this._debouncer,
this._debouncer = Polymer.Debounce(this._debouncer, this._notify);
this._notify); this._debouncer.context = this;
this._debouncer.context = this; Polymer.dom.addDebouncer(this._debouncer);
Polymer.dom.addDebouncer(this._debouncer); },
},
notify: function() {
notify: function() { if (this._hasListeners()) {
if (this._hasListeners()) { this._scheduleNotify();
this._scheduleNotify(); }
} },
},
_notify: function() {
_notify: function(mxns) { this._beforeCallListeners();
this._beforeCallListeners(); this._callListeners();
this._callListeners(); },
},
_beforeCallListeners: function() {
_beforeCallListeners: function() { this._updateContentElements();
this._updateContentElements(); },
},
_updateContentElements: function() {
_updateContentElements: function() { this._observeContentElements(this.domApi.childNodes);
this._observeContentElements(this.domApi.childNodes); },
},
_observeContentElements: function(elements) {
_observeContentElements: function(elements) { for (var i=0, n; (i < elements.length) && (n=elements[i]); i++) {
for (var i=0, n; (i < elements.length) && (n=elements[i]); i++) { if (this._isContent(n)) {
if (this._isContent(n)) { n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
n.__observeNodesMap = n.__observeNodesMap || new WeakMap(); if (!n.__observeNodesMap.has(this)) {
if (!n.__observeNodesMap.has(this)) { n.__observeNodesMap.set(this, this._observeContent(n));
n.__observeNodesMap.set(this, this._observeContent(n)); }
} }
} }
} },
},
_observeContent: function(content) {
_observeContent: function(content) { var self = this;
var self = this; var h = Polymer.dom(content).observeNodes(function() {
var h = Polymer.dom(content).observeNodes(function() { self._scheduleNotify();
self._scheduleNotify(); });
}); h._avoidChangeCalculation = true;
h._avoidChangeCalculation = true; return h;
return h; },
},
_unobserveContentElements: function(elements) {
_unobserveContentElements: function(elements) { for (var i=0, n, h; (i < elements.length) && (n=elements[i]); i++) {
for (var i=0, n, h; (i < elements.length) && (n=elements[i]); i++) { if (this._isContent(n)) {
if (this._isContent(n)) { h = n.__observeNodesMap.get(this);
h = n.__observeNodesMap.get(this); if (h) {
if (h) { Polymer.dom(n).unobserveNodes(h);
Polymer.dom(n).unobserveNodes(h); n.__observeNodesMap.delete(this);
n.__observeNodesMap.delete(this); }
} }
} }
} },
},
_isContent: function(node) {
_isContent: function(node) { return (node.localName === 'content');
return (node.localName === 'content'); },
},
_callListeners: function() {
_callListeners: function() { var o$ = this._listeners;
var o$ = this._listeners; var nodes = this._getEffectiveNodes();
var nodes = this._getEffectiveNodes(); for (var i=0, o; (i < o$.length) && (o=o$[i]); i++) {
for (var i=0, o; (i < o$.length) && (o=o$[i]); i++) { var info = this._generateListenerInfo(o, nodes);
var info = this._generateListenerInfo(o, nodes); if (info || o._alwaysNotify) {
if (info || o._alwaysNotify) { this._callListener(o, info);
this._callListener(o, info); }
} }
} },
},
_getEffectiveNodes: function() {
_getEffectiveNodes: function() { return this.domApi.getEffectiveChildNodes()
return this.domApi.getEffectiveChildNodes() },
},
_generateListenerInfo: function(listener, newNodes) {
_generateListenerInfo: function(listener, newNodes) { if (listener._avoidChangeCalculation) {
if (listener._avoidChangeCalculation) { return true;
return true; }
} var oldNodes = listener._nodes;
var oldNodes = listener._nodes; var info = {
var info = { target: this.node,
target: this.node, addedNodes: [],
addedNodes: [], removedNodes: []
removedNodes: [] };
}; var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes);
var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes); // process removals
// process removals for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) {
for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) { for (var j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) {
for (var j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) { info.removedNodes.push(n);
info.removedNodes.push(n); }
} }
} // process adds
// process adds for (i=0, s; (i<splices.length) && (s=splices[i]); i++) {
for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) { for (j=s.index; j < s.index + s.addedCount; j++) {
for (var j=s.index; j < s.index + s.addedCount; j++) { info.addedNodes.push(newNodes[j]);
info.addedNodes.push(newNodes[j]); }
} }
} // update cache
// update cache listener._nodes = newNodes;
listener._nodes = newNodes; if (info.addedNodes.length || info.removedNodes.length) {
if (info.addedNodes.length || info.removedNodes.length) { return info;
return info; }
} },
},
_callListener: function(listener, info) {
_callListener: function(listener, info) { return listener.fn.call(this.node, info);
return listener.fn.call(this.node, info); },
},
enableShadowAttributeTracking: function() {}
enableShadowAttributeTracking: function() {}
};
};
if (Settings.useShadow) {
if (Settings.useShadow) {
var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup; var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, {
var beforeCallListeners = DomApi.EffectiveNodesObserver
.prototype._beforeCallListeners; _setup: function() {
if (!this._observer) {
Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, { var self = this;
this._mutationHandler = function(mxns) {
_setup: function() { if (mxns && mxns.length) {
if (!this._observer) { self._scheduleNotify();
var self = this; }
this._mutationHandler = function(mxns) { };
if (mxns && mxns.length) { this._observer = new MutationObserver(this._mutationHandler);
self._scheduleNotify(); this._boundFlush = function() {
} self._flush();
}; }
this._observer = new MutationObserver(this._mutationHandler); Polymer.dom.addStaticFlush(this._boundFlush);
this._boundFlush = function() { // NOTE: subtree true is way too aggressive, but it easily catches
self._flush(); // attribute changes on children. These changes otherwise require
} // attribute observers on every child. Testing has shown this
Polymer.dom.addStaticFlush(this._boundFlush); // approach to be more efficient.
// NOTE: subtree true is way too aggressive, but it easily catches // TODO(sorvell): do we still need to include an option to defeat
// attribute changes on children. These changes otherwise require // attribute tracking?
// attribute observers on every child. Testing has shown this this._observer.observe(this.node, { childList: true });
// approach to be more efficient. }
// TODO(sorvell): do we still need to include an option to defeat baseSetup.call(this);
// attribute tracking? },
this._observer.observe(this.node, { childList: true });
} _cleanup: function() {
baseSetup.call(this); this._observer.disconnect();
}, this._observer = null;
this._mutationHandler = null;
_cleanup: function() { Polymer.dom.removeStaticFlush(this._boundFlush);
this._observer.disconnect(); baseCleanup.call(this);
this._observer = null; },
this._mutationHandler = null;
Polymer.dom.removeStaticFlush(this._boundFlush); _flush: function() {
baseCleanup.call(this); if (this._observer) {
}, this._mutationHandler(this._observer.takeRecords());
}
_flush: function() { },
if (this._observer) {
this._mutationHandler(this._observer.takeRecords()); enableShadowAttributeTracking: function() {
} if (this._observer) {
}, // provoke all listeners needed for <content> observation
// to always call listeners when no-op changes occur (which may
enableShadowAttributeTracking: function() { // affect lower distributions.
if (this._observer) { this._makeContentListenersAlwaysNotify();
// provoke all listeners needed for <content> observation this._observer.disconnect();
// to always call listeners when no-op changes occur (which may this._observer.observe(this.node, {
// affect lower distributions. childList: true,
this._makeContentListenersAlwaysNotify(); attributes: true,
this._observer.disconnect(); subtree: true
this._observer.observe(this.node, { });
childList: true, var root = this.domApi.getOwnerRoot();
attributes: true, var host = root && root.host;
subtree: true if (host && Polymer.dom(host).observer) {
}); Polymer.dom(host).observer.enableShadowAttributeTracking();
var root = this.domApi.getOwnerRoot(); }
var host = root && root.host; }
if (host && Polymer.dom(host).observer) { },
Polymer.dom(host).observer.enableShadowAttributeTracking();
} _makeContentListenersAlwaysNotify: function() {
} for (var i=0, h; i < this._listeners.length ; i++) {
}, h = this._listeners[i];
h._alwaysNotify = h._isContentListener;
_makeContentListenersAlwaysNotify: function() { }
for (var i=0, h; i < this._listeners.length ; i++) { }
h = this._listeners[i];
h._alwaysNotify = h._isContentListener; });
}
} }
}); })();
} </script>
})();
</script>

View File

@ -93,7 +93,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
if (root) { if (root) {
// note: we always need to see if an insertion point is added // note: we always need to see if an insertion point is added
// since this saves logical tree info; however, invalidation state // since this saves logical tree info; however, invalidation state
// needs // needs
var ipAdded = this._maybeAddInsertionPoint(node, this.node); var ipAdded = this._maybeAddInsertionPoint(node, this.node);
// invalidate insertion points IFF not already invalid! // invalidate insertion points IFF not already invalid!
if (!root._invalidInsertionPoints) { if (!root._invalidInsertionPoints) {
@ -107,14 +107,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// if not distributing and not adding to host, do a fast path addition // if not distributing and not adding to host, do a fast path addition
var handled = this._maybeDistribute(node) || var handled = this._maybeDistribute(node) ||
this.node.shadyRoot; this.node.shadyRoot;
// if shady is handling this node, // if shady is handling this node,
// the actual dom may not be removed if the node or fragment contents // the actual dom may not be removed if the node or fragment contents
// remain undistributed so we ensure removal here. // remain undistributed so we ensure removal here.
// NOTE: we only remove from existing location iff shady dom is involved. // NOTE: we only remove from existing location iff shady dom is involved.
// This is because a node fragment is passed to the native add method // This is because a node fragment is passed to the native add method
// which expects to see fragment children. Regular elements must also // which expects to see fragment children. Regular elements must also
// use this check because not doing so causes separation of // use this check because not doing so causes separation of
// attached/detached and breaks, for example, // attached/detached and breaks, for example,
// dom-if's attached/detached checks. // dom-if's attached/detached checks.
if (handled) { if (handled) {
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
@ -137,7 +137,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/ */
removeChild: function(node) { removeChild: function(node) {
if (TreeApi.Logical.getParentNode(node) !== this.node) { if (TreeApi.Logical.getParentNode(node) !== this.node) {
throw Error('The node to be removed is not a child of this node: ' + throw Error('The node to be removed is not a child of this node: ' +
node); node);
} }
if (!this._removeNode(node)) { if (!this._removeNode(node)) {
@ -154,7 +154,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return node; return node;
}, },
// Try to remove node: update logical info and perform distribution iff // Try to remove node: update logical info and perform distribution iff
// needed. Return true if the removal has been handled. // needed. Return true if the removal has been handled.
// note that it's possible for both the node's host and its parent // note that it's possible for both the node's host and its parent
// to require distribution... both cases are handled here. // to require distribution... both cases are handled here.
@ -214,7 +214,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
} }
// memo-ize result for performance but only memo-ize a false-y // memo-ize result for performance but only memo-ize a false-y
// result if node is in the document. This avoids a problem where a root // result if node is in the document. This avoids a problem where a root
// can be cached while an element is inside a fragment. // can be cached while an element is inside a fragment.
// If this happens and we cache the result, the value can become stale // If this happens and we cache the result, the value can become stale
// because for perf we avoid processing the subtree of added fragments. // because for perf we avoid processing the subtree of added fragments.
if (root || document.documentElement.contains(node)) { if (root || document.documentElement.contains(node)) {
@ -298,7 +298,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
_nodeNeedsDistribution: function(node) { _nodeNeedsDistribution: function(node) {
return node && node.shadyRoot && return node && node.shadyRoot &&
DomApi.hasInsertionPoint(node.shadyRoot); DomApi.hasInsertionPoint(node.shadyRoot);
}, },
@ -587,7 +587,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return this.node.textContent; return this.node.textContent;
} else { } else {
var tc = []; var tc = [];
for (var i = 0, cn = this.childNodes, c; c = cn[i]; i++) { for (var i = 0, cn = this.childNodes, c; (c = cn[i]); i++) {
if (c.nodeType !== Node.COMMENT_NODE) { if (c.nodeType !== Node.COMMENT_NODE) {
tc.push(c.textContent); tc.push(c.textContent);
} }

View File

@ -1,131 +1,131 @@
<!-- <!--
@license @license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved. Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--> -->
<script> <script>
Polymer.domInnerHTML = (function() { Polymer.domInnerHTML = (function() {
// Cribbed from ShadowDOM polyfill // Cribbed from ShadowDOM polyfill
// https://github.com/webcomponents/webcomponentsjs/blob/master/src/ShadowDOM/wrappers/HTMLElement.js#L28 // https://github.com/webcomponents/webcomponentsjs/blob/master/src/ShadowDOM/wrappers/HTMLElement.js#L28
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// innerHTML and outerHTML // innerHTML and outerHTML
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString
var escapeAttrRegExp = /[&\u00A0"]/g; var escapeAttrRegExp = /[&\u00A0"]/g;
var escapeDataRegExp = /[&\u00A0<>]/g; var escapeDataRegExp = /[&\u00A0<>]/g;
function escapeReplace(c) { function escapeReplace(c) {
switch (c) { switch (c) {
case '&': case '&':
return '&amp;'; return '&amp;';
case '<': case '<':
return '&lt;'; return '&lt;';
case '>': case '>':
return '&gt;'; return '&gt;';
case '"': case '"':
return '&quot;'; return '&quot;';
case '\u00A0': case '\u00A0':
return '&nbsp;'; return '&nbsp;';
} }
} }
function escapeAttr(s) { function escapeAttr(s) {
return s.replace(escapeAttrRegExp, escapeReplace); return s.replace(escapeAttrRegExp, escapeReplace);
} }
function escapeData(s) { function escapeData(s) {
return s.replace(escapeDataRegExp, escapeReplace); return s.replace(escapeDataRegExp, escapeReplace);
} }
function makeSet(arr) { function makeSet(arr) {
var set = {}; var set = {};
for (var i = 0; i < arr.length; i++) { for (var i = 0; i < arr.length; i++) {
set[arr[i]] = true; set[arr[i]] = true;
} }
return set; return set;
} }
// http://www.whatwg.org/specs/web-apps/current-work/#void-elements // http://www.whatwg.org/specs/web-apps/current-work/#void-elements
var voidElements = makeSet([ var voidElements = makeSet([
'area', 'area',
'base', 'base',
'br', 'br',
'col', 'col',
'command', 'command',
'embed', 'embed',
'hr', 'hr',
'img', 'img',
'input', 'input',
'keygen', 'keygen',
'link', 'link',
'meta', 'meta',
'param', 'param',
'source', 'source',
'track', 'track',
'wbr' 'wbr'
]); ]);
var plaintextParents = makeSet([ var plaintextParents = makeSet([
'style', 'style',
'script', 'script',
'xmp', 'xmp',
'iframe', 'iframe',
'noembed', 'noembed',
'noframes', 'noframes',
'plaintext', 'plaintext',
'noscript' 'noscript'
]); ]);
function getOuterHTML(node, parentNode, composed) { function getOuterHTML(node, parentNode, composed) {
switch (node.nodeType) { switch (node.nodeType) {
case Node.ELEMENT_NODE: case Node.ELEMENT_NODE:
//var tagName = node.tagName.toLowerCase(); //var tagName = node.tagName.toLowerCase();
var tagName = node.localName; var tagName = node.localName;
var s = '<' + tagName; var s = '<' + tagName;
var attrs = node.attributes; var attrs = node.attributes;
for (var i = 0, attr; attr = attrs[i]; i++) { for (var i = 0, attr; (attr = attrs[i]); i++) {
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"'; s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
} }
s += '>'; s += '>';
if (voidElements[tagName]) { if (voidElements[tagName]) {
return s; return s;
} }
return s + getInnerHTML(node, composed) + '</' + tagName + '>'; return s + getInnerHTML(node, composed) + '</' + tagName + '>';
case Node.TEXT_NODE: case Node.TEXT_NODE:
var data = node.data; var data = node.data;
if (parentNode && plaintextParents[parentNode.localName]) { if (parentNode && plaintextParents[parentNode.localName]) {
return data; return data;
} }
return escapeData(data); return escapeData(data);
case Node.COMMENT_NODE: case Node.COMMENT_NODE:
return '<!--' + node.data + '-->'; return '<!--' + node.data + '-->';
default: default:
console.error(node); console.error(node);
throw new Error('not implemented'); throw new Error('not implemented');
} }
} }
function getInnerHTML(node, composed) { function getInnerHTML(node, composed) {
if (node instanceof HTMLTemplateElement) if (node instanceof HTMLTemplateElement)
node = node.content; node = node.content;
var s = ''; var s = '';
var c$ = Polymer.dom(node).childNodes; var c$ = Polymer.dom(node).childNodes;
for (var i=0, l=c$.length, child; (i<l) && (child=c$[i]); i++) { for (var i=0, l=c$.length, child; (i<l) && (child=c$[i]); i++) {
s += getOuterHTML(child, node, composed); s += getOuterHTML(child, node, composed);
} }
return s; return s;
} }
return { return {
getInnerHTML: getInnerHTML getInnerHTML: getInnerHTML
}; };
})(); })();
</script> </script>

View File

@ -45,7 +45,7 @@
* @param {String} id The id at which to register the dom-module. * @param {String} id The id at which to register the dom-module.
*/ */
register: function(id) { register: function(id) {
var id = id || this.id || id = id || this.id ||
this.getAttribute('name') || this.getAttribute('is'); this.getAttribute('name') || this.getAttribute('is');
if (id) { if (id) {
this.id = id; this.id = id;
@ -103,7 +103,7 @@
var doc = script && script.ownerDocument || document; var doc = script && script.ownerDocument || document;
// find all dom-modules // find all dom-modules
var modules = doc.querySelectorAll('dom-module'); var modules = doc.querySelectorAll('dom-module');
// minimize work by going backwards and stopping if we find an // minimize work by going backwards and stopping if we find an
// upgraded module. // upgraded module.
for (var i= modules.length-1, m; (i >=0) && (m=modules[i]); i--) { for (var i= modules.length-1, m; (i >=0) && (m=modules[i]); i--) {
if (m.__upgraded__) { if (m.__upgraded__) {

View File

@ -11,20 +11,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<link rel="import" href="dom-innerHTML.html"> <link rel="import" href="dom-innerHTML.html">
<script> <script>
(function() { (function() {
'use strict'; 'use strict';
// native add/remove // native add/remove
var nativeInsertBefore = Element.prototype.insertBefore; var nativeInsertBefore = Element.prototype.insertBefore;
var nativeAppendChild = Element.prototype.appendChild; var nativeAppendChild = Element.prototype.appendChild;
var nativeRemoveChild = Element.prototype.removeChild; var nativeRemoveChild = Element.prototype.removeChild;
/** /**
* TreeApi is a dom manipulation library used by Shady/Polymer.dom to * TreeApi is a dom manipulation library used by Shady/Polymer.dom to
* manipulate composed and logical trees. * manipulate composed and logical trees.
*/ */
var TreeApi = Polymer.TreeApi = { Polymer.TreeApi = {
// sad but faster than slice... // sad but faster than slice...
arrayCopyChildNodes: function(parent) { arrayCopyChildNodes: function(parent) {
var copy=[], i=0; var copy=[], i=0;
@ -62,7 +62,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
hasChildNodes: function(node) { hasChildNodes: function(node) {
return Boolean(node.__dom && node.__dom.childNodes !== undefined); return Boolean(node.__dom && node.__dom.childNodes !== undefined);
}, },
getChildNodes: function(node) { getChildNodes: function(node) {
// note: we're distinguishing here between undefined and false-y: // note: we're distinguishing here between undefined and false-y:
// hasChildNodes uses undefined check to see if this element has logical // hasChildNodes uses undefined check to see if this element has logical
@ -77,7 +77,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
node.__dom.childNodes = []; node.__dom.childNodes = [];
for (var n=node.__dom.firstChild; n; n=n.__dom.nextSibling) { for (var n=node.__dom.firstChild; n; n=n.__dom.nextSibling) {
node.__dom.childNodes.push(n); node.__dom.childNodes.push(n);
} }
} }
return node.__dom.childNodes; return node.__dom.childNodes;
}, },
@ -89,32 +89,32 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// the mere existence of __dom is not enough to know if the requested // the mere existence of __dom is not enough to know if the requested
// logical data is available and instead we do an explicit undefined check. // logical data is available and instead we do an explicit undefined check.
getParentNode: function(node) { getParentNode: function(node) {
return node.__dom && node.__dom.parentNode !== undefined ? return node.__dom && node.__dom.parentNode !== undefined ?
node.__dom.parentNode : node.parentNode; node.__dom.parentNode : node.parentNode;
}, },
getFirstChild: function(node) { getFirstChild: function(node) {
return node.__dom && node.__dom.firstChild !== undefined ? return node.__dom && node.__dom.firstChild !== undefined ?
node.__dom.firstChild : node.firstChild; node.__dom.firstChild : node.firstChild;
}, },
getLastChild: function(node) { getLastChild: function(node) {
return node.__dom && node.__dom.lastChild !== undefined ? return node.__dom && node.__dom.lastChild !== undefined ?
node.__dom.lastChild : node.lastChild; node.__dom.lastChild : node.lastChild;
}, },
getNextSibling: function(node) { getNextSibling: function(node) {
return node.__dom && node.__dom.nextSibling !== undefined ? return node.__dom && node.__dom.nextSibling !== undefined ?
node.__dom.nextSibling : node.nextSibling; node.__dom.nextSibling : node.nextSibling;
}, },
getPreviousSibling: function(node) { getPreviousSibling: function(node) {
return node.__dom && node.__dom.previousSibling !== undefined ? return node.__dom && node.__dom.previousSibling !== undefined ?
node.__dom.previousSibling : node.previousSibling; node.__dom.previousSibling : node.previousSibling;
}, },
getFirstElementChild: function(node) { getFirstElementChild: function(node) {
return node.__dom && node.__dom.firstChild !== undefined ? return node.__dom && node.__dom.firstChild !== undefined ?
this._getFirstElementChild(node) : node.firstElementChild; this._getFirstElementChild(node) : node.firstElementChild;
}, },
@ -207,9 +207,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
container.__dom = container.__dom || {}; container.__dom = container.__dom || {};
if (ref_node) { if (ref_node) {
ref_node.__dom = ref_node.__dom || {}; ref_node.__dom = ref_node.__dom || {};
} }
// update ref_node.previousSibling <-> node // update ref_node.previousSibling <-> node
node.__dom.previousSibling = ref_node ? ref_node.__dom.previousSibling : node.__dom.previousSibling = ref_node ? ref_node.__dom.previousSibling :
container.__dom.lastChild; container.__dom.lastChild;
if (node.__dom.previousSibling) { if (node.__dom.previousSibling) {
node.__dom.previousSibling.__dom.nextSibling = node; node.__dom.previousSibling.__dom.nextSibling = node;
@ -255,7 +255,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// When an element is removed, logical data is no longer tracked. // When an element is removed, logical data is no longer tracked.
// Explicitly set `undefined` here to indicate this. This is disginguished // Explicitly set `undefined` here to indicate this. This is disginguished
// from `null` which is set if info is null. // from `null` which is set if info is null.
node.__dom.parentNode = node.__dom.previousSibling = node.__dom.parentNode = node.__dom.previousSibling =
node.__dom.nextSibling = undefined; node.__dom.nextSibling = undefined;
// remove caching of childNodes // remove caching of childNodes
container.__dom.childNodes = null; container.__dom.childNodes = null;
@ -277,8 +277,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
// composed tracking needs to reset composed children here in case // composed tracking needs to reset composed children here in case
// they may have already been set (this shouldn't happen but can // they may have already been set (this shouldn't happen but can
// if dependency ordering is incorrect and as a result upgrade order // if dependency ordering is incorrect and as a result upgrade order
// is unexpected) // is unexpected)
clearChildNodes: function(node) { clearChildNodes: function(node) {
node.textContent = ''; node.textContent = '';

View File

@ -13,11 +13,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* Helper for determining when first render occurs. * Helper for determining when first render occurs.
* Call `Polymer.RenderStatus.whenReady(callback)` to be notified when * Call `Polymer.RenderStatus.whenReady(callback)` to be notified when
* first render occurs or immediately if it has already occured. * first render occurs or immediately if it has already occured.
* Note that since HTML Imports are designed to load before rendering, * Note that since HTML Imports are designed to load before rendering,
* this call can also be used to guarantee that imports have loaded. * this call can also be used to guarantee that imports have loaded.
* This behavior is normalized to function correctly with the HTMLImports * This behavior is normalized to function correctly with the HTMLImports
* polyfill which does not otherwise maintain this rendering guarantee. * polyfill which does not otherwise maintain this rendering guarantee.
* Querying style and layout data before first render is currently * Querying style and layout data before first render is currently
* problematic on some browsers (Blink/Webkit) so this helper can be used * problematic on some browsers (Blink/Webkit) so this helper can be used
* to prevent doing so until a safe time. * to prevent doing so until a safe time.
*/ */
@ -85,7 +85,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
for (var i=0, h; i < callbacks.length; i++) { for (var i=0, h; i < callbacks.length; i++) {
h = callbacks[i]; h = callbacks[i];
h[1].apply(h[0], h[2] || Polymer.nar); h[1].apply(h[0], h[2] || Polymer.nar);
}; }
} }
}; };
@ -101,4 +101,4 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
Polymer.ImportStatus = Polymer.RenderStatus; Polymer.ImportStatus = Polymer.RenderStatus;
Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady; Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady;
</script> </script>

View File

@ -1,91 +1,90 @@
<!-- <!--
@license @license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved. Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--> -->
<link rel="import" href="style-util.html"> <link rel="import" href="style-util.html">
<link rel="import" href="style-cache.html"> <link rel="import" href="style-cache.html">
<script> <script>
Polymer.StyleDefaults = (function() { Polymer.StyleDefaults = (function() {
var styleProperties = Polymer.StyleProperties; var styleProperties = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil; var StyleCache = Polymer.StyleCache;
var StyleCache = Polymer.StyleCache;
var api = {
var api = {
_styles: [],
_styles: [], _properties: null,
_properties: null, customStyle: {},
customStyle: {}, _styleCache: new StyleCache(),
_styleCache: new StyleCache(),
addStyle: function(style) {
addStyle: function(style) { this._styles.push(style);
this._styles.push(style); this._properties = null;
this._properties = null; },
},
// NOTE: this object can be used as a styling scope so it has an api
// NOTE: this object can be used as a styling scope so it has an api // similar to that of an element wrt style properties
// similar to that of an element wrt style properties get _styleProperties() {
get _styleProperties() { if (!this._properties) {
if (!this._properties) { // force rules to reparse since they may be out of date
// force rules to reparse since they may be out of date styleProperties.decorateStyles(this._styles);
styleProperties.decorateStyles(this._styles); // NOTE: reset cache for own properties; it may have been set when
// NOTE: reset cache for own properties; it may have been set when // an element in an import applied styles (e.g. custom-style)
// an element in an import applied styles (e.g. custom-style) this._styles._scopeStyleProperties = null;
this._styles._scopeStyleProperties = null; this._properties = styleProperties
this._properties = styleProperties .scopePropertiesFromStyles(this._styles);
.scopePropertiesFromStyles(this._styles); // mixin customStyle
// mixin customStyle styleProperties.mixinCustomStyle(this._properties, this.customStyle);
styleProperties.mixinCustomStyle(this._properties, this.customStyle); styleProperties.reify(this._properties);
styleProperties.reify(this._properties); }
} return this._properties;
return this._properties; },
},
_needsStyleProperties: function() {},
_needsStyleProperties: function() {},
_computeStyleProperties: function() {
_computeStyleProperties: function() { return this._styleProperties;
return this._styleProperties; },
},
/**
/** * Re-evaluates and applies custom CSS properties to all elements in the
* Re-evaluates and applies custom CSS properties to all elements in the * document based on dynamic changes, such as adding or removing classes.
* document based on dynamic changes, such as adding or removing classes. *
* * For performance reasons, Polymer's custom CSS property shim relies
* For performance reasons, Polymer's custom CSS property shim relies * on this explicit signal from the user to indicate when changes have
* on this explicit signal from the user to indicate when changes have * been made that affect the values of custom properties.
* been made that affect the values of custom properties. *
* * @method updateStyles
* @method updateStyles * @param {Object=} properties Properties object which is mixed into
* @param {Object=} properties Properties object which is mixed into * the document root `customStyle` property. This argument provides a
* the document root `customStyle` property. This argument provides a * shortcut for setting `customStyle` and then calling `updateStyles`.
* shortcut for setting `customStyle` and then calling `updateStyles`. */
*/ updateStyles: function(properties) {
updateStyles: function(properties) { // force properties update.
// force properties update. this._properties = null;
this._properties = null; if (properties) {
if (properties) { Polymer.Base.mixin(this.customStyle, properties);
Polymer.Base.mixin(this.customStyle, properties); }
} // invalidate the cache
// invalidate the cache this._styleCache.clear();
this._styleCache.clear(); // update any custom-styles we are tracking
// update any custom-styles we are tracking for (var i=0, s; i < this._styles.length; i++) {
for (var i=0, s; i < this._styles.length; i++) { s = this._styles[i];
s = this._styles[i]; s = s.__importElement || s;
s = s.__importElement || s; s._apply();
s._apply(); }
} }
}
};
};
// exports
// exports return api;
return api;
})();
})(); </script>
</script>

View File

@ -1,101 +1,101 @@
<!-- <!--
@license @license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved. Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--> -->
<link rel="import" href="style-util.html"> <link rel="import" href="style-util.html">
<script> <script>
Polymer.StyleExtends = (function() { Polymer.StyleExtends = (function() {
var styleUtil = Polymer.StyleUtil; var styleUtil = Polymer.StyleUtil;
return { return {
hasExtends: function(cssText) { hasExtends: function(cssText) {
return Boolean(cssText.match(this.rx.EXTEND)); return Boolean(cssText.match(this.rx.EXTEND));
}, },
transform: function(style) { transform: function(style) {
var rules = styleUtil.rulesForStyle(style); var rules = styleUtil.rulesForStyle(style);
var self = this; var self = this;
styleUtil.forEachRule(rules, function(rule) { styleUtil.forEachRule(rules, function(rule) {
var map = self._mapRule(rule); self._mapRuleOntoParent(rule);
if (rule.parent) { if (rule.parent) {
var m; var m;
while (m = self.rx.EXTEND.exec(rule.cssText)) { while ((m = self.rx.EXTEND.exec(rule.cssText))) {
var extend = m[1]; var extend = m[1];
var extendor = self._findExtendor(extend, rule); var extendor = self._findExtendor(extend, rule);
if (extendor) { if (extendor) {
self._extendRule(rule, extendor); self._extendRule(rule, extendor);
} }
} }
} }
rule.cssText = rule.cssText.replace(self.rx.EXTEND, ''); rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
}); });
// strip unused % selectors // strip unused % selectors
return styleUtil.toCssText(rules, function(rule) { return styleUtil.toCssText(rules, function(rule) {
if (rule.selector.match(self.rx.STRIP)) { if (rule.selector.match(self.rx.STRIP)) {
rule.cssText = ''; rule.cssText = '';
} }
}, true); }, true);
}, },
_mapRule: function(rule) { _mapRuleOntoParent: function(rule) {
if (rule.parent) { if (rule.parent) {
var map = rule.parent.map || (rule.parent.map = {}); var map = rule.parent.map || (rule.parent.map = {});
var parts = rule.selector.split(','); var parts = rule.selector.split(',');
for (var i=0, p; i < parts.length; i++) { for (var i=0, p; i < parts.length; i++) {
p = parts[i]; p = parts[i];
map[p.trim()] = rule; map[p.trim()] = rule;
} }
return map; return map;
} }
}, },
_findExtendor: function(extend, rule) { _findExtendor: function(extend, rule) {
return rule.parent && rule.parent.map && rule.parent.map[extend] || return rule.parent && rule.parent.map && rule.parent.map[extend] ||
this._findExtendor(extend, rule.parent); this._findExtendor(extend, rule.parent);
}, },
_extendRule: function(target, source) { _extendRule: function(target, source) {
if (target.parent !== source.parent) { if (target.parent !== source.parent) {
this._cloneAndAddRuleToParent(source, target.parent); this._cloneAndAddRuleToParent(source, target.parent);
} }
target.extends = target.extends || []; target.extends = target.extends || [];
target.extends.push(source); target.extends.push(source);
// TODO: this misses `%foo, .bar` as an unetended selector but // TODO: this misses `%foo, .bar` as an unetended selector but
// this seems rare and could possibly be unsupported. // this seems rare and could possibly be unsupported.
source.selector = source.selector.replace(this.rx.STRIP, ''); source.selector = source.selector.replace(this.rx.STRIP, '');
source.selector = (source.selector && source.selector + ',\n') + source.selector = (source.selector && source.selector + ',\n') +
target.selector; target.selector;
if (source.extends) { if (source.extends) {
source.extends.forEach(function(e) { source.extends.forEach(function(e) {
this._extendRule(target, e); this._extendRule(target, e);
}, this); }, this);
} }
}, },
_cloneAndAddRuleToParent: function(rule, parent) { _cloneAndAddRuleToParent: function(rule, parent) {
rule = Object.create(rule); rule = Object.create(rule);
rule.parent = parent; rule.parent = parent;
if (rule.extends) { if (rule.extends) {
rule.extends = rule.extends.slice(); rule.extends = rule.extends.slice();
} }
parent.rules.push(rule); parent.rules.push(rule);
}, },
rx: { rx: {
EXTEND: /@extends\(([^)]*)\)\s*?;/gim, EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
STRIP: /%[^,]*$/ STRIP: /%[^,]*$/
} }
}; };
})(); })();
</script> </script>

View File

@ -71,7 +71,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var m, rx = this.rx.VAR_ASSIGN; var m, rx = this.rx.VAR_ASSIGN;
var cssText = rule.parsedCssText; var cssText = rule.parsedCssText;
var any; var any;
while (m = rx.exec(cssText)) { while ((m = rx.exec(cssText))) {
// note: group 2 is var, 3 is mixin // note: group 2 is var, 3 is mixin
properties[m[1]] = (m[2] || m[3]).trim(); properties[m[1]] = (m[2] || m[3]).trim();
any = true; any = true;
@ -93,7 +93,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
collectPropertiesInCssText: function(cssText, props) { collectPropertiesInCssText: function(cssText, props) {
var m; var m;
while (m = this.rx.VAR_CAPTURE.exec(cssText)) { while ((m = this.rx.VAR_CAPTURE.exec(cssText))) {
props[m[1]] = true; props[m[1]] = true;
var def = m[2]; var def = m[2];
if (def && def.match(this.rx.IS_VAR)) { if (def && def.match(this.rx.IS_VAR)) {
@ -145,7 +145,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
valueForProperties: function(property, props) { valueForProperties: function(property, props) {
var parts = property.split(';'); var parts = property.split(';');
for (var i=0, p, m; i<parts.length; i++) { for (var i=0, p, m; i<parts.length; i++) {
if (p = parts[i]) { if ((p = parts[i])) {
m = p.match(this.rx.MIXIN_MATCH); m = p.match(this.rx.MIXIN_MATCH);
if (m) { if (m) {
p = this.valueForProperty(props[m[1]], props); p = this.valueForProperty(props[m[1]], props);

View File

@ -193,9 +193,9 @@ Then the `observe` property should be configured as follows:
/** /**
* Count of currently rendered items after `filter` (if any) has been applied. * Count of currently rendered items after `filter` (if any) has been applied.
* If "chunking mode" is enabled, `renderedItemCount` is updated each time a * If "chunking mode" is enabled, `renderedItemCount` is updated each time a
* set of template instances is rendered. * set of template instances is rendered.
* *
*/ */
renderedItemCount: { renderedItemCount: {
type: Number, type: Number,
@ -409,7 +409,6 @@ Then the `observe` property should be configured as follows:
}, },
_render: function() { _render: function() {
var c = this.collection;
// Choose rendering path: full vs. incremental using splices // Choose rendering path: full vs. incremental using splices
if (this._needFullRefresh) { if (this._needFullRefresh) {
// Full refresh when items, sort, or filter change, or when render() called // Full refresh when items, sort, or filter change, or when render() called
@ -456,7 +455,7 @@ Then the `observe` property should be configured as follows:
// `item` may not be sufficient if the pooled instance happens to be // `item` may not be sufficient if the pooled instance happens to be
// the same item. // the same item.
this._pool.length = 0; this._pool.length = 0;
// Set rendered item count // Set rendered item count
this._setRenderedItemCount(this._instances.length); this._setRenderedItemCount(this._instances.length);
// Notify users // Notify users
this.fire('dom-change'); this.fire('dom-change');
@ -499,7 +498,7 @@ Then the `observe` property should be configured as follows:
}); });
} }
// Generate instances and assign items and keys // Generate instances and assign items and keys
for (var i=0; i<keys.length; i++) { for (i=0; i<keys.length; i++) {
var key = keys[i]; var key = keys[i];
var inst = this._instances[i]; var inst = this._instances[i];
if (inst) { if (inst) {
@ -529,23 +528,23 @@ Then the `observe` property should be configured as follows:
// first, and added rows are insertion-sorted into place using user sort // first, and added rows are insertion-sorted into place using user sort
_applySplicesUserSort: function(splices) { _applySplicesUserSort: function(splices) {
var c = this.collection; var c = this.collection;
var instances = this._instances;
var keyMap = {}; var keyMap = {};
var key;
// Dedupe added and removed keys to a final added/removed map // Dedupe added and removed keys to a final added/removed map
for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) { for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) {
for (var j=0; j<s.removed.length; j++) { for (var j=0; j<s.removed.length; j++) {
var key = s.removed[j]; key = s.removed[j];
keyMap[key] = keyMap[key] ? null : -1; keyMap[key] = keyMap[key] ? null : -1;
} }
for (var j=0; j<s.added.length; j++) { for (j=0; j<s.added.length; j++) {
var key = s.added[j]; key = s.added[j];
keyMap[key] = keyMap[key] ? null : 1; keyMap[key] = keyMap[key] ? null : 1;
} }
} }
// Convert added/removed key map to added/removed arrays // Convert added/removed key map to added/removed arrays
var removedIdxs = []; var removedIdxs = [];
var addedKeys = []; var addedKeys = [];
for (var key in keyMap) { for (key in keyMap) {
if (keyMap[key] === -1) { if (keyMap[key] === -1) {
removedIdxs.push(this._keyToInstIdx[key]); removedIdxs.push(this._keyToInstIdx[key]);
} }
@ -559,7 +558,7 @@ Then the `observe` property should be configured as follows:
// so we don't invalidate instance index // so we don't invalidate instance index
// use numeric sort, default .sort is alphabetic // use numeric sort, default .sort is alphabetic
removedIdxs.sort(this._numericSort); removedIdxs.sort(this._numericSort);
for (var i=removedIdxs.length-1; i>=0 ; i--) { for (i=removedIdxs.length-1; i>=0 ; i--) {
var idx = removedIdxs[i]; var idx = removedIdxs[i];
// Removed idx may be undefined if item was previously filtered out // Removed idx may be undefined if item was previously filtered out
if (idx !== undefined) { if (idx !== undefined) {
@ -583,7 +582,7 @@ Then the `observe` property should be configured as follows:
}); });
// Insertion-sort new instances into place (from pool or newly created) // Insertion-sort new instances into place (from pool or newly created)
var start = 0; var start = 0;
for (var i=0; i<addedKeys.length; i++) { for (i=0; i<addedKeys.length; i++) {
start = this._insertRowUserSort(start, addedKeys[i]); start = this._insertRowUserSort(start, addedKeys[i]);
} }
} }
@ -622,13 +621,12 @@ Then the `observe` property should be configured as follows:
// rows are as placeholders, and placeholders are updated to // rows are as placeholders, and placeholders are updated to
// actual rows at the end to take full advantage of removed rows // actual rows at the end to take full advantage of removed rows
_applySplicesArrayOrder: function(splices) { _applySplicesArrayOrder: function(splices) {
var c = this.collection;
for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) { for (var i=0, s; (i<splices.length) && (s=splices[i]); i++) {
// Detach & pool removed instances // Detach & pool removed instances
for (var j=0; j<s.removed.length; j++) { for (var j=0; j<s.removed.length; j++) {
this._detachAndRemoveInstance(s.index); this._detachAndRemoveInstance(s.index);
} }
for (var j=0; j<s.addedKeys.length; j++) { for (j=0; j<s.addedKeys.length; j++) {
this._insertPlaceholder(s.index+j, s.addedKeys[j]); this._insertPlaceholder(s.index+j, s.addedKeys[j]);
} }
} }

View File

@ -181,7 +181,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn)); Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn));
}, },
_flushTemplates: function(debouncerExpired) { _flushTemplates: function() {
Polymer.dom.flush(); Polymer.dom.flush();
}, },
@ -191,7 +191,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
archetype._addPropertyEffect(prop, 'function', archetype._addPropertyEffect(prop, 'function',
this._createHostPropEffector(prop)); this._createHostPropEffector(prop));
} }
for (var prop in this._instanceProps) { for (prop in this._instanceProps) {
archetype._addPropertyEffect(prop, 'function', archetype._addPropertyEffect(prop, 'function',
this._createInstancePropEffector(prop)); this._createInstancePropEffector(prop));
} }
@ -309,12 +309,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
// Extension points for Templatizer sub-classes // Extension points for Templatizer sub-classes
/* eslint-disable no-unused-vars */
_showHideChildren: function(hidden) { }, _showHideChildren: function(hidden) { },
_forwardInstancePath: function(inst, path, value) { }, _forwardInstancePath: function(inst, path, value) { },
_forwardInstanceProp: function(inst, prop, value) { }, _forwardInstanceProp: function(inst, prop, value) { },
// Defined-check rather than thunk used to avoid unnecessary work for these: // Defined-check rather than thunk used to avoid unnecessary work for these:
// _forwardParentPath: function(path, value) { }, // _forwardParentPath: function(path, value) { },
// _forwardParentProp: function(prop, value) { }, // _forwardParentProp: function(prop, value) { },
/* eslint-enable no-unused-vars */
_notifyPathUpImpl: function(path, value) { _notifyPathUpImpl: function(path, value) {
var dataHost = this.dataHost; var dataHost = this.dataHost;
@ -448,7 +450,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// An element with a _templateInstance marks the top boundary // An element with a _templateInstance marks the top boundary
// of a scope; walk up until we find one, and then ensure that // of a scope; walk up until we find one, and then ensure that
// its dataHost matches `this`, meaning this dom-repeat stamped it // its dataHost matches `this`, meaning this dom-repeat stamped it
if (model = el._templateInstance) { if ((model = el._templateInstance)) {
// Found an element stamped by another template; keep walking up // Found an element stamped by another template; keep walking up
// from its dataHost // from its dataHost
if (model.dataHost != this) { if (model.dataHost != this) {

View File

@ -108,7 +108,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_setAttributeToProperty: function(model, attribute, property, info) { _setAttributeToProperty: function(model, attribute, property, info) {
// Don't deserialize back to property if currently reflecting // Don't deserialize back to property if currently reflecting
if (!this._serializing) { if (!this._serializing) {
var property = property || Polymer.CaseMap.dashToCamelCase(attribute); property = (property || Polymer.CaseMap.dashToCamelCase(attribute));
// fallback to property lookup // fallback to property lookup
// TODO(sorvell): check for _propertyInfo existence because of dom-bind // TODO(sorvell): check for _propertyInfo existence because of dom-bind
info = info || (this._propertyInfo && this._propertyInfo[property]); info = info || (this._propertyInfo && this._propertyInfo[property]);
@ -236,6 +236,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* @return {string} String serialized from the provided property value. * @return {string} String serialized from the provided property value.
*/ */
serialize: function(value) { serialize: function(value) {
/* eslint-disable no-fallthrough */
switch (typeof value) { switch (typeof value) {
case 'boolean': case 'boolean':
return value ? '' : undefined; return value ? '' : undefined;
@ -255,7 +256,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return value != null ? value : undefined; return value != null ? value : undefined;
} }
} }
/* eslint-enable no-fallthrough */
}); });
</script> </script>

View File

@ -116,7 +116,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
if (info) { if (info) {
return info; return info;
} }
}; }
} }
return info || Polymer.nob; return info || Polymer.nob;
}, },
@ -138,7 +138,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// union properties, behaviors.properties, and propertyEffects // union properties, behaviors.properties, and propertyEffects
_prepPropertyInfo: function() { _prepPropertyInfo: function() {
this._propertyInfo = {}; this._propertyInfo = {};
for (var i=0, p; i < this.behaviors.length; i++) { for (var i=0; i < this.behaviors.length; i++) {
this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties); this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties);
} }
this._addPropertyInfo(this._propertyInfo, this.properties); this._addPropertyInfo(this._propertyInfo, this.properties);
@ -174,7 +174,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
} }
} }
} }
}, }
}); });

View File

@ -77,12 +77,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
this.shadyRoot._isShadyRoot = true; this.shadyRoot._isShadyRoot = true;
this.shadyRoot._dirtyRoots = []; this.shadyRoot._dirtyRoots = [];
// capture insertion point list // capture insertion point list
var i$ = this.shadyRoot._insertionPoints = !this._notes || var i$ = this.shadyRoot._insertionPoints = !this._notes ||
this._notes._hasContent ? this._notes._hasContent ?
this.shadyRoot.querySelectorAll('content') : []; this.shadyRoot.querySelectorAll('content') : [];
// save logical tree info // save logical tree info
// a. for shadyRoot // a. for shadyRoot
// b. for insertion points (fallback) // b. for insertion points (fallback)
// c. for parents of insertion points // c. for parents of insertion points
TreeApi.Logical.saveChildNodes(this.shadyRoot); TreeApi.Logical.saveChildNodes(this.shadyRoot);
for (var i=0, c; i < i$.length; i++) { for (var i=0, c; i < i$.length; i++) {
@ -119,7 +119,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/ */
distributeContent: function(updateInsertionPoints) { distributeContent: function(updateInsertionPoints) {
if (this.shadyRoot) { if (this.shadyRoot) {
this.shadyRoot._invalidInsertionPoints = this.shadyRoot._invalidInsertionPoints =
this.shadyRoot._invalidInsertionPoints || updateInsertionPoints; this.shadyRoot._invalidInsertionPoints || updateInsertionPoints;
// Distribute the host that's the top of this element's distribution // Distribute the host that's the top of this element's distribution
// tree. Distributing that host will *always* distibute this element. // tree. Distributing that host will *always* distibute this element.
@ -164,7 +164,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// compose self // compose self
if (this._useContent) { if (this._useContent) {
// note: it's important to mark this clean before distribution // note: it's important to mark this clean before distribution
// so that attachment that provokes additional distribution (e.g. // so that attachment that provokes additional distribution (e.g.
// adding something to your parentNode) works // adding something to your parentNode) works
this.shadyRoot._distributionClean = true; this.shadyRoot._distributionClean = true;
if (DomApi.hasInsertionPoint(this.shadyRoot)) { if (DomApi.hasInsertionPoint(this.shadyRoot)) {
@ -331,7 +331,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
for (var i=0, d=0, s; (i<splices.length) && (s=splices[i]); i++) { for (var i=0, d=0, s; (i<splices.length) && (s=splices[i]); i++) {
for (var j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) { for (var j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) {
// check if the node is still where we expect it is before trying // check if the node is still where we expect it is before trying
// to remove it; this can happen if Polymer.dom moves a node and // to remove it; this can happen if Polymer.dom moves a node and
// then schedules its previous host for distribution resulting in // then schedules its previous host for distribution resulting in
// the node being removed here. // the node being removed here.
if (TreeApi.Composed.getParentNode(n) === container) { if (TreeApi.Composed.getParentNode(n) === container) {
@ -342,9 +342,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
d -= s.addedCount; d -= s.addedCount;
} }
// process adds // process adds
for (var i=0, s, next; (i<splices.length) && (s=splices[i]); i++) { for (var i=0, s, next; (i<splices.length) && (s=splices[i]); i++) { //eslint-disable-line no-redeclare
next = composed[s.index]; next = composed[s.index];
for (var j=s.index, n; j < s.index + s.addedCount; j++) { for (j=s.index, n; j < s.index + s.addedCount; j++) {
n = children[j]; n = children[j];
TreeApi.Composed.insertBefore(container, n, next); TreeApi.Composed.insertBefore(container, n, next);
// TODO(sorvell): is this splice strictly needed? // TODO(sorvell): is this splice strictly needed?

View File

@ -227,7 +227,7 @@ TODO(sjmiles): this module should produce either syntactic metadata
}, },
// push configuration references at configure time // push configuration references at configure time
_configureAnnotationReferences: function(config) { _configureAnnotationReferences: function() {
var notes = this._notes; var notes = this._notes;
var nodes = this._nodes; var nodes = this._nodes;
for (var i=0; i<notes.length; i++) { for (var i=0; i<notes.length; i++) {

View File

@ -255,7 +255,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
} }
} }
// enforce gesture recognizer order // enforce gesture recognizer order
for (var i = 0, r; i < recognizers.length; i++) { for (i = 0, r; i < recognizers.length; i++) {
r = recognizers[i]; r = recognizers[i];
if (gs[r.name] && !handled[r.name]) { if (gs[r.name] && !handled[r.name]) {
handled[r.name] = true; handled[r.name] = true;

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
getEffectiveTextContent: function() { getEffectiveTextContent: function() {
var cn = this.getEffectiveChildNodes(); var cn = this.getEffectiveChildNodes();
var tc = []; var tc = [];
for (var i=0, c; c = cn[i]; i++) { for (var i=0, c; (c = cn[i]); i++) {
if (c.nodeType !== Node.COMMENT_NODE) { if (c.nodeType !== Node.COMMENT_NODE) {
tc.push(Polymer.dom(c).textContent); tc.push(Polymer.dom(c).textContent);
} }
@ -215,7 +215,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
fire: function(type, detail, options) { fire: function(type, detail, options) {
options = options || Polymer.nob; options = options || Polymer.nob;
var node = options.node || this; var node = options.node || this;
var detail = (detail === null || detail === undefined) ? {} : detail; detail = (detail === null || detail === undefined) ? {} : detail;
var bubbles = options.bubbles === undefined ? true : options.bubbles; var bubbles = options.bubbles === undefined ? true : options.bubbles;
var cancelable = Boolean(options.cancelable); var cancelable = Boolean(options.cancelable);
var useCache = options._useCache; var useCache = options._useCache;

View File

@ -19,7 +19,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var propertyUtils = Polymer.StyleProperties; var propertyUtils = Polymer.StyleProperties;
var styleTransformer = Polymer.StyleTransformer; var styleTransformer = Polymer.StyleTransformer;
var styleUtil = Polymer.StyleUtil;
var styleDefaults = Polymer.StyleDefaults; var styleDefaults = Polymer.StyleDefaults;
var nativeShadow = Polymer.Settings.useNativeShadow; var nativeShadow = Polymer.Settings.useNativeShadow;
@ -93,7 +92,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_findStyleHost: function() { _findStyleHost: function() {
var e = this, root; var e = this, root;
while (root = Polymer.dom(e).getOwnerRoot()) { while ((root = Polymer.dom(e).getOwnerRoot())) {
if (Polymer.isInstance(root.host)) { if (Polymer.isInstance(root.host)) {
return root.host; return root.host;
} }