Created
January 13, 2016 23:41
-
-
Save stuartlynn/2c2edb151665492c3463 to your computer and use it in GitHub Desktop.
Color Picker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html><html lang="en"><head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<script>(function () { | |
function resolve() { | |
document.body.removeAttribute('unresolved'); | |
} | |
if (window.WebComponents) { | |
addEventListener('WebComponentsReady', resolve); | |
} else { | |
if (document.readyState === 'interactive' || document.readyState === 'complete') { | |
resolve(); | |
} else { | |
addEventListener('DOMContentLoaded', resolve); | |
} | |
} | |
}()); | |
window.Polymer = { | |
Settings: function () { | |
var user = window.Polymer || {}; | |
var parts = location.search.slice(1).split('&'); | |
for (var i = 0, o; i < parts.length && (o = parts[i]); i++) { | |
o = o.split('='); | |
o[0] && (user[o[0]] = o[1] || true); | |
} | |
var wantShadow = user.dom === 'shadow'; | |
var hasShadow = Boolean(Element.prototype.createShadowRoot); | |
var nativeShadow = hasShadow && !window.ShadowDOMPolyfill; | |
var useShadow = wantShadow && hasShadow; | |
var hasNativeImports = Boolean('import' in document.createElement('link')); | |
var useNativeImports = hasNativeImports; | |
var useNativeCustomElements = !window.CustomElements || window.CustomElements.useNative; | |
return { | |
wantShadow: wantShadow, | |
hasShadow: hasShadow, | |
nativeShadow: nativeShadow, | |
useShadow: useShadow, | |
useNativeShadow: useShadow && nativeShadow, | |
useNativeImports: useNativeImports, | |
useNativeCustomElements: useNativeCustomElements | |
}; | |
}() | |
}; | |
(function () { | |
var userPolymer = window.Polymer; | |
window.Polymer = function (prototype) { | |
if (typeof prototype === 'function') { | |
prototype = prototype.prototype; | |
} | |
if (!prototype) { | |
prototype = {}; | |
} | |
var factory = desugar(prototype); | |
prototype = factory.prototype; | |
var options = { prototype: prototype }; | |
if (prototype.extends) { | |
options.extends = prototype.extends; | |
} | |
Polymer.telemetry._registrate(prototype); | |
document.registerElement(prototype.is, options); | |
return factory; | |
}; | |
var desugar = function (prototype) { | |
var base = Polymer.Base; | |
if (prototype.extends) { | |
base = Polymer.Base._getExtendedPrototype(prototype.extends); | |
} | |
prototype = Polymer.Base.chainObject(prototype, base); | |
prototype.registerCallback(); | |
return prototype.constructor; | |
}; | |
window.Polymer = Polymer; | |
if (userPolymer) { | |
for (var i in userPolymer) { | |
Polymer[i] = userPolymer[i]; | |
} | |
} | |
Polymer.Class = desugar; | |
}()); | |
Polymer.telemetry = { | |
registrations: [], | |
_regLog: function (prototype) { | |
console.log('[' + prototype.is + ']: registered'); | |
}, | |
_registrate: function (prototype) { | |
this.registrations.push(prototype); | |
Polymer.log && this._regLog(prototype); | |
}, | |
dumpRegistrations: function () { | |
this.registrations.forEach(this._regLog); | |
} | |
}; | |
Object.defineProperty(window, 'currentImport', { | |
enumerable: true, | |
configurable: true, | |
get: function () { | |
return (document._currentScript || document.currentScript).ownerDocument; | |
} | |
}); | |
Polymer.RenderStatus = { | |
_ready: false, | |
_callbacks: [], | |
whenReady: function (cb) { | |
if (this._ready) { | |
cb(); | |
} else { | |
this._callbacks.push(cb); | |
} | |
}, | |
_makeReady: function () { | |
this._ready = true; | |
for (var i = 0; i < this._callbacks.length; i++) { | |
this._callbacks[i](); | |
} | |
this._callbacks = []; | |
}, | |
_catchFirstRender: function () { | |
requestAnimationFrame(function () { | |
Polymer.RenderStatus._makeReady(); | |
}); | |
}, | |
_afterNextRenderQueue: [], | |
_waitingNextRender: false, | |
afterNextRender: function (element, fn, args) { | |
this._watchNextRender(); | |
this._afterNextRenderQueue.push([ | |
element, | |
fn, | |
args | |
]); | |
}, | |
_watchNextRender: function () { | |
if (!this._waitingNextRender) { | |
this._waitingNextRender = true; | |
var fn = function () { | |
Polymer.RenderStatus._flushNextRender(); | |
}; | |
if (!this._ready) { | |
this.whenReady(fn); | |
} else { | |
requestAnimationFrame(fn); | |
} | |
} | |
}, | |
_flushNextRender: function () { | |
var self = this; | |
setTimeout(function () { | |
self._flushRenderCallbacks(self._afterNextRenderQueue); | |
self._afterNextRenderQueue = []; | |
self._waitingNextRender = false; | |
}); | |
}, | |
_flushRenderCallbacks: function (callbacks) { | |
for (var i = 0, h; i < callbacks.length; i++) { | |
h = callbacks[i]; | |
h[1].apply(h[0], h[2] || Polymer.nar); | |
} | |
; | |
} | |
}; | |
if (window.HTMLImports) { | |
HTMLImports.whenReady(function () { | |
Polymer.RenderStatus._catchFirstRender(); | |
}); | |
} else { | |
Polymer.RenderStatus._catchFirstRender(); | |
} | |
Polymer.ImportStatus = Polymer.RenderStatus; | |
Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady; | |
Polymer.Base = { | |
__isPolymerInstance__: true, | |
_addFeature: function (feature) { | |
this.extend(this, feature); | |
}, | |
registerCallback: function () { | |
this._desugarBehaviors(); | |
this._doBehavior('beforeRegister'); | |
this._registerFeatures(); | |
this._doBehavior('registered'); | |
}, | |
createdCallback: function () { | |
Polymer.telemetry.instanceCount++; | |
this.root = this; | |
this._doBehavior('created'); | |
this._initFeatures(); | |
}, | |
attachedCallback: function () { | |
var self = this; | |
Polymer.RenderStatus.whenReady(function () { | |
self.isAttached = true; | |
self._doBehavior('attached'); | |
}); | |
}, | |
detachedCallback: function () { | |
this.isAttached = false; | |
this._doBehavior('detached'); | |
}, | |
attributeChangedCallback: function (name, oldValue, newValue) { | |
this._attributeChangedImpl(name); | |
this._doBehavior('attributeChanged', [ | |
name, | |
oldValue, | |
newValue | |
]); | |
}, | |
_attributeChangedImpl: function (name) { | |
this._setAttributeToProperty(this, name); | |
}, | |
extend: function (prototype, api) { | |
if (prototype && api) { | |
var n$ = Object.getOwnPropertyNames(api); | |
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { | |
this.copyOwnProperty(n, api, prototype); | |
} | |
} | |
return prototype || api; | |
}, | |
mixin: function (target, source) { | |
for (var i in source) { | |
target[i] = source[i]; | |
} | |
return target; | |
}, | |
copyOwnProperty: function (name, source, target) { | |
var pd = Object.getOwnPropertyDescriptor(source, name); | |
if (pd) { | |
Object.defineProperty(target, name, pd); | |
} | |
}, | |
_log: console.log.apply.bind(console.log, console), | |
_warn: console.warn.apply.bind(console.warn, console), | |
_error: console.error.apply.bind(console.error, console), | |
_logf: function () { | |
return this._logPrefix.concat([this.is]).concat(Array.prototype.slice.call(arguments, 0)); | |
} | |
}; | |
Polymer.Base._logPrefix = function () { | |
var color = window.chrome || /firefox/i.test(navigator.userAgent); | |
return color ? [ | |
'%c[%s::%s]:', | |
'font-weight: bold; background-color:#EEEE00;' | |
] : ['[%s::%s]:']; | |
}(); | |
Polymer.Base.chainObject = function (object, inherited) { | |
if (object && inherited && object !== inherited) { | |
if (!Object.__proto__) { | |
object = Polymer.Base.extend(Object.create(inherited), object); | |
} | |
object.__proto__ = inherited; | |
} | |
return object; | |
}; | |
Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype); | |
if (window.CustomElements) { | |
Polymer.instanceof = CustomElements.instanceof; | |
} else { | |
Polymer.instanceof = function (obj, ctor) { | |
return obj instanceof ctor; | |
}; | |
} | |
Polymer.isInstance = function (obj) { | |
return Boolean(obj && obj.__isPolymerInstance__); | |
}; | |
Polymer.telemetry.instanceCount = 0; | |
(function () { | |
var modules = {}; | |
var lcModules = {}; | |
var findModule = function (id) { | |
return modules[id] || lcModules[id.toLowerCase()]; | |
}; | |
var DomModule = function () { | |
return document.createElement('dom-module'); | |
}; | |
DomModule.prototype = Object.create(HTMLElement.prototype); | |
Polymer.Base.extend(DomModule.prototype, { | |
constructor: DomModule, | |
createdCallback: function () { | |
this.register(); | |
}, | |
register: function (id) { | |
var id = id || this.id || this.getAttribute('name') || this.getAttribute('is'); | |
if (id) { | |
this.id = id; | |
modules[id] = this; | |
lcModules[id.toLowerCase()] = this; | |
} | |
}, | |
import: function (id, selector) { | |
if (id) { | |
var m = findModule(id); | |
if (!m) { | |
forceDomModulesUpgrade(); | |
m = findModule(id); | |
} | |
if (m && selector) { | |
m = m.querySelector(selector); | |
} | |
return m; | |
} | |
} | |
}); | |
var cePolyfill = window.CustomElements && !CustomElements.useNative; | |
document.registerElement('dom-module', DomModule); | |
function forceDomModulesUpgrade() { | |
if (cePolyfill) { | |
var script = document._currentScript || document.currentScript; | |
var doc = script && script.ownerDocument || document; | |
var modules = doc.querySelectorAll('dom-module'); | |
for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) { | |
if (m.__upgraded__) { | |
return; | |
} else { | |
CustomElements.upgrade(m); | |
} | |
} | |
} | |
} | |
}()); | |
Polymer.Base._addFeature({ | |
_prepIs: function () { | |
if (!this.is) { | |
var module = (document._currentScript || document.currentScript).parentNode; | |
if (module.localName === 'dom-module') { | |
var id = module.id || module.getAttribute('name') || module.getAttribute('is'); | |
this.is = id; | |
} | |
} | |
if (this.is) { | |
this.is = this.is.toLowerCase(); | |
} | |
} | |
}); | |
Polymer.Base._addFeature({ | |
behaviors: [], | |
_desugarBehaviors: function () { | |
if (this.behaviors.length) { | |
this.behaviors = this._desugarSomeBehaviors(this.behaviors); | |
} | |
}, | |
_desugarSomeBehaviors: function (behaviors) { | |
behaviors = this._flattenBehaviorsList(behaviors); | |
for (var i = behaviors.length - 1; i >= 0; i--) { | |
this._mixinBehavior(behaviors[i]); | |
} | |
return behaviors; | |
}, | |
_flattenBehaviorsList: function (behaviors) { | |
var flat = []; | |
for (var i = 0; i < behaviors.length; i++) { | |
var b = behaviors[i]; | |
if (b instanceof Array) { | |
flat = flat.concat(this._flattenBehaviorsList(b)); | |
} else if (b) { | |
flat.push(b); | |
} else { | |
this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import')); | |
} | |
} | |
return flat; | |
}, | |
_mixinBehavior: function (b) { | |
var n$ = Object.getOwnPropertyNames(b); | |
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { | |
if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) { | |
this.copyOwnProperty(n, b, this); | |
} | |
} | |
}, | |
_prepBehaviors: function () { | |
this._prepFlattenedBehaviors(this.behaviors); | |
}, | |
_prepFlattenedBehaviors: function (behaviors) { | |
for (var i = 0, l = behaviors.length; i < l; i++) { | |
this._prepBehavior(behaviors[i]); | |
} | |
this._prepBehavior(this); | |
}, | |
_doBehavior: function (name, args) { | |
for (var i = 0; i < this.behaviors.length; i++) { | |
this._invokeBehavior(this.behaviors[i], name, args); | |
} | |
this._invokeBehavior(this, name, args); | |
}, | |
_invokeBehavior: function (b, name, args) { | |
var fn = b[name]; | |
if (fn) { | |
fn.apply(this, args || Polymer.nar); | |
} | |
}, | |
_marshalBehaviors: function () { | |
for (var i = 0; i < this.behaviors.length; i++) { | |
this._marshalBehavior(this.behaviors[i]); | |
} | |
this._marshalBehavior(this); | |
} | |
}); | |
Polymer.Base._behaviorProperties = { | |
hostAttributes: true, | |
registered: true, | |
properties: true, | |
observers: true, | |
listeners: true, | |
created: true, | |
attached: true, | |
detached: true, | |
attributeChanged: true, | |
ready: true | |
}; | |
Polymer.Base._addFeature({ | |
_getExtendedPrototype: function (tag) { | |
return this._getExtendedNativePrototype(tag); | |
}, | |
_nativePrototypes: {}, | |
_getExtendedNativePrototype: function (tag) { | |
var p = this._nativePrototypes[tag]; | |
if (!p) { | |
var np = this.getNativePrototype(tag); | |
p = this.extend(Object.create(np), Polymer.Base); | |
this._nativePrototypes[tag] = p; | |
} | |
return p; | |
}, | |
getNativePrototype: function (tag) { | |
return Object.getPrototypeOf(document.createElement(tag)); | |
} | |
}); | |
Polymer.Base._addFeature({ | |
_prepConstructor: function () { | |
this._factoryArgs = this.extends ? [ | |
this.extends, | |
this.is | |
] : [this.is]; | |
var ctor = function () { | |
return this._factory(arguments); | |
}; | |
if (this.hasOwnProperty('extends')) { | |
ctor.extends = this.extends; | |
} | |
Object.defineProperty(this, 'constructor', { | |
value: ctor, | |
writable: true, | |
configurable: true | |
}); | |
ctor.prototype = this; | |
}, | |
_factory: function (args) { | |
var elt = document.createElement.apply(document, this._factoryArgs); | |
if (this.factoryImpl) { | |
this.factoryImpl.apply(elt, args); | |
} | |
return elt; | |
} | |
}); | |
Polymer.nob = Object.create(null); | |
Polymer.Base._addFeature({ | |
properties: {}, | |
getPropertyInfo: function (property) { | |
var info = this._getPropertyInfo(property, this.properties); | |
if (!info) { | |
for (var i = 0; i < this.behaviors.length; i++) { | |
info = this._getPropertyInfo(property, this.behaviors[i].properties); | |
if (info) { | |
return info; | |
} | |
} | |
; | |
} | |
return info || Polymer.nob; | |
}, | |
_getPropertyInfo: function (property, properties) { | |
var p = properties && properties[property]; | |
if (typeof p === 'function') { | |
p = properties[property] = { type: p }; | |
} | |
if (p) { | |
p.defined = true; | |
} | |
return p; | |
}, | |
_prepPropertyInfo: function () { | |
this._propertyInfo = {}; | |
for (var i = 0, p; i < this.behaviors.length; i++) { | |
this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties); | |
} | |
this._addPropertyInfo(this._propertyInfo, this.properties); | |
this._addPropertyInfo(this._propertyInfo, this._propertyEffects); | |
}, | |
_addPropertyInfo: function (target, source) { | |
if (source) { | |
var t, s; | |
for (var i in source) { | |
t = target[i]; | |
s = source[i]; | |
if (i[0] === '_' && !s.readOnly) { | |
continue; | |
} | |
if (!target[i]) { | |
target[i] = { | |
type: typeof s === 'function' ? s : s.type, | |
readOnly: s.readOnly, | |
attribute: Polymer.CaseMap.camelToDashCase(i) | |
}; | |
} else { | |
if (!t.type) { | |
t.type = s.type; | |
} | |
if (!t.readOnly) { | |
t.readOnly = s.readOnly; | |
} | |
} | |
} | |
} | |
} | |
}); | |
Polymer.CaseMap = { | |
_caseMap: {}, | |
dashToCamelCase: function (dash) { | |
var mapped = Polymer.CaseMap._caseMap[dash]; | |
if (mapped) { | |
return mapped; | |
} | |
if (dash.indexOf('-') < 0) { | |
return Polymer.CaseMap._caseMap[dash] = dash; | |
} | |
return Polymer.CaseMap._caseMap[dash] = dash.replace(/-([a-z])/g, function (m) { | |
return m[1].toUpperCase(); | |
}); | |
}, | |
camelToDashCase: function (camel) { | |
var mapped = Polymer.CaseMap._caseMap[camel]; | |
if (mapped) { | |
return mapped; | |
} | |
return Polymer.CaseMap._caseMap[camel] = camel.replace(/([a-z][A-Z])/g, function (g) { | |
return g[0] + '-' + g[1].toLowerCase(); | |
}); | |
} | |
}; | |
Polymer.Base._addFeature({ | |
_addHostAttributes: function (attributes) { | |
if (!this._aggregatedAttributes) { | |
this._aggregatedAttributes = {}; | |
} | |
if (attributes) { | |
this.mixin(this._aggregatedAttributes, attributes); | |
} | |
}, | |
_marshalHostAttributes: function () { | |
if (this._aggregatedAttributes) { | |
this._applyAttributes(this, this._aggregatedAttributes); | |
} | |
}, | |
_applyAttributes: function (node, attr$) { | |
for (var n in attr$) { | |
if (!this.hasAttribute(n) && n !== 'class') { | |
var v = attr$[n]; | |
this.serializeValueToAttribute(v, n, this); | |
} | |
} | |
}, | |
_marshalAttributes: function () { | |
this._takeAttributesToModel(this); | |
}, | |
_takeAttributesToModel: function (model) { | |
if (this.hasAttributes()) { | |
for (var i in this._propertyInfo) { | |
var info = this._propertyInfo[i]; | |
if (this.hasAttribute(info.attribute)) { | |
this._setAttributeToProperty(model, info.attribute, i, info); | |
} | |
} | |
} | |
}, | |
_setAttributeToProperty: function (model, attribute, property, info) { | |
if (!this._serializing) { | |
var property = property || Polymer.CaseMap.dashToCamelCase(attribute); | |
info = info || this._propertyInfo && this._propertyInfo[property]; | |
if (info && !info.readOnly) { | |
var v = this.getAttribute(attribute); | |
model[property] = this.deserialize(v, info.type); | |
} | |
} | |
}, | |
_serializing: false, | |
reflectPropertyToAttribute: function (property, attribute, value) { | |
this._serializing = true; | |
value = value === undefined ? this[property] : value; | |
this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCase(property)); | |
this._serializing = false; | |
}, | |
serializeValueToAttribute: function (value, attribute, node) { | |
var str = this.serialize(value); | |
node = node || this; | |
if (str === undefined) { | |
node.removeAttribute(attribute); | |
} else { | |
node.setAttribute(attribute, str); | |
} | |
}, | |
deserialize: function (value, type) { | |
switch (type) { | |
case Number: | |
value = Number(value); | |
break; | |
case Boolean: | |
value = value !== null; | |
break; | |
case Object: | |
try { | |
value = JSON.parse(value); | |
} catch (x) { | |
} | |
break; | |
case Array: | |
try { | |
value = JSON.parse(value); | |
} catch (x) { | |
value = null; | |
console.warn('Polymer::Attributes: couldn`t decode Array as JSON'); | |
} | |
break; | |
case Date: | |
value = new Date(value); | |
break; | |
case String: | |
default: | |
break; | |
} | |
return value; | |
}, | |
serialize: function (value) { | |
switch (typeof value) { | |
case 'boolean': | |
return value ? '' : undefined; | |
case 'object': | |
if (value instanceof Date) { | |
return value; | |
} else if (value) { | |
try { | |
return JSON.stringify(value); | |
} catch (x) { | |
return ''; | |
} | |
} | |
default: | |
return value != null ? value : undefined; | |
} | |
} | |
}); | |
Polymer.Base._addFeature({ | |
_setupDebouncers: function () { | |
this._debouncers = {}; | |
}, | |
debounce: function (jobName, callback, wait) { | |
return this._debouncers[jobName] = Polymer.Debounce.call(this, this._debouncers[jobName], callback, wait); | |
}, | |
isDebouncerActive: function (jobName) { | |
var debouncer = this._debouncers[jobName]; | |
return debouncer && debouncer.finish; | |
}, | |
flushDebouncer: function (jobName) { | |
var debouncer = this._debouncers[jobName]; | |
if (debouncer) { | |
debouncer.complete(); | |
} | |
}, | |
cancelDebouncer: function (jobName) { | |
var debouncer = this._debouncers[jobName]; | |
if (debouncer) { | |
debouncer.stop(); | |
} | |
} | |
}); | |
Polymer.version = '1.2.3'; | |
Polymer.Base._addFeature({ | |
_registerFeatures: function () { | |
this._prepIs(); | |
this._prepBehaviors(); | |
this._prepConstructor(); | |
this._prepPropertyInfo(); | |
}, | |
_prepBehavior: function (b) { | |
this._addHostAttributes(b.hostAttributes); | |
}, | |
_marshalBehavior: function (b) { | |
}, | |
_initFeatures: function () { | |
this._marshalHostAttributes(); | |
this._setupDebouncers(); | |
this._marshalBehaviors(); | |
} | |
});</script> | |
<script>Polymer.Base._addFeature({ | |
_prepTemplate: function () { | |
if (this._template === undefined) { | |
this._template = Polymer.DomModule.import(this.is, 'template'); | |
} | |
if (this._template && this._template.hasAttribute('is')) { | |
this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.')); | |
} | |
if (this._template && !this._template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) { | |
HTMLTemplateElement.decorate(this._template); | |
} | |
}, | |
_stampTemplate: function () { | |
if (this._template) { | |
this.root = this.instanceTemplate(this._template); | |
} | |
}, | |
instanceTemplate: function (template) { | |
var dom = document.importNode(template._content || template.content, true); | |
return dom; | |
} | |
}); | |
(function () { | |
var baseAttachedCallback = Polymer.Base.attachedCallback; | |
Polymer.Base._addFeature({ | |
_hostStack: [], | |
ready: function () { | |
}, | |
_registerHost: function (host) { | |
this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.length - 1]; | |
if (host && host._clients) { | |
host._clients.push(this); | |
} | |
}, | |
_beginHosting: function () { | |
Polymer.Base._hostStack.push(this); | |
if (!this._clients) { | |
this._clients = []; | |
} | |
}, | |
_endHosting: function () { | |
Polymer.Base._hostStack.pop(); | |
}, | |
_tryReady: function () { | |
if (this._canReady()) { | |
this._ready(); | |
} | |
}, | |
_canReady: function () { | |
return !this.dataHost || this.dataHost._clientsReadied; | |
}, | |
_ready: function () { | |
this._beforeClientsReady(); | |
if (this._template) { | |
this._setupRoot(); | |
this._readyClients(); | |
} | |
this._clientsReadied = true; | |
this._clients = null; | |
this._afterClientsReady(); | |
this._readySelf(); | |
}, | |
_readyClients: function () { | |
this._beginDistribute(); | |
var c$ = this._clients; | |
if (c$) { | |
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { | |
c._ready(); | |
} | |
} | |
this._finishDistribute(); | |
}, | |
_readySelf: function () { | |
this._doBehavior('ready'); | |
this._readied = true; | |
if (this._attachedPending) { | |
this._attachedPending = false; | |
this.attachedCallback(); | |
} | |
}, | |
_beforeClientsReady: function () { | |
}, | |
_afterClientsReady: function () { | |
}, | |
_beforeAttached: function () { | |
}, | |
attachedCallback: function () { | |
if (this._readied) { | |
this._beforeAttached(); | |
baseAttachedCallback.call(this); | |
} else { | |
this._attachedPending = true; | |
} | |
} | |
}); | |
}()); | |
Polymer.ArraySplice = function () { | |
function newSplice(index, removed, addedCount) { | |
return { | |
index: index, | |
removed: removed, | |
addedCount: addedCount | |
}; | |
} | |
var EDIT_LEAVE = 0; | |
var EDIT_UPDATE = 1; | |
var EDIT_ADD = 2; | |
var EDIT_DELETE = 3; | |
function ArraySplice() { | |
} | |
ArraySplice.prototype = { | |
calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, oldEnd) { | |
var rowCount = oldEnd - oldStart + 1; | |
var columnCount = currentEnd - currentStart + 1; | |
var distances = new Array(rowCount); | |
for (var i = 0; i < rowCount; i++) { | |
distances[i] = new Array(columnCount); | |
distances[i][0] = i; | |
} | |
for (var j = 0; j < columnCount; j++) | |
distances[0][j] = j; | |
for (var i = 1; i < rowCount; i++) { | |
for (var j = 1; j < columnCount; j++) { | |
if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) | |
distances[i][j] = distances[i - 1][j - 1]; | |
else { | |
var north = distances[i - 1][j] + 1; | |
var west = distances[i][j - 1] + 1; | |
distances[i][j] = north < west ? north : west; | |
} | |
} | |
} | |
return distances; | |
}, | |
spliceOperationsFromEditDistances: function (distances) { | |
var i = distances.length - 1; | |
var j = distances[0].length - 1; | |
var current = distances[i][j]; | |
var edits = []; | |
while (i > 0 || j > 0) { | |
if (i == 0) { | |
edits.push(EDIT_ADD); | |
j--; | |
continue; | |
} | |
if (j == 0) { | |
edits.push(EDIT_DELETE); | |
i--; | |
continue; | |
} | |
var northWest = distances[i - 1][j - 1]; | |
var west = distances[i - 1][j]; | |
var north = distances[i][j - 1]; | |
var min; | |
if (west < north) | |
min = west < northWest ? west : northWest; | |
else | |
min = north < northWest ? north : northWest; | |
if (min == northWest) { | |
if (northWest == current) { | |
edits.push(EDIT_LEAVE); | |
} else { | |
edits.push(EDIT_UPDATE); | |
current = northWest; | |
} | |
i--; | |
j--; | |
} else if (min == west) { | |
edits.push(EDIT_DELETE); | |
i--; | |
current = west; | |
} else { | |
edits.push(EDIT_ADD); | |
j--; | |
current = north; | |
} | |
} | |
edits.reverse(); | |
return edits; | |
}, | |
calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) { | |
var prefixCount = 0; | |
var suffixCount = 0; | |
var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart); | |
if (currentStart == 0 && oldStart == 0) | |
prefixCount = this.sharedPrefix(current, old, minLength); | |
if (currentEnd == current.length && oldEnd == old.length) | |
suffixCount = this.sharedSuffix(current, old, minLength - prefixCount); | |
currentStart += prefixCount; | |
oldStart += prefixCount; | |
currentEnd -= suffixCount; | |
oldEnd -= suffixCount; | |
if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) | |
return []; | |
if (currentStart == currentEnd) { | |
var splice = newSplice(currentStart, [], 0); | |
while (oldStart < oldEnd) | |
splice.removed.push(old[oldStart++]); | |
return [splice]; | |
} else if (oldStart == oldEnd) | |
return [newSplice(currentStart, [], currentEnd - currentStart)]; | |
var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd)); | |
var splice = undefined; | |
var splices = []; | |
var index = currentStart; | |
var oldIndex = oldStart; | |
for (var i = 0; i < ops.length; i++) { | |
switch (ops[i]) { | |
case EDIT_LEAVE: | |
if (splice) { | |
splices.push(splice); | |
splice = undefined; | |
} | |
index++; | |
oldIndex++; | |
break; | |
case EDIT_UPDATE: | |
if (!splice) | |
splice = newSplice(index, [], 0); | |
splice.addedCount++; | |
index++; | |
splice.removed.push(old[oldIndex]); | |
oldIndex++; | |
break; | |
case EDIT_ADD: | |
if (!splice) | |
splice = newSplice(index, [], 0); | |
splice.addedCount++; | |
index++; | |
break; | |
case EDIT_DELETE: | |
if (!splice) | |
splice = newSplice(index, [], 0); | |
splice.removed.push(old[oldIndex]); | |
oldIndex++; | |
break; | |
} | |
} | |
if (splice) { | |
splices.push(splice); | |
} | |
return splices; | |
}, | |
sharedPrefix: function (current, old, searchLength) { | |
for (var i = 0; i < searchLength; i++) | |
if (!this.equals(current[i], old[i])) | |
return i; | |
return searchLength; | |
}, | |
sharedSuffix: function (current, old, searchLength) { | |
var index1 = current.length; | |
var index2 = old.length; | |
var count = 0; | |
while (count < searchLength && this.equals(current[--index1], old[--index2])) | |
count++; | |
return count; | |
}, | |
calculateSplices: function (current, previous) { | |
return this.calcSplices(current, 0, current.length, previous, 0, previous.length); | |
}, | |
equals: function (currentValue, previousValue) { | |
return currentValue === previousValue; | |
} | |
}; | |
return new ArraySplice(); | |
}(); | |
Polymer.domInnerHTML = function () { | |
var escapeAttrRegExp = /[&\u00A0"]/g; | |
var escapeDataRegExp = /[&\u00A0<>]/g; | |
function escapeReplace(c) { | |
switch (c) { | |
case '&': | |
return '&'; | |
case '<': | |
return '<'; | |
case '>': | |
return '>'; | |
case '"': | |
return '"'; | |
case '\xA0': | |
return ' '; | |
} | |
} | |
function escapeAttr(s) { | |
return s.replace(escapeAttrRegExp, escapeReplace); | |
} | |
function escapeData(s) { | |
return s.replace(escapeDataRegExp, escapeReplace); | |
} | |
function makeSet(arr) { | |
var set = {}; | |
for (var i = 0; i < arr.length; i++) { | |
set[arr[i]] = true; | |
} | |
return set; | |
} | |
var voidElements = makeSet([ | |
'area', | |
'base', | |
'br', | |
'col', | |
'command', | |
'embed', | |
'hr', | |
'img', | |
'input', | |
'keygen', | |
'link', | |
'meta', | |
'param', | |
'source', | |
'track', | |
'wbr' | |
]); | |
var plaintextParents = makeSet([ | |
'style', | |
'script', | |
'xmp', | |
'iframe', | |
'noembed', | |
'noframes', | |
'plaintext', | |
'noscript' | |
]); | |
function getOuterHTML(node, parentNode, composed) { | |
switch (node.nodeType) { | |
case Node.ELEMENT_NODE: | |
var tagName = node.localName; | |
var s = '<' + tagName; | |
var attrs = node.attributes; | |
for (var i = 0, attr; attr = attrs[i]; i++) { | |
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"'; | |
} | |
s += '>'; | |
if (voidElements[tagName]) { | |
return s; | |
} | |
return s + getInnerHTML(node, composed) + '</' + tagName + '>'; | |
case Node.TEXT_NODE: | |
var data = node.data; | |
if (parentNode && plaintextParents[parentNode.localName]) { | |
return data; | |
} | |
return escapeData(data); | |
case Node.COMMENT_NODE: | |
return '<!--' + node.data + '-->'; | |
default: | |
console.error(node); | |
throw new Error('not implemented'); | |
} | |
} | |
function getInnerHTML(node, composed) { | |
if (node instanceof HTMLTemplateElement) | |
node = node.content; | |
var s = ''; | |
var c$ = Polymer.dom(node).childNodes; | |
c$ = composed ? node._composedChildren : c$; | |
for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) { | |
s += getOuterHTML(child, node, composed); | |
} | |
return s; | |
} | |
return { getInnerHTML: getInnerHTML }; | |
}(); | |
Polymer.DomApi = function () { | |
'use strict'; | |
var Settings = Polymer.Settings; | |
var getInnerHTML = Polymer.domInnerHTML.getInnerHTML; | |
var nativeInsertBefore = Element.prototype.insertBefore; | |
var nativeRemoveChild = Element.prototype.removeChild; | |
var nativeAppendChild = Element.prototype.appendChild; | |
var nativeCloneNode = Element.prototype.cloneNode; | |
var nativeImportNode = Document.prototype.importNode; | |
var needsToWrap = Settings.hasShadow && !Settings.nativeShadow; | |
var wrap = window.wrap ? window.wrap : function (node) { | |
return node; | |
}; | |
var DomApi = function (node) { | |
this.node = needsToWrap ? wrap(node) : node; | |
if (this.patch) { | |
this.patch(); | |
} | |
}; | |
DomApi.prototype = { | |
flush: function () { | |
Polymer.dom.flush(); | |
}, | |
deepContains: function (node) { | |
if (this.node.contains(node)) { | |
return true; | |
} | |
var n = node; | |
var wrappedDocument = wrap(document); | |
while (n && n !== wrappedDocument && n !== this.node) { | |
n = Polymer.dom(n).parentNode || n.host; | |
} | |
return n === this.node; | |
}, | |
_lazyDistribute: function (host) { | |
if (host.shadyRoot && host.shadyRoot._distributionClean) { | |
host.shadyRoot._distributionClean = false; | |
Polymer.dom.addDebouncer(host.debounce('_distribute', host._distributeContent)); | |
} | |
}, | |
appendChild: function (node) { | |
return this._addNode(node); | |
}, | |
insertBefore: function (node, ref_node) { | |
return this._addNode(node, ref_node); | |
}, | |
_addNode: function (node, ref_node) { | |
this._removeNodeFromParent(node); | |
var addedInsertionPoint; | |
var root = this.getOwnerRoot(); | |
if (root) { | |
addedInsertionPoint = this._maybeAddInsertionPoint(node, this.node); | |
} | |
if (this._nodeHasLogicalChildren(this.node)) { | |
if (ref_node) { | |
var children = this.childNodes; | |
var index = children.indexOf(ref_node); | |
if (index < 0) { | |
throw Error('The ref_node to be inserted before is not a child ' + 'of this node'); | |
} | |
} | |
this._addLogicalInfo(node, this.node, index); | |
} | |
this._addNodeToHost(node); | |
if (!this._maybeDistribute(node, this.node) && !this._tryRemoveUndistributedNode(node)) { | |
if (ref_node) { | |
ref_node = ref_node.localName === CONTENT ? this._firstComposedNode(ref_node) : ref_node; | |
} | |
var container = this.node._isShadyRoot ? this.node.host : this.node; | |
addToComposedParent(container, node, ref_node); | |
if (ref_node) { | |
nativeInsertBefore.call(container, node, ref_node); | |
} else { | |
nativeAppendChild.call(container, node); | |
} | |
} | |
if (addedInsertionPoint) { | |
this._updateInsertionPoints(root.host); | |
} | |
this.notifyObserver(); | |
return node; | |
}, | |
removeChild: function (node) { | |
if (factory(node).parentNode !== this.node) { | |
console.warn('The node to be removed is not a child of this node', node); | |
} | |
this._removeNodeFromHost(node); | |
if (!this._maybeDistribute(node, this.node)) { | |
var container = this.node._isShadyRoot ? this.node.host : this.node; | |
if (container === node.parentNode) { | |
removeFromComposedParent(container, node); | |
nativeRemoveChild.call(container, node); | |
} | |
} | |
this.notifyObserver(); | |
return node; | |
}, | |
replaceChild: function (node, ref_node) { | |
this.insertBefore(node, ref_node); | |
this.removeChild(ref_node); | |
return node; | |
}, | |
_hasCachedOwnerRoot: function (node) { | |
return Boolean(node._ownerShadyRoot !== undefined); | |
}, | |
getOwnerRoot: function () { | |
return this._ownerShadyRootForNode(this.node); | |
}, | |
_ownerShadyRootForNode: function (node) { | |
if (!node) { | |
return; | |
} | |
if (node._ownerShadyRoot === undefined) { | |
var root; | |
if (node._isShadyRoot) { | |
root = node; | |
} else { | |
var parent = Polymer.dom(node).parentNode; | |
if (parent) { | |
root = parent._isShadyRoot ? parent : this._ownerShadyRootForNode(parent); | |
} else { | |
root = null; | |
} | |
} | |
node._ownerShadyRoot = root; | |
} | |
return node._ownerShadyRoot; | |
}, | |
_maybeDistribute: function (node, parent) { | |
var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent && Polymer.dom(node).querySelector(CONTENT); | |
var wrappedContent = fragContent && Polymer.dom(fragContent).parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE; | |
var hasContent = fragContent || node.localName === CONTENT; | |
if (hasContent) { | |
var root = this._ownerShadyRootForNode(parent); | |
if (root) { | |
var host = root.host; | |
this._lazyDistribute(host); | |
} | |
} | |
var parentNeedsDist = this._parentNeedsDistribution(parent); | |
if (parentNeedsDist) { | |
this._lazyDistribute(parent); | |
} | |
return parentNeedsDist || hasContent && !wrappedContent; | |
}, | |
_maybeAddInsertionPoint: function (node, parent) { | |
var added; | |
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent) { | |
var c$ = factory(node).querySelectorAll(CONTENT); | |
for (var i = 0, n, np, na; i < c$.length && (n = c$[i]); i++) { | |
np = factory(n).parentNode; | |
if (np === node) { | |
np = parent; | |
} | |
na = this._maybeAddInsertionPoint(n, np); | |
added = added || na; | |
} | |
} else if (node.localName === CONTENT) { | |
saveLightChildrenIfNeeded(parent); | |
saveLightChildrenIfNeeded(node); | |
added = true; | |
} | |
return added; | |
}, | |
_tryRemoveUndistributedNode: function (node) { | |
if (this.node.shadyRoot) { | |
var parent = getComposedParent(node); | |
if (parent) { | |
nativeRemoveChild.call(parent, node); | |
} | |
return true; | |
} | |
}, | |
_updateInsertionPoints: function (host) { | |
var i$ = host.shadyRoot._insertionPoints = factory(host.shadyRoot).querySelectorAll(CONTENT); | |
for (var i = 0, c; i < i$.length; i++) { | |
c = i$[i]; | |
saveLightChildrenIfNeeded(c); | |
saveLightChildrenIfNeeded(factory(c).parentNode); | |
} | |
}, | |
_nodeHasLogicalChildren: function (node) { | |
return Boolean(node._lightChildren !== undefined); | |
}, | |
_parentNeedsDistribution: function (parent) { | |
return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); | |
}, | |
_removeNodeFromParent: function (node) { | |
var parent = node._lightParent || node.parentNode; | |
if (parent && hasDomApi(parent)) { | |
factory(parent).notifyObserver(); | |
} | |
this._removeNodeFromHost(node, true); | |
}, | |
_removeNodeFromHost: function (node, ensureComposedRemoval) { | |
var hostNeedsDist; | |
var root; | |
var parent = node._lightParent; | |
if (parent) { | |
factory(node)._distributeParent(); | |
root = this._ownerShadyRootForNode(node); | |
if (root) { | |
root.host._elementRemove(node); | |
hostNeedsDist = this._removeDistributedChildren(root, node); | |
} | |
this._removeLogicalInfo(node, parent); | |
} | |
this._removeOwnerShadyRoot(node); | |
if (root && hostNeedsDist) { | |
this._updateInsertionPoints(root.host); | |
this._lazyDistribute(root.host); | |
} else if (ensureComposedRemoval) { | |
removeFromComposedParent(getComposedParent(node), node); | |
} | |
}, | |
_removeDistributedChildren: function (root, container) { | |
var hostNeedsDist; | |
var ip$ = root._insertionPoints; | |
for (var i = 0; i < ip$.length; i++) { | |
var content = ip$[i]; | |
if (this._contains(container, content)) { | |
var dc$ = factory(content).getDistributedNodes(); | |
for (var j = 0; j < dc$.length; j++) { | |
hostNeedsDist = true; | |
var node = dc$[j]; | |
var parent = node.parentNode; | |
if (parent) { | |
removeFromComposedParent(parent, node); | |
nativeRemoveChild.call(parent, node); | |
} | |
} | |
} | |
} | |
return hostNeedsDist; | |
}, | |
_contains: function (container, node) { | |
while (node) { | |
if (node == container) { | |
return true; | |
} | |
node = factory(node).parentNode; | |
} | |
}, | |
_addNodeToHost: function (node) { | |
var root = this.getOwnerRoot(); | |
if (root) { | |
root.host._elementAdd(node); | |
} | |
}, | |
_addLogicalInfo: function (node, container, index) { | |
var children = factory(container).childNodes; | |
index = index === undefined ? children.length : index; | |
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | |
var c$ = arrayCopyChildNodes(node); | |
for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { | |
children.splice(index++, 0, n); | |
n._lightParent = container; | |
} | |
} else { | |
children.splice(index, 0, node); | |
node._lightParent = container; | |
} | |
}, | |
_removeLogicalInfo: function (node, container) { | |
var children = factory(container).childNodes; | |
var index = children.indexOf(node); | |
if (index < 0 || container !== node._lightParent) { | |
throw Error('The node to be removed is not a child of this node'); | |
} | |
children.splice(index, 1); | |
node._lightParent = null; | |
}, | |
_removeOwnerShadyRoot: function (node) { | |
if (this._hasCachedOwnerRoot(node)) { | |
var c$ = factory(node).childNodes; | |
for (var i = 0, l = c$.length, n; i < l && (n = c$[i]); i++) { | |
this._removeOwnerShadyRoot(n); | |
} | |
} | |
node._ownerShadyRoot = undefined; | |
}, | |
_firstComposedNode: function (content) { | |
var n$ = factory(content).getDistributedNodes(); | |
for (var i = 0, l = n$.length, n, p$; i < l && (n = n$[i]); i++) { | |
p$ = factory(n).getDestinationInsertionPoints(); | |
if (p$[p$.length - 1] === content) { | |
return n; | |
} | |
} | |
}, | |
querySelector: function (selector) { | |
return this.querySelectorAll(selector)[0]; | |
}, | |
querySelectorAll: function (selector) { | |
return this._query(function (n) { | |
return matchesSelector.call(n, selector); | |
}, this.node); | |
}, | |
_query: function (matcher, node) { | |
node = node || this.node; | |
var list = []; | |
this._queryElements(factory(node).childNodes, matcher, list); | |
return list; | |
}, | |
_queryElements: function (elements, matcher, list) { | |
for (var i = 0, l = elements.length, c; i < l && (c = elements[i]); i++) { | |
if (c.nodeType === Node.ELEMENT_NODE) { | |
this._queryElement(c, matcher, list); | |
} | |
} | |
}, | |
_queryElement: function (node, matcher, list) { | |
if (matcher(node)) { | |
list.push(node); | |
} | |
this._queryElements(factory(node).childNodes, matcher, list); | |
}, | |
getDestinationInsertionPoints: function () { | |
return this.node._destinationInsertionPoints || []; | |
}, | |
getDistributedNodes: function () { | |
return this.node._distributedNodes || []; | |
}, | |
queryDistributedElements: function (selector) { | |
var c$ = this.getEffectiveChildNodes(); | |
var list = []; | |
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { | |
if (c.nodeType === Node.ELEMENT_NODE && matchesSelector.call(c, selector)) { | |
list.push(c); | |
} | |
} | |
return list; | |
}, | |
getEffectiveChildNodes: function () { | |
var list = []; | |
var c$ = this.childNodes; | |
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { | |
if (c.localName === CONTENT) { | |
var d$ = factory(c).getDistributedNodes(); | |
for (var j = 0; j < d$.length; j++) { | |
list.push(d$[j]); | |
} | |
} else { | |
list.push(c); | |
} | |
} | |
return list; | |
}, | |
_clear: function () { | |
while (this.childNodes.length) { | |
this.removeChild(this.childNodes[0]); | |
} | |
}, | |
setAttribute: function (name, value) { | |
this.node.setAttribute(name, value); | |
this._distributeParent(); | |
}, | |
removeAttribute: function (name) { | |
this.node.removeAttribute(name); | |
this._distributeParent(); | |
}, | |
_distributeParent: function () { | |
if (this._parentNeedsDistribution(this.parentNode)) { | |
this._lazyDistribute(this.parentNode); | |
} | |
}, | |
cloneNode: function (deep) { | |
var n = nativeCloneNode.call(this.node, false); | |
if (deep) { | |
var c$ = this.childNodes; | |
var d = factory(n); | |
for (var i = 0, nc; i < c$.length; i++) { | |
nc = factory(c$[i]).cloneNode(true); | |
d.appendChild(nc); | |
} | |
} | |
return n; | |
}, | |
importNode: function (externalNode, deep) { | |
var doc = this.node instanceof Document ? this.node : this.node.ownerDocument; | |
var n = nativeImportNode.call(doc, externalNode, false); | |
if (deep) { | |
var c$ = factory(externalNode).childNodes; | |
var d = factory(n); | |
for (var i = 0, nc; i < c$.length; i++) { | |
nc = factory(doc).importNode(c$[i], true); | |
d.appendChild(nc); | |
} | |
} | |
return n; | |
}, | |
observeNodes: function (callback) { | |
if (callback) { | |
if (!this.observer) { | |
this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObserver(this) : new DomApi.EffectiveNodesObserver(this); | |
} | |
return this.observer.addListener(callback); | |
} | |
}, | |
unobserveNodes: function (handle) { | |
if (this.observer) { | |
this.observer.removeListener(handle); | |
} | |
}, | |
notifyObserver: function () { | |
if (this.observer) { | |
this.observer.notify(); | |
} | |
} | |
}; | |
if (!Settings.useShadow) { | |
Object.defineProperties(DomApi.prototype, { | |
childNodes: { | |
get: function () { | |
var c$ = getLightChildren(this.node); | |
return Array.isArray(c$) ? c$ : arrayCopyChildNodes(this.node); | |
}, | |
configurable: true | |
}, | |
children: { | |
get: function () { | |
return Array.prototype.filter.call(this.childNodes, function (n) { | |
return n.nodeType === Node.ELEMENT_NODE; | |
}); | |
}, | |
configurable: true | |
}, | |
parentNode: { | |
get: function () { | |
return this.node._lightParent || getComposedParent(this.node); | |
}, | |
configurable: true | |
}, | |
firstChild: { | |
get: function () { | |
return this.childNodes[0]; | |
}, | |
configurable: true | |
}, | |
lastChild: { | |
get: function () { | |
var c$ = this.childNodes; | |
return c$[c$.length - 1]; | |
}, | |
configurable: true | |
}, | |
nextSibling: { | |
get: function () { | |
var c$ = this.parentNode && factory(this.parentNode).childNodes; | |
if (c$) { | |
return c$[Array.prototype.indexOf.call(c$, this.node) + 1]; | |
} | |
}, | |
configurable: true | |
}, | |
previousSibling: { | |
get: function () { | |
var c$ = this.parentNode && factory(this.parentNode).childNodes; | |
if (c$) { | |
return c$[Array.prototype.indexOf.call(c$, this.node) - 1]; | |
} | |
}, | |
configurable: true | |
}, | |
firstElementChild: { | |
get: function () { | |
return this.children[0]; | |
}, | |
configurable: true | |
}, | |
lastElementChild: { | |
get: function () { | |
var c$ = this.children; | |
return c$[c$.length - 1]; | |
}, | |
configurable: true | |
}, | |
nextElementSibling: { | |
get: function () { | |
var c$ = this.parentNode && factory(this.parentNode).children; | |
if (c$) { | |
return c$[Array.prototype.indexOf.call(c$, this.node) + 1]; | |
} | |
}, | |
configurable: true | |
}, | |
previousElementSibling: { | |
get: function () { | |
var c$ = this.parentNode && factory(this.parentNode).children; | |
if (c$) { | |
return c$[Array.prototype.indexOf.call(c$, this.node) - 1]; | |
} | |
}, | |
configurable: true | |
}, | |
textContent: { | |
get: function () { | |
var nt = this.node.nodeType; | |
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) { | |
return this.node.textContent; | |
} else { | |
var tc = []; | |
for (var i = 0, cn = this.childNodes, c; c = cn[i]; i++) { | |
if (c.nodeType !== Node.COMMENT_NODE) { | |
tc.push(c.textContent); | |
} | |
} | |
return tc.join(''); | |
} | |
}, | |
set: function (text) { | |
var nt = this.node.nodeType; | |
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) { | |
this.node.textContent = text; | |
} else { | |
this._clear(); | |
if (text) { | |
this.appendChild(document.createTextNode(text)); | |
} | |
} | |
}, | |
configurable: true | |
}, | |
innerHTML: { | |
get: function () { | |
var nt = this.node.nodeType; | |
if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) { | |
return null; | |
} else { | |
return getInnerHTML(this.node); | |
} | |
}, | |
set: function (text) { | |
var nt = this.node.nodeType; | |
if (nt !== Node.TEXT_NODE || nt !== Node.COMMENT_NODE) { | |
this._clear(); | |
var d = document.createElement('div'); | |
d.innerHTML = text; | |
var c$ = arrayCopyChildNodes(d); | |
for (var i = 0; i < c$.length; i++) { | |
this.appendChild(c$[i]); | |
} | |
} | |
}, | |
configurable: true | |
} | |
}); | |
DomApi.prototype._getComposedInnerHTML = function () { | |
return getInnerHTML(this.node, true); | |
}; | |
} else { | |
var forwardMethods = function (m$) { | |
for (var i = 0; i < m$.length; i++) { | |
forwardMethod(m$[i]); | |
} | |
}; | |
var forwardMethod = function (method) { | |
DomApi.prototype[method] = function () { | |
return this.node[method].apply(this.node, arguments); | |
}; | |
}; | |
forwardMethods([ | |
'cloneNode', | |
'appendChild', | |
'insertBefore', | |
'removeChild', | |
'replaceChild' | |
]); | |
DomApi.prototype.querySelectorAll = function (selector) { | |
return arrayCopy(this.node.querySelectorAll(selector)); | |
}; | |
DomApi.prototype.getOwnerRoot = function () { | |
var n = this.node; | |
while (n) { | |
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) { | |
return n; | |
} | |
n = n.parentNode; | |
} | |
}; | |
DomApi.prototype.importNode = function (externalNode, deep) { | |
var doc = this.node instanceof Document ? this.node : this.node.ownerDocument; | |
return doc.importNode(externalNode, deep); | |
}; | |
DomApi.prototype.getDestinationInsertionPoints = function () { | |
var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInsertionPoints(); | |
return n$ ? arrayCopy(n$) : []; | |
}; | |
DomApi.prototype.getDistributedNodes = function () { | |
var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes(); | |
return n$ ? arrayCopy(n$) : []; | |
}; | |
DomApi.prototype._distributeParent = function () { | |
}; | |
Object.defineProperties(DomApi.prototype, { | |
childNodes: { | |
get: function () { | |
return arrayCopyChildNodes(this.node); | |
}, | |
configurable: true | |
}, | |
children: { | |
get: function () { | |
return arrayCopyChildren(this.node); | |
}, | |
configurable: true | |
}, | |
textContent: { | |
get: function () { | |
return this.node.textContent; | |
}, | |
set: function (value) { | |
return this.node.textContent = value; | |
}, | |
configurable: true | |
}, | |
innerHTML: { | |
get: function () { | |
return this.node.innerHTML; | |
}, | |
set: function (value) { | |
return this.node.innerHTML = value; | |
}, | |
configurable: true | |
} | |
}); | |
var forwardProperties = function (f$) { | |
for (var i = 0; i < f$.length; i++) { | |
forwardProperty(f$[i]); | |
} | |
}; | |
var forwardProperty = function (name) { | |
Object.defineProperty(DomApi.prototype, name, { | |
get: function () { | |
return this.node[name]; | |
}, | |
configurable: true | |
}); | |
}; | |
forwardProperties([ | |
'parentNode', | |
'firstChild', | |
'lastChild', | |
'nextSibling', | |
'previousSibling', | |
'firstElementChild', | |
'lastElementChild', | |
'nextElementSibling', | |
'previousElementSibling' | |
]); | |
} | |
var CONTENT = 'content'; | |
function factory(node, patch) { | |
node = node || document; | |
if (!node.__domApi) { | |
node.__domApi = new DomApi(node, patch); | |
} | |
return node.__domApi; | |
} | |
; | |
function hasDomApi(node) { | |
return Boolean(node.__domApi); | |
} | |
; | |
Polymer.dom = function (obj, patch) { | |
if (obj instanceof Event) { | |
return Polymer.EventApi.factory(obj); | |
} else { | |
return factory(obj, patch); | |
} | |
}; | |
function getLightChildren(node) { | |
var children = node._lightChildren; | |
return children ? children : node.childNodes; | |
} | |
function getComposedChildren(node) { | |
if (!node._composedChildren) { | |
node._composedChildren = arrayCopyChildNodes(node); | |
} | |
return node._composedChildren; | |
} | |
function addToComposedParent(parent, node, ref_node) { | |
var children = getComposedChildren(parent); | |
var i = ref_node ? children.indexOf(ref_node) : -1; | |
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | |
var fragChildren = getComposedChildren(node); | |
for (var j = 0; j < fragChildren.length; j++) { | |
addNodeToComposedChildren(fragChildren[j], parent, children, i + j); | |
} | |
node._composedChildren = null; | |
} else { | |
addNodeToComposedChildren(node, parent, children, i); | |
} | |
} | |
function getComposedParent(node) { | |
return node.__patched ? node._composedParent : node.parentNode; | |
} | |
function addNodeToComposedChildren(node, parent, children, i) { | |
node._composedParent = parent; | |
children.splice(i >= 0 ? i : children.length, 0, node); | |
} | |
function removeFromComposedParent(parent, node) { | |
node._composedParent = null; | |
if (parent) { | |
var children = getComposedChildren(parent); | |
var i = children.indexOf(node); | |
if (i >= 0) { | |
children.splice(i, 1); | |
} | |
} | |
} | |
function saveLightChildrenIfNeeded(node) { | |
if (!node._lightChildren) { | |
var c$ = arrayCopyChildNodes(node); | |
for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) { | |
child._lightParent = child._lightParent || node; | |
} | |
node._lightChildren = c$; | |
} | |
} | |
function arrayCopyChildNodes(parent) { | |
var copy = [], i = 0; | |
for (var n = parent.firstChild; n; n = n.nextSibling) { | |
copy[i++] = n; | |
} | |
return copy; | |
} | |
function arrayCopyChildren(parent) { | |
var copy = [], i = 0; | |
for (var n = parent.firstElementChild; n; n = n.nextElementSibling) { | |
copy[i++] = n; | |
} | |
return copy; | |
} | |
function arrayCopy(a$) { | |
var l = a$.length; | |
var copy = new Array(l); | |
for (var i = 0; i < l; i++) { | |
copy[i] = a$[i]; | |
} | |
return copy; | |
} | |
function hasInsertionPoint(root) { | |
return Boolean(root && root._insertionPoints.length); | |
} | |
var p = Element.prototype; | |
var matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector; | |
return { | |
getLightChildren: getLightChildren, | |
getComposedParent: getComposedParent, | |
getComposedChildren: getComposedChildren, | |
removeFromComposedParent: removeFromComposedParent, | |
saveLightChildrenIfNeeded: saveLightChildrenIfNeeded, | |
matchesSelector: matchesSelector, | |
hasInsertionPoint: hasInsertionPoint, | |
ctor: DomApi, | |
factory: factory, | |
hasDomApi: hasDomApi, | |
arrayCopy: arrayCopy, | |
arrayCopyChildNodes: arrayCopyChildNodes, | |
arrayCopyChildren: arrayCopyChildren, | |
wrap: wrap | |
}; | |
}(); | |
Polymer.Base.extend(Polymer.dom, { | |
_flushGuard: 0, | |
_FLUSH_MAX: 100, | |
_needsTakeRecords: !Polymer.Settings.useNativeCustomElements, | |
_debouncers: [], | |
_staticFlushList: [], | |
_finishDebouncer: null, | |
flush: function () { | |
this._flushGuard = 0; | |
this._prepareFlush(); | |
while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) { | |
for (var i = 0; i < this._debouncers.length; i++) { | |
this._debouncers[i].complete(); | |
} | |
if (this._finishDebouncer) { | |
this._finishDebouncer.complete(); | |
} | |
this._prepareFlush(); | |
this._flushGuard++; | |
} | |
if (this._flushGuard >= this._FLUSH_MAX) { | |
console.warn('Polymer.dom.flush aborted. Flush may not be complete.'); | |
} | |
}, | |
_prepareFlush: function () { | |
if (this._needsTakeRecords) { | |
CustomElements.takeRecords(); | |
} | |
for (var i = 0; i < this._staticFlushList.length; i++) { | |
this._staticFlushList[i](); | |
} | |
}, | |
addStaticFlush: function (fn) { | |
this._staticFlushList.push(fn); | |
}, | |
removeStaticFlush: function (fn) { | |
var i = this._staticFlushList.indexOf(fn); | |
if (i >= 0) { | |
this._staticFlushList.splice(i, 1); | |
} | |
}, | |
addDebouncer: function (debouncer) { | |
this._debouncers.push(debouncer); | |
this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush); | |
}, | |
_finishFlush: function () { | |
Polymer.dom._debouncers = []; | |
} | |
}); | |
Polymer.EventApi = function () { | |
'use strict'; | |
var DomApi = Polymer.DomApi.ctor; | |
var Settings = Polymer.Settings; | |
DomApi.Event = function (event) { | |
this.event = event; | |
}; | |
if (Settings.useShadow) { | |
DomApi.Event.prototype = { | |
get rootTarget() { | |
return this.event.path[0]; | |
}, | |
get localTarget() { | |
return this.event.target; | |
}, | |
get path() { | |
return this.event.path; | |
} | |
}; | |
} else { | |
DomApi.Event.prototype = { | |
get rootTarget() { | |
return this.event.target; | |
}, | |
get localTarget() { | |
var current = this.event.currentTarget; | |
var currentRoot = current && Polymer.dom(current).getOwnerRoot(); | |
var p$ = this.path; | |
for (var i = 0; i < p$.length; i++) { | |
if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) { | |
return p$[i]; | |
} | |
} | |
}, | |
get path() { | |
if (!this.event._path) { | |
var path = []; | |
var o = this.rootTarget; | |
while (o) { | |
path.push(o); | |
o = Polymer.dom(o).parentNode || o.host; | |
} | |
path.push(window); | |
this.event._path = path; | |
} | |
return this.event._path; | |
} | |
}; | |
} | |
var factory = function (event) { | |
if (!event.__eventApi) { | |
event.__eventApi = new DomApi.Event(event); | |
} | |
return event.__eventApi; | |
}; | |
return { factory: factory }; | |
}(); | |
(function () { | |
'use strict'; | |
var DomApi = Polymer.DomApi.ctor; | |
Object.defineProperty(DomApi.prototype, 'classList', { | |
get: function () { | |
if (!this._classList) { | |
this._classList = new DomApi.ClassList(this); | |
} | |
return this._classList; | |
}, | |
configurable: true | |
}); | |
DomApi.ClassList = function (host) { | |
this.domApi = host; | |
this.node = host.node; | |
}; | |
DomApi.ClassList.prototype = { | |
add: function () { | |
this.node.classList.add.apply(this.node.classList, arguments); | |
this.domApi._distributeParent(); | |
}, | |
remove: function () { | |
this.node.classList.remove.apply(this.node.classList, arguments); | |
this.domApi._distributeParent(); | |
}, | |
toggle: function () { | |
this.node.classList.toggle.apply(this.node.classList, arguments); | |
this.domApi._distributeParent(); | |
}, | |
contains: function () { | |
return this.node.classList.contains.apply(this.node.classList, arguments); | |
} | |
}; | |
}()); | |
(function () { | |
'use strict'; | |
var DomApi = Polymer.DomApi.ctor; | |
var Settings = Polymer.Settings; | |
var hasDomApi = Polymer.DomApi.hasDomApi; | |
DomApi.EffectiveNodesObserver = function (domApi) { | |
this.domApi = domApi; | |
this.node = this.domApi.node; | |
this._listeners = []; | |
}; | |
DomApi.EffectiveNodesObserver.prototype = { | |
addListener: function (callback) { | |
if (!this._isSetup) { | |
this._setup(); | |
this._isSetup = true; | |
} | |
var listener = { | |
fn: callback, | |
_nodes: [] | |
}; | |
this._listeners.push(listener); | |
this._scheduleNotify(); | |
return listener; | |
}, | |
removeListener: function (handle) { | |
var i = this._listeners.indexOf(handle); | |
if (i >= 0) { | |
this._listeners.splice(i, 1); | |
handle._nodes = []; | |
} | |
if (!this._hasListeners()) { | |
this._cleanup(); | |
this._isSetup = false; | |
} | |
}, | |
_setup: function () { | |
this._observeContentElements(this.domApi.childNodes); | |
}, | |
_cleanup: function () { | |
this._unobserveContentElements(this.domApi.childNodes); | |
}, | |
_hasListeners: function () { | |
return Boolean(this._listeners.length); | |
}, | |
_scheduleNotify: function () { | |
if (this._debouncer) { | |
this._debouncer.stop(); | |
} | |
this._debouncer = Polymer.Debounce(this._debouncer, this._notify); | |
this._debouncer.context = this; | |
Polymer.dom.addDebouncer(this._debouncer); | |
}, | |
notify: function () { | |
if (this._hasListeners()) { | |
this._scheduleNotify(); | |
} | |
}, | |
_notify: function (mxns) { | |
this._beforeCallListeners(); | |
this._callListeners(); | |
}, | |
_beforeCallListeners: function () { | |
this._updateContentElements(); | |
}, | |
_updateContentElements: function () { | |
this._observeContentElements(this.domApi.childNodes); | |
}, | |
_observeContentElements: function (elements) { | |
for (var i = 0, n; i < elements.length && (n = elements[i]); i++) { | |
if (this._isContent(n)) { | |
n.__observeNodesMap = n.__observeNodesMap || new WeakMap(); | |
if (!n.__observeNodesMap.has(this)) { | |
n.__observeNodesMap.set(this, this._observeContent(n)); | |
} | |
} | |
} | |
}, | |
_observeContent: function (content) { | |
var self = this; | |
var h = Polymer.dom(content).observeNodes(function () { | |
self._scheduleNotify(); | |
}); | |
h._avoidChangeCalculation = true; | |
return h; | |
}, | |
_unobserveContentElements: function (elements) { | |
for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) { | |
if (this._isContent(n)) { | |
h = n.__observeNodesMap.get(this); | |
if (h) { | |
Polymer.dom(n).unobserveNodes(h); | |
n.__observeNodesMap.delete(this); | |
} | |
} | |
} | |
}, | |
_isContent: function (node) { | |
return node.localName === 'content'; | |
}, | |
_callListeners: function () { | |
var o$ = this._listeners; | |
var nodes = this._getEffectiveNodes(); | |
for (var i = 0, o; i < o$.length && (o = o$[i]); i++) { | |
var info = this._generateListenerInfo(o, nodes); | |
if (info || o._alwaysNotify) { | |
this._callListener(o, info); | |
} | |
} | |
}, | |
_getEffectiveNodes: function () { | |
return this.domApi.getEffectiveChildNodes(); | |
}, | |
_generateListenerInfo: function (listener, newNodes) { | |
if (listener._avoidChangeCalculation) { | |
return true; | |
} | |
var oldNodes = listener._nodes; | |
var info = { | |
target: this.node, | |
addedNodes: [], | |
removedNodes: [] | |
}; | |
var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes); | |
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++) { | |
info.removedNodes.push(n); | |
} | |
} | |
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { | |
for (var j = s.index; j < s.index + s.addedCount; j++) { | |
info.addedNodes.push(newNodes[j]); | |
} | |
} | |
listener._nodes = newNodes; | |
if (info.addedNodes.length || info.removedNodes.length) { | |
return info; | |
} | |
}, | |
_callListener: function (listener, info) { | |
return listener.fn.call(this.node, info); | |
}, | |
enableShadowAttributeTracking: function () { | |
} | |
}; | |
if (Settings.useShadow) { | |
var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup; | |
var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup; | |
var beforeCallListeners = DomApi.EffectiveNodesObserver.prototype._beforeCallListeners; | |
Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, { | |
_setup: function () { | |
if (!this._observer) { | |
var self = this; | |
this._mutationHandler = function (mxns) { | |
if (mxns && mxns.length) { | |
self._scheduleNotify(); | |
} | |
}; | |
this._observer = new MutationObserver(this._mutationHandler); | |
this._boundFlush = function () { | |
self._flush(); | |
}; | |
Polymer.dom.addStaticFlush(this._boundFlush); | |
this._observer.observe(this.node, { childList: true }); | |
} | |
baseSetup.call(this); | |
}, | |
_cleanup: function () { | |
this._observer.disconnect(); | |
this._observer = null; | |
this._mutationHandler = null; | |
Polymer.dom.removeStaticFlush(this._boundFlush); | |
baseCleanup.call(this); | |
}, | |
_flush: function () { | |
if (this._observer) { | |
this._mutationHandler(this._observer.takeRecords()); | |
} | |
}, | |
enableShadowAttributeTracking: function () { | |
if (this._observer) { | |
this._makeContentListenersAlwaysNotify(); | |
this._observer.disconnect(); | |
this._observer.observe(this.node, { | |
childList: true, | |
attributes: true, | |
subtree: true | |
}); | |
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; | |
} | |
} | |
}); | |
} | |
}()); | |
(function () { | |
'use strict'; | |
var DomApi = Polymer.DomApi.ctor; | |
var Settings = Polymer.Settings; | |
DomApi.DistributedNodesObserver = function (domApi) { | |
DomApi.EffectiveNodesObserver.call(this, domApi); | |
}; | |
DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesObserver.prototype); | |
Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, { | |
_setup: function () { | |
}, | |
_cleanup: function () { | |
}, | |
_beforeCallListeners: function () { | |
}, | |
_getEffectiveNodes: function () { | |
return this.domApi.getDistributedNodes(); | |
} | |
}); | |
if (Settings.useShadow) { | |
Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, { | |
_setup: function () { | |
if (!this._observer) { | |
var root = this.domApi.getOwnerRoot(); | |
var host = root && root.host; | |
if (host) { | |
var self = this; | |
this._observer = Polymer.dom(host).observeNodes(function () { | |
self._scheduleNotify(); | |
}); | |
this._observer._isContentListener = true; | |
if (this._hasAttrSelect()) { | |
Polymer.dom(host).observer.enableShadowAttributeTracking(); | |
} | |
} | |
} | |
}, | |
_hasAttrSelect: function () { | |
var select = this.node.getAttribute('select'); | |
return select && select.match(/[[.]+/); | |
}, | |
_cleanup: function () { | |
var root = this.domApi.getOwnerRoot(); | |
var host = root && root.host; | |
if (host) { | |
Polymer.dom(host).unobserveNodes(this._observer); | |
} | |
this._observer = null; | |
} | |
}); | |
} | |
}()); | |
(function () { | |
var hasDomApi = Polymer.DomApi.hasDomApi; | |
Polymer.Base._addFeature({ | |
_prepShady: function () { | |
this._useContent = this._useContent || Boolean(this._template); | |
}, | |
_poolContent: function () { | |
if (this._useContent) { | |
saveLightChildrenIfNeeded(this); | |
} | |
}, | |
_setupRoot: function () { | |
if (this._useContent) { | |
this._createLocalRoot(); | |
if (!this.dataHost) { | |
upgradeLightChildren(this._lightChildren); | |
} | |
} | |
}, | |
_createLocalRoot: function () { | |
this.shadyRoot = this.root; | |
this.shadyRoot._distributionClean = false; | |
this.shadyRoot._hasDistributed = false; | |
this.shadyRoot._isShadyRoot = true; | |
this.shadyRoot._dirtyRoots = []; | |
var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : []; | |
saveLightChildrenIfNeeded(this.shadyRoot); | |
for (var i = 0, c; i < i$.length; i++) { | |
c = i$[i]; | |
saveLightChildrenIfNeeded(c); | |
saveLightChildrenIfNeeded(c.parentNode); | |
} | |
this.shadyRoot.host = this; | |
}, | |
get domHost() { | |
var root = Polymer.dom(this).getOwnerRoot(); | |
return root && root.host; | |
}, | |
distributeContent: function (updateInsertionPoints) { | |
if (this.shadyRoot) { | |
var dom = Polymer.dom(this); | |
if (updateInsertionPoints) { | |
dom._updateInsertionPoints(this); | |
} | |
var host = getTopDistributingHost(this); | |
dom._lazyDistribute(host); | |
} | |
}, | |
_distributeContent: function () { | |
if (this._useContent && !this.shadyRoot._distributionClean) { | |
this._beginDistribute(); | |
this._distributeDirtyRoots(); | |
this._finishDistribute(); | |
} | |
}, | |
_beginDistribute: function () { | |
if (this._useContent && hasInsertionPoint(this.shadyRoot)) { | |
this._resetDistribution(); | |
this._distributePool(this.shadyRoot, this._collectPool()); | |
} | |
}, | |
_distributeDirtyRoots: function () { | |
var c$ = this.shadyRoot._dirtyRoots; | |
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { | |
c._distributeContent(); | |
} | |
this.shadyRoot._dirtyRoots = []; | |
}, | |
_finishDistribute: function () { | |
if (this._useContent) { | |
this.shadyRoot._distributionClean = true; | |
if (hasInsertionPoint(this.shadyRoot)) { | |
this._composeTree(); | |
notifyContentObservers(this.shadyRoot); | |
} else { | |
if (!this.shadyRoot._hasDistributed) { | |
this.textContent = ''; | |
this._composedChildren = null; | |
this.appendChild(this.shadyRoot); | |
} else { | |
var children = this._composeNode(this); | |
this._updateChildNodes(this, children); | |
} | |
} | |
if (!this.shadyRoot._hasDistributed) { | |
notifyInitialDistribution(this); | |
} | |
this.shadyRoot._hasDistributed = true; | |
} | |
}, | |
elementMatches: function (selector, node) { | |
node = node || this; | |
return matchesSelector.call(node, selector); | |
}, | |
_resetDistribution: function () { | |
var children = getLightChildren(this); | |
for (var i = 0; i < children.length; i++) { | |
var child = children[i]; | |
if (child._destinationInsertionPoints) { | |
child._destinationInsertionPoints = undefined; | |
} | |
if (isInsertionPoint(child)) { | |
clearDistributedDestinationInsertionPoints(child); | |
} | |
} | |
var root = this.shadyRoot; | |
var p$ = root._insertionPoints; | |
for (var j = 0; j < p$.length; j++) { | |
p$[j]._distributedNodes = []; | |
} | |
}, | |
_collectPool: function () { | |
var pool = []; | |
var children = getLightChildren(this); | |
for (var i = 0; i < children.length; i++) { | |
var child = children[i]; | |
if (isInsertionPoint(child)) { | |
pool.push.apply(pool, child._distributedNodes); | |
} else { | |
pool.push(child); | |
} | |
} | |
return pool; | |
}, | |
_distributePool: function (node, pool) { | |
var p$ = node._insertionPoints; | |
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) { | |
this._distributeInsertionPoint(p, pool); | |
maybeRedistributeParent(p, this); | |
} | |
}, | |
_distributeInsertionPoint: function (content, pool) { | |
var anyDistributed = false; | |
for (var i = 0, l = pool.length, node; i < l; i++) { | |
node = pool[i]; | |
if (!node) { | |
continue; | |
} | |
if (this._matchesContentSelect(node, content)) { | |
distributeNodeInto(node, content); | |
pool[i] = undefined; | |
anyDistributed = true; | |
} | |
} | |
if (!anyDistributed) { | |
var children = getLightChildren(content); | |
for (var j = 0; j < children.length; j++) { | |
distributeNodeInto(children[j], content); | |
} | |
} | |
}, | |
_composeTree: function () { | |
this._updateChildNodes(this, this._composeNode(this)); | |
var p$ = this.shadyRoot._insertionPoints; | |
for (var i = 0, l = p$.length, p, parent; i < l && (p = p$[i]); i++) { | |
parent = p._lightParent || p.parentNode; | |
if (!parent._useContent && parent !== this && parent !== this.shadyRoot) { | |
this._updateChildNodes(parent, this._composeNode(parent)); | |
} | |
} | |
}, | |
_composeNode: function (node) { | |
var children = []; | |
var c$ = getLightChildren(node.shadyRoot || node); | |
for (var i = 0; i < c$.length; i++) { | |
var child = c$[i]; | |
if (isInsertionPoint(child)) { | |
var distributedNodes = child._distributedNodes; | |
for (var j = 0; j < distributedNodes.length; j++) { | |
var distributedNode = distributedNodes[j]; | |
if (isFinalDestination(child, distributedNode)) { | |
children.push(distributedNode); | |
} | |
} | |
} else { | |
children.push(child); | |
} | |
} | |
return children; | |
}, | |
_updateChildNodes: function (container, children) { | |
var composed = getComposedChildren(container); | |
var splices = Polymer.ArraySplice.calculateSplices(children, composed); | |
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++) { | |
if (getComposedParent(n) === container) { | |
remove(n); | |
} | |
composed.splice(s.index + d, 1); | |
} | |
d -= s.addedCount; | |
} | |
for (var i = 0, s, next; i < splices.length && (s = splices[i]); i++) { | |
next = composed[s.index]; | |
for (var j = s.index, n; j < s.index + s.addedCount; j++) { | |
n = children[j]; | |
insertBefore(container, n, next); | |
composed.splice(j, 0, n); | |
} | |
} | |
ensureComposedParent(container, children); | |
}, | |
_matchesContentSelect: function (node, contentElement) { | |
var select = contentElement.getAttribute('select'); | |
if (!select) { | |
return true; | |
} | |
select = select.trim(); | |
if (!select) { | |
return true; | |
} | |
if (!(node instanceof Element)) { | |
return false; | |
} | |
var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/; | |
if (!validSelectors.test(select)) { | |
return false; | |
} | |
return this.elementMatches(select, node); | |
}, | |
_elementAdd: function () { | |
}, | |
_elementRemove: function () { | |
} | |
}); | |
var saveLightChildrenIfNeeded = Polymer.DomApi.saveLightChildrenIfNeeded; | |
var getLightChildren = Polymer.DomApi.getLightChildren; | |
var matchesSelector = Polymer.DomApi.matchesSelector; | |
var hasInsertionPoint = Polymer.DomApi.hasInsertionPoint; | |
var getComposedChildren = Polymer.DomApi.getComposedChildren; | |
var getComposedParent = Polymer.DomApi.getComposedParent; | |
var removeFromComposedParent = Polymer.DomApi.removeFromComposedParent; | |
function distributeNodeInto(child, insertionPoint) { | |
insertionPoint._distributedNodes.push(child); | |
var points = child._destinationInsertionPoints; | |
if (!points) { | |
child._destinationInsertionPoints = [insertionPoint]; | |
} else { | |
points.push(insertionPoint); | |
} | |
} | |
function clearDistributedDestinationInsertionPoints(content) { | |
var e$ = content._distributedNodes; | |
if (e$) { | |
for (var i = 0; i < e$.length; i++) { | |
var d = e$[i]._destinationInsertionPoints; | |
if (d) { | |
d.splice(d.indexOf(content) + 1, d.length); | |
} | |
} | |
} | |
} | |
function maybeRedistributeParent(content, host) { | |
var parent = content._lightParent; | |
if (parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot) && parent.shadyRoot._distributionClean) { | |
parent.shadyRoot._distributionClean = false; | |
host.shadyRoot._dirtyRoots.push(parent); | |
} | |
} | |
function isFinalDestination(insertionPoint, node) { | |
var points = node._destinationInsertionPoints; | |
return points && points[points.length - 1] === insertionPoint; | |
} | |
function isInsertionPoint(node) { | |
return node.localName == 'content'; | |
} | |
var nativeInsertBefore = Element.prototype.insertBefore; | |
var nativeRemoveChild = Element.prototype.removeChild; | |
function insertBefore(parentNode, newChild, refChild) { | |
var newChildParent = getComposedParent(newChild); | |
if (newChildParent !== parentNode) { | |
removeFromComposedParent(newChildParent, newChild); | |
} | |
remove(newChild); | |
nativeInsertBefore.call(parentNode, newChild, refChild || null); | |
newChild._composedParent = parentNode; | |
} | |
function remove(node) { | |
var parentNode = getComposedParent(node); | |
if (parentNode) { | |
node._composedParent = null; | |
nativeRemoveChild.call(parentNode, node); | |
} | |
} | |
function ensureComposedParent(parent, children) { | |
for (var i = 0, n; i < children.length; i++) { | |
children[i]._composedParent = parent; | |
} | |
} | |
function getTopDistributingHost(host) { | |
while (host && hostNeedsRedistribution(host)) { | |
host = host.domHost; | |
} | |
return host; | |
} | |
function hostNeedsRedistribution(host) { | |
var c$ = Polymer.dom(host).children; | |
for (var i = 0, c; i < c$.length; i++) { | |
c = c$[i]; | |
if (c.localName === 'content') { | |
return host.domHost; | |
} | |
} | |
} | |
function notifyContentObservers(root) { | |
for (var i = 0, c; i < root._insertionPoints.length; i++) { | |
c = root._insertionPoints[i]; | |
if (hasDomApi(c)) { | |
Polymer.dom(c).notifyObserver(); | |
} | |
} | |
} | |
function notifyInitialDistribution(host) { | |
if (hasDomApi(host)) { | |
Polymer.dom(host).notifyObserver(); | |
} | |
} | |
var needsUpgrade = window.CustomElements && !CustomElements.useNative; | |
function upgradeLightChildren(children) { | |
if (needsUpgrade && children) { | |
for (var i = 0; i < children.length; i++) { | |
CustomElements.upgrade(children[i]); | |
} | |
} | |
} | |
}()); | |
if (Polymer.Settings.useShadow) { | |
Polymer.Base._addFeature({ | |
_poolContent: function () { | |
}, | |
_beginDistribute: function () { | |
}, | |
distributeContent: function () { | |
}, | |
_distributeContent: function () { | |
}, | |
_finishDistribute: function () { | |
}, | |
_createLocalRoot: function () { | |
this.createShadowRoot(); | |
this.shadowRoot.appendChild(this.root); | |
this.root = this.shadowRoot; | |
} | |
}); | |
} | |
Polymer.DomModule = document.createElement('dom-module'); | |
Polymer.Base._addFeature({ | |
_registerFeatures: function () { | |
this._prepIs(); | |
this._prepBehaviors(); | |
this._prepConstructor(); | |
this._prepTemplate(); | |
this._prepShady(); | |
this._prepPropertyInfo(); | |
}, | |
_prepBehavior: function (b) { | |
this._addHostAttributes(b.hostAttributes); | |
}, | |
_initFeatures: function () { | |
this._registerHost(); | |
if (this._template) { | |
this._poolContent(); | |
this._beginHosting(); | |
this._stampTemplate(); | |
this._endHosting(); | |
} | |
this._marshalHostAttributes(); | |
this._setupDebouncers(); | |
this._marshalBehaviors(); | |
this._tryReady(); | |
}, | |
_marshalBehavior: function (b) { | |
} | |
});</script> | |
<script>Polymer.nar = []; | |
Polymer.Annotations = { | |
parseAnnotations: function (template) { | |
var list = []; | |
var content = template._content || template.content; | |
this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace')); | |
return list; | |
}, | |
_parseNodeAnnotations: function (node, list, stripWhiteSpace) { | |
return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace); | |
}, | |
_bindingRegex: /([^{[]*)(\{\{|\[\[)(?!\}\}|\]\])(.+?)(?:\]\]|\}\})/g, | |
_parseBindings: function (text) { | |
var re = this._bindingRegex; | |
var parts = []; | |
var m, lastIndex; | |
while ((m = re.exec(text)) !== null) { | |
if (m[1]) { | |
parts.push({ literal: m[1] }); | |
} | |
var mode = m[2][0]; | |
var value = m[3].trim(); | |
var negate = false; | |
if (value[0] == '!') { | |
negate = true; | |
value = value.substring(1).trim(); | |
} | |
var customEvent, notifyEvent, colon; | |
if (mode == '{' && (colon = value.indexOf('::')) > 0) { | |
notifyEvent = value.substring(colon + 2); | |
value = value.substring(0, colon); | |
customEvent = true; | |
} | |
parts.push({ | |
compoundIndex: parts.length, | |
value: value, | |
mode: mode, | |
negate: negate, | |
event: notifyEvent, | |
customEvent: customEvent | |
}); | |
lastIndex = re.lastIndex; | |
} | |
if (lastIndex && lastIndex < text.length) { | |
var literal = text.substring(lastIndex); | |
if (literal) { | |
parts.push({ literal: literal }); | |
} | |
} | |
if (parts.length) { | |
return parts; | |
} | |
}, | |
_literalFromParts: function (parts) { | |
var s = ''; | |
for (var i = 0; i < parts.length; i++) { | |
var literal = parts[i].literal; | |
s += literal || ''; | |
} | |
return s; | |
}, | |
_parseTextNodeAnnotation: function (node, list) { | |
var parts = this._parseBindings(node.textContent); | |
if (parts) { | |
node.textContent = this._literalFromParts(parts) || ' '; | |
var annote = { | |
bindings: [{ | |
kind: 'text', | |
name: 'textContent', | |
parts: parts, | |
isCompound: parts.length !== 1 | |
}] | |
}; | |
list.push(annote); | |
return annote; | |
} | |
}, | |
_parseElementAnnotations: function (element, list, stripWhiteSpace) { | |
var annote = { | |
bindings: [], | |
events: [] | |
}; | |
if (element.localName === 'content') { | |
list._hasContent = true; | |
} | |
this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace); | |
if (element.attributes) { | |
this._parseNodeAttributeAnnotations(element, annote, list); | |
if (this.prepElement) { | |
this.prepElement(element); | |
} | |
} | |
if (annote.bindings.length || annote.events.length || annote.id) { | |
list.push(annote); | |
} | |
return annote; | |
}, | |
_parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) { | |
if (root.firstChild) { | |
var node = root.firstChild; | |
var i = 0; | |
while (node) { | |
var next = node.nextSibling; | |
if (node.localName === 'template' && !node.hasAttribute('preserve-content')) { | |
this._parseTemplate(node, i, list, annote); | |
} | |
if (node.nodeType === Node.TEXT_NODE) { | |
var n = next; | |
while (n && n.nodeType === Node.TEXT_NODE) { | |
node.textContent += n.textContent; | |
next = n.nextSibling; | |
root.removeChild(n); | |
n = next; | |
} | |
if (stripWhiteSpace && !node.textContent.trim()) { | |
root.removeChild(node); | |
i--; | |
} | |
} | |
if (node.parentNode) { | |
var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace); | |
if (childAnnotation) { | |
childAnnotation.parent = annote; | |
childAnnotation.index = i; | |
} | |
} | |
node = next; | |
i++; | |
} | |
} | |
}, | |
_parseTemplate: function (node, index, list, parent) { | |
var content = document.createDocumentFragment(); | |
content._notes = this.parseAnnotations(node); | |
content.appendChild(node.content); | |
list.push({ | |
bindings: Polymer.nar, | |
events: Polymer.nar, | |
templateContent: content, | |
parent: parent, | |
index: index | |
}); | |
}, | |
_parseNodeAttributeAnnotations: function (node, annotation) { | |
var attrs = Array.prototype.slice.call(node.attributes); | |
for (var i = attrs.length - 1, a; a = attrs[i]; i--) { | |
var n = a.name; | |
var v = a.value; | |
var b; | |
if (n.slice(0, 3) === 'on-') { | |
node.removeAttribute(n); | |
annotation.events.push({ | |
name: n.slice(3), | |
value: v | |
}); | |
} else if (b = this._parseNodeAttributeAnnotation(node, n, v)) { | |
annotation.bindings.push(b); | |
} else if (n === 'id') { | |
annotation.id = v; | |
} | |
} | |
}, | |
_parseNodeAttributeAnnotation: function (node, name, value) { | |
var parts = this._parseBindings(value); | |
if (parts) { | |
var origName = name; | |
var kind = 'property'; | |
if (name[name.length - 1] == '$') { | |
name = name.slice(0, -1); | |
kind = 'attribute'; | |
} | |
var literal = this._literalFromParts(parts); | |
if (literal && kind == 'attribute') { | |
node.setAttribute(name, literal); | |
} | |
if (node.localName == 'input' && name == 'value') { | |
node.setAttribute(origName, ''); | |
} | |
node.removeAttribute(origName); | |
if (kind === 'property') { | |
name = Polymer.CaseMap.dashToCamelCase(name); | |
} | |
return { | |
kind: kind, | |
name: name, | |
parts: parts, | |
literal: literal, | |
isCompound: parts.length !== 1 | |
}; | |
} | |
}, | |
_localSubTree: function (node, host) { | |
return node === host ? node.childNodes : node._lightChildren || node.childNodes; | |
}, | |
findAnnotatedNode: function (root, annote) { | |
var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote.parent); | |
return !parent ? root : Polymer.Annotations._localSubTree(parent, root)[annote.index]; | |
} | |
}; | |
(function () { | |
function resolveCss(cssText, ownerDocument) { | |
return cssText.replace(CSS_URL_RX, function (m, pre, url, post) { | |
return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + post; | |
}); | |
} | |
function resolveAttrs(element, ownerDocument) { | |
for (var name in URL_ATTRS) { | |
var a$ = URL_ATTRS[name]; | |
for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) { | |
if (name === '*' || element.localName === name) { | |
at = element.attributes[a]; | |
v = at && at.value; | |
if (v && v.search(BINDING_RX) < 0) { | |
at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocument); | |
} | |
} | |
} | |
} | |
} | |
function resolve(url, ownerDocument) { | |
if (url && url[0] === '#') { | |
return url; | |
} | |
var resolver = getUrlResolver(ownerDocument); | |
resolver.href = url; | |
return resolver.href || url; | |
} | |
var tempDoc; | |
var tempDocBase; | |
function resolveUrl(url, baseUri) { | |
if (!tempDoc) { | |
tempDoc = document.implementation.createHTMLDocument('temp'); | |
tempDocBase = tempDoc.createElement('base'); | |
tempDoc.head.appendChild(tempDocBase); | |
} | |
tempDocBase.href = baseUri; | |
return resolve(url, tempDoc); | |
} | |
function getUrlResolver(ownerDocument) { | |
return ownerDocument.__urlResolver || (ownerDocument.__urlResolver = ownerDocument.createElement('a')); | |
} | |
var CSS_URL_RX = /(url\()([^)]*)(\))/g; | |
var URL_ATTRS = { | |
'*': [ | |
'href', | |
'src', | |
'style', | |
'url' | |
], | |
form: ['action'] | |
}; | |
var BINDING_RX = /\{\{|\[\[/; | |
Polymer.ResolveUrl = { | |
resolveCss: resolveCss, | |
resolveAttrs: resolveAttrs, | |
resolveUrl: resolveUrl | |
}; | |
}()); | |
Polymer.Base._addFeature({ | |
_prepAnnotations: function () { | |
if (!this._template) { | |
this._notes = []; | |
} else { | |
var self = this; | |
Polymer.Annotations.prepElement = function (element) { | |
self._prepElement(element); | |
}; | |
if (this._template._content && this._template._content._notes) { | |
this._notes = this._template._content._notes; | |
} else { | |
this._notes = Polymer.Annotations.parseAnnotations(this._template); | |
} | |
this._processAnnotations(this._notes); | |
Polymer.Annotations.prepElement = null; | |
} | |
}, | |
_processAnnotations: function (notes) { | |
for (var i = 0; i < notes.length; i++) { | |
var note = notes[i]; | |
for (var j = 0; j < note.bindings.length; j++) { | |
var b = note.bindings[j]; | |
for (var k = 0; k < b.parts.length; k++) { | |
var p = b.parts[k]; | |
if (!p.literal) { | |
p.signature = this._parseMethod(p.value); | |
if (!p.signature) { | |
p.model = this._modelForPath(p.value); | |
} | |
} | |
} | |
} | |
if (note.templateContent) { | |
this._processAnnotations(note.templateContent._notes); | |
var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(note.templateContent._notes); | |
var bindings = []; | |
for (var prop in pp) { | |
bindings.push({ | |
index: note.index, | |
kind: 'property', | |
name: '_parent_' + prop, | |
parts: [{ | |
mode: '{', | |
model: prop, | |
value: prop | |
}] | |
}); | |
} | |
note.bindings = note.bindings.concat(bindings); | |
} | |
} | |
}, | |
_discoverTemplateParentProps: function (notes) { | |
var pp = {}; | |
for (var i = 0, n; i < notes.length && (n = notes[i]); i++) { | |
for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) { | |
for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) { | |
if (p.signature) { | |
var args = p.signature.args; | |
for (var kk = 0; kk < args.length; kk++) { | |
pp[args[kk].model] = true; | |
} | |
} else { | |
pp[p.model] = true; | |
} | |
} | |
} | |
if (n.templateContent) { | |
var tpp = n.templateContent._parentProps; | |
Polymer.Base.mixin(pp, tpp); | |
} | |
} | |
return pp; | |
}, | |
_prepElement: function (element) { | |
Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument); | |
}, | |
_findAnnotatedNode: Polymer.Annotations.findAnnotatedNode, | |
_marshalAnnotationReferences: function () { | |
if (this._template) { | |
this._marshalIdNodes(); | |
this._marshalAnnotatedNodes(); | |
this._marshalAnnotatedListeners(); | |
} | |
}, | |
_configureAnnotationReferences: function (config) { | |
var notes = this._notes; | |
var nodes = this._nodes; | |
for (var i = 0; i < notes.length; i++) { | |
var note = notes[i]; | |
var node = nodes[i]; | |
this._configureTemplateContent(note, node); | |
this._configureCompoundBindings(note, node); | |
} | |
}, | |
_configureTemplateContent: function (note, node) { | |
if (note.templateContent) { | |
node._content = note.templateContent; | |
} | |
}, | |
_configureCompoundBindings: function (note, node) { | |
var bindings = note.bindings; | |
for (var i = 0; i < bindings.length; i++) { | |
var binding = bindings[i]; | |
if (binding.isCompound) { | |
var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {}); | |
var parts = binding.parts; | |
var literals = new Array(parts.length); | |
for (var j = 0; j < parts.length; j++) { | |
literals[j] = parts[j].literal; | |
} | |
var name = binding.name; | |
storage[name] = literals; | |
if (binding.literal && binding.kind == 'property') { | |
if (node._configValue) { | |
node._configValue(name, binding.literal); | |
} else { | |
node[name] = binding.literal; | |
} | |
} | |
} | |
} | |
}, | |
_marshalIdNodes: function () { | |
this.$ = {}; | |
for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { | |
if (a.id) { | |
this.$[a.id] = this._findAnnotatedNode(this.root, a); | |
} | |
} | |
}, | |
_marshalAnnotatedNodes: function () { | |
if (this._notes && this._notes.length) { | |
var r = new Array(this._notes.length); | |
for (var i = 0; i < this._notes.length; i++) { | |
r[i] = this._findAnnotatedNode(this.root, this._notes[i]); | |
} | |
this._nodes = r; | |
} | |
}, | |
_marshalAnnotatedListeners: function () { | |
for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { | |
if (a.events && a.events.length) { | |
var node = this._findAnnotatedNode(this.root, a); | |
for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) { | |
this.listen(node, e.name, e.value); | |
} | |
} | |
} | |
} | |
}); | |
Polymer.Base._addFeature({ | |
listeners: {}, | |
_listenListeners: function (listeners) { | |
var node, name, eventName; | |
for (eventName in listeners) { | |
if (eventName.indexOf('.') < 0) { | |
node = this; | |
name = eventName; | |
} else { | |
name = eventName.split('.'); | |
node = this.$[name[0]]; | |
name = name[1]; | |
} | |
this.listen(node, name, listeners[eventName]); | |
} | |
}, | |
listen: function (node, eventName, methodName) { | |
var handler = this._recallEventHandler(this, eventName, node, methodName); | |
if (!handler) { | |
handler = this._createEventHandler(node, eventName, methodName); | |
} | |
if (handler._listening) { | |
return; | |
} | |
this._listen(node, eventName, handler); | |
handler._listening = true; | |
}, | |
_boundListenerKey: function (eventName, methodName) { | |
return eventName + ':' + methodName; | |
}, | |
_recordEventHandler: function (host, eventName, target, methodName, handler) { | |
var hbl = host.__boundListeners; | |
if (!hbl) { | |
hbl = host.__boundListeners = new WeakMap(); | |
} | |
var bl = hbl.get(target); | |
if (!bl) { | |
bl = {}; | |
hbl.set(target, bl); | |
} | |
var key = this._boundListenerKey(eventName, methodName); | |
bl[key] = handler; | |
}, | |
_recallEventHandler: function (host, eventName, target, methodName) { | |
var hbl = host.__boundListeners; | |
if (!hbl) { | |
return; | |
} | |
var bl = hbl.get(target); | |
if (!bl) { | |
return; | |
} | |
var key = this._boundListenerKey(eventName, methodName); | |
return bl[key]; | |
}, | |
_createEventHandler: function (node, eventName, methodName) { | |
var host = this; | |
var handler = function (e) { | |
if (host[methodName]) { | |
host[methodName](e, e.detail); | |
} else { | |
host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined')); | |
} | |
}; | |
handler._listening = false; | |
this._recordEventHandler(host, eventName, node, methodName, handler); | |
return handler; | |
}, | |
unlisten: function (node, eventName, methodName) { | |
var handler = this._recallEventHandler(this, eventName, node, methodName); | |
if (handler) { | |
this._unlisten(node, eventName, handler); | |
handler._listening = false; | |
} | |
}, | |
_listen: function (node, eventName, handler) { | |
node.addEventListener(eventName, handler); | |
}, | |
_unlisten: function (node, eventName, handler) { | |
node.removeEventListener(eventName, handler); | |
} | |
}); | |
(function () { | |
'use strict'; | |
var wrap = Polymer.DomApi.wrap; | |
var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string'; | |
var GESTURE_KEY = '__polymerGestures'; | |
var HANDLED_OBJ = '__polymerGesturesHandled'; | |
var TOUCH_ACTION = '__polymerGesturesTouchAction'; | |
var TAP_DISTANCE = 25; | |
var TRACK_DISTANCE = 5; | |
var TRACK_LENGTH = 2; | |
var MOUSE_TIMEOUT = 2500; | |
var MOUSE_EVENTS = [ | |
'mousedown', | |
'mousemove', | |
'mouseup', | |
'click' | |
]; | |
var MOUSE_WHICH_TO_BUTTONS = [ | |
0, | |
1, | |
4, | |
2 | |
]; | |
var MOUSE_HAS_BUTTONS = function () { | |
try { | |
return new MouseEvent('test', { buttons: 1 }).buttons === 1; | |
} catch (e) { | |
return false; | |
} | |
}(); | |
var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/); | |
var mouseCanceller = function (mouseEvent) { | |
mouseEvent[HANDLED_OBJ] = { skip: true }; | |
if (mouseEvent.type === 'click') { | |
var path = Polymer.dom(mouseEvent).path; | |
for (var i = 0; i < path.length; i++) { | |
if (path[i] === POINTERSTATE.mouse.target) { | |
return; | |
} | |
} | |
mouseEvent.preventDefault(); | |
mouseEvent.stopPropagation(); | |
} | |
}; | |
function setupTeardownMouseCanceller(setup) { | |
for (var i = 0, en; i < MOUSE_EVENTS.length; i++) { | |
en = MOUSE_EVENTS[i]; | |
if (setup) { | |
document.addEventListener(en, mouseCanceller, true); | |
} else { | |
document.removeEventListener(en, mouseCanceller, true); | |
} | |
} | |
} | |
function ignoreMouse() { | |
if (IS_TOUCH_ONLY) { | |
return; | |
} | |
if (!POINTERSTATE.mouse.mouseIgnoreJob) { | |
setupTeardownMouseCanceller(true); | |
} | |
var unset = function () { | |
setupTeardownMouseCanceller(); | |
POINTERSTATE.mouse.target = null; | |
POINTERSTATE.mouse.mouseIgnoreJob = null; | |
}; | |
POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT); | |
} | |
function hasLeftMouseButton(ev) { | |
var type = ev.type; | |
if (MOUSE_EVENTS.indexOf(type) === -1) { | |
return false; | |
} | |
if (type === 'mousemove') { | |
var buttons = ev.buttons === undefined ? 1 : ev.buttons; | |
if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) { | |
buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0; | |
} | |
return Boolean(buttons & 1); | |
} else { | |
var button = ev.button === undefined ? 0 : ev.button; | |
return button === 0; | |
} | |
} | |
function isSyntheticClick(ev) { | |
if (ev.type === 'click') { | |
if (ev.detail === 0) { | |
return true; | |
} | |
var t = Gestures.findOriginalTarget(ev); | |
var bcr = t.getBoundingClientRect(); | |
var x = ev.pageX, y = ev.pageY; | |
return !(x >= bcr.left && x <= bcr.right && (y >= bcr.top && y <= bcr.bottom)); | |
} | |
return false; | |
} | |
var POINTERSTATE = { | |
mouse: { | |
target: null, | |
mouseIgnoreJob: null | |
}, | |
touch: { | |
x: 0, | |
y: 0, | |
id: -1, | |
scrollDecided: false | |
} | |
}; | |
function firstTouchAction(ev) { | |
var path = Polymer.dom(ev).path; | |
var ta = 'auto'; | |
for (var i = 0, n; i < path.length; i++) { | |
n = path[i]; | |
if (n[TOUCH_ACTION]) { | |
ta = n[TOUCH_ACTION]; | |
break; | |
} | |
} | |
return ta; | |
} | |
function trackDocument(stateObj, movefn, upfn) { | |
stateObj.movefn = movefn; | |
stateObj.upfn = upfn; | |
document.addEventListener('mousemove', movefn); | |
document.addEventListener('mouseup', upfn); | |
} | |
function untrackDocument(stateObj) { | |
document.removeEventListener('mousemove', stateObj.movefn); | |
document.removeEventListener('mouseup', stateObj.upfn); | |
} | |
var Gestures = { | |
gestures: {}, | |
recognizers: [], | |
deepTargetFind: function (x, y) { | |
var node = document.elementFromPoint(x, y); | |
var next = node; | |
while (next && next.shadowRoot) { | |
next = next.shadowRoot.elementFromPoint(x, y); | |
if (next) { | |
node = next; | |
} | |
} | |
return node; | |
}, | |
findOriginalTarget: function (ev) { | |
if (ev.path) { | |
return ev.path[0]; | |
} | |
return ev.target; | |
}, | |
handleNative: function (ev) { | |
var handled; | |
var type = ev.type; | |
var node = wrap(ev.currentTarget); | |
var gobj = node[GESTURE_KEY]; | |
if (!gobj) { | |
return; | |
} | |
var gs = gobj[type]; | |
if (!gs) { | |
return; | |
} | |
if (!ev[HANDLED_OBJ]) { | |
ev[HANDLED_OBJ] = {}; | |
if (type.slice(0, 5) === 'touch') { | |
var t = ev.changedTouches[0]; | |
if (type === 'touchstart') { | |
if (ev.touches.length === 1) { | |
POINTERSTATE.touch.id = t.identifier; | |
} | |
} | |
if (POINTERSTATE.touch.id !== t.identifier) { | |
return; | |
} | |
if (!HAS_NATIVE_TA) { | |
if (type === 'touchstart' || type === 'touchmove') { | |
Gestures.handleTouchAction(ev); | |
} | |
} | |
if (type === 'touchend') { | |
POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget; | |
ignoreMouse(true); | |
} | |
} | |
} | |
handled = ev[HANDLED_OBJ]; | |
if (handled.skip) { | |
return; | |
} | |
var recognizers = Gestures.recognizers; | |
for (var i = 0, r; i < recognizers.length; i++) { | |
r = recognizers[i]; | |
if (gs[r.name] && !handled[r.name]) { | |
if (r.flow && r.flow.start.indexOf(ev.type) > -1) { | |
if (r.reset) { | |
r.reset(); | |
} | |
} | |
} | |
} | |
for (var i = 0, r; i < recognizers.length; i++) { | |
r = recognizers[i]; | |
if (gs[r.name] && !handled[r.name]) { | |
handled[r.name] = true; | |
r[type](ev); | |
} | |
} | |
}, | |
handleTouchAction: function (ev) { | |
var t = ev.changedTouches[0]; | |
var type = ev.type; | |
if (type === 'touchstart') { | |
POINTERSTATE.touch.x = t.clientX; | |
POINTERSTATE.touch.y = t.clientY; | |
POINTERSTATE.touch.scrollDecided = false; | |
} else if (type === 'touchmove') { | |
if (POINTERSTATE.touch.scrollDecided) { | |
return; | |
} | |
POINTERSTATE.touch.scrollDecided = true; | |
var ta = firstTouchAction(ev); | |
var prevent = false; | |
var dx = Math.abs(POINTERSTATE.touch.x - t.clientX); | |
var dy = Math.abs(POINTERSTATE.touch.y - t.clientY); | |
if (!ev.cancelable) { | |
} else if (ta === 'none') { | |
prevent = true; | |
} else if (ta === 'pan-x') { | |
prevent = dy > dx; | |
} else if (ta === 'pan-y') { | |
prevent = dx > dy; | |
} | |
if (prevent) { | |
ev.preventDefault(); | |
} else { | |
Gestures.prevent('track'); | |
} | |
} | |
}, | |
add: function (node, evType, handler) { | |
node = wrap(node); | |
var recognizer = this.gestures[evType]; | |
var deps = recognizer.deps; | |
var name = recognizer.name; | |
var gobj = node[GESTURE_KEY]; | |
if (!gobj) { | |
node[GESTURE_KEY] = gobj = {}; | |
} | |
for (var i = 0, dep, gd; i < deps.length; i++) { | |
dep = deps[i]; | |
if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) { | |
continue; | |
} | |
gd = gobj[dep]; | |
if (!gd) { | |
gobj[dep] = gd = { _count: 0 }; | |
} | |
if (gd._count === 0) { | |
node.addEventListener(dep, this.handleNative); | |
} | |
gd[name] = (gd[name] || 0) + 1; | |
gd._count = (gd._count || 0) + 1; | |
} | |
node.addEventListener(evType, handler); | |
if (recognizer.touchAction) { | |
this.setTouchAction(node, recognizer.touchAction); | |
} | |
}, | |
remove: function (node, evType, handler) { | |
node = wrap(node); | |
var recognizer = this.gestures[evType]; | |
var deps = recognizer.deps; | |
var name = recognizer.name; | |
var gobj = node[GESTURE_KEY]; | |
if (gobj) { | |
for (var i = 0, dep, gd; i < deps.length; i++) { | |
dep = deps[i]; | |
gd = gobj[dep]; | |
if (gd && gd[name]) { | |
gd[name] = (gd[name] || 1) - 1; | |
gd._count = (gd._count || 1) - 1; | |
if (gd._count === 0) { | |
node.removeEventListener(dep, this.handleNative); | |
} | |
} | |
} | |
} | |
node.removeEventListener(evType, handler); | |
}, | |
register: function (recog) { | |
this.recognizers.push(recog); | |
for (var i = 0; i < recog.emits.length; i++) { | |
this.gestures[recog.emits[i]] = recog; | |
} | |
}, | |
findRecognizerByEvent: function (evName) { | |
for (var i = 0, r; i < this.recognizers.length; i++) { | |
r = this.recognizers[i]; | |
for (var j = 0, n; j < r.emits.length; j++) { | |
n = r.emits[j]; | |
if (n === evName) { | |
return r; | |
} | |
} | |
} | |
return null; | |
}, | |
setTouchAction: function (node, value) { | |
if (HAS_NATIVE_TA) { | |
node.style.touchAction = value; | |
} | |
node[TOUCH_ACTION] = value; | |
}, | |
fire: function (target, type, detail) { | |
var ev = Polymer.Base.fire(type, detail, { | |
node: target, | |
bubbles: true, | |
cancelable: true | |
}); | |
if (ev.defaultPrevented) { | |
var se = detail.sourceEvent; | |
if (se && se.preventDefault) { | |
se.preventDefault(); | |
} | |
} | |
}, | |
prevent: function (evName) { | |
var recognizer = this.findRecognizerByEvent(evName); | |
if (recognizer.info) { | |
recognizer.info.prevent = true; | |
} | |
} | |
}; | |
Gestures.register({ | |
name: 'downup', | |
deps: [ | |
'mousedown', | |
'touchstart', | |
'touchend' | |
], | |
flow: { | |
start: [ | |
'mousedown', | |
'touchstart' | |
], | |
end: [ | |
'mouseup', | |
'touchend' | |
] | |
}, | |
emits: [ | |
'down', | |
'up' | |
], | |
info: { | |
movefn: function () { | |
}, | |
upfn: function () { | |
} | |
}, | |
reset: function () { | |
untrackDocument(this.info); | |
}, | |
mousedown: function (e) { | |
if (!hasLeftMouseButton(e)) { | |
return; | |
} | |
var t = Gestures.findOriginalTarget(e); | |
var self = this; | |
var movefn = function movefn(e) { | |
if (!hasLeftMouseButton(e)) { | |
self.fire('up', t, e); | |
untrackDocument(self.info); | |
} | |
}; | |
var upfn = function upfn(e) { | |
if (hasLeftMouseButton(e)) { | |
self.fire('up', t, e); | |
} | |
untrackDocument(self.info); | |
}; | |
trackDocument(this.info, movefn, upfn); | |
this.fire('down', t, e); | |
}, | |
touchstart: function (e) { | |
this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0]); | |
}, | |
touchend: function (e) { | |
this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0]); | |
}, | |
fire: function (type, target, event) { | |
var self = this; | |
Gestures.fire(target, type, { | |
x: event.clientX, | |
y: event.clientY, | |
sourceEvent: event, | |
prevent: function (e) { | |
return Gestures.prevent(e); | |
} | |
}); | |
} | |
}); | |
Gestures.register({ | |
name: 'track', | |
touchAction: 'none', | |
deps: [ | |
'mousedown', | |
'touchstart', | |
'touchmove', | |
'touchend' | |
], | |
flow: { | |
start: [ | |
'mousedown', | |
'touchstart' | |
], | |
end: [ | |
'mouseup', | |
'touchend' | |
] | |
}, | |
emits: ['track'], | |
info: { | |
x: 0, | |
y: 0, | |
state: 'start', | |
started: false, | |
moves: [], | |
addMove: function (move) { | |
if (this.moves.length > TRACK_LENGTH) { | |
this.moves.shift(); | |
} | |
this.moves.push(move); | |
}, | |
movefn: function () { | |
}, | |
upfn: function () { | |
}, | |
prevent: false | |
}, | |
reset: function () { | |
this.info.state = 'start'; | |
this.info.started = false; | |
this.info.moves = []; | |
this.info.x = 0; | |
this.info.y = 0; | |
this.info.prevent = false; | |
untrackDocument(this.info); | |
}, | |
hasMovedEnough: function (x, y) { | |
if (this.info.prevent) { | |
return false; | |
} | |
if (this.info.started) { | |
return true; | |
} | |
var dx = Math.abs(this.info.x - x); | |
var dy = Math.abs(this.info.y - y); | |
return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE; | |
}, | |
mousedown: function (e) { | |
if (!hasLeftMouseButton(e)) { | |
return; | |
} | |
var t = Gestures.findOriginalTarget(e); | |
var self = this; | |
var movefn = function movefn(e) { | |
var x = e.clientX, y = e.clientY; | |
if (self.hasMovedEnough(x, y)) { | |
self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : 'start'; | |
self.info.addMove({ | |
x: x, | |
y: y | |
}); | |
if (!hasLeftMouseButton(e)) { | |
self.info.state = 'end'; | |
untrackDocument(self.info); | |
} | |
self.fire(t, e); | |
self.info.started = true; | |
} | |
}; | |
var upfn = function upfn(e) { | |
if (self.info.started) { | |
Gestures.prevent('tap'); | |
movefn(e); | |
} | |
untrackDocument(self.info); | |
}; | |
trackDocument(this.info, movefn, upfn); | |
this.info.x = e.clientX; | |
this.info.y = e.clientY; | |
}, | |
touchstart: function (e) { | |
var ct = e.changedTouches[0]; | |
this.info.x = ct.clientX; | |
this.info.y = ct.clientY; | |
}, | |
touchmove: function (e) { | |
var t = Gestures.findOriginalTarget(e); | |
var ct = e.changedTouches[0]; | |
var x = ct.clientX, y = ct.clientY; | |
if (this.hasMovedEnough(x, y)) { | |
this.info.addMove({ | |
x: x, | |
y: y | |
}); | |
this.fire(t, ct); | |
this.info.state = 'track'; | |
this.info.started = true; | |
} | |
}, | |
touchend: function (e) { | |
var t = Gestures.findOriginalTarget(e); | |
var ct = e.changedTouches[0]; | |
if (this.info.started) { | |
Gestures.prevent('tap'); | |
this.info.state = 'end'; | |
this.info.addMove({ | |
x: ct.clientX, | |
y: ct.clientY | |
}); | |
this.fire(t, ct); | |
} | |
}, | |
fire: function (target, touch) { | |
var secondlast = this.info.moves[this.info.moves.length - 2]; | |
var lastmove = this.info.moves[this.info.moves.length - 1]; | |
var dx = lastmove.x - this.info.x; | |
var dy = lastmove.y - this.info.y; | |
var ddx, ddy = 0; | |
if (secondlast) { | |
ddx = lastmove.x - secondlast.x; | |
ddy = lastmove.y - secondlast.y; | |
} | |
return Gestures.fire(target, 'track', { | |
state: this.info.state, | |
x: touch.clientX, | |
y: touch.clientY, | |
dx: dx, | |
dy: dy, | |
ddx: ddx, | |
ddy: ddy, | |
sourceEvent: touch, | |
hover: function () { | |
return Gestures.deepTargetFind(touch.clientX, touch.clientY); | |
} | |
}); | |
} | |
}); | |
Gestures.register({ | |
name: 'tap', | |
deps: [ | |
'mousedown', | |
'click', | |
'touchstart', | |
'touchend' | |
], | |
flow: { | |
start: [ | |
'mousedown', | |
'touchstart' | |
], | |
end: [ | |
'click', | |
'touchend' | |
] | |
}, | |
emits: ['tap'], | |
info: { | |
x: NaN, | |
y: NaN, | |
prevent: false | |
}, | |
reset: function () { | |
this.info.x = NaN; | |
this.info.y = NaN; | |
this.info.prevent = false; | |
}, | |
save: function (e) { | |
this.info.x = e.clientX; | |
this.info.y = e.clientY; | |
}, | |
mousedown: function (e) { | |
if (hasLeftMouseButton(e)) { | |
this.save(e); | |
} | |
}, | |
click: function (e) { | |
if (hasLeftMouseButton(e)) { | |
this.forward(e); | |
} | |
}, | |
touchstart: function (e) { | |
this.save(e.changedTouches[0]); | |
}, | |
touchend: function (e) { | |
this.forward(e.changedTouches[0]); | |
}, | |
forward: function (e) { | |
var dx = Math.abs(e.clientX - this.info.x); | |
var dy = Math.abs(e.clientY - this.info.y); | |
var t = Gestures.findOriginalTarget(e); | |
if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE || isSyntheticClick(e)) { | |
if (!this.info.prevent) { | |
Gestures.fire(t, 'tap', { | |
x: e.clientX, | |
y: e.clientY, | |
sourceEvent: e | |
}); | |
} | |
} | |
} | |
}); | |
var DIRECTION_MAP = { | |
x: 'pan-x', | |
y: 'pan-y', | |
none: 'none', | |
all: 'auto' | |
}; | |
Polymer.Base._addFeature({ | |
_listen: function (node, eventName, handler) { | |
if (Gestures.gestures[eventName]) { | |
Gestures.add(node, eventName, handler); | |
} else { | |
node.addEventListener(eventName, handler); | |
} | |
}, | |
_unlisten: function (node, eventName, handler) { | |
if (Gestures.gestures[eventName]) { | |
Gestures.remove(node, eventName, handler); | |
} else { | |
node.removeEventListener(eventName, handler); | |
} | |
}, | |
setScrollDirection: function (direction, node) { | |
node = node || this; | |
Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto'); | |
} | |
}); | |
Polymer.Gestures = Gestures; | |
}()); | |
Polymer.Async = { | |
_currVal: 0, | |
_lastVal: 0, | |
_callbacks: [], | |
_twiddleContent: 0, | |
_twiddle: document.createTextNode(''), | |
run: function (callback, waitTime) { | |
if (waitTime > 0) { | |
return ~setTimeout(callback, waitTime); | |
} else { | |
this._twiddle.textContent = this._twiddleContent++; | |
this._callbacks.push(callback); | |
return this._currVal++; | |
} | |
}, | |
cancel: function (handle) { | |
if (handle < 0) { | |
clearTimeout(~handle); | |
} else { | |
var idx = handle - this._lastVal; | |
if (idx >= 0) { | |
if (!this._callbacks[idx]) { | |
throw 'invalid async handle: ' + handle; | |
} | |
this._callbacks[idx] = null; | |
} | |
} | |
}, | |
_atEndOfMicrotask: function () { | |
var len = this._callbacks.length; | |
for (var i = 0; i < len; i++) { | |
var cb = this._callbacks[i]; | |
if (cb) { | |
try { | |
cb(); | |
} catch (e) { | |
i++; | |
this._callbacks.splice(0, i); | |
this._lastVal += i; | |
this._twiddle.textContent = this._twiddleContent++; | |
throw e; | |
} | |
} | |
} | |
this._callbacks.splice(0, len); | |
this._lastVal += len; | |
} | |
}; | |
new window.MutationObserver(function () { | |
Polymer.Async._atEndOfMicrotask(); | |
}).observe(Polymer.Async._twiddle, { characterData: true }); | |
Polymer.Debounce = function () { | |
var Async = Polymer.Async; | |
var Debouncer = function (context) { | |
this.context = context; | |
var self = this; | |
this.boundComplete = function () { | |
self.complete(); | |
}; | |
}; | |
Debouncer.prototype = { | |
go: function (callback, wait) { | |
var h; | |
this.finish = function () { | |
Async.cancel(h); | |
}; | |
h = Async.run(this.boundComplete, wait); | |
this.callback = callback; | |
}, | |
stop: function () { | |
if (this.finish) { | |
this.finish(); | |
this.finish = null; | |
} | |
}, | |
complete: function () { | |
if (this.finish) { | |
this.stop(); | |
this.callback.call(this.context); | |
} | |
} | |
}; | |
function debounce(debouncer, callback, wait) { | |
if (debouncer) { | |
debouncer.stop(); | |
} else { | |
debouncer = new Debouncer(this); | |
} | |
debouncer.go(callback, wait); | |
return debouncer; | |
} | |
return debounce; | |
}(); | |
Polymer.Base._addFeature({ | |
$$: function (slctr) { | |
return Polymer.dom(this.root).querySelector(slctr); | |
}, | |
toggleClass: function (name, bool, node) { | |
node = node || this; | |
if (arguments.length == 1) { | |
bool = !node.classList.contains(name); | |
} | |
if (bool) { | |
Polymer.dom(node).classList.add(name); | |
} else { | |
Polymer.dom(node).classList.remove(name); | |
} | |
}, | |
toggleAttribute: function (name, bool, node) { | |
node = node || this; | |
if (arguments.length == 1) { | |
bool = !node.hasAttribute(name); | |
} | |
if (bool) { | |
Polymer.dom(node).setAttribute(name, ''); | |
} else { | |
Polymer.dom(node).removeAttribute(name); | |
} | |
}, | |
classFollows: function (name, toElement, fromElement) { | |
if (fromElement) { | |
Polymer.dom(fromElement).classList.remove(name); | |
} | |
if (toElement) { | |
Polymer.dom(toElement).classList.add(name); | |
} | |
}, | |
attributeFollows: function (name, toElement, fromElement) { | |
if (fromElement) { | |
Polymer.dom(fromElement).removeAttribute(name); | |
} | |
if (toElement) { | |
Polymer.dom(toElement).setAttribute(name, ''); | |
} | |
}, | |
getEffectiveChildNodes: function () { | |
return Polymer.dom(this).getEffectiveChildNodes(); | |
}, | |
getEffectiveChildren: function () { | |
var list = Polymer.dom(this).getEffectiveChildNodes(); | |
return list.filter(function (n) { | |
return n.nodeType === Node.ELEMENT_NODE; | |
}); | |
}, | |
getEffectiveTextContent: function () { | |
var cn = this.getEffectiveChildNodes(); | |
var tc = []; | |
for (var i = 0, c; c = cn[i]; i++) { | |
if (c.nodeType !== Node.COMMENT_NODE) { | |
tc.push(Polymer.dom(c).textContent); | |
} | |
} | |
return tc.join(''); | |
}, | |
queryEffectiveChildren: function (slctr) { | |
var e$ = Polymer.dom(this).queryDistributedElements(slctr); | |
return e$ && e$[0]; | |
}, | |
queryAllEffectiveChildren: function (slctr) { | |
return Polymer.dom(this).queryDistributedElements(slctr); | |
}, | |
getContentChildNodes: function (slctr) { | |
var content = Polymer.dom(this.root).querySelector(slctr || 'content'); | |
return content ? Polymer.dom(content).getDistributedNodes() : []; | |
}, | |
getContentChildren: function (slctr) { | |
return this.getContentChildNodes(slctr).filter(function (n) { | |
return n.nodeType === Node.ELEMENT_NODE; | |
}); | |
}, | |
fire: function (type, detail, options) { | |
options = options || Polymer.nob; | |
var node = options.node || this; | |
var detail = detail === null || detail === undefined ? {} : detail; | |
var bubbles = options.bubbles === undefined ? true : options.bubbles; | |
var cancelable = Boolean(options.cancelable); | |
var useCache = options._useCache; | |
var event = this._getEvent(type, bubbles, cancelable, useCache); | |
event.detail = detail; | |
if (useCache) { | |
this.__eventCache[type] = null; | |
} | |
node.dispatchEvent(event); | |
if (useCache) { | |
this.__eventCache[type] = event; | |
} | |
return event; | |
}, | |
__eventCache: {}, | |
_getEvent: function (type, bubbles, cancelable, useCache) { | |
var event = useCache && this.__eventCache[type]; | |
if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) { | |
event = new Event(type, { | |
bubbles: Boolean(bubbles), | |
cancelable: cancelable | |
}); | |
} | |
return event; | |
}, | |
async: function (callback, waitTime) { | |
var self = this; | |
return Polymer.Async.run(function () { | |
callback.call(self); | |
}, waitTime); | |
}, | |
cancelAsync: function (handle) { | |
Polymer.Async.cancel(handle); | |
}, | |
arrayDelete: function (path, item) { | |
var index; | |
if (Array.isArray(path)) { | |
index = path.indexOf(item); | |
if (index >= 0) { | |
return path.splice(index, 1); | |
} | |
} else { | |
var arr = this._get(path); | |
index = arr.indexOf(item); | |
if (index >= 0) { | |
return this.splice(path, index, 1); | |
} | |
} | |
}, | |
transform: function (transform, node) { | |
node = node || this; | |
node.style.webkitTransform = transform; | |
node.style.transform = transform; | |
}, | |
translate3d: function (x, y, z, node) { | |
node = node || this; | |
this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node); | |
}, | |
importHref: function (href, onload, onerror) { | |
var l = document.createElement('link'); | |
l.rel = 'import'; | |
l.href = href; | |
var self = this; | |
if (onload) { | |
l.onload = function (e) { | |
return onload.call(self, e); | |
}; | |
} | |
if (onerror) { | |
l.onerror = function (e) { | |
return onerror.call(self, e); | |
}; | |
} | |
document.head.appendChild(l); | |
return l; | |
}, | |
create: function (tag, props) { | |
var elt = document.createElement(tag); | |
if (props) { | |
for (var n in props) { | |
elt[n] = props[n]; | |
} | |
} | |
return elt; | |
}, | |
isLightDescendant: function (node) { | |
return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot(); | |
}, | |
isLocalDescendant: function (node) { | |
return this.root === Polymer.dom(node).getOwnerRoot(); | |
} | |
}); | |
Polymer.Bind = { | |
_dataEventCache: {}, | |
prepareModel: function (model) { | |
Polymer.Base.mixin(model, this._modelApi); | |
}, | |
_modelApi: { | |
_notifyChange: function (source, event, value) { | |
value = value === undefined ? this[source] : value; | |
event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed'; | |
this.fire(event, { value: value }, { | |
bubbles: false, | |
cancelable: false, | |
_useCache: true | |
}); | |
}, | |
_propertySetter: function (property, value, effects, fromAbove) { | |
var old = this.__data__[property]; | |
if (old !== value && (old === old || value === value)) { | |
this.__data__[property] = value; | |
if (typeof value == 'object') { | |
this._clearPath(property); | |
} | |
if (this._propertyChanged) { | |
this._propertyChanged(property, value, old); | |
} | |
if (effects) { | |
this._effectEffects(property, value, effects, old, fromAbove); | |
} | |
} | |
return old; | |
}, | |
__setProperty: function (property, value, quiet, node) { | |
node = node || this; | |
var effects = node._propertyEffects && node._propertyEffects[property]; | |
if (effects) { | |
node._propertySetter(property, value, effects, quiet); | |
} else { | |
node[property] = value; | |
} | |
}, | |
_effectEffects: function (property, value, effects, old, fromAbove) { | |
for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) { | |
fx.fn.call(this, property, value, fx.effect, old, fromAbove); | |
} | |
}, | |
_clearPath: function (path) { | |
for (var prop in this.__data__) { | |
if (prop.indexOf(path + '.') === 0) { | |
this.__data__[prop] = undefined; | |
} | |
} | |
} | |
}, | |
ensurePropertyEffects: function (model, property) { | |
if (!model._propertyEffects) { | |
model._propertyEffects = {}; | |
} | |
var fx = model._propertyEffects[property]; | |
if (!fx) { | |
fx = model._propertyEffects[property] = []; | |
} | |
return fx; | |
}, | |
addPropertyEffect: function (model, property, kind, effect) { | |
var fx = this.ensurePropertyEffects(model, property); | |
var propEffect = { | |
kind: kind, | |
effect: effect, | |
fn: Polymer.Bind['_' + kind + 'Effect'] | |
}; | |
fx.push(propEffect); | |
return propEffect; | |
}, | |
createBindings: function (model) { | |
var fx$ = model._propertyEffects; | |
if (fx$) { | |
for (var n in fx$) { | |
var fx = fx$[n]; | |
fx.sort(this._sortPropertyEffects); | |
this._createAccessors(model, n, fx); | |
} | |
} | |
}, | |
_sortPropertyEffects: function () { | |
var EFFECT_ORDER = { | |
'compute': 0, | |
'annotation': 1, | |
'computedAnnotation': 2, | |
'reflect': 3, | |
'notify': 4, | |
'observer': 5, | |
'complexObserver': 6, | |
'function': 7 | |
}; | |
return function (a, b) { | |
return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind]; | |
}; | |
}(), | |
_createAccessors: function (model, property, effects) { | |
var defun = { | |
get: function () { | |
return this.__data__[property]; | |
} | |
}; | |
var setter = function (value) { | |
this._propertySetter(property, value, effects); | |
}; | |
var info = model.getPropertyInfo && model.getPropertyInfo(property); | |
if (info && info.readOnly) { | |
if (!info.computed) { | |
model['_set' + this.upper(property)] = setter; | |
} | |
} else { | |
defun.set = setter; | |
} | |
Object.defineProperty(model, property, defun); | |
}, | |
upper: function (name) { | |
return name[0].toUpperCase() + name.substring(1); | |
}, | |
_addAnnotatedListener: function (model, index, property, path, event) { | |
if (!model._bindListeners) { | |
model._bindListeners = []; | |
} | |
var fn = this._notedListenerFactory(property, path, this._isStructured(path)); | |
var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed'; | |
model._bindListeners.push({ | |
index: index, | |
property: property, | |
path: path, | |
changedFn: fn, | |
event: eventName | |
}); | |
}, | |
_isStructured: function (path) { | |
return path.indexOf('.') > 0; | |
}, | |
_isEventBogus: function (e, target) { | |
return e.path && e.path[0] !== target; | |
}, | |
_notedListenerFactory: function (property, path, isStructured) { | |
return function (target, value, targetPath) { | |
if (targetPath) { | |
this._notifyPath(this._fixPath(path, property, targetPath), value); | |
} else { | |
value = target[property]; | |
if (!isStructured) { | |
this[path] = value; | |
} else { | |
if (this.__data__[path] != value) { | |
this.set(path, value); | |
} | |
} | |
} | |
}; | |
}, | |
prepareInstance: function (inst) { | |
inst.__data__ = Object.create(null); | |
}, | |
setupBindListeners: function (inst) { | |
var b$ = inst._bindListeners; | |
for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) { | |
var node = inst._nodes[info.index]; | |
this._addNotifyListener(node, inst, info.event, info.changedFn); | |
} | |
; | |
}, | |
_addNotifyListener: function (element, context, event, changedFn) { | |
element.addEventListener(event, function (e) { | |
return context._notifyListener(changedFn, e); | |
}); | |
} | |
}; | |
Polymer.Base.extend(Polymer.Bind, { | |
_shouldAddListener: function (effect) { | |
return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{' && !effect.parts[0].negate; | |
}, | |
_annotationEffect: function (source, value, effect) { | |
if (source != effect.value) { | |
value = this._get(effect.value); | |
this.__data__[effect.value] = value; | |
} | |
var calc = effect.negate ? !value : value; | |
if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) { | |
return this._applyEffectValue(effect, calc); | |
} | |
}, | |
_reflectEffect: function (source, value, effect) { | |
this.reflectPropertyToAttribute(source, effect.attribute, value); | |
}, | |
_notifyEffect: function (source, value, effect, old, fromAbove) { | |
if (!fromAbove) { | |
this._notifyChange(source, effect.event, value); | |
} | |
}, | |
_functionEffect: function (source, value, fn, old, fromAbove) { | |
fn.call(this, source, value, old, fromAbove); | |
}, | |
_observerEffect: function (source, value, effect, old) { | |
var fn = this[effect.method]; | |
if (fn) { | |
fn.call(this, value, old); | |
} else { | |
this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + '` not defined')); | |
} | |
}, | |
_complexObserverEffect: function (source, value, effect) { | |
var fn = this[effect.method]; | |
if (fn) { | |
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); | |
if (args) { | |
fn.apply(this, args); | |
} | |
} else { | |
this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.method + '` not defined')); | |
} | |
}, | |
_computeEffect: function (source, value, effect) { | |
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); | |
if (args) { | |
var fn = this[effect.method]; | |
if (fn) { | |
this.__setProperty(effect.name, fn.apply(this, args)); | |
} else { | |
this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined')); | |
} | |
} | |
}, | |
_annotatedComputationEffect: function (source, value, effect) { | |
var computedHost = this._rootDataHost || this; | |
var fn = computedHost[effect.method]; | |
if (fn) { | |
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); | |
if (args) { | |
var computedvalue = fn.apply(computedHost, args); | |
if (effect.negate) { | |
computedvalue = !computedvalue; | |
} | |
this._applyEffectValue(effect, computedvalue); | |
} | |
} else { | |
computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined')); | |
} | |
}, | |
_marshalArgs: function (model, effect, path, value) { | |
var values = []; | |
var args = effect.args; | |
for (var i = 0, l = args.length; i < l; i++) { | |
var arg = args[i]; | |
var name = arg.name; | |
var v; | |
if (arg.literal) { | |
v = arg.value; | |
} else if (arg.structured) { | |
v = Polymer.Base._get(name, model); | |
} else { | |
v = model[name]; | |
} | |
if (args.length > 1 && v === undefined) { | |
return; | |
} | |
if (arg.wildcard) { | |
var baseChanged = name.indexOf(path + '.') === 0; | |
var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged; | |
values[i] = { | |
path: matches ? path : name, | |
value: matches ? value : v, | |
base: v | |
}; | |
} else { | |
values[i] = v; | |
} | |
} | |
return values; | |
} | |
}); | |
Polymer.Base._addFeature({ | |
_addPropertyEffect: function (property, kind, effect) { | |
var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect); | |
prop.pathFn = this['_' + prop.kind + 'PathEffect']; | |
}, | |
_prepEffects: function () { | |
Polymer.Bind.prepareModel(this); | |
this._addAnnotationEffects(this._notes); | |
}, | |
_prepBindings: function () { | |
Polymer.Bind.createBindings(this); | |
}, | |
_addPropertyEffects: function (properties) { | |
if (properties) { | |
for (var p in properties) { | |
var prop = properties[p]; | |
if (prop.observer) { | |
this._addObserverEffect(p, prop.observer); | |
} | |
if (prop.computed) { | |
prop.readOnly = true; | |
this._addComputedEffect(p, prop.computed); | |
} | |
if (prop.notify) { | |
this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' }); | |
} | |
if (prop.reflectToAttribute) { | |
this._addPropertyEffect(p, 'reflect', { attribute: Polymer.CaseMap.camelToDashCase(p) }); | |
} | |
if (prop.readOnly) { | |
Polymer.Bind.ensurePropertyEffects(this, p); | |
} | |
} | |
} | |
}, | |
_addComputedEffect: function (name, expression) { | |
var sig = this._parseMethod(expression); | |
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { | |
this._addPropertyEffect(arg.model, 'compute', { | |
method: sig.method, | |
args: sig.args, | |
trigger: arg, | |
name: name | |
}); | |
} | |
}, | |
_addObserverEffect: function (property, observer) { | |
this._addPropertyEffect(property, 'observer', { | |
method: observer, | |
property: property | |
}); | |
}, | |
_addComplexObserverEffects: function (observers) { | |
if (observers) { | |
for (var i = 0, o; i < observers.length && (o = observers[i]); i++) { | |
this._addComplexObserverEffect(o); | |
} | |
} | |
}, | |
_addComplexObserverEffect: function (observer) { | |
var sig = this._parseMethod(observer); | |
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { | |
this._addPropertyEffect(arg.model, 'complexObserver', { | |
method: sig.method, | |
args: sig.args, | |
trigger: arg | |
}); | |
} | |
}, | |
_addAnnotationEffects: function (notes) { | |
for (var i = 0, note; i < notes.length && (note = notes[i]); i++) { | |
var b$ = note.bindings; | |
for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) { | |
this._addAnnotationEffect(binding, i); | |
} | |
} | |
}, | |
_addAnnotationEffect: function (note, index) { | |
if (Polymer.Bind._shouldAddListener(note)) { | |
Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event); | |
} | |
for (var i = 0; i < note.parts.length; i++) { | |
var part = note.parts[i]; | |
if (part.signature) { | |
this._addAnnotatedComputationEffect(note, part, index); | |
} else if (!part.literal) { | |
this._addPropertyEffect(part.model, 'annotation', { | |
kind: note.kind, | |
index: index, | |
name: note.name, | |
value: part.value, | |
isCompound: note.isCompound, | |
compoundIndex: part.compoundIndex, | |
event: part.event, | |
customEvent: part.customEvent, | |
negate: part.negate | |
}); | |
} | |
} | |
}, | |
_addAnnotatedComputationEffect: function (note, part, index) { | |
var sig = part.signature; | |
if (sig.static) { | |
this.__addAnnotatedComputationEffect('__static__', index, note, part, null); | |
} else { | |
for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { | |
if (!arg.literal) { | |
this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg); | |
} | |
} | |
} | |
}, | |
__addAnnotatedComputationEffect: function (property, index, note, part, trigger) { | |
this._addPropertyEffect(property, 'annotatedComputation', { | |
index: index, | |
isCompound: note.isCompound, | |
compoundIndex: part.compoundIndex, | |
kind: note.kind, | |
name: note.name, | |
negate: part.negate, | |
method: part.signature.method, | |
args: part.signature.args, | |
trigger: trigger | |
}); | |
}, | |
_parseMethod: function (expression) { | |
var m = expression.match(/([^\s]+)\((.*)\)/); | |
if (m) { | |
var sig = { | |
method: m[1], | |
static: true | |
}; | |
if (m[2].trim()) { | |
var args = m[2].replace(/\\,/g, ',').split(','); | |
return this._parseArgs(args, sig); | |
} else { | |
sig.args = Polymer.nar; | |
return sig; | |
} | |
} | |
}, | |
_parseArgs: function (argList, sig) { | |
sig.args = argList.map(function (rawArg) { | |
var arg = this._parseArg(rawArg); | |
if (!arg.literal) { | |
sig.static = false; | |
} | |
return arg; | |
}, this); | |
return sig; | |
}, | |
_parseArg: function (rawArg) { | |
var arg = rawArg.trim().replace(/,/g, ',').replace(/\\(.)/g, '$1'); | |
var a = { | |
name: arg, | |
model: this._modelForPath(arg) | |
}; | |
var fc = arg[0]; | |
if (fc === '-') { | |
fc = arg[1]; | |
} | |
if (fc >= '0' && fc <= '9') { | |
fc = '#'; | |
} | |
switch (fc) { | |
case '\'': | |
case '"': | |
a.value = arg.slice(1, -1); | |
a.literal = true; | |
break; | |
case '#': | |
a.value = Number(arg); | |
a.literal = true; | |
break; | |
} | |
if (!a.literal) { | |
a.structured = arg.indexOf('.') > 0; | |
if (a.structured) { | |
a.wildcard = arg.slice(-2) == '.*'; | |
if (a.wildcard) { | |
a.name = arg.slice(0, -2); | |
} | |
} | |
} | |
return a; | |
}, | |
_marshalInstanceEffects: function () { | |
Polymer.Bind.prepareInstance(this); | |
if (this._bindListeners) { | |
Polymer.Bind.setupBindListeners(this); | |
} | |
}, | |
_applyEffectValue: function (info, value) { | |
var node = this._nodes[info.index]; | |
var property = info.name; | |
if (info.isCompound) { | |
var storage = node.__compoundStorage__[property]; | |
storage[info.compoundIndex] = value; | |
value = storage.join(''); | |
} | |
if (info.kind == 'attribute') { | |
this.serializeValueToAttribute(value, property, node); | |
} else { | |
if (property === 'className') { | |
value = this._scopeElementClass(node, value); | |
} | |
if (property === 'textContent' || node.localName == 'input' && property == 'value') { | |
value = value == undefined ? '' : value; | |
} | |
var pinfo; | |
if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.readOnly) { | |
this.__setProperty(property, value, true, node); | |
} | |
} | |
}, | |
_executeStaticEffects: function () { | |
if (this._propertyEffects && this._propertyEffects.__static__) { | |
this._effectEffects('__static__', null, this._propertyEffects.__static__); | |
} | |
} | |
}); | |
Polymer.Base._addFeature({ | |
_setupConfigure: function (initialConfig) { | |
this._config = {}; | |
this._handlers = []; | |
if (initialConfig) { | |
for (var i in initialConfig) { | |
if (initialConfig[i] !== undefined) { | |
this._config[i] = initialConfig[i]; | |
} | |
} | |
} | |
}, | |
_marshalAttributes: function () { | |
this._takeAttributesToModel(this._config); | |
}, | |
_attributeChangedImpl: function (name) { | |
var model = this._clientsReadied ? this : this._config; | |
this._setAttributeToProperty(model, name); | |
}, | |
_configValue: function (name, value) { | |
var info = this._propertyInfo[name]; | |
if (!info || !info.readOnly) { | |
this._config[name] = value; | |
} | |
}, | |
_beforeClientsReady: function () { | |
this._configure(); | |
}, | |
_configure: function () { | |
this._configureAnnotationReferences(); | |
this._aboveConfig = this.mixin({}, this._config); | |
var config = {}; | |
for (var i = 0; i < this.behaviors.length; i++) { | |
this._configureProperties(this.behaviors[i].properties, config); | |
} | |
this._configureProperties(this.properties, config); | |
this.mixin(config, this._aboveConfig); | |
this._config = config; | |
if (this._clients && this._clients.length) { | |
this._distributeConfig(this._config); | |
} | |
}, | |
_configureProperties: function (properties, config) { | |
for (var i in properties) { | |
var c = properties[i]; | |
if (c.value !== undefined) { | |
var value = c.value; | |
if (typeof value == 'function') { | |
value = value.call(this, this._config); | |
} | |
config[i] = value; | |
} | |
} | |
}, | |
_distributeConfig: function (config) { | |
var fx$ = this._propertyEffects; | |
if (fx$) { | |
for (var p in config) { | |
var fx = fx$[p]; | |
if (fx) { | |
for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) { | |
if (x.kind === 'annotation' && !x.isCompound) { | |
var node = this._nodes[x.effect.index]; | |
if (node._configValue) { | |
var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config); | |
node._configValue(x.effect.name, value); | |
} | |
} | |
} | |
} | |
} | |
} | |
}, | |
_afterClientsReady: function () { | |
this._executeStaticEffects(); | |
this._applyConfig(this._config, this._aboveConfig); | |
this._flushHandlers(); | |
}, | |
_applyConfig: function (config, aboveConfig) { | |
for (var n in config) { | |
if (this[n] === undefined) { | |
this.__setProperty(n, config[n], n in aboveConfig); | |
} | |
} | |
}, | |
_notifyListener: function (fn, e) { | |
if (!Polymer.Bind._isEventBogus(e, e.target)) { | |
var value, path; | |
if (e.detail) { | |
value = e.detail.value; | |
path = e.detail.path; | |
} | |
if (!this._clientsReadied) { | |
this._queueHandler([ | |
fn, | |
e.target, | |
value, | |
path | |
]); | |
} else { | |
return fn.call(this, e.target, value, path); | |
} | |
} | |
}, | |
_queueHandler: function (args) { | |
this._handlers.push(args); | |
}, | |
_flushHandlers: function () { | |
var h$ = this._handlers; | |
for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) { | |
h[0].call(this, h[1], h[2], h[3]); | |
} | |
this._handlers = []; | |
} | |
}); | |
(function () { | |
'use strict'; | |
Polymer.Base._addFeature({ | |
notifyPath: function (path, value, fromAbove) { | |
var info = {}; | |
this._get(path, this, info); | |
this._notifyPath(info.path, value, fromAbove); | |
}, | |
_notifyPath: function (path, value, fromAbove) { | |
var old = this._propertySetter(path, value); | |
if (old !== value && (old === old || value === value)) { | |
this._pathEffector(path, value); | |
if (!fromAbove) { | |
this._notifyPathUp(path, value); | |
} | |
return true; | |
} | |
}, | |
_getPathParts: function (path) { | |
if (Array.isArray(path)) { | |
var parts = []; | |
for (var i = 0; i < path.length; i++) { | |
var args = path[i].toString().split('.'); | |
for (var j = 0; j < args.length; j++) { | |
parts.push(args[j]); | |
} | |
} | |
return parts; | |
} else { | |
return path.toString().split('.'); | |
} | |
}, | |
set: function (path, value, root) { | |
var prop = root || this; | |
var parts = this._getPathParts(path); | |
var array; | |
var last = parts[parts.length - 1]; | |
if (parts.length > 1) { | |
for (var i = 0; i < parts.length - 1; i++) { | |
var part = parts[i]; | |
if (array && part[0] == '#') { | |
prop = Polymer.Collection.get(array).getItem(part); | |
} else { | |
prop = prop[part]; | |
if (array && parseInt(part, 10) == part) { | |
parts[i] = Polymer.Collection.get(array).getKey(prop); | |
} | |
} | |
if (!prop) { | |
return; | |
} | |
array = Array.isArray(prop) ? prop : null; | |
} | |
if (array) { | |
var coll = Polymer.Collection.get(array); | |
if (last[0] == '#') { | |
var key = last; | |
var old = coll.getItem(key); | |
last = array.indexOf(old); | |
coll.setItem(key, value); | |
} else if (parseInt(last, 10) == last) { | |
var old = prop[last]; | |
var key = coll.getKey(old); | |
parts[i] = key; | |
coll.setItem(key, value); | |
} | |
} | |
prop[last] = value; | |
if (!root) { | |
this._notifyPath(parts.join('.'), value); | |
} | |
} else { | |
prop[path] = value; | |
} | |
}, | |
get: function (path, root) { | |
return this._get(path, root); | |
}, | |
_get: function (path, root, info) { | |
var prop = root || this; | |
var parts = this._getPathParts(path); | |
var array; | |
for (var i = 0; i < parts.length; i++) { | |
if (!prop) { | |
return; | |
} | |
var part = parts[i]; | |
if (array && part[0] == '#') { | |
prop = Polymer.Collection.get(array).getItem(part); | |
} else { | |
prop = prop[part]; | |
if (info && array && parseInt(part, 10) == part) { | |
parts[i] = Polymer.Collection.get(array).getKey(prop); | |
} | |
} | |
array = Array.isArray(prop) ? prop : null; | |
} | |
if (info) { | |
info.path = parts.join('.'); | |
} | |
return prop; | |
}, | |
_pathEffector: function (path, value) { | |
var model = this._modelForPath(path); | |
var fx$ = this._propertyEffects && this._propertyEffects[model]; | |
if (fx$) { | |
for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) { | |
var fxFn = fx.pathFn; | |
if (fxFn) { | |
fxFn.call(this, path, value, fx.effect); | |
} | |
} | |
} | |
if (this._boundPaths) { | |
this._notifyBoundPaths(path, value); | |
} | |
}, | |
_annotationPathEffect: function (path, value, effect) { | |
if (effect.value === path || effect.value.indexOf(path + '.') === 0) { | |
Polymer.Bind._annotationEffect.call(this, path, value, effect); | |
} else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) { | |
var node = this._nodes[effect.index]; | |
if (node && node._notifyPath) { | |
var p = this._fixPath(effect.name, effect.value, path); | |
node._notifyPath(p, value, true); | |
} | |
} | |
}, | |
_complexObserverPathEffect: function (path, value, effect) { | |
if (this._pathMatchesEffect(path, effect)) { | |
Polymer.Bind._complexObserverEffect.call(this, path, value, effect); | |
} | |
}, | |
_computePathEffect: function (path, value, effect) { | |
if (this._pathMatchesEffect(path, effect)) { | |
Polymer.Bind._computeEffect.call(this, path, value, effect); | |
} | |
}, | |
_annotatedComputationPathEffect: function (path, value, effect) { | |
if (this._pathMatchesEffect(path, effect)) { | |
Polymer.Bind._annotatedComputationEffect.call(this, path, value, effect); | |
} | |
}, | |
_pathMatchesEffect: function (path, effect) { | |
var effectArg = effect.trigger.name; | |
return effectArg == path || effectArg.indexOf(path + '.') === 0 || effect.trigger.wildcard && path.indexOf(effectArg) === 0; | |
}, | |
linkPaths: function (to, from) { | |
this._boundPaths = this._boundPaths || {}; | |
if (from) { | |
this._boundPaths[to] = from; | |
} else { | |
this.unlinkPaths(to); | |
} | |
}, | |
unlinkPaths: function (path) { | |
if (this._boundPaths) { | |
delete this._boundPaths[path]; | |
} | |
}, | |
_notifyBoundPaths: function (path, value) { | |
for (var a in this._boundPaths) { | |
var b = this._boundPaths[a]; | |
if (path.indexOf(a + '.') == 0) { | |
this._notifyPath(this._fixPath(b, a, path), value); | |
} else if (path.indexOf(b + '.') == 0) { | |
this._notifyPath(this._fixPath(a, b, path), value); | |
} | |
} | |
}, | |
_fixPath: function (property, root, path) { | |
return property + path.slice(root.length); | |
}, | |
_notifyPathUp: function (path, value) { | |
var rootName = this._modelForPath(path); | |
var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName); | |
var eventName = dashCaseName + this._EVENT_CHANGED; | |
this.fire(eventName, { | |
path: path, | |
value: value | |
}, { | |
bubbles: false, | |
_useCache: true | |
}); | |
}, | |
_modelForPath: function (path) { | |
var dot = path.indexOf('.'); | |
return dot < 0 ? path : path.slice(0, dot); | |
}, | |
_EVENT_CHANGED: '-changed', | |
notifySplices: function (path, splices) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
this._notifySplices(array, info.path, splices); | |
}, | |
_notifySplices: function (array, path, splices) { | |
var change = { | |
keySplices: Polymer.Collection.applySplices(array, splices), | |
indexSplices: splices | |
}; | |
if (!array.hasOwnProperty('splices')) { | |
Object.defineProperty(array, 'splices', { | |
configurable: true, | |
writable: true | |
}); | |
} | |
array.splices = change; | |
this._notifyPath(path + '.splices', change); | |
this._notifyPath(path + '.length', array.length); | |
change.keySplices = null; | |
change.indexSplices = null; | |
}, | |
_notifySplice: function (array, path, index, added, removed) { | |
this._notifySplices(array, path, [{ | |
index: index, | |
addedCount: added, | |
removed: removed, | |
object: array, | |
type: 'splice' | |
}]); | |
}, | |
push: function (path) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
var args = Array.prototype.slice.call(arguments, 1); | |
var len = array.length; | |
var ret = array.push.apply(array, args); | |
if (args.length) { | |
this._notifySplice(array, info.path, len, args.length, []); | |
} | |
return ret; | |
}, | |
pop: function (path) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
var hadLength = Boolean(array.length); | |
var args = Array.prototype.slice.call(arguments, 1); | |
var ret = array.pop.apply(array, args); | |
if (hadLength) { | |
this._notifySplice(array, info.path, array.length, 0, [ret]); | |
} | |
return ret; | |
}, | |
splice: function (path, start, deleteCount) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
if (start < 0) { | |
start = array.length - Math.floor(-start); | |
} else { | |
start = Math.floor(start); | |
} | |
if (!start) { | |
start = 0; | |
} | |
var args = Array.prototype.slice.call(arguments, 1); | |
var ret = array.splice.apply(array, args); | |
var addedCount = Math.max(args.length - 2, 0); | |
if (addedCount || ret.length) { | |
this._notifySplice(array, info.path, start, addedCount, ret); | |
} | |
return ret; | |
}, | |
shift: function (path) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
var hadLength = Boolean(array.length); | |
var args = Array.prototype.slice.call(arguments, 1); | |
var ret = array.shift.apply(array, args); | |
if (hadLength) { | |
this._notifySplice(array, info.path, 0, 0, [ret]); | |
} | |
return ret; | |
}, | |
unshift: function (path) { | |
var info = {}; | |
var array = this._get(path, this, info); | |
var args = Array.prototype.slice.call(arguments, 1); | |
var ret = array.unshift.apply(array, args); | |
if (args.length) { | |
this._notifySplice(array, info.path, 0, args.length, []); | |
} | |
return ret; | |
}, | |
prepareModelNotifyPath: function (model) { | |
this.mixin(model, { | |
fire: Polymer.Base.fire, | |
_getEvent: Polymer.Base._getEvent, | |
__eventCache: Polymer.Base.__eventCache, | |
notifyPath: Polymer.Base.notifyPath, | |
_get: Polymer.Base._get, | |
_EVENT_CHANGED: Polymer.Base._EVENT_CHANGED, | |
_notifyPath: Polymer.Base._notifyPath, | |
_notifyPathUp: Polymer.Base._notifyPathUp, | |
_pathEffector: Polymer.Base._pathEffector, | |
_annotationPathEffect: Polymer.Base._annotationPathEffect, | |
_complexObserverPathEffect: Polymer.Base._complexObserverPathEffect, | |
_annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect, | |
_computePathEffect: Polymer.Base._computePathEffect, | |
_modelForPath: Polymer.Base._modelForPath, | |
_pathMatchesEffect: Polymer.Base._pathMatchesEffect, | |
_notifyBoundPaths: Polymer.Base._notifyBoundPaths, | |
_getPathParts: Polymer.Base._getPathParts | |
}); | |
} | |
}); | |
}()); | |
Polymer.Base._addFeature({ | |
resolveUrl: function (url) { | |
var module = Polymer.DomModule.import(this.is); | |
var root = ''; | |
if (module) { | |
var assetPath = module.getAttribute('assetpath') || ''; | |
root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI); | |
} | |
return Polymer.ResolveUrl.resolveUrl(url, root); | |
} | |
}); | |
Polymer.CssParse = function () { | |
var api = { | |
parse: function (text) { | |
text = this._clean(text); | |
return this._parseCss(this._lex(text), text); | |
}, | |
_clean: function (cssText) { | |
return cssText.replace(this._rx.comments, '').replace(this._rx.port, ''); | |
}, | |
_lex: function (text) { | |
var root = { | |
start: 0, | |
end: text.length | |
}; | |
var n = root; | |
for (var i = 0, s = 0, l = text.length; i < l; i++) { | |
switch (text[i]) { | |
case this.OPEN_BRACE: | |
if (!n.rules) { | |
n.rules = []; | |
} | |
var p = n; | |
var previous = p.rules[p.rules.length - 1]; | |
n = { | |
start: i + 1, | |
parent: p, | |
previous: previous | |
}; | |
p.rules.push(n); | |
break; | |
case this.CLOSE_BRACE: | |
n.end = i + 1; | |
n = n.parent || root; | |
break; | |
} | |
} | |
return root; | |
}, | |
_parseCss: function (node, text) { | |
var t = text.substring(node.start, node.end - 1); | |
node.parsedCssText = node.cssText = t.trim(); | |
if (node.parent) { | |
var ss = node.previous ? node.previous.end : node.parent.start; | |
t = text.substring(ss, node.start - 1); | |
t = this._expandUnicodeEscapes(t); | |
t = t.replace(this._rx.multipleSpaces, ' '); | |
t = t.substring(t.lastIndexOf(';') + 1); | |
var s = node.parsedSelector = node.selector = t.trim(); | |
node.atRule = s.indexOf(this.AT_START) === 0; | |
if (node.atRule) { | |
if (s.indexOf(this.MEDIA_START) === 0) { | |
node.type = this.types.MEDIA_RULE; | |
} else if (s.match(this._rx.keyframesRule)) { | |
node.type = this.types.KEYFRAMES_RULE; | |
} | |
} else { | |
if (s.indexOf(this.VAR_START) === 0) { | |
node.type = this.types.MIXIN_RULE; | |
} else { | |
node.type = this.types.STYLE_RULE; | |
} | |
} | |
} | |
var r$ = node.rules; | |
if (r$) { | |
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) { | |
this._parseCss(r, text); | |
} | |
} | |
return node; | |
}, | |
_expandUnicodeEscapes: function (s) { | |
return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () { | |
var code = arguments[1], repeat = 6 - code.length; | |
while (repeat--) { | |
code = '0' + code; | |
} | |
return '\\' + code; | |
}); | |
}, | |
stringify: function (node, preserveProperties, text) { | |
text = text || ''; | |
var cssText = ''; | |
if (node.cssText || node.rules) { | |
var r$ = node.rules; | |
if (r$ && (preserveProperties || !this._hasMixinRules(r$))) { | |
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) { | |
cssText = this.stringify(r, preserveProperties, cssText); | |
} | |
} else { | |
cssText = preserveProperties ? node.cssText : this.removeCustomProps(node.cssText); | |
cssText = cssText.trim(); | |
if (cssText) { | |
cssText = ' ' + cssText + '\n'; | |
} | |
} | |
} | |
if (cssText) { | |
if (node.selector) { | |
text += node.selector + ' ' + this.OPEN_BRACE + '\n'; | |
} | |
text += cssText; | |
if (node.selector) { | |
text += this.CLOSE_BRACE + '\n\n'; | |
} | |
} | |
return text; | |
}, | |
_hasMixinRules: function (rules) { | |
return rules[0].selector.indexOf(this.VAR_START) === 0; | |
}, | |
removeCustomProps: function (cssText) { | |
cssText = this.removeCustomPropAssignment(cssText); | |
return this.removeCustomPropApply(cssText); | |
}, | |
removeCustomPropAssignment: function (cssText) { | |
return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, ''); | |
}, | |
removeCustomPropApply: function (cssText) { | |
return cssText.replace(this._rx.mixinApply, '').replace(this._rx.varApply, ''); | |
}, | |
types: { | |
STYLE_RULE: 1, | |
KEYFRAMES_RULE: 7, | |
MEDIA_RULE: 4, | |
MIXIN_RULE: 1000 | |
}, | |
OPEN_BRACE: '{', | |
CLOSE_BRACE: '}', | |
_rx: { | |
comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim, | |
port: /@import[^;]*;/gim, | |
customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim, | |
mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, | |
mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim, | |
varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim, | |
keyframesRule: /^@[^\s]*keyframes/, | |
multipleSpaces: /\s+/g | |
}, | |
VAR_START: '--', | |
MEDIA_START: '@media', | |
AT_START: '@' | |
}; | |
return api; | |
}(); | |
Polymer.StyleUtil = function () { | |
return { | |
MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template', | |
INCLUDE_ATTR: 'include', | |
toCssText: function (rules, callback, preserveProperties) { | |
if (typeof rules === 'string') { | |
rules = this.parser.parse(rules); | |
} | |
if (callback) { | |
this.forEachStyleRule(rules, callback); | |
} | |
return this.parser.stringify(rules, preserveProperties); | |
}, | |
forRulesInStyles: function (styles, callback) { | |
if (styles) { | |
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) { | |
this.forEachStyleRule(this.rulesForStyle(s), callback); | |
} | |
} | |
}, | |
rulesForStyle: function (style) { | |
if (!style.__cssRules && style.textContent) { | |
style.__cssRules = this.parser.parse(style.textContent); | |
} | |
return style.__cssRules; | |
}, | |
clearStyleRules: function (style) { | |
style.__cssRules = null; | |
}, | |
forEachStyleRule: function (node, callback) { | |
if (!node) { | |
return; | |
} | |
var s = node.parsedSelector; | |
var skipRules = false; | |
if (node.type === this.ruleTypes.STYLE_RULE) { | |
callback(node); | |
} else if (node.type === this.ruleTypes.KEYFRAMES_RULE || node.type === this.ruleTypes.MIXIN_RULE) { | |
skipRules = true; | |
} | |
var r$ = node.rules; | |
if (r$ && !skipRules) { | |
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) { | |
this.forEachStyleRule(r, callback); | |
} | |
} | |
}, | |
applyCss: function (cssText, moniker, target, afterNode) { | |
var style = document.createElement('style'); | |
if (moniker) { | |
style.setAttribute('scope', moniker); | |
} | |
style.textContent = cssText; | |
target = target || document.head; | |
if (!afterNode) { | |
var n$ = target.querySelectorAll('style[scope]'); | |
afterNode = n$[n$.length - 1]; | |
} | |
target.insertBefore(style, afterNode && afterNode.nextSibling || target.firstChild); | |
return style; | |
}, | |
cssFromModules: function (moduleIds, warnIfNotFound) { | |
var modules = moduleIds.trim().split(' '); | |
var cssText = ''; | |
for (var i = 0; i < modules.length; i++) { | |
cssText += this.cssFromModule(modules[i], warnIfNotFound); | |
} | |
return cssText; | |
}, | |
cssFromModule: function (moduleId, warnIfNotFound) { | |
var m = Polymer.DomModule.import(moduleId); | |
if (m && !m._cssText) { | |
m._cssText = this.cssFromElement(m); | |
} | |
if (!m && warnIfNotFound) { | |
console.warn('Could not find style data in module named', moduleId); | |
} | |
return m && m._cssText || ''; | |
}, | |
cssFromElement: function (element) { | |
var cssText = ''; | |
var content = element.content || element; | |
var e$ = Polymer.DomApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR)); | |
for (var i = 0, e; i < e$.length; i++) { | |
e = e$[i]; | |
if (e.localName === 'template') { | |
cssText += this.cssFromElement(e); | |
} else { | |
if (e.localName === 'style') { | |
var include = e.getAttribute(this.INCLUDE_ATTR); | |
if (include) { | |
cssText += this.cssFromModules(include, true); | |
} | |
e = e.__appliedElement || e; | |
e.parentNode.removeChild(e); | |
cssText += this.resolveCss(e.textContent, element.ownerDocument); | |
} else if (e.import && e.import.body) { | |
cssText += this.resolveCss(e.import.body.textContent, e.import); | |
} | |
} | |
} | |
return cssText; | |
}, | |
resolveCss: Polymer.ResolveUrl.resolveCss, | |
parser: Polymer.CssParse, | |
ruleTypes: Polymer.CssParse.types | |
}; | |
}(); | |
Polymer.StyleTransformer = function () { | |
var nativeShadow = Polymer.Settings.useNativeShadow; | |
var styleUtil = Polymer.StyleUtil; | |
var api = { | |
dom: function (node, scope, useAttr, shouldRemoveScope) { | |
this._transformDom(node, scope || '', useAttr, shouldRemoveScope); | |
}, | |
_transformDom: function (node, selector, useAttr, shouldRemoveScope) { | |
if (node.setAttribute) { | |
this.element(node, selector, useAttr, shouldRemoveScope); | |
} | |
var c$ = Polymer.dom(node).childNodes; | |
for (var i = 0; i < c$.length; i++) { | |
this._transformDom(c$[i], selector, useAttr, shouldRemoveScope); | |
} | |
}, | |
element: function (element, scope, useAttr, shouldRemoveScope) { | |
if (useAttr) { | |
if (shouldRemoveScope) { | |
element.removeAttribute(SCOPE_NAME); | |
} else { | |
element.setAttribute(SCOPE_NAME, scope); | |
} | |
} else { | |
if (scope) { | |
if (element.classList) { | |
if (shouldRemoveScope) { | |
element.classList.remove(SCOPE_NAME); | |
element.classList.remove(scope); | |
} else { | |
element.classList.add(SCOPE_NAME); | |
element.classList.add(scope); | |
} | |
} else if (element.getAttribute) { | |
var c = element.getAttribute(CLASS); | |
if (shouldRemoveScope) { | |
if (c) { | |
element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, '')); | |
} | |
} else { | |
element.setAttribute(CLASS, c + (c ? ' ' : '') + SCOPE_NAME + ' ' + scope); | |
} | |
} | |
} | |
} | |
}, | |
elementStyles: function (element, callback) { | |
var styles = element._styles; | |
var cssText = ''; | |
for (var i = 0, l = styles.length, s, text; i < l && (s = styles[i]); i++) { | |
var rules = styleUtil.rulesForStyle(s); | |
cssText += nativeShadow ? styleUtil.toCssText(rules, callback) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n'; | |
} | |
return cssText.trim(); | |
}, | |
css: function (rules, scope, ext, callback, useAttr) { | |
var hostScope = this._calcHostScope(scope, ext); | |
scope = this._calcElementScope(scope, useAttr); | |
var self = this; | |
return styleUtil.toCssText(rules, function (rule) { | |
if (!rule.isScoped) { | |
self.rule(rule, scope, hostScope); | |
rule.isScoped = true; | |
} | |
if (callback) { | |
callback(rule, scope, hostScope); | |
} | |
}); | |
}, | |
_calcElementScope: function (scope, useAttr) { | |
if (scope) { | |
return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope; | |
} else { | |
return ''; | |
} | |
}, | |
_calcHostScope: function (scope, ext) { | |
return ext ? '[is=' + scope + ']' : scope; | |
}, | |
rule: function (rule, scope, hostScope) { | |
this._transformRule(rule, this._transformComplexSelector, scope, hostScope); | |
}, | |
_transformRule: function (rule, transformer, scope, hostScope) { | |
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); | |
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) { | |
p$[i] = transformer.call(this, p, scope, hostScope); | |
} | |
rule.selector = rule.transformedSelector = p$.join(COMPLEX_SELECTOR_SEP); | |
}, | |
_transformComplexSelector: function (selector, scope, hostScope) { | |
var stop = false; | |
var hostContext = false; | |
var self = this; | |
selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) { | |
if (!stop) { | |
var info = self._transformCompoundSelector(s, c, scope, hostScope); | |
stop = stop || info.stop; | |
hostContext = hostContext || info.hostContext; | |
c = info.combinator; | |
s = info.value; | |
} else { | |
s = s.replace(SCOPE_JUMP, ' '); | |
} | |
return c + s; | |
}); | |
if (hostContext) { | |
selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) { | |
return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post; | |
}); | |
} | |
return selector; | |
}, | |
_transformCompoundSelector: function (selector, combinator, scope, hostScope) { | |
var jumpIndex = selector.search(SCOPE_JUMP); | |
var hostContext = false; | |
if (selector.indexOf(HOST_CONTEXT) >= 0) { | |
hostContext = true; | |
} else if (selector.indexOf(HOST) >= 0) { | |
selector = selector.replace(HOST_PAREN, function (m, host, paren) { | |
return hostScope + paren; | |
}); | |
selector = selector.replace(HOST, hostScope); | |
} else if (jumpIndex !== 0) { | |
selector = scope ? this._transformSimpleSelector(selector, scope) : selector; | |
} | |
if (selector.indexOf(CONTENT) >= 0) { | |
combinator = ''; | |
} | |
var stop; | |
if (jumpIndex >= 0) { | |
selector = selector.replace(SCOPE_JUMP, ' '); | |
stop = true; | |
} | |
return { | |
value: selector, | |
combinator: combinator, | |
stop: stop, | |
hostContext: hostContext | |
}; | |
}, | |
_transformSimpleSelector: function (selector, scope) { | |
var p$ = selector.split(PSEUDO_PREFIX); | |
p$[0] += scope; | |
return p$.join(PSEUDO_PREFIX); | |
}, | |
documentRule: function (rule) { | |
rule.selector = rule.parsedSelector; | |
this.normalizeRootSelector(rule); | |
if (!nativeShadow) { | |
this._transformRule(rule, this._transformDocumentSelector); | |
} | |
}, | |
normalizeRootSelector: function (rule) { | |
if (rule.selector === ROOT) { | |
rule.selector = 'body'; | |
} | |
}, | |
_transformDocumentSelector: function (selector) { | |
return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELECTOR); | |
}, | |
SCOPE_NAME: 'style-scope' | |
}; | |
var SCOPE_NAME = api.SCOPE_NAME; | |
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')'; | |
var COMPLEX_SELECTOR_SEP = ','; | |
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g; | |
var HOST = ':host'; | |
var ROOT = ':root'; | |
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; | |
var HOST_CONTEXT = ':host-context'; | |
var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/; | |
var CONTENT = '::content'; | |
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; | |
var CSS_CLASS_PREFIX = '.'; | |
var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~='; | |
var CSS_ATTR_SUFFIX = ']'; | |
var PSEUDO_PREFIX = ':'; | |
var CLASS = 'class'; | |
return api; | |
}(); | |
Polymer.StyleExtends = function () { | |
var styleUtil = Polymer.StyleUtil; | |
return { | |
hasExtends: function (cssText) { | |
return Boolean(cssText.match(this.rx.EXTEND)); | |
}, | |
transform: function (style) { | |
var rules = styleUtil.rulesForStyle(style); | |
var self = this; | |
styleUtil.forEachStyleRule(rules, function (rule) { | |
var map = self._mapRule(rule); | |
if (rule.parent) { | |
var m; | |
while (m = self.rx.EXTEND.exec(rule.cssText)) { | |
var extend = m[1]; | |
var extendor = self._findExtendor(extend, rule); | |
if (extendor) { | |
self._extendRule(rule, extendor); | |
} | |
} | |
} | |
rule.cssText = rule.cssText.replace(self.rx.EXTEND, ''); | |
}); | |
return styleUtil.toCssText(rules, function (rule) { | |
if (rule.selector.match(self.rx.STRIP)) { | |
rule.cssText = ''; | |
} | |
}, true); | |
}, | |
_mapRule: function (rule) { | |
if (rule.parent) { | |
var map = rule.parent.map || (rule.parent.map = {}); | |
var parts = rule.selector.split(','); | |
for (var i = 0, p; i < parts.length; i++) { | |
p = parts[i]; | |
map[p.trim()] = rule; | |
} | |
return map; | |
} | |
}, | |
_findExtendor: function (extend, rule) { | |
return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findExtendor(extend, rule.parent); | |
}, | |
_extendRule: function (target, source) { | |
if (target.parent !== source.parent) { | |
this._cloneAndAddRuleToParent(source, target.parent); | |
} | |
target.extends = target.extends || []; | |
target.extends.push(source); | |
source.selector = source.selector.replace(this.rx.STRIP, ''); | |
source.selector = (source.selector && source.selector + ',\n') + target.selector; | |
if (source.extends) { | |
source.extends.forEach(function (e) { | |
this._extendRule(target, e); | |
}, this); | |
} | |
}, | |
_cloneAndAddRuleToParent: function (rule, parent) { | |
rule = Object.create(rule); | |
rule.parent = parent; | |
if (rule.extends) { | |
rule.extends = rule.extends.slice(); | |
} | |
parent.rules.push(rule); | |
}, | |
rx: { | |
EXTEND: /@extends\(([^)]*)\)\s*?;/gim, | |
STRIP: /%[^,]*$/ | |
} | |
}; | |
}(); | |
(function () { | |
var prepElement = Polymer.Base._prepElement; | |
var nativeShadow = Polymer.Settings.useNativeShadow; | |
var styleUtil = Polymer.StyleUtil; | |
var styleTransformer = Polymer.StyleTransformer; | |
var styleExtends = Polymer.StyleExtends; | |
Polymer.Base._addFeature({ | |
_prepElement: function (element) { | |
if (this._encapsulateStyle) { | |
styleTransformer.element(element, this.is, this._scopeCssViaAttr); | |
} | |
prepElement.call(this, element); | |
}, | |
_prepStyles: function () { | |
if (this._encapsulateStyle === undefined) { | |
this._encapsulateStyle = !nativeShadow && Boolean(this._template); | |
} | |
if (this._template) { | |
this._styles = this._collectStyles(); | |
var cssText = styleTransformer.elementStyles(this); | |
if (cssText) { | |
var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null); | |
if (!nativeShadow) { | |
this._scopeStyle = style; | |
} | |
} | |
} else { | |
this._styles = []; | |
} | |
}, | |
_collectStyles: function () { | |
var styles = []; | |
var cssText = '', m$ = this.styleModules; | |
if (m$) { | |
for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) { | |
cssText += styleUtil.cssFromModule(m); | |
} | |
} | |
cssText += styleUtil.cssFromModule(this.is); | |
var p = this._template && this._template.parentNode; | |
if (this._template && (!p || p.id.toLowerCase() !== this.is)) { | |
cssText += styleUtil.cssFromElement(this._template); | |
} | |
if (cssText) { | |
var style = document.createElement('style'); | |
style.textContent = cssText; | |
if (styleExtends.hasExtends(style.textContent)) { | |
cssText = styleExtends.transform(style); | |
} | |
styles.push(style); | |
} | |
return styles; | |
}, | |
_elementAdd: function (node) { | |
if (this._encapsulateStyle) { | |
if (node.__styleScoped) { | |
node.__styleScoped = false; | |
} else { | |
styleTransformer.dom(node, this.is, this._scopeCssViaAttr); | |
} | |
} | |
}, | |
_elementRemove: function (node) { | |
if (this._encapsulateStyle) { | |
styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true); | |
} | |
}, | |
scopeSubtree: function (container, shouldObserve) { | |
if (nativeShadow) { | |
return; | |
} | |
var self = this; | |
var scopify = function (node) { | |
if (node.nodeType === Node.ELEMENT_NODE) { | |
node.className = self._scopeElementClass(node, node.className); | |
var n$ = node.querySelectorAll('*'); | |
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { | |
n.className = self._scopeElementClass(n, n.className); | |
} | |
} | |
}; | |
scopify(container); | |
if (shouldObserve) { | |
var mo = new MutationObserver(function (mxns) { | |
for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) { | |
if (m.addedNodes) { | |
for (var j = 0; j < m.addedNodes.length; j++) { | |
scopify(m.addedNodes[j]); | |
} | |
} | |
} | |
}); | |
mo.observe(container, { | |
childList: true, | |
subtree: true | |
}); | |
return mo; | |
} | |
} | |
}); | |
}()); | |
Polymer.StyleProperties = function () { | |
'use strict'; | |
var nativeShadow = Polymer.Settings.useNativeShadow; | |
var matchesSelector = Polymer.DomApi.matchesSelector; | |
var styleUtil = Polymer.StyleUtil; | |
var styleTransformer = Polymer.StyleTransformer; | |
return { | |
decorateStyles: function (styles) { | |
var self = this, props = {}; | |
styleUtil.forRulesInStyles(styles, function (rule) { | |
self.decorateRule(rule); | |
self.collectPropertiesInCssText(rule.propertyInfo.cssText, props); | |
}); | |
var names = []; | |
for (var i in props) { | |
names.push(i); | |
} | |
return names; | |
}, | |
decorateRule: function (rule) { | |
if (rule.propertyInfo) { | |
return rule.propertyInfo; | |
} | |
var info = {}, properties = {}; | |
var hasProperties = this.collectProperties(rule, properties); | |
if (hasProperties) { | |
info.properties = properties; | |
rule.rules = null; | |
} | |
info.cssText = this.collectCssText(rule); | |
rule.propertyInfo = info; | |
return info; | |
}, | |
collectProperties: function (rule, properties) { | |
var info = rule.propertyInfo; | |
if (info) { | |
if (info.properties) { | |
Polymer.Base.mixin(properties, info.properties); | |
return true; | |
} | |
} else { | |
var m, rx = this.rx.VAR_ASSIGN; | |
var cssText = rule.parsedCssText; | |
var any; | |
while (m = rx.exec(cssText)) { | |
properties[m[1]] = (m[2] || m[3]).trim(); | |
any = true; | |
} | |
return any; | |
} | |
}, | |
collectCssText: function (rule) { | |
var customCssText = ''; | |
var cssText = rule.parsedCssText; | |
cssText = cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, ''); | |
var parts = cssText.split(';'); | |
for (var i = 0, p; i < parts.length; i++) { | |
p = parts[i]; | |
if (p.match(this.rx.MIXIN_MATCH) || p.match(this.rx.VAR_MATCH)) { | |
customCssText += p + ';\n'; | |
} | |
} | |
return customCssText; | |
}, | |
collectPropertiesInCssText: function (cssText, props) { | |
var m; | |
while (m = this.rx.VAR_CAPTURE.exec(cssText)) { | |
props[m[1]] = true; | |
var def = m[2]; | |
if (def && def.match(this.rx.IS_VAR)) { | |
props[def] = true; | |
} | |
} | |
}, | |
reify: function (props) { | |
var names = Object.getOwnPropertyNames(props); | |
for (var i = 0, n; i < names.length; i++) { | |
n = names[i]; | |
props[n] = this.valueForProperty(props[n], props); | |
} | |
}, | |
valueForProperty: function (property, props) { | |
if (property) { | |
if (property.indexOf(';') >= 0) { | |
property = this.valueForProperties(property, props); | |
} else { | |
var self = this; | |
var fn = function (all, prefix, value, fallback) { | |
var propertyValue = self.valueForProperty(props[value], props) || (props[fallback] ? self.valueForProperty(props[fallback], props) : fallback); | |
return prefix + (propertyValue || ''); | |
}; | |
property = property.replace(this.rx.VAR_MATCH, fn); | |
} | |
} | |
return property && property.trim() || ''; | |
}, | |
valueForProperties: function (property, props) { | |
var parts = property.split(';'); | |
for (var i = 0, p, m; i < parts.length; i++) { | |
if (p = parts[i]) { | |
m = p.match(this.rx.MIXIN_MATCH); | |
if (m) { | |
p = this.valueForProperty(props[m[1]], props); | |
} else { | |
var pp = p.split(':'); | |
if (pp[1]) { | |
pp[1] = pp[1].trim(); | |
pp[1] = this.valueForProperty(pp[1], props) || pp[1]; | |
} | |
p = pp.join(':'); | |
} | |
parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || ''; | |
} | |
} | |
return parts.filter(function (v) { | |
return v; | |
}).join(';'); | |
}, | |
applyProperties: function (rule, props) { | |
var output = ''; | |
if (!rule.propertyInfo) { | |
this.decorateRule(rule); | |
} | |
if (rule.propertyInfo.cssText) { | |
output = this.valueForProperties(rule.propertyInfo.cssText, props); | |
} | |
rule.cssText = output; | |
}, | |
propertyDataFromStyles: function (styles, element) { | |
var props = {}, self = this; | |
var o = [], i = 0; | |
styleUtil.forRulesInStyles(styles, function (rule) { | |
if (!rule.propertyInfo) { | |
self.decorateRule(rule); | |
} | |
if (element && rule.propertyInfo.properties && matchesSelector.call(element, rule.transformedSelector || rule.parsedSelector)) { | |
self.collectProperties(rule, props); | |
addToBitMask(i, o); | |
} | |
i++; | |
}); | |
return { | |
properties: props, | |
key: o | |
}; | |
}, | |
scopePropertiesFromStyles: function (styles) { | |
if (!styles._scopeStyleProperties) { | |
styles._scopeStyleProperties = this.selectedPropertiesFromStyles(styles, this.SCOPE_SELECTORS); | |
} | |
return styles._scopeStyleProperties; | |
}, | |
hostPropertiesFromStyles: function (styles) { | |
if (!styles._hostStyleProperties) { | |
styles._hostStyleProperties = this.selectedPropertiesFromStyles(styles, this.HOST_SELECTORS); | |
} | |
return styles._hostStyleProperties; | |
}, | |
selectedPropertiesFromStyles: function (styles, selectors) { | |
var props = {}, self = this; | |
styleUtil.forRulesInStyles(styles, function (rule) { | |
if (!rule.propertyInfo) { | |
self.decorateRule(rule); | |
} | |
for (var i = 0; i < selectors.length; i++) { | |
if (rule.parsedSelector === selectors[i]) { | |
self.collectProperties(rule, props); | |
return; | |
} | |
} | |
}); | |
return props; | |
}, | |
transformStyles: function (element, properties, scopeSelector) { | |
var self = this; | |
var hostSelector = styleTransformer._calcHostScope(element.is, element.extends); | |
var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector; | |
var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFFIX); | |
return styleTransformer.elementStyles(element, function (rule) { | |
self.applyProperties(rule, properties); | |
if (rule.cssText && !nativeShadow) { | |
self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeSelector); | |
} | |
}); | |
}, | |
_scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) { | |
rule.transformedSelector = rule.transformedSelector || rule.selector; | |
var selector = rule.transformedSelector; | |
var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId; | |
var parts = selector.split(','); | |
for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) { | |
parts[i] = p.match(hostRx) ? p.replace(hostSelector, hostSelector + scope) : scope + ' ' + p; | |
} | |
rule.selector = parts.join(','); | |
}, | |
applyElementScopeSelector: function (element, selector, old, viaAttr) { | |
var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.className; | |
var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector; | |
if (c !== v) { | |
if (viaAttr) { | |
element.setAttribute(styleTransformer.SCOPE_NAME, v); | |
} else { | |
element.className = v; | |
} | |
} | |
}, | |
applyElementStyle: function (element, properties, selector, style) { | |
var cssText = style ? style.textContent || '' : this.transformStyles(element, properties, selector); | |
var s = element._customStyle; | |
if (s && !nativeShadow && s !== style) { | |
s._useCount--; | |
if (s._useCount <= 0 && s.parentNode) { | |
s.parentNode.removeChild(s); | |
} | |
} | |
if (nativeShadow || (!style || !style.parentNode)) { | |
if (nativeShadow && element._customStyle) { | |
element._customStyle.textContent = cssText; | |
style = element._customStyle; | |
} else if (cssText) { | |
style = styleUtil.applyCss(cssText, selector, nativeShadow ? element.root : null, element._scopeStyle); | |
} | |
} | |
if (style) { | |
style._useCount = style._useCount || 0; | |
if (element._customStyle != style) { | |
style._useCount++; | |
} | |
element._customStyle = style; | |
} | |
return style; | |
}, | |
mixinCustomStyle: function (props, customStyle) { | |
var v; | |
for (var i in customStyle) { | |
v = customStyle[i]; | |
if (v || v === 0) { | |
props[i] = v; | |
} | |
} | |
}, | |
rx: { | |
VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi, | |
MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, | |
VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi, | |
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi, | |
IS_VAR: /^--/, | |
BRACKETED: /\{[^}]*\}/g, | |
HOST_PREFIX: '(?:^|[^.#[:])', | |
HOST_SUFFIX: '($|[.:[\\s>+~])' | |
}, | |
HOST_SELECTORS: [':host'], | |
SCOPE_SELECTORS: [':root'], | |
XSCOPE_NAME: 'x-scope' | |
}; | |
function addToBitMask(n, bits) { | |
var o = parseInt(n / 32); | |
var v = 1 << n % 32; | |
bits[o] = (bits[o] || 0) | v; | |
} | |
}(); | |
(function () { | |
Polymer.StyleCache = function () { | |
this.cache = {}; | |
}; | |
Polymer.StyleCache.prototype = { | |
MAX: 100, | |
store: function (is, data, keyValues, keyStyles) { | |
data.keyValues = keyValues; | |
data.styles = keyStyles; | |
var s$ = this.cache[is] = this.cache[is] || []; | |
s$.push(data); | |
if (s$.length > this.MAX) { | |
s$.shift(); | |
} | |
}, | |
retrieve: function (is, keyValues, keyStyles) { | |
var cache = this.cache[is]; | |
if (cache) { | |
for (var i = cache.length - 1, data; i >= 0; i--) { | |
data = cache[i]; | |
if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) { | |
return data; | |
} | |
} | |
} | |
}, | |
clear: function () { | |
this.cache = {}; | |
}, | |
_objectsEqual: function (target, source) { | |
var t, s; | |
for (var i in target) { | |
t = target[i], s = source[i]; | |
if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) { | |
return false; | |
} | |
} | |
if (Array.isArray(target)) { | |
return target.length === source.length; | |
} | |
return true; | |
}, | |
_objectsStrictlyEqual: function (target, source) { | |
return this._objectsEqual(target, source) && this._objectsEqual(source, target); | |
} | |
}; | |
}()); | |
Polymer.StyleDefaults = function () { | |
var styleProperties = Polymer.StyleProperties; | |
var styleUtil = Polymer.StyleUtil; | |
var StyleCache = Polymer.StyleCache; | |
var api = { | |
_styles: [], | |
_properties: null, | |
customStyle: {}, | |
_styleCache: new StyleCache(), | |
addStyle: function (style) { | |
this._styles.push(style); | |
this._properties = null; | |
}, | |
get _styleProperties() { | |
if (!this._properties) { | |
styleProperties.decorateStyles(this._styles); | |
this._styles._scopeStyleProperties = null; | |
this._properties = styleProperties.scopePropertiesFromStyles(this._styles); | |
styleProperties.mixinCustomStyle(this._properties, this.customStyle); | |
styleProperties.reify(this._properties); | |
} | |
return this._properties; | |
}, | |
_needsStyleProperties: function () { | |
}, | |
_computeStyleProperties: function () { | |
return this._styleProperties; | |
}, | |
updateStyles: function (properties) { | |
this._properties = null; | |
if (properties) { | |
Polymer.Base.mixin(this.customStyle, properties); | |
} | |
this._styleCache.clear(); | |
for (var i = 0, s; i < this._styles.length; i++) { | |
s = this._styles[i]; | |
s = s.__importElement || s; | |
s._apply(); | |
} | |
} | |
}; | |
return api; | |
}(); | |
(function () { | |
'use strict'; | |
var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute; | |
var propertyUtils = Polymer.StyleProperties; | |
var styleTransformer = Polymer.StyleTransformer; | |
var styleUtil = Polymer.StyleUtil; | |
var styleDefaults = Polymer.StyleDefaults; | |
var nativeShadow = Polymer.Settings.useNativeShadow; | |
Polymer.Base._addFeature({ | |
_prepStyleProperties: function () { | |
this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : null; | |
}, | |
customStyle: null, | |
getComputedStyleValue: function (property) { | |
return this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property); | |
}, | |
_setupStyleProperties: function () { | |
this.customStyle = {}; | |
}, | |
_needsStyleProperties: function () { | |
return Boolean(this._ownStylePropertyNames && this._ownStylePropertyNames.length); | |
}, | |
_beforeAttached: function () { | |
if (!this._scopeSelector && this._needsStyleProperties()) { | |
this._updateStyleProperties(); | |
} | |
}, | |
_findStyleHost: function () { | |
var e = this, root; | |
while (root = Polymer.dom(e).getOwnerRoot()) { | |
if (Polymer.isInstance(root.host)) { | |
return root.host; | |
} | |
e = root.host; | |
} | |
return styleDefaults; | |
}, | |
_updateStyleProperties: function () { | |
var info, scope = this._findStyleHost(); | |
if (!scope._styleCache) { | |
scope._styleCache = new Polymer.StyleCache(); | |
} | |
var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this); | |
scopeData.key.customStyle = this.customStyle; | |
info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles); | |
var scopeCached = Boolean(info); | |
if (scopeCached) { | |
this._styleProperties = info._styleProperties; | |
} else { | |
this._computeStyleProperties(scopeData.properties); | |
} | |
this._computeOwnStyleProperties(); | |
if (!scopeCached) { | |
info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles); | |
} | |
var globalCached = Boolean(info) && !scopeCached; | |
var style = this._applyStyleProperties(info); | |
if (!scopeCached) { | |
style = style && nativeShadow ? style.cloneNode(true) : style; | |
info = { | |
style: style, | |
_scopeSelector: this._scopeSelector, | |
_styleProperties: this._styleProperties | |
}; | |
scopeData.key.customStyle = {}; | |
this.mixin(scopeData.key.customStyle, this.customStyle); | |
scope._styleCache.store(this.is, info, scopeData.key, this._styles); | |
if (!globalCached) { | |
styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._styles); | |
} | |
} | |
}, | |
_computeStyleProperties: function (scopeProps) { | |
var scope = this._findStyleHost(); | |
if (!scope._styleProperties) { | |
scope._computeStyleProperties(); | |
} | |
var props = Object.create(scope._styleProperties); | |
this.mixin(props, propertyUtils.hostPropertiesFromStyles(this._styles)); | |
scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, this).properties; | |
this.mixin(props, scopeProps); | |
this.mixin(props, propertyUtils.scopePropertiesFromStyles(this._styles)); | |
propertyUtils.mixinCustomStyle(props, this.customStyle); | |
propertyUtils.reify(props); | |
this._styleProperties = props; | |
}, | |
_computeOwnStyleProperties: function () { | |
var props = {}; | |
for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) { | |
n = this._ownStylePropertyNames[i]; | |
props[n] = this._styleProperties[n]; | |
} | |
this._ownStyleProperties = props; | |
}, | |
_scopeCount: 0, | |
_applyStyleProperties: function (info) { | |
var oldScopeSelector = this._scopeSelector; | |
this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++; | |
var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style); | |
if (!nativeShadow) { | |
propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr); | |
} | |
return style; | |
}, | |
serializeValueToAttribute: function (value, attribute, node) { | |
node = node || this; | |
if (attribute === 'class' && !nativeShadow) { | |
var host = node === this ? this.domHost || this.dataHost : this; | |
if (host) { | |
value = host._scopeElementClass(node, value); | |
} | |
} | |
node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : node; | |
serializeValueToAttribute.call(this, value, attribute, node); | |
}, | |
_scopeElementClass: function (element, selector) { | |
if (!nativeShadow && !this._scopeCssViaAttr) { | |
selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scopeSelector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : ''); | |
} | |
return selector; | |
}, | |
updateStyles: function (properties) { | |
if (this.isAttached) { | |
if (properties) { | |
this.mixin(this.customStyle, properties); | |
} | |
if (this._needsStyleProperties()) { | |
this._updateStyleProperties(); | |
} else { | |
this._styleProperties = null; | |
} | |
if (this._styleCache) { | |
this._styleCache.clear(); | |
} | |
this._updateRootStyles(); | |
} | |
}, | |
_updateRootStyles: function (root) { | |
root = root || this.root; | |
var c$ = Polymer.dom(root)._query(function (e) { | |
return e.shadyRoot || e.shadowRoot; | |
}); | |
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { | |
if (c.updateStyles) { | |
c.updateStyles(); | |
} | |
} | |
} | |
}); | |
Polymer.updateStyles = function (properties) { | |
styleDefaults.updateStyles(properties); | |
Polymer.Base._updateRootStyles(document); | |
}; | |
var styleCache = new Polymer.StyleCache(); | |
Polymer.customStyleCache = styleCache; | |
var SCOPE_NAME = styleTransformer.SCOPE_NAME; | |
var XSCOPE_NAME = propertyUtils.XSCOPE_NAME; | |
}()); | |
Polymer.Base._addFeature({ | |
_registerFeatures: function () { | |
this._prepIs(); | |
this._prepConstructor(); | |
this._prepTemplate(); | |
this._prepStyles(); | |
this._prepStyleProperties(); | |
this._prepAnnotations(); | |
this._prepEffects(); | |
this._prepBehaviors(); | |
this._prepPropertyInfo(); | |
this._prepBindings(); | |
this._prepShady(); | |
}, | |
_prepBehavior: function (b) { | |
this._addPropertyEffects(b.properties); | |
this._addComplexObserverEffects(b.observers); | |
this._addHostAttributes(b.hostAttributes); | |
}, | |
_initFeatures: function () { | |
this._setupConfigure(); | |
this._setupStyleProperties(); | |
this._setupDebouncers(); | |
this._registerHost(); | |
if (this._template) { | |
this._poolContent(); | |
this._beginHosting(); | |
this._stampTemplate(); | |
this._endHosting(); | |
this._marshalAnnotationReferences(); | |
} | |
this._marshalInstanceEffects(); | |
this._marshalBehaviors(); | |
this._marshalHostAttributes(); | |
this._marshalAttributes(); | |
this._tryReady(); | |
}, | |
_marshalBehavior: function (b) { | |
if (b.listeners) { | |
this._listenListeners(b.listeners); | |
} | |
} | |
}); | |
(function () { | |
var nativeShadow = Polymer.Settings.useNativeShadow; | |
var propertyUtils = Polymer.StyleProperties; | |
var styleUtil = Polymer.StyleUtil; | |
var cssParse = Polymer.CssParse; | |
var styleDefaults = Polymer.StyleDefaults; | |
var styleTransformer = Polymer.StyleTransformer; | |
Polymer({ | |
is: 'custom-style', | |
extends: 'style', | |
_template: null, | |
properties: { include: String }, | |
ready: function () { | |
this._tryApply(); | |
}, | |
attached: function () { | |
this._tryApply(); | |
}, | |
_tryApply: function () { | |
if (!this._appliesToDocument) { | |
if (this.parentNode && this.parentNode.localName !== 'dom-module') { | |
this._appliesToDocument = true; | |
var e = this.__appliedElement || this; | |
styleDefaults.addStyle(e); | |
if (e.textContent || this.include) { | |
this._apply(true); | |
} else { | |
var self = this; | |
var observer = new MutationObserver(function () { | |
observer.disconnect(); | |
self._apply(true); | |
}); | |
observer.observe(e, { childList: true }); | |
} | |
} | |
} | |
}, | |
_apply: function (deferProperties) { | |
var e = this.__appliedElement || this; | |
if (this.include) { | |
e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent; | |
} | |
if (e.textContent) { | |
styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function (rule) { | |
styleTransformer.documentRule(rule); | |
}); | |
var self = this; | |
function fn() { | |
self._applyCustomProperties(e); | |
} | |
if (this._pendingApplyProperties) { | |
cancelAnimationFrame(this._pendingApplyProperties); | |
this._pendingApplyProperties = null; | |
} | |
if (deferProperties) { | |
this._pendingApplyProperties = requestAnimationFrame(fn); | |
} else { | |
fn(); | |
} | |
} | |
}, | |
_applyCustomProperties: function (element) { | |
this._computeStyleProperties(); | |
var props = this._styleProperties; | |
var rules = styleUtil.rulesForStyle(element); | |
element.textContent = styleUtil.toCssText(rules, function (rule) { | |
var css = rule.cssText = rule.parsedCssText; | |
if (rule.propertyInfo && rule.propertyInfo.cssText) { | |
css = cssParse.removeCustomPropAssignment(css); | |
rule.cssText = propertyUtils.valueForProperties(css, props); | |
} | |
}); | |
} | |
}); | |
}()); | |
Polymer.Templatizer = { | |
properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } }, | |
_instanceProps: Polymer.nob, | |
_parentPropPrefix: '_parent_', | |
templatize: function (template) { | |
this._templatized = template; | |
if (!template._content) { | |
template._content = template.content; | |
} | |
if (template._content._ctor) { | |
this.ctor = template._content._ctor; | |
this._prepParentProperties(this.ctor.prototype, template); | |
return; | |
} | |
var archetype = Object.create(Polymer.Base); | |
this._customPrepAnnotations(archetype, template); | |
this._prepParentProperties(archetype, template); | |
archetype._prepEffects(); | |
this._customPrepEffects(archetype); | |
archetype._prepBehaviors(); | |
archetype._prepPropertyInfo(); | |
archetype._prepBindings(); | |
archetype._notifyPathUp = this._notifyPathUpImpl; | |
archetype._scopeElementClass = this._scopeElementClassImpl; | |
archetype.listen = this._listenImpl; | |
archetype._showHideChildren = this._showHideChildrenImpl; | |
var _constructor = this._constructorImpl; | |
var ctor = function TemplateInstance(model, host) { | |
_constructor.call(this, model, host); | |
}; | |
ctor.prototype = archetype; | |
archetype.constructor = ctor; | |
template._content._ctor = ctor; | |
this.ctor = ctor; | |
}, | |
_getRootDataHost: function () { | |
return this.dataHost && this.dataHost._rootDataHost || this.dataHost; | |
}, | |
_showHideChildrenImpl: function (hide) { | |
var c = this._children; | |
for (var i = 0; i < c.length; i++) { | |
var n = c[i]; | |
if (Boolean(hide) != Boolean(n.__hideTemplateChildren__)) { | |
if (n.nodeType === Node.TEXT_NODE) { | |
if (hide) { | |
n.__polymerTextContent__ = n.textContent; | |
n.textContent = ''; | |
} else { | |
n.textContent = n.__polymerTextContent__; | |
} | |
} else if (n.style) { | |
if (hide) { | |
n.__polymerDisplay__ = n.style.display; | |
n.style.display = 'none'; | |
} else { | |
n.style.display = n.__polymerDisplay__; | |
} | |
} | |
} | |
n.__hideTemplateChildren__ = hide; | |
} | |
}, | |
_debounceTemplate: function (fn) { | |
Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn)); | |
}, | |
_flushTemplates: function (debouncerExpired) { | |
Polymer.dom.flush(); | |
}, | |
_customPrepEffects: function (archetype) { | |
var parentProps = archetype._parentProps; | |
for (var prop in parentProps) { | |
archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop)); | |
} | |
for (var prop in this._instanceProps) { | |
archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector(prop)); | |
} | |
}, | |
_customPrepAnnotations: function (archetype, template) { | |
archetype._template = template; | |
var c = template._content; | |
if (!c._notes) { | |
var rootDataHost = archetype._rootDataHost; | |
if (rootDataHost) { | |
Polymer.Annotations.prepElement = function () { | |
rootDataHost._prepElement(); | |
}; | |
} | |
c._notes = Polymer.Annotations.parseAnnotations(template); | |
Polymer.Annotations.prepElement = null; | |
this._processAnnotations(c._notes); | |
} | |
archetype._notes = c._notes; | |
archetype._parentProps = c._parentProps; | |
}, | |
_prepParentProperties: function (archetype, template) { | |
var parentProps = this._parentProps = archetype._parentProps; | |
if (this._forwardParentProp && parentProps) { | |
var proto = archetype._parentPropProto; | |
var prop; | |
if (!proto) { | |
for (prop in this._instanceProps) { | |
delete parentProps[prop]; | |
} | |
proto = archetype._parentPropProto = Object.create(null); | |
if (template != this) { | |
Polymer.Bind.prepareModel(proto); | |
Polymer.Base.prepareModelNotifyPath(proto); | |
} | |
for (prop in parentProps) { | |
var parentProp = this._parentPropPrefix + prop; | |
var effects = [ | |
{ | |
kind: 'function', | |
effect: this._createForwardPropEffector(prop), | |
fn: Polymer.Bind._functionEffect | |
}, | |
{ | |
kind: 'notify', | |
fn: Polymer.Bind._notifyEffect, | |
effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' } | |
} | |
]; | |
Polymer.Bind._createAccessors(proto, parentProp, effects); | |
} | |
} | |
var self = this; | |
if (template != this) { | |
Polymer.Bind.prepareInstance(template); | |
template._forwardParentProp = function (source, value) { | |
self._forwardParentProp(source, value); | |
}; | |
} | |
this._extendTemplate(template, proto); | |
template._pathEffector = function (path, value, fromAbove) { | |
return self._pathEffectorImpl(path, value, fromAbove); | |
}; | |
} | |
}, | |
_createForwardPropEffector: function (prop) { | |
return function (source, value) { | |
this._forwardParentProp(prop, value); | |
}; | |
}, | |
_createHostPropEffector: function (prop) { | |
var prefix = this._parentPropPrefix; | |
return function (source, value) { | |
this.dataHost._templatized[prefix + prop] = value; | |
}; | |
}, | |
_createInstancePropEffector: function (prop) { | |
return function (source, value, old, fromAbove) { | |
if (!fromAbove) { | |
this.dataHost._forwardInstanceProp(this, prop, value); | |
} | |
}; | |
}, | |
_extendTemplate: function (template, proto) { | |
var n$ = Object.getOwnPropertyNames(proto); | |
for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { | |
var val = template[n]; | |
var pd = Object.getOwnPropertyDescriptor(proto, n); | |
Object.defineProperty(template, n, pd); | |
if (val !== undefined) { | |
template._propertySetter(n, val); | |
} | |
} | |
}, | |
_showHideChildren: function (hidden) { | |
}, | |
_forwardInstancePath: function (inst, path, value) { | |
}, | |
_forwardInstanceProp: function (inst, prop, value) { | |
}, | |
_notifyPathUpImpl: function (path, value) { | |
var dataHost = this.dataHost; | |
var dot = path.indexOf('.'); | |
var root = dot < 0 ? path : path.slice(0, dot); | |
dataHost._forwardInstancePath.call(dataHost, this, path, value); | |
if (root in dataHost._parentProps) { | |
dataHost._templatized.notifyPath(dataHost._parentPropPrefix + path, value); | |
} | |
}, | |
_pathEffectorImpl: function (path, value, fromAbove) { | |
if (this._forwardParentPath) { | |
if (path.indexOf(this._parentPropPrefix) === 0) { | |
var subPath = path.substring(this._parentPropPrefix.length); | |
var model = this._modelForPath(subPath); | |
if (model in this._parentProps) { | |
this._forwardParentPath(subPath, value); | |
} | |
} | |
} | |
Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove); | |
}, | |
_constructorImpl: function (model, host) { | |
this._rootDataHost = host._getRootDataHost(); | |
this._setupConfigure(model); | |
this._registerHost(host); | |
this._beginHosting(); | |
this.root = this.instanceTemplate(this._template); | |
this.root.__noContent = !this._notes._hasContent; | |
this.root.__styleScoped = true; | |
this._endHosting(); | |
this._marshalAnnotatedNodes(); | |
this._marshalInstanceEffects(); | |
this._marshalAnnotatedListeners(); | |
var children = []; | |
for (var n = this.root.firstChild; n; n = n.nextSibling) { | |
children.push(n); | |
n._templateInstance = this; | |
} | |
this._children = children; | |
if (host.__hideTemplateChildren__) { | |
this._showHideChildren(true); | |
} | |
this._tryReady(); | |
}, | |
_listenImpl: function (node, eventName, methodName) { | |
var model = this; | |
var host = this._rootDataHost; | |
var handler = host._createEventHandler(node, eventName, methodName); | |
var decorated = function (e) { | |
e.model = model; | |
handler(e); | |
}; | |
host._listen(node, eventName, decorated); | |
}, | |
_scopeElementClassImpl: function (node, value) { | |
var host = this._rootDataHost; | |
if (host) { | |
return host._scopeElementClass(node, value); | |
} | |
}, | |
stamp: function (model) { | |
model = model || {}; | |
if (this._parentProps) { | |
var templatized = this._templatized; | |
for (var prop in this._parentProps) { | |
model[prop] = templatized[this._parentPropPrefix + prop]; | |
} | |
} | |
return new this.ctor(model, this); | |
}, | |
modelForElement: function (el) { | |
var model; | |
while (el) { | |
if (model = el._templateInstance) { | |
if (model.dataHost != this) { | |
el = model.dataHost; | |
} else { | |
return model; | |
} | |
} else { | |
el = el.parentNode; | |
} | |
} | |
} | |
}; | |
Polymer({ | |
is: 'dom-template', | |
extends: 'template', | |
_template: null, | |
behaviors: [Polymer.Templatizer], | |
ready: function () { | |
this.templatize(this); | |
} | |
}); | |
Polymer._collections = new WeakMap(); | |
Polymer.Collection = function (userArray) { | |
Polymer._collections.set(userArray, this); | |
this.userArray = userArray; | |
this.store = userArray.slice(); | |
this.initMap(); | |
}; | |
Polymer.Collection.prototype = { | |
constructor: Polymer.Collection, | |
initMap: function () { | |
var omap = this.omap = new WeakMap(); | |
var pmap = this.pmap = {}; | |
var s = this.store; | |
for (var i = 0; i < s.length; i++) { | |
var item = s[i]; | |
if (item && typeof item == 'object') { | |
omap.set(item, i); | |
} else { | |
pmap[item] = i; | |
} | |
} | |
}, | |
add: function (item) { | |
var key = this.store.push(item) - 1; | |
if (item && typeof item == 'object') { | |
this.omap.set(item, key); | |
} else { | |
this.pmap[item] = key; | |
} | |
return '#' + key; | |
}, | |
removeKey: function (key) { | |
key = this._parseKey(key); | |
this._removeFromMap(this.store[key]); | |
delete this.store[key]; | |
}, | |
_removeFromMap: function (item) { | |
if (item && typeof item == 'object') { | |
this.omap.delete(item); | |
} else { | |
delete this.pmap[item]; | |
} | |
}, | |
remove: function (item) { | |
var key = this.getKey(item); | |
this.removeKey(key); | |
return key; | |
}, | |
getKey: function (item) { | |
var key; | |
if (item && typeof item == 'object') { | |
key = this.omap.get(item); | |
} else { | |
key = this.pmap[item]; | |
} | |
if (key != undefined) { | |
return '#' + key; | |
} | |
}, | |
getKeys: function () { | |
return Object.keys(this.store).map(function (key) { | |
return '#' + key; | |
}); | |
}, | |
_parseKey: function (key) { | |
if (key[0] == '#') { | |
return key.slice(1); | |
} | |
throw new Error('unexpected key ' + key); | |
}, | |
setItem: function (key, item) { | |
key = this._parseKey(key); | |
var old = this.store[key]; | |
if (old) { | |
this._removeFromMap(old); | |
} | |
if (item && typeof item == 'object') { | |
this.omap.set(item, key); | |
} else { | |
this.pmap[item] = key; | |
} | |
this.store[key] = item; | |
}, | |
getItem: function (key) { | |
key = this._parseKey(key); | |
return this.store[key]; | |
}, | |
getItems: function () { | |
var items = [], store = this.store; | |
for (var key in store) { | |
items.push(store[key]); | |
} | |
return items; | |
}, | |
_applySplices: function (splices) { | |
var keyMap = {}, key; | |
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { | |
s.addedKeys = []; | |
for (var j = 0; j < s.removed.length; j++) { | |
key = this.getKey(s.removed[j]); | |
keyMap[key] = keyMap[key] ? null : -1; | |
} | |
for (var j = 0; j < s.addedCount; j++) { | |
var item = this.userArray[s.index + j]; | |
key = this.getKey(item); | |
key = key === undefined ? this.add(item) : key; | |
keyMap[key] = keyMap[key] ? null : 1; | |
s.addedKeys.push(key); | |
} | |
} | |
var removed = []; | |
var added = []; | |
for (var key in keyMap) { | |
if (keyMap[key] < 0) { | |
this.removeKey(key); | |
removed.push(key); | |
} | |
if (keyMap[key] > 0) { | |
added.push(key); | |
} | |
} | |
return [{ | |
removed: removed, | |
added: added | |
}]; | |
} | |
}; | |
Polymer.Collection.get = function (userArray) { | |
return Polymer._collections.get(userArray) || new Polymer.Collection(userArray); | |
}; | |
Polymer.Collection.applySplices = function (userArray, splices) { | |
var coll = Polymer._collections.get(userArray); | |
return coll ? coll._applySplices(splices) : null; | |
}; | |
Polymer({ | |
is: 'dom-repeat', | |
extends: 'template', | |
_template: null, | |
properties: { | |
items: { type: Array }, | |
as: { | |
type: String, | |
value: 'item' | |
}, | |
indexAs: { | |
type: String, | |
value: 'index' | |
}, | |
sort: { | |
type: Function, | |
observer: '_sortChanged' | |
}, | |
filter: { | |
type: Function, | |
observer: '_filterChanged' | |
}, | |
observe: { | |
type: String, | |
observer: '_observeChanged' | |
}, | |
delay: Number, | |
initialCount: { | |
type: Number, | |
observer: '_initializeChunking' | |
}, | |
targetFramerate: { | |
type: Number, | |
value: 20 | |
}, | |
_targetFrameTime: { computed: '_computeFrameTime(targetFramerate)' } | |
}, | |
behaviors: [Polymer.Templatizer], | |
observers: ['_itemsChanged(items.*)'], | |
created: function () { | |
this._instances = []; | |
this._pool = []; | |
this._limit = Infinity; | |
var self = this; | |
this._boundRenderChunk = function () { | |
self._renderChunk(); | |
}; | |
}, | |
detached: function () { | |
for (var i = 0; i < this._instances.length; i++) { | |
this._detachInstance(i); | |
} | |
}, | |
attached: function () { | |
var parent = Polymer.dom(Polymer.dom(this).parentNode); | |
for (var i = 0; i < this._instances.length; i++) { | |
this._attachInstance(i, parent); | |
} | |
}, | |
ready: function () { | |
this._instanceProps = { __key__: true }; | |
this._instanceProps[this.as] = true; | |
this._instanceProps[this.indexAs] = true; | |
if (!this.ctor) { | |
this.templatize(this); | |
} | |
}, | |
_sortChanged: function (sort) { | |
var dataHost = this._getRootDataHost(); | |
this._sortFn = sort && (typeof sort == 'function' ? sort : function () { | |
return dataHost[sort].apply(dataHost, arguments); | |
}); | |
this._needFullRefresh = true; | |
if (this.items) { | |
this._debounceTemplate(this._render); | |
} | |
}, | |
_filterChanged: function (filter) { | |
var dataHost = this._getRootDataHost(); | |
this._filterFn = filter && (typeof filter == 'function' ? filter : function () { | |
return dataHost[filter].apply(dataHost, arguments); | |
}); | |
this._needFullRefresh = true; | |
if (this.items) { | |
this._debounceTemplate(this._render); | |
} | |
}, | |
_computeFrameTime: function (rate) { | |
return Math.ceil(1000 / rate); | |
}, | |
_initializeChunking: function () { | |
if (this.initialCount) { | |
this._limit = this.initialCount; | |
this._chunkCount = this.initialCount; | |
this._lastChunkTime = performance.now(); | |
} | |
}, | |
_tryRenderChunk: function () { | |
if (this.items && this._limit < this.items.length) { | |
this.debounce('renderChunk', this._requestRenderChunk); | |
} | |
}, | |
_requestRenderChunk: function () { | |
requestAnimationFrame(this._boundRenderChunk); | |
}, | |
_renderChunk: function () { | |
var currChunkTime = performance.now(); | |
var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime); | |
this._chunkCount = Math.round(this._chunkCount * ratio) || 1; | |
this._limit += this._chunkCount; | |
this._lastChunkTime = currChunkTime; | |
this._debounceTemplate(this._render); | |
}, | |
_observeChanged: function () { | |
this._observePaths = this.observe && this.observe.replace('.*', '.').split(' '); | |
}, | |
_itemsChanged: function (change) { | |
if (change.path == 'items') { | |
if (Array.isArray(this.items)) { | |
this.collection = Polymer.Collection.get(this.items); | |
} else if (!this.items) { | |
this.collection = null; | |
} else { | |
this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', this.items)); | |
} | |
this._keySplices = []; | |
this._indexSplices = []; | |
this._needFullRefresh = true; | |
this._initializeChunking(); | |
this._debounceTemplate(this._render); | |
} else if (change.path == 'items.splices') { | |
this._keySplices = this._keySplices.concat(change.value.keySplices); | |
this._indexSplices = this._indexSplices.concat(change.value.indexSplices); | |
this._debounceTemplate(this._render); | |
} else { | |
var subpath = change.path.slice(6); | |
this._forwardItemPath(subpath, change.value); | |
this._checkObservedPaths(subpath); | |
} | |
}, | |
_checkObservedPaths: function (path) { | |
if (this._observePaths) { | |
path = path.substring(path.indexOf('.') + 1); | |
var paths = this._observePaths; | |
for (var i = 0; i < paths.length; i++) { | |
if (path.indexOf(paths[i]) === 0) { | |
this._needFullRefresh = true; | |
if (this.delay) { | |
this.debounce('render', this._render, this.delay); | |
} else { | |
this._debounceTemplate(this._render); | |
} | |
return; | |
} | |
} | |
} | |
}, | |
render: function () { | |
this._needFullRefresh = true; | |
this._debounceTemplate(this._render); | |
this._flushTemplates(); | |
}, | |
_render: function () { | |
var c = this.collection; | |
if (this._needFullRefresh) { | |
this._applyFullRefresh(); | |
this._needFullRefresh = false; | |
} else if (this._keySplices.length) { | |
if (this._sortFn) { | |
this._applySplicesUserSort(this._keySplices); | |
} else { | |
if (this._filterFn) { | |
this._applyFullRefresh(); | |
} else { | |
this._applySplicesArrayOrder(this._indexSplices); | |
} | |
} | |
} else { | |
} | |
this._keySplices = []; | |
this._indexSplices = []; | |
var keyToIdx = this._keyToInstIdx = {}; | |
for (var i = this._instances.length - 1; i >= 0; i--) { | |
var inst = this._instances[i]; | |
if (inst.isPlaceholder && i < this._limit) { | |
inst = this._insertInstance(i, inst.__key__); | |
} else if (!inst.isPlaceholder && i >= this._limit) { | |
inst = this._downgradeInstance(i, inst.__key__); | |
} | |
keyToIdx[inst.__key__] = i; | |
if (!inst.isPlaceholder) { | |
inst.__setProperty(this.indexAs, i, true); | |
} | |
} | |
this._pool.length = 0; | |
this.fire('dom-change'); | |
this._tryRenderChunk(); | |
}, | |
_applyFullRefresh: function () { | |
var c = this.collection; | |
var keys; | |
if (this._sortFn) { | |
keys = c ? c.getKeys() : []; | |
} else { | |
keys = []; | |
var items = this.items; | |
if (items) { | |
for (var i = 0; i < items.length; i++) { | |
keys.push(c.getKey(items[i])); | |
} | |
} | |
} | |
var self = this; | |
if (this._filterFn) { | |
keys = keys.filter(function (a) { | |
return self._filterFn(c.getItem(a)); | |
}); | |
} | |
if (this._sortFn) { | |
keys.sort(function (a, b) { | |
return self._sortFn(c.getItem(a), c.getItem(b)); | |
}); | |
} | |
for (var i = 0; i < keys.length; i++) { | |
var key = keys[i]; | |
var inst = this._instances[i]; | |
if (inst) { | |
inst.__key__ = key; | |
if (!inst.isPlaceholder && i < this._limit) { | |
inst.__setProperty(this.as, c.getItem(key), true); | |
} | |
} else if (i < this._limit) { | |
this._insertInstance(i, key); | |
} else { | |
this._insertPlaceholder(i, key); | |
} | |
} | |
for (var j = this._instances.length - 1; j >= i; j--) { | |
this._detachAndRemoveInstance(j); | |
} | |
}, | |
_numericSort: function (a, b) { | |
return a - b; | |
}, | |
_applySplicesUserSort: function (splices) { | |
var c = this.collection; | |
var instances = this._instances; | |
var keyMap = {}; | |
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { | |
for (var j = 0; j < s.removed.length; j++) { | |
var key = s.removed[j]; | |
keyMap[key] = keyMap[key] ? null : -1; | |
} | |
for (var j = 0; j < s.added.length; j++) { | |
var key = s.added[j]; | |
keyMap[key] = keyMap[key] ? null : 1; | |
} | |
} | |
var removedIdxs = []; | |
var addedKeys = []; | |
for (var key in keyMap) { | |
if (keyMap[key] === -1) { | |
removedIdxs.push(this._keyToInstIdx[key]); | |
} | |
if (keyMap[key] === 1) { | |
addedKeys.push(key); | |
} | |
} | |
if (removedIdxs.length) { | |
removedIdxs.sort(this._numericSort); | |
for (var i = removedIdxs.length - 1; i >= 0; i--) { | |
var idx = removedIdxs[i]; | |
if (idx !== undefined) { | |
this._detachAndRemoveInstance(idx); | |
} | |
} | |
} | |
var self = this; | |
if (addedKeys.length) { | |
if (this._filterFn) { | |
addedKeys = addedKeys.filter(function (a) { | |
return self._filterFn(c.getItem(a)); | |
}); | |
} | |
addedKeys.sort(function (a, b) { | |
return self._sortFn(c.getItem(a), c.getItem(b)); | |
}); | |
var start = 0; | |
for (var i = 0; i < addedKeys.length; i++) { | |
start = this._insertRowUserSort(start, addedKeys[i]); | |
} | |
} | |
}, | |
_insertRowUserSort: function (start, key) { | |
var c = this.collection; | |
var item = c.getItem(key); | |
var end = this._instances.length - 1; | |
var idx = -1; | |
while (start <= end) { | |
var mid = start + end >> 1; | |
var midKey = this._instances[mid].__key__; | |
var cmp = this._sortFn(c.getItem(midKey), item); | |
if (cmp < 0) { | |
start = mid + 1; | |
} else if (cmp > 0) { | |
end = mid - 1; | |
} else { | |
idx = mid; | |
break; | |
} | |
} | |
if (idx < 0) { | |
idx = end + 1; | |
} | |
this._insertPlaceholder(idx, key); | |
return idx; | |
}, | |
_applySplicesArrayOrder: function (splices) { | |
var c = this.collection; | |
for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { | |
for (var j = 0; j < s.removed.length; j++) { | |
this._detachAndRemoveInstance(s.index); | |
} | |
for (var j = 0; j < s.addedKeys.length; j++) { | |
this._insertPlaceholder(s.index + j, s.addedKeys[j]); | |
} | |
} | |
}, | |
_detachInstance: function (idx) { | |
var inst = this._instances[idx]; | |
if (!inst.isPlaceholder) { | |
for (var i = 0; i < inst._children.length; i++) { | |
var el = inst._children[i]; | |
Polymer.dom(inst.root).appendChild(el); | |
} | |
return inst; | |
} | |
}, | |
_attachInstance: function (idx, parent) { | |
var inst = this._instances[idx]; | |
if (!inst.isPlaceholder) { | |
parent.insertBefore(inst.root, this); | |
} | |
}, | |
_detachAndRemoveInstance: function (idx) { | |
var inst = this._detachInstance(idx); | |
if (inst) { | |
this._pool.push(inst); | |
} | |
this._instances.splice(idx, 1); | |
}, | |
_insertPlaceholder: function (idx, key) { | |
this._instances.splice(idx, 0, { | |
isPlaceholder: true, | |
__key__: key | |
}); | |
}, | |
_stampInstance: function (idx, key) { | |
var model = { __key__: key }; | |
model[this.as] = this.collection.getItem(key); | |
model[this.indexAs] = idx; | |
return this.stamp(model); | |
}, | |
_insertInstance: function (idx, key) { | |
var inst = this._pool.pop(); | |
if (inst) { | |
inst.__setProperty(this.as, this.collection.getItem(key), true); | |
inst.__setProperty('__key__', key, true); | |
} else { | |
inst = this._stampInstance(idx, key); | |
} | |
var beforeRow = this._instances[idx + 1]; | |
var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this; | |
var parentNode = Polymer.dom(this).parentNode; | |
Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); | |
this._instances[idx] = inst; | |
return inst; | |
}, | |
_downgradeInstance: function (idx, key) { | |
var inst = this._detachInstance(idx); | |
if (inst) { | |
this._pool.push(inst); | |
} | |
inst = { | |
isPlaceholder: true, | |
__key__: key | |
}; | |
this._instances[idx] = inst; | |
return inst; | |
}, | |
_showHideChildren: function (hidden) { | |
for (var i = 0; i < this._instances.length; i++) { | |
this._instances[i]._showHideChildren(hidden); | |
} | |
}, | |
_forwardInstanceProp: function (inst, prop, value) { | |
if (prop == this.as) { | |
var idx; | |
if (this._sortFn || this._filterFn) { | |
idx = this.items.indexOf(this.collection.getItem(inst.__key__)); | |
} else { | |
idx = inst[this.indexAs]; | |
} | |
this.set('items.' + idx, value); | |
} | |
}, | |
_forwardInstancePath: function (inst, path, value) { | |
if (path.indexOf(this.as + '.') === 0) { | |
this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value); | |
} | |
}, | |
_forwardParentProp: function (prop, value) { | |
var i$ = this._instances; | |
for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { | |
if (!inst.isPlaceholder) { | |
inst.__setProperty(prop, value, true); | |
} | |
} | |
}, | |
_forwardParentPath: function (path, value) { | |
var i$ = this._instances; | |
for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { | |
if (!inst.isPlaceholder) { | |
inst._notifyPath(path, value, true); | |
} | |
} | |
}, | |
_forwardItemPath: function (path, value) { | |
if (this._keyToInstIdx) { | |
var dot = path.indexOf('.'); | |
var key = path.substring(0, dot < 0 ? path.length : dot); | |
var idx = this._keyToInstIdx[key]; | |
var inst = this._instances[idx]; | |
if (inst && !inst.isPlaceholder) { | |
if (dot >= 0) { | |
path = this.as + '.' + path.substring(dot + 1); | |
inst._notifyPath(path, value, true); | |
} else { | |
inst.__setProperty(this.as, value, true); | |
} | |
} | |
} | |
}, | |
itemForElement: function (el) { | |
var instance = this.modelForElement(el); | |
return instance && instance[this.as]; | |
}, | |
keyForElement: function (el) { | |
var instance = this.modelForElement(el); | |
return instance && instance.__key__; | |
}, | |
indexForElement: function (el) { | |
var instance = this.modelForElement(el); | |
return instance && instance[this.indexAs]; | |
} | |
}); | |
Polymer({ | |
is: 'array-selector', | |
_template: null, | |
properties: { | |
items: { | |
type: Array, | |
observer: 'clearSelection' | |
}, | |
multi: { | |
type: Boolean, | |
value: false, | |
observer: 'clearSelection' | |
}, | |
selected: { | |
type: Object, | |
notify: true | |
}, | |
selectedItem: { | |
type: Object, | |
notify: true | |
}, | |
toggle: { | |
type: Boolean, | |
value: false | |
} | |
}, | |
clearSelection: function () { | |
if (Array.isArray(this.selected)) { | |
for (var i = 0; i < this.selected.length; i++) { | |
this.unlinkPaths('selected.' + i); | |
} | |
} else { | |
this.unlinkPaths('selected'); | |
this.unlinkPaths('selectedItem'); | |
} | |
if (this.multi) { | |
if (!this.selected || this.selected.length) { | |
this.selected = []; | |
this._selectedColl = Polymer.Collection.get(this.selected); | |
} | |
} else { | |
this.selected = null; | |
this._selectedColl = null; | |
} | |
this.selectedItem = null; | |
}, | |
isSelected: function (item) { | |
if (this.multi) { | |
return this._selectedColl.getKey(item) !== undefined; | |
} else { | |
return this.selected == item; | |
} | |
}, | |
deselect: function (item) { | |
if (this.multi) { | |
if (this.isSelected(item)) { | |
var skey = this._selectedColl.getKey(item); | |
this.arrayDelete('selected', item); | |
this.unlinkPaths('selected.' + skey); | |
} | |
} else { | |
this.selected = null; | |
this.selectedItem = null; | |
this.unlinkPaths('selected'); | |
this.unlinkPaths('selectedItem'); | |
} | |
}, | |
select: function (item) { | |
var icol = Polymer.Collection.get(this.items); | |
var key = icol.getKey(item); | |
if (this.multi) { | |
if (this.isSelected(item)) { | |
if (this.toggle) { | |
this.deselect(item); | |
} | |
} else { | |
this.push('selected', item); | |
var skey = this._selectedColl.getKey(item); | |
this.linkPaths('selected.' + skey, 'items.' + key); | |
} | |
} else { | |
if (this.toggle && item == this.selected) { | |
this.deselect(); | |
} else { | |
this.selected = item; | |
this.selectedItem = item; | |
this.linkPaths('selected', 'items.' + key); | |
this.linkPaths('selectedItem', 'items.' + key); | |
} | |
} | |
} | |
}); | |
Polymer({ | |
is: 'dom-if', | |
extends: 'template', | |
_template: null, | |
properties: { | |
'if': { | |
type: Boolean, | |
value: false, | |
observer: '_queueRender' | |
}, | |
restamp: { | |
type: Boolean, | |
value: false, | |
observer: '_queueRender' | |
} | |
}, | |
behaviors: [Polymer.Templatizer], | |
_queueRender: function () { | |
this._debounceTemplate(this._render); | |
}, | |
detached: function () { | |
this._teardownInstance(); | |
}, | |
attached: function () { | |
if (this.if && this.ctor) { | |
this.async(this._ensureInstance); | |
} | |
}, | |
render: function () { | |
this._flushTemplates(); | |
}, | |
_render: function () { | |
if (this.if) { | |
if (!this.ctor) { | |
this.templatize(this); | |
} | |
this._ensureInstance(); | |
this._showHideChildren(); | |
} else if (this.restamp) { | |
this._teardownInstance(); | |
} | |
if (!this.restamp && this._instance) { | |
this._showHideChildren(); | |
} | |
if (this.if != this._lastIf) { | |
this.fire('dom-change'); | |
this._lastIf = this.if; | |
} | |
}, | |
_ensureInstance: function () { | |
if (!this._instance) { | |
var parentNode = Polymer.dom(this).parentNode; | |
if (parentNode) { | |
var parent = Polymer.dom(parentNode); | |
this._instance = this.stamp(); | |
var root = this._instance.root; | |
parent.insertBefore(root, this); | |
} | |
} | |
}, | |
_teardownInstance: function () { | |
if (this._instance) { | |
var c$ = this._instance._children; | |
if (c$) { | |
var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode); | |
for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { | |
parent.removeChild(n); | |
} | |
} | |
this._instance = null; | |
} | |
}, | |
_showHideChildren: function () { | |
var hidden = this.__hideTemplateChildren__ || !this.if; | |
if (this._instance) { | |
this._instance._showHideChildren(hidden); | |
} | |
}, | |
_forwardParentProp: function (prop, value) { | |
if (this._instance) { | |
this._instance[prop] = value; | |
} | |
}, | |
_forwardParentPath: function (path, value) { | |
if (this._instance) { | |
this._instance._notifyPath(path, value, true); | |
} | |
} | |
}); | |
Polymer({ | |
is: 'dom-bind', | |
extends: 'template', | |
_template: null, | |
created: function () { | |
var self = this; | |
Polymer.RenderStatus.whenReady(function () { | |
self._markImportsReady(); | |
}); | |
}, | |
_ensureReady: function () { | |
if (!this._readied) { | |
this._readySelf(); | |
} | |
}, | |
_markImportsReady: function () { | |
this._importsReady = true; | |
this._ensureReady(); | |
}, | |
_registerFeatures: function () { | |
this._prepConstructor(); | |
}, | |
_insertChildren: function () { | |
var parentDom = Polymer.dom(Polymer.dom(this).parentNode); | |
parentDom.insertBefore(this.root, this); | |
}, | |
_removeChildren: function () { | |
if (this._children) { | |
for (var i = 0; i < this._children.length; i++) { | |
this.root.appendChild(this._children[i]); | |
} | |
} | |
}, | |
_initFeatures: function () { | |
}, | |
_scopeElementClass: function (element, selector) { | |
if (this.dataHost) { | |
return this.dataHost._scopeElementClass(element, selector); | |
} else { | |
return selector; | |
} | |
}, | |
_prepConfigure: function () { | |
var config = {}; | |
for (var prop in this._propertyEffects) { | |
config[prop] = this[prop]; | |
} | |
var setupConfigure = this._setupConfigure; | |
this._setupConfigure = function () { | |
setupConfigure.call(this, config); | |
}; | |
}, | |
attached: function () { | |
if (this._importsReady) { | |
this.render(); | |
} | |
}, | |
detached: function () { | |
this._removeChildren(); | |
}, | |
render: function () { | |
this._ensureReady(); | |
if (!this._children) { | |
this._template = this; | |
this._prepAnnotations(); | |
this._prepEffects(); | |
this._prepBehaviors(); | |
this._prepConfigure(); | |
this._prepBindings(); | |
this._prepPropertyInfo(); | |
Polymer.Base._initFeatures.call(this); | |
this._children = Polymer.DomApi.arrayCopyChildNodes(this.root); | |
} | |
this._insertChildren(); | |
this.fire('dom-change'); | |
} | |
});</script> | |
<!-- | |
The `<iron-flex-layout>` component provides simple ways to use [CSS flexible box layout](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes), also known as flexbox. This component provides two different ways to use flexbox: | |
1. [Layout classes](https://github.com/PolymerElements/iron-flex-layout/tree/master/classes). The layout class stylesheet provides a simple set of class-based flexbox rules. Layout classes let you specify layout properties directly in markup. | |
2. [Custom CSS mixins](https://github.com/PolymerElements/iron-flex-layout/blob/master/iron-flex-layout.html). The mixin stylesheet includes custom CSS mixins that can be applied inside a CSS rule using the `@apply` function. | |
A complete [guide](https://elements.polymer-project.org/guides/flex-layout) to `<iron-flex-layout>` is available. | |
@group Iron Elements | |
@pseudoElement iron-flex-layout | |
@demo demo/index.html | |
--> | |
<style> | |
/* IE 10 support for HTML5 hidden attr */ | |
[hidden] { | |
display: none !important; | |
} | |
</style> | |
<style is="custom-style"> | |
:root { | |
--layout: { | |
display: -ms-flexbox; | |
display: -webkit-flex; | |
display: flex; | |
}; | |
--layout-inline: { | |
display: -ms-inline-flexbox; | |
display: -webkit-inline-flex; | |
display: inline-flex; | |
}; | |
--layout-horizontal: { | |
@apply(--layout); | |
-ms-flex-direction: row; | |
-webkit-flex-direction: row; | |
flex-direction: row; | |
}; | |
--layout-horizontal-reverse: { | |
@apply(--layout); | |
-ms-flex-direction: row-reverse; | |
-webkit-flex-direction: row-reverse; | |
flex-direction: row-reverse; | |
}; | |
--layout-vertical: { | |
@apply(--layout); | |
-ms-flex-direction: column; | |
-webkit-flex-direction: column; | |
flex-direction: column; | |
}; | |
--layout-vertical-reverse: { | |
@apply(--layout); | |
-ms-flex-direction: column-reverse; | |
-webkit-flex-direction: column-reverse; | |
flex-direction: column-reverse; | |
}; | |
--layout-wrap: { | |
-ms-flex-wrap: wrap; | |
-webkit-flex-wrap: wrap; | |
flex-wrap: wrap; | |
}; | |
--layout-wrap-reverse: { | |
-ms-flex-wrap: wrap-reverse; | |
-webkit-flex-wrap: wrap-reverse; | |
flex-wrap: wrap-reverse; | |
}; | |
--layout-flex-auto: { | |
-ms-flex: 1 1 auto; | |
-webkit-flex: 1 1 auto; | |
flex: 1 1 auto; | |
}; | |
--layout-flex-none: { | |
-ms-flex: none; | |
-webkit-flex: none; | |
flex: none; | |
}; | |
--layout-flex: { | |
-ms-flex: 1 1 0.000000001px; | |
-webkit-flex: 1; | |
flex: 1; | |
-webkit-flex-basis: 0.000000001px; | |
flex-basis: 0.000000001px; | |
}; | |
--layout-flex-2: { | |
-ms-flex: 2; | |
-webkit-flex: 2; | |
flex: 2; | |
}; | |
--layout-flex-3: { | |
-ms-flex: 3; | |
-webkit-flex: 3; | |
flex: 3; | |
}; | |
--layout-flex-4: { | |
-ms-flex: 4; | |
-webkit-flex: 4; | |
flex: 4; | |
}; | |
--layout-flex-5: { | |
-ms-flex: 5; | |
-webkit-flex: 5; | |
flex: 5; | |
}; | |
--layout-flex-6: { | |
-ms-flex: 6; | |
-webkit-flex: 6; | |
flex: 6; | |
}; | |
--layout-flex-7: { | |
-ms-flex: 7; | |
-webkit-flex: 7; | |
flex: 7; | |
}; | |
--layout-flex-8: { | |
-ms-flex: 8; | |
-webkit-flex: 8; | |
flex: 8; | |
}; | |
--layout-flex-9: { | |
-ms-flex: 9; | |
-webkit-flex: 9; | |
flex: 9; | |
}; | |
--layout-flex-10: { | |
-ms-flex: 10; | |
-webkit-flex: 10; | |
flex: 10; | |
}; | |
--layout-flex-11: { | |
-ms-flex: 11; | |
-webkit-flex: 11; | |
flex: 11; | |
}; | |
--layout-flex-12: { | |
-ms-flex: 12; | |
-webkit-flex: 12; | |
flex: 12; | |
}; | |
/* alignment in cross axis */ | |
--layout-start: { | |
-ms-flex-align: start; | |
-webkit-align-items: flex-start; | |
align-items: flex-start; | |
}; | |
--layout-center: { | |
-ms-flex-align: center; | |
-webkit-align-items: center; | |
align-items: center; | |
}; | |
--layout-end: { | |
-ms-flex-align: end; | |
-webkit-align-items: flex-end; | |
align-items: flex-end; | |
}; | |
/* alignment in main axis */ | |
--layout-start-justified: { | |
-ms-flex-pack: start; | |
-webkit-justify-content: flex-start; | |
justify-content: flex-start; | |
}; | |
--layout-center-justified: { | |
-ms-flex-pack: center; | |
-webkit-justify-content: center; | |
justify-content: center; | |
}; | |
--layout-end-justified: { | |
-ms-flex-pack: end; | |
-webkit-justify-content: flex-end; | |
justify-content: flex-end; | |
}; | |
--layout-around-justified: { | |
-ms-flex-pack: around; | |
-webkit-justify-content: space-around; | |
justify-content: space-around; | |
}; | |
--layout-justified: { | |
-ms-flex-pack: justify; | |
-webkit-justify-content: space-between; | |
justify-content: space-between; | |
}; | |
--layout-center-center: { | |
@apply(--layout-center); | |
@apply(--layout-center-justified); | |
}; | |
/* self alignment */ | |
--layout-self-start: { | |
-ms-align-self: flex-start; | |
-webkit-align-self: flex-start; | |
align-self: flex-start; | |
}; | |
--layout-self-center: { | |
-ms-align-self: center; | |
-webkit-align-self: center; | |
align-self: center; | |
}; | |
--layout-self-end: { | |
-ms-align-self: flex-end; | |
-webkit-align-self: flex-end; | |
align-self: flex-end; | |
}; | |
--layout-self-stretch: { | |
-ms-align-self: stretch; | |
-webkit-align-self: stretch; | |
align-self: stretch; | |
}; | |
/******************************* | |
Other Layout | |
*******************************/ | |
--layout-block: { | |
display: block; | |
}; | |
--layout-invisible: { | |
visibility: hidden !important; | |
}; | |
--layout-relative: { | |
position: relative; | |
}; | |
--layout-fit: { | |
position: absolute; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
}; | |
--layout-scroll: { | |
-webkit-overflow-scrolling: touch; | |
overflow: auto; | |
}; | |
--layout-fullbleed: { | |
margin: 0; | |
height: 100vh; | |
}; | |
/* fixed position */ | |
--layout-fixed-top: { | |
position: fixed; | |
top: 0; | |
left: 0; | |
right: 0; | |
}; | |
--layout-fixed-right: { | |
position: fixed; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
}; | |
--layout-fixed-bottom: { | |
position: fixed; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
}; | |
--layout-fixed-left: { | |
position: fixed; | |
top: 0; | |
bottom: 0; | |
left: 0; | |
}; | |
} | |
</style> | |
<script> | |
/** | |
* @param {!Function} selectCallback | |
* @constructor | |
*/ | |
Polymer.IronSelection = function(selectCallback) { | |
this.selection = []; | |
this.selectCallback = selectCallback; | |
}; | |
Polymer.IronSelection.prototype = { | |
/** | |
* Retrieves the selected item(s). | |
* | |
* @method get | |
* @returns Returns the selected item(s). If the multi property is true, | |
* `get` will return an array, otherwise it will return | |
* the selected item or undefined if there is no selection. | |
*/ | |
get: function() { | |
return this.multi ? this.selection.slice() : this.selection[0]; | |
}, | |
/** | |
* Clears all the selection except the ones indicated. | |
* | |
* @method clear | |
* @param {Array} excludes items to be excluded. | |
*/ | |
clear: function(excludes) { | |
this.selection.slice().forEach(function(item) { | |
if (!excludes || excludes.indexOf(item) < 0) { | |
this.setItemSelected(item, false); | |
} | |
}, this); | |
}, | |
/** | |
* Indicates if a given item is selected. | |
* | |
* @method isSelected | |
* @param {*} item The item whose selection state should be checked. | |
* @returns Returns true if `item` is selected. | |
*/ | |
isSelected: function(item) { | |
return this.selection.indexOf(item) >= 0; | |
}, | |
/** | |
* Sets the selection state for a given item to either selected or deselected. | |
* | |
* @method setItemSelected | |
* @param {*} item The item to select. | |
* @param {boolean} isSelected True for selected, false for deselected. | |
*/ | |
setItemSelected: function(item, isSelected) { | |
if (item != null) { | |
if (isSelected) { | |
this.selection.push(item); | |
} else { | |
var i = this.selection.indexOf(item); | |
if (i >= 0) { | |
this.selection.splice(i, 1); | |
} | |
} | |
if (this.selectCallback) { | |
this.selectCallback(item, isSelected); | |
} | |
} | |
}, | |
/** | |
* Sets the selection state for a given item. If the `multi` property | |
* is true, then the selected state of `item` will be toggled; otherwise | |
* the `item` will be selected. | |
* | |
* @method select | |
* @param {*} item The item to select. | |
*/ | |
select: function(item) { | |
if (this.multi) { | |
this.toggle(item); | |
} else if (this.get() !== item) { | |
this.setItemSelected(this.get(), false); | |
this.setItemSelected(item, true); | |
} | |
}, | |
/** | |
* Toggles the selection state for `item`. | |
* | |
* @method toggle | |
* @param {*} item The item to toggle. | |
*/ | |
toggle: function(item) { | |
this.setItemSelected(item, !this.isSelected(item)); | |
} | |
}; | |
</script> | |
<script> | |
/** @polymerBehavior */ | |
Polymer.IronSelectableBehavior = { | |
/** | |
* Fired when iron-selector is activated (selected or deselected). | |
* It is fired before the selected items are changed. | |
* Cancel the event to abort selection. | |
* | |
* @event iron-activate | |
*/ | |
/** | |
* Fired when an item is selected | |
* | |
* @event iron-select | |
*/ | |
/** | |
* Fired when an item is deselected | |
* | |
* @event iron-deselect | |
*/ | |
/** | |
* Fired when the list of selectable items changes (e.g., items are | |
* added or removed). The detail of the event is a list of mutation | |
* records that describe what changed. | |
* | |
* @event iron-items-changed | |
*/ | |
properties: { | |
/** | |
* If you want to use the attribute value of an element for `selected` instead of the index, | |
* set this to the name of the attribute. | |
*/ | |
attrForSelected: { | |
type: String, | |
value: null | |
}, | |
/** | |
* Gets or sets the selected element. The default is to use the index of the item. | |
*/ | |
selected: { | |
type: String, | |
notify: true | |
}, | |
/** | |
* Returns the currently selected item. | |
* | |
* @type {?Object} | |
*/ | |
selectedItem: { | |
type: Object, | |
readOnly: true, | |
notify: true | |
}, | |
/** | |
* The event that fires from items when they are selected. Selectable | |
* will listen for this event from items and update the selection state. | |
* Set to empty string to listen to no events. | |
*/ | |
activateEvent: { | |
type: String, | |
value: 'tap', | |
observer: '_activateEventChanged' | |
}, | |
/** | |
* This is a CSS selector string. If this is set, only items that match the CSS selector | |
* are selectable. | |
*/ | |
selectable: String, | |
/** | |
* The class to set on elements when selected. | |
*/ | |
selectedClass: { | |
type: String, | |
value: 'iron-selected' | |
}, | |
/** | |
* The attribute to set on elements when selected. | |
*/ | |
selectedAttribute: { | |
type: String, | |
value: null | |
}, | |
/** | |
* The list of items from which a selection can be made. | |
*/ | |
items: { | |
type: Array, | |
readOnly: true, | |
value: function() { | |
return []; | |
} | |
}, | |
/** | |
* The set of excluded elements where the key is the `localName` | |
* of the element that will be ignored from the item list. | |
* | |
* @default {template: 1} | |
*/ | |
_excludedLocalNames: { | |
type: Object, | |
value: function() { | |
return { | |
'template': 1 | |
}; | |
} | |
} | |
}, | |
observers: [ | |
'_updateSelected(attrForSelected, selected)' | |
], | |
created: function() { | |
this._bindFilterItem = this._filterItem.bind(this); | |
this._selection = new Polymer.IronSelection(this._applySelection.bind(this)); | |
}, | |
attached: function() { | |
this._observer = this._observeItems(this); | |
this._updateItems(); | |
if (!this._shouldUpdateSelection) { | |
this._updateSelected(this.attrForSelected,this.selected) | |
} | |
this._addListener(this.activateEvent); | |
}, | |
detached: function() { | |
if (this._observer) { | |
Polymer.dom(this).unobserveNodes(this._observer); | |
} | |
this._removeListener(this.activateEvent); | |
}, | |
/** | |
* Returns the index of the given item. | |
* | |
* @method indexOf | |
* @param {Object} item | |
* @returns Returns the index of the item | |
*/ | |
indexOf: function(item) { | |
return this.items.indexOf(item); | |
}, | |
/** | |
* Selects the given value. | |
* | |
* @method select | |
* @param {string} value the value to select. | |
*/ | |
select: function(value) { | |
this.selected = value; | |
}, | |
/** | |
* Selects the previous item. | |
* | |
* @method selectPrevious | |
*/ | |
selectPrevious: function() { | |
var length = this.items.length; | |
var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length; | |
this.selected = this._indexToValue(index); | |
}, | |
/** | |
* Selects the next item. | |
* | |
* @method selectNext | |
*/ | |
selectNext: function() { | |
var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length; | |
this.selected = this._indexToValue(index); | |
}, | |
get _shouldUpdateSelection() { | |
return this.selected != null; | |
}, | |
_addListener: function(eventName) { | |
this.listen(this, eventName, '_activateHandler'); | |
}, | |
_removeListener: function(eventName) { | |
this.unlisten(this, eventName, '_activateHandler'); | |
}, | |
_activateEventChanged: function(eventName, old) { | |
this._removeListener(old); | |
this._addListener(eventName); | |
}, | |
_updateItems: function() { | |
var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*'); | |
nodes = Array.prototype.filter.call(nodes, this._bindFilterItem); | |
this._setItems(nodes); | |
}, | |
_updateSelected: function() { | |
this._selectSelected(this.selected); | |
}, | |
_selectSelected: function(selected) { | |
this._selection.select(this._valueToItem(this.selected)); | |
}, | |
_filterItem: function(node) { | |
return !this._excludedLocalNames[node.localName]; | |
}, | |
_valueToItem: function(value) { | |
return (value == null) ? null : this.items[this._valueToIndex(value)]; | |
}, | |
_valueToIndex: function(value) { | |
if (this.attrForSelected) { | |
for (var i = 0, item; item = this.items[i]; i++) { | |
if (this._valueForItem(item) == value) { | |
return i; | |
} | |
} | |
} else { | |
return Number(value); | |
} | |
}, | |
_indexToValue: function(index) { | |
if (this.attrForSelected) { | |
var item = this.items[index]; | |
if (item) { | |
return this._valueForItem(item); | |
} | |
} else { | |
return index; | |
} | |
}, | |
_valueForItem: function(item) { | |
return item[this.attrForSelected] || item.getAttribute(this.attrForSelected); | |
}, | |
_applySelection: function(item, isSelected) { | |
if (this.selectedClass) { | |
this.toggleClass(this.selectedClass, isSelected, item); | |
} | |
if (this.selectedAttribute) { | |
this.toggleAttribute(this.selectedAttribute, isSelected, item); | |
} | |
this._selectionChange(); | |
this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); | |
}, | |
_selectionChange: function() { | |
this._setSelectedItem(this._selection.get()); | |
}, | |
// observe items change under the given node. | |
_observeItems: function(node) { | |
return Polymer.dom(node).observeNodes(function(mutations) { | |
// Let other interested parties know about the change so that | |
// we don't have to recreate mutation observers everywher. | |
this.fire('iron-items-changed', mutations, { | |
bubbles: false, | |
cancelable: false | |
}); | |
this._updateItems(); | |
if (this._shouldUpdateSelection) { | |
this._updateSelected(); | |
} | |
}); | |
}, | |
_activateHandler: function(e) { | |
var t = e.target; | |
var items = this.items; | |
while (t && t != this) { | |
var i = items.indexOf(t); | |
if (i >= 0) { | |
var value = this._indexToValue(i); | |
this._itemActivate(value, t); | |
return; | |
} | |
t = t.parentNode; | |
} | |
}, | |
_itemActivate: function(value, item) { | |
if (!this.fire('iron-activate', | |
{selected: value, item: item}, {cancelable: true}).defaultPrevented) { | |
this.select(value); | |
} | |
} | |
}; | |
</script> | |
<script> | |
/** @polymerBehavior Polymer.IronMultiSelectableBehavior */ | |
Polymer.IronMultiSelectableBehaviorImpl = { | |
properties: { | |
/** | |
* If true, multiple selections are allowed. | |
*/ | |
multi: { | |
type: Boolean, | |
value: false, | |
observer: 'multiChanged' | |
}, | |
/** | |
* Gets or sets the selected elements. This is used instead of `selected` when `multi` | |
* is true. | |
*/ | |
selectedValues: { | |
type: Array, | |
notify: true | |
}, | |
/** | |
* Returns an array of currently selected items. | |
*/ | |
selectedItems: { | |
type: Array, | |
readOnly: true, | |
notify: true | |
}, | |
}, | |
observers: [ | |
'_updateSelected(attrForSelected, selectedValues)' | |
], | |
/** | |
* Selects the given value. If the `multi` property is true, then the selected state of the | |
* `value` will be toggled; otherwise the `value` will be selected. | |
* | |
* @method select | |
* @param {string} value the value to select. | |
*/ | |
select: function(value) { | |
if (this.multi) { | |
if (this.selectedValues) { | |
this._toggleSelected(value); | |
} else { | |
this.selectedValues = [value]; | |
} | |
} else { | |
this.selected = value; | |
} | |
}, | |
multiChanged: function(multi) { | |
this._selection.multi = multi; | |
}, | |
get _shouldUpdateSelection() { | |
return this.selected != null || | |
(this.selectedValues != null && this.selectedValues.length); | |
}, | |
_updateSelected: function() { | |
if (this.multi) { | |
this._selectMulti(this.selectedValues); | |
} else { | |
this._selectSelected(this.selected); | |
} | |
}, | |
_selectMulti: function(values) { | |
this._selection.clear(); | |
if (values) { | |
for (var i = 0; i < values.length; i++) { | |
this._selection.setItemSelected(this._valueToItem(values[i]), true); | |
} | |
} | |
}, | |
_selectionChange: function() { | |
var s = this._selection.get(); | |
if (this.multi) { | |
this._setSelectedItems(s); | |
} else { | |
this._setSelectedItems([s]); | |
this._setSelectedItem(s); | |
} | |
}, | |
_toggleSelected: function(value) { | |
var i = this.selectedValues.indexOf(value); | |
var unselected = i < 0; | |
if (unselected) { | |
this.push('selectedValues',value); | |
} else { | |
this.splice('selectedValues',i,1); | |
} | |
this._selection.setItemSelected(this._valueToItem(value), unselected); | |
} | |
}; | |
/** @polymerBehavior */ | |
Polymer.IronMultiSelectableBehavior = [ | |
Polymer.IronSelectableBehavior, | |
Polymer.IronMultiSelectableBehaviorImpl | |
]; | |
</script> | |
<script> | |
(function() { | |
'use strict'; | |
/** | |
* Chrome uses an older version of DOM Level 3 Keyboard Events | |
* | |
* Most keys are labeled as text, but some are Unicode codepoints. | |
* Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set | |
*/ | |
var KEY_IDENTIFIER = { | |
'U+0008': 'backspace', | |
'U+0009': 'tab', | |
'U+001B': 'esc', | |
'U+0020': 'space', | |
'U+007F': 'del' | |
}; | |
/** | |
* Special table for KeyboardEvent.keyCode. | |
* KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better | |
* than that. | |
* | |
* Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode | |
*/ | |
var KEY_CODE = { | |
8: 'backspace', | |
9: 'tab', | |
13: 'enter', | |
27: 'esc', | |
33: 'pageup', | |
34: 'pagedown', | |
35: 'end', | |
36: 'home', | |
32: 'space', | |
37: 'left', | |
38: 'up', | |
39: 'right', | |
40: 'down', | |
46: 'del', | |
106: '*' | |
}; | |
/** | |
* MODIFIER_KEYS maps the short name for modifier keys used in a key | |
* combo string to the property name that references those same keys | |
* in a KeyboardEvent instance. | |
*/ | |
var MODIFIER_KEYS = { | |
'shift': 'shiftKey', | |
'ctrl': 'ctrlKey', | |
'alt': 'altKey', | |
'meta': 'metaKey' | |
}; | |
/** | |
* KeyboardEvent.key is mostly represented by printable character made by | |
* the keyboard, with unprintable keys labeled nicely. | |
* | |
* However, on OS X, Alt+char can make a Unicode character that follows an | |
* Apple-specific mapping. In this case, we fall back to .keyCode. | |
*/ | |
var KEY_CHAR = /[a-z0-9*]/; | |
/** | |
* Matches a keyIdentifier string. | |
*/ | |
var IDENT_CHAR = /U\+/; | |
/** | |
* Matches arrow keys in Gecko 27.0+ | |
*/ | |
var ARROW_KEY = /^arrow/; | |
/** | |
* Matches space keys everywhere (notably including IE10's exceptional name | |
* `spacebar`). | |
*/ | |
var SPACE_KEY = /^space(bar)?/; | |
/** | |
* Transforms the key. | |
* @param {string} key The KeyBoardEvent.key | |
* @param {Boolean} [noSpecialChars] Limits the transformation to | |
* alpha-numeric characters. | |
*/ | |
function transformKey(key, noSpecialChars) { | |
var validKey = ''; | |
if (key) { | |
var lKey = key.toLowerCase(); | |
if (lKey === ' ' || SPACE_KEY.test(lKey)) { | |
validKey = 'space'; | |
} else if (lKey.length == 1) { | |
if (!noSpecialChars || KEY_CHAR.test(lKey)) { | |
validKey = lKey; | |
} | |
} else if (ARROW_KEY.test(lKey)) { | |
validKey = lKey.replace('arrow', ''); | |
} else if (lKey == 'multiply') { | |
// numpad '*' can map to Multiply on IE/Windows | |
validKey = '*'; | |
} else { | |
validKey = lKey; | |
} | |
} | |
return validKey; | |
} | |
function transformKeyIdentifier(keyIdent) { | |
var validKey = ''; | |
if (keyIdent) { | |
if (keyIdent in KEY_IDENTIFIER) { | |
validKey = KEY_IDENTIFIER[keyIdent]; | |
} else if (IDENT_CHAR.test(keyIdent)) { | |
keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16); | |
validKey = String.fromCharCode(keyIdent).toLowerCase(); | |
} else { | |
validKey = keyIdent.toLowerCase(); | |
} | |
} | |
return validKey; | |
} | |
function transformKeyCode(keyCode) { | |
var validKey = ''; | |
if (Number(keyCode)) { | |
if (keyCode >= 65 && keyCode <= 90) { | |
// ascii a-z | |
// lowercase is 32 offset from uppercase | |
validKey = String.fromCharCode(32 + keyCode); | |
} else if (keyCode >= 112 && keyCode <= 123) { | |
// function keys f1-f12 | |
validKey = 'f' + (keyCode - 112); | |
} else if (keyCode >= 48 && keyCode <= 57) { | |
// top 0-9 keys | |
validKey = String(48 - keyCode); | |
} else if (keyCode >= 96 && keyCode <= 105) { | |
// num pad 0-9 | |
validKey = String(96 - keyCode); | |
} else { | |
validKey = KEY_CODE[keyCode]; | |
} | |
} | |
return validKey; | |
} | |
/** | |
* Calculates the normalized key for a KeyboardEvent. | |
* @param {KeyboardEvent} keyEvent | |
* @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key | |
* transformation to alpha-numeric chars. This is useful with key | |
* combinations like shift + 2, which on FF for MacOS produces | |
* keyEvent.key = @ | |
* To get 2 returned, set noSpecialChars = true | |
* To get @ returned, set noSpecialChars = false | |
*/ | |
function normalizedKeyForEvent(keyEvent, noSpecialChars) { | |
// Fall back from .key, to .keyIdentifier, to .keyCode, and then to | |
// .detail.key to support artificial keyboard events. | |
return transformKey(keyEvent.key, noSpecialChars) || | |
transformKeyIdentifier(keyEvent.keyIdentifier) || | |
transformKeyCode(keyEvent.keyCode) || | |
transformKey(keyEvent.detail.key, noSpecialChars) || ''; | |
} | |
function keyComboMatchesEvent(keyCombo, event) { | |
// For combos with modifiers we support only alpha-numeric keys | |
var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers); | |
return keyEvent === keyCombo.key && | |
(!keyCombo.hasModifiers || ( | |
!!event.shiftKey === !!keyCombo.shiftKey && | |
!!event.ctrlKey === !!keyCombo.ctrlKey && | |
!!event.altKey === !!keyCombo.altKey && | |
!!event.metaKey === !!keyCombo.metaKey) | |
); | |
} | |
function parseKeyComboString(keyComboString) { | |
if (keyComboString.length === 1) { | |
return { | |
combo: keyComboString, | |
key: keyComboString, | |
event: 'keydown' | |
}; | |
} | |
return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboPart) { | |
var eventParts = keyComboPart.split(':'); | |
var keyName = eventParts[0]; | |
var event = eventParts[1]; | |
if (keyName in MODIFIER_KEYS) { | |
parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; | |
parsedKeyCombo.hasModifiers = true; | |
} else { | |
parsedKeyCombo.key = keyName; | |
parsedKeyCombo.event = event || 'keydown'; | |
} | |
return parsedKeyCombo; | |
}, { | |
combo: keyComboString.split(':').shift() | |
}); | |
} | |
function parseEventString(eventString) { | |
return eventString.trim().split(' ').map(function(keyComboString) { | |
return parseKeyComboString(keyComboString); | |
}); | |
} | |
/** | |
* `Polymer.IronA11yKeysBehavior` provides a normalized interface for processing | |
* keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). | |
* The element takes care of browser differences with respect to Keyboard events | |
* and uses an expressive syntax to filter key presses. | |
* | |
* Use the `keyBindings` prototype property to express what combination of keys | |
* will trigger the event to fire. | |
* | |
* Use the `key-event-target` attribute to set up event handlers on a specific | |
* node. | |
* The `keys-pressed` event will fire when one of the key combinations set with the | |
* `keys` property is pressed. | |
* | |
* @demo demo/index.html | |
* @polymerBehavior | |
*/ | |
Polymer.IronA11yKeysBehavior = { | |
properties: { | |
/** | |
* The HTMLElement that will be firing relevant KeyboardEvents. | |
*/ | |
keyEventTarget: { | |
type: Object, | |
value: function() { | |
return this; | |
} | |
}, | |
/** | |
* If true, this property will cause the implementing element to | |
* automatically stop propagation on any handled KeyboardEvents. | |
*/ | |
stopKeyboardEventPropagation: { | |
type: Boolean, | |
value: false | |
}, | |
_boundKeyHandlers: { | |
type: Array, | |
value: function() { | |
return []; | |
} | |
}, | |
// We use this due to a limitation in IE10 where instances will have | |
// own properties of everything on the "prototype". | |
_imperativeKeyBindings: { | |
type: Object, | |
value: function() { | |
return {}; | |
} | |
} | |
}, | |
observers: [ | |
'_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' | |
], | |
keyBindings: {}, | |
registered: function() { | |
this._prepKeyBindings(); | |
}, | |
attached: function() { | |
this._listenKeyEventListeners(); | |
}, | |
detached: function() { | |
this._unlistenKeyEventListeners(); | |
}, | |
/** | |
* Can be used to imperatively add a key binding to the implementing | |
* element. This is the imperative equivalent of declaring a keybinding | |
* in the `keyBindings` prototype property. | |
*/ | |
addOwnKeyBinding: function(eventString, handlerName) { | |
this._imperativeKeyBindings[eventString] = handlerName; | |
this._prepKeyBindings(); | |
this._resetKeyEventListeners(); | |
}, | |
/** | |
* When called, will remove all imperatively-added key bindings. | |
*/ | |
removeOwnKeyBindings: function() { | |
this._imperativeKeyBindings = {}; | |
this._prepKeyBindings(); | |
this._resetKeyEventListeners(); | |
}, | |
keyboardEventMatchesKeys: function(event, eventString) { | |
var keyCombos = parseEventString(eventString); | |
for (var i = 0; i < keyCombos.length; ++i) { | |
if (keyComboMatchesEvent(keyCombos[i], event)) { | |
return true; | |
} | |
} | |
return false; | |
}, | |
_collectKeyBindings: function() { | |
var keyBindings = this.behaviors.map(function(behavior) { | |
return behavior.keyBindings; | |
}); | |
if (keyBindings.indexOf(this.keyBindings) === -1) { | |
keyBindings.push(this.keyBindings); | |
} | |
return keyBindings; | |
}, | |
_prepKeyBindings: function() { | |
this._keyBindings = {}; | |
this._collectKeyBindings().forEach(function(keyBindings) { | |
for (var eventString in keyBindings) { | |
this._addKeyBinding(eventString, keyBindings[eventString]); | |
} | |
}, this); | |
for (var eventString in this._imperativeKeyBindings) { | |
this._addKeyBinding(eventString, this._imperativeKeyBindings[eventString]); | |
} | |
// Give precedence to combos with modifiers to be checked first. | |
for (var eventName in this._keyBindings) { | |
this._keyBindings[eventName].sort(function (kb1, kb2) { | |
var b1 = kb1[0].hasModifiers; | |
var b2 = kb2[0].hasModifiers; | |
return (b1 === b2) ? 0 : b1 ? -1 : 1; | |
}) | |
} | |
}, | |
_addKeyBinding: function(eventString, handlerName) { | |
parseEventString(eventString).forEach(function(keyCombo) { | |
this._keyBindings[keyCombo.event] = | |
this._keyBindings[keyCombo.event] || []; | |
this._keyBindings[keyCombo.event].push([ | |
keyCombo, | |
handlerName | |
]); | |
}, this); | |
}, | |
_resetKeyEventListeners: function() { | |
this._unlistenKeyEventListeners(); | |
if (this.isAttached) { | |
this._listenKeyEventListeners(); | |
} | |
}, | |
_listenKeyEventListeners: function() { | |
Object.keys(this._keyBindings).forEach(function(eventName) { | |
var keyBindings = this._keyBindings[eventName]; | |
var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings); | |
this._boundKeyHandlers.push([this.keyEventTarget, eventName, boundKeyHandler]); | |
this.keyEventTarget.addEventListener(eventName, boundKeyHandler); | |
}, this); | |
}, | |
_unlistenKeyEventListeners: function() { | |
var keyHandlerTuple; | |
var keyEventTarget; | |
var eventName; | |
var boundKeyHandler; | |
while (this._boundKeyHandlers.length) { | |
// My kingdom for block-scope binding and destructuring assignment.. | |
keyHandlerTuple = this._boundKeyHandlers.pop(); | |
keyEventTarget = keyHandlerTuple[0]; | |
eventName = keyHandlerTuple[1]; | |
boundKeyHandler = keyHandlerTuple[2]; | |
keyEventTarget.removeEventListener(eventName, boundKeyHandler); | |
} | |
}, | |
_onKeyBindingEvent: function(keyBindings, event) { | |
if (this.stopKeyboardEventPropagation) { | |
event.stopPropagation(); | |
} | |
// if event has been already prevented, don't do anything | |
if (event.defaultPrevented) { | |
return; | |
} | |
for (var i = 0; i < keyBindings.length; i++) { | |
var keyCombo = keyBindings[i][0]; | |
var handlerName = keyBindings[i][1]; | |
if (keyComboMatchesEvent(keyCombo, event)) { | |
this._triggerKeyHandler(keyCombo, handlerName, event); | |
// exit the loop if eventDefault was prevented | |
if (event.defaultPrevented) { | |
return; | |
} | |
} | |
} | |
}, | |
_triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { | |
var detail = Object.create(keyCombo); | |
detail.keyboardEvent = keyboardEvent; | |
var event = new CustomEvent(keyCombo.event, { | |
detail: detail, | |
cancelable: true | |
}); | |
this[handlerName].call(this, event); | |
if (event.defaultPrevented) { | |
keyboardEvent.preventDefault(); | |
} | |
} | |
}; | |
})(); | |
</script> | |
<script> | |
/** | |
* `Polymer.IronMenuBehavior` implements accessible menu behavior. | |
* | |
* @demo demo/index.html | |
* @polymerBehavior Polymer.IronMenuBehavior | |
*/ | |
Polymer.IronMenuBehaviorImpl = { | |
properties: { | |
/** | |
* Returns the currently focused item. | |
* @type {?Object} | |
*/ | |
focusedItem: { | |
observer: '_focusedItemChanged', | |
readOnly: true, | |
type: Object | |
}, | |
/** | |
* The attribute to use on menu items to look up the item title. Typing the first | |
* letter of an item when the menu is open focuses that item. If unset, `textContent` | |
* will be used. | |
*/ | |
attrForItemTitle: { | |
type: String | |
} | |
}, | |
hostAttributes: { | |
'role': 'menu', | |
'tabindex': '0' | |
}, | |
observers: [ | |
'_updateMultiselectable(multi)' | |
], | |
listeners: { | |
'focus': '_onFocus', | |
'keydown': '_onKeydown', | |
'iron-items-changed': '_onIronItemsChanged' | |
}, | |
keyBindings: { | |
'up': '_onUpKey', | |
'down': '_onDownKey', | |
'esc': '_onEscKey', | |
'shift+tab:keydown': '_onShiftTabDown' | |
}, | |
attached: function() { | |
this._resetTabindices(); | |
}, | |
/** | |
* Selects the given value. If the `multi` property is true, then the selected state of the | |
* `value` will be toggled; otherwise the `value` will be selected. | |
* | |
* @param {string} value the value to select. | |
*/ | |
select: function(value) { | |
if (this._defaultFocusAsync) { | |
this.cancelAsync(this._defaultFocusAsync); | |
this._defaultFocusAsync = null; | |
} | |
var item = this._valueToItem(value); | |
if (item && item.hasAttribute('disabled')) return; | |
this._setFocusedItem(item); | |
Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments); | |
}, | |
/** | |
* Resets all tabindex attributes to the appropriate value based on the | |
* current selection state. The appropriate value is `0` (focusable) for | |
* the default selected item, and `-1` (not keyboard focusable) for all | |
* other items. | |
*/ | |
_resetTabindices: function() { | |
var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[0]) : this.selectedItem; | |
this.items.forEach(function(item) { | |
item.setAttribute('tabindex', item === selectedItem ? '0' : '-1'); | |
}, this); | |
}, | |
/** | |
* Sets appropriate ARIA based on whether or not the menu is meant to be | |
* multi-selectable. | |
* | |
* @param {boolean} multi True if the menu should be multi-selectable. | |
*/ | |
_updateMultiselectable: function(multi) { | |
if (multi) { | |
this.setAttribute('aria-multiselectable', 'true'); | |
} else { | |
this.removeAttribute('aria-multiselectable'); | |
} | |
}, | |
/** | |
* Given a KeyboardEvent, this method will focus the appropriate item in the | |
* menu (if there is a relevant item, and it is possible to focus it). | |
* | |
* @param {KeyboardEvent} event A KeyboardEvent. | |
*/ | |
_focusWithKeyboardEvent: function(event) { | |
for (var i = 0, item; item = this.items[i]; i++) { | |
var attr = this.attrForItemTitle || 'textContent'; | |
var title = item[attr] || item.getAttribute(attr); | |
if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) { | |
this._setFocusedItem(item); | |
break; | |
} | |
} | |
}, | |
/** | |
* Focuses the previous item (relative to the currently focused item) in the | |
* menu. | |
*/ | |
_focusPrevious: function() { | |
var length = this.items.length; | |
var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length; | |
this._setFocusedItem(this.items[index]); | |
}, | |
/** | |
* Focuses the next item (relative to the currently focused item) in the | |
* menu. | |
*/ | |
_focusNext: function() { | |
var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.length; | |
this._setFocusedItem(this.items[index]); | |
}, | |
/** | |
* Mutates items in the menu based on provided selection details, so that | |
* all items correctly reflect selection state. | |
* | |
* @param {Element} item An item in the menu. | |
* @param {boolean} isSelected True if the item should be shown in a | |
* selected state, otherwise false. | |
*/ | |
_applySelection: function(item, isSelected) { | |
if (isSelected) { | |
item.setAttribute('aria-selected', 'true'); | |
} else { | |
item.removeAttribute('aria-selected'); | |
} | |
Polymer.IronSelectableBehavior._applySelection.apply(this, arguments); | |
}, | |
/** | |
* Discretely updates tabindex values among menu items as the focused item | |
* changes. | |
* | |
* @param {Element} focusedItem The element that is currently focused. | |
* @param {?Element} old The last element that was considered focused, if | |
* applicable. | |
*/ | |
_focusedItemChanged: function(focusedItem, old) { | |
old && old.setAttribute('tabindex', '-1'); | |
if (focusedItem) { | |
focusedItem.setAttribute('tabindex', '0'); | |
focusedItem.focus(); | |
} | |
}, | |
/** | |
* A handler that responds to mutation changes related to the list of items | |
* in the menu. | |
* | |
* @param {CustomEvent} event An event containing mutation records as its | |
* detail. | |
*/ | |
_onIronItemsChanged: function(event) { | |
var mutations = event.detail; | |
var mutation; | |
var index; | |
for (index = 0; index < mutations.length; ++index) { | |
mutation = mutations[index]; | |
if (mutation.addedNodes.length) { | |
this._resetTabindices(); | |
break; | |
} | |
} | |
}, | |
/** | |
* Handler that is called when a shift+tab keypress is detected by the menu. | |
* | |
* @param {CustomEvent} event A key combination event. | |
*/ | |
_onShiftTabDown: function(event) { | |
var oldTabIndex = this.getAttribute('tabindex'); | |
Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; | |
this._setFocusedItem(null); | |
this.setAttribute('tabindex', '-1'); | |
this.async(function() { | |
this.setAttribute('tabindex', oldTabIndex); | |
Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; | |
// NOTE(cdata): polymer/polymer#1305 | |
}, 1); | |
}, | |
/** | |
* Handler that is called when the menu receives focus. | |
* | |
* @param {FocusEvent} event A focus event. | |
*/ | |
_onFocus: function(event) { | |
if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) { | |
// do not focus the menu itself | |
return; | |
} | |
this.blur(); | |
// clear the cached focus item | |
this._defaultFocusAsync = this.async(function() { | |
// focus the selected item when the menu receives focus, or the first item | |
// if no item is selected | |
var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[0]) : this.selectedItem; | |
this._setFocusedItem(null); | |
if (selectedItem) { | |
this._setFocusedItem(selectedItem); | |
} else { | |
this._setFocusedItem(this.items[0]); | |
} | |
// async 1ms to wait for `select` to get called from `_itemActivate` | |
}, 1); | |
}, | |
/** | |
* Handler that is called when the up key is pressed. | |
* | |
* @param {CustomEvent} event A key combination event. | |
*/ | |
_onUpKey: function(event) { | |
// up and down arrows moves the focus | |
this._focusPrevious(); | |
}, | |
/** | |
* Handler that is called when the down key is pressed. | |
* | |
* @param {CustomEvent} event A key combination event. | |
*/ | |
_onDownKey: function(event) { | |
this._focusNext(); | |
}, | |
/** | |
* Handler that is called when the esc key is pressed. | |
* | |
* @param {CustomEvent} event A key combination event. | |
*/ | |
_onEscKey: function(event) { | |
// esc blurs the control | |
this.focusedItem.blur(); | |
}, | |
/** | |
* Handler that is called when a keydown event is detected. | |
* | |
* @param {KeyboardEvent} event A keyboard event. | |
*/ | |
_onKeydown: function(event) { | |
if (!this.keyboardEventMatchesKeys(event, 'up down esc')) { | |
// all other keys focus the menu item starting with that character | |
this._focusWithKeyboardEvent(event); | |
} | |
event.stopPropagation(); | |
}, | |
// override _activateHandler | |
_activateHandler: function(event) { | |
Polymer.IronSelectableBehavior._activateHandler.call(this, event); | |
event.stopPropagation(); | |
} | |
}; | |
Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; | |
/** @polymerBehavior Polymer.IronMenuBehavior */ | |
Polymer.IronMenuBehavior = [ | |
Polymer.IronMultiSelectableBehavior, | |
Polymer.IronA11yKeysBehavior, | |
Polymer.IronMenuBehaviorImpl | |
]; | |
</script> | |
<!-- Taken from https://www.google.com/design/spec/style/color.html#color-ui-color-application --> | |
<style is="custom-style"> | |
:root { | |
/* | |
* You can use these generic variables in your elements for easy theming. | |
* For example, if all your elements use `--primary-text-color` as its main | |
* color, then switching from a light to a dark theme is just a matter of | |
* changing the value of `--primary-text-color` in your application. | |
*/ | |
--primary-text-color: var(--light-theme-text-color); | |
--primary-background-color: var(--light-theme-background-color); | |
--secondary-text-color: var(--light-theme-secondary-color); | |
--disabled-text-color: var(--light-theme-disabled-color); | |
--divider-color: var(--light-theme-divider-color); | |
/* | |
* Primary and accent colors. Also see color.html for more colors. | |
*/ | |
--primary-color: #3f51b5; /* --paper-indigo-500 */ | |
--light-primary-color: #c5cae9; /* --paper-indigo-100 */ | |
--dark-primary-color: #303f9f; /* --paper-indigo-700 */ | |
--accent-color: #ff4081; /* --paper-pink-a200 */ | |
--light-accent-color: #ff80ab; /* --paper-pink-a100 */ | |
--dark-accent-color: #f50057; /* --paper-pink-a400 */ | |
/* | |
* Material Design Light background theme | |
*/ | |
--light-theme-background-color: #ffffff; | |
--light-theme-base-color: #000000; | |
--light-theme-text-color: #212121; | |
--light-theme-secondary-color: #737373; /* for secondary text and icons */ | |
--light-theme-disabled-color: #9b9b9b; /* disabled/hint text */ | |
--light-theme-divider-color: #dbdbdb; | |
/* | |
* Material Design Dark background theme | |
*/ | |
--dark-theme-background-color: #212121; | |
--dark-theme-base-color: #ffffff; | |
--dark-theme-text-color: #ffffff; | |
--dark-theme-secondary-color: #bcbcbc; /* for secondary text and icons */ | |
--dark-theme-disabled-color: #646464; /* disabled/hint text */ | |
--dark-theme-divider-color: #3c3c3c; | |
/* | |
* Deprecated values because of their confusing names. | |
*/ | |
--text-primary-color: var(--dark-theme-text-color); | |
--default-primary-color: var(--primary-color); | |
} | |
</style> | |
<style is="custom-style"> | |
:root { | |
/* Material Design color palette for Google products */ | |
--google-red-100: #f4c7c3; | |
--google-red-300: #e67c73; | |
--google-red-500: #db4437; | |
--google-red-700: #c53929; | |
--google-blue-100: #c6dafc; | |
--google-blue-300: #7baaf7; | |
--google-blue-500: #4285f4; | |
--google-blue-700: #3367d6; | |
--google-green-100: #b7e1cd; | |
--google-green-300: #57bb8a; | |
--google-green-500: #0f9d58; | |
--google-green-700: #0b8043; | |
--google-yellow-100: #fce8b2; | |
--google-yellow-300: #f7cb4d; | |
--google-yellow-500: #f4b400; | |
--google-yellow-700: #f09300; | |
--google-grey-100: #f5f5f5; | |
--google-grey-300: #e0e0e0; | |
--google-grey-500: #9e9e9e; | |
--google-grey-700: #616161; | |
/* Material Design color palette from online spec document */ | |
--paper-red-50: #ffebee; | |
--paper-red-100: #ffcdd2; | |
--paper-red-200: #ef9a9a; | |
--paper-red-300: #e57373; | |
--paper-red-400: #ef5350; | |
--paper-red-500: #f44336; | |
--paper-red-600: #e53935; | |
--paper-red-700: #d32f2f; | |
--paper-red-800: #c62828; | |
--paper-red-900: #b71c1c; | |
--paper-red-a100: #ff8a80; | |
--paper-red-a200: #ff5252; | |
--paper-red-a400: #ff1744; | |
--paper-red-a700: #d50000; | |
--paper-pink-50: #fce4ec; | |
--paper-pink-100: #f8bbd0; | |
--paper-pink-200: #f48fb1; | |
--paper-pink-300: #f06292; | |
--paper-pink-400: #ec407a; | |
--paper-pink-500: #e91e63; | |
--paper-pink-600: #d81b60; | |
--paper-pink-700: #c2185b; | |
--paper-pink-800: #ad1457; | |
--paper-pink-900: #880e4f; | |
--paper-pink-a100: #ff80ab; | |
--paper-pink-a200: #ff4081; | |
--paper-pink-a400: #f50057; | |
--paper-pink-a700: #c51162; | |
--paper-purple-50: #f3e5f5; | |
--paper-purple-100: #e1bee7; | |
--paper-purple-200: #ce93d8; | |
--paper-purple-300: #ba68c8; | |
--paper-purple-400: #ab47bc; | |
--paper-purple-500: #9c27b0; | |
--paper-purple-600: #8e24aa; | |
--paper-purple-700: #7b1fa2; | |
--paper-purple-800: #6a1b9a; | |
--paper-purple-900: #4a148c; | |
--paper-purple-a100: #ea80fc; | |
--paper-purple-a200: #e040fb; | |
--paper-purple-a400: #d500f9; | |
--paper-purple-a700: #aa00ff; | |
--paper-deep-purple-50: #ede7f6; | |
--paper-deep-purple-100: #d1c4e9; | |
--paper-deep-purple-200: #b39ddb; | |
--paper-deep-purple-300: #9575cd; | |
--paper-deep-purple-400: #7e57c2; | |
--paper-deep-purple-500: #673ab7; | |
--paper-deep-purple-600: #5e35b1; | |
--paper-deep-purple-700: #512da8; | |
--paper-deep-purple-800: #4527a0; | |
--paper-deep-purple-900: #311b92; | |
--paper-deep-purple-a100: #b388ff; | |
--paper-deep-purple-a200: #7c4dff; | |
--paper-deep-purple-a400: #651fff; | |
--paper-deep-purple-a700: #6200ea; | |
--paper-indigo-50: #e8eaf6; | |
--paper-indigo-100: #c5cae9; | |
--paper-indigo-200: #9fa8da; | |
--paper-indigo-300: #7986cb; | |
--paper-indigo-400: #5c6bc0; | |
--paper-indigo-500: #3f51b5; | |
--paper-indigo-600: #3949ab; | |
--paper-indigo-700: #303f9f; | |
--paper-indigo-800: #283593; | |
--paper-indigo-900: #1a237e; | |
--paper-indigo-a100: #8c9eff; | |
--paper-indigo-a200: #536dfe; | |
--paper-indigo-a400: #3d5afe; | |
--paper-indigo-a700: #304ffe; | |
--paper-blue-50: #e3f2fd; | |
--paper-blue-100: #bbdefb; | |
--paper-blue-200: #90caf9; | |
--paper-blue-300: #64b5f6; | |
--paper-blue-400: #42a5f5; | |
--paper-blue-500: #2196f3; | |
--paper-blue-600: #1e88e5; | |
--paper-blue-700: #1976d2; | |
--paper-blue-800: #1565c0; | |
--paper-blue-900: #0d47a1; | |
--paper-blue-a100: #82b1ff; | |
--paper-blue-a200: #448aff; | |
--paper-blue-a400: #2979ff; | |
--paper-blue-a700: #2962ff; | |
--paper-light-blue-50: #e1f5fe; | |
--paper-light-blue-100: #b3e5fc; | |
--paper-light-blue-200: #81d4fa; | |
--paper-light-blue-300: #4fc3f7; | |
--paper-light-blue-400: #29b6f6; | |
--paper-light-blue-500: #03a9f4; | |
--paper-light-blue-600: #039be5; | |
--paper-light-blue-700: #0288d1; | |
--paper-light-blue-800: #0277bd; | |
--paper-light-blue-900: #01579b; | |
--paper-light-blue-a100: #80d8ff; | |
--paper-light-blue-a200: #40c4ff; | |
--paper-light-blue-a400: #00b0ff; | |
--paper-light-blue-a700: #0091ea; | |
--paper-cyan-50: #e0f7fa; | |
--paper-cyan-100: #b2ebf2; | |
--paper-cyan-200: #80deea; | |
--paper-cyan-300: #4dd0e1; | |
--paper-cyan-400: #26c6da; | |
--paper-cyan-500: #00bcd4; | |
--paper-cyan-600: #00acc1; | |
--paper-cyan-700: #0097a7; | |
--paper-cyan-800: #00838f; | |
--paper-cyan-900: #006064; | |
--paper-cyan-a100: #84ffff; | |
--paper-cyan-a200: #18ffff; | |
--paper-cyan-a400: #00e5ff; | |
--paper-cyan-a700: #00b8d4; | |
--paper-teal-50: #e0f2f1; | |
--paper-teal-100: #b2dfdb; | |
--paper-teal-200: #80cbc4; | |
--paper-teal-300: #4db6ac; | |
--paper-teal-400: #26a69a; | |
--paper-teal-500: #009688; | |
--paper-teal-600: #00897b; | |
--paper-teal-700: #00796b; | |
--paper-teal-800: #00695c; | |
--paper-teal-900: #004d40; | |
--paper-teal-a100: #a7ffeb; | |
--paper-teal-a200: #64ffda; | |
--paper-teal-a400: #1de9b6; | |
--paper-teal-a700: #00bfa5; | |
--paper-green-50: #e8f5e9; | |
--paper-green-100: #c8e6c9; | |
--paper-green-200: #a5d6a7; | |
--paper-green-300: #81c784; | |
--paper-green-400: #66bb6a; | |
--paper-green-500: #4caf50; | |
--paper-green-600: #43a047; | |
--paper-green-700: #388e3c; | |
--paper-green-800: #2e7d32; | |
--paper-green-900: #1b5e20; | |
--paper-green-a100: #b9f6ca; | |
--paper-green-a200: #69f0ae; | |
--paper-green-a400: #00e676; | |
--paper-green-a700: #00c853; | |
--paper-light-green-50: #f1f8e9; | |
--paper-light-green-100: #dcedc8; | |
--paper-light-green-200: #c5e1a5; | |
--paper-light-green-300: #aed581; | |
--paper-light-green-400: #9ccc65; | |
--paper-light-green-500: #8bc34a; | |
--paper-light-green-600: #7cb342; | |
--paper-light-green-700: #689f38; | |
--paper-light-green-800: #558b2f; | |
--paper-light-green-900: #33691e; | |
--paper-light-green-a100: #ccff90; | |
--paper-light-green-a200: #b2ff59; | |
--paper-light-green-a400: #76ff03; | |
--paper-light-green-a700: #64dd17; | |
--paper-lime-50: #f9fbe7; | |
--paper-lime-100: #f0f4c3; | |
--paper-lime-200: #e6ee9c; | |
--paper-lime-300: #dce775; | |
--paper-lime-400: #d4e157; | |
--paper-lime-500: #cddc39; | |
--paper-lime-600: #c0ca33; | |
--paper-lime-700: #afb42b; | |
--paper-lime-800: #9e9d24; | |
--paper-lime-900: #827717; | |
--paper-lime-a100: #f4ff81; | |
--paper-lime-a200: #eeff41; | |
--paper-lime-a400: #c6ff00; | |
--paper-lime-a700: #aeea00; | |
--paper-yellow-50: #fffde7; | |
--paper-yellow-100: #fff9c4; | |
--paper-yellow-200: #fff59d; | |
--paper-yellow-300: #fff176; | |
--paper-yellow-400: #ffee58; | |
--paper-yellow-500: #ffeb3b; | |
--paper-yellow-600: #fdd835; | |
--paper-yellow-700: #fbc02d; | |
--paper-yellow-800: #f9a825; | |
--paper-yellow-900: #f57f17; | |
--paper-yellow-a100: #ffff8d; | |
--paper-yellow-a200: #ffff00; | |
--paper-yellow-a400: #ffea00; | |
--paper-yellow-a700: #ffd600; | |
--paper-amber-50: #fff8e1; | |
--paper-amber-100: #ffecb3; | |
--paper-amber-200: #ffe082; | |
--paper-amber-300: #ffd54f; | |
--paper-amber-400: #ffca28; | |
--paper-amber-500: #ffc107; | |
--paper-amber-600: #ffb300; | |
--paper-amber-700: #ffa000; | |
--paper-amber-800: #ff8f00; | |
--paper-amber-900: #ff6f00; | |
--paper-amber-a100: #ffe57f; | |
--paper-amber-a200: #ffd740; | |
--paper-amber-a400: #ffc400; | |
--paper-amber-a700: #ffab00; | |
--paper-orange-50: #fff3e0; | |
--paper-orange-100: #ffe0b2; | |
--paper-orange-200: #ffcc80; | |
--paper-orange-300: #ffb74d; | |
--paper-orange-400: #ffa726; | |
--paper-orange-500: #ff9800; | |
--paper-orange-600: #fb8c00; | |
--paper-orange-700: #f57c00; | |
--paper-orange-800: #ef6c00; | |
--paper-orange-900: #e65100; | |
--paper-orange-a100: #ffd180; | |
--paper-orange-a200: #ffab40; | |
--paper-orange-a400: #ff9100; | |
--paper-orange-a700: #ff6500; | |
--paper-deep-orange-50: #fbe9e7; | |
--paper-deep-orange-100: #ffccbc; | |
--paper-deep-orange-200: #ffab91; | |
--paper-deep-orange-300: #ff8a65; | |
--paper-deep-orange-400: #ff7043; | |
--paper-deep-orange-500: #ff5722; | |
--paper-deep-orange-600: #f4511e; | |
--paper-deep-orange-700: #e64a19; | |
--paper-deep-orange-800: #d84315; | |
--paper-deep-orange-900: #bf360c; | |
--paper-deep-orange-a100: #ff9e80; | |
--paper-deep-orange-a200: #ff6e40; | |
--paper-deep-orange-a400: #ff3d00; | |
--paper-deep-orange-a700: #dd2c00; | |
--paper-brown-50: #efebe9; | |
--paper-brown-100: #d7ccc8; | |
--paper-brown-200: #bcaaa4; | |
--paper-brown-300: #a1887f; | |
--paper-brown-400: #8d6e63; | |
--paper-brown-500: #795548; | |
--paper-brown-600: #6d4c41; | |
--paper-brown-700: #5d4037; | |
--paper-brown-800: #4e342e; | |
--paper-brown-900: #3e2723; | |
--paper-grey-50: #fafafa; | |
--paper-grey-100: #f5f5f5; | |
--paper-grey-200: #eeeeee; | |
--paper-grey-300: #e0e0e0; | |
--paper-grey-400: #bdbdbd; | |
--paper-grey-500: #9e9e9e; | |
--paper-grey-600: #757575; | |
--paper-grey-700: #616161; | |
--paper-grey-800: #424242; | |
--paper-grey-900: #212121; | |
--paper-blue-grey-50: #eceff1; | |
--paper-blue-grey-100: #cfd8dc; | |
--paper-blue-grey-200: #b0bec5; | |
--paper-blue-grey-300: #90a4ae; | |
--paper-blue-grey-400: #78909c; | |
--paper-blue-grey-500: #607d8b; | |
--paper-blue-grey-600: #546e7a; | |
--paper-blue-grey-700: #455a64; | |
--paper-blue-grey-800: #37474f; | |
--paper-blue-grey-900: #263238; | |
/* opacity for dark text on a light background */ | |
--dark-divider-opacity: 0.12; | |
--dark-disabled-opacity: 0.38; /* or hint text or icon */ | |
--dark-secondary-opacity: 0.54; | |
--dark-primary-opacity: 0.87; | |
/* opacity for light text on a dark background */ | |
--light-divider-opacity: 0.12; | |
--light-disabled-opacity: 0.3; /* or hint text or icon */ | |
--light-secondary-opacity: 0.7; | |
--light-primary-opacity: 1.0; | |
} | |
</style> | |
<!-- | |
Material design: [Menus](https://www.google.com/design/spec/components/menus.html) | |
`<paper-menu>` implements an accessible menu control with Material Design styling. The focused item | |
is highlighted, and the selected item has bolded text. | |
<paper-menu> | |
<paper-item>Item 1</paper-item> | |
<paper-item>Item 2</paper-item> | |
</paper-menu> | |
An initial selection can be specified with the `selected` attribute. | |
<paper-menu selected="0"> | |
<paper-item>Item 1</paper-item> | |
<paper-item>Item 2</paper-item> | |
</paper-menu> | |
Make a multi-select menu with the `multi` attribute. Items in a multi-select menu can be deselected, | |
and multiple items can be selected. | |
<paper-menu multi> | |
<paper-item>Item 1</paper-item> | |
<paper-item>Item 2</paper-item> | |
</paper-menu> | |
### Styling | |
The following custom properties and mixins are available for styling: | |
Custom property | Description | Default | |
----------------|-------------|---------- | |
`--paper-menu-background-color` | Menu background color | `--primary-background-color` | |
`--paper-menu-color` | Menu foreground color | `--primary-text-color` | |
`--paper-menu-disabled-color` | Foreground color for a disabled item | `--disabled-text-color` | |
`--paper-menu` | Mixin applied to the menu | `{}` | |
`--paper-menu-selected-item` | Mixin applied to the selected item | `{}` | |
`--paper-menu-focused-item` | Mixin applied to the focused item | `{}` | |
`--paper-menu-focused-item-after` | Mixin applied to the ::after pseudo-element for the focused item | `{}` | |
### Accessibility | |
`<paper-menu>` has `role="menu"` by default. A multi-select menu will also have | |
`aria-multiselectable` set. It implements key bindings to navigate through the menu with the up and | |
down arrow keys, esc to exit the menu, and enter to activate a menu item. Typing the first letter | |
of a menu item will also focus it. | |
@group Paper Elements | |
@element paper-menu | |
@hero hero.svg | |
@demo demo/index.html | |
--> | |
<script> | |
/** | |
* @demo demo/index.html | |
* @polymerBehavior | |
*/ | |
Polymer.IronControlState = { | |
properties: { | |
/** | |
* If true, the element currently has focus. | |
*/ | |
focused: { | |
type: Boolean, | |
value: false, | |
notify: true, | |
readOnly: true, | |
reflectToAttribute: true | |
}, | |
/** | |
* If true, the user cannot interact with this element. | |
*/ | |
disabled: { | |
type: Boolean, | |
value: false, | |
notify: true, | |
observer: '_disabledChanged', | |
reflectToAttribute: true | |
}, | |
_oldTabIndex: { | |
type: Number | |
}, | |
_boundFocusBlurHandler: { | |
type: Function, | |
value: function() { | |
return this._focusBlurHandler.bind(this); | |
} | |
} | |
}, | |
observers: [ | |
'_changedControlState(focused, disabled)' | |
], | |
ready: function() { | |
this.addEventListener('focus', this._boundFocusBlurHandler, true); | |
this.addEventListener('blur', this._boundFocusBlurHandler, true); | |
}, | |
_focusBlurHandler: function(event) { | |
// NOTE(cdata): if we are in ShadowDOM land, `event.target` will | |
// eventually become `this` due to retargeting; if we are not in | |
// ShadowDOM land, `event.target` will eventually become `this` due | |
// to the second conditional which fires a synthetic event (that is also | |
// handled). In either case, we can disregard `event.path`. | |
if (event.target === this) { | |
this._setFocused(event.type === 'focus'); | |
} else if (!this.shadowRoot && !this.isLightDescendant(event.target)) { | |
this.fire(event.type, {sourceEvent: event}, { | |
node: this, | |
bubbles: event.bubbles, | |
cancelable: event.cancelable | |
}); | |
} | |
}, | |
_disabledChanged: function(disabled, old) { | |
this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); | |
this.style.pointerEvents = disabled ? 'none' : ''; | |
if (disabled) { | |
this._oldTabIndex = this.tabIndex; | |
this.focused = false; | |
this.tabIndex = -1; | |
} else if (this._oldTabIndex !== undefined) { | |
this.tabIndex = this._oldTabIndex; | |
} | |
}, | |
_changedControlState: function() { | |
// _controlStateChanged is abstract, follow-on behaviors may implement it | |
if (this._controlStateChanged) { | |
this._controlStateChanged(); | |
} | |
} | |
}; | |
</script> | |
<script> | |
/** | |
* @demo demo/index.html | |
* @polymerBehavior Polymer.IronButtonState | |
*/ | |
Polymer.IronButtonStateImpl = { | |
properties: { | |
/** | |
* If true, the user is currently holding down the button. | |
*/ | |
pressed: { | |
type: Boolean, | |
readOnly: true, | |
value: false, | |
reflectToAttribute: true, | |
observer: '_pressedChanged' | |
}, | |
/** | |
* If true, the button toggles the active state with each tap or press | |
* of the spacebar. | |
*/ | |
toggles: { | |
type: Boolean, | |
value: false, | |
reflectToAttribute: true | |
}, | |
/** | |
* If true, the button is a toggle and is currently in the active state. | |
*/ | |
active: { | |
type: Boolean, | |
value: false, | |
notify: true, | |
reflectToAttribute: true | |
}, | |
/** | |
* True if the element is currently being pressed by a "pointer," which | |
* is loosely defined as mouse or touch input (but specifically excluding | |
* keyboard input). | |
*/ | |
pointerDown: { | |
type: Boolean, | |
readOnly: true, | |
value: false | |
}, | |
/** | |
* True if the input device that caused the element to receive focus | |
* was a keyboard. | |
*/ | |
receivedFocusFromKeyboard: { | |
type: Boolean, | |
readOnly: true | |
}, | |
/** | |
* The aria attribute to be set if the button is a toggle and in the | |
* active state. | |
*/ | |
ariaActiveAttribute: { | |
type: String, | |
value: 'aria-pressed', | |
observer: '_ariaActiveAttributeChanged' | |
} | |
}, | |
listeners: { | |
down: '_downHandler', | |
up: '_upHandler', | |
tap: '_tapHandler' | |
}, | |
observers: [ | |
'_detectKeyboardFocus(focused)', | |
'_activeChanged(active, ariaActiveAttribute)' | |
], | |
keyBindings: { | |
'enter:keydown': '_asyncClick', | |
'space:keydown': '_spaceKeyDownHandler', | |
'space:keyup': '_spaceKeyUpHandler', | |
}, | |
_mouseEventRe: /^mouse/, | |
_tapHandler: function() { | |
if (this.toggles) { | |
// a tap is needed to toggle the active state | |
this._userActivate(!this.active); | |
} else { | |
this.active = false; | |
} | |
}, | |
_detectKeyboardFocus: function(focused) { | |
this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); | |
}, | |
// to emulate native checkbox, (de-)activations from a user interaction fire | |
// 'change' events | |
_userActivate: function(active) { | |
if (this.active !== active) { | |
this.active = active; | |
this.fire('change'); | |
} | |
}, | |
_downHandler: function(event) { | |
this._setPointerDown(true); | |
this._setPressed(true); | |
this._setReceivedFocusFromKeyboard(false); | |
}, | |
_upHandler: function() { | |
this._setPointerDown(false); | |
this._setPressed(false); | |
}, | |
/** | |
* @param {!KeyboardEvent} event . | |
*/ | |
_spaceKeyDownHandler: function(event) { | |
var keyboardEvent = event.detail.keyboardEvent; | |
var target = Polymer.dom(keyboardEvent).localTarget; | |
// Ignore the event if this is coming from a focused light child, since that | |
// element will deal with it. | |
if (this.isLightDescendant(/** @type {Node} */(target))) | |
return; | |
keyboardEvent.preventDefault(); | |
keyboardEvent.stopImmediatePropagation(); | |
this._setPressed(true); | |
}, | |
/** | |
* @param {!KeyboardEvent} event . | |
*/ | |
_spaceKeyUpHandler: function(event) { | |
var keyboardEvent = event.detail.keyboardEvent; | |
var target = Polymer.dom(keyboardEvent).localTarget; | |
// Ignore the event if this is coming from a focused light child, since that | |
// element will deal with it. | |
if (this.isLightDescendant(/** @type {Node} */(target))) | |
return; | |
if (this.pressed) { | |
this._asyncClick(); | |
} | |
this._setPressed(false); | |
}, | |
// trigger click asynchronously, the asynchrony is useful to allow one | |
// event handler to unwind before triggering another event | |
_asyncClick: function() { | |
this.async(function() { | |
this.click(); | |
}, 1); | |
}, | |
// any of these changes are considered a change to button state | |
_pressedChanged: function(pressed) { | |
this._changedButtonState(); | |
}, | |
_ariaActiveAttributeChanged: function(value, oldValue) { | |
if (oldValue && oldValue != value && this.hasAttribute(oldValue)) { | |
this.removeAttribute(oldValue); | |
} | |
}, | |
_activeChanged: function(active, ariaActiveAttribute) { | |
if (this.toggles) { | |
this.setAttribute(this.ariaActiveAttribute, | |
active ? 'true' : 'false'); | |
} else { | |
this.removeAttribute(this.ariaActiveAttribute); | |
} | |
this._changedButtonState(); | |
}, | |
_controlStateChanged: function() { | |
if (this.disabled) { | |
this._setPressed(false); | |
} else { | |
this._changedButtonState(); | |
} | |
}, | |
// provide hook for follow-on behaviors to react to button-state | |
_changedButtonState: function() { | |
if (this._buttonStateChanged) { | |
this._buttonStateChanged(); // abstract | |
} | |
} | |
}; | |
/** @polymerBehavior */ | |
Polymer.IronButtonState = [ | |
Polymer.IronA11yKeysBehavior, | |
Polymer.IronButtonStateImpl | |
]; | |
</script> | |
<!-- | |
`PaperItemBehavior` is a convenience behavior shared by <paper-item> and | |
<paper-icon-item> that manages the shared control states and attributes of | |
the items. | |
--> | |
<script> | |
/** @polymerBehavior Polymer.PaperItemBehavior */ | |
Polymer.PaperItemBehaviorImpl = { | |
hostAttributes: { | |
role: 'option', | |
tabindex: '0' | |
} | |
}; | |
/** @polymerBehavior */ | |
Polymer.PaperItemBehavior = [ | |
Polymer.IronButtonState, | |
Polymer.IronControlState, | |
Polymer.PaperItemBehaviorImpl | |
]; | |
</script> | |
<!-- | |
Material design: [Lists](https://www.google.com/design/spec/components/lists.html) | |
`<paper-item>` is an interactive list item. By default, it is a horizontal flexbox. | |
<paper-item>Item</paper-item> | |
Use this element with `<paper-item-body>` to make Material Design styled two-line and three-line | |
items. | |
<paper-item> | |
<paper-item-body two-line> | |
<div>Show your status</div> | |
<div secondary>Your status is visible to everyone</div> | |
</paper-item-body> | |
<iron-icon icon="warning"></iron-icon> | |
</paper-item> | |
### Styling | |
The following custom properties and mixins are available for styling: | |
Custom property | Description | Default | |
------------------------------|----------------------------------------------|---------- | |
`--paper-item-min-height` | Minimum height of the item | `48px` | |
`--paper-item` | Mixin applied to the item | `{}` | |
`--paper-item-selected-weight`| The font weight of a selected item | `bold` | |
`--paper-item-selected` | Mixin applied to selected paper-items | `{}` | |
`--paper-item-disabled-color` | The color for disabled paper-items | `--disabled-text-color` | |
`--paper-item-disabled` | Mixin applied to disabled paper-items | `{}` | |
`--paper-item-focused` | Mixin applied to focused paper-items | `{}` | |
`--paper-item-focused-before` | Mixin applied to :before focused paper-items | `{}` | |
### Accessibility | |
This element has `role="listitem"` by default. Depending on usage, it may be more appropriate to set | |
`role="menuitem"`, `role="menuitemcheckbox"` or `role="menuitemradio"`. | |
<paper-item role="menuitemcheckbox"> | |
<paper-item-body> | |
Show your status | |
</paper-item-body> | |
<paper-checkbox></paper-checkbox> | |
</paper-item> | |
@group Paper Elements | |
@element paper-item | |
@demo demo/index.html | |
--> | |
<script> | |
/** | |
Polymer.IronFormElementBehavior enables a custom element to be included | |
in an `iron-form`. | |
@demo demo/index.html | |
@polymerBehavior | |
*/ | |
Polymer.IronFormElementBehavior = { | |
properties: { | |
/** | |
* Fired when the element is added to an `iron-form`. | |
* | |
* @event iron-form-element-register | |
*/ | |
/** | |
* Fired when the element is removed from an `iron-form`. | |
* | |
* @event iron-form-element-unregister | |
*/ | |
/** | |
* The name of this element. | |
*/ | |
name: { | |
type: String | |
}, | |
/** | |
* The value for this element. | |
*/ | |
value: { | |
notify: true, | |
type: String | |
}, | |
/** | |
* Set to true to mark the input as required. If used in a form, a | |
* custom element that uses this behavior should also use | |
* Polymer.IronValidatableBehavior and define a custom validation method. | |
* Otherwise, a `required` element will always be considered valid. | |
* It's also strongly recommended to provide a visual style for the element | |
* when its value is invalid. | |
*/ | |
required: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* The form that the element is registered to. | |
*/ | |
_parentForm: { | |
type: Object | |
} | |
}, | |
attached: function() { | |
// Note: the iron-form that this element belongs to will set this | |
// element's _parentForm property when handling this event. | |
this.fire('iron-form-element-register'); | |
}, | |
detached: function() { | |
if (this._parentForm) { | |
this._parentForm.fire('iron-form-element-unregister', {target: this}); | |
} | |
} | |
}; | |
</script> | |
<!-- | |
`iron-meta` is a generic element you can use for sharing information across the DOM tree. | |
It uses [monostate pattern](http://c2.com/cgi/wiki?MonostatePattern) such that any | |
instance of iron-meta has access to the shared | |
information. You can use `iron-meta` to share whatever you want (or create an extension | |
[like x-meta] for enhancements). | |
The `iron-meta` instances containing your actual data can be loaded in an import, | |
or constructed in any way you see fit. The only requirement is that you create them | |
before you try to access them. | |
Examples: | |
If I create an instance like this: | |
<iron-meta key="info" value="foo/bar"></iron-meta> | |
Note that value="foo/bar" is the metadata I've defined. I could define more | |
attributes or use child nodes to define additional metadata. | |
Now I can access that element (and it's metadata) from any iron-meta instance | |
via the byKey method, e.g. | |
meta.byKey('info').getAttribute('value'); | |
Pure imperative form would be like: | |
document.createElement('iron-meta').byKey('info').getAttribute('value'); | |
Or, in a Polymer element, you can include a meta in your template: | |
<iron-meta id="meta"></iron-meta> | |
... | |
this.$.meta.byKey('info').getAttribute('value'); | |
@group Iron Elements | |
@demo demo/index.html | |
@hero hero.svg | |
@element iron-meta | |
--> | |
<script> | |
(function() { | |
// monostate data | |
var metaDatas = {}; | |
var metaArrays = {}; | |
var singleton = null; | |
Polymer.IronMeta = Polymer({ | |
is: 'iron-meta', | |
properties: { | |
/** | |
* The type of meta-data. All meta-data of the same type is stored | |
* together. | |
*/ | |
type: { | |
type: String, | |
value: 'default', | |
observer: '_typeChanged' | |
}, | |
/** | |
* The key used to store `value` under the `type` namespace. | |
*/ | |
key: { | |
type: String, | |
observer: '_keyChanged' | |
}, | |
/** | |
* The meta-data to store or retrieve. | |
*/ | |
value: { | |
type: Object, | |
notify: true, | |
observer: '_valueChanged' | |
}, | |
/** | |
* If true, `value` is set to the iron-meta instance itself. | |
*/ | |
self: { | |
type: Boolean, | |
observer: '_selfChanged' | |
}, | |
/** | |
* Array of all meta-data values for the given type. | |
*/ | |
list: { | |
type: Array, | |
notify: true | |
} | |
}, | |
hostAttributes: { | |
hidden: true | |
}, | |
/** | |
* Only runs if someone invokes the factory/constructor directly | |
* e.g. `new Polymer.IronMeta()` | |
* | |
* @param {{type: (string|undefined), key: (string|undefined), value}=} config | |
*/ | |
factoryImpl: function(config) { | |
if (config) { | |
for (var n in config) { | |
switch(n) { | |
case 'type': | |
case 'key': | |
case 'value': | |
this[n] = config[n]; | |
break; | |
} | |
} | |
} | |
}, | |
created: function() { | |
// TODO(sjmiles): good for debugging? | |
this._metaDatas = metaDatas; | |
this._metaArrays = metaArrays; | |
}, | |
_keyChanged: function(key, old) { | |
this._resetRegistration(old); | |
}, | |
_valueChanged: function(value) { | |
this._resetRegistration(this.key); | |
}, | |
_selfChanged: function(self) { | |
if (self) { | |
this.value = this; | |
} | |
}, | |
_typeChanged: function(type) { | |
this._unregisterKey(this.key); | |
if (!metaDatas[type]) { | |
metaDatas[type] = {}; | |
} | |
this._metaData = metaDatas[type]; | |
if (!metaArrays[type]) { | |
metaArrays[type] = []; | |
} | |
this.list = metaArrays[type]; | |
this._registerKeyValue(this.key, this.value); | |
}, | |
/** | |
* Retrieves meta data value by key. | |
* | |
* @method byKey | |
* @param {string} key The key of the meta-data to be returned. | |
* @return {*} | |
*/ | |
byKey: function(key) { | |
return this._metaData && this._metaData[key]; | |
}, | |
_resetRegistration: function(oldKey) { | |
this._unregisterKey(oldKey); | |
this._registerKeyValue(this.key, this.value); | |
}, | |
_unregisterKey: function(key) { | |
this._unregister(key, this._metaData, this.list); | |
}, | |
_registerKeyValue: function(key, value) { | |
this._register(key, value, this._metaData, this.list); | |
}, | |
_register: function(key, value, data, list) { | |
if (key && data && value !== undefined) { | |
data[key] = value; | |
list.push(value); | |
} | |
}, | |
_unregister: function(key, data, list) { | |
if (key && data) { | |
if (key in data) { | |
var value = data[key]; | |
delete data[key]; | |
this.arrayDelete(list, value); | |
} | |
} | |
} | |
}); | |
Polymer.IronMeta.getIronMeta = function getIronMeta() { | |
if (singleton === null) { | |
singleton = new Polymer.IronMeta(); | |
} | |
return singleton; | |
}; | |
/** | |
`iron-meta-query` can be used to access infomation stored in `iron-meta`. | |
Examples: | |
If I create an instance like this: | |
<iron-meta key="info" value="foo/bar"></iron-meta> | |
Note that value="foo/bar" is the metadata I've defined. I could define more | |
attributes or use child nodes to define additional metadata. | |
Now I can access that element (and it's metadata) from any `iron-meta-query` instance: | |
var value = new Polymer.IronMetaQuery({key: 'info'}).value; | |
@group Polymer Iron Elements | |
@element iron-meta-query | |
*/ | |
Polymer.IronMetaQuery = Polymer({ | |
is: 'iron-meta-query', | |
properties: { | |
/** | |
* The type of meta-data. All meta-data of the same type is stored | |
* together. | |
*/ | |
type: { | |
type: String, | |
value: 'default', | |
observer: '_typeChanged' | |
}, | |
/** | |
* Specifies a key to use for retrieving `value` from the `type` | |
* namespace. | |
*/ | |
key: { | |
type: String, | |
observer: '_keyChanged' | |
}, | |
/** | |
* The meta-data to store or retrieve. | |
*/ | |
value: { | |
type: Object, | |
notify: true, | |
readOnly: true | |
}, | |
/** | |
* Array of all meta-data values for the given type. | |
*/ | |
list: { | |
type: Array, | |
notify: true | |
} | |
}, | |
/** | |
* Actually a factory method, not a true constructor. Only runs if | |
* someone invokes it directly (via `new Polymer.IronMeta()`); | |
* | |
* @param {{type: (string|undefined), key: (string|undefined)}=} config | |
*/ | |
factoryImpl: function(config) { | |
if (config) { | |
for (var n in config) { | |
switch(n) { | |
case 'type': | |
case 'key': | |
this[n] = config[n]; | |
break; | |
} | |
} | |
} | |
}, | |
created: function() { | |
// TODO(sjmiles): good for debugging? | |
this._metaDatas = metaDatas; | |
this._metaArrays = metaArrays; | |
}, | |
_keyChanged: function(key) { | |
this._setValue(this._metaData && this._metaData[key]); | |
}, | |
_typeChanged: function(type) { | |
this._metaData = metaDatas[type]; | |
this.list = metaArrays[type]; | |
if (this.key) { | |
this._keyChanged(this.key); | |
} | |
}, | |
/** | |
* Retrieves meta data value by key. | |
* @param {string} key The key of the meta-data to be returned. | |
* @return {*} | |
*/ | |
byKey: function(key) { | |
return this._metaData && this._metaData[key]; | |
} | |
}); | |
})(); | |
</script> | |
<script> | |
/** | |
* `Use Polymer.IronValidatableBehavior` to implement an element that validates user input. | |
* Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input. | |
* | |
* By default, an `<iron-form>` element validates its fields when the user presses the submit button. | |
* To validate a form imperatively, call the form's `validate()` method, which in turn will | |
* call `validate()` on all its children. By using `Polymer.IronValidatableBehavior`, your | |
* custom element will get a public `validate()`, which | |
* will return the validity of the element, and a corresponding `invalid` attribute, | |
* which can be used for styling. | |
* | |
* To implement the custom validation logic of your element, you must override | |
* the protected `_getValidity()` method of this behaviour, rather than `validate()`. | |
* See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/simple-element.html) | |
* for an example. | |
* | |
* ### Accessibility | |
* | |
* Changing the `invalid` property, either manually or by calling `validate()` will update the | |
* `aria-invalid` attribute. | |
* | |
* @demo demo/index.html | |
* @polymerBehavior | |
*/ | |
Polymer.IronValidatableBehavior = { | |
properties: { | |
/** | |
* Namespace for this validator. | |
*/ | |
validatorType: { | |
type: String, | |
value: 'validator' | |
}, | |
/** | |
* Name of the validator to use. | |
*/ | |
validator: { | |
type: String | |
}, | |
/** | |
* True if the last call to `validate` is invalid. | |
*/ | |
invalid: { | |
notify: true, | |
reflectToAttribute: true, | |
type: Boolean, | |
value: false | |
}, | |
_validatorMeta: { | |
type: Object | |
} | |
}, | |
observers: [ | |
'_invalidChanged(invalid)' | |
], | |
get _validator() { | |
return this._validatorMeta && this._validatorMeta.byKey(this.validator); | |
}, | |
ready: function() { | |
this._validatorMeta = new Polymer.IronMeta({type: this.validatorType}); | |
}, | |
_invalidChanged: function() { | |
if (this.invalid) { | |
this.setAttribute('aria-invalid', 'true'); | |
} else { | |
this.removeAttribute('aria-invalid'); | |
} | |
}, | |
/** | |
* @return {boolean} True if the validator `validator` exists. | |
*/ | |
hasValidator: function() { | |
return this._validator != null; | |
}, | |
/** | |
* Returns true if the `value` is valid, and updates `invalid`. If you want | |
* your element to have custom validation logic, do not override this method; | |
* override `_getValidity(value)` instead. | |
* @param {Object} value The value to be validated. By default, it is passed | |
* to the validator's `validate()` function, if a validator is set. | |
* @return {boolean} True if `value` is valid. | |
*/ | |
validate: function(value) { | |
this.invalid = !this._getValidity(value); | |
return !this.invalid; | |
}, | |
/** | |
* Returns true if `value` is valid. By default, it is passed | |
* to the validator's `validate()` function, if a validator is set. You | |
* should override this method if you want to implement custom validity | |
* logic for your element. | |
* | |
* @param {Object} value The value to be validated. | |
* @return {boolean} True if `value` is valid. | |
*/ | |
_getValidity: function(value) { | |
if (this.hasValidator()) { | |
return this._validator.validate(value); | |
} | |
return true; | |
} | |
}; | |
</script> | |
<script> | |
/* | |
`<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior` | |
to `<input>`. | |
### Two-way binding | |
By default you can only get notified of changes to an `input`'s `value` due to user input: | |
<input value="{{myValue::input}}"> | |
`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used | |
for two-way data binding. `bind-value` will notify if it is changed either by user input or by script. | |
<input is="iron-input" bind-value="{{myValue}}"> | |
### Custom validators | |
You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`. | |
<input is="iron-input" validator="my-custom-validator"> | |
### Stopping invalid input | |
It may be desirable to only allow users to enter certain characters. You can use the | |
`prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature | |
is separate from validation, and `allowed-pattern` does not affect how the input is validated. | |
<!-- only allow characters that match [0-9] --> | |
<input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> | |
@hero hero.svg | |
@demo demo/index.html | |
*/ | |
Polymer({ | |
is: 'iron-input', | |
extends: 'input', | |
behaviors: [ | |
Polymer.IronValidatableBehavior | |
], | |
properties: { | |
/** | |
* Use this property instead of `value` for two-way data binding. | |
*/ | |
bindValue: { | |
observer: '_bindValueChanged', | |
type: String | |
}, | |
/** | |
* Set to true to prevent the user from entering invalid input. The new input characters are | |
* matched with `allowedPattern` if it is set, otherwise it will use the `type` attribute (only | |
* supported for `type=number`). | |
*/ | |
preventInvalidInput: { | |
type: Boolean | |
}, | |
/** | |
* Regular expression expressing a set of characters to enforce the validity of input characters. | |
* The recommended value should follow this format: `[a-ZA-Z0-9.+-!;:]` that list the characters | |
* allowed as input. | |
*/ | |
allowedPattern: { | |
type: String, | |
observer: "_allowedPatternChanged" | |
}, | |
_previousValidInput: { | |
type: String, | |
value: '' | |
}, | |
_patternAlreadyChecked: { | |
type: Boolean, | |
value: false | |
} | |
}, | |
listeners: { | |
'input': '_onInput', | |
'keypress': '_onKeypress' | |
}, | |
get _patternRegExp() { | |
var pattern; | |
if (this.allowedPattern) { | |
pattern = new RegExp(this.allowedPattern); | |
} else { | |
switch (this.type) { | |
case 'number': | |
pattern = /[0-9.,e-]/; | |
break; | |
} | |
} | |
return pattern; | |
}, | |
ready: function() { | |
this.bindValue = this.value; | |
}, | |
/** | |
* @suppress {checkTypes} | |
*/ | |
_bindValueChanged: function() { | |
if (this.value !== this.bindValue) { | |
this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue === false) ? '' : this.bindValue; | |
} | |
// manually notify because we don't want to notify until after setting value | |
this.fire('bind-value-changed', {value: this.bindValue}); | |
}, | |
_allowedPatternChanged: function() { | |
// Force to prevent invalid input when an `allowed-pattern` is set | |
this.preventInvalidInput = this.allowedPattern ? true : false; | |
}, | |
_onInput: function() { | |
// Need to validate each of the characters pasted if they haven't | |
// been validated inside `_onKeypress` already. | |
if (this.preventInvalidInput && !this._patternAlreadyChecked) { | |
var valid = this._checkPatternValidity(); | |
if (!valid) { | |
this.value = this._previousValidInput; | |
} | |
} | |
this.bindValue = this.value; | |
this._previousValidInput = this.value; | |
this._patternAlreadyChecked = false; | |
}, | |
_isPrintable: function(event) { | |
// What a control/printable character is varies wildly based on the browser. | |
// - most control characters (arrows, backspace) do not send a `keypress` event | |
// in Chrome, but the *do* on Firefox | |
// - in Firefox, when they do send a `keypress` event, control chars have | |
// a charCode = 0, keyCode = xx (for ex. 40 for down arrow) | |
// - printable characters always send a keypress event. | |
// - in Firefox, printable chars always have a keyCode = 0. In Chrome, the keyCode | |
// always matches the charCode. | |
// None of this makes any sense. | |
// For these keys, ASCII code == browser keycode. | |
var anyNonPrintable = | |
(event.keyCode == 8) || // backspace | |
(event.keyCode == 9) || // tab | |
(event.keyCode == 13) || // enter | |
(event.keyCode == 27); // escape | |
// For these keys, make sure it's a browser keycode and not an ASCII code. | |
var mozNonPrintable = | |
(event.keyCode == 19) || // pause | |
(event.keyCode == 20) || // caps lock | |
(event.keyCode == 45) || // insert | |
(event.keyCode == 46) || // delete | |
(event.keyCode == 144) || // num lock | |
(event.keyCode == 145) || // scroll lock | |
(event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, home, arrows | |
(event.keyCode > 111 && event.keyCode < 124); // fn keys | |
return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); | |
}, | |
_onKeypress: function(event) { | |
if (!this.preventInvalidInput && this.type !== 'number') { | |
return; | |
} | |
var regexp = this._patternRegExp; | |
if (!regexp) { | |
return; | |
} | |
// Handle special keys and backspace | |
if (event.metaKey || event.ctrlKey || event.altKey) | |
return; | |
// Check the pattern either here or in `_onInput`, but not in both. | |
this._patternAlreadyChecked = true; | |
var thisChar = String.fromCharCode(event.charCode); | |
if (this._isPrintable(event) && !regexp.test(thisChar)) { | |
event.preventDefault(); | |
} | |
}, | |
_checkPatternValidity: function() { | |
var regexp = this._patternRegExp; | |
if (!regexp) { | |
return true; | |
} | |
for (var i = 0; i < this.value.length; i++) { | |
if (!regexp.test(this.value[i])) { | |
return false; | |
} | |
} | |
return true; | |
}, | |
/** | |
* Returns true if `value` is valid. The validator provided in `validator` will be used first, | |
* then any constraints. | |
* @return {boolean} True if the value is valid. | |
*/ | |
validate: function() { | |
// Empty, non-required input is valid. | |
if (!this.required && this.value == '') { | |
this.invalid = false; | |
return true; | |
} | |
var valid; | |
if (this.hasValidator()) { | |
valid = Polymer.IronValidatableBehavior.validate.call(this, this.value); | |
} else { | |
valid = this.checkValidity(); | |
this.invalid = !valid; | |
} | |
this.fire('iron-input-validate'); | |
return valid; | |
} | |
}); | |
/* | |
The `iron-input-validate` event is fired whenever `validate()` is called. | |
@event iron-input-validate | |
*/ | |
</script> | |
<script> | |
/** | |
* Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This | |
* behavior is implemented by `<paper-input>`. It exposes a number of properties from | |
* `<paper-input-container>` and `<input is="iron-input">` and they should be bound in your | |
* template. | |
* | |
* The input element can be accessed by the `inputElement` property if you need to access | |
* properties or methods that are not exposed. | |
* @polymerBehavior Polymer.PaperInputBehavior | |
*/ | |
Polymer.PaperInputBehaviorImpl = { | |
properties: { | |
/** | |
* Fired when the input changes due to user interaction. | |
* | |
* @event change | |
*/ | |
/** | |
* The label for this input. Bind this to `<label>`'s content and `hidden` property, e.g. | |
* `<label hidden$="[[!label]]">[[label]]</label>` in your `template` | |
*/ | |
label: { | |
type: String | |
}, | |
/** | |
* The value for this input. Bind this to the `<input is="iron-input">`'s `bindValue` | |
* property, or the value property of your input that is `notify:true`. | |
*/ | |
value: { | |
notify: true, | |
type: String | |
}, | |
/** | |
* Set to true to disable this input. Bind this to both the `<paper-input-container>`'s | |
* and the input's `disabled` property. | |
*/ | |
disabled: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Returns true if the value is invalid. Bind this to both the `<paper-input-container>`'s | |
* and the input's `invalid` property. | |
* | |
* If `autoValidate` is true, the `invalid` attribute is managed automatically, | |
* which can clobber attempts to manage it manually. | |
*/ | |
invalid: { | |
type: Boolean, | |
value: false, | |
notify: true | |
}, | |
/** | |
* Set to true to prevent the user from entering invalid input. Bind this to the | |
* `<input is="iron-input">`'s `preventInvalidInput` property. | |
*/ | |
preventInvalidInput: { | |
type: Boolean | |
}, | |
/** | |
* Set this to specify the pattern allowed by `preventInvalidInput`. Bind this to the | |
* `<input is="iron-input">`'s `allowedPattern` property. | |
*/ | |
allowedPattern: { | |
type: String | |
}, | |
/** | |
* The type of the input. The supported types are `text`, `number` and `password`. Bind this | |
* to the `<input is="iron-input">`'s `type` property. | |
*/ | |
type: { | |
type: String | |
}, | |
/** | |
* The datalist of the input (if any). This should match the id of an existing `<datalist>`. Bind this | |
* to the `<input is="iron-input">`'s `list` property. | |
*/ | |
list: { | |
type: String | |
}, | |
/** | |
* A pattern to validate the `input` with. Bind this to the `<input is="iron-input">`'s | |
* `pattern` property. | |
*/ | |
pattern: { | |
type: String | |
}, | |
/** | |
* Set to true to mark the input as required. Bind this to the `<input is="iron-input">`'s | |
* `required` property. | |
*/ | |
required: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* The error message to display when the input is invalid. Bind this to the | |
* `<paper-input-error>`'s content, if using. | |
*/ | |
errorMessage: { | |
type: String | |
}, | |
/** | |
* Set to true to show a character counter. | |
*/ | |
charCounter: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Set to true to disable the floating label. Bind this to the `<paper-input-container>`'s | |
* `noLabelFloat` property. | |
*/ | |
noLabelFloat: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Set to true to always float the label. Bind this to the `<paper-input-container>`'s | |
* `alwaysFloatLabel` property. | |
*/ | |
alwaysFloatLabel: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Set to true to auto-validate the input value. Bind this to the `<paper-input-container>`'s | |
* `autoValidate` property. | |
*/ | |
autoValidate: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Name of the validator to use. Bind this to the `<input is="iron-input">`'s `validator` | |
* property. | |
*/ | |
validator: { | |
type: String | |
}, | |
// HTMLInputElement attributes for binding if needed | |
/** | |
* Bind this to the `<input is="iron-input">`'s `autocomplete` property. | |
*/ | |
autocomplete: { | |
type: String, | |
value: 'off' | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `autofocus` property. | |
*/ | |
autofocus: { | |
type: Boolean | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `inputmode` property. | |
*/ | |
inputmode: { | |
type: String | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `minlength` property. | |
*/ | |
minlength: { | |
type: Number | |
}, | |
/** | |
* The maximum length of the input value. Bind this to the `<input is="iron-input">`'s | |
* `maxlength` property. | |
*/ | |
maxlength: { | |
type: Number | |
}, | |
/** | |
* The minimum (numeric or date-time) input value. | |
* Bind this to the `<input is="iron-input">`'s `min` property. | |
*/ | |
min: { | |
type: String | |
}, | |
/** | |
* The maximum (numeric or date-time) input value. | |
* Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`). | |
* Bind this to the `<input is="iron-input">`'s `max` property. | |
*/ | |
max: { | |
type: String | |
}, | |
/** | |
* Limits the numeric or date-time increments. | |
* Bind this to the `<input is="iron-input">`'s `step` property. | |
*/ | |
step: { | |
type: String | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `name` property. | |
*/ | |
name: { | |
type: String | |
}, | |
/** | |
* A placeholder string in addition to the label. If this is set, the label will always float. | |
*/ | |
placeholder: { | |
type: String, | |
// need to set a default so _computeAlwaysFloatLabel is run | |
value: '' | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `readonly` property. | |
*/ | |
readonly: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `size` property. | |
*/ | |
size: { | |
type: Number | |
}, | |
// Nonstandard attributes for binding if needed | |
/** | |
* Bind this to the `<input is="iron-input">`'s `autocapitalize` property. | |
*/ | |
autocapitalize: { | |
type: String, | |
value: 'none' | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `autocorrect` property. | |
*/ | |
autocorrect: { | |
type: String, | |
value: 'off' | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `autosave` property, used with type=search. | |
*/ | |
autosave: { | |
type: String | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `results` property, used with type=search. | |
*/ | |
results: { | |
type: Number | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `accept` property, used with type=file. | |
*/ | |
accept: { | |
type: String | |
}, | |
/** | |
* Bind this to the `<input is="iron-input">`'s `multiple` property, used with type=file. | |
*/ | |
multiple: { | |
type: Boolean | |
}, | |
_ariaDescribedBy: { | |
type: String, | |
value: '' | |
}, | |
_ariaLabelledBy: { | |
type: String, | |
value: '' | |
} | |
}, | |
listeners: { | |
'addon-attached': '_onAddonAttached', | |
'focus': '_onFocus' | |
}, | |
observers: [ | |
'_focusedControlStateChanged(focused)' | |
], | |
keyBindings: { | |
'shift+tab:keydown': '_onShiftTabDown' | |
}, | |
hostAttributes: { | |
tabindex: 0 | |
}, | |
/** | |
* Returns a reference to the input element. | |
*/ | |
get inputElement() { | |
return this.$.input; | |
}, | |
/** | |
* Returns a reference to the focusable element. | |
*/ | |
get _focusableElement() { | |
return this.inputElement; | |
}, | |
attached: function() { | |
this._updateAriaLabelledBy(); | |
}, | |
_appendStringWithSpace: function(str, more) { | |
if (str) { | |
str = str + ' ' + more; | |
} else { | |
str = more; | |
} | |
return str; | |
}, | |
_onAddonAttached: function(event) { | |
var target = event.path ? event.path[0] : event.target; | |
if (target.id) { | |
this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, target.id); | |
} else { | |
var id = 'paper-input-add-on-' + Math.floor((Math.random() * 100000)); | |
target.id = id; | |
this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, id); | |
} | |
}, | |
/** | |
* Validates the input element and sets an error style if needed. | |
* | |
* @return {boolean} | |
*/ | |
validate: function() { | |
return this.inputElement.validate(); | |
}, | |
/** | |
* Forward focus to inputElement | |
*/ | |
_onFocus: function() { | |
if (!this._shiftTabPressed) { | |
this._focusableElement.focus(); | |
} | |
}, | |
/** | |
* Handler that is called when a shift+tab keypress is detected by the menu. | |
* | |
* @param {CustomEvent} event A key combination event. | |
*/ | |
_onShiftTabDown: function(event) { | |
var oldTabIndex = this.getAttribute('tabindex'); | |
this._shiftTabPressed = true; | |
this.setAttribute('tabindex', '-1'); | |
this.async(function() { | |
this.setAttribute('tabindex', oldTabIndex); | |
this._shiftTabPressed = false; | |
}, 1); | |
}, | |
/** | |
* If `autoValidate` is true, then validates the element. | |
*/ | |
_handleAutoValidate: function() { | |
if (this.autoValidate) | |
this.validate(); | |
}, | |
/** | |
* Restores the cursor to its original position after updating the value. | |
* @param {string} newValue The value that should be saved. | |
*/ | |
updateValueAndPreserveCaret: function(newValue) { | |
// Not all elements might have selection, and even if they have the | |
// right properties, accessing them might throw an exception (like for | |
// <input type=number>) | |
try { | |
var start = this.inputElement.selectionStart; | |
this.value = newValue; | |
// The cursor automatically jumps to the end after re-setting the value, | |
// so restore it to its original position. | |
this.inputElement.selectionStart = start; | |
this.inputElement.selectionEnd = start; | |
} catch (e) { | |
// Just set the value and give up on the caret. | |
this.value = newValue; | |
} | |
}, | |
_computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) { | |
return placeholder || alwaysFloatLabel; | |
}, | |
_focusedControlStateChanged: function(focused) { | |
// IronControlState stops the focus and blur events in order to redispatch them on the host | |
// element, but paper-input-container listens to those events. Since there are more | |
// pending work on focus/blur in IronControlState, I'm putting in this hack to get the | |
// input focus state working for now. | |
if (!this.$.container) { | |
this.$.container = Polymer.dom(this.root).querySelector('paper-input-container'); | |
if (!this.$.container) { | |
return; | |
} | |
} | |
if (focused) { | |
this.$.container._onFocus(); | |
} else { | |
this.$.container._onBlur(); | |
} | |
}, | |
_updateAriaLabelledBy: function() { | |
var label = Polymer.dom(this.root).querySelector('label'); | |
if (!label) { | |
this._ariaLabelledBy = ''; | |
return; | |
} | |
var labelledBy; | |
if (label.id) { | |
labelledBy = label.id; | |
} else { | |
labelledBy = 'paper-input-label-' + new Date().getUTCMilliseconds(); | |
label.id = labelledBy; | |
} | |
this._ariaLabelledBy = labelledBy; | |
}, | |
_onChange:function(event) { | |
// In the Shadow DOM, the `change` event is not leaked into the | |
// ancestor tree, so we must do this manually. | |
// See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-not-leaked-into-ancestor-trees. | |
if (this.shadowRoot) { | |
this.fire(event.type, {sourceEvent: event}, { | |
node: this, | |
bubbles: event.bubbles, | |
cancelable: event.cancelable | |
}); | |
} | |
} | |
}; | |
/** @polymerBehavior */ | |
Polymer.PaperInputBehavior = [ | |
Polymer.IronControlState, | |
Polymer.IronA11yKeysBehavior, | |
Polymer.PaperInputBehaviorImpl | |
]; | |
</script> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono:400,700"> | |
<style is="custom-style"> | |
:root { | |
/* Shared Styles */ | |
--paper-font-common-base: { | |
font-family: 'Roboto', 'Noto', sans-serif; | |
-webkit-font-smoothing: antialiased; | |
}; | |
--paper-font-common-code: { | |
font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace; | |
-webkit-font-smoothing: antialiased; | |
}; | |
--paper-font-common-expensive-kerning: { | |
text-rendering: optimizeLegibility; | |
}; | |
--paper-font-common-nowrap: { | |
white-space: nowrap; | |
overflow: hidden; | |
text-overflow: ellipsis; | |
}; | |
/* Material Font Styles */ | |
--paper-font-display4: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 112px; | |
font-weight: 300; | |
letter-spacing: -.044em; | |
line-height: 120px; | |
}; | |
--paper-font-display3: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 56px; | |
font-weight: 400; | |
letter-spacing: -.026em; | |
line-height: 60px; | |
}; | |
--paper-font-display2: { | |
@apply(--paper-font-common-base); | |
font-size: 45px; | |
font-weight: 400; | |
letter-spacing: -.018em; | |
line-height: 48px; | |
}; | |
--paper-font-display1: { | |
@apply(--paper-font-common-base); | |
font-size: 34px; | |
font-weight: 400; | |
letter-spacing: -.01em; | |
line-height: 40px; | |
}; | |
--paper-font-headline: { | |
@apply(--paper-font-common-base); | |
font-size: 24px; | |
font-weight: 400; | |
letter-spacing: -.012em; | |
line-height: 32px; | |
}; | |
--paper-font-title: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 20px; | |
font-weight: 500; | |
line-height: 28px; | |
}; | |
--paper-font-subhead: { | |
@apply(--paper-font-common-base); | |
font-size: 16px; | |
font-weight: 400; | |
line-height: 24px; | |
}; | |
--paper-font-body2: { | |
@apply(--paper-font-common-base); | |
font-size: 14px; | |
font-weight: 500; | |
line-height: 24px; | |
}; | |
--paper-font-body1: { | |
@apply(--paper-font-common-base); | |
font-size: 14px; | |
font-weight: 400; | |
line-height: 20px; | |
}; | |
--paper-font-caption: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 12px; | |
font-weight: 400; | |
letter-spacing: 0.011em; | |
line-height: 20px; | |
}; | |
--paper-font-menu: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 13px; | |
font-weight: 500; | |
line-height: 24px; | |
}; | |
--paper-font-button: { | |
@apply(--paper-font-common-base); | |
@apply(--paper-font-common-nowrap); | |
font-size: 14px; | |
font-weight: 500; | |
letter-spacing: 0.018em; | |
line-height: 24px; | |
text-transform: uppercase; | |
}; | |
--paper-font-code2: { | |
@apply(--paper-font-common-code); | |
font-size: 14px; | |
font-weight: 700; | |
line-height: 20px; | |
}; | |
--paper-font-code1: { | |
@apply(--paper-font-common-code); | |
font-size: 14px; | |
font-weight: 500; | |
line-height: 20px; | |
}; | |
} | |
</style> | |
<script> | |
/** | |
* Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-input-container>`. A | |
* add-on appears below the input, and may display information based on the input value and | |
* validity such as a character counter or an error message. | |
* @polymerBehavior | |
*/ | |
Polymer.PaperInputAddonBehavior = { | |
hostAttributes: { | |
'add-on': '' | |
}, | |
attached: function() { | |
this.fire('addon-attached'); | |
}, | |
/** | |
* The function called by `<paper-input-container>` when the input value or validity changes. | |
* @param {{ | |
* inputElement: (Node|undefined), | |
* value: (string|undefined), | |
* invalid: (boolean|undefined) | |
* }} state All properties are optional - | |
* inputElement: The input element. | |
* value: The input value. | |
* invalid: True if the input value is invalid. | |
*/ | |
update: function(state) { | |
} | |
}; | |
</script> | |
<!-- | |
`<paper-input-char-counter>` is a character counter for use with `<paper-input-container>`. It | |
shows the number of characters entered in the input and the max length if it is specified. | |
<paper-input-container> | |
<input is="iron-input" maxlength="20"> | |
<paper-input-char-counter></paper-input-char-counter> | |
</paper-input-container> | |
### Styling | |
The following mixin is available for styling: | |
Custom property | Description | Default | |
----------------|-------------|---------- | |
`--paper-input-char-counter` | Mixin applied to the element | `{}` | |
--> | |
<!-- | |
`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or | |
`<iron-autogrow-textarea>` and optional add-on elements such as an error message or character | |
counter, used to implement Material Design text fields. | |
For example: | |
<paper-input-container> | |
<label>Your name</label> | |
<input is="iron-input"> | |
</paper-input-container> | |
### Listening for input changes | |
By default, it listens for changes on the `bind-value` attribute on its children nodes and perform | |
tasks such as auto-validating and label styling when the `bind-value` changes. You can configure | |
the attribute it listens to with the `attr-for-value` attribute. | |
### Using a custom input element | |
You can use a custom input element in a `<paper-input-container>`, for example to implement a | |
compound input field like a social security number input. The custom input element should have the | |
`paper-input-input` class, have a `notify:true` value property and optionally implements | |
`Polymer.IronValidatableBehavior` if it is validatable. | |
<paper-input-container attr-for-value="ssn-value"> | |
<label>Social security number</label> | |
<ssn-input class="paper-input-input"></ssn-input> | |
</paper-input-container> | |
### Validation | |
If the `auto-validate` attribute is set, the input container will validate the input and update | |
the container styling when the input value changes. | |
### Add-ons | |
Add-ons are child elements of a `<paper-input-container>` with the `add-on` attribute and | |
implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified when the input value | |
or validity changes, and may implement functionality such as error messages or character counters. | |
They appear at the bottom of the input. | |
### Prefixes and suffixes | |
These are child elements of a `<paper-input-container>` with the `prefix` | |
or `suffix` attribute, and are displayed inline with the input, before or after. | |
<paper-input-container> | |
<div prefix>$</div> | |
<label>Total</label> | |
<input is="iron-input"> | |
<paper-icon-button suffix icon="clear"></paper-icon-button> | |
</paper-input-container> | |
### Styling | |
The following custom properties and mixins are available for styling: | |
Custom property | Description | Default | |
----------------|-------------|---------- | |
`--paper-input-container-color` | Label and underline color when the input is not focused | `--secondary-text-color` | |
`--paper-input-container-focus-color` | Label and underline color when the input is focused | `--default-primary-color` | |
`--paper-input-container-invalid-color` | Label and underline color when the input is is invalid | `--google-red-500` | |
`--paper-input-container-input-color` | Input foreground color | `--primary-text-color` | |
`--paper-input-container` | Mixin applied to the container | `{}` | |
`--paper-input-container-disabled` | Mixin applied to the container when it's disabled | `{}` | |
`--paper-input-container-label` | Mixin applied to the label | `{}` | |
`--paper-input-container-label-focus` | Mixin applied to the label when the input is focused | `{}` | |
`--paper-input-container-label-floating` | Mixin applied to the label when floating | `{}` | |
`--paper-input-container-input` | Mixin applied to the input | `{}` | |
`--paper-input-container-underline` | Mixin applied to the underline | `{}` | |
`--paper-input-container-underline-focus` | Mixin applied to the underline when the input is focused | `{}` | |
`--paper-input-container-underline-disabled` | Mixin applied to the underline when the input is disabled | `{}` | |
`--paper-input-prefix` | Mixin applied to the input prefix | `{}` | |
`--paper-input-suffix` | Mixin applied to the input suffix | `{}` | |
This element is `display:block` by default, but you can set the `inline` attribute to make it | |
`display:inline-block`. | |
--> | |
<!-- | |
`<paper-input-error>` is an error message for use with `<paper-input-container>`. The error is | |
displayed when the `<paper-input-container>` is `invalid`. | |
<paper-input-container> | |
<input is="iron-input" pattern="[0-9]*"> | |
<paper-input-error>Only numbers are allowed!</paper-input-error> | |
</paper-input-container> | |
### Styling | |
The following custom properties and mixins are available for styling: | |
Custom property | Description | Default | |
----------------|-------------|---------- | |
`--paper-input-container-invalid-color` | The foreground color of the error | `--google-red-500` | |
`--paper-input-error` | Mixin applied to the error | `{}` | |
--> | |
<!-- | |
Material design: [Text fields](https://www.google.com/design/spec/components/text-fields.html) | |
`<paper-input>` is a single-line text field with Material Design styling. | |
<paper-input label="Input label"></paper-input> | |
It may include an optional error message or character counter. | |
<paper-input error-message="Invalid input!" label="Input label"></paper-input> | |
<paper-input char-counter label="Input label"></paper-input> | |
It can also include custom prefix or suffix elements, which are displayed | |
before or after the text input itself. In order for an element to be | |
considered as a prefix, it must have the `prefix` attribute (and similarly | |
for `suffix`). | |
<paper-input label="total"> | |
<div prefix>$</div> | |
<paper-icon-button suffix icon="clear"></paper-icon-button> | |
</paper-input> | |
A `paper-input` can use the native `type=search` or `type=file` features. | |
However, since we can't control the native styling of the input, in these cases | |
it's recommended to use a placeholder text, or `always-float-label`, | |
as to not overlap the native UI (search icon, file button, etc.). | |
<paper-input label="search!" type="search" | |
placeholder="search for cats" autosave="test" results="5"> | |
</paper-input> | |
See `Polymer.PaperInputBehavior` for more API docs. | |
### Focus | |
To focus a paper-input, you can call the native `focus()` method as long as the | |
paper input has a tab index. | |
### Styling | |
See `Polymer.PaperInputContainer` for a list of custom properties used to | |
style this element. | |
@group Paper Elements | |
@element paper-input | |
@hero hero.svg | |
@demo demo/index.html | |
--> | |
<script>!function() { | |
var d3 = { | |
version: "3.5.12" | |
}; | |
var d3_arraySlice = [].slice, d3_array = function(list) { | |
return d3_arraySlice.call(list); | |
}; | |
var d3_document = this.document; | |
function d3_documentElement(node) { | |
return node && (node.ownerDocument || node.document || node).documentElement; | |
} | |
function d3_window(node) { | |
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); | |
} | |
if (d3_document) { | |
try { | |
d3_array(d3_document.documentElement.childNodes)[0].nodeType; | |
} catch (e) { | |
d3_array = function(list) { | |
var i = list.length, array = new Array(i); | |
while (i--) array[i] = list[i]; | |
return array; | |
}; | |
} | |
} | |
if (!Date.now) Date.now = function() { | |
return +new Date(); | |
}; | |
if (d3_document) { | |
try { | |
d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); | |
} catch (error) { | |
var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; | |
d3_element_prototype.setAttribute = function(name, value) { | |
d3_element_setAttribute.call(this, name, value + ""); | |
}; | |
d3_element_prototype.setAttributeNS = function(space, local, value) { | |
d3_element_setAttributeNS.call(this, space, local, value + ""); | |
}; | |
d3_style_prototype.setProperty = function(name, value, priority) { | |
d3_style_setProperty.call(this, name, value + "", priority); | |
}; | |
} | |
} | |
d3.ascending = d3_ascending; | |
function d3_ascending(a, b) { | |
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; | |
} | |
d3.descending = function(a, b) { | |
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; | |
}; | |
d3.min = function(array, f) { | |
var i = -1, n = array.length, a, b; | |
if (arguments.length === 1) { | |
while (++i < n) if ((b = array[i]) != null && b >= b) { | |
a = b; | |
break; | |
} | |
while (++i < n) if ((b = array[i]) != null && a > b) a = b; | |
} else { | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { | |
a = b; | |
break; | |
} | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; | |
} | |
return a; | |
}; | |
d3.max = function(array, f) { | |
var i = -1, n = array.length, a, b; | |
if (arguments.length === 1) { | |
while (++i < n) if ((b = array[i]) != null && b >= b) { | |
a = b; | |
break; | |
} | |
while (++i < n) if ((b = array[i]) != null && b > a) a = b; | |
} else { | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { | |
a = b; | |
break; | |
} | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; | |
} | |
return a; | |
}; | |
d3.extent = function(array, f) { | |
var i = -1, n = array.length, a, b, c; | |
if (arguments.length === 1) { | |
while (++i < n) if ((b = array[i]) != null && b >= b) { | |
a = c = b; | |
break; | |
} | |
while (++i < n) if ((b = array[i]) != null) { | |
if (a > b) a = b; | |
if (c < b) c = b; | |
} | |
} else { | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { | |
a = c = b; | |
break; | |
} | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null) { | |
if (a > b) a = b; | |
if (c < b) c = b; | |
} | |
} | |
return [ a, c ]; | |
}; | |
function d3_number(x) { | |
return x === null ? NaN : +x; | |
} | |
function d3_numeric(x) { | |
return !isNaN(x); | |
} | |
d3.sum = function(array, f) { | |
var s = 0, n = array.length, a, i = -1; | |
if (arguments.length === 1) { | |
while (++i < n) if (d3_numeric(a = +array[i])) s += a; | |
} else { | |
while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; | |
} | |
return s; | |
}; | |
d3.mean = function(array, f) { | |
var s = 0, n = array.length, a, i = -1, j = n; | |
if (arguments.length === 1) { | |
while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; | |
} else { | |
while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; | |
} | |
if (j) return s / j; | |
}; | |
d3.quantile = function(values, p) { | |
var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; | |
return e ? v + e * (values[h] - v) : v; | |
}; | |
d3.median = function(array, f) { | |
var numbers = [], n = array.length, a, i = -1; | |
if (arguments.length === 1) { | |
while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); | |
} else { | |
while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); | |
} | |
if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); | |
}; | |
d3.variance = function(array, f) { | |
var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; | |
if (arguments.length === 1) { | |
while (++i < n) { | |
if (d3_numeric(a = d3_number(array[i]))) { | |
d = a - m; | |
m += d / ++j; | |
s += d * (a - m); | |
} | |
} | |
} else { | |
while (++i < n) { | |
if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { | |
d = a - m; | |
m += d / ++j; | |
s += d * (a - m); | |
} | |
} | |
} | |
if (j > 1) return s / (j - 1); | |
}; | |
d3.deviation = function() { | |
var v = d3.variance.apply(this, arguments); | |
return v ? Math.sqrt(v) : v; | |
}; | |
function d3_bisector(compare) { | |
return { | |
left: function(a, x, lo, hi) { | |
if (arguments.length < 3) lo = 0; | |
if (arguments.length < 4) hi = a.length; | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; | |
} | |
return lo; | |
}, | |
right: function(a, x, lo, hi) { | |
if (arguments.length < 3) lo = 0; | |
if (arguments.length < 4) hi = a.length; | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; | |
} | |
return lo; | |
} | |
}; | |
} | |
var d3_bisect = d3_bisector(d3_ascending); | |
d3.bisectLeft = d3_bisect.left; | |
d3.bisect = d3.bisectRight = d3_bisect.right; | |
d3.bisector = function(f) { | |
return d3_bisector(f.length === 1 ? function(d, x) { | |
return d3_ascending(f(d), x); | |
} : f); | |
}; | |
d3.shuffle = function(array, i0, i1) { | |
if ((m = arguments.length) < 3) { | |
i1 = array.length; | |
if (m < 2) i0 = 0; | |
} | |
var m = i1 - i0, t, i; | |
while (m) { | |
i = Math.random() * m-- | 0; | |
t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; | |
} | |
return array; | |
}; | |
d3.permute = function(array, indexes) { | |
var i = indexes.length, permutes = new Array(i); | |
while (i--) permutes[i] = array[indexes[i]]; | |
return permutes; | |
}; | |
d3.pairs = function(array) { | |
var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); | |
while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; | |
return pairs; | |
}; | |
d3.zip = function() { | |
if (!(n = arguments.length)) return []; | |
for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { | |
for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { | |
zip[j] = arguments[j][i]; | |
} | |
} | |
return zips; | |
}; | |
function d3_zipLength(d) { | |
return d.length; | |
} | |
d3.transpose = function(matrix) { | |
return d3.zip.apply(d3, matrix); | |
}; | |
d3.keys = function(map) { | |
var keys = []; | |
for (var key in map) keys.push(key); | |
return keys; | |
}; | |
d3.values = function(map) { | |
var values = []; | |
for (var key in map) values.push(map[key]); | |
return values; | |
}; | |
d3.entries = function(map) { | |
var entries = []; | |
for (var key in map) entries.push({ | |
key: key, | |
value: map[key] | |
}); | |
return entries; | |
}; | |
d3.merge = function(arrays) { | |
var n = arrays.length, m, i = -1, j = 0, merged, array; | |
while (++i < n) j += arrays[i].length; | |
merged = new Array(j); | |
while (--n >= 0) { | |
array = arrays[n]; | |
m = array.length; | |
while (--m >= 0) { | |
merged[--j] = array[m]; | |
} | |
} | |
return merged; | |
}; | |
var abs = Math.abs; | |
d3.range = function(start, stop, step) { | |
if (arguments.length < 3) { | |
step = 1; | |
if (arguments.length < 2) { | |
stop = start; | |
start = 0; | |
} | |
} | |
if ((stop - start) / step === Infinity) throw new Error("infinite range"); | |
var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; | |
start *= k, stop *= k, step *= k; | |
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); | |
return range; | |
}; | |
function d3_range_integerScale(x) { | |
var k = 1; | |
while (x * k % 1) k *= 10; | |
return k; | |
} | |
function d3_class(ctor, properties) { | |
for (var key in properties) { | |
Object.defineProperty(ctor.prototype, key, { | |
value: properties[key], | |
enumerable: false | |
}); | |
} | |
} | |
d3.map = function(object, f) { | |
var map = new d3_Map(); | |
if (object instanceof d3_Map) { | |
object.forEach(function(key, value) { | |
map.set(key, value); | |
}); | |
} else if (Array.isArray(object)) { | |
var i = -1, n = object.length, o; | |
if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); | |
} else { | |
for (var key in object) map.set(key, object[key]); | |
} | |
return map; | |
}; | |
function d3_Map() { | |
this._ = Object.create(null); | |
} | |
var d3_map_proto = "__proto__", d3_map_zero = "\x00"; | |
d3_class(d3_Map, { | |
has: d3_map_has, | |
get: function(key) { | |
return this._[d3_map_escape(key)]; | |
}, | |
set: function(key, value) { | |
return this._[d3_map_escape(key)] = value; | |
}, | |
remove: d3_map_remove, | |
keys: d3_map_keys, | |
values: function() { | |
var values = []; | |
for (var key in this._) values.push(this._[key]); | |
return values; | |
}, | |
entries: function() { | |
var entries = []; | |
for (var key in this._) entries.push({ | |
key: d3_map_unescape(key), | |
value: this._[key] | |
}); | |
return entries; | |
}, | |
size: d3_map_size, | |
empty: d3_map_empty, | |
forEach: function(f) { | |
for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); | |
} | |
}); | |
function d3_map_escape(key) { | |
return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; | |
} | |
function d3_map_unescape(key) { | |
return (key += "")[0] === d3_map_zero ? key.slice(1) : key; | |
} | |
function d3_map_has(key) { | |
return d3_map_escape(key) in this._; | |
} | |
function d3_map_remove(key) { | |
return (key = d3_map_escape(key)) in this._ && delete this._[key]; | |
} | |
function d3_map_keys() { | |
var keys = []; | |
for (var key in this._) keys.push(d3_map_unescape(key)); | |
return keys; | |
} | |
function d3_map_size() { | |
var size = 0; | |
for (var key in this._) ++size; | |
return size; | |
} | |
function d3_map_empty() { | |
for (var key in this._) return false; | |
return true; | |
} | |
d3.nest = function() { | |
var nest = {}, keys = [], sortKeys = [], sortValues, rollup; | |
function map(mapType, array, depth) { | |
if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; | |
var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; | |
while (++i < n) { | |
if (values = valuesByKey.get(keyValue = key(object = array[i]))) { | |
values.push(object); | |
} else { | |
valuesByKey.set(keyValue, [ object ]); | |
} | |
} | |
if (mapType) { | |
object = mapType(); | |
setter = function(keyValue, values) { | |
object.set(keyValue, map(mapType, values, depth)); | |
}; | |
} else { | |
object = {}; | |
setter = function(keyValue, values) { | |
object[keyValue] = map(mapType, values, depth); | |
}; | |
} | |
valuesByKey.forEach(setter); | |
return object; | |
} | |
function entries(map, depth) { | |
if (depth >= keys.length) return map; | |
var array = [], sortKey = sortKeys[depth++]; | |
map.forEach(function(key, keyMap) { | |
array.push({ | |
key: key, | |
values: entries(keyMap, depth) | |
}); | |
}); | |
return sortKey ? array.sort(function(a, b) { | |
return sortKey(a.key, b.key); | |
}) : array; | |
} | |
nest.map = function(array, mapType) { | |
return map(mapType, array, 0); | |
}; | |
nest.entries = function(array) { | |
return entries(map(d3.map, array, 0), 0); | |
}; | |
nest.key = function(d) { | |
keys.push(d); | |
return nest; | |
}; | |
nest.sortKeys = function(order) { | |
sortKeys[keys.length - 1] = order; | |
return nest; | |
}; | |
nest.sortValues = function(order) { | |
sortValues = order; | |
return nest; | |
}; | |
nest.rollup = function(f) { | |
rollup = f; | |
return nest; | |
}; | |
return nest; | |
}; | |
d3.set = function(array) { | |
var set = new d3_Set(); | |
if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); | |
return set; | |
}; | |
function d3_Set() { | |
this._ = Object.create(null); | |
} | |
d3_class(d3_Set, { | |
has: d3_map_has, | |
add: function(key) { | |
this._[d3_map_escape(key += "")] = true; | |
return key; | |
}, | |
remove: d3_map_remove, | |
values: d3_map_keys, | |
size: d3_map_size, | |
empty: d3_map_empty, | |
forEach: function(f) { | |
for (var key in this._) f.call(this, d3_map_unescape(key)); | |
} | |
}); | |
d3.behavior = {}; | |
function d3_identity(d) { | |
return d; | |
} | |
d3.rebind = function(target, source) { | |
var i = 1, n = arguments.length, method; | |
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); | |
return target; | |
}; | |
function d3_rebind(target, source, method) { | |
return function() { | |
var value = method.apply(source, arguments); | |
return value === source ? target : value; | |
}; | |
} | |
function d3_vendorSymbol(object, name) { | |
if (name in object) return name; | |
name = name.charAt(0).toUpperCase() + name.slice(1); | |
for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { | |
var prefixName = d3_vendorPrefixes[i] + name; | |
if (prefixName in object) return prefixName; | |
} | |
} | |
var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; | |
function d3_noop() {} | |
d3.dispatch = function() { | |
var dispatch = new d3_dispatch(), i = -1, n = arguments.length; | |
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); | |
return dispatch; | |
}; | |
function d3_dispatch() {} | |
d3_dispatch.prototype.on = function(type, listener) { | |
var i = type.indexOf("."), name = ""; | |
if (i >= 0) { | |
name = type.slice(i + 1); | |
type = type.slice(0, i); | |
} | |
if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); | |
if (arguments.length === 2) { | |
if (listener == null) for (type in this) { | |
if (this.hasOwnProperty(type)) this[type].on(name, null); | |
} | |
return this; | |
} | |
}; | |
function d3_dispatch_event(dispatch) { | |
var listeners = [], listenerByName = new d3_Map(); | |
function event() { | |
var z = listeners, i = -1, n = z.length, l; | |
while (++i < n) if (l = z[i].on) l.apply(this, arguments); | |
return dispatch; | |
} | |
event.on = function(name, listener) { | |
var l = listenerByName.get(name), i; | |
if (arguments.length < 2) return l && l.on; | |
if (l) { | |
l.on = null; | |
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); | |
listenerByName.remove(name); | |
} | |
if (listener) listeners.push(listenerByName.set(name, { | |
on: listener | |
})); | |
return dispatch; | |
}; | |
return event; | |
} | |
d3.event = null; | |
function d3_eventPreventDefault() { | |
d3.event.preventDefault(); | |
} | |
function d3_eventSource() { | |
var e = d3.event, s; | |
while (s = e.sourceEvent) e = s; | |
return e; | |
} | |
function d3_eventDispatch(target) { | |
var dispatch = new d3_dispatch(), i = 0, n = arguments.length; | |
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); | |
dispatch.of = function(thiz, argumentz) { | |
return function(e1) { | |
try { | |
var e0 = e1.sourceEvent = d3.event; | |
e1.target = target; | |
d3.event = e1; | |
dispatch[e1.type].apply(thiz, argumentz); | |
} finally { | |
d3.event = e0; | |
} | |
}; | |
}; | |
return dispatch; | |
} | |
d3.requote = function(s) { | |
return s.replace(d3_requote_re, "\\$&"); | |
}; | |
var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; | |
var d3_subclass = {}.__proto__ ? function(object, prototype) { | |
object.__proto__ = prototype; | |
} : function(object, prototype) { | |
for (var property in prototype) object[property] = prototype[property]; | |
}; | |
function d3_selection(groups) { | |
d3_subclass(groups, d3_selectionPrototype); | |
return groups; | |
} | |
var d3_select = function(s, n) { | |
return n.querySelector(s); | |
}, d3_selectAll = function(s, n) { | |
return n.querySelectorAll(s); | |
}, d3_selectMatches = function(n, s) { | |
var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; | |
d3_selectMatches = function(n, s) { | |
return d3_selectMatcher.call(n, s); | |
}; | |
return d3_selectMatches(n, s); | |
}; | |
if (typeof Sizzle === "function") { | |
d3_select = function(s, n) { | |
return Sizzle(s, n)[0] || null; | |
}; | |
d3_selectAll = Sizzle; | |
d3_selectMatches = Sizzle.matchesSelector; | |
} | |
d3.selection = function() { | |
return d3.select(d3_document.documentElement); | |
}; | |
var d3_selectionPrototype = d3.selection.prototype = []; | |
d3_selectionPrototype.select = function(selector) { | |
var subgroups = [], subgroup, subnode, group, node; | |
selector = d3_selection_selector(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = (group = this[j]).parentNode; | |
for (var i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroup.push(subnode = selector.call(node, node.__data__, i, j)); | |
if (subnode && "__data__" in node) subnode.__data__ = node.__data__; | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_selector(selector) { | |
return typeof selector === "function" ? selector : function() { | |
return d3_select(selector, this); | |
}; | |
} | |
d3_selectionPrototype.selectAll = function(selector) { | |
var subgroups = [], subgroup, node; | |
selector = d3_selection_selectorAll(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); | |
subgroup.parentNode = node; | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_selectorAll(selector) { | |
return typeof selector === "function" ? selector : function() { | |
return d3_selectAll(selector, this); | |
}; | |
} | |
var d3_nsPrefix = { | |
svg: "http://www.w3.org/2000/svg", | |
xhtml: "http://www.w3.org/1999/xhtml", | |
xlink: "http://www.w3.org/1999/xlink", | |
xml: "http://www.w3.org/XML/1998/namespace", | |
xmlns: "http://www.w3.org/2000/xmlns/" | |
}; | |
d3.ns = { | |
prefix: d3_nsPrefix, | |
qualify: function(name) { | |
var i = name.indexOf(":"), prefix = name; | |
if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); | |
return d3_nsPrefix.hasOwnProperty(prefix) ? { | |
space: d3_nsPrefix[prefix], | |
local: name | |
} : name; | |
} | |
}; | |
d3_selectionPrototype.attr = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") { | |
var node = this.node(); | |
name = d3.ns.qualify(name); | |
return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); | |
} | |
for (value in name) this.each(d3_selection_attr(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_attr(name, value)); | |
}; | |
function d3_selection_attr(name, value) { | |
name = d3.ns.qualify(name); | |
function attrNull() { | |
this.removeAttribute(name); | |
} | |
function attrNullNS() { | |
this.removeAttributeNS(name.space, name.local); | |
} | |
function attrConstant() { | |
this.setAttribute(name, value); | |
} | |
function attrConstantNS() { | |
this.setAttributeNS(name.space, name.local, value); | |
} | |
function attrFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); | |
} | |
function attrFunctionNS() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); | |
} | |
return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; | |
} | |
function d3_collapse(s) { | |
return s.trim().replace(/\s+/g, " "); | |
} | |
d3_selectionPrototype.classed = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") { | |
var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; | |
if (value = node.classList) { | |
while (++i < n) if (!value.contains(name[i])) return false; | |
} else { | |
value = node.getAttribute("class"); | |
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; | |
} | |
return true; | |
} | |
for (value in name) this.each(d3_selection_classed(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_classed(name, value)); | |
}; | |
function d3_selection_classedRe(name) { | |
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); | |
} | |
function d3_selection_classes(name) { | |
return (name + "").trim().split(/^|\s+/); | |
} | |
function d3_selection_classed(name, value) { | |
name = d3_selection_classes(name).map(d3_selection_classedName); | |
var n = name.length; | |
function classedConstant() { | |
var i = -1; | |
while (++i < n) name[i](this, value); | |
} | |
function classedFunction() { | |
var i = -1, x = value.apply(this, arguments); | |
while (++i < n) name[i](this, x); | |
} | |
return typeof value === "function" ? classedFunction : classedConstant; | |
} | |
function d3_selection_classedName(name) { | |
var re = d3_selection_classedRe(name); | |
return function(node, value) { | |
if (c = node.classList) return value ? c.add(name) : c.remove(name); | |
var c = node.getAttribute("class") || ""; | |
if (value) { | |
re.lastIndex = 0; | |
if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); | |
} else { | |
node.setAttribute("class", d3_collapse(c.replace(re, " "))); | |
} | |
}; | |
} | |
d3_selectionPrototype.style = function(name, value, priority) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof name !== "string") { | |
if (n < 2) value = ""; | |
for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); | |
return this; | |
} | |
if (n < 2) { | |
var node = this.node(); | |
return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); | |
} | |
priority = ""; | |
} | |
return this.each(d3_selection_style(name, value, priority)); | |
}; | |
function d3_selection_style(name, value, priority) { | |
function styleNull() { | |
this.style.removeProperty(name); | |
} | |
function styleConstant() { | |
this.style.setProperty(name, value, priority); | |
} | |
function styleFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); | |
} | |
return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; | |
} | |
d3_selectionPrototype.property = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") return this.node()[name]; | |
for (value in name) this.each(d3_selection_property(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_property(name, value)); | |
}; | |
function d3_selection_property(name, value) { | |
function propertyNull() { | |
delete this[name]; | |
} | |
function propertyConstant() { | |
this[name] = value; | |
} | |
function propertyFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) delete this[name]; else this[name] = x; | |
} | |
return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; | |
} | |
d3_selectionPrototype.text = function(value) { | |
return arguments.length ? this.each(typeof value === "function" ? function() { | |
var v = value.apply(this, arguments); | |
this.textContent = v == null ? "" : v; | |
} : value == null ? function() { | |
this.textContent = ""; | |
} : function() { | |
this.textContent = value; | |
}) : this.node().textContent; | |
}; | |
d3_selectionPrototype.html = function(value) { | |
return arguments.length ? this.each(typeof value === "function" ? function() { | |
var v = value.apply(this, arguments); | |
this.innerHTML = v == null ? "" : v; | |
} : value == null ? function() { | |
this.innerHTML = ""; | |
} : function() { | |
this.innerHTML = value; | |
}) : this.node().innerHTML; | |
}; | |
d3_selectionPrototype.append = function(name) { | |
name = d3_selection_creator(name); | |
return this.select(function() { | |
return this.appendChild(name.apply(this, arguments)); | |
}); | |
}; | |
function d3_selection_creator(name) { | |
function create() { | |
var document = this.ownerDocument, namespace = this.namespaceURI; | |
return namespace ? document.createElementNS(namespace, name) : document.createElement(name); | |
} | |
function createNS() { | |
return this.ownerDocument.createElementNS(name.space, name.local); | |
} | |
return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; | |
} | |
d3_selectionPrototype.insert = function(name, before) { | |
name = d3_selection_creator(name); | |
before = d3_selection_selector(before); | |
return this.select(function() { | |
return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); | |
}); | |
}; | |
d3_selectionPrototype.remove = function() { | |
return this.each(d3_selectionRemove); | |
}; | |
function d3_selectionRemove() { | |
var parent = this.parentNode; | |
if (parent) parent.removeChild(this); | |
} | |
d3_selectionPrototype.data = function(value, key) { | |
var i = -1, n = this.length, group, node; | |
if (!arguments.length) { | |
value = new Array(n = (group = this[0]).length); | |
while (++i < n) { | |
if (node = group[i]) { | |
value[i] = node.__data__; | |
} | |
} | |
return value; | |
} | |
function bind(group, groupData) { | |
var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; | |
if (key) { | |
var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; | |
for (i = -1; ++i < n; ) { | |
if (node = group[i]) { | |
if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { | |
exitNodes[i] = node; | |
} else { | |
nodeByKeyValue.set(keyValue, node); | |
} | |
keyValues[i] = keyValue; | |
} | |
} | |
for (i = -1; ++i < m; ) { | |
if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { | |
enterNodes[i] = d3_selection_dataNode(nodeData); | |
} else if (node !== true) { | |
updateNodes[i] = node; | |
node.__data__ = nodeData; | |
} | |
nodeByKeyValue.set(keyValue, true); | |
} | |
for (i = -1; ++i < n; ) { | |
if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { | |
exitNodes[i] = group[i]; | |
} | |
} | |
} else { | |
for (i = -1; ++i < n0; ) { | |
node = group[i]; | |
nodeData = groupData[i]; | |
if (node) { | |
node.__data__ = nodeData; | |
updateNodes[i] = node; | |
} else { | |
enterNodes[i] = d3_selection_dataNode(nodeData); | |
} | |
} | |
for (;i < m; ++i) { | |
enterNodes[i] = d3_selection_dataNode(groupData[i]); | |
} | |
for (;i < n; ++i) { | |
exitNodes[i] = group[i]; | |
} | |
} | |
enterNodes.update = updateNodes; | |
enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; | |
enter.push(enterNodes); | |
update.push(updateNodes); | |
exit.push(exitNodes); | |
} | |
var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); | |
if (typeof value === "function") { | |
while (++i < n) { | |
bind(group = this[i], value.call(group, group.parentNode.__data__, i)); | |
} | |
} else { | |
while (++i < n) { | |
bind(group = this[i], value); | |
} | |
} | |
update.enter = function() { | |
return enter; | |
}; | |
update.exit = function() { | |
return exit; | |
}; | |
return update; | |
}; | |
function d3_selection_dataNode(data) { | |
return { | |
__data__: data | |
}; | |
} | |
d3_selectionPrototype.datum = function(value) { | |
return arguments.length ? this.property("__data__", value) : this.property("__data__"); | |
}; | |
d3_selectionPrototype.filter = function(filter) { | |
var subgroups = [], subgroup, group, node; | |
if (typeof filter !== "function") filter = d3_selection_filter(filter); | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = (group = this[j]).parentNode; | |
for (var i = 0, n = group.length; i < n; i++) { | |
if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_filter(selector) { | |
return function() { | |
return d3_selectMatches(this, selector); | |
}; | |
} | |
d3_selectionPrototype.order = function() { | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { | |
if (node = group[i]) { | |
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); | |
next = node; | |
} | |
} | |
} | |
return this; | |
}; | |
d3_selectionPrototype.sort = function(comparator) { | |
comparator = d3_selection_sortComparator.apply(this, arguments); | |
for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); | |
return this.order(); | |
}; | |
function d3_selection_sortComparator(comparator) { | |
if (!arguments.length) comparator = d3_ascending; | |
return function(a, b) { | |
return a && b ? comparator(a.__data__, b.__data__) : !a - !b; | |
}; | |
} | |
d3_selectionPrototype.each = function(callback) { | |
return d3_selection_each(this, function(node, i, j) { | |
callback.call(node, node.__data__, i, j); | |
}); | |
}; | |
function d3_selection_each(groups, callback) { | |
for (var j = 0, m = groups.length; j < m; j++) { | |
for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { | |
if (node = group[i]) callback(node, i, j); | |
} | |
} | |
return groups; | |
} | |
d3_selectionPrototype.call = function(callback) { | |
var args = d3_array(arguments); | |
callback.apply(args[0] = this, args); | |
return this; | |
}; | |
d3_selectionPrototype.empty = function() { | |
return !this.node(); | |
}; | |
d3_selectionPrototype.node = function() { | |
for (var j = 0, m = this.length; j < m; j++) { | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
var node = group[i]; | |
if (node) return node; | |
} | |
} | |
return null; | |
}; | |
d3_selectionPrototype.size = function() { | |
var n = 0; | |
d3_selection_each(this, function() { | |
++n; | |
}); | |
return n; | |
}; | |
function d3_selection_enter(selection) { | |
d3_subclass(selection, d3_selection_enterPrototype); | |
return selection; | |
} | |
var d3_selection_enterPrototype = []; | |
d3.selection.enter = d3_selection_enter; | |
d3.selection.enter.prototype = d3_selection_enterPrototype; | |
d3_selection_enterPrototype.append = d3_selectionPrototype.append; | |
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; | |
d3_selection_enterPrototype.node = d3_selectionPrototype.node; | |
d3_selection_enterPrototype.call = d3_selectionPrototype.call; | |
d3_selection_enterPrototype.size = d3_selectionPrototype.size; | |
d3_selection_enterPrototype.select = function(selector) { | |
var subgroups = [], subgroup, subnode, upgroup, group, node; | |
for (var j = -1, m = this.length; ++j < m; ) { | |
upgroup = (group = this[j]).update; | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = group.parentNode; | |
for (var i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); | |
subnode.__data__ = node.__data__; | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
d3_selection_enterPrototype.insert = function(name, before) { | |
if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); | |
return d3_selectionPrototype.insert.call(this, name, before); | |
}; | |
function d3_selection_enterInsertBefore(enter) { | |
var i0, j0; | |
return function(d, i, j) { | |
var group = enter[j].update, n = group.length, node; | |
if (j != j0) j0 = j, i0 = 0; | |
if (i >= i0) i0 = i + 1; | |
while (!(node = group[i0]) && ++i0 < n) ; | |
return node; | |
}; | |
} | |
d3.select = function(node) { | |
var group; | |
if (typeof node === "string") { | |
group = [ d3_select(node, d3_document) ]; | |
group.parentNode = d3_document.documentElement; | |
} else { | |
group = [ node ]; | |
group.parentNode = d3_documentElement(node); | |
} | |
return d3_selection([ group ]); | |
}; | |
d3.selectAll = function(nodes) { | |
var group; | |
if (typeof nodes === "string") { | |
group = d3_array(d3_selectAll(nodes, d3_document)); | |
group.parentNode = d3_document.documentElement; | |
} else { | |
group = d3_array(nodes); | |
group.parentNode = null; | |
} | |
return d3_selection([ group ]); | |
}; | |
d3_selectionPrototype.on = function(type, listener, capture) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof type !== "string") { | |
if (n < 2) listener = false; | |
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); | |
return this; | |
} | |
if (n < 2) return (n = this.node()["__on" + type]) && n._; | |
capture = false; | |
} | |
return this.each(d3_selection_on(type, listener, capture)); | |
}; | |
function d3_selection_on(type, listener, capture) { | |
var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; | |
if (i > 0) type = type.slice(0, i); | |
var filter = d3_selection_onFilters.get(type); | |
if (filter) type = filter, wrap = d3_selection_onFilter; | |
function onRemove() { | |
var l = this[name]; | |
if (l) { | |
this.removeEventListener(type, l, l.$); | |
delete this[name]; | |
} | |
} | |
function onAdd() { | |
var l = wrap(listener, d3_array(arguments)); | |
onRemove.call(this); | |
this.addEventListener(type, this[name] = l, l.$ = capture); | |
l._ = listener; | |
} | |
function removeAll() { | |
var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; | |
for (var name in this) { | |
if (match = name.match(re)) { | |
var l = this[name]; | |
this.removeEventListener(match[1], l, l.$); | |
delete this[name]; | |
} | |
} | |
} | |
return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; | |
} | |
var d3_selection_onFilters = d3.map({ | |
mouseenter: "mouseover", | |
mouseleave: "mouseout" | |
}); | |
if (d3_document) { | |
d3_selection_onFilters.forEach(function(k) { | |
if ("on" + k in d3_document) d3_selection_onFilters.remove(k); | |
}); | |
} | |
function d3_selection_onListener(listener, argumentz) { | |
return function(e) { | |
var o = d3.event; | |
d3.event = e; | |
argumentz[0] = this.__data__; | |
try { | |
listener.apply(this, argumentz); | |
} finally { | |
d3.event = o; | |
} | |
}; | |
} | |
function d3_selection_onFilter(listener, argumentz) { | |
var l = d3_selection_onListener(listener, argumentz); | |
return function(e) { | |
var target = this, related = e.relatedTarget; | |
if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { | |
l.call(target, e); | |
} | |
}; | |
} | |
var d3_event_dragSelect, d3_event_dragId = 0; | |
function d3_event_dragSuppress(node) { | |
var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); | |
if (d3_event_dragSelect == null) { | |
d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); | |
} | |
if (d3_event_dragSelect) { | |
var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; | |
style[d3_event_dragSelect] = "none"; | |
} | |
return function(suppressClick) { | |
w.on(name, null); | |
if (d3_event_dragSelect) style[d3_event_dragSelect] = select; | |
if (suppressClick) { | |
var off = function() { | |
w.on(click, null); | |
}; | |
w.on(click, function() { | |
d3_eventPreventDefault(); | |
off(); | |
}, true); | |
setTimeout(off, 0); | |
} | |
}; | |
} | |
d3.mouse = function(container) { | |
return d3_mousePoint(container, d3_eventSource()); | |
}; | |
var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; | |
function d3_mousePoint(container, e) { | |
if (e.changedTouches) e = e.changedTouches[0]; | |
var svg = container.ownerSVGElement || container; | |
if (svg.createSVGPoint) { | |
var point = svg.createSVGPoint(); | |
if (d3_mouse_bug44083 < 0) { | |
var window = d3_window(container); | |
if (window.scrollX || window.scrollY) { | |
svg = d3.select("body").append("svg").style({ | |
position: "absolute", | |
top: 0, | |
left: 0, | |
margin: 0, | |
padding: 0, | |
border: "none" | |
}, "important"); | |
var ctm = svg[0][0].getScreenCTM(); | |
d3_mouse_bug44083 = !(ctm.f || ctm.e); | |
svg.remove(); | |
} | |
} | |
if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, | |
point.y = e.clientY; | |
point = point.matrixTransform(container.getScreenCTM().inverse()); | |
return [ point.x, point.y ]; | |
} | |
var rect = container.getBoundingClientRect(); | |
return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; | |
} | |
d3.touch = function(container, touches, identifier) { | |
if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; | |
if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { | |
if ((touch = touches[i]).identifier === identifier) { | |
return d3_mousePoint(container, touch); | |
} | |
} | |
}; | |
d3.behavior.drag = function() { | |
var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); | |
function drag() { | |
this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); | |
} | |
function dragstart(id, position, subject, move, end) { | |
return function() { | |
var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); | |
if (origin) { | |
dragOffset = origin.apply(that, arguments); | |
dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; | |
} else { | |
dragOffset = [ 0, 0 ]; | |
} | |
dispatch({ | |
type: "dragstart" | |
}); | |
function moved() { | |
var position1 = position(parent, dragId), dx, dy; | |
if (!position1) return; | |
dx = position1[0] - position0[0]; | |
dy = position1[1] - position0[1]; | |
dragged |= dx | dy; | |
position0 = position1; | |
dispatch({ | |
type: "drag", | |
x: position1[0] + dragOffset[0], | |
y: position1[1] + dragOffset[1], | |
dx: dx, | |
dy: dy | |
}); | |
} | |
function ended() { | |
if (!position(parent, dragId)) return; | |
dragSubject.on(move + dragName, null).on(end + dragName, null); | |
dragRestore(dragged); | |
dispatch({ | |
type: "dragend" | |
}); | |
} | |
}; | |
} | |
drag.origin = function(x) { | |
if (!arguments.length) return origin; | |
origin = x; | |
return drag; | |
}; | |
return d3.rebind(drag, event, "on"); | |
}; | |
function d3_behavior_dragTouchId() { | |
return d3.event.changedTouches[0].identifier; | |
} | |
d3.touches = function(container, touches) { | |
if (arguments.length < 2) touches = d3_eventSource().touches; | |
return touches ? d3_array(touches).map(function(touch) { | |
var point = d3_mousePoint(container, touch); | |
point.identifier = touch.identifier; | |
return point; | |
}) : []; | |
}; | |
var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; | |
function d3_sgn(x) { | |
return x > 0 ? 1 : x < 0 ? -1 : 0; | |
} | |
function d3_cross2d(a, b, c) { | |
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); | |
} | |
function d3_acos(x) { | |
return x > 1 ? 0 : x < -1 ? π : Math.acos(x); | |
} | |
function d3_asin(x) { | |
return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); | |
} | |
function d3_sinh(x) { | |
return ((x = Math.exp(x)) - 1 / x) / 2; | |
} | |
function d3_cosh(x) { | |
return ((x = Math.exp(x)) + 1 / x) / 2; | |
} | |
function d3_tanh(x) { | |
return ((x = Math.exp(2 * x)) - 1) / (x + 1); | |
} | |
function d3_haversin(x) { | |
return (x = Math.sin(x / 2)) * x; | |
} | |
var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; | |
d3.interpolateZoom = function(p0, p1) { | |
var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; | |
if (d2 < ε2) { | |
S = Math.log(w1 / w0) / ρ; | |
i = function(t) { | |
return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; | |
}; | |
} else { | |
var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); | |
S = (r1 - r0) / ρ; | |
i = function(t) { | |
var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); | |
return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; | |
}; | |
} | |
i.duration = S * 1e3; | |
return i; | |
}; | |
d3.behavior.zoom = function() { | |
var view = { | |
x: 0, | |
y: 0, | |
k: 1 | |
}, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; | |
if (!d3_behavior_zoomWheel) { | |
d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { | |
return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); | |
}, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { | |
return d3.event.wheelDelta; | |
}, "mousewheel") : (d3_behavior_zoomDelta = function() { | |
return -d3.event.detail; | |
}, "MozMousePixelScroll"); | |
} | |
function zoom(g) { | |
g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); | |
} | |
zoom.event = function(g) { | |
g.each(function() { | |
var dispatch = event.of(this, arguments), view1 = view; | |
if (d3_transitionInheritId) { | |
d3.select(this).transition().each("start.zoom", function() { | |
view = this.__chart__ || { | |
x: 0, | |
y: 0, | |
k: 1 | |
}; | |
zoomstarted(dispatch); | |
}).tween("zoom:zoom", function() { | |
var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); | |
return function(t) { | |
var l = i(t), k = dx / l[2]; | |
this.__chart__ = view = { | |
x: cx - l[0] * k, | |
y: cy - l[1] * k, | |
k: k | |
}; | |
zoomed(dispatch); | |
}; | |
}).each("interrupt.zoom", function() { | |
zoomended(dispatch); | |
}).each("end.zoom", function() { | |
zoomended(dispatch); | |
}); | |
} else { | |
this.__chart__ = view; | |
zoomstarted(dispatch); | |
zoomed(dispatch); | |
zoomended(dispatch); | |
} | |
}); | |
}; | |
zoom.translate = function(_) { | |
if (!arguments.length) return [ view.x, view.y ]; | |
view = { | |
x: +_[0], | |
y: +_[1], | |
k: view.k | |
}; | |
rescale(); | |
return zoom; | |
}; | |
zoom.scale = function(_) { | |
if (!arguments.length) return view.k; | |
view = { | |
x: view.x, | |
y: view.y, | |
k: null | |
}; | |
scaleTo(+_); | |
rescale(); | |
return zoom; | |
}; | |
zoom.scaleExtent = function(_) { | |
if (!arguments.length) return scaleExtent; | |
scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; | |
return zoom; | |
}; | |
zoom.center = function(_) { | |
if (!arguments.length) return center; | |
center = _ && [ +_[0], +_[1] ]; | |
return zoom; | |
}; | |
zoom.size = function(_) { | |
if (!arguments.length) return size; | |
size = _ && [ +_[0], +_[1] ]; | |
return zoom; | |
}; | |
zoom.duration = function(_) { | |
if (!arguments.length) return duration; | |
duration = +_; | |
return zoom; | |
}; | |
zoom.x = function(z) { | |
if (!arguments.length) return x1; | |
x1 = z; | |
x0 = z.copy(); | |
view = { | |
x: 0, | |
y: 0, | |
k: 1 | |
}; | |
return zoom; | |
}; | |
zoom.y = function(z) { | |
if (!arguments.length) return y1; | |
y1 = z; | |
y0 = z.copy(); | |
view = { | |
x: 0, | |
y: 0, | |
k: 1 | |
}; | |
return zoom; | |
}; | |
function location(p) { | |
return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; | |
} | |
function point(l) { | |
return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; | |
} | |
function scaleTo(s) { | |
view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); | |
} | |
function translateTo(p, l) { | |
l = point(l); | |
view.x += p[0] - l[0]; | |
view.y += p[1] - l[1]; | |
} | |
function zoomTo(that, p, l, k) { | |
that.__chart__ = { | |
x: view.x, | |
y: view.y, | |
k: view.k | |
}; | |
scaleTo(Math.pow(2, k)); | |
translateTo(center0 = p, l); | |
that = d3.select(that); | |
if (duration > 0) that = that.transition().duration(duration); | |
that.call(zoom.event); | |
} | |
function rescale() { | |
if (x1) x1.domain(x0.range().map(function(x) { | |
return (x - view.x) / view.k; | |
}).map(x0.invert)); | |
if (y1) y1.domain(y0.range().map(function(y) { | |
return (y - view.y) / view.k; | |
}).map(y0.invert)); | |
} | |
function zoomstarted(dispatch) { | |
if (!zooming++) dispatch({ | |
type: "zoomstart" | |
}); | |
} | |
function zoomed(dispatch) { | |
rescale(); | |
dispatch({ | |
type: "zoom", | |
scale: view.k, | |
translate: [ view.x, view.y ] | |
}); | |
} | |
function zoomended(dispatch) { | |
if (!--zooming) dispatch({ | |
type: "zoomend" | |
}), center0 = null; | |
} | |
function mousedowned() { | |
var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); | |
d3_selection_interrupt.call(that); | |
zoomstarted(dispatch); | |
function moved() { | |
dragged = 1; | |
translateTo(d3.mouse(that), location0); | |
zoomed(dispatch); | |
} | |
function ended() { | |
subject.on(mousemove, null).on(mouseup, null); | |
dragRestore(dragged); | |
zoomended(dispatch); | |
} | |
} | |
function touchstarted() { | |
var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); | |
started(); | |
zoomstarted(dispatch); | |
subject.on(mousedown, null).on(touchstart, started); | |
function relocate() { | |
var touches = d3.touches(that); | |
scale0 = view.k; | |
touches.forEach(function(t) { | |
if (t.identifier in locations0) locations0[t.identifier] = location(t); | |
}); | |
return touches; | |
} | |
function started() { | |
var target = d3.event.target; | |
d3.select(target).on(touchmove, moved).on(touchend, ended); | |
targets.push(target); | |
var changed = d3.event.changedTouches; | |
for (var i = 0, n = changed.length; i < n; ++i) { | |
locations0[changed[i].identifier] = null; | |
} | |
var touches = relocate(), now = Date.now(); | |
if (touches.length === 1) { | |
if (now - touchtime < 500) { | |
var p = touches[0]; | |
zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); | |
d3_eventPreventDefault(); | |
} | |
touchtime = now; | |
} else if (touches.length > 1) { | |
var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; | |
distance0 = dx * dx + dy * dy; | |
} | |
} | |
function moved() { | |
var touches = d3.touches(that), p0, l0, p1, l1; | |
d3_selection_interrupt.call(that); | |
for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { | |
p1 = touches[i]; | |
if (l1 = locations0[p1.identifier]) { | |
if (l0) break; | |
p0 = p1, l0 = l1; | |
} | |
} | |
if (l1) { | |
var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); | |
p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; | |
l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; | |
scaleTo(scale1 * scale0); | |
} | |
touchtime = null; | |
translateTo(p0, l0); | |
zoomed(dispatch); | |
} | |
function ended() { | |
if (d3.event.touches.length) { | |
var changed = d3.event.changedTouches; | |
for (var i = 0, n = changed.length; i < n; ++i) { | |
delete locations0[changed[i].identifier]; | |
} | |
for (var identifier in locations0) { | |
return void relocate(); | |
} | |
} | |
d3.selectAll(targets).on(zoomName, null); | |
subject.on(mousedown, mousedowned).on(touchstart, touchstarted); | |
dragRestore(); | |
zoomended(dispatch); | |
} | |
} | |
function mousewheeled() { | |
var dispatch = event.of(this, arguments); | |
if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), | |
translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); | |
mousewheelTimer = setTimeout(function() { | |
mousewheelTimer = null; | |
zoomended(dispatch); | |
}, 50); | |
d3_eventPreventDefault(); | |
scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); | |
translateTo(center0, translate0); | |
zoomed(dispatch); | |
} | |
function dblclicked() { | |
var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; | |
zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); | |
} | |
return d3.rebind(zoom, event, "on"); | |
}; | |
var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; | |
d3.color = d3_color; | |
function d3_color() {} | |
d3_color.prototype.toString = function() { | |
return this.rgb() + ""; | |
}; | |
d3.hsl = d3_hsl; | |
function d3_hsl(h, s, l) { | |
return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); | |
} | |
var d3_hslPrototype = d3_hsl.prototype = new d3_color(); | |
d3_hslPrototype.brighter = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return new d3_hsl(this.h, this.s, this.l / k); | |
}; | |
d3_hslPrototype.darker = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return new d3_hsl(this.h, this.s, k * this.l); | |
}; | |
d3_hslPrototype.rgb = function() { | |
return d3_hsl_rgb(this.h, this.s, this.l); | |
}; | |
function d3_hsl_rgb(h, s, l) { | |
var m1, m2; | |
h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; | |
s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; | |
l = l < 0 ? 0 : l > 1 ? 1 : l; | |
m2 = l <= .5 ? l * (1 + s) : l + s - l * s; | |
m1 = 2 * l - m2; | |
function v(h) { | |
if (h > 360) h -= 360; else if (h < 0) h += 360; | |
if (h < 60) return m1 + (m2 - m1) * h / 60; | |
if (h < 180) return m2; | |
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; | |
return m1; | |
} | |
function vv(h) { | |
return Math.round(v(h) * 255); | |
} | |
return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); | |
} | |
d3.hcl = d3_hcl; | |
function d3_hcl(h, c, l) { | |
return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); | |
} | |
var d3_hclPrototype = d3_hcl.prototype = new d3_color(); | |
d3_hclPrototype.brighter = function(k) { | |
return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); | |
}; | |
d3_hclPrototype.darker = function(k) { | |
return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); | |
}; | |
d3_hclPrototype.rgb = function() { | |
return d3_hcl_lab(this.h, this.c, this.l).rgb(); | |
}; | |
function d3_hcl_lab(h, c, l) { | |
if (isNaN(h)) h = 0; | |
if (isNaN(c)) c = 0; | |
return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); | |
} | |
d3.lab = d3_lab; | |
function d3_lab(l, a, b) { | |
return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); | |
} | |
var d3_lab_K = 18; | |
var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; | |
var d3_labPrototype = d3_lab.prototype = new d3_color(); | |
d3_labPrototype.brighter = function(k) { | |
return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | |
}; | |
d3_labPrototype.darker = function(k) { | |
return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | |
}; | |
d3_labPrototype.rgb = function() { | |
return d3_lab_rgb(this.l, this.a, this.b); | |
}; | |
function d3_lab_rgb(l, a, b) { | |
var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; | |
x = d3_lab_xyz(x) * d3_lab_X; | |
y = d3_lab_xyz(y) * d3_lab_Y; | |
z = d3_lab_xyz(z) * d3_lab_Z; | |
return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); | |
} | |
function d3_lab_hcl(l, a, b) { | |
return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); | |
} | |
function d3_lab_xyz(x) { | |
return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; | |
} | |
function d3_xyz_lab(x) { | |
return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; | |
} | |
function d3_xyz_rgb(r) { | |
return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); | |
} | |
d3.rgb = d3_rgb; | |
function d3_rgb(r, g, b) { | |
return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); | |
} | |
function d3_rgbNumber(value) { | |
return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); | |
} | |
function d3_rgbString(value) { | |
return d3_rgbNumber(value) + ""; | |
} | |
var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); | |
d3_rgbPrototype.brighter = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
var r = this.r, g = this.g, b = this.b, i = 30; | |
if (!r && !g && !b) return new d3_rgb(i, i, i); | |
if (r && r < i) r = i; | |
if (g && g < i) g = i; | |
if (b && b < i) b = i; | |
return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); | |
}; | |
d3_rgbPrototype.darker = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return new d3_rgb(k * this.r, k * this.g, k * this.b); | |
}; | |
d3_rgbPrototype.hsl = function() { | |
return d3_rgb_hsl(this.r, this.g, this.b); | |
}; | |
d3_rgbPrototype.toString = function() { | |
return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); | |
}; | |
function d3_rgb_hex(v) { | |
return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); | |
} | |
function d3_rgb_parse(format, rgb, hsl) { | |
var r = 0, g = 0, b = 0, m1, m2, color; | |
m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); | |
if (m1) { | |
m2 = m1[2].split(","); | |
switch (m1[1]) { | |
case "hsl": | |
{ | |
return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); | |
} | |
case "rgb": | |
{ | |
return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); | |
} | |
} | |
} | |
if (color = d3_rgb_names.get(format)) { | |
return rgb(color.r, color.g, color.b); | |
} | |
if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { | |
if (format.length === 4) { | |
r = (color & 3840) >> 4; | |
r = r >> 4 | r; | |
g = color & 240; | |
g = g >> 4 | g; | |
b = color & 15; | |
b = b << 4 | b; | |
} else if (format.length === 7) { | |
r = (color & 16711680) >> 16; | |
g = (color & 65280) >> 8; | |
b = color & 255; | |
} | |
} | |
return rgb(r, g, b); | |
} | |
function d3_rgb_hsl(r, g, b) { | |
var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; | |
if (d) { | |
s = l < .5 ? d / (max + min) : d / (2 - max - min); | |
if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; | |
h *= 60; | |
} else { | |
h = NaN; | |
s = l > 0 && l < 1 ? 0 : h; | |
} | |
return new d3_hsl(h, s, l); | |
} | |
function d3_rgb_lab(r, g, b) { | |
r = d3_rgb_xyz(r); | |
g = d3_rgb_xyz(g); | |
b = d3_rgb_xyz(b); | |
var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); | |
return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); | |
} | |
function d3_rgb_xyz(r) { | |
return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); | |
} | |
function d3_rgb_parseNumber(c) { | |
var f = parseFloat(c); | |
return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; | |
} | |
var d3_rgb_names = d3.map({ | |
aliceblue: 15792383, | |
antiquewhite: 16444375, | |
aqua: 65535, | |
aquamarine: 8388564, | |
azure: 15794175, | |
beige: 16119260, | |
bisque: 16770244, | |
black: 0, | |
blanchedalmond: 16772045, | |
blue: 255, | |
blueviolet: 9055202, | |
brown: 10824234, | |
burlywood: 14596231, | |
cadetblue: 6266528, | |
chartreuse: 8388352, | |
chocolate: 13789470, | |
coral: 16744272, | |
cornflowerblue: 6591981, | |
cornsilk: 16775388, | |
crimson: 14423100, | |
cyan: 65535, | |
darkblue: 139, | |
darkcyan: 35723, | |
darkgoldenrod: 12092939, | |
darkgray: 11119017, | |
darkgreen: 25600, | |
darkgrey: 11119017, | |
darkkhaki: 12433259, | |
darkmagenta: 9109643, | |
darkolivegreen: 5597999, | |
darkorange: 16747520, | |
darkorchid: 10040012, | |
darkred: 9109504, | |
darksalmon: 15308410, | |
darkseagreen: 9419919, | |
darkslateblue: 4734347, | |
darkslategray: 3100495, | |
darkslategrey: 3100495, | |
darkturquoise: 52945, | |
darkviolet: 9699539, | |
deeppink: 16716947, | |
deepskyblue: 49151, | |
dimgray: 6908265, | |
dimgrey: 6908265, | |
dodgerblue: 2003199, | |
firebrick: 11674146, | |
floralwhite: 16775920, | |
forestgreen: 2263842, | |
fuchsia: 16711935, | |
gainsboro: 14474460, | |
ghostwhite: 16316671, | |
gold: 16766720, | |
goldenrod: 14329120, | |
gray: 8421504, | |
green: 32768, | |
greenyellow: 11403055, | |
grey: 8421504, | |
honeydew: 15794160, | |
hotpink: 16738740, | |
indianred: 13458524, | |
indigo: 4915330, | |
ivory: 16777200, | |
khaki: 15787660, | |
lavender: 15132410, | |
lavenderblush: 16773365, | |
lawngreen: 8190976, | |
lemonchiffon: 16775885, | |
lightblue: 11393254, | |
lightcoral: 15761536, | |
lightcyan: 14745599, | |
lightgoldenrodyellow: 16448210, | |
lightgray: 13882323, | |
lightgreen: 9498256, | |
lightgrey: 13882323, | |
lightpink: 16758465, | |
lightsalmon: 16752762, | |
lightseagreen: 2142890, | |
lightskyblue: 8900346, | |
lightslategray: 7833753, | |
lightslategrey: 7833753, | |
lightsteelblue: 11584734, | |
lightyellow: 16777184, | |
lime: 65280, | |
limegreen: 3329330, | |
linen: 16445670, | |
magenta: 16711935, | |
maroon: 8388608, | |
mediumaquamarine: 6737322, | |
mediumblue: 205, | |
mediumorchid: 12211667, | |
mediumpurple: 9662683, | |
mediumseagreen: 3978097, | |
mediumslateblue: 8087790, | |
mediumspringgreen: 64154, | |
mediumturquoise: 4772300, | |
mediumvioletred: 13047173, | |
midnightblue: 1644912, | |
mintcream: 16121850, | |
mistyrose: 16770273, | |
moccasin: 16770229, | |
navajowhite: 16768685, | |
navy: 128, | |
oldlace: 16643558, | |
olive: 8421376, | |
olivedrab: 7048739, | |
orange: 16753920, | |
orangered: 16729344, | |
orchid: 14315734, | |
palegoldenrod: 15657130, | |
palegreen: 10025880, | |
paleturquoise: 11529966, | |
palevioletred: 14381203, | |
papayawhip: 16773077, | |
peachpuff: 16767673, | |
peru: 13468991, | |
pink: 16761035, | |
plum: 14524637, | |
powderblue: 11591910, | |
purple: 8388736, | |
rebeccapurple: 6697881, | |
red: 16711680, | |
rosybrown: 12357519, | |
royalblue: 4286945, | |
saddlebrown: 9127187, | |
salmon: 16416882, | |
sandybrown: 16032864, | |
seagreen: 3050327, | |
seashell: 16774638, | |
sienna: 10506797, | |
silver: 12632256, | |
skyblue: 8900331, | |
slateblue: 6970061, | |
slategray: 7372944, | |
slategrey: 7372944, | |
snow: 16775930, | |
springgreen: 65407, | |
steelblue: 4620980, | |
tan: 13808780, | |
teal: 32896, | |
thistle: 14204888, | |
tomato: 16737095, | |
turquoise: 4251856, | |
violet: 15631086, | |
wheat: 16113331, | |
white: 16777215, | |
whitesmoke: 16119285, | |
yellow: 16776960, | |
yellowgreen: 10145074 | |
}); | |
d3_rgb_names.forEach(function(key, value) { | |
d3_rgb_names.set(key, d3_rgbNumber(value)); | |
}); | |
function d3_functor(v) { | |
return typeof v === "function" ? v : function() { | |
return v; | |
}; | |
} | |
d3.functor = d3_functor; | |
d3.xhr = d3_xhrType(d3_identity); | |
function d3_xhrType(response) { | |
return function(url, mimeType, callback) { | |
if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, | |
mimeType = null; | |
return d3_xhr(url, mimeType, response, callback); | |
}; | |
} | |
function d3_xhr(url, mimeType, response, callback) { | |
var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; | |
if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); | |
"onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { | |
request.readyState > 3 && respond(); | |
}; | |
function respond() { | |
var status = request.status, result; | |
if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { | |
try { | |
result = response.call(xhr, request); | |
} catch (e) { | |
dispatch.error.call(xhr, e); | |
return; | |
} | |
dispatch.load.call(xhr, result); | |
} else { | |
dispatch.error.call(xhr, request); | |
} | |
} | |
request.onprogress = function(event) { | |
var o = d3.event; | |
d3.event = event; | |
try { | |
dispatch.progress.call(xhr, request); | |
} finally { | |
d3.event = o; | |
} | |
}; | |
xhr.header = function(name, value) { | |
name = (name + "").toLowerCase(); | |
if (arguments.length < 2) return headers[name]; | |
if (value == null) delete headers[name]; else headers[name] = value + ""; | |
return xhr; | |
}; | |
xhr.mimeType = function(value) { | |
if (!arguments.length) return mimeType; | |
mimeType = value == null ? null : value + ""; | |
return xhr; | |
}; | |
xhr.responseType = function(value) { | |
if (!arguments.length) return responseType; | |
responseType = value; | |
return xhr; | |
}; | |
xhr.response = function(value) { | |
response = value; | |
return xhr; | |
}; | |
[ "get", "post" ].forEach(function(method) { | |
xhr[method] = function() { | |
return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); | |
}; | |
}); | |
xhr.send = function(method, data, callback) { | |
if (arguments.length === 2 && typeof data === "function") callback = data, data = null; | |
request.open(method, url, true); | |
if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; | |
if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); | |
if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); | |
if (responseType != null) request.responseType = responseType; | |
if (callback != null) xhr.on("error", callback).on("load", function(request) { | |
callback(null, request); | |
}); | |
dispatch.beforesend.call(xhr, request); | |
request.send(data == null ? null : data); | |
return xhr; | |
}; | |
xhr.abort = function() { | |
request.abort(); | |
return xhr; | |
}; | |
d3.rebind(xhr, dispatch, "on"); | |
return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); | |
} | |
function d3_xhr_fixCallback(callback) { | |
return callback.length === 1 ? function(error, request) { | |
callback(error == null ? request : null); | |
} : callback; | |
} | |
function d3_xhrHasResponse(request) { | |
var type = request.responseType; | |
return type && type !== "text" ? request.response : request.responseText; | |
} | |
d3.dsv = function(delimiter, mimeType) { | |
var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); | |
function dsv(url, row, callback) { | |
if (arguments.length < 3) callback = row, row = null; | |
var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); | |
xhr.row = function(_) { | |
return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; | |
}; | |
return xhr; | |
} | |
function response(request) { | |
return dsv.parse(request.responseText); | |
} | |
function typedResponse(f) { | |
return function(request) { | |
return dsv.parse(request.responseText, f); | |
}; | |
} | |
dsv.parse = function(text, f) { | |
var o; | |
return dsv.parseRows(text, function(row, i) { | |
if (o) return o(row, i - 1); | |
var a = new Function("d", "return {" + row.map(function(name, i) { | |
return JSON.stringify(name) + ": d[" + i + "]"; | |
}).join(",") + "}"); | |
o = f ? function(row, i) { | |
return f(a(row), i); | |
} : a; | |
}); | |
}; | |
dsv.parseRows = function(text, f) { | |
var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; | |
function token() { | |
if (I >= N) return EOF; | |
if (eol) return eol = false, EOL; | |
var j = I; | |
if (text.charCodeAt(j) === 34) { | |
var i = j; | |
while (i++ < N) { | |
if (text.charCodeAt(i) === 34) { | |
if (text.charCodeAt(i + 1) !== 34) break; | |
++i; | |
} | |
} | |
I = i + 2; | |
var c = text.charCodeAt(i + 1); | |
if (c === 13) { | |
eol = true; | |
if (text.charCodeAt(i + 2) === 10) ++I; | |
} else if (c === 10) { | |
eol = true; | |
} | |
return text.slice(j + 1, i).replace(/""/g, '"'); | |
} | |
while (I < N) { | |
var c = text.charCodeAt(I++), k = 1; | |
if (c === 10) eol = true; else if (c === 13) { | |
eol = true; | |
if (text.charCodeAt(I) === 10) ++I, ++k; | |
} else if (c !== delimiterCode) continue; | |
return text.slice(j, I - k); | |
} | |
return text.slice(j); | |
} | |
while ((t = token()) !== EOF) { | |
var a = []; | |
while (t !== EOL && t !== EOF) { | |
a.push(t); | |
t = token(); | |
} | |
if (f && (a = f(a, n++)) == null) continue; | |
rows.push(a); | |
} | |
return rows; | |
}; | |
dsv.format = function(rows) { | |
if (Array.isArray(rows[0])) return dsv.formatRows(rows); | |
var fieldSet = new d3_Set(), fields = []; | |
rows.forEach(function(row) { | |
for (var field in row) { | |
if (!fieldSet.has(field)) { | |
fields.push(fieldSet.add(field)); | |
} | |
} | |
}); | |
return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { | |
return fields.map(function(field) { | |
return formatValue(row[field]); | |
}).join(delimiter); | |
})).join("\n"); | |
}; | |
dsv.formatRows = function(rows) { | |
return rows.map(formatRow).join("\n"); | |
}; | |
function formatRow(row) { | |
return row.map(formatValue).join(delimiter); | |
} | |
function formatValue(text) { | |
return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; | |
} | |
return dsv; | |
}; | |
d3.csv = d3.dsv(",", "text/csv"); | |
d3.tsv = d3.dsv(" ", "text/tab-separated-values"); | |
var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { | |
setTimeout(callback, 17); | |
}; | |
d3.timer = function() { | |
d3_timer.apply(this, arguments); | |
}; | |
function d3_timer(callback, delay, then) { | |
var n = arguments.length; | |
if (n < 2) delay = 0; | |
if (n < 3) then = Date.now(); | |
var time = then + delay, timer = { | |
c: callback, | |
t: time, | |
n: null | |
}; | |
if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; | |
d3_timer_queueTail = timer; | |
if (!d3_timer_interval) { | |
d3_timer_timeout = clearTimeout(d3_timer_timeout); | |
d3_timer_interval = 1; | |
d3_timer_frame(d3_timer_step); | |
} | |
return timer; | |
} | |
function d3_timer_step() { | |
var now = d3_timer_mark(), delay = d3_timer_sweep() - now; | |
if (delay > 24) { | |
if (isFinite(delay)) { | |
clearTimeout(d3_timer_timeout); | |
d3_timer_timeout = setTimeout(d3_timer_step, delay); | |
} | |
d3_timer_interval = 0; | |
} else { | |
d3_timer_interval = 1; | |
d3_timer_frame(d3_timer_step); | |
} | |
} | |
d3.timer.flush = function() { | |
d3_timer_mark(); | |
d3_timer_sweep(); | |
}; | |
function d3_timer_mark() { | |
var now = Date.now(), timer = d3_timer_queueHead; | |
while (timer) { | |
if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; | |
timer = timer.n; | |
} | |
return now; | |
} | |
function d3_timer_sweep() { | |
var t0, t1 = d3_timer_queueHead, time = Infinity; | |
while (t1) { | |
if (t1.c) { | |
if (t1.t < time) time = t1.t; | |
t1 = (t0 = t1).n; | |
} else { | |
t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; | |
} | |
} | |
d3_timer_queueTail = t0; | |
return time; | |
} | |
function d3_format_precision(x, p) { | |
return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); | |
} | |
d3.round = function(x, n) { | |
return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); | |
}; | |
var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); | |
d3.formatPrefix = function(value, precision) { | |
var i = 0; | |
if (value = +value) { | |
if (value < 0) value *= -1; | |
if (precision) value = d3.round(value, d3_format_precision(value, precision)); | |
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); | |
i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); | |
} | |
return d3_formatPrefixes[8 + i / 3]; | |
}; | |
function d3_formatPrefix(d, i) { | |
var k = Math.pow(10, abs(8 - i) * 3); | |
return { | |
scale: i > 8 ? function(d) { | |
return d / k; | |
} : function(d) { | |
return d * k; | |
}, | |
symbol: d | |
}; | |
} | |
function d3_locale_numberFormat(locale) { | |
var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { | |
var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; | |
while (i > 0 && g > 0) { | |
if (length + g + 1 > width) g = Math.max(1, width - length); | |
t.push(value.substring(i -= g, i + g)); | |
if ((length += g + 1) > width) break; | |
g = locale_grouping[j = (j + 1) % locale_grouping.length]; | |
} | |
return t.reverse().join(locale_thousands); | |
} : d3_identity; | |
return function(specifier) { | |
var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; | |
if (precision) precision = +precision.substring(1); | |
if (zfill || fill === "0" && align === "=") { | |
zfill = fill = "0"; | |
align = "="; | |
} | |
switch (type) { | |
case "n": | |
comma = true; | |
type = "g"; | |
break; | |
case "%": | |
scale = 100; | |
suffix = "%"; | |
type = "f"; | |
break; | |
case "p": | |
scale = 100; | |
suffix = "%"; | |
type = "r"; | |
break; | |
case "b": | |
case "o": | |
case "x": | |
case "X": | |
if (symbol === "#") prefix = "0" + type.toLowerCase(); | |
case "c": | |
exponent = false; | |
case "d": | |
integer = true; | |
precision = 0; | |
break; | |
case "s": | |
scale = -1; | |
type = "r"; | |
break; | |
} | |
if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; | |
if (type == "r" && !precision) type = "g"; | |
if (precision != null) { | |
if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); | |
} | |
type = d3_format_types.get(type) || d3_format_typeDefault; | |
var zcomma = zfill && comma; | |
return function(value) { | |
var fullSuffix = suffix; | |
if (integer && value % 1) return ""; | |
var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; | |
if (scale < 0) { | |
var unit = d3.formatPrefix(value, precision); | |
value = unit.scale(value); | |
fullSuffix = unit.symbol + suffix; | |
} else { | |
value *= scale; | |
} | |
value = type(value, precision); | |
var i = value.lastIndexOf("."), before, after; | |
if (i < 0) { | |
var j = exponent ? value.lastIndexOf("e") : -1; | |
if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); | |
} else { | |
before = value.substring(0, i); | |
after = locale_decimal + value.substring(i + 1); | |
} | |
if (!zfill && comma) before = formatGroup(before, Infinity); | |
var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; | |
if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); | |
negative += prefix; | |
value = before + after; | |
return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; | |
}; | |
}; | |
} | |
var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; | |
var d3_format_types = d3.map({ | |
b: function(x) { | |
return x.toString(2); | |
}, | |
c: function(x) { | |
return String.fromCharCode(x); | |
}, | |
o: function(x) { | |
return x.toString(8); | |
}, | |
x: function(x) { | |
return x.toString(16); | |
}, | |
X: function(x) { | |
return x.toString(16).toUpperCase(); | |
}, | |
g: function(x, p) { | |
return x.toPrecision(p); | |
}, | |
e: function(x, p) { | |
return x.toExponential(p); | |
}, | |
f: function(x, p) { | |
return x.toFixed(p); | |
}, | |
r: function(x, p) { | |
return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); | |
} | |
}); | |
function d3_format_typeDefault(x) { | |
return x + ""; | |
} | |
var d3_time = d3.time = {}, d3_date = Date; | |
function d3_date_utc() { | |
this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); | |
} | |
d3_date_utc.prototype = { | |
getDate: function() { | |
return this._.getUTCDate(); | |
}, | |
getDay: function() { | |
return this._.getUTCDay(); | |
}, | |
getFullYear: function() { | |
return this._.getUTCFullYear(); | |
}, | |
getHours: function() { | |
return this._.getUTCHours(); | |
}, | |
getMilliseconds: function() { | |
return this._.getUTCMilliseconds(); | |
}, | |
getMinutes: function() { | |
return this._.getUTCMinutes(); | |
}, | |
getMonth: function() { | |
return this._.getUTCMonth(); | |
}, | |
getSeconds: function() { | |
return this._.getUTCSeconds(); | |
}, | |
getTime: function() { | |
return this._.getTime(); | |
}, | |
getTimezoneOffset: function() { | |
return 0; | |
}, | |
valueOf: function() { | |
return this._.valueOf(); | |
}, | |
setDate: function() { | |
d3_time_prototype.setUTCDate.apply(this._, arguments); | |
}, | |
setDay: function() { | |
d3_time_prototype.setUTCDay.apply(this._, arguments); | |
}, | |
setFullYear: function() { | |
d3_time_prototype.setUTCFullYear.apply(this._, arguments); | |
}, | |
setHours: function() { | |
d3_time_prototype.setUTCHours.apply(this._, arguments); | |
}, | |
setMilliseconds: function() { | |
d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); | |
}, | |
setMinutes: function() { | |
d3_time_prototype.setUTCMinutes.apply(this._, arguments); | |
}, | |
setMonth: function() { | |
d3_time_prototype.setUTCMonth.apply(this._, arguments); | |
}, | |
setSeconds: function() { | |
d3_time_prototype.setUTCSeconds.apply(this._, arguments); | |
}, | |
setTime: function() { | |
d3_time_prototype.setTime.apply(this._, arguments); | |
} | |
}; | |
var d3_time_prototype = Date.prototype; | |
function d3_time_interval(local, step, number) { | |
function round(date) { | |
var d0 = local(date), d1 = offset(d0, 1); | |
return date - d0 < d1 - date ? d0 : d1; | |
} | |
function ceil(date) { | |
step(date = local(new d3_date(date - 1)), 1); | |
return date; | |
} | |
function offset(date, k) { | |
step(date = new d3_date(+date), k); | |
return date; | |
} | |
function range(t0, t1, dt) { | |
var time = ceil(t0), times = []; | |
if (dt > 1) { | |
while (time < t1) { | |
if (!(number(time) % dt)) times.push(new Date(+time)); | |
step(time, 1); | |
} | |
} else { | |
while (time < t1) times.push(new Date(+time)), step(time, 1); | |
} | |
return times; | |
} | |
function range_utc(t0, t1, dt) { | |
try { | |
d3_date = d3_date_utc; | |
var utc = new d3_date_utc(); | |
utc._ = t0; | |
return range(utc, t1, dt); | |
} finally { | |
d3_date = Date; | |
} | |
} | |
local.floor = local; | |
local.round = round; | |
local.ceil = ceil; | |
local.offset = offset; | |
local.range = range; | |
var utc = local.utc = d3_time_interval_utc(local); | |
utc.floor = utc; | |
utc.round = d3_time_interval_utc(round); | |
utc.ceil = d3_time_interval_utc(ceil); | |
utc.offset = d3_time_interval_utc(offset); | |
utc.range = range_utc; | |
return local; | |
} | |
function d3_time_interval_utc(method) { | |
return function(date, k) { | |
try { | |
d3_date = d3_date_utc; | |
var utc = new d3_date_utc(); | |
utc._ = date; | |
return method(utc, k)._; | |
} finally { | |
d3_date = Date; | |
} | |
}; | |
} | |
d3_time.year = d3_time_interval(function(date) { | |
date = d3_time.day(date); | |
date.setMonth(0, 1); | |
return date; | |
}, function(date, offset) { | |
date.setFullYear(date.getFullYear() + offset); | |
}, function(date) { | |
return date.getFullYear(); | |
}); | |
d3_time.years = d3_time.year.range; | |
d3_time.years.utc = d3_time.year.utc.range; | |
d3_time.day = d3_time_interval(function(date) { | |
var day = new d3_date(2e3, 0); | |
day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); | |
return day; | |
}, function(date, offset) { | |
date.setDate(date.getDate() + offset); | |
}, function(date) { | |
return date.getDate() - 1; | |
}); | |
d3_time.days = d3_time.day.range; | |
d3_time.days.utc = d3_time.day.utc.range; | |
d3_time.dayOfYear = function(date) { | |
var year = d3_time.year(date); | |
return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); | |
}; | |
[ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { | |
i = 7 - i; | |
var interval = d3_time[day] = d3_time_interval(function(date) { | |
(date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); | |
return date; | |
}, function(date, offset) { | |
date.setDate(date.getDate() + Math.floor(offset) * 7); | |
}, function(date) { | |
var day = d3_time.year(date).getDay(); | |
return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); | |
}); | |
d3_time[day + "s"] = interval.range; | |
d3_time[day + "s"].utc = interval.utc.range; | |
d3_time[day + "OfYear"] = function(date) { | |
var day = d3_time.year(date).getDay(); | |
return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); | |
}; | |
}); | |
d3_time.week = d3_time.sunday; | |
d3_time.weeks = d3_time.sunday.range; | |
d3_time.weeks.utc = d3_time.sunday.utc.range; | |
d3_time.weekOfYear = d3_time.sundayOfYear; | |
function d3_locale_timeFormat(locale) { | |
var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; | |
function d3_time_format(template) { | |
var n = template.length; | |
function format(date) { | |
var string = [], i = -1, j = 0, c, p, f; | |
while (++i < n) { | |
if (template.charCodeAt(i) === 37) { | |
string.push(template.slice(j, i)); | |
if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); | |
if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); | |
string.push(c); | |
j = i + 1; | |
} | |
} | |
string.push(template.slice(j, i)); | |
return string.join(""); | |
} | |
format.parse = function(string) { | |
var d = { | |
y: 1900, | |
m: 0, | |
d: 1, | |
H: 0, | |
M: 0, | |
S: 0, | |
L: 0, | |
Z: null | |
}, i = d3_time_parse(d, template, string, 0); | |
if (i != string.length) return null; | |
if ("p" in d) d.H = d.H % 12 + d.p * 12; | |
var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); | |
if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { | |
if (!("w" in d)) d.w = "W" in d ? 1 : 0; | |
date.setFullYear(d.y, 0, 1); | |
date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); | |
} else date.setFullYear(d.y, d.m, d.d); | |
date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); | |
return localZ ? date._ : date; | |
}; | |
format.toString = function() { | |
return template; | |
}; | |
return format; | |
} | |
function d3_time_parse(date, template, string, j) { | |
var c, p, t, i = 0, n = template.length, m = string.length; | |
while (i < n) { | |
if (j >= m) return -1; | |
c = template.charCodeAt(i++); | |
if (c === 37) { | |
t = template.charAt(i++); | |
p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; | |
if (!p || (j = p(date, string, j)) < 0) return -1; | |
} else if (c != string.charCodeAt(j++)) { | |
return -1; | |
} | |
} | |
return j; | |
} | |
d3_time_format.utc = function(template) { | |
var local = d3_time_format(template); | |
function format(date) { | |
try { | |
d3_date = d3_date_utc; | |
var utc = new d3_date(); | |
utc._ = date; | |
return local(utc); | |
} finally { | |
d3_date = Date; | |
} | |
} | |
format.parse = function(string) { | |
try { | |
d3_date = d3_date_utc; | |
var date = local.parse(string); | |
return date && date._; | |
} finally { | |
d3_date = Date; | |
} | |
}; | |
format.toString = local.toString; | |
return format; | |
}; | |
d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; | |
var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); | |
locale_periods.forEach(function(p, i) { | |
d3_time_periodLookup.set(p.toLowerCase(), i); | |
}); | |
var d3_time_formats = { | |
a: function(d) { | |
return locale_shortDays[d.getDay()]; | |
}, | |
A: function(d) { | |
return locale_days[d.getDay()]; | |
}, | |
b: function(d) { | |
return locale_shortMonths[d.getMonth()]; | |
}, | |
B: function(d) { | |
return locale_months[d.getMonth()]; | |
}, | |
c: d3_time_format(locale_dateTime), | |
d: function(d, p) { | |
return d3_time_formatPad(d.getDate(), p, 2); | |
}, | |
e: function(d, p) { | |
return d3_time_formatPad(d.getDate(), p, 2); | |
}, | |
H: function(d, p) { | |
return d3_time_formatPad(d.getHours(), p, 2); | |
}, | |
I: function(d, p) { | |
return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); | |
}, | |
j: function(d, p) { | |
return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); | |
}, | |
L: function(d, p) { | |
return d3_time_formatPad(d.getMilliseconds(), p, 3); | |
}, | |
m: function(d, p) { | |
return d3_time_formatPad(d.getMonth() + 1, p, 2); | |
}, | |
M: function(d, p) { | |
return d3_time_formatPad(d.getMinutes(), p, 2); | |
}, | |
p: function(d) { | |
return locale_periods[+(d.getHours() >= 12)]; | |
}, | |
S: function(d, p) { | |
return d3_time_formatPad(d.getSeconds(), p, 2); | |
}, | |
U: function(d, p) { | |
return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); | |
}, | |
w: function(d) { | |
return d.getDay(); | |
}, | |
W: function(d, p) { | |
return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); | |
}, | |
x: d3_time_format(locale_date), | |
X: d3_time_format(locale_time), | |
y: function(d, p) { | |
return d3_time_formatPad(d.getFullYear() % 100, p, 2); | |
}, | |
Y: function(d, p) { | |
return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); | |
}, | |
Z: d3_time_zone, | |
"%": function() { | |
return "%"; | |
} | |
}; | |
var d3_time_parsers = { | |
a: d3_time_parseWeekdayAbbrev, | |
A: d3_time_parseWeekday, | |
b: d3_time_parseMonthAbbrev, | |
B: d3_time_parseMonth, | |
c: d3_time_parseLocaleFull, | |
d: d3_time_parseDay, | |
e: d3_time_parseDay, | |
H: d3_time_parseHour24, | |
I: d3_time_parseHour24, | |
j: d3_time_parseDayOfYear, | |
L: d3_time_parseMilliseconds, | |
m: d3_time_parseMonthNumber, | |
M: d3_time_parseMinutes, | |
p: d3_time_parseAmPm, | |
S: d3_time_parseSeconds, | |
U: d3_time_parseWeekNumberSunday, | |
w: d3_time_parseWeekdayNumber, | |
W: d3_time_parseWeekNumberMonday, | |
x: d3_time_parseLocaleDate, | |
X: d3_time_parseLocaleTime, | |
y: d3_time_parseYear, | |
Y: d3_time_parseFullYear, | |
Z: d3_time_parseZone, | |
"%": d3_time_parseLiteralPercent | |
}; | |
function d3_time_parseWeekdayAbbrev(date, string, i) { | |
d3_time_dayAbbrevRe.lastIndex = 0; | |
var n = d3_time_dayAbbrevRe.exec(string.slice(i)); | |
return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function d3_time_parseWeekday(date, string, i) { | |
d3_time_dayRe.lastIndex = 0; | |
var n = d3_time_dayRe.exec(string.slice(i)); | |
return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function d3_time_parseMonthAbbrev(date, string, i) { | |
d3_time_monthAbbrevRe.lastIndex = 0; | |
var n = d3_time_monthAbbrevRe.exec(string.slice(i)); | |
return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function d3_time_parseMonth(date, string, i) { | |
d3_time_monthRe.lastIndex = 0; | |
var n = d3_time_monthRe.exec(string.slice(i)); | |
return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function d3_time_parseLocaleFull(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.c.toString(), string, i); | |
} | |
function d3_time_parseLocaleDate(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.x.toString(), string, i); | |
} | |
function d3_time_parseLocaleTime(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.X.toString(), string, i); | |
} | |
function d3_time_parseAmPm(date, string, i) { | |
var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); | |
return n == null ? -1 : (date.p = n, i); | |
} | |
return d3_time_format; | |
} | |
var d3_time_formatPads = { | |
"-": "", | |
_: " ", | |
"0": "0" | |
}, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; | |
function d3_time_formatPad(value, fill, width) { | |
var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; | |
return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); | |
} | |
function d3_time_formatRe(names) { | |
return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); | |
} | |
function d3_time_formatLookup(names) { | |
var map = new d3_Map(), i = -1, n = names.length; | |
while (++i < n) map.set(names[i].toLowerCase(), i); | |
return map; | |
} | |
function d3_time_parseWeekdayNumber(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 1)); | |
return n ? (date.w = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseWeekNumberSunday(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i)); | |
return n ? (date.U = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseWeekNumberMonday(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i)); | |
return n ? (date.W = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseFullYear(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 4)); | |
return n ? (date.y = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseYear(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; | |
} | |
function d3_time_parseZone(date, string, i) { | |
return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, | |
i + 5) : -1; | |
} | |
function d3_time_expandYear(d) { | |
return d + (d > 68 ? 1900 : 2e3); | |
} | |
function d3_time_parseMonthNumber(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.m = n[0] - 1, i + n[0].length) : -1; | |
} | |
function d3_time_parseDay(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.d = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseDayOfYear(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 3)); | |
return n ? (date.j = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseHour24(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.H = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseMinutes(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.M = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseSeconds(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 2)); | |
return n ? (date.S = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_parseMilliseconds(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.slice(i, i + 3)); | |
return n ? (date.L = +n[0], i + n[0].length) : -1; | |
} | |
function d3_time_zone(d) { | |
var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; | |
return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); | |
} | |
function d3_time_parseLiteralPercent(date, string, i) { | |
d3_time_percentRe.lastIndex = 0; | |
var n = d3_time_percentRe.exec(string.slice(i, i + 1)); | |
return n ? i + n[0].length : -1; | |
} | |
function d3_time_formatMulti(formats) { | |
var n = formats.length, i = -1; | |
while (++i < n) formats[i][0] = this(formats[i][0]); | |
return function(date) { | |
var i = 0, f = formats[i]; | |
while (!f[1](date)) f = formats[++i]; | |
return f[0](date); | |
}; | |
} | |
d3.locale = function(locale) { | |
return { | |
numberFormat: d3_locale_numberFormat(locale), | |
timeFormat: d3_locale_timeFormat(locale) | |
}; | |
}; | |
var d3_locale_enUS = d3.locale({ | |
decimal: ".", | |
thousands: ",", | |
grouping: [ 3 ], | |
currency: [ "$", "" ], | |
dateTime: "%a %b %e %X %Y", | |
date: "%m/%d/%Y", | |
time: "%H:%M:%S", | |
periods: [ "AM", "PM" ], | |
days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], | |
shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], | |
months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], | |
shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] | |
}); | |
d3.format = d3_locale_enUS.numberFormat; | |
d3.geo = {}; | |
function d3_adder() {} | |
d3_adder.prototype = { | |
s: 0, | |
t: 0, | |
add: function(y) { | |
d3_adderSum(y, this.t, d3_adderTemp); | |
d3_adderSum(d3_adderTemp.s, this.s, this); | |
if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; | |
}, | |
reset: function() { | |
this.s = this.t = 0; | |
}, | |
valueOf: function() { | |
return this.s; | |
} | |
}; | |
var d3_adderTemp = new d3_adder(); | |
function d3_adderSum(a, b, o) { | |
var x = o.s = a + b, bv = x - a, av = x - bv; | |
o.t = a - av + (b - bv); | |
} | |
d3.geo.stream = function(object, listener) { | |
if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { | |
d3_geo_streamObjectType[object.type](object, listener); | |
} else { | |
d3_geo_streamGeometry(object, listener); | |
} | |
}; | |
function d3_geo_streamGeometry(geometry, listener) { | |
if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { | |
d3_geo_streamGeometryType[geometry.type](geometry, listener); | |
} | |
} | |
var d3_geo_streamObjectType = { | |
Feature: function(feature, listener) { | |
d3_geo_streamGeometry(feature.geometry, listener); | |
}, | |
FeatureCollection: function(object, listener) { | |
var features = object.features, i = -1, n = features.length; | |
while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); | |
} | |
}; | |
var d3_geo_streamGeometryType = { | |
Sphere: function(object, listener) { | |
listener.sphere(); | |
}, | |
Point: function(object, listener) { | |
object = object.coordinates; | |
listener.point(object[0], object[1], object[2]); | |
}, | |
MultiPoint: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); | |
}, | |
LineString: function(object, listener) { | |
d3_geo_streamLine(object.coordinates, listener, 0); | |
}, | |
MultiLineString: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); | |
}, | |
Polygon: function(object, listener) { | |
d3_geo_streamPolygon(object.coordinates, listener); | |
}, | |
MultiPolygon: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); | |
}, | |
GeometryCollection: function(object, listener) { | |
var geometries = object.geometries, i = -1, n = geometries.length; | |
while (++i < n) d3_geo_streamGeometry(geometries[i], listener); | |
} | |
}; | |
function d3_geo_streamLine(coordinates, listener, closed) { | |
var i = -1, n = coordinates.length - closed, coordinate; | |
listener.lineStart(); | |
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); | |
listener.lineEnd(); | |
} | |
function d3_geo_streamPolygon(coordinates, listener) { | |
var i = -1, n = coordinates.length; | |
listener.polygonStart(); | |
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); | |
listener.polygonEnd(); | |
} | |
d3.geo.area = function(object) { | |
d3_geo_areaSum = 0; | |
d3.geo.stream(object, d3_geo_area); | |
return d3_geo_areaSum; | |
}; | |
var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); | |
var d3_geo_area = { | |
sphere: function() { | |
d3_geo_areaSum += 4 * π; | |
}, | |
point: d3_noop, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: function() { | |
d3_geo_areaRingSum.reset(); | |
d3_geo_area.lineStart = d3_geo_areaRingStart; | |
}, | |
polygonEnd: function() { | |
var area = 2 * d3_geo_areaRingSum; | |
d3_geo_areaSum += area < 0 ? 4 * π + area : area; | |
d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; | |
} | |
}; | |
function d3_geo_areaRingStart() { | |
var λ00, φ00, λ0, cosφ0, sinφ0; | |
d3_geo_area.point = function(λ, φ) { | |
d3_geo_area.point = nextPoint; | |
λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), | |
sinφ0 = Math.sin(φ); | |
}; | |
function nextPoint(λ, φ) { | |
λ *= d3_radians; | |
φ = φ * d3_radians / 2 + π / 4; | |
var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); | |
d3_geo_areaRingSum.add(Math.atan2(v, u)); | |
λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; | |
} | |
d3_geo_area.lineEnd = function() { | |
nextPoint(λ00, φ00); | |
}; | |
} | |
function d3_geo_cartesian(spherical) { | |
var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); | |
return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; | |
} | |
function d3_geo_cartesianDot(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
} | |
function d3_geo_cartesianCross(a, b) { | |
return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; | |
} | |
function d3_geo_cartesianAdd(a, b) { | |
a[0] += b[0]; | |
a[1] += b[1]; | |
a[2] += b[2]; | |
} | |
function d3_geo_cartesianScale(vector, k) { | |
return [ vector[0] * k, vector[1] * k, vector[2] * k ]; | |
} | |
function d3_geo_cartesianNormalize(d) { | |
var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); | |
d[0] /= l; | |
d[1] /= l; | |
d[2] /= l; | |
} | |
function d3_geo_spherical(cartesian) { | |
return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; | |
} | |
function d3_geo_sphericalEqual(a, b) { | |
return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; | |
} | |
d3.geo.bounds = function() { | |
var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; | |
var bound = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
bound.point = ringPoint; | |
bound.lineStart = ringStart; | |
bound.lineEnd = ringEnd; | |
dλSum = 0; | |
d3_geo_area.polygonStart(); | |
}, | |
polygonEnd: function() { | |
d3_geo_area.polygonEnd(); | |
bound.point = point; | |
bound.lineStart = lineStart; | |
bound.lineEnd = lineEnd; | |
if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; | |
range[0] = λ0, range[1] = λ1; | |
} | |
}; | |
function point(λ, φ) { | |
ranges.push(range = [ λ0 = λ, λ1 = λ ]); | |
if (φ < φ0) φ0 = φ; | |
if (φ > φ1) φ1 = φ; | |
} | |
function linePoint(λ, φ) { | |
var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); | |
if (p0) { | |
var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); | |
d3_geo_cartesianNormalize(inflection); | |
inflection = d3_geo_spherical(inflection); | |
var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; | |
if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { | |
var φi = inflection[1] * d3_degrees; | |
if (φi > φ1) φ1 = φi; | |
} else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { | |
var φi = -inflection[1] * d3_degrees; | |
if (φi < φ0) φ0 = φi; | |
} else { | |
if (φ < φ0) φ0 = φ; | |
if (φ > φ1) φ1 = φ; | |
} | |
if (antimeridian) { | |
if (λ < λ_) { | |
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; | |
} else { | |
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; | |
} | |
} else { | |
if (λ1 >= λ0) { | |
if (λ < λ0) λ0 = λ; | |
if (λ > λ1) λ1 = λ; | |
} else { | |
if (λ > λ_) { | |
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; | |
} else { | |
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; | |
} | |
} | |
} | |
} else { | |
point(λ, φ); | |
} | |
p0 = p, λ_ = λ; | |
} | |
function lineStart() { | |
bound.point = linePoint; | |
} | |
function lineEnd() { | |
range[0] = λ0, range[1] = λ1; | |
bound.point = point; | |
p0 = null; | |
} | |
function ringPoint(λ, φ) { | |
if (p0) { | |
var dλ = λ - λ_; | |
dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; | |
} else λ__ = λ, φ__ = φ; | |
d3_geo_area.point(λ, φ); | |
linePoint(λ, φ); | |
} | |
function ringStart() { | |
d3_geo_area.lineStart(); | |
} | |
function ringEnd() { | |
ringPoint(λ__, φ__); | |
d3_geo_area.lineEnd(); | |
if (abs(dλSum) > ε) λ0 = -(λ1 = 180); | |
range[0] = λ0, range[1] = λ1; | |
p0 = null; | |
} | |
function angle(λ0, λ1) { | |
return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; | |
} | |
function compareRanges(a, b) { | |
return a[0] - b[0]; | |
} | |
function withinRange(x, range) { | |
return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; | |
} | |
return function(feature) { | |
φ1 = λ1 = -(λ0 = φ0 = Infinity); | |
ranges = []; | |
d3.geo.stream(feature, bound); | |
var n = ranges.length; | |
if (n) { | |
ranges.sort(compareRanges); | |
for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { | |
b = ranges[i]; | |
if (withinRange(b[0], a) || withinRange(b[1], a)) { | |
if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; | |
if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; | |
} else { | |
merged.push(a = b); | |
} | |
} | |
var best = -Infinity, dλ; | |
for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { | |
b = merged[i]; | |
if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; | |
} | |
} | |
ranges = range = null; | |
return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; | |
}; | |
}(); | |
d3.geo.centroid = function(object) { | |
d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; | |
d3.geo.stream(object, d3_geo_centroid); | |
var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; | |
if (m < ε2) { | |
x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; | |
if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; | |
m = x * x + y * y + z * z; | |
if (m < ε2) return [ NaN, NaN ]; | |
} | |
return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; | |
}; | |
var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; | |
var d3_geo_centroid = { | |
sphere: d3_noop, | |
point: d3_geo_centroidPoint, | |
lineStart: d3_geo_centroidLineStart, | |
lineEnd: d3_geo_centroidLineEnd, | |
polygonStart: function() { | |
d3_geo_centroid.lineStart = d3_geo_centroidRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_centroid.lineStart = d3_geo_centroidLineStart; | |
} | |
}; | |
function d3_geo_centroidPoint(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians); | |
d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); | |
} | |
function d3_geo_centroidPointXYZ(x, y, z) { | |
++d3_geo_centroidW0; | |
d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; | |
d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; | |
d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; | |
} | |
function d3_geo_centroidLineStart() { | |
var x0, y0, z0; | |
d3_geo_centroid.point = function(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians); | |
x0 = cosφ * Math.cos(λ); | |
y0 = cosφ * Math.sin(λ); | |
z0 = Math.sin(φ); | |
d3_geo_centroid.point = nextPoint; | |
d3_geo_centroidPointXYZ(x0, y0, z0); | |
}; | |
function nextPoint(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); | |
d3_geo_centroidW1 += w; | |
d3_geo_centroidX1 += w * (x0 + (x0 = x)); | |
d3_geo_centroidY1 += w * (y0 + (y0 = y)); | |
d3_geo_centroidZ1 += w * (z0 + (z0 = z)); | |
d3_geo_centroidPointXYZ(x0, y0, z0); | |
} | |
} | |
function d3_geo_centroidLineEnd() { | |
d3_geo_centroid.point = d3_geo_centroidPoint; | |
} | |
function d3_geo_centroidRingStart() { | |
var λ00, φ00, x0, y0, z0; | |
d3_geo_centroid.point = function(λ, φ) { | |
λ00 = λ, φ00 = φ; | |
d3_geo_centroid.point = nextPoint; | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians); | |
x0 = cosφ * Math.cos(λ); | |
y0 = cosφ * Math.sin(λ); | |
z0 = Math.sin(φ); | |
d3_geo_centroidPointXYZ(x0, y0, z0); | |
}; | |
d3_geo_centroid.lineEnd = function() { | |
nextPoint(λ00, φ00); | |
d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; | |
d3_geo_centroid.point = d3_geo_centroidPoint; | |
}; | |
function nextPoint(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); | |
d3_geo_centroidX2 += v * cx; | |
d3_geo_centroidY2 += v * cy; | |
d3_geo_centroidZ2 += v * cz; | |
d3_geo_centroidW1 += w; | |
d3_geo_centroidX1 += w * (x0 + (x0 = x)); | |
d3_geo_centroidY1 += w * (y0 + (y0 = y)); | |
d3_geo_centroidZ1 += w * (z0 + (z0 = z)); | |
d3_geo_centroidPointXYZ(x0, y0, z0); | |
} | |
} | |
function d3_geo_compose(a, b) { | |
function compose(x, y) { | |
return x = a(x, y), b(x[0], x[1]); | |
} | |
if (a.invert && b.invert) compose.invert = function(x, y) { | |
return x = b.invert(x, y), x && a.invert(x[0], x[1]); | |
}; | |
return compose; | |
} | |
function d3_true() { | |
return true; | |
} | |
function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { | |
var subject = [], clip = []; | |
segments.forEach(function(segment) { | |
if ((n = segment.length - 1) <= 0) return; | |
var n, p0 = segment[0], p1 = segment[n]; | |
if (d3_geo_sphericalEqual(p0, p1)) { | |
listener.lineStart(); | |
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); | |
listener.lineEnd(); | |
return; | |
} | |
var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); | |
a.o = b; | |
subject.push(a); | |
clip.push(b); | |
a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); | |
b = new d3_geo_clipPolygonIntersection(p1, null, a, true); | |
a.o = b; | |
subject.push(a); | |
clip.push(b); | |
}); | |
clip.sort(compare); | |
d3_geo_clipPolygonLinkCircular(subject); | |
d3_geo_clipPolygonLinkCircular(clip); | |
if (!subject.length) return; | |
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { | |
clip[i].e = entry = !entry; | |
} | |
var start = subject[0], points, point; | |
while (1) { | |
var current = start, isSubject = true; | |
while (current.v) if ((current = current.n) === start) return; | |
points = current.z; | |
listener.lineStart(); | |
do { | |
current.v = current.o.v = true; | |
if (current.e) { | |
if (isSubject) { | |
for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.x, current.n.x, 1, listener); | |
} | |
current = current.n; | |
} else { | |
if (isSubject) { | |
points = current.p.z; | |
for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.x, current.p.x, -1, listener); | |
} | |
current = current.p; | |
} | |
current = current.o; | |
points = current.z; | |
isSubject = !isSubject; | |
} while (!current.v); | |
listener.lineEnd(); | |
} | |
} | |
function d3_geo_clipPolygonLinkCircular(array) { | |
if (!(n = array.length)) return; | |
var n, i = 0, a = array[0], b; | |
while (++i < n) { | |
a.n = b = array[i]; | |
b.p = a; | |
a = b; | |
} | |
a.n = b = array[0]; | |
b.p = a; | |
} | |
function d3_geo_clipPolygonIntersection(point, points, other, entry) { | |
this.x = point; | |
this.z = points; | |
this.o = other; | |
this.e = entry; | |
this.v = false; | |
this.n = this.p = null; | |
} | |
function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { | |
return function(rotate, listener) { | |
var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); | |
var clip = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
clip.point = pointRing; | |
clip.lineStart = ringStart; | |
clip.lineEnd = ringEnd; | |
segments = []; | |
polygon = []; | |
}, | |
polygonEnd: function() { | |
clip.point = point; | |
clip.lineStart = lineStart; | |
clip.lineEnd = lineEnd; | |
segments = d3.merge(segments); | |
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); | |
if (segments.length) { | |
if (!polygonStarted) listener.polygonStart(), polygonStarted = true; | |
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); | |
} else if (clipStartInside) { | |
if (!polygonStarted) listener.polygonStart(), polygonStarted = true; | |
listener.lineStart(); | |
interpolate(null, null, 1, listener); | |
listener.lineEnd(); | |
} | |
if (polygonStarted) listener.polygonEnd(), polygonStarted = false; | |
segments = polygon = null; | |
}, | |
sphere: function() { | |
listener.polygonStart(); | |
listener.lineStart(); | |
interpolate(null, null, 1, listener); | |
listener.lineEnd(); | |
listener.polygonEnd(); | |
} | |
}; | |
function point(λ, φ) { | |
var point = rotate(λ, φ); | |
if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); | |
} | |
function pointLine(λ, φ) { | |
var point = rotate(λ, φ); | |
line.point(point[0], point[1]); | |
} | |
function lineStart() { | |
clip.point = pointLine; | |
line.lineStart(); | |
} | |
function lineEnd() { | |
clip.point = point; | |
line.lineEnd(); | |
} | |
var segments; | |
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; | |
function pointRing(λ, φ) { | |
ring.push([ λ, φ ]); | |
var point = rotate(λ, φ); | |
ringListener.point(point[0], point[1]); | |
} | |
function ringStart() { | |
ringListener.lineStart(); | |
ring = []; | |
} | |
function ringEnd() { | |
pointRing(ring[0][0], ring[0][1]); | |
ringListener.lineEnd(); | |
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; | |
ring.pop(); | |
polygon.push(ring); | |
ring = null; | |
if (!n) return; | |
if (clean & 1) { | |
segment = ringSegments[0]; | |
var n = segment.length - 1, i = -1, point; | |
if (n > 0) { | |
if (!polygonStarted) listener.polygonStart(), polygonStarted = true; | |
listener.lineStart(); | |
while (++i < n) listener.point((point = segment[i])[0], point[1]); | |
listener.lineEnd(); | |
} | |
return; | |
} | |
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); | |
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); | |
} | |
return clip; | |
}; | |
} | |
function d3_geo_clipSegmentLength1(segment) { | |
return segment.length > 1; | |
} | |
function d3_geo_clipBufferListener() { | |
var lines = [], line; | |
return { | |
lineStart: function() { | |
lines.push(line = []); | |
}, | |
point: function(λ, φ) { | |
line.push([ λ, φ ]); | |
}, | |
lineEnd: d3_noop, | |
buffer: function() { | |
var buffer = lines; | |
lines = []; | |
line = null; | |
return buffer; | |
}, | |
rejoin: function() { | |
if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); | |
} | |
}; | |
} | |
function d3_geo_clipSort(a, b) { | |
return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); | |
} | |
var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); | |
function d3_geo_clipAntimeridianLine(listener) { | |
var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; | |
return { | |
lineStart: function() { | |
listener.lineStart(); | |
clean = 1; | |
}, | |
point: function(λ1, φ1) { | |
var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); | |
if (abs(dλ - π) < ε) { | |
listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); | |
listener.point(sλ0, φ0); | |
listener.lineEnd(); | |
listener.lineStart(); | |
listener.point(sλ1, φ0); | |
listener.point(λ1, φ0); | |
clean = 0; | |
} else if (sλ0 !== sλ1 && dλ >= π) { | |
if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; | |
if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; | |
φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); | |
listener.point(sλ0, φ0); | |
listener.lineEnd(); | |
listener.lineStart(); | |
listener.point(sλ1, φ0); | |
clean = 0; | |
} | |
listener.point(λ0 = λ1, φ0 = φ1); | |
sλ0 = sλ1; | |
}, | |
lineEnd: function() { | |
listener.lineEnd(); | |
λ0 = φ0 = NaN; | |
}, | |
clean: function() { | |
return 2 - clean; | |
} | |
}; | |
} | |
function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { | |
var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); | |
return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; | |
} | |
function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { | |
var φ; | |
if (from == null) { | |
φ = direction * halfπ; | |
listener.point(-π, φ); | |
listener.point(0, φ); | |
listener.point(π, φ); | |
listener.point(π, 0); | |
listener.point(π, -φ); | |
listener.point(0, -φ); | |
listener.point(-π, -φ); | |
listener.point(-π, 0); | |
listener.point(-π, φ); | |
} else if (abs(from[0] - to[0]) > ε) { | |
var s = from[0] < to[0] ? π : -π; | |
φ = direction * s / 2; | |
listener.point(-s, φ); | |
listener.point(0, φ); | |
listener.point(s, φ); | |
} else { | |
listener.point(to[0], to[1]); | |
} | |
} | |
function d3_geo_pointInPolygon(point, polygon) { | |
var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; | |
d3_geo_areaRingSum.reset(); | |
for (var i = 0, n = polygon.length; i < n; ++i) { | |
var ring = polygon[i], m = ring.length; | |
if (!m) continue; | |
var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; | |
while (true) { | |
if (j === m) j = 0; | |
point = ring[j]; | |
var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; | |
d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); | |
polarAngle += antimeridian ? dλ + sdλ * τ : dλ; | |
if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { | |
var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); | |
d3_geo_cartesianNormalize(arc); | |
var intersection = d3_geo_cartesianCross(meridianNormal, arc); | |
d3_geo_cartesianNormalize(intersection); | |
var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); | |
if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { | |
winding += antimeridian ^ dλ >= 0 ? 1 : -1; | |
} | |
} | |
if (!j++) break; | |
λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; | |
} | |
} | |
return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; | |
} | |
function d3_geo_clipCircle(radius) { | |
var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); | |
return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); | |
function visible(λ, φ) { | |
return Math.cos(λ) * Math.cos(φ) > cr; | |
} | |
function clipLine(listener) { | |
var point0, c0, v0, v00, clean; | |
return { | |
lineStart: function() { | |
v00 = v0 = false; | |
clean = 1; | |
}, | |
point: function(λ, φ) { | |
var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; | |
if (!point0 && (v00 = v0 = v)) listener.lineStart(); | |
if (v !== v0) { | |
point2 = intersect(point0, point1); | |
if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { | |
point1[0] += ε; | |
point1[1] += ε; | |
v = visible(point1[0], point1[1]); | |
} | |
} | |
if (v !== v0) { | |
clean = 0; | |
if (v) { | |
listener.lineStart(); | |
point2 = intersect(point1, point0); | |
listener.point(point2[0], point2[1]); | |
} else { | |
point2 = intersect(point0, point1); | |
listener.point(point2[0], point2[1]); | |
listener.lineEnd(); | |
} | |
point0 = point2; | |
} else if (notHemisphere && point0 && smallRadius ^ v) { | |
var t; | |
if (!(c & c0) && (t = intersect(point1, point0, true))) { | |
clean = 0; | |
if (smallRadius) { | |
listener.lineStart(); | |
listener.point(t[0][0], t[0][1]); | |
listener.point(t[1][0], t[1][1]); | |
listener.lineEnd(); | |
} else { | |
listener.point(t[1][0], t[1][1]); | |
listener.lineEnd(); | |
listener.lineStart(); | |
listener.point(t[0][0], t[0][1]); | |
} | |
} | |
} | |
if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { | |
listener.point(point1[0], point1[1]); | |
} | |
point0 = point1, v0 = v, c0 = c; | |
}, | |
lineEnd: function() { | |
if (v0) listener.lineEnd(); | |
point0 = null; | |
}, | |
clean: function() { | |
return clean | (v00 && v0) << 1; | |
} | |
}; | |
} | |
function intersect(a, b, two) { | |
var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); | |
var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; | |
if (!determinant) return !two && a; | |
var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); | |
d3_geo_cartesianAdd(A, B); | |
var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); | |
if (t2 < 0) return; | |
var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); | |
d3_geo_cartesianAdd(q, A); | |
q = d3_geo_spherical(q); | |
if (!two) return q; | |
var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; | |
if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; | |
var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; | |
if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; | |
if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { | |
var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); | |
d3_geo_cartesianAdd(q1, A); | |
return [ q, d3_geo_spherical(q1) ]; | |
} | |
} | |
function code(λ, φ) { | |
var r = smallRadius ? radius : π - radius, code = 0; | |
if (λ < -r) code |= 1; else if (λ > r) code |= 2; | |
if (φ < -r) code |= 4; else if (φ > r) code |= 8; | |
return code; | |
} | |
} | |
function d3_geom_clipLine(x0, y0, x1, y1) { | |
return function(line) { | |
var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; | |
r = x0 - ax; | |
if (!dx && r > 0) return; | |
r /= dx; | |
if (dx < 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} else if (dx > 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} | |
r = x1 - ax; | |
if (!dx && r < 0) return; | |
r /= dx; | |
if (dx < 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} else if (dx > 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} | |
r = y0 - ay; | |
if (!dy && r > 0) return; | |
r /= dy; | |
if (dy < 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} else if (dy > 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} | |
r = y1 - ay; | |
if (!dy && r < 0) return; | |
r /= dy; | |
if (dy < 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} else if (dy > 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} | |
if (t0 > 0) line.a = { | |
x: ax + t0 * dx, | |
y: ay + t0 * dy | |
}; | |
if (t1 < 1) line.b = { | |
x: ax + t1 * dx, | |
y: ay + t1 * dy | |
}; | |
return line; | |
}; | |
} | |
var d3_geo_clipExtentMAX = 1e9; | |
d3.geo.clipExtent = function() { | |
var x0, y0, x1, y1, stream, clip, clipExtent = { | |
stream: function(output) { | |
if (stream) stream.valid = false; | |
stream = clip(output); | |
stream.valid = true; | |
return stream; | |
}, | |
extent: function(_) { | |
if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; | |
clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); | |
if (stream) stream.valid = false, stream = null; | |
return clipExtent; | |
} | |
}; | |
return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); | |
}; | |
function d3_geo_clipExtent(x0, y0, x1, y1) { | |
return function(listener) { | |
var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; | |
var clip = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
listener = bufferListener; | |
segments = []; | |
polygon = []; | |
clean = true; | |
}, | |
polygonEnd: function() { | |
listener = listener_; | |
segments = d3.merge(segments); | |
var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; | |
if (inside || visible) { | |
listener.polygonStart(); | |
if (inside) { | |
listener.lineStart(); | |
interpolate(null, null, 1, listener); | |
listener.lineEnd(); | |
} | |
if (visible) { | |
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); | |
} | |
listener.polygonEnd(); | |
} | |
segments = polygon = ring = null; | |
} | |
}; | |
function insidePolygon(p) { | |
var wn = 0, n = polygon.length, y = p[1]; | |
for (var i = 0; i < n; ++i) { | |
for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { | |
b = v[j]; | |
if (a[1] <= y) { | |
if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; | |
} else { | |
if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; | |
} | |
a = b; | |
} | |
} | |
return wn !== 0; | |
} | |
function interpolate(from, to, direction, listener) { | |
var a = 0, a1 = 0; | |
if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { | |
do { | |
listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); | |
} while ((a = (a + direction + 4) % 4) !== a1); | |
} else { | |
listener.point(to[0], to[1]); | |
} | |
} | |
function pointVisible(x, y) { | |
return x0 <= x && x <= x1 && y0 <= y && y <= y1; | |
} | |
function point(x, y) { | |
if (pointVisible(x, y)) listener.point(x, y); | |
} | |
var x__, y__, v__, x_, y_, v_, first, clean; | |
function lineStart() { | |
clip.point = linePoint; | |
if (polygon) polygon.push(ring = []); | |
first = true; | |
v_ = false; | |
x_ = y_ = NaN; | |
} | |
function lineEnd() { | |
if (segments) { | |
linePoint(x__, y__); | |
if (v__ && v_) bufferListener.rejoin(); | |
segments.push(bufferListener.buffer()); | |
} | |
clip.point = point; | |
if (v_) listener.lineEnd(); | |
} | |
function linePoint(x, y) { | |
x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); | |
y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); | |
var v = pointVisible(x, y); | |
if (polygon) ring.push([ x, y ]); | |
if (first) { | |
x__ = x, y__ = y, v__ = v; | |
first = false; | |
if (v) { | |
listener.lineStart(); | |
listener.point(x, y); | |
} | |
} else { | |
if (v && v_) listener.point(x, y); else { | |
var l = { | |
a: { | |
x: x_, | |
y: y_ | |
}, | |
b: { | |
x: x, | |
y: y | |
} | |
}; | |
if (clipLine(l)) { | |
if (!v_) { | |
listener.lineStart(); | |
listener.point(l.a.x, l.a.y); | |
} | |
listener.point(l.b.x, l.b.y); | |
if (!v) listener.lineEnd(); | |
clean = false; | |
} else if (v) { | |
listener.lineStart(); | |
listener.point(x, y); | |
clean = false; | |
} | |
} | |
} | |
x_ = x, y_ = y, v_ = v; | |
} | |
return clip; | |
}; | |
function corner(p, direction) { | |
return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; | |
} | |
function compare(a, b) { | |
return comparePoints(a.x, b.x); | |
} | |
function comparePoints(a, b) { | |
var ca = corner(a, 1), cb = corner(b, 1); | |
return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; | |
} | |
} | |
function d3_geo_conic(projectAt) { | |
var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); | |
p.parallels = function(_) { | |
if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; | |
return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); | |
}; | |
return p; | |
} | |
function d3_geo_conicEqualArea(φ0, φ1) { | |
var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; | |
function forward(λ, φ) { | |
var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; | |
return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; | |
} | |
forward.invert = function(x, y) { | |
var ρ0_y = ρ0 - y; | |
return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; | |
}; | |
return forward; | |
} | |
(d3.geo.conicEqualArea = function() { | |
return d3_geo_conic(d3_geo_conicEqualArea); | |
}).raw = d3_geo_conicEqualArea; | |
d3.geo.albers = function() { | |
return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); | |
}; | |
d3.geo.albersUsa = function() { | |
var lower48 = d3.geo.albers(); | |
var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); | |
var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); | |
var point, pointStream = { | |
point: function(x, y) { | |
point = [ x, y ]; | |
} | |
}, lower48Point, alaskaPoint, hawaiiPoint; | |
function albersUsa(coordinates) { | |
var x = coordinates[0], y = coordinates[1]; | |
point = null; | |
(lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); | |
return point; | |
} | |
albersUsa.invert = function(coordinates) { | |
var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; | |
return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); | |
}; | |
albersUsa.stream = function(stream) { | |
var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); | |
return { | |
point: function(x, y) { | |
lower48Stream.point(x, y); | |
alaskaStream.point(x, y); | |
hawaiiStream.point(x, y); | |
}, | |
sphere: function() { | |
lower48Stream.sphere(); | |
alaskaStream.sphere(); | |
hawaiiStream.sphere(); | |
}, | |
lineStart: function() { | |
lower48Stream.lineStart(); | |
alaskaStream.lineStart(); | |
hawaiiStream.lineStart(); | |
}, | |
lineEnd: function() { | |
lower48Stream.lineEnd(); | |
alaskaStream.lineEnd(); | |
hawaiiStream.lineEnd(); | |
}, | |
polygonStart: function() { | |
lower48Stream.polygonStart(); | |
alaskaStream.polygonStart(); | |
hawaiiStream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
lower48Stream.polygonEnd(); | |
alaskaStream.polygonEnd(); | |
hawaiiStream.polygonEnd(); | |
} | |
}; | |
}; | |
albersUsa.precision = function(_) { | |
if (!arguments.length) return lower48.precision(); | |
lower48.precision(_); | |
alaska.precision(_); | |
hawaii.precision(_); | |
return albersUsa; | |
}; | |
albersUsa.scale = function(_) { | |
if (!arguments.length) return lower48.scale(); | |
lower48.scale(_); | |
alaska.scale(_ * .35); | |
hawaii.scale(_); | |
return albersUsa.translate(lower48.translate()); | |
}; | |
albersUsa.translate = function(_) { | |
if (!arguments.length) return lower48.translate(); | |
var k = lower48.scale(), x = +_[0], y = +_[1]; | |
lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; | |
alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; | |
hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; | |
return albersUsa; | |
}; | |
return albersUsa.scale(1070); | |
}; | |
var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { | |
point: d3_noop, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: function() { | |
d3_geo_pathAreaPolygon = 0; | |
d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; | |
d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); | |
} | |
}; | |
function d3_geo_pathAreaRingStart() { | |
var x00, y00, x0, y0; | |
d3_geo_pathArea.point = function(x, y) { | |
d3_geo_pathArea.point = nextPoint; | |
x00 = x0 = x, y00 = y0 = y; | |
}; | |
function nextPoint(x, y) { | |
d3_geo_pathAreaPolygon += y0 * x - x0 * y; | |
x0 = x, y0 = y; | |
} | |
d3_geo_pathArea.lineEnd = function() { | |
nextPoint(x00, y00); | |
}; | |
} | |
var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; | |
var d3_geo_pathBounds = { | |
point: d3_geo_pathBoundsPoint, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: d3_noop, | |
polygonEnd: d3_noop | |
}; | |
function d3_geo_pathBoundsPoint(x, y) { | |
if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; | |
if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; | |
if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; | |
if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; | |
} | |
function d3_geo_pathBuffer() { | |
var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; | |
var stream = { | |
point: point, | |
lineStart: function() { | |
stream.point = pointLineStart; | |
}, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.lineEnd = lineEndPolygon; | |
}, | |
polygonEnd: function() { | |
stream.lineEnd = lineEnd; | |
stream.point = point; | |
}, | |
pointRadius: function(_) { | |
pointCircle = d3_geo_pathBufferCircle(_); | |
return stream; | |
}, | |
result: function() { | |
if (buffer.length) { | |
var result = buffer.join(""); | |
buffer = []; | |
return result; | |
} | |
} | |
}; | |
function point(x, y) { | |
buffer.push("M", x, ",", y, pointCircle); | |
} | |
function pointLineStart(x, y) { | |
buffer.push("M", x, ",", y); | |
stream.point = pointLine; | |
} | |
function pointLine(x, y) { | |
buffer.push("L", x, ",", y); | |
} | |
function lineEnd() { | |
stream.point = point; | |
} | |
function lineEndPolygon() { | |
buffer.push("Z"); | |
} | |
return stream; | |
} | |
function d3_geo_pathBufferCircle(radius) { | |
return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; | |
} | |
var d3_geo_pathCentroid = { | |
point: d3_geo_pathCentroidPoint, | |
lineStart: d3_geo_pathCentroidLineStart, | |
lineEnd: d3_geo_pathCentroidLineEnd, | |
polygonStart: function() { | |
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; | |
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; | |
d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; | |
} | |
}; | |
function d3_geo_pathCentroidPoint(x, y) { | |
d3_geo_centroidX0 += x; | |
d3_geo_centroidY0 += y; | |
++d3_geo_centroidZ0; | |
} | |
function d3_geo_pathCentroidLineStart() { | |
var x0, y0; | |
d3_geo_pathCentroid.point = function(x, y) { | |
d3_geo_pathCentroid.point = nextPoint; | |
d3_geo_pathCentroidPoint(x0 = x, y0 = y); | |
}; | |
function nextPoint(x, y) { | |
var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); | |
d3_geo_centroidX1 += z * (x0 + x) / 2; | |
d3_geo_centroidY1 += z * (y0 + y) / 2; | |
d3_geo_centroidZ1 += z; | |
d3_geo_pathCentroidPoint(x0 = x, y0 = y); | |
} | |
} | |
function d3_geo_pathCentroidLineEnd() { | |
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; | |
} | |
function d3_geo_pathCentroidRingStart() { | |
var x00, y00, x0, y0; | |
d3_geo_pathCentroid.point = function(x, y) { | |
d3_geo_pathCentroid.point = nextPoint; | |
d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); | |
}; | |
function nextPoint(x, y) { | |
var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); | |
d3_geo_centroidX1 += z * (x0 + x) / 2; | |
d3_geo_centroidY1 += z * (y0 + y) / 2; | |
d3_geo_centroidZ1 += z; | |
z = y0 * x - x0 * y; | |
d3_geo_centroidX2 += z * (x0 + x); | |
d3_geo_centroidY2 += z * (y0 + y); | |
d3_geo_centroidZ2 += z * 3; | |
d3_geo_pathCentroidPoint(x0 = x, y0 = y); | |
} | |
d3_geo_pathCentroid.lineEnd = function() { | |
nextPoint(x00, y00); | |
}; | |
} | |
function d3_geo_pathContext(context) { | |
var pointRadius = 4.5; | |
var stream = { | |
point: point, | |
lineStart: function() { | |
stream.point = pointLineStart; | |
}, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.lineEnd = lineEndPolygon; | |
}, | |
polygonEnd: function() { | |
stream.lineEnd = lineEnd; | |
stream.point = point; | |
}, | |
pointRadius: function(_) { | |
pointRadius = _; | |
return stream; | |
}, | |
result: d3_noop | |
}; | |
function point(x, y) { | |
context.moveTo(x + pointRadius, y); | |
context.arc(x, y, pointRadius, 0, τ); | |
} | |
function pointLineStart(x, y) { | |
context.moveTo(x, y); | |
stream.point = pointLine; | |
} | |
function pointLine(x, y) { | |
context.lineTo(x, y); | |
} | |
function lineEnd() { | |
stream.point = point; | |
} | |
function lineEndPolygon() { | |
context.closePath(); | |
} | |
return stream; | |
} | |
function d3_geo_resample(project) { | |
var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; | |
function resample(stream) { | |
return (maxDepth ? resampleRecursive : resampleNone)(stream); | |
} | |
function resampleNone(stream) { | |
return d3_geo_transformPoint(stream, function(x, y) { | |
x = project(x, y); | |
stream.point(x[0], x[1]); | |
}); | |
} | |
function resampleRecursive(stream) { | |
var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; | |
var resample = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.polygonStart(); | |
resample.lineStart = ringStart; | |
}, | |
polygonEnd: function() { | |
stream.polygonEnd(); | |
resample.lineStart = lineStart; | |
} | |
}; | |
function point(x, y) { | |
x = project(x, y); | |
stream.point(x[0], x[1]); | |
} | |
function lineStart() { | |
x0 = NaN; | |
resample.point = linePoint; | |
stream.lineStart(); | |
} | |
function linePoint(λ, φ) { | |
var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); | |
stream.point(x0, y0); | |
} | |
function lineEnd() { | |
resample.point = point; | |
stream.lineEnd(); | |
} | |
function ringStart() { | |
lineStart(); | |
resample.point = ringPoint; | |
resample.lineEnd = ringEnd; | |
} | |
function ringPoint(λ, φ) { | |
linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; | |
resample.point = linePoint; | |
} | |
function ringEnd() { | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); | |
resample.lineEnd = lineEnd; | |
lineEnd(); | |
} | |
return resample; | |
} | |
function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { | |
var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; | |
if (d2 > 4 * δ2 && depth--) { | |
var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; | |
if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); | |
stream.point(x2, y2); | |
resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); | |
} | |
} | |
} | |
resample.precision = function(_) { | |
if (!arguments.length) return Math.sqrt(δ2); | |
maxDepth = (δ2 = _ * _) > 0 && 16; | |
return resample; | |
}; | |
return resample; | |
} | |
d3.geo.path = function() { | |
var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; | |
function path(object) { | |
if (object) { | |
if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); | |
if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); | |
d3.geo.stream(object, cacheStream); | |
} | |
return contextStream.result(); | |
} | |
path.area = function(object) { | |
d3_geo_pathAreaSum = 0; | |
d3.geo.stream(object, projectStream(d3_geo_pathArea)); | |
return d3_geo_pathAreaSum; | |
}; | |
path.centroid = function(object) { | |
d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; | |
d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); | |
return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; | |
}; | |
path.bounds = function(object) { | |
d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); | |
d3.geo.stream(object, projectStream(d3_geo_pathBounds)); | |
return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; | |
}; | |
path.projection = function(_) { | |
if (!arguments.length) return projection; | |
projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; | |
return reset(); | |
}; | |
path.context = function(_) { | |
if (!arguments.length) return context; | |
contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); | |
if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); | |
return reset(); | |
}; | |
path.pointRadius = function(_) { | |
if (!arguments.length) return pointRadius; | |
pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); | |
return path; | |
}; | |
function reset() { | |
cacheStream = null; | |
return path; | |
} | |
return path.projection(d3.geo.albersUsa()).context(null); | |
}; | |
function d3_geo_pathProjectStream(project) { | |
var resample = d3_geo_resample(function(x, y) { | |
return project([ x * d3_degrees, y * d3_degrees ]); | |
}); | |
return function(stream) { | |
return d3_geo_projectionRadians(resample(stream)); | |
}; | |
} | |
d3.geo.transform = function(methods) { | |
return { | |
stream: function(stream) { | |
var transform = new d3_geo_transform(stream); | |
for (var k in methods) transform[k] = methods[k]; | |
return transform; | |
} | |
}; | |
}; | |
function d3_geo_transform(stream) { | |
this.stream = stream; | |
} | |
d3_geo_transform.prototype = { | |
point: function(x, y) { | |
this.stream.point(x, y); | |
}, | |
sphere: function() { | |
this.stream.sphere(); | |
}, | |
lineStart: function() { | |
this.stream.lineStart(); | |
}, | |
lineEnd: function() { | |
this.stream.lineEnd(); | |
}, | |
polygonStart: function() { | |
this.stream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
this.stream.polygonEnd(); | |
} | |
}; | |
function d3_geo_transformPoint(stream, point) { | |
return { | |
point: point, | |
sphere: function() { | |
stream.sphere(); | |
}, | |
lineStart: function() { | |
stream.lineStart(); | |
}, | |
lineEnd: function() { | |
stream.lineEnd(); | |
}, | |
polygonStart: function() { | |
stream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
stream.polygonEnd(); | |
} | |
}; | |
} | |
d3.geo.projection = d3_geo_projection; | |
d3.geo.projectionMutator = d3_geo_projectionMutator; | |
function d3_geo_projection(project) { | |
return d3_geo_projectionMutator(function() { | |
return project; | |
})(); | |
} | |
function d3_geo_projectionMutator(projectAt) { | |
var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { | |
x = project(x, y); | |
return [ x[0] * k + δx, δy - x[1] * k ]; | |
}), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; | |
function projection(point) { | |
point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); | |
return [ point[0] * k + δx, δy - point[1] * k ]; | |
} | |
function invert(point) { | |
point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); | |
return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; | |
} | |
projection.stream = function(output) { | |
if (stream) stream.valid = false; | |
stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); | |
stream.valid = true; | |
return stream; | |
}; | |
projection.clipAngle = function(_) { | |
if (!arguments.length) return clipAngle; | |
preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); | |
return invalidate(); | |
}; | |
projection.clipExtent = function(_) { | |
if (!arguments.length) return clipExtent; | |
clipExtent = _; | |
postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; | |
return invalidate(); | |
}; | |
projection.scale = function(_) { | |
if (!arguments.length) return k; | |
k = +_; | |
return reset(); | |
}; | |
projection.translate = function(_) { | |
if (!arguments.length) return [ x, y ]; | |
x = +_[0]; | |
y = +_[1]; | |
return reset(); | |
}; | |
projection.center = function(_) { | |
if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; | |
λ = _[0] % 360 * d3_radians; | |
φ = _[1] % 360 * d3_radians; | |
return reset(); | |
}; | |
projection.rotate = function(_) { | |
if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; | |
δλ = _[0] % 360 * d3_radians; | |
δφ = _[1] % 360 * d3_radians; | |
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; | |
return reset(); | |
}; | |
d3.rebind(projection, projectResample, "precision"); | |
function reset() { | |
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); | |
var center = project(λ, φ); | |
δx = x - center[0] * k; | |
δy = y + center[1] * k; | |
return invalidate(); | |
} | |
function invalidate() { | |
if (stream) stream.valid = false, stream = null; | |
return projection; | |
} | |
return function() { | |
project = projectAt.apply(this, arguments); | |
projection.invert = project.invert && invert; | |
return reset(); | |
}; | |
} | |
function d3_geo_projectionRadians(stream) { | |
return d3_geo_transformPoint(stream, function(x, y) { | |
stream.point(x * d3_radians, y * d3_radians); | |
}); | |
} | |
function d3_geo_equirectangular(λ, φ) { | |
return [ λ, φ ]; | |
} | |
(d3.geo.equirectangular = function() { | |
return d3_geo_projection(d3_geo_equirectangular); | |
}).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; | |
d3.geo.rotation = function(rotate) { | |
rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); | |
function forward(coordinates) { | |
coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); | |
return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; | |
} | |
forward.invert = function(coordinates) { | |
coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); | |
return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; | |
}; | |
return forward; | |
}; | |
function d3_geo_identityRotation(λ, φ) { | |
return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; | |
} | |
d3_geo_identityRotation.invert = d3_geo_equirectangular; | |
function d3_geo_rotation(δλ, δφ, δγ) { | |
return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; | |
} | |
function d3_geo_forwardRotationλ(δλ) { | |
return function(λ, φ) { | |
return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; | |
}; | |
} | |
function d3_geo_rotationλ(δλ) { | |
var rotation = d3_geo_forwardRotationλ(δλ); | |
rotation.invert = d3_geo_forwardRotationλ(-δλ); | |
return rotation; | |
} | |
function d3_geo_rotationφγ(δφ, δγ) { | |
var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); | |
function rotation(λ, φ) { | |
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; | |
return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; | |
} | |
rotation.invert = function(λ, φ) { | |
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; | |
return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; | |
}; | |
return rotation; | |
} | |
d3.geo.circle = function() { | |
var origin = [ 0, 0 ], angle, precision = 6, interpolate; | |
function circle() { | |
var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; | |
interpolate(null, null, 1, { | |
point: function(x, y) { | |
ring.push(x = rotate(x, y)); | |
x[0] *= d3_degrees, x[1] *= d3_degrees; | |
} | |
}); | |
return { | |
type: "Polygon", | |
coordinates: [ ring ] | |
}; | |
} | |
circle.origin = function(x) { | |
if (!arguments.length) return origin; | |
origin = x; | |
return circle; | |
}; | |
circle.angle = function(x) { | |
if (!arguments.length) return angle; | |
interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); | |
return circle; | |
}; | |
circle.precision = function(_) { | |
if (!arguments.length) return precision; | |
interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); | |
return circle; | |
}; | |
return circle.angle(90); | |
}; | |
function d3_geo_circleInterpolate(radius, precision) { | |
var cr = Math.cos(radius), sr = Math.sin(radius); | |
return function(from, to, direction, listener) { | |
var step = direction * precision; | |
if (from != null) { | |
from = d3_geo_circleAngle(cr, from); | |
to = d3_geo_circleAngle(cr, to); | |
if (direction > 0 ? from < to : from > to) from += direction * τ; | |
} else { | |
from = radius + direction * τ; | |
to = radius - .5 * step; | |
} | |
for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { | |
listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); | |
} | |
}; | |
} | |
function d3_geo_circleAngle(cr, point) { | |
var a = d3_geo_cartesian(point); | |
a[0] -= cr; | |
d3_geo_cartesianNormalize(a); | |
var angle = d3_acos(-a[1]); | |
return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); | |
} | |
d3.geo.distance = function(a, b) { | |
var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; | |
return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); | |
}; | |
d3.geo.graticule = function() { | |
var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; | |
function graticule() { | |
return { | |
type: "MultiLineString", | |
coordinates: lines() | |
}; | |
} | |
function lines() { | |
return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { | |
return abs(x % DX) > ε; | |
}).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { | |
return abs(y % DY) > ε; | |
}).map(y)); | |
} | |
graticule.lines = function() { | |
return lines().map(function(coordinates) { | |
return { | |
type: "LineString", | |
coordinates: coordinates | |
}; | |
}); | |
}; | |
graticule.outline = function() { | |
return { | |
type: "Polygon", | |
coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] | |
}; | |
}; | |
graticule.extent = function(_) { | |
if (!arguments.length) return graticule.minorExtent(); | |
return graticule.majorExtent(_).minorExtent(_); | |
}; | |
graticule.majorExtent = function(_) { | |
if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; | |
X0 = +_[0][0], X1 = +_[1][0]; | |
Y0 = +_[0][1], Y1 = +_[1][1]; | |
if (X0 > X1) _ = X0, X0 = X1, X1 = _; | |
if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; | |
return graticule.precision(precision); | |
}; | |
graticule.minorExtent = function(_) { | |
if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; | |
x0 = +_[0][0], x1 = +_[1][0]; | |
y0 = +_[0][1], y1 = +_[1][1]; | |
if (x0 > x1) _ = x0, x0 = x1, x1 = _; | |
if (y0 > y1) _ = y0, y0 = y1, y1 = _; | |
return graticule.precision(precision); | |
}; | |
graticule.step = function(_) { | |
if (!arguments.length) return graticule.minorStep(); | |
return graticule.majorStep(_).minorStep(_); | |
}; | |
graticule.majorStep = function(_) { | |
if (!arguments.length) return [ DX, DY ]; | |
DX = +_[0], DY = +_[1]; | |
return graticule; | |
}; | |
graticule.minorStep = function(_) { | |
if (!arguments.length) return [ dx, dy ]; | |
dx = +_[0], dy = +_[1]; | |
return graticule; | |
}; | |
graticule.precision = function(_) { | |
if (!arguments.length) return precision; | |
precision = +_; | |
x = d3_geo_graticuleX(y0, y1, 90); | |
y = d3_geo_graticuleY(x0, x1, precision); | |
X = d3_geo_graticuleX(Y0, Y1, 90); | |
Y = d3_geo_graticuleY(X0, X1, precision); | |
return graticule; | |
}; | |
return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); | |
}; | |
function d3_geo_graticuleX(y0, y1, dy) { | |
var y = d3.range(y0, y1 - ε, dy).concat(y1); | |
return function(x) { | |
return y.map(function(y) { | |
return [ x, y ]; | |
}); | |
}; | |
} | |
function d3_geo_graticuleY(x0, x1, dx) { | |
var x = d3.range(x0, x1 - ε, dx).concat(x1); | |
return function(y) { | |
return x.map(function(x) { | |
return [ x, y ]; | |
}); | |
}; | |
} | |
function d3_source(d) { | |
return d.source; | |
} | |
function d3_target(d) { | |
return d.target; | |
} | |
d3.geo.greatArc = function() { | |
var source = d3_source, source_, target = d3_target, target_; | |
function greatArc() { | |
return { | |
type: "LineString", | |
coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] | |
}; | |
} | |
greatArc.distance = function() { | |
return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); | |
}; | |
greatArc.source = function(_) { | |
if (!arguments.length) return source; | |
source = _, source_ = typeof _ === "function" ? null : _; | |
return greatArc; | |
}; | |
greatArc.target = function(_) { | |
if (!arguments.length) return target; | |
target = _, target_ = typeof _ === "function" ? null : _; | |
return greatArc; | |
}; | |
greatArc.precision = function() { | |
return arguments.length ? greatArc : 0; | |
}; | |
return greatArc; | |
}; | |
d3.geo.interpolate = function(source, target) { | |
return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); | |
}; | |
function d3_geo_interpolate(x0, y0, x1, y1) { | |
var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); | |
var interpolate = d ? function(t) { | |
var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; | |
return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; | |
} : function() { | |
return [ x0 * d3_degrees, y0 * d3_degrees ]; | |
}; | |
interpolate.distance = d; | |
return interpolate; | |
} | |
d3.geo.length = function(object) { | |
d3_geo_lengthSum = 0; | |
d3.geo.stream(object, d3_geo_length); | |
return d3_geo_lengthSum; | |
}; | |
var d3_geo_lengthSum; | |
var d3_geo_length = { | |
sphere: d3_noop, | |
point: d3_noop, | |
lineStart: d3_geo_lengthLineStart, | |
lineEnd: d3_noop, | |
polygonStart: d3_noop, | |
polygonEnd: d3_noop | |
}; | |
function d3_geo_lengthLineStart() { | |
var λ0, sinφ0, cosφ0; | |
d3_geo_length.point = function(λ, φ) { | |
λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); | |
d3_geo_length.point = nextPoint; | |
}; | |
d3_geo_length.lineEnd = function() { | |
d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; | |
}; | |
function nextPoint(λ, φ) { | |
var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); | |
d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); | |
λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; | |
} | |
} | |
function d3_geo_azimuthal(scale, angle) { | |
function azimuthal(λ, φ) { | |
var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); | |
return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; | |
} | |
azimuthal.invert = function(x, y) { | |
var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); | |
return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; | |
}; | |
return azimuthal; | |
} | |
var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { | |
return Math.sqrt(2 / (1 + cosλcosφ)); | |
}, function(ρ) { | |
return 2 * Math.asin(ρ / 2); | |
}); | |
(d3.geo.azimuthalEqualArea = function() { | |
return d3_geo_projection(d3_geo_azimuthalEqualArea); | |
}).raw = d3_geo_azimuthalEqualArea; | |
var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { | |
var c = Math.acos(cosλcosφ); | |
return c && c / Math.sin(c); | |
}, d3_identity); | |
(d3.geo.azimuthalEquidistant = function() { | |
return d3_geo_projection(d3_geo_azimuthalEquidistant); | |
}).raw = d3_geo_azimuthalEquidistant; | |
function d3_geo_conicConformal(φ0, φ1) { | |
var cosφ0 = Math.cos(φ0), t = function(φ) { | |
return Math.tan(π / 4 + φ / 2); | |
}, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; | |
if (!n) return d3_geo_mercator; | |
function forward(λ, φ) { | |
if (F > 0) { | |
if (φ < -halfπ + ε) φ = -halfπ + ε; | |
} else { | |
if (φ > halfπ - ε) φ = halfπ - ε; | |
} | |
var ρ = F / Math.pow(t(φ), n); | |
return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; | |
} | |
forward.invert = function(x, y) { | |
var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); | |
return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; | |
}; | |
return forward; | |
} | |
(d3.geo.conicConformal = function() { | |
return d3_geo_conic(d3_geo_conicConformal); | |
}).raw = d3_geo_conicConformal; | |
function d3_geo_conicEquidistant(φ0, φ1) { | |
var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; | |
if (abs(n) < ε) return d3_geo_equirectangular; | |
function forward(λ, φ) { | |
var ρ = G - φ; | |
return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; | |
} | |
forward.invert = function(x, y) { | |
var ρ0_y = G - y; | |
return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; | |
}; | |
return forward; | |
} | |
(d3.geo.conicEquidistant = function() { | |
return d3_geo_conic(d3_geo_conicEquidistant); | |
}).raw = d3_geo_conicEquidistant; | |
var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { | |
return 1 / cosλcosφ; | |
}, Math.atan); | |
(d3.geo.gnomonic = function() { | |
return d3_geo_projection(d3_geo_gnomonic); | |
}).raw = d3_geo_gnomonic; | |
function d3_geo_mercator(λ, φ) { | |
return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; | |
} | |
d3_geo_mercator.invert = function(x, y) { | |
return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; | |
}; | |
function d3_geo_mercatorProjection(project) { | |
var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; | |
m.scale = function() { | |
var v = scale.apply(m, arguments); | |
return v === m ? clipAuto ? m.clipExtent(null) : m : v; | |
}; | |
m.translate = function() { | |
var v = translate.apply(m, arguments); | |
return v === m ? clipAuto ? m.clipExtent(null) : m : v; | |
}; | |
m.clipExtent = function(_) { | |
var v = clipExtent.apply(m, arguments); | |
if (v === m) { | |
if (clipAuto = _ == null) { | |
var k = π * scale(), t = translate(); | |
clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); | |
} | |
} else if (clipAuto) { | |
v = null; | |
} | |
return v; | |
}; | |
return m.clipExtent(null); | |
} | |
(d3.geo.mercator = function() { | |
return d3_geo_mercatorProjection(d3_geo_mercator); | |
}).raw = d3_geo_mercator; | |
var d3_geo_orthographic = d3_geo_azimuthal(function() { | |
return 1; | |
}, Math.asin); | |
(d3.geo.orthographic = function() { | |
return d3_geo_projection(d3_geo_orthographic); | |
}).raw = d3_geo_orthographic; | |
var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { | |
return 1 / (1 + cosλcosφ); | |
}, function(ρ) { | |
return 2 * Math.atan(ρ); | |
}); | |
(d3.geo.stereographic = function() { | |
return d3_geo_projection(d3_geo_stereographic); | |
}).raw = d3_geo_stereographic; | |
function d3_geo_transverseMercator(λ, φ) { | |
return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; | |
} | |
d3_geo_transverseMercator.invert = function(x, y) { | |
return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; | |
}; | |
(d3.geo.transverseMercator = function() { | |
var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; | |
projection.center = function(_) { | |
return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); | |
}; | |
projection.rotate = function(_) { | |
return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), | |
[ _[0], _[1], _[2] - 90 ]); | |
}; | |
return rotate([ 0, 0, 90 ]); | |
}).raw = d3_geo_transverseMercator; | |
d3.geom = {}; | |
function d3_geom_pointX(d) { | |
return d[0]; | |
} | |
function d3_geom_pointY(d) { | |
return d[1]; | |
} | |
d3.geom.hull = function(vertices) { | |
var x = d3_geom_pointX, y = d3_geom_pointY; | |
if (arguments.length) return hull(vertices); | |
function hull(data) { | |
if (data.length < 3) return []; | |
var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; | |
for (i = 0; i < n; i++) { | |
points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); | |
} | |
points.sort(d3_geom_hullOrder); | |
for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); | |
var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); | |
var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; | |
for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); | |
for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); | |
return polygon; | |
} | |
hull.x = function(_) { | |
return arguments.length ? (x = _, hull) : x; | |
}; | |
hull.y = function(_) { | |
return arguments.length ? (y = _, hull) : y; | |
}; | |
return hull; | |
}; | |
function d3_geom_hullUpper(points) { | |
var n = points.length, hull = [ 0, 1 ], hs = 2; | |
for (var i = 2; i < n; i++) { | |
while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; | |
hull[hs++] = i; | |
} | |
return hull.slice(0, hs); | |
} | |
function d3_geom_hullOrder(a, b) { | |
return a[0] - b[0] || a[1] - b[1]; | |
} | |
d3.geom.polygon = function(coordinates) { | |
d3_subclass(coordinates, d3_geom_polygonPrototype); | |
return coordinates; | |
}; | |
var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; | |
d3_geom_polygonPrototype.area = function() { | |
var i = -1, n = this.length, a, b = this[n - 1], area = 0; | |
while (++i < n) { | |
a = b; | |
b = this[i]; | |
area += a[1] * b[0] - a[0] * b[1]; | |
} | |
return area * .5; | |
}; | |
d3_geom_polygonPrototype.centroid = function(k) { | |
var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; | |
if (!arguments.length) k = -1 / (6 * this.area()); | |
while (++i < n) { | |
a = b; | |
b = this[i]; | |
c = a[0] * b[1] - b[0] * a[1]; | |
x += (a[0] + b[0]) * c; | |
y += (a[1] + b[1]) * c; | |
} | |
return [ x * k, y * k ]; | |
}; | |
d3_geom_polygonPrototype.clip = function(subject) { | |
var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; | |
while (++i < n) { | |
input = subject.slice(); | |
subject.length = 0; | |
b = this[i]; | |
c = input[(m = input.length - closed) - 1]; | |
j = -1; | |
while (++j < m) { | |
d = input[j]; | |
if (d3_geom_polygonInside(d, a, b)) { | |
if (!d3_geom_polygonInside(c, a, b)) { | |
subject.push(d3_geom_polygonIntersect(c, d, a, b)); | |
} | |
subject.push(d); | |
} else if (d3_geom_polygonInside(c, a, b)) { | |
subject.push(d3_geom_polygonIntersect(c, d, a, b)); | |
} | |
c = d; | |
} | |
if (closed) subject.push(subject[0]); | |
a = b; | |
} | |
return subject; | |
}; | |
function d3_geom_polygonInside(p, a, b) { | |
return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); | |
} | |
function d3_geom_polygonIntersect(c, d, a, b) { | |
var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); | |
return [ x1 + ua * x21, y1 + ua * y21 ]; | |
} | |
function d3_geom_polygonClosed(coordinates) { | |
var a = coordinates[0], b = coordinates[coordinates.length - 1]; | |
return !(a[0] - b[0] || a[1] - b[1]); | |
} | |
var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; | |
function d3_geom_voronoiBeach() { | |
d3_geom_voronoiRedBlackNode(this); | |
this.edge = this.site = this.circle = null; | |
} | |
function d3_geom_voronoiCreateBeach(site) { | |
var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); | |
beach.site = site; | |
return beach; | |
} | |
function d3_geom_voronoiDetachBeach(beach) { | |
d3_geom_voronoiDetachCircle(beach); | |
d3_geom_voronoiBeaches.remove(beach); | |
d3_geom_voronoiBeachPool.push(beach); | |
d3_geom_voronoiRedBlackNode(beach); | |
} | |
function d3_geom_voronoiRemoveBeach(beach) { | |
var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { | |
x: x, | |
y: y | |
}, previous = beach.P, next = beach.N, disappearing = [ beach ]; | |
d3_geom_voronoiDetachBeach(beach); | |
var lArc = previous; | |
while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { | |
previous = lArc.P; | |
disappearing.unshift(lArc); | |
d3_geom_voronoiDetachBeach(lArc); | |
lArc = previous; | |
} | |
disappearing.unshift(lArc); | |
d3_geom_voronoiDetachCircle(lArc); | |
var rArc = next; | |
while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { | |
next = rArc.N; | |
disappearing.push(rArc); | |
d3_geom_voronoiDetachBeach(rArc); | |
rArc = next; | |
} | |
disappearing.push(rArc); | |
d3_geom_voronoiDetachCircle(rArc); | |
var nArcs = disappearing.length, iArc; | |
for (iArc = 1; iArc < nArcs; ++iArc) { | |
rArc = disappearing[iArc]; | |
lArc = disappearing[iArc - 1]; | |
d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); | |
} | |
lArc = disappearing[0]; | |
rArc = disappearing[nArcs - 1]; | |
rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); | |
d3_geom_voronoiAttachCircle(lArc); | |
d3_geom_voronoiAttachCircle(rArc); | |
} | |
function d3_geom_voronoiAddBeach(site) { | |
var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; | |
while (node) { | |
dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; | |
if (dxl > ε) node = node.L; else { | |
dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); | |
if (dxr > ε) { | |
if (!node.R) { | |
lArc = node; | |
break; | |
} | |
node = node.R; | |
} else { | |
if (dxl > -ε) { | |
lArc = node.P; | |
rArc = node; | |
} else if (dxr > -ε) { | |
lArc = node; | |
rArc = node.N; | |
} else { | |
lArc = rArc = node; | |
} | |
break; | |
} | |
} | |
} | |
var newArc = d3_geom_voronoiCreateBeach(site); | |
d3_geom_voronoiBeaches.insert(lArc, newArc); | |
if (!lArc && !rArc) return; | |
if (lArc === rArc) { | |
d3_geom_voronoiDetachCircle(lArc); | |
rArc = d3_geom_voronoiCreateBeach(lArc.site); | |
d3_geom_voronoiBeaches.insert(newArc, rArc); | |
newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); | |
d3_geom_voronoiAttachCircle(lArc); | |
d3_geom_voronoiAttachCircle(rArc); | |
return; | |
} | |
if (!rArc) { | |
newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); | |
return; | |
} | |
d3_geom_voronoiDetachCircle(lArc); | |
d3_geom_voronoiDetachCircle(rArc); | |
var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { | |
x: (cy * hb - by * hc) / d + ax, | |
y: (bx * hc - cx * hb) / d + ay | |
}; | |
d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); | |
newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); | |
rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); | |
d3_geom_voronoiAttachCircle(lArc); | |
d3_geom_voronoiAttachCircle(rArc); | |
} | |
function d3_geom_voronoiLeftBreakPoint(arc, directrix) { | |
var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; | |
if (!pby2) return rfocx; | |
var lArc = arc.P; | |
if (!lArc) return -Infinity; | |
site = lArc.site; | |
var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; | |
if (!plby2) return lfocx; | |
var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; | |
if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; | |
return (rfocx + lfocx) / 2; | |
} | |
function d3_geom_voronoiRightBreakPoint(arc, directrix) { | |
var rArc = arc.N; | |
if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); | |
var site = arc.site; | |
return site.y === directrix ? site.x : Infinity; | |
} | |
function d3_geom_voronoiCell(site) { | |
this.site = site; | |
this.edges = []; | |
} | |
d3_geom_voronoiCell.prototype.prepare = function() { | |
var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; | |
while (iHalfEdge--) { | |
edge = halfEdges[iHalfEdge].edge; | |
if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); | |
} | |
halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); | |
return halfEdges.length; | |
}; | |
function d3_geom_voronoiCloseCells(extent) { | |
var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; | |
while (iCell--) { | |
cell = cells[iCell]; | |
if (!cell || !cell.prepare()) continue; | |
halfEdges = cell.edges; | |
nHalfEdges = halfEdges.length; | |
iHalfEdge = 0; | |
while (iHalfEdge < nHalfEdges) { | |
end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; | |
start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; | |
if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { | |
halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { | |
x: x0, | |
y: abs(x2 - x0) < ε ? y2 : y1 | |
} : abs(y3 - y1) < ε && x1 - x3 > ε ? { | |
x: abs(y2 - y1) < ε ? x2 : x1, | |
y: y1 | |
} : abs(x3 - x1) < ε && y3 - y0 > ε ? { | |
x: x1, | |
y: abs(x2 - x1) < ε ? y2 : y0 | |
} : abs(y3 - y0) < ε && x3 - x0 > ε ? { | |
x: abs(y2 - y0) < ε ? x2 : x0, | |
y: y0 | |
} : null), cell.site, null)); | |
++nHalfEdges; | |
} | |
} | |
} | |
} | |
function d3_geom_voronoiHalfEdgeOrder(a, b) { | |
return b.angle - a.angle; | |
} | |
function d3_geom_voronoiCircle() { | |
d3_geom_voronoiRedBlackNode(this); | |
this.x = this.y = this.arc = this.site = this.cy = null; | |
} | |
function d3_geom_voronoiAttachCircle(arc) { | |
var lArc = arc.P, rArc = arc.N; | |
if (!lArc || !rArc) return; | |
var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; | |
if (lSite === rSite) return; | |
var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; | |
var d = 2 * (ax * cy - ay * cx); | |
if (d >= -ε2) return; | |
var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; | |
var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); | |
circle.arc = arc; | |
circle.site = cSite; | |
circle.x = x + bx; | |
circle.y = cy + Math.sqrt(x * x + y * y); | |
circle.cy = cy; | |
arc.circle = circle; | |
var before = null, node = d3_geom_voronoiCircles._; | |
while (node) { | |
if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { | |
if (node.L) node = node.L; else { | |
before = node.P; | |
break; | |
} | |
} else { | |
if (node.R) node = node.R; else { | |
before = node; | |
break; | |
} | |
} | |
} | |
d3_geom_voronoiCircles.insert(before, circle); | |
if (!before) d3_geom_voronoiFirstCircle = circle; | |
} | |
function d3_geom_voronoiDetachCircle(arc) { | |
var circle = arc.circle; | |
if (circle) { | |
if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; | |
d3_geom_voronoiCircles.remove(circle); | |
d3_geom_voronoiCirclePool.push(circle); | |
d3_geom_voronoiRedBlackNode(circle); | |
arc.circle = null; | |
} | |
} | |
function d3_geom_voronoiClipEdges(extent) { | |
var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; | |
while (i--) { | |
e = edges[i]; | |
if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { | |
e.a = e.b = null; | |
edges.splice(i, 1); | |
} | |
} | |
} | |
function d3_geom_voronoiConnectEdge(edge, extent) { | |
var vb = edge.b; | |
if (vb) return true; | |
var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; | |
if (ry === ly) { | |
if (fx < x0 || fx >= x1) return; | |
if (lx > rx) { | |
if (!va) va = { | |
x: fx, | |
y: y0 | |
}; else if (va.y >= y1) return; | |
vb = { | |
x: fx, | |
y: y1 | |
}; | |
} else { | |
if (!va) va = { | |
x: fx, | |
y: y1 | |
}; else if (va.y < y0) return; | |
vb = { | |
x: fx, | |
y: y0 | |
}; | |
} | |
} else { | |
fm = (lx - rx) / (ry - ly); | |
fb = fy - fm * fx; | |
if (fm < -1 || fm > 1) { | |
if (lx > rx) { | |
if (!va) va = { | |
x: (y0 - fb) / fm, | |
y: y0 | |
}; else if (va.y >= y1) return; | |
vb = { | |
x: (y1 - fb) / fm, | |
y: y1 | |
}; | |
} else { | |
if (!va) va = { | |
x: (y1 - fb) / fm, | |
y: y1 | |
}; else if (va.y < y0) return; | |
vb = { | |
x: (y0 - fb) / fm, | |
y: y0 | |
}; | |
} | |
} else { | |
if (ly < ry) { | |
if (!va) va = { | |
x: x0, | |
y: fm * x0 + fb | |
}; else if (va.x >= x1) return; | |
vb = { | |
x: x1, | |
y: fm * x1 + fb | |
}; | |
} else { | |
if (!va) va = { | |
x: x1, | |
y: fm * x1 + fb | |
}; else if (va.x < x0) return; | |
vb = { | |
x: x0, | |
y: fm * x0 + fb | |
}; | |
} | |
} | |
} | |
edge.a = va; | |
edge.b = vb; | |
return true; | |
} | |
function d3_geom_voronoiEdge(lSite, rSite) { | |
this.l = lSite; | |
this.r = rSite; | |
this.a = this.b = null; | |
} | |
function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { | |
var edge = new d3_geom_voronoiEdge(lSite, rSite); | |
d3_geom_voronoiEdges.push(edge); | |
if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); | |
if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); | |
d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); | |
d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); | |
return edge; | |
} | |
function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { | |
var edge = new d3_geom_voronoiEdge(lSite, null); | |
edge.a = va; | |
edge.b = vb; | |
d3_geom_voronoiEdges.push(edge); | |
return edge; | |
} | |
function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { | |
if (!edge.a && !edge.b) { | |
edge.a = vertex; | |
edge.l = lSite; | |
edge.r = rSite; | |
} else if (edge.l === rSite) { | |
edge.b = vertex; | |
} else { | |
edge.a = vertex; | |
} | |
} | |
function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { | |
var va = edge.a, vb = edge.b; | |
this.edge = edge; | |
this.site = lSite; | |
this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); | |
} | |
d3_geom_voronoiHalfEdge.prototype = { | |
start: function() { | |
return this.edge.l === this.site ? this.edge.a : this.edge.b; | |
}, | |
end: function() { | |
return this.edge.l === this.site ? this.edge.b : this.edge.a; | |
} | |
}; | |
function d3_geom_voronoiRedBlackTree() { | |
this._ = null; | |
} | |
function d3_geom_voronoiRedBlackNode(node) { | |
node.U = node.C = node.L = node.R = node.P = node.N = null; | |
} | |
d3_geom_voronoiRedBlackTree.prototype = { | |
insert: function(after, node) { | |
var parent, grandpa, uncle; | |
if (after) { | |
node.P = after; | |
node.N = after.N; | |
if (after.N) after.N.P = node; | |
after.N = node; | |
if (after.R) { | |
after = after.R; | |
while (after.L) after = after.L; | |
after.L = node; | |
} else { | |
after.R = node; | |
} | |
parent = after; | |
} else if (this._) { | |
after = d3_geom_voronoiRedBlackFirst(this._); | |
node.P = null; | |
node.N = after; | |
after.P = after.L = node; | |
parent = after; | |
} else { | |
node.P = node.N = null; | |
this._ = node; | |
parent = null; | |
} | |
node.L = node.R = null; | |
node.U = parent; | |
node.C = true; | |
after = node; | |
while (parent && parent.C) { | |
grandpa = parent.U; | |
if (parent === grandpa.L) { | |
uncle = grandpa.R; | |
if (uncle && uncle.C) { | |
parent.C = uncle.C = false; | |
grandpa.C = true; | |
after = grandpa; | |
} else { | |
if (after === parent.R) { | |
d3_geom_voronoiRedBlackRotateLeft(this, parent); | |
after = parent; | |
parent = after.U; | |
} | |
parent.C = false; | |
grandpa.C = true; | |
d3_geom_voronoiRedBlackRotateRight(this, grandpa); | |
} | |
} else { | |
uncle = grandpa.L; | |
if (uncle && uncle.C) { | |
parent.C = uncle.C = false; | |
grandpa.C = true; | |
after = grandpa; | |
} else { | |
if (after === parent.L) { | |
d3_geom_voronoiRedBlackRotateRight(this, parent); | |
after = parent; | |
parent = after.U; | |
} | |
parent.C = false; | |
grandpa.C = true; | |
d3_geom_voronoiRedBlackRotateLeft(this, grandpa); | |
} | |
} | |
parent = after.U; | |
} | |
this._.C = false; | |
}, | |
remove: function(node) { | |
if (node.N) node.N.P = node.P; | |
if (node.P) node.P.N = node.N; | |
node.N = node.P = null; | |
var parent = node.U, sibling, left = node.L, right = node.R, next, red; | |
if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); | |
if (parent) { | |
if (parent.L === node) parent.L = next; else parent.R = next; | |
} else { | |
this._ = next; | |
} | |
if (left && right) { | |
red = next.C; | |
next.C = node.C; | |
next.L = left; | |
left.U = next; | |
if (next !== right) { | |
parent = next.U; | |
next.U = node.U; | |
node = next.R; | |
parent.L = node; | |
next.R = right; | |
right.U = next; | |
} else { | |
next.U = parent; | |
parent = next; | |
node = next.R; | |
} | |
} else { | |
red = node.C; | |
node = next; | |
} | |
if (node) node.U = parent; | |
if (red) return; | |
if (node && node.C) { | |
node.C = false; | |
return; | |
} | |
do { | |
if (node === this._) break; | |
if (node === parent.L) { | |
sibling = parent.R; | |
if (sibling.C) { | |
sibling.C = false; | |
parent.C = true; | |
d3_geom_voronoiRedBlackRotateLeft(this, parent); | |
sibling = parent.R; | |
} | |
if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { | |
if (!sibling.R || !sibling.R.C) { | |
sibling.L.C = false; | |
sibling.C = true; | |
d3_geom_voronoiRedBlackRotateRight(this, sibling); | |
sibling = parent.R; | |
} | |
sibling.C = parent.C; | |
parent.C = sibling.R.C = false; | |
d3_geom_voronoiRedBlackRotateLeft(this, parent); | |
node = this._; | |
break; | |
} | |
} else { | |
sibling = parent.L; | |
if (sibling.C) { | |
sibling.C = false; | |
parent.C = true; | |
d3_geom_voronoiRedBlackRotateRight(this, parent); | |
sibling = parent.L; | |
} | |
if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { | |
if (!sibling.L || !sibling.L.C) { | |
sibling.R.C = false; | |
sibling.C = true; | |
d3_geom_voronoiRedBlackRotateLeft(this, sibling); | |
sibling = parent.L; | |
} | |
sibling.C = parent.C; | |
parent.C = sibling.L.C = false; | |
d3_geom_voronoiRedBlackRotateRight(this, parent); | |
node = this._; | |
break; | |
} | |
} | |
sibling.C = true; | |
node = parent; | |
parent = parent.U; | |
} while (!node.C); | |
if (node) node.C = false; | |
} | |
}; | |
function d3_geom_voronoiRedBlackRotateLeft(tree, node) { | |
var p = node, q = node.R, parent = p.U; | |
if (parent) { | |
if (parent.L === p) parent.L = q; else parent.R = q; | |
} else { | |
tree._ = q; | |
} | |
q.U = parent; | |
p.U = q; | |
p.R = q.L; | |
if (p.R) p.R.U = p; | |
q.L = p; | |
} | |
function d3_geom_voronoiRedBlackRotateRight(tree, node) { | |
var p = node, q = node.L, parent = p.U; | |
if (parent) { | |
if (parent.L === p) parent.L = q; else parent.R = q; | |
} else { | |
tree._ = q; | |
} | |
q.U = parent; | |
p.U = q; | |
p.L = q.R; | |
if (p.L) p.L.U = p; | |
q.R = p; | |
} | |
function d3_geom_voronoiRedBlackFirst(node) { | |
while (node.L) node = node.L; | |
return node; | |
} | |
function d3_geom_voronoi(sites, bbox) { | |
var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; | |
d3_geom_voronoiEdges = []; | |
d3_geom_voronoiCells = new Array(sites.length); | |
d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); | |
d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); | |
while (true) { | |
circle = d3_geom_voronoiFirstCircle; | |
if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { | |
if (site.x !== x0 || site.y !== y0) { | |
d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); | |
d3_geom_voronoiAddBeach(site); | |
x0 = site.x, y0 = site.y; | |
} | |
site = sites.pop(); | |
} else if (circle) { | |
d3_geom_voronoiRemoveBeach(circle.arc); | |
} else { | |
break; | |
} | |
} | |
if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); | |
var diagram = { | |
cells: d3_geom_voronoiCells, | |
edges: d3_geom_voronoiEdges | |
}; | |
d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; | |
return diagram; | |
} | |
function d3_geom_voronoiVertexOrder(a, b) { | |
return b.y - a.y || b.x - a.x; | |
} | |
d3.geom.voronoi = function(points) { | |
var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; | |
if (points) return voronoi(points); | |
function voronoi(data) { | |
var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; | |
d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { | |
var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { | |
var s = e.start(); | |
return [ s.x, s.y ]; | |
}) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; | |
polygon.point = data[i]; | |
}); | |
return polygons; | |
} | |
function sites(data) { | |
return data.map(function(d, i) { | |
return { | |
x: Math.round(fx(d, i) / ε) * ε, | |
y: Math.round(fy(d, i) / ε) * ε, | |
i: i | |
}; | |
}); | |
} | |
voronoi.links = function(data) { | |
return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { | |
return edge.l && edge.r; | |
}).map(function(edge) { | |
return { | |
source: data[edge.l.i], | |
target: data[edge.r.i] | |
}; | |
}); | |
}; | |
voronoi.triangles = function(data) { | |
var triangles = []; | |
d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { | |
var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; | |
while (++j < m) { | |
e0 = e1; | |
s0 = s1; | |
e1 = edges[j].edge; | |
s1 = e1.l === site ? e1.r : e1.l; | |
if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { | |
triangles.push([ data[i], data[s0.i], data[s1.i] ]); | |
} | |
} | |
}); | |
return triangles; | |
}; | |
voronoi.x = function(_) { | |
return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; | |
}; | |
voronoi.y = function(_) { | |
return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; | |
}; | |
voronoi.clipExtent = function(_) { | |
if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; | |
clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; | |
return voronoi; | |
}; | |
voronoi.size = function(_) { | |
if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; | |
return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); | |
}; | |
return voronoi; | |
}; | |
var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; | |
function d3_geom_voronoiTriangleArea(a, b, c) { | |
return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); | |
} | |
d3.geom.delaunay = function(vertices) { | |
return d3.geom.voronoi().triangles(vertices); | |
}; | |
d3.geom.quadtree = function(points, x1, y1, x2, y2) { | |
var x = d3_geom_pointX, y = d3_geom_pointY, compat; | |
if (compat = arguments.length) { | |
x = d3_geom_quadtreeCompatX; | |
y = d3_geom_quadtreeCompatY; | |
if (compat === 3) { | |
y2 = y1; | |
x2 = x1; | |
y1 = x1 = 0; | |
} | |
return quadtree(points); | |
} | |
function quadtree(data) { | |
var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; | |
if (x1 != null) { | |
x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; | |
} else { | |
x2_ = y2_ = -(x1_ = y1_ = Infinity); | |
xs = [], ys = []; | |
n = data.length; | |
if (compat) for (i = 0; i < n; ++i) { | |
d = data[i]; | |
if (d.x < x1_) x1_ = d.x; | |
if (d.y < y1_) y1_ = d.y; | |
if (d.x > x2_) x2_ = d.x; | |
if (d.y > y2_) y2_ = d.y; | |
xs.push(d.x); | |
ys.push(d.y); | |
} else for (i = 0; i < n; ++i) { | |
var x_ = +fx(d = data[i], i), y_ = +fy(d, i); | |
if (x_ < x1_) x1_ = x_; | |
if (y_ < y1_) y1_ = y_; | |
if (x_ > x2_) x2_ = x_; | |
if (y_ > y2_) y2_ = y_; | |
xs.push(x_); | |
ys.push(y_); | |
} | |
} | |
var dx = x2_ - x1_, dy = y2_ - y1_; | |
if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; | |
function insert(n, d, x, y, x1, y1, x2, y2) { | |
if (isNaN(x) || isNaN(y)) return; | |
if (n.leaf) { | |
var nx = n.x, ny = n.y; | |
if (nx != null) { | |
if (abs(nx - x) + abs(ny - y) < .01) { | |
insertChild(n, d, x, y, x1, y1, x2, y2); | |
} else { | |
var nPoint = n.point; | |
n.x = n.y = n.point = null; | |
insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); | |
insertChild(n, d, x, y, x1, y1, x2, y2); | |
} | |
} else { | |
n.x = x, n.y = y, n.point = d; | |
} | |
} else { | |
insertChild(n, d, x, y, x1, y1, x2, y2); | |
} | |
} | |
function insertChild(n, d, x, y, x1, y1, x2, y2) { | |
var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; | |
n.leaf = false; | |
n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); | |
if (right) x1 = xm; else x2 = xm; | |
if (below) y1 = ym; else y2 = ym; | |
insert(n, d, x, y, x1, y1, x2, y2); | |
} | |
var root = d3_geom_quadtreeNode(); | |
root.add = function(d) { | |
insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); | |
}; | |
root.visit = function(f) { | |
d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); | |
}; | |
root.find = function(point) { | |
return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); | |
}; | |
i = -1; | |
if (x1 == null) { | |
while (++i < n) { | |
insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); | |
} | |
--i; | |
} else data.forEach(root.add); | |
xs = ys = data = d = null; | |
return root; | |
} | |
quadtree.x = function(_) { | |
return arguments.length ? (x = _, quadtree) : x; | |
}; | |
quadtree.y = function(_) { | |
return arguments.length ? (y = _, quadtree) : y; | |
}; | |
quadtree.extent = function(_) { | |
if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; | |
if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], | |
y2 = +_[1][1]; | |
return quadtree; | |
}; | |
quadtree.size = function(_) { | |
if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; | |
if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; | |
return quadtree; | |
}; | |
return quadtree; | |
}; | |
function d3_geom_quadtreeCompatX(d) { | |
return d.x; | |
} | |
function d3_geom_quadtreeCompatY(d) { | |
return d.y; | |
} | |
function d3_geom_quadtreeNode() { | |
return { | |
leaf: true, | |
nodes: [], | |
point: null, | |
x: null, | |
y: null | |
}; | |
} | |
function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { | |
if (!f(node, x1, y1, x2, y2)) { | |
var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; | |
if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); | |
if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); | |
if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); | |
if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); | |
} | |
} | |
function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { | |
var minDistance2 = Infinity, closestPoint; | |
(function find(node, x1, y1, x2, y2) { | |
if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; | |
if (point = node.point) { | |
var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; | |
if (distance2 < minDistance2) { | |
var distance = Math.sqrt(minDistance2 = distance2); | |
x0 = x - distance, y0 = y - distance; | |
x3 = x + distance, y3 = y + distance; | |
closestPoint = point; | |
} | |
} | |
var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; | |
for (var i = below << 1 | right, j = i + 4; i < j; ++i) { | |
if (node = children[i & 3]) switch (i & 3) { | |
case 0: | |
find(node, x1, y1, xm, ym); | |
break; | |
case 1: | |
find(node, xm, y1, x2, ym); | |
break; | |
case 2: | |
find(node, x1, ym, xm, y2); | |
break; | |
case 3: | |
find(node, xm, ym, x2, y2); | |
break; | |
} | |
} | |
})(root, x0, y0, x3, y3); | |
return closestPoint; | |
} | |
d3.interpolateRgb = d3_interpolateRgb; | |
function d3_interpolateRgb(a, b) { | |
a = d3.rgb(a); | |
b = d3.rgb(b); | |
var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; | |
return function(t) { | |
return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); | |
}; | |
} | |
d3.interpolateObject = d3_interpolateObject; | |
function d3_interpolateObject(a, b) { | |
var i = {}, c = {}, k; | |
for (k in a) { | |
if (k in b) { | |
i[k] = d3_interpolate(a[k], b[k]); | |
} else { | |
c[k] = a[k]; | |
} | |
} | |
for (k in b) { | |
if (!(k in a)) { | |
c[k] = b[k]; | |
} | |
} | |
return function(t) { | |
for (k in i) c[k] = i[k](t); | |
return c; | |
}; | |
} | |
d3.interpolateNumber = d3_interpolateNumber; | |
function d3_interpolateNumber(a, b) { | |
a = +a, b = +b; | |
return function(t) { | |
return a * (1 - t) + b * t; | |
}; | |
} | |
d3.interpolateString = d3_interpolateString; | |
function d3_interpolateString(a, b) { | |
var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; | |
a = a + "", b = b + ""; | |
while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { | |
if ((bs = bm.index) > bi) { | |
bs = b.slice(bi, bs); | |
if (s[i]) s[i] += bs; else s[++i] = bs; | |
} | |
if ((am = am[0]) === (bm = bm[0])) { | |
if (s[i]) s[i] += bm; else s[++i] = bm; | |
} else { | |
s[++i] = null; | |
q.push({ | |
i: i, | |
x: d3_interpolateNumber(am, bm) | |
}); | |
} | |
bi = d3_interpolate_numberB.lastIndex; | |
} | |
if (bi < b.length) { | |
bs = b.slice(bi); | |
if (s[i]) s[i] += bs; else s[++i] = bs; | |
} | |
return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { | |
return b(t) + ""; | |
}) : function() { | |
return b; | |
} : (b = q.length, function(t) { | |
for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}); | |
} | |
var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); | |
d3.interpolate = d3_interpolate; | |
function d3_interpolate(a, b) { | |
var i = d3.interpolators.length, f; | |
while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; | |
return f; | |
} | |
d3.interpolators = [ function(a, b) { | |
var t = typeof b; | |
return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); | |
} ]; | |
d3.interpolateArray = d3_interpolateArray; | |
function d3_interpolateArray(a, b) { | |
var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; | |
for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); | |
for (;i < na; ++i) c[i] = a[i]; | |
for (;i < nb; ++i) c[i] = b[i]; | |
return function(t) { | |
for (i = 0; i < n0; ++i) c[i] = x[i](t); | |
return c; | |
}; | |
} | |
var d3_ease_default = function() { | |
return d3_identity; | |
}; | |
var d3_ease = d3.map({ | |
linear: d3_ease_default, | |
poly: d3_ease_poly, | |
quad: function() { | |
return d3_ease_quad; | |
}, | |
cubic: function() { | |
return d3_ease_cubic; | |
}, | |
sin: function() { | |
return d3_ease_sin; | |
}, | |
exp: function() { | |
return d3_ease_exp; | |
}, | |
circle: function() { | |
return d3_ease_circle; | |
}, | |
elastic: d3_ease_elastic, | |
back: d3_ease_back, | |
bounce: function() { | |
return d3_ease_bounce; | |
} | |
}); | |
var d3_ease_mode = d3.map({ | |
"in": d3_identity, | |
out: d3_ease_reverse, | |
"in-out": d3_ease_reflect, | |
"out-in": function(f) { | |
return d3_ease_reflect(d3_ease_reverse(f)); | |
} | |
}); | |
d3.ease = function(name) { | |
var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; | |
t = d3_ease.get(t) || d3_ease_default; | |
m = d3_ease_mode.get(m) || d3_identity; | |
return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); | |
}; | |
function d3_ease_clamp(f) { | |
return function(t) { | |
return t <= 0 ? 0 : t >= 1 ? 1 : f(t); | |
}; | |
} | |
function d3_ease_reverse(f) { | |
return function(t) { | |
return 1 - f(1 - t); | |
}; | |
} | |
function d3_ease_reflect(f) { | |
return function(t) { | |
return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); | |
}; | |
} | |
function d3_ease_quad(t) { | |
return t * t; | |
} | |
function d3_ease_cubic(t) { | |
return t * t * t; | |
} | |
function d3_ease_cubicInOut(t) { | |
if (t <= 0) return 0; | |
if (t >= 1) return 1; | |
var t2 = t * t, t3 = t2 * t; | |
return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); | |
} | |
function d3_ease_poly(e) { | |
return function(t) { | |
return Math.pow(t, e); | |
}; | |
} | |
function d3_ease_sin(t) { | |
return 1 - Math.cos(t * halfπ); | |
} | |
function d3_ease_exp(t) { | |
return Math.pow(2, 10 * (t - 1)); | |
} | |
function d3_ease_circle(t) { | |
return 1 - Math.sqrt(1 - t * t); | |
} | |
function d3_ease_elastic(a, p) { | |
var s; | |
if (arguments.length < 2) p = .45; | |
if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; | |
return function(t) { | |
return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); | |
}; | |
} | |
function d3_ease_back(s) { | |
if (!s) s = 1.70158; | |
return function(t) { | |
return t * t * ((s + 1) * t - s); | |
}; | |
} | |
function d3_ease_bounce(t) { | |
return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; | |
} | |
d3.interpolateHcl = d3_interpolateHcl; | |
function d3_interpolateHcl(a, b) { | |
a = d3.hcl(a); | |
b = d3.hcl(b); | |
var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; | |
if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; | |
if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; | |
return function(t) { | |
return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; | |
}; | |
} | |
d3.interpolateHsl = d3_interpolateHsl; | |
function d3_interpolateHsl(a, b) { | |
a = d3.hsl(a); | |
b = d3.hsl(b); | |
var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; | |
if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; | |
if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; | |
return function(t) { | |
return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; | |
}; | |
} | |
d3.interpolateLab = d3_interpolateLab; | |
function d3_interpolateLab(a, b) { | |
a = d3.lab(a); | |
b = d3.lab(b); | |
var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; | |
return function(t) { | |
return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; | |
}; | |
} | |
d3.interpolateRound = d3_interpolateRound; | |
function d3_interpolateRound(a, b) { | |
b -= a; | |
return function(t) { | |
return Math.round(a + b * t); | |
}; | |
} | |
d3.transform = function(string) { | |
var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); | |
return (d3.transform = function(string) { | |
if (string != null) { | |
g.setAttribute("transform", string); | |
var t = g.transform.baseVal.consolidate(); | |
} | |
return new d3_transform(t ? t.matrix : d3_transformIdentity); | |
})(string); | |
}; | |
function d3_transform(m) { | |
var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; | |
if (r0[0] * r1[1] < r1[0] * r0[1]) { | |
r0[0] *= -1; | |
r0[1] *= -1; | |
kx *= -1; | |
kz *= -1; | |
} | |
this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; | |
this.translate = [ m.e, m.f ]; | |
this.scale = [ kx, ky ]; | |
this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; | |
} | |
d3_transform.prototype.toString = function() { | |
return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; | |
}; | |
function d3_transformDot(a, b) { | |
return a[0] * b[0] + a[1] * b[1]; | |
} | |
function d3_transformNormalize(a) { | |
var k = Math.sqrt(d3_transformDot(a, a)); | |
if (k) { | |
a[0] /= k; | |
a[1] /= k; | |
} | |
return k; | |
} | |
function d3_transformCombine(a, b, k) { | |
a[0] += k * b[0]; | |
a[1] += k * b[1]; | |
return a; | |
} | |
var d3_transformIdentity = { | |
a: 1, | |
b: 0, | |
c: 0, | |
d: 1, | |
e: 0, | |
f: 0 | |
}; | |
d3.interpolateTransform = d3_interpolateTransform; | |
function d3_interpolateTransformPop(s) { | |
return s.length ? s.pop() + "," : ""; | |
} | |
function d3_interpolateTranslate(ta, tb, s, q) { | |
if (ta[0] !== tb[0] || ta[1] !== tb[1]) { | |
var i = s.push("translate(", null, ",", null, ")"); | |
q.push({ | |
i: i - 4, | |
x: d3_interpolateNumber(ta[0], tb[0]) | |
}, { | |
i: i - 2, | |
x: d3_interpolateNumber(ta[1], tb[1]) | |
}); | |
} else if (tb[0] || tb[1]) { | |
s.push("translate(" + tb + ")"); | |
} | |
} | |
function d3_interpolateRotate(ra, rb, s, q) { | |
if (ra !== rb) { | |
if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; | |
q.push({ | |
i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, | |
x: d3_interpolateNumber(ra, rb) | |
}); | |
} else if (rb) { | |
s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); | |
} | |
} | |
function d3_interpolateSkew(wa, wb, s, q) { | |
if (wa !== wb) { | |
q.push({ | |
i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, | |
x: d3_interpolateNumber(wa, wb) | |
}); | |
} else if (wb) { | |
s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); | |
} | |
} | |
function d3_interpolateScale(ka, kb, s, q) { | |
if (ka[0] !== kb[0] || ka[1] !== kb[1]) { | |
var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); | |
q.push({ | |
i: i - 4, | |
x: d3_interpolateNumber(ka[0], kb[0]) | |
}, { | |
i: i - 2, | |
x: d3_interpolateNumber(ka[1], kb[1]) | |
}); | |
} else if (kb[0] !== 1 || kb[1] !== 1) { | |
s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); | |
} | |
} | |
function d3_interpolateTransform(a, b) { | |
var s = [], q = []; | |
a = d3.transform(a), b = d3.transform(b); | |
d3_interpolateTranslate(a.translate, b.translate, s, q); | |
d3_interpolateRotate(a.rotate, b.rotate, s, q); | |
d3_interpolateSkew(a.skew, b.skew, s, q); | |
d3_interpolateScale(a.scale, b.scale, s, q); | |
a = b = null; | |
return function(t) { | |
var i = -1, n = q.length, o; | |
while (++i < n) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}; | |
} | |
function d3_uninterpolateNumber(a, b) { | |
b = (b -= a = +a) || 1 / b; | |
return function(x) { | |
return (x - a) / b; | |
}; | |
} | |
function d3_uninterpolateClamp(a, b) { | |
b = (b -= a = +a) || 1 / b; | |
return function(x) { | |
return Math.max(0, Math.min(1, (x - a) / b)); | |
}; | |
} | |
d3.layout = {}; | |
d3.layout.bundle = function() { | |
return function(links) { | |
var paths = [], i = -1, n = links.length; | |
while (++i < n) paths.push(d3_layout_bundlePath(links[i])); | |
return paths; | |
}; | |
}; | |
function d3_layout_bundlePath(link) { | |
var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; | |
while (start !== lca) { | |
start = start.parent; | |
points.push(start); | |
} | |
var k = points.length; | |
while (end !== lca) { | |
points.splice(k, 0, end); | |
end = end.parent; | |
} | |
return points; | |
} | |
function d3_layout_bundleAncestors(node) { | |
var ancestors = [], parent = node.parent; | |
while (parent != null) { | |
ancestors.push(node); | |
node = parent; | |
parent = parent.parent; | |
} | |
ancestors.push(node); | |
return ancestors; | |
} | |
function d3_layout_bundleLeastCommonAncestor(a, b) { | |
if (a === b) return a; | |
var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; | |
while (aNode === bNode) { | |
sharedNode = aNode; | |
aNode = aNodes.pop(); | |
bNode = bNodes.pop(); | |
} | |
return sharedNode; | |
} | |
d3.layout.chord = function() { | |
var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; | |
function relayout() { | |
var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; | |
chords = []; | |
groups = []; | |
k = 0, i = -1; | |
while (++i < n) { | |
x = 0, j = -1; | |
while (++j < n) { | |
x += matrix[i][j]; | |
} | |
groupSums.push(x); | |
subgroupIndex.push(d3.range(n)); | |
k += x; | |
} | |
if (sortGroups) { | |
groupIndex.sort(function(a, b) { | |
return sortGroups(groupSums[a], groupSums[b]); | |
}); | |
} | |
if (sortSubgroups) { | |
subgroupIndex.forEach(function(d, i) { | |
d.sort(function(a, b) { | |
return sortSubgroups(matrix[i][a], matrix[i][b]); | |
}); | |
}); | |
} | |
k = (τ - padding * n) / k; | |
x = 0, i = -1; | |
while (++i < n) { | |
x0 = x, j = -1; | |
while (++j < n) { | |
var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; | |
subgroups[di + "-" + dj] = { | |
index: di, | |
subindex: dj, | |
startAngle: a0, | |
endAngle: a1, | |
value: v | |
}; | |
} | |
groups[di] = { | |
index: di, | |
startAngle: x0, | |
endAngle: x, | |
value: groupSums[di] | |
}; | |
x += padding; | |
} | |
i = -1; | |
while (++i < n) { | |
j = i - 1; | |
while (++j < n) { | |
var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; | |
if (source.value || target.value) { | |
chords.push(source.value < target.value ? { | |
source: target, | |
target: source | |
} : { | |
source: source, | |
target: target | |
}); | |
} | |
} | |
} | |
if (sortChords) resort(); | |
} | |
function resort() { | |
chords.sort(function(a, b) { | |
return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); | |
}); | |
} | |
chord.matrix = function(x) { | |
if (!arguments.length) return matrix; | |
n = (matrix = x) && matrix.length; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.padding = function(x) { | |
if (!arguments.length) return padding; | |
padding = x; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.sortGroups = function(x) { | |
if (!arguments.length) return sortGroups; | |
sortGroups = x; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.sortSubgroups = function(x) { | |
if (!arguments.length) return sortSubgroups; | |
sortSubgroups = x; | |
chords = null; | |
return chord; | |
}; | |
chord.sortChords = function(x) { | |
if (!arguments.length) return sortChords; | |
sortChords = x; | |
if (chords) resort(); | |
return chord; | |
}; | |
chord.chords = function() { | |
if (!chords) relayout(); | |
return chords; | |
}; | |
chord.groups = function() { | |
if (!groups) relayout(); | |
return groups; | |
}; | |
return chord; | |
}; | |
d3.layout.force = function() { | |
var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; | |
function repulse(node) { | |
return function(quad, x1, _, x2) { | |
if (quad.point !== node) { | |
var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; | |
if (dw * dw / theta2 < dn) { | |
if (dn < chargeDistance2) { | |
var k = quad.charge / dn; | |
node.px -= dx * k; | |
node.py -= dy * k; | |
} | |
return true; | |
} | |
if (quad.point && dn && dn < chargeDistance2) { | |
var k = quad.pointCharge / dn; | |
node.px -= dx * k; | |
node.py -= dy * k; | |
} | |
} | |
return !quad.charge; | |
}; | |
} | |
force.tick = function() { | |
if ((alpha *= .99) < .005) { | |
timer = null; | |
event.end({ | |
type: "end", | |
alpha: alpha = 0 | |
}); | |
return true; | |
} | |
var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; | |
for (i = 0; i < m; ++i) { | |
o = links[i]; | |
s = o.source; | |
t = o.target; | |
x = t.x - s.x; | |
y = t.y - s.y; | |
if (l = x * x + y * y) { | |
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; | |
x *= l; | |
y *= l; | |
t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); | |
t.y -= y * k; | |
s.x += x * (k = 1 - k); | |
s.y += y * k; | |
} | |
} | |
if (k = alpha * gravity) { | |
x = size[0] / 2; | |
y = size[1] / 2; | |
i = -1; | |
if (k) while (++i < n) { | |
o = nodes[i]; | |
o.x += (x - o.x) * k; | |
o.y += (y - o.y) * k; | |
} | |
} | |
if (charge) { | |
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); | |
i = -1; | |
while (++i < n) { | |
if (!(o = nodes[i]).fixed) { | |
q.visit(repulse(o)); | |
} | |
} | |
} | |
i = -1; | |
while (++i < n) { | |
o = nodes[i]; | |
if (o.fixed) { | |
o.x = o.px; | |
o.y = o.py; | |
} else { | |
o.x -= (o.px - (o.px = o.x)) * friction; | |
o.y -= (o.py - (o.py = o.y)) * friction; | |
} | |
} | |
event.tick({ | |
type: "tick", | |
alpha: alpha | |
}); | |
}; | |
force.nodes = function(x) { | |
if (!arguments.length) return nodes; | |
nodes = x; | |
return force; | |
}; | |
force.links = function(x) { | |
if (!arguments.length) return links; | |
links = x; | |
return force; | |
}; | |
force.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return force; | |
}; | |
force.linkDistance = function(x) { | |
if (!arguments.length) return linkDistance; | |
linkDistance = typeof x === "function" ? x : +x; | |
return force; | |
}; | |
force.distance = force.linkDistance; | |
force.linkStrength = function(x) { | |
if (!arguments.length) return linkStrength; | |
linkStrength = typeof x === "function" ? x : +x; | |
return force; | |
}; | |
force.friction = function(x) { | |
if (!arguments.length) return friction; | |
friction = +x; | |
return force; | |
}; | |
force.charge = function(x) { | |
if (!arguments.length) return charge; | |
charge = typeof x === "function" ? x : +x; | |
return force; | |
}; | |
force.chargeDistance = function(x) { | |
if (!arguments.length) return Math.sqrt(chargeDistance2); | |
chargeDistance2 = x * x; | |
return force; | |
}; | |
force.gravity = function(x) { | |
if (!arguments.length) return gravity; | |
gravity = +x; | |
return force; | |
}; | |
force.theta = function(x) { | |
if (!arguments.length) return Math.sqrt(theta2); | |
theta2 = x * x; | |
return force; | |
}; | |
force.alpha = function(x) { | |
if (!arguments.length) return alpha; | |
x = +x; | |
if (alpha) { | |
if (x > 0) { | |
alpha = x; | |
} else { | |
timer.c = null, timer.t = NaN, timer = null; | |
event.end({ | |
type: "end", | |
alpha: alpha = 0 | |
}); | |
} | |
} else if (x > 0) { | |
event.start({ | |
type: "start", | |
alpha: alpha = x | |
}); | |
timer = d3_timer(force.tick); | |
} | |
return force; | |
}; | |
force.start = function() { | |
var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; | |
for (i = 0; i < n; ++i) { | |
(o = nodes[i]).index = i; | |
o.weight = 0; | |
} | |
for (i = 0; i < m; ++i) { | |
o = links[i]; | |
if (typeof o.source == "number") o.source = nodes[o.source]; | |
if (typeof o.target == "number") o.target = nodes[o.target]; | |
++o.source.weight; | |
++o.target.weight; | |
} | |
for (i = 0; i < n; ++i) { | |
o = nodes[i]; | |
if (isNaN(o.x)) o.x = position("x", w); | |
if (isNaN(o.y)) o.y = position("y", h); | |
if (isNaN(o.px)) o.px = o.x; | |
if (isNaN(o.py)) o.py = o.y; | |
} | |
distances = []; | |
if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; | |
strengths = []; | |
if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; | |
charges = []; | |
if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; | |
function position(dimension, size) { | |
if (!neighbors) { | |
neighbors = new Array(n); | |
for (j = 0; j < n; ++j) { | |
neighbors[j] = []; | |
} | |
for (j = 0; j < m; ++j) { | |
var o = links[j]; | |
neighbors[o.source.index].push(o.target); | |
neighbors[o.target.index].push(o.source); | |
} | |
} | |
var candidates = neighbors[i], j = -1, l = candidates.length, x; | |
while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; | |
return Math.random() * size; | |
} | |
return force.resume(); | |
}; | |
force.resume = function() { | |
return force.alpha(.1); | |
}; | |
force.stop = function() { | |
return force.alpha(0); | |
}; | |
force.drag = function() { | |
if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); | |
if (!arguments.length) return drag; | |
this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); | |
}; | |
function dragmove(d) { | |
d.px = d3.event.x, d.py = d3.event.y; | |
force.resume(); | |
} | |
return d3.rebind(force, event, "on"); | |
}; | |
function d3_layout_forceDragstart(d) { | |
d.fixed |= 2; | |
} | |
function d3_layout_forceDragend(d) { | |
d.fixed &= ~6; | |
} | |
function d3_layout_forceMouseover(d) { | |
d.fixed |= 4; | |
d.px = d.x, d.py = d.y; | |
} | |
function d3_layout_forceMouseout(d) { | |
d.fixed &= ~4; | |
} | |
function d3_layout_forceAccumulate(quad, alpha, charges) { | |
var cx = 0, cy = 0; | |
quad.charge = 0; | |
if (!quad.leaf) { | |
var nodes = quad.nodes, n = nodes.length, i = -1, c; | |
while (++i < n) { | |
c = nodes[i]; | |
if (c == null) continue; | |
d3_layout_forceAccumulate(c, alpha, charges); | |
quad.charge += c.charge; | |
cx += c.charge * c.cx; | |
cy += c.charge * c.cy; | |
} | |
} | |
if (quad.point) { | |
if (!quad.leaf) { | |
quad.point.x += Math.random() - .5; | |
quad.point.y += Math.random() - .5; | |
} | |
var k = alpha * charges[quad.point.index]; | |
quad.charge += quad.pointCharge = k; | |
cx += k * quad.point.x; | |
cy += k * quad.point.y; | |
} | |
quad.cx = cx / quad.charge; | |
quad.cy = cy / quad.charge; | |
} | |
var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; | |
d3.layout.hierarchy = function() { | |
var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; | |
function hierarchy(root) { | |
var stack = [ root ], nodes = [], node; | |
root.depth = 0; | |
while ((node = stack.pop()) != null) { | |
nodes.push(node); | |
if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { | |
var n, childs, child; | |
while (--n >= 0) { | |
stack.push(child = childs[n]); | |
child.parent = node; | |
child.depth = node.depth + 1; | |
} | |
if (value) node.value = 0; | |
node.children = childs; | |
} else { | |
if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; | |
delete node.children; | |
} | |
} | |
d3_layout_hierarchyVisitAfter(root, function(node) { | |
var childs, parent; | |
if (sort && (childs = node.children)) childs.sort(sort); | |
if (value && (parent = node.parent)) parent.value += node.value; | |
}); | |
return nodes; | |
} | |
hierarchy.sort = function(x) { | |
if (!arguments.length) return sort; | |
sort = x; | |
return hierarchy; | |
}; | |
hierarchy.children = function(x) { | |
if (!arguments.length) return children; | |
children = x; | |
return hierarchy; | |
}; | |
hierarchy.value = function(x) { | |
if (!arguments.length) return value; | |
value = x; | |
return hierarchy; | |
}; | |
hierarchy.revalue = function(root) { | |
if (value) { | |
d3_layout_hierarchyVisitBefore(root, function(node) { | |
if (node.children) node.value = 0; | |
}); | |
d3_layout_hierarchyVisitAfter(root, function(node) { | |
var parent; | |
if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; | |
if (parent = node.parent) parent.value += node.value; | |
}); | |
} | |
return root; | |
}; | |
return hierarchy; | |
}; | |
function d3_layout_hierarchyRebind(object, hierarchy) { | |
d3.rebind(object, hierarchy, "sort", "children", "value"); | |
object.nodes = object; | |
object.links = d3_layout_hierarchyLinks; | |
return object; | |
} | |
function d3_layout_hierarchyVisitBefore(node, callback) { | |
var nodes = [ node ]; | |
while ((node = nodes.pop()) != null) { | |
callback(node); | |
if ((children = node.children) && (n = children.length)) { | |
var n, children; | |
while (--n >= 0) nodes.push(children[n]); | |
} | |
} | |
} | |
function d3_layout_hierarchyVisitAfter(node, callback) { | |
var nodes = [ node ], nodes2 = []; | |
while ((node = nodes.pop()) != null) { | |
nodes2.push(node); | |
if ((children = node.children) && (n = children.length)) { | |
var i = -1, n, children; | |
while (++i < n) nodes.push(children[i]); | |
} | |
} | |
while ((node = nodes2.pop()) != null) { | |
callback(node); | |
} | |
} | |
function d3_layout_hierarchyChildren(d) { | |
return d.children; | |
} | |
function d3_layout_hierarchyValue(d) { | |
return d.value; | |
} | |
function d3_layout_hierarchySort(a, b) { | |
return b.value - a.value; | |
} | |
function d3_layout_hierarchyLinks(nodes) { | |
return d3.merge(nodes.map(function(parent) { | |
return (parent.children || []).map(function(child) { | |
return { | |
source: parent, | |
target: child | |
}; | |
}); | |
})); | |
} | |
d3.layout.partition = function() { | |
var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; | |
function position(node, x, dx, dy) { | |
var children = node.children; | |
node.x = x; | |
node.y = node.depth * dy; | |
node.dx = dx; | |
node.dy = dy; | |
if (children && (n = children.length)) { | |
var i = -1, n, c, d; | |
dx = node.value ? dx / node.value : 0; | |
while (++i < n) { | |
position(c = children[i], x, d = c.value * dx, dy); | |
x += d; | |
} | |
} | |
} | |
function depth(node) { | |
var children = node.children, d = 0; | |
if (children && (n = children.length)) { | |
var i = -1, n; | |
while (++i < n) d = Math.max(d, depth(children[i])); | |
} | |
return 1 + d; | |
} | |
function partition(d, i) { | |
var nodes = hierarchy.call(this, d, i); | |
position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); | |
return nodes; | |
} | |
partition.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return partition; | |
}; | |
return d3_layout_hierarchyRebind(partition, hierarchy); | |
}; | |
d3.layout.pie = function() { | |
var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; | |
function pie(data) { | |
var n = data.length, values = data.map(function(d, i) { | |
return +value.call(pie, d, i); | |
}), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; | |
if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { | |
return values[j] - values[i]; | |
} : function(i, j) { | |
return sort(data[i], data[j]); | |
}); | |
index.forEach(function(i) { | |
arcs[i] = { | |
data: data[i], | |
value: v = values[i], | |
startAngle: a, | |
endAngle: a += v * k + pa, | |
padAngle: p | |
}; | |
}); | |
return arcs; | |
} | |
pie.value = function(_) { | |
if (!arguments.length) return value; | |
value = _; | |
return pie; | |
}; | |
pie.sort = function(_) { | |
if (!arguments.length) return sort; | |
sort = _; | |
return pie; | |
}; | |
pie.startAngle = function(_) { | |
if (!arguments.length) return startAngle; | |
startAngle = _; | |
return pie; | |
}; | |
pie.endAngle = function(_) { | |
if (!arguments.length) return endAngle; | |
endAngle = _; | |
return pie; | |
}; | |
pie.padAngle = function(_) { | |
if (!arguments.length) return padAngle; | |
padAngle = _; | |
return pie; | |
}; | |
return pie; | |
}; | |
var d3_layout_pieSortByValue = {}; | |
d3.layout.stack = function() { | |
var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; | |
function stack(data, index) { | |
if (!(n = data.length)) return data; | |
var series = data.map(function(d, i) { | |
return values.call(stack, d, i); | |
}); | |
var points = series.map(function(d) { | |
return d.map(function(v, i) { | |
return [ x.call(stack, v, i), y.call(stack, v, i) ]; | |
}); | |
}); | |
var orders = order.call(stack, points, index); | |
series = d3.permute(series, orders); | |
points = d3.permute(points, orders); | |
var offsets = offset.call(stack, points, index); | |
var m = series[0].length, n, i, j, o; | |
for (j = 0; j < m; ++j) { | |
out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); | |
for (i = 1; i < n; ++i) { | |
out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); | |
} | |
} | |
return data; | |
} | |
stack.values = function(x) { | |
if (!arguments.length) return values; | |
values = x; | |
return stack; | |
}; | |
stack.order = function(x) { | |
if (!arguments.length) return order; | |
order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; | |
return stack; | |
}; | |
stack.offset = function(x) { | |
if (!arguments.length) return offset; | |
offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; | |
return stack; | |
}; | |
stack.x = function(z) { | |
if (!arguments.length) return x; | |
x = z; | |
return stack; | |
}; | |
stack.y = function(z) { | |
if (!arguments.length) return y; | |
y = z; | |
return stack; | |
}; | |
stack.out = function(z) { | |
if (!arguments.length) return out; | |
out = z; | |
return stack; | |
}; | |
return stack; | |
}; | |
function d3_layout_stackX(d) { | |
return d.x; | |
} | |
function d3_layout_stackY(d) { | |
return d.y; | |
} | |
function d3_layout_stackOut(d, y0, y) { | |
d.y0 = y0; | |
d.y = y; | |
} | |
var d3_layout_stackOrders = d3.map({ | |
"inside-out": function(data) { | |
var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { | |
return max[a] - max[b]; | |
}), top = 0, bottom = 0, tops = [], bottoms = []; | |
for (i = 0; i < n; ++i) { | |
j = index[i]; | |
if (top < bottom) { | |
top += sums[j]; | |
tops.push(j); | |
} else { | |
bottom += sums[j]; | |
bottoms.push(j); | |
} | |
} | |
return bottoms.reverse().concat(tops); | |
}, | |
reverse: function(data) { | |
return d3.range(data.length).reverse(); | |
}, | |
"default": d3_layout_stackOrderDefault | |
}); | |
var d3_layout_stackOffsets = d3.map({ | |
silhouette: function(data) { | |
var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; | |
for (j = 0; j < m; ++j) { | |
for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; | |
if (o > max) max = o; | |
sums.push(o); | |
} | |
for (j = 0; j < m; ++j) { | |
y0[j] = (max - sums[j]) / 2; | |
} | |
return y0; | |
}, | |
wiggle: function(data) { | |
var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; | |
y0[0] = o = o0 = 0; | |
for (j = 1; j < m; ++j) { | |
for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; | |
for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { | |
for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { | |
s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; | |
} | |
s2 += s3 * data[i][j][1]; | |
} | |
y0[j] = o -= s1 ? s2 / s1 * dx : 0; | |
if (o < o0) o0 = o; | |
} | |
for (j = 0; j < m; ++j) y0[j] -= o0; | |
return y0; | |
}, | |
expand: function(data) { | |
var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; | |
for (j = 0; j < m; ++j) { | |
for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; | |
if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; | |
} | |
for (j = 0; j < m; ++j) y0[j] = 0; | |
return y0; | |
}, | |
zero: d3_layout_stackOffsetZero | |
}); | |
function d3_layout_stackOrderDefault(data) { | |
return d3.range(data.length); | |
} | |
function d3_layout_stackOffsetZero(data) { | |
var j = -1, m = data[0].length, y0 = []; | |
while (++j < m) y0[j] = 0; | |
return y0; | |
} | |
function d3_layout_stackMaxIndex(array) { | |
var i = 1, j = 0, v = array[0][1], k, n = array.length; | |
for (;i < n; ++i) { | |
if ((k = array[i][1]) > v) { | |
j = i; | |
v = k; | |
} | |
} | |
return j; | |
} | |
function d3_layout_stackReduceSum(d) { | |
return d.reduce(d3_layout_stackSum, 0); | |
} | |
function d3_layout_stackSum(p, d) { | |
return p + d[1]; | |
} | |
d3.layout.histogram = function() { | |
var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; | |
function histogram(data, i) { | |
var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; | |
while (++i < m) { | |
bin = bins[i] = []; | |
bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); | |
bin.y = 0; | |
} | |
if (m > 0) { | |
i = -1; | |
while (++i < n) { | |
x = values[i]; | |
if (x >= range[0] && x <= range[1]) { | |
bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; | |
bin.y += k; | |
bin.push(data[i]); | |
} | |
} | |
} | |
return bins; | |
} | |
histogram.value = function(x) { | |
if (!arguments.length) return valuer; | |
valuer = x; | |
return histogram; | |
}; | |
histogram.range = function(x) { | |
if (!arguments.length) return ranger; | |
ranger = d3_functor(x); | |
return histogram; | |
}; | |
histogram.bins = function(x) { | |
if (!arguments.length) return binner; | |
binner = typeof x === "number" ? function(range) { | |
return d3_layout_histogramBinFixed(range, x); | |
} : d3_functor(x); | |
return histogram; | |
}; | |
histogram.frequency = function(x) { | |
if (!arguments.length) return frequency; | |
frequency = !!x; | |
return histogram; | |
}; | |
return histogram; | |
}; | |
function d3_layout_histogramBinSturges(range, values) { | |
return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); | |
} | |
function d3_layout_histogramBinFixed(range, n) { | |
var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; | |
while (++x <= n) f[x] = m * x + b; | |
return f; | |
} | |
function d3_layout_histogramRange(values) { | |
return [ d3.min(values), d3.max(values) ]; | |
} | |
d3.layout.pack = function() { | |
var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; | |
function pack(d, i) { | |
var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { | |
return radius; | |
}; | |
root.x = root.y = 0; | |
d3_layout_hierarchyVisitAfter(root, function(d) { | |
d.r = +r(d.value); | |
}); | |
d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); | |
if (padding) { | |
var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; | |
d3_layout_hierarchyVisitAfter(root, function(d) { | |
d.r += dr; | |
}); | |
d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); | |
d3_layout_hierarchyVisitAfter(root, function(d) { | |
d.r -= dr; | |
}); | |
} | |
d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); | |
return nodes; | |
} | |
pack.size = function(_) { | |
if (!arguments.length) return size; | |
size = _; | |
return pack; | |
}; | |
pack.radius = function(_) { | |
if (!arguments.length) return radius; | |
radius = _ == null || typeof _ === "function" ? _ : +_; | |
return pack; | |
}; | |
pack.padding = function(_) { | |
if (!arguments.length) return padding; | |
padding = +_; | |
return pack; | |
}; | |
return d3_layout_hierarchyRebind(pack, hierarchy); | |
}; | |
function d3_layout_packSort(a, b) { | |
return a.value - b.value; | |
} | |
function d3_layout_packInsert(a, b) { | |
var c = a._pack_next; | |
a._pack_next = b; | |
b._pack_prev = a; | |
b._pack_next = c; | |
c._pack_prev = b; | |
} | |
function d3_layout_packSplice(a, b) { | |
a._pack_next = b; | |
b._pack_prev = a; | |
} | |
function d3_layout_packIntersects(a, b) { | |
var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; | |
return .999 * dr * dr > dx * dx + dy * dy; | |
} | |
function d3_layout_packSiblings(node) { | |
if (!(nodes = node.children) || !(n = nodes.length)) return; | |
var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; | |
function bound(node) { | |
xMin = Math.min(node.x - node.r, xMin); | |
xMax = Math.max(node.x + node.r, xMax); | |
yMin = Math.min(node.y - node.r, yMin); | |
yMax = Math.max(node.y + node.r, yMax); | |
} | |
nodes.forEach(d3_layout_packLink); | |
a = nodes[0]; | |
a.x = -a.r; | |
a.y = 0; | |
bound(a); | |
if (n > 1) { | |
b = nodes[1]; | |
b.x = b.r; | |
b.y = 0; | |
bound(b); | |
if (n > 2) { | |
c = nodes[2]; | |
d3_layout_packPlace(a, b, c); | |
bound(c); | |
d3_layout_packInsert(a, c); | |
a._pack_prev = c; | |
d3_layout_packInsert(c, b); | |
b = a._pack_next; | |
for (i = 3; i < n; i++) { | |
d3_layout_packPlace(a, b, c = nodes[i]); | |
var isect = 0, s1 = 1, s2 = 1; | |
for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { | |
if (d3_layout_packIntersects(j, c)) { | |
isect = 1; | |
break; | |
} | |
} | |
if (isect == 1) { | |
for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { | |
if (d3_layout_packIntersects(k, c)) { | |
break; | |
} | |
} | |
} | |
if (isect) { | |
if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); | |
i--; | |
} else { | |
d3_layout_packInsert(a, c); | |
b = c; | |
bound(c); | |
} | |
} | |
} | |
} | |
var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; | |
for (i = 0; i < n; i++) { | |
c = nodes[i]; | |
c.x -= cx; | |
c.y -= cy; | |
cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); | |
} | |
node.r = cr; | |
nodes.forEach(d3_layout_packUnlink); | |
} | |
function d3_layout_packLink(node) { | |
node._pack_next = node._pack_prev = node; | |
} | |
function d3_layout_packUnlink(node) { | |
delete node._pack_next; | |
delete node._pack_prev; | |
} | |
function d3_layout_packTransform(node, x, y, k) { | |
var children = node.children; | |
node.x = x += k * node.x; | |
node.y = y += k * node.y; | |
node.r *= k; | |
if (children) { | |
var i = -1, n = children.length; | |
while (++i < n) d3_layout_packTransform(children[i], x, y, k); | |
} | |
} | |
function d3_layout_packPlace(a, b, c) { | |
var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; | |
if (db && (dx || dy)) { | |
var da = b.r + c.r, dc = dx * dx + dy * dy; | |
da *= da; | |
db *= db; | |
var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); | |
c.x = a.x + x * dx + y * dy; | |
c.y = a.y + x * dy - y * dx; | |
} else { | |
c.x = a.x + db; | |
c.y = a.y; | |
} | |
} | |
d3.layout.tree = function() { | |
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; | |
function tree(d, i) { | |
var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); | |
d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; | |
d3_layout_hierarchyVisitBefore(root1, secondWalk); | |
if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { | |
var left = root0, right = root0, bottom = root0; | |
d3_layout_hierarchyVisitBefore(root0, function(node) { | |
if (node.x < left.x) left = node; | |
if (node.x > right.x) right = node; | |
if (node.depth > bottom.depth) bottom = node; | |
}); | |
var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); | |
d3_layout_hierarchyVisitBefore(root0, function(node) { | |
node.x = (node.x + tx) * kx; | |
node.y = node.depth * ky; | |
}); | |
} | |
return nodes; | |
} | |
function wrapTree(root0) { | |
var root1 = { | |
A: null, | |
children: [ root0 ] | |
}, queue = [ root1 ], node1; | |
while ((node1 = queue.pop()) != null) { | |
for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { | |
queue.push((children[i] = child = { | |
_: children[i], | |
parent: node1, | |
children: (child = children[i].children) && child.slice() || [], | |
A: null, | |
a: null, | |
z: 0, | |
m: 0, | |
c: 0, | |
s: 0, | |
t: null, | |
i: i | |
}).a = child); | |
} | |
} | |
return root1.children[0]; | |
} | |
function firstWalk(v) { | |
var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; | |
if (children.length) { | |
d3_layout_treeShift(v); | |
var midpoint = (children[0].z + children[children.length - 1].z) / 2; | |
if (w) { | |
v.z = w.z + separation(v._, w._); | |
v.m = v.z - midpoint; | |
} else { | |
v.z = midpoint; | |
} | |
} else if (w) { | |
v.z = w.z + separation(v._, w._); | |
} | |
v.parent.A = apportion(v, w, v.parent.A || siblings[0]); | |
} | |
function secondWalk(v) { | |
v._.x = v.z + v.parent.m; | |
v.m += v.parent.m; | |
} | |
function apportion(v, w, ancestor) { | |
if (w) { | |
var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; | |
while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { | |
vom = d3_layout_treeLeft(vom); | |
vop = d3_layout_treeRight(vop); | |
vop.a = v; | |
shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); | |
if (shift > 0) { | |
d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); | |
sip += shift; | |
sop += shift; | |
} | |
sim += vim.m; | |
sip += vip.m; | |
som += vom.m; | |
sop += vop.m; | |
} | |
if (vim && !d3_layout_treeRight(vop)) { | |
vop.t = vim; | |
vop.m += sim - sop; | |
} | |
if (vip && !d3_layout_treeLeft(vom)) { | |
vom.t = vip; | |
vom.m += sip - som; | |
ancestor = v; | |
} | |
} | |
return ancestor; | |
} | |
function sizeNode(node) { | |
node.x *= size[0]; | |
node.y = node.depth * size[1]; | |
} | |
tree.separation = function(x) { | |
if (!arguments.length) return separation; | |
separation = x; | |
return tree; | |
}; | |
tree.size = function(x) { | |
if (!arguments.length) return nodeSize ? null : size; | |
nodeSize = (size = x) == null ? sizeNode : null; | |
return tree; | |
}; | |
tree.nodeSize = function(x) { | |
if (!arguments.length) return nodeSize ? size : null; | |
nodeSize = (size = x) == null ? null : sizeNode; | |
return tree; | |
}; | |
return d3_layout_hierarchyRebind(tree, hierarchy); | |
}; | |
function d3_layout_treeSeparation(a, b) { | |
return a.parent == b.parent ? 1 : 2; | |
} | |
function d3_layout_treeLeft(v) { | |
var children = v.children; | |
return children.length ? children[0] : v.t; | |
} | |
function d3_layout_treeRight(v) { | |
var children = v.children, n; | |
return (n = children.length) ? children[n - 1] : v.t; | |
} | |
function d3_layout_treeMove(wm, wp, shift) { | |
var change = shift / (wp.i - wm.i); | |
wp.c -= change; | |
wp.s += shift; | |
wm.c += change; | |
wp.z += shift; | |
wp.m += shift; | |
} | |
function d3_layout_treeShift(v) { | |
var shift = 0, change = 0, children = v.children, i = children.length, w; | |
while (--i >= 0) { | |
w = children[i]; | |
w.z += shift; | |
w.m += shift; | |
shift += w.s + (change += w.c); | |
} | |
} | |
function d3_layout_treeAncestor(vim, v, ancestor) { | |
return vim.a.parent === v.parent ? vim.a : ancestor; | |
} | |
d3.layout.cluster = function() { | |
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; | |
function cluster(d, i) { | |
var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; | |
d3_layout_hierarchyVisitAfter(root, function(node) { | |
var children = node.children; | |
if (children && children.length) { | |
node.x = d3_layout_clusterX(children); | |
node.y = d3_layout_clusterY(children); | |
} else { | |
node.x = previousNode ? x += separation(node, previousNode) : 0; | |
node.y = 0; | |
previousNode = node; | |
} | |
}); | |
var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; | |
d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { | |
node.x = (node.x - root.x) * size[0]; | |
node.y = (root.y - node.y) * size[1]; | |
} : function(node) { | |
node.x = (node.x - x0) / (x1 - x0) * size[0]; | |
node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; | |
}); | |
return nodes; | |
} | |
cluster.separation = function(x) { | |
if (!arguments.length) return separation; | |
separation = x; | |
return cluster; | |
}; | |
cluster.size = function(x) { | |
if (!arguments.length) return nodeSize ? null : size; | |
nodeSize = (size = x) == null; | |
return cluster; | |
}; | |
cluster.nodeSize = function(x) { | |
if (!arguments.length) return nodeSize ? size : null; | |
nodeSize = (size = x) != null; | |
return cluster; | |
}; | |
return d3_layout_hierarchyRebind(cluster, hierarchy); | |
}; | |
function d3_layout_clusterY(children) { | |
return 1 + d3.max(children, function(child) { | |
return child.y; | |
}); | |
} | |
function d3_layout_clusterX(children) { | |
return children.reduce(function(x, child) { | |
return x + child.x; | |
}, 0) / children.length; | |
} | |
function d3_layout_clusterLeft(node) { | |
var children = node.children; | |
return children && children.length ? d3_layout_clusterLeft(children[0]) : node; | |
} | |
function d3_layout_clusterRight(node) { | |
var children = node.children, n; | |
return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; | |
} | |
d3.layout.treemap = function() { | |
var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); | |
function scale(children, k) { | |
var i = -1, n = children.length, child, area; | |
while (++i < n) { | |
area = (child = children[i]).value * (k < 0 ? 0 : k); | |
child.area = isNaN(area) || area <= 0 ? 0 : area; | |
} | |
} | |
function squarify(node) { | |
var children = node.children; | |
if (children && children.length) { | |
var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; | |
scale(remaining, rect.dx * rect.dy / node.value); | |
row.area = 0; | |
while ((n = remaining.length) > 0) { | |
row.push(child = remaining[n - 1]); | |
row.area += child.area; | |
if (mode !== "squarify" || (score = worst(row, u)) <= best) { | |
remaining.pop(); | |
best = score; | |
} else { | |
row.area -= row.pop().area; | |
position(row, u, rect, false); | |
u = Math.min(rect.dx, rect.dy); | |
row.length = row.area = 0; | |
best = Infinity; | |
} | |
} | |
if (row.length) { | |
position(row, u, rect, true); | |
row.length = row.area = 0; | |
} | |
children.forEach(squarify); | |
} | |
} | |
function stickify(node) { | |
var children = node.children; | |
if (children && children.length) { | |
var rect = pad(node), remaining = children.slice(), child, row = []; | |
scale(remaining, rect.dx * rect.dy / node.value); | |
row.area = 0; | |
while (child = remaining.pop()) { | |
row.push(child); | |
row.area += child.area; | |
if (child.z != null) { | |
position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); | |
row.length = row.area = 0; | |
} | |
} | |
children.forEach(stickify); | |
} | |
} | |
function worst(row, u) { | |
var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; | |
while (++i < n) { | |
if (!(r = row[i].area)) continue; | |
if (r < rmin) rmin = r; | |
if (r > rmax) rmax = r; | |
} | |
s *= s; | |
u *= u; | |
return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; | |
} | |
function position(row, u, rect, flush) { | |
var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; | |
if (u == rect.dx) { | |
if (flush || v > rect.dy) v = rect.dy; | |
while (++i < n) { | |
o = row[i]; | |
o.x = x; | |
o.y = y; | |
o.dy = v; | |
x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); | |
} | |
o.z = true; | |
o.dx += rect.x + rect.dx - x; | |
rect.y += v; | |
rect.dy -= v; | |
} else { | |
if (flush || v > rect.dx) v = rect.dx; | |
while (++i < n) { | |
o = row[i]; | |
o.x = x; | |
o.y = y; | |
o.dx = v; | |
y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); | |
} | |
o.z = false; | |
o.dy += rect.y + rect.dy - y; | |
rect.x += v; | |
rect.dx -= v; | |
} | |
} | |
function treemap(d) { | |
var nodes = stickies || hierarchy(d), root = nodes[0]; | |
root.x = root.y = 0; | |
if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; | |
if (stickies) hierarchy.revalue(root); | |
scale([ root ], root.dx * root.dy / root.value); | |
(stickies ? stickify : squarify)(root); | |
if (sticky) stickies = nodes; | |
return nodes; | |
} | |
treemap.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return treemap; | |
}; | |
treemap.padding = function(x) { | |
if (!arguments.length) return padding; | |
function padFunction(node) { | |
var p = x.call(treemap, node, node.depth); | |
return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); | |
} | |
function padConstant(node) { | |
return d3_layout_treemapPad(node, x); | |
} | |
var type; | |
pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], | |
padConstant) : padConstant; | |
return treemap; | |
}; | |
treemap.round = function(x) { | |
if (!arguments.length) return round != Number; | |
round = x ? Math.round : Number; | |
return treemap; | |
}; | |
treemap.sticky = function(x) { | |
if (!arguments.length) return sticky; | |
sticky = x; | |
stickies = null; | |
return treemap; | |
}; | |
treemap.ratio = function(x) { | |
if (!arguments.length) return ratio; | |
ratio = x; | |
return treemap; | |
}; | |
treemap.mode = function(x) { | |
if (!arguments.length) return mode; | |
mode = x + ""; | |
return treemap; | |
}; | |
return d3_layout_hierarchyRebind(treemap, hierarchy); | |
}; | |
function d3_layout_treemapPadNull(node) { | |
return { | |
x: node.x, | |
y: node.y, | |
dx: node.dx, | |
dy: node.dy | |
}; | |
} | |
function d3_layout_treemapPad(node, padding) { | |
var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; | |
if (dx < 0) { | |
x += dx / 2; | |
dx = 0; | |
} | |
if (dy < 0) { | |
y += dy / 2; | |
dy = 0; | |
} | |
return { | |
x: x, | |
y: y, | |
dx: dx, | |
dy: dy | |
}; | |
} | |
d3.random = { | |
normal: function(µ, σ) { | |
var n = arguments.length; | |
if (n < 2) σ = 1; | |
if (n < 1) µ = 0; | |
return function() { | |
var x, y, r; | |
do { | |
x = Math.random() * 2 - 1; | |
y = Math.random() * 2 - 1; | |
r = x * x + y * y; | |
} while (!r || r > 1); | |
return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); | |
}; | |
}, | |
logNormal: function() { | |
var random = d3.random.normal.apply(d3, arguments); | |
return function() { | |
return Math.exp(random()); | |
}; | |
}, | |
bates: function(m) { | |
var random = d3.random.irwinHall(m); | |
return function() { | |
return random() / m; | |
}; | |
}, | |
irwinHall: function(m) { | |
return function() { | |
for (var s = 0, j = 0; j < m; j++) s += Math.random(); | |
return s; | |
}; | |
} | |
}; | |
d3.scale = {}; | |
function d3_scaleExtent(domain) { | |
var start = domain[0], stop = domain[domain.length - 1]; | |
return start < stop ? [ start, stop ] : [ stop, start ]; | |
} | |
function d3_scaleRange(scale) { | |
return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); | |
} | |
function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { | |
var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); | |
return function(x) { | |
return i(u(x)); | |
}; | |
} | |
function d3_scale_nice(domain, nice) { | |
var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; | |
if (x1 < x0) { | |
dx = i0, i0 = i1, i1 = dx; | |
dx = x0, x0 = x1, x1 = dx; | |
} | |
domain[i0] = nice.floor(x0); | |
domain[i1] = nice.ceil(x1); | |
return domain; | |
} | |
function d3_scale_niceStep(step) { | |
return step ? { | |
floor: function(x) { | |
return Math.floor(x / step) * step; | |
}, | |
ceil: function(x) { | |
return Math.ceil(x / step) * step; | |
} | |
} : d3_scale_niceIdentity; | |
} | |
var d3_scale_niceIdentity = { | |
floor: d3_identity, | |
ceil: d3_identity | |
}; | |
function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { | |
var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; | |
if (domain[k] < domain[0]) { | |
domain = domain.slice().reverse(); | |
range = range.slice().reverse(); | |
} | |
while (++j <= k) { | |
u.push(uninterpolate(domain[j - 1], domain[j])); | |
i.push(interpolate(range[j - 1], range[j])); | |
} | |
return function(x) { | |
var j = d3.bisect(domain, x, 1, k) - 1; | |
return i[j](u[j](x)); | |
}; | |
} | |
d3.scale.linear = function() { | |
return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); | |
}; | |
function d3_scale_linear(domain, range, interpolate, clamp) { | |
var output, input; | |
function rescale() { | |
var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; | |
output = linear(domain, range, uninterpolate, interpolate); | |
input = linear(range, domain, uninterpolate, d3_interpolate); | |
return scale; | |
} | |
function scale(x) { | |
return output(x); | |
} | |
scale.invert = function(y) { | |
return input(y); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.map(Number); | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.rangeRound = function(x) { | |
return scale.range(x).interpolate(d3_interpolateRound); | |
}; | |
scale.clamp = function(x) { | |
if (!arguments.length) return clamp; | |
clamp = x; | |
return rescale(); | |
}; | |
scale.interpolate = function(x) { | |
if (!arguments.length) return interpolate; | |
interpolate = x; | |
return rescale(); | |
}; | |
scale.ticks = function(m) { | |
return d3_scale_linearTicks(domain, m); | |
}; | |
scale.tickFormat = function(m, format) { | |
return d3_scale_linearTickFormat(domain, m, format); | |
}; | |
scale.nice = function(m) { | |
d3_scale_linearNice(domain, m); | |
return rescale(); | |
}; | |
scale.copy = function() { | |
return d3_scale_linear(domain, range, interpolate, clamp); | |
}; | |
return rescale(); | |
} | |
function d3_scale_linearRebind(scale, linear) { | |
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); | |
} | |
function d3_scale_linearNice(domain, m) { | |
d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); | |
d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); | |
return domain; | |
} | |
function d3_scale_linearTickRange(domain, m) { | |
if (m == null) m = 10; | |
var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; | |
if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; | |
extent[0] = Math.ceil(extent[0] / step) * step; | |
extent[1] = Math.floor(extent[1] / step) * step + step * .5; | |
extent[2] = step; | |
return extent; | |
} | |
function d3_scale_linearTicks(domain, m) { | |
return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); | |
} | |
function d3_scale_linearTickFormat(domain, m, format) { | |
var range = d3_scale_linearTickRange(domain, m); | |
if (format) { | |
var match = d3_format_re.exec(format); | |
match.shift(); | |
if (match[8] === "s") { | |
var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); | |
if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); | |
match[8] = "f"; | |
format = d3.format(match.join("")); | |
return function(d) { | |
return format(prefix.scale(d)) + prefix.symbol; | |
}; | |
} | |
if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); | |
format = match.join(""); | |
} else { | |
format = ",." + d3_scale_linearPrecision(range[2]) + "f"; | |
} | |
return d3.format(format); | |
} | |
var d3_scale_linearFormatSignificant = { | |
s: 1, | |
g: 1, | |
p: 1, | |
r: 1, | |
e: 1 | |
}; | |
function d3_scale_linearPrecision(value) { | |
return -Math.floor(Math.log(value) / Math.LN10 + .01); | |
} | |
function d3_scale_linearFormatPrecision(type, range) { | |
var p = d3_scale_linearPrecision(range[2]); | |
return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; | |
} | |
d3.scale.log = function() { | |
return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); | |
}; | |
function d3_scale_log(linear, base, positive, domain) { | |
function log(x) { | |
return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); | |
} | |
function pow(x) { | |
return positive ? Math.pow(base, x) : -Math.pow(base, -x); | |
} | |
function scale(x) { | |
return linear(log(x)); | |
} | |
scale.invert = function(x) { | |
return pow(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
positive = x[0] >= 0; | |
linear.domain((domain = x.map(Number)).map(log)); | |
return scale; | |
}; | |
scale.base = function(_) { | |
if (!arguments.length) return base; | |
base = +_; | |
linear.domain(domain.map(log)); | |
return scale; | |
}; | |
scale.nice = function() { | |
var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); | |
linear.domain(niced); | |
domain = niced.map(pow); | |
return scale; | |
}; | |
scale.ticks = function() { | |
var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; | |
if (isFinite(j - i)) { | |
if (positive) { | |
for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); | |
ticks.push(pow(i)); | |
} else { | |
ticks.push(pow(i)); | |
for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); | |
} | |
for (i = 0; ticks[i] < u; i++) {} | |
for (j = ticks.length; ticks[j - 1] > v; j--) {} | |
ticks = ticks.slice(i, j); | |
} | |
return ticks; | |
}; | |
scale.tickFormat = function(n, format) { | |
if (!arguments.length) return d3_scale_logFormat; | |
if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); | |
var k = Math.max(1, base * n / scale.ticks().length); | |
return function(d) { | |
var i = d / pow(Math.round(log(d))); | |
if (i * base < base - .5) i *= base; | |
return i <= k ? format(d) : ""; | |
}; | |
}; | |
scale.copy = function() { | |
return d3_scale_log(linear.copy(), base, positive, domain); | |
}; | |
return d3_scale_linearRebind(scale, linear); | |
} | |
var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { | |
floor: function(x) { | |
return -Math.ceil(-x); | |
}, | |
ceil: function(x) { | |
return -Math.floor(-x); | |
} | |
}; | |
d3.scale.pow = function() { | |
return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); | |
}; | |
function d3_scale_pow(linear, exponent, domain) { | |
var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); | |
function scale(x) { | |
return linear(powp(x)); | |
} | |
scale.invert = function(x) { | |
return powb(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
linear.domain((domain = x.map(Number)).map(powp)); | |
return scale; | |
}; | |
scale.ticks = function(m) { | |
return d3_scale_linearTicks(domain, m); | |
}; | |
scale.tickFormat = function(m, format) { | |
return d3_scale_linearTickFormat(domain, m, format); | |
}; | |
scale.nice = function(m) { | |
return scale.domain(d3_scale_linearNice(domain, m)); | |
}; | |
scale.exponent = function(x) { | |
if (!arguments.length) return exponent; | |
powp = d3_scale_powPow(exponent = x); | |
powb = d3_scale_powPow(1 / exponent); | |
linear.domain(domain.map(powp)); | |
return scale; | |
}; | |
scale.copy = function() { | |
return d3_scale_pow(linear.copy(), exponent, domain); | |
}; | |
return d3_scale_linearRebind(scale, linear); | |
} | |
function d3_scale_powPow(e) { | |
return function(x) { | |
return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); | |
}; | |
} | |
d3.scale.sqrt = function() { | |
return d3.scale.pow().exponent(.5); | |
}; | |
d3.scale.ordinal = function() { | |
return d3_scale_ordinal([], { | |
t: "range", | |
a: [ [] ] | |
}); | |
}; | |
function d3_scale_ordinal(domain, ranger) { | |
var index, range, rangeBand; | |
function scale(x) { | |
return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; | |
} | |
function steps(start, step) { | |
return d3.range(domain.length).map(function(i) { | |
return start + step * i; | |
}); | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = []; | |
index = new d3_Map(); | |
var i = -1, n = x.length, xi; | |
while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); | |
return scale[ranger.t].apply(scale, ranger.a); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
rangeBand = 0; | |
ranger = { | |
t: "range", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangePoints = function(x, padding) { | |
if (arguments.length < 2) padding = 0; | |
var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, | |
0) : (stop - start) / (domain.length - 1 + padding); | |
range = steps(start + step * padding / 2, step); | |
rangeBand = 0; | |
ranger = { | |
t: "rangePoints", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeRoundPoints = function(x, padding) { | |
if (arguments.length < 2) padding = 0; | |
var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), | |
0) : (stop - start) / (domain.length - 1 + padding) | 0; | |
range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); | |
rangeBand = 0; | |
ranger = { | |
t: "rangeRoundPoints", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeBands = function(x, padding, outerPadding) { | |
if (arguments.length < 2) padding = 0; | |
if (arguments.length < 3) outerPadding = padding; | |
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); | |
range = steps(start + step * outerPadding, step); | |
if (reverse) range.reverse(); | |
rangeBand = step * (1 - padding); | |
ranger = { | |
t: "rangeBands", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeRoundBands = function(x, padding, outerPadding) { | |
if (arguments.length < 2) padding = 0; | |
if (arguments.length < 3) outerPadding = padding; | |
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); | |
range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); | |
if (reverse) range.reverse(); | |
rangeBand = Math.round(step * (1 - padding)); | |
ranger = { | |
t: "rangeRoundBands", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeBand = function() { | |
return rangeBand; | |
}; | |
scale.rangeExtent = function() { | |
return d3_scaleExtent(ranger.a[0]); | |
}; | |
scale.copy = function() { | |
return d3_scale_ordinal(domain, ranger); | |
}; | |
return scale.domain(domain); | |
} | |
d3.scale.category10 = function() { | |
return d3.scale.ordinal().range(d3_category10); | |
}; | |
d3.scale.category20 = function() { | |
return d3.scale.ordinal().range(d3_category20); | |
}; | |
d3.scale.category20b = function() { | |
return d3.scale.ordinal().range(d3_category20b); | |
}; | |
d3.scale.category20c = function() { | |
return d3.scale.ordinal().range(d3_category20c); | |
}; | |
var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); | |
var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); | |
var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); | |
var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); | |
d3.scale.quantile = function() { | |
return d3_scale_quantile([], []); | |
}; | |
function d3_scale_quantile(domain, range) { | |
var thresholds; | |
function rescale() { | |
var k = 0, q = range.length; | |
thresholds = []; | |
while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); | |
return scale; | |
} | |
function scale(x) { | |
if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.quantiles = function() { | |
return thresholds; | |
}; | |
scale.invertExtent = function(y) { | |
y = range.indexOf(y); | |
return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; | |
}; | |
scale.copy = function() { | |
return d3_scale_quantile(domain, range); | |
}; | |
return rescale(); | |
} | |
d3.scale.quantize = function() { | |
return d3_scale_quantize(0, 1, [ 0, 1 ]); | |
}; | |
function d3_scale_quantize(x0, x1, range) { | |
var kx, i; | |
function scale(x) { | |
return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; | |
} | |
function rescale() { | |
kx = range.length / (x1 - x0); | |
i = range.length - 1; | |
return scale; | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return [ x0, x1 ]; | |
x0 = +x[0]; | |
x1 = +x[x.length - 1]; | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.invertExtent = function(y) { | |
y = range.indexOf(y); | |
y = y < 0 ? NaN : y / kx + x0; | |
return [ y, y + 1 / kx ]; | |
}; | |
scale.copy = function() { | |
return d3_scale_quantize(x0, x1, range); | |
}; | |
return rescale(); | |
} | |
d3.scale.threshold = function() { | |
return d3_scale_threshold([ .5 ], [ 0, 1 ]); | |
}; | |
function d3_scale_threshold(domain, range) { | |
function scale(x) { | |
if (x <= x) return range[d3.bisect(domain, x)]; | |
} | |
scale.domain = function(_) { | |
if (!arguments.length) return domain; | |
domain = _; | |
return scale; | |
}; | |
scale.range = function(_) { | |
if (!arguments.length) return range; | |
range = _; | |
return scale; | |
}; | |
scale.invertExtent = function(y) { | |
y = range.indexOf(y); | |
return [ domain[y - 1], domain[y] ]; | |
}; | |
scale.copy = function() { | |
return d3_scale_threshold(domain, range); | |
}; | |
return scale; | |
} | |
d3.scale.identity = function() { | |
return d3_scale_identity([ 0, 1 ]); | |
}; | |
function d3_scale_identity(domain) { | |
function identity(x) { | |
return +x; | |
} | |
identity.invert = identity; | |
identity.domain = identity.range = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.map(identity); | |
return identity; | |
}; | |
identity.ticks = function(m) { | |
return d3_scale_linearTicks(domain, m); | |
}; | |
identity.tickFormat = function(m, format) { | |
return d3_scale_linearTickFormat(domain, m, format); | |
}; | |
identity.copy = function() { | |
return d3_scale_identity(domain); | |
}; | |
return identity; | |
} | |
d3.svg = {}; | |
function d3_zero() { | |
return 0; | |
} | |
d3.svg.arc = function() { | |
var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; | |
function arc() { | |
var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; | |
if (r1 < r0) rc = r1, r1 = r0, r0 = rc; | |
if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; | |
var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; | |
if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { | |
rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); | |
if (!cw) p1 *= -1; | |
if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); | |
if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); | |
} | |
if (r1) { | |
x0 = r1 * Math.cos(a0 + p1); | |
y0 = r1 * Math.sin(a0 + p1); | |
x1 = r1 * Math.cos(a1 - p1); | |
y1 = r1 * Math.sin(a1 - p1); | |
var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; | |
if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { | |
var h1 = (a0 + a1) / 2; | |
x0 = r1 * Math.cos(h1); | |
y0 = r1 * Math.sin(h1); | |
x1 = y1 = null; | |
} | |
} else { | |
x0 = y0 = 0; | |
} | |
if (r0) { | |
x2 = r0 * Math.cos(a1 - p0); | |
y2 = r0 * Math.sin(a1 - p0); | |
x3 = r0 * Math.cos(a0 + p0); | |
y3 = r0 * Math.sin(a0 + p0); | |
var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; | |
if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { | |
var h0 = (a0 + a1) / 2; | |
x2 = r0 * Math.cos(h0); | |
y2 = r0 * Math.sin(h0); | |
x3 = y3 = null; | |
} | |
} else { | |
x2 = y2 = 0; | |
} | |
if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { | |
cr = r0 < r1 ^ cw ? 0 : 1; | |
var rc1 = rc, rc0 = rc; | |
if (da < π) { | |
var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); | |
rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); | |
rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); | |
} | |
if (x1 != null) { | |
var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); | |
if (rc === rc1) { | |
path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); | |
} else { | |
path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); | |
} | |
} else { | |
path.push("M", x0, ",", y0); | |
} | |
if (x3 != null) { | |
var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); | |
if (rc === rc0) { | |
path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); | |
} else { | |
path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); | |
} | |
} else { | |
path.push("L", x2, ",", y2); | |
} | |
} else { | |
path.push("M", x0, ",", y0); | |
if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); | |
path.push("L", x2, ",", y2); | |
if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); | |
} | |
path.push("Z"); | |
return path.join(""); | |
} | |
function circleSegment(r1, cw) { | |
return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; | |
} | |
arc.innerRadius = function(v) { | |
if (!arguments.length) return innerRadius; | |
innerRadius = d3_functor(v); | |
return arc; | |
}; | |
arc.outerRadius = function(v) { | |
if (!arguments.length) return outerRadius; | |
outerRadius = d3_functor(v); | |
return arc; | |
}; | |
arc.cornerRadius = function(v) { | |
if (!arguments.length) return cornerRadius; | |
cornerRadius = d3_functor(v); | |
return arc; | |
}; | |
arc.padRadius = function(v) { | |
if (!arguments.length) return padRadius; | |
padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); | |
return arc; | |
}; | |
arc.startAngle = function(v) { | |
if (!arguments.length) return startAngle; | |
startAngle = d3_functor(v); | |
return arc; | |
}; | |
arc.endAngle = function(v) { | |
if (!arguments.length) return endAngle; | |
endAngle = d3_functor(v); | |
return arc; | |
}; | |
arc.padAngle = function(v) { | |
if (!arguments.length) return padAngle; | |
padAngle = d3_functor(v); | |
return arc; | |
}; | |
arc.centroid = function() { | |
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; | |
return [ Math.cos(a) * r, Math.sin(a) * r ]; | |
}; | |
return arc; | |
}; | |
var d3_svg_arcAuto = "auto"; | |
function d3_svg_arcInnerRadius(d) { | |
return d.innerRadius; | |
} | |
function d3_svg_arcOuterRadius(d) { | |
return d.outerRadius; | |
} | |
function d3_svg_arcStartAngle(d) { | |
return d.startAngle; | |
} | |
function d3_svg_arcEndAngle(d) { | |
return d.endAngle; | |
} | |
function d3_svg_arcPadAngle(d) { | |
return d && d.padAngle; | |
} | |
function d3_svg_arcSweep(x0, y0, x1, y1) { | |
return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; | |
} | |
function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { | |
var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; | |
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; | |
return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; | |
} | |
function d3_svg_line(projection) { | |
var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; | |
function line(data) { | |
var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); | |
function segment() { | |
segments.push("M", interpolate(projection(points), tension)); | |
} | |
while (++i < n) { | |
if (defined.call(this, d = data[i], i)) { | |
points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); | |
} else if (points.length) { | |
segment(); | |
points = []; | |
} | |
} | |
if (points.length) segment(); | |
return segments.length ? segments.join("") : null; | |
} | |
line.x = function(_) { | |
if (!arguments.length) return x; | |
x = _; | |
return line; | |
}; | |
line.y = function(_) { | |
if (!arguments.length) return y; | |
y = _; | |
return line; | |
}; | |
line.defined = function(_) { | |
if (!arguments.length) return defined; | |
defined = _; | |
return line; | |
}; | |
line.interpolate = function(_) { | |
if (!arguments.length) return interpolateKey; | |
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; | |
return line; | |
}; | |
line.tension = function(_) { | |
if (!arguments.length) return tension; | |
tension = _; | |
return line; | |
}; | |
return line; | |
} | |
d3.svg.line = function() { | |
return d3_svg_line(d3_identity); | |
}; | |
var d3_svg_lineInterpolators = d3.map({ | |
linear: d3_svg_lineLinear, | |
"linear-closed": d3_svg_lineLinearClosed, | |
step: d3_svg_lineStep, | |
"step-before": d3_svg_lineStepBefore, | |
"step-after": d3_svg_lineStepAfter, | |
basis: d3_svg_lineBasis, | |
"basis-open": d3_svg_lineBasisOpen, | |
"basis-closed": d3_svg_lineBasisClosed, | |
bundle: d3_svg_lineBundle, | |
cardinal: d3_svg_lineCardinal, | |
"cardinal-open": d3_svg_lineCardinalOpen, | |
"cardinal-closed": d3_svg_lineCardinalClosed, | |
monotone: d3_svg_lineMonotone | |
}); | |
d3_svg_lineInterpolators.forEach(function(key, value) { | |
value.key = key; | |
value.closed = /-closed$/.test(key); | |
}); | |
function d3_svg_lineLinear(points) { | |
return points.length > 1 ? points.join("L") : points + "Z"; | |
} | |
function d3_svg_lineLinearClosed(points) { | |
return points.join("L") + "Z"; | |
} | |
function d3_svg_lineStep(points) { | |
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; | |
while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); | |
if (n > 1) path.push("H", p[0]); | |
return path.join(""); | |
} | |
function d3_svg_lineStepBefore(points) { | |
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; | |
while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); | |
return path.join(""); | |
} | |
function d3_svg_lineStepAfter(points) { | |
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; | |
while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); | |
return path.join(""); | |
} | |
function d3_svg_lineCardinalOpen(points, tension) { | |
return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); | |
} | |
function d3_svg_lineCardinalClosed(points, tension) { | |
return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), | |
points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); | |
} | |
function d3_svg_lineCardinal(points, tension) { | |
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); | |
} | |
function d3_svg_lineHermite(points, tangents) { | |
if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { | |
return d3_svg_lineLinear(points); | |
} | |
var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; | |
if (quad) { | |
path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; | |
p0 = points[1]; | |
pi = 2; | |
} | |
if (tangents.length > 1) { | |
t = tangents[1]; | |
p = points[pi]; | |
pi++; | |
path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; | |
for (var i = 2; i < tangents.length; i++, pi++) { | |
p = points[pi]; | |
t = tangents[i]; | |
path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; | |
} | |
} | |
if (quad) { | |
var lp = points[pi]; | |
path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; | |
} | |
return path; | |
} | |
function d3_svg_lineCardinalTangents(points, tension) { | |
var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; | |
while (++i < n) { | |
p0 = p1; | |
p1 = p2; | |
p2 = points[i]; | |
tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); | |
} | |
return tangents; | |
} | |
function d3_svg_lineBasis(points) { | |
if (points.length < 3) return d3_svg_lineLinear(points); | |
var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; | |
points.push(points[n - 1]); | |
while (++i <= n) { | |
pi = points[i]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
points.pop(); | |
path.push("L", pi); | |
return path.join(""); | |
} | |
function d3_svg_lineBasisOpen(points) { | |
if (points.length < 4) return d3_svg_lineLinear(points); | |
var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; | |
while (++i < 3) { | |
pi = points[i]; | |
px.push(pi[0]); | |
py.push(pi[1]); | |
} | |
path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); | |
--i; | |
while (++i < n) { | |
pi = points[i]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
return path.join(""); | |
} | |
function d3_svg_lineBasisClosed(points) { | |
var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; | |
while (++i < 4) { | |
pi = points[i % n]; | |
px.push(pi[0]); | |
py.push(pi[1]); | |
} | |
path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; | |
--i; | |
while (++i < m) { | |
pi = points[i % n]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
return path.join(""); | |
} | |
function d3_svg_lineBundle(points, tension) { | |
var n = points.length - 1; | |
if (n) { | |
var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; | |
while (++i <= n) { | |
p = points[i]; | |
t = i / n; | |
p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); | |
p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); | |
} | |
} | |
return d3_svg_lineBasis(points); | |
} | |
function d3_svg_lineDot4(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; | |
} | |
var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; | |
function d3_svg_lineBasisBezier(path, x, y) { | |
path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); | |
} | |
function d3_svg_lineSlope(p0, p1) { | |
return (p1[1] - p0[1]) / (p1[0] - p0[0]); | |
} | |
function d3_svg_lineFiniteDifferences(points) { | |
var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); | |
while (++i < j) { | |
m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; | |
} | |
m[i] = d; | |
return m; | |
} | |
function d3_svg_lineMonotoneTangents(points) { | |
var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; | |
while (++i < j) { | |
d = d3_svg_lineSlope(points[i], points[i + 1]); | |
if (abs(d) < ε) { | |
m[i] = m[i + 1] = 0; | |
} else { | |
a = m[i] / d; | |
b = m[i + 1] / d; | |
s = a * a + b * b; | |
if (s > 9) { | |
s = d * 3 / Math.sqrt(s); | |
m[i] = s * a; | |
m[i + 1] = s * b; | |
} | |
} | |
} | |
i = -1; | |
while (++i <= j) { | |
s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); | |
tangents.push([ s || 0, m[i] * s || 0 ]); | |
} | |
return tangents; | |
} | |
function d3_svg_lineMonotone(points) { | |
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); | |
} | |
d3.svg.line.radial = function() { | |
var line = d3_svg_line(d3_svg_lineRadial); | |
line.radius = line.x, delete line.x; | |
line.angle = line.y, delete line.y; | |
return line; | |
}; | |
function d3_svg_lineRadial(points) { | |
var point, i = -1, n = points.length, r, a; | |
while (++i < n) { | |
point = points[i]; | |
r = point[0]; | |
a = point[1] - halfπ; | |
point[0] = r * Math.cos(a); | |
point[1] = r * Math.sin(a); | |
} | |
return points; | |
} | |
function d3_svg_area(projection) { | |
var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; | |
function area(data) { | |
var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { | |
return x; | |
} : d3_functor(x1), fy1 = y0 === y1 ? function() { | |
return y; | |
} : d3_functor(y1), x, y; | |
function segment() { | |
segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); | |
} | |
while (++i < n) { | |
if (defined.call(this, d = data[i], i)) { | |
points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); | |
points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); | |
} else if (points0.length) { | |
segment(); | |
points0 = []; | |
points1 = []; | |
} | |
} | |
if (points0.length) segment(); | |
return segments.length ? segments.join("") : null; | |
} | |
area.x = function(_) { | |
if (!arguments.length) return x1; | |
x0 = x1 = _; | |
return area; | |
}; | |
area.x0 = function(_) { | |
if (!arguments.length) return x0; | |
x0 = _; | |
return area; | |
}; | |
area.x1 = function(_) { | |
if (!arguments.length) return x1; | |
x1 = _; | |
return area; | |
}; | |
area.y = function(_) { | |
if (!arguments.length) return y1; | |
y0 = y1 = _; | |
return area; | |
}; | |
area.y0 = function(_) { | |
if (!arguments.length) return y0; | |
y0 = _; | |
return area; | |
}; | |
area.y1 = function(_) { | |
if (!arguments.length) return y1; | |
y1 = _; | |
return area; | |
}; | |
area.defined = function(_) { | |
if (!arguments.length) return defined; | |
defined = _; | |
return area; | |
}; | |
area.interpolate = function(_) { | |
if (!arguments.length) return interpolateKey; | |
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; | |
interpolateReverse = interpolate.reverse || interpolate; | |
L = interpolate.closed ? "M" : "L"; | |
return area; | |
}; | |
area.tension = function(_) { | |
if (!arguments.length) return tension; | |
tension = _; | |
return area; | |
}; | |
return area; | |
} | |
d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; | |
d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; | |
d3.svg.area = function() { | |
return d3_svg_area(d3_identity); | |
}; | |
d3.svg.area.radial = function() { | |
var area = d3_svg_area(d3_svg_lineRadial); | |
area.radius = area.x, delete area.x; | |
area.innerRadius = area.x0, delete area.x0; | |
area.outerRadius = area.x1, delete area.x1; | |
area.angle = area.y, delete area.y; | |
area.startAngle = area.y0, delete area.y0; | |
area.endAngle = area.y1, delete area.y1; | |
return area; | |
}; | |
d3.svg.chord = function() { | |
var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; | |
function chord(d, i) { | |
var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); | |
return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; | |
} | |
function subgroup(self, f, d, i) { | |
var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; | |
return { | |
r: r, | |
a0: a0, | |
a1: a1, | |
p0: [ r * Math.cos(a0), r * Math.sin(a0) ], | |
p1: [ r * Math.cos(a1), r * Math.sin(a1) ] | |
}; | |
} | |
function equals(a, b) { | |
return a.a0 == b.a0 && a.a1 == b.a1; | |
} | |
function arc(r, p, a) { | |
return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; | |
} | |
function curve(r0, p0, r1, p1) { | |
return "Q 0,0 " + p1; | |
} | |
chord.radius = function(v) { | |
if (!arguments.length) return radius; | |
radius = d3_functor(v); | |
return chord; | |
}; | |
chord.source = function(v) { | |
if (!arguments.length) return source; | |
source = d3_functor(v); | |
return chord; | |
}; | |
chord.target = function(v) { | |
if (!arguments.length) return target; | |
target = d3_functor(v); | |
return chord; | |
}; | |
chord.startAngle = function(v) { | |
if (!arguments.length) return startAngle; | |
startAngle = d3_functor(v); | |
return chord; | |
}; | |
chord.endAngle = function(v) { | |
if (!arguments.length) return endAngle; | |
endAngle = d3_functor(v); | |
return chord; | |
}; | |
return chord; | |
}; | |
function d3_svg_chordRadius(d) { | |
return d.radius; | |
} | |
d3.svg.diagonal = function() { | |
var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; | |
function diagonal(d, i) { | |
var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { | |
x: p0.x, | |
y: m | |
}, { | |
x: p3.x, | |
y: m | |
}, p3 ]; | |
p = p.map(projection); | |
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; | |
} | |
diagonal.source = function(x) { | |
if (!arguments.length) return source; | |
source = d3_functor(x); | |
return diagonal; | |
}; | |
diagonal.target = function(x) { | |
if (!arguments.length) return target; | |
target = d3_functor(x); | |
return diagonal; | |
}; | |
diagonal.projection = function(x) { | |
if (!arguments.length) return projection; | |
projection = x; | |
return diagonal; | |
}; | |
return diagonal; | |
}; | |
function d3_svg_diagonalProjection(d) { | |
return [ d.x, d.y ]; | |
} | |
d3.svg.diagonal.radial = function() { | |
var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; | |
diagonal.projection = function(x) { | |
return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; | |
}; | |
return diagonal; | |
}; | |
function d3_svg_diagonalRadialProjection(projection) { | |
return function() { | |
var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; | |
return [ r * Math.cos(a), r * Math.sin(a) ]; | |
}; | |
} | |
d3.svg.symbol = function() { | |
var type = d3_svg_symbolType, size = d3_svg_symbolSize; | |
function symbol(d, i) { | |
return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); | |
} | |
symbol.type = function(x) { | |
if (!arguments.length) return type; | |
type = d3_functor(x); | |
return symbol; | |
}; | |
symbol.size = function(x) { | |
if (!arguments.length) return size; | |
size = d3_functor(x); | |
return symbol; | |
}; | |
return symbol; | |
}; | |
function d3_svg_symbolSize() { | |
return 64; | |
} | |
function d3_svg_symbolType() { | |
return "circle"; | |
} | |
function d3_svg_symbolCircle(size) { | |
var r = Math.sqrt(size / π); | |
return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; | |
} | |
var d3_svg_symbols = d3.map({ | |
circle: d3_svg_symbolCircle, | |
cross: function(size) { | |
var r = Math.sqrt(size / 5) / 2; | |
return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; | |
}, | |
diamond: function(size) { | |
var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; | |
return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; | |
}, | |
square: function(size) { | |
var r = Math.sqrt(size) / 2; | |
return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; | |
}, | |
"triangle-down": function(size) { | |
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; | |
return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; | |
}, | |
"triangle-up": function(size) { | |
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; | |
return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; | |
} | |
}); | |
d3.svg.symbolTypes = d3_svg_symbols.keys(); | |
var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); | |
d3_selectionPrototype.transition = function(name) { | |
var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { | |
time: Date.now(), | |
ease: d3_ease_cubicInOut, | |
delay: 0, | |
duration: 250 | |
}; | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); | |
subgroup.push(node); | |
} | |
} | |
return d3_transition(subgroups, ns, id); | |
}; | |
d3_selectionPrototype.interrupt = function(name) { | |
return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); | |
}; | |
var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); | |
function d3_selection_interruptNS(ns) { | |
return function() { | |
var lock, activeId, active; | |
if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { | |
active.timer.c = null; | |
active.timer.t = NaN; | |
if (--lock.count) delete lock[activeId]; else delete this[ns]; | |
lock.active += .5; | |
active.event && active.event.interrupt.call(this, this.__data__, active.index); | |
} | |
}; | |
} | |
function d3_transition(groups, ns, id) { | |
d3_subclass(groups, d3_transitionPrototype); | |
groups.namespace = ns; | |
groups.id = id; | |
return groups; | |
} | |
var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; | |
d3_transitionPrototype.call = d3_selectionPrototype.call; | |
d3_transitionPrototype.empty = d3_selectionPrototype.empty; | |
d3_transitionPrototype.node = d3_selectionPrototype.node; | |
d3_transitionPrototype.size = d3_selectionPrototype.size; | |
d3.transition = function(selection, name) { | |
return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); | |
}; | |
d3.transition.prototype = d3_transitionPrototype; | |
d3_transitionPrototype.select = function(selector) { | |
var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; | |
selector = d3_selection_selector(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { | |
if ("__data__" in node) subnode.__data__ = node.__data__; | |
d3_transitionNode(subnode, i, ns, id, node[ns][id]); | |
subgroup.push(subnode); | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_transition(subgroups, ns, id); | |
}; | |
d3_transitionPrototype.selectAll = function(selector) { | |
var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; | |
selector = d3_selection_selectorAll(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
transition = node[ns][id]; | |
subnodes = selector.call(node, node.__data__, i, j); | |
subgroups.push(subgroup = []); | |
for (var k = -1, o = subnodes.length; ++k < o; ) { | |
if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); | |
subgroup.push(subnode); | |
} | |
} | |
} | |
} | |
return d3_transition(subgroups, ns, id); | |
}; | |
d3_transitionPrototype.filter = function(filter) { | |
var subgroups = [], subgroup, group, node; | |
if (typeof filter !== "function") filter = d3_selection_filter(filter); | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return d3_transition(subgroups, this.namespace, this.id); | |
}; | |
d3_transitionPrototype.tween = function(name, tween) { | |
var id = this.id, ns = this.namespace; | |
if (arguments.length < 2) return this.node()[ns][id].tween.get(name); | |
return d3_selection_each(this, tween == null ? function(node) { | |
node[ns][id].tween.remove(name); | |
} : function(node) { | |
node[ns][id].tween.set(name, tween); | |
}); | |
}; | |
function d3_transition_tween(groups, name, value, tween) { | |
var id = groups.id, ns = groups.namespace; | |
return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { | |
node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); | |
} : (value = tween(value), function(node) { | |
node[ns][id].tween.set(name, value); | |
})); | |
} | |
d3_transitionPrototype.attr = function(nameNS, value) { | |
if (arguments.length < 2) { | |
for (value in nameNS) this.attr(value, nameNS[value]); | |
return this; | |
} | |
var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); | |
function attrNull() { | |
this.removeAttribute(name); | |
} | |
function attrNullNS() { | |
this.removeAttributeNS(name.space, name.local); | |
} | |
function attrTween(b) { | |
return b == null ? attrNull : (b += "", function() { | |
var a = this.getAttribute(name), i; | |
return a !== b && (i = interpolate(a, b), function(t) { | |
this.setAttribute(name, i(t)); | |
}); | |
}); | |
} | |
function attrTweenNS(b) { | |
return b == null ? attrNullNS : (b += "", function() { | |
var a = this.getAttributeNS(name.space, name.local), i; | |
return a !== b && (i = interpolate(a, b), function(t) { | |
this.setAttributeNS(name.space, name.local, i(t)); | |
}); | |
}); | |
} | |
return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); | |
}; | |
d3_transitionPrototype.attrTween = function(nameNS, tween) { | |
var name = d3.ns.qualify(nameNS); | |
function attrTween(d, i) { | |
var f = tween.call(this, d, i, this.getAttribute(name)); | |
return f && function(t) { | |
this.setAttribute(name, f(t)); | |
}; | |
} | |
function attrTweenNS(d, i) { | |
var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); | |
return f && function(t) { | |
this.setAttributeNS(name.space, name.local, f(t)); | |
}; | |
} | |
return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); | |
}; | |
d3_transitionPrototype.style = function(name, value, priority) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof name !== "string") { | |
if (n < 2) value = ""; | |
for (priority in name) this.style(priority, name[priority], value); | |
return this; | |
} | |
priority = ""; | |
} | |
function styleNull() { | |
this.style.removeProperty(name); | |
} | |
function styleString(b) { | |
return b == null ? styleNull : (b += "", function() { | |
var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; | |
return a !== b && (i = d3_interpolate(a, b), function(t) { | |
this.style.setProperty(name, i(t), priority); | |
}); | |
}); | |
} | |
return d3_transition_tween(this, "style." + name, value, styleString); | |
}; | |
d3_transitionPrototype.styleTween = function(name, tween, priority) { | |
if (arguments.length < 3) priority = ""; | |
function styleTween(d, i) { | |
var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); | |
return f && function(t) { | |
this.style.setProperty(name, f(t), priority); | |
}; | |
} | |
return this.tween("style." + name, styleTween); | |
}; | |
d3_transitionPrototype.text = function(value) { | |
return d3_transition_tween(this, "text", value, d3_transition_text); | |
}; | |
function d3_transition_text(b) { | |
if (b == null) b = ""; | |
return function() { | |
this.textContent = b; | |
}; | |
} | |
d3_transitionPrototype.remove = function() { | |
var ns = this.namespace; | |
return this.each("end.transition", function() { | |
var p; | |
if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); | |
}); | |
}; | |
d3_transitionPrototype.ease = function(value) { | |
var id = this.id, ns = this.namespace; | |
if (arguments.length < 1) return this.node()[ns][id].ease; | |
if (typeof value !== "function") value = d3.ease.apply(d3, arguments); | |
return d3_selection_each(this, function(node) { | |
node[ns][id].ease = value; | |
}); | |
}; | |
d3_transitionPrototype.delay = function(value) { | |
var id = this.id, ns = this.namespace; | |
if (arguments.length < 1) return this.node()[ns][id].delay; | |
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { | |
node[ns][id].delay = +value.call(node, node.__data__, i, j); | |
} : (value = +value, function(node) { | |
node[ns][id].delay = value; | |
})); | |
}; | |
d3_transitionPrototype.duration = function(value) { | |
var id = this.id, ns = this.namespace; | |
if (arguments.length < 1) return this.node()[ns][id].duration; | |
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { | |
node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); | |
} : (value = Math.max(1, value), function(node) { | |
node[ns][id].duration = value; | |
})); | |
}; | |
d3_transitionPrototype.each = function(type, listener) { | |
var id = this.id, ns = this.namespace; | |
if (arguments.length < 2) { | |
var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; | |
try { | |
d3_transitionInheritId = id; | |
d3_selection_each(this, function(node, i, j) { | |
d3_transitionInherit = node[ns][id]; | |
type.call(node, node.__data__, i, j); | |
}); | |
} finally { | |
d3_transitionInherit = inherit; | |
d3_transitionInheritId = inheritId; | |
} | |
} else { | |
d3_selection_each(this, function(node) { | |
var transition = node[ns][id]; | |
(transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); | |
}); | |
} | |
return this; | |
}; | |
d3_transitionPrototype.transition = function() { | |
var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
if (node = group[i]) { | |
transition = node[ns][id0]; | |
d3_transitionNode(node, i, ns, id1, { | |
time: transition.time, | |
ease: transition.ease, | |
delay: transition.delay + transition.duration, | |
duration: transition.duration | |
}); | |
} | |
subgroup.push(node); | |
} | |
} | |
return d3_transition(subgroups, ns, id1); | |
}; | |
function d3_transitionNamespace(name) { | |
return name == null ? "__transition__" : "__transition_" + name + "__"; | |
} | |
function d3_transitionNode(node, i, ns, id, inherit) { | |
var lock = node[ns] || (node[ns] = { | |
active: 0, | |
count: 0 | |
}), transition = lock[id], time, timer, duration, ease, tweens; | |
function schedule(elapsed) { | |
var delay = transition.delay; | |
timer.t = delay + time; | |
if (delay <= elapsed) return start(elapsed - delay); | |
timer.c = start; | |
} | |
function start(elapsed) { | |
var activeId = lock.active, active = lock[activeId]; | |
if (active) { | |
active.timer.c = null; | |
active.timer.t = NaN; | |
--lock.count; | |
delete lock[activeId]; | |
active.event && active.event.interrupt.call(node, node.__data__, active.index); | |
} | |
for (var cancelId in lock) { | |
if (+cancelId < id) { | |
var cancel = lock[cancelId]; | |
cancel.timer.c = null; | |
cancel.timer.t = NaN; | |
--lock.count; | |
delete lock[cancelId]; | |
} | |
} | |
timer.c = tick; | |
d3_timer(function() { | |
if (timer.c && tick(elapsed || 1)) { | |
timer.c = null; | |
timer.t = NaN; | |
} | |
return 1; | |
}, 0, time); | |
lock.active = id; | |
transition.event && transition.event.start.call(node, node.__data__, i); | |
tweens = []; | |
transition.tween.forEach(function(key, value) { | |
if (value = value.call(node, node.__data__, i)) { | |
tweens.push(value); | |
} | |
}); | |
ease = transition.ease; | |
duration = transition.duration; | |
} | |
function tick(elapsed) { | |
var t = elapsed / duration, e = ease(t), n = tweens.length; | |
while (n > 0) { | |
tweens[--n].call(node, e); | |
} | |
if (t >= 1) { | |
transition.event && transition.event.end.call(node, node.__data__, i); | |
if (--lock.count) delete lock[id]; else delete node[ns]; | |
return 1; | |
} | |
} | |
if (!transition) { | |
time = inherit.time; | |
timer = d3_timer(schedule, 0, time); | |
transition = lock[id] = { | |
tween: new d3_Map(), | |
time: time, | |
timer: timer, | |
delay: inherit.delay, | |
duration: inherit.duration, | |
ease: inherit.ease, | |
index: i | |
}; | |
inherit = null; | |
++lock.count; | |
} | |
} | |
d3.svg.axis = function() { | |
var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; | |
function axis(g) { | |
g.each(function() { | |
var g = d3.select(this); | |
var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); | |
var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; | |
var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), | |
d3.transition(path)); | |
tickEnter.append("line"); | |
tickEnter.append("text"); | |
var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; | |
if (orient === "bottom" || orient === "top") { | |
tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; | |
text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); | |
pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); | |
} else { | |
tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; | |
text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); | |
pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); | |
} | |
lineEnter.attr(y2, sign * innerTickSize); | |
textEnter.attr(y1, sign * tickSpacing); | |
lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); | |
textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); | |
if (scale1.rangeBand) { | |
var x = scale1, dx = x.rangeBand() / 2; | |
scale0 = scale1 = function(d) { | |
return x(d) + dx; | |
}; | |
} else if (scale0.rangeBand) { | |
scale0 = scale1; | |
} else { | |
tickExit.call(tickTransform, scale1, scale0); | |
} | |
tickEnter.call(tickTransform, scale0, scale1); | |
tickUpdate.call(tickTransform, scale1, scale1); | |
}); | |
} | |
axis.scale = function(x) { | |
if (!arguments.length) return scale; | |
scale = x; | |
return axis; | |
}; | |
axis.orient = function(x) { | |
if (!arguments.length) return orient; | |
orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; | |
return axis; | |
}; | |
axis.ticks = function() { | |
if (!arguments.length) return tickArguments_; | |
tickArguments_ = d3_array(arguments); | |
return axis; | |
}; | |
axis.tickValues = function(x) { | |
if (!arguments.length) return tickValues; | |
tickValues = x; | |
return axis; | |
}; | |
axis.tickFormat = function(x) { | |
if (!arguments.length) return tickFormat_; | |
tickFormat_ = x; | |
return axis; | |
}; | |
axis.tickSize = function(x) { | |
var n = arguments.length; | |
if (!n) return innerTickSize; | |
innerTickSize = +x; | |
outerTickSize = +arguments[n - 1]; | |
return axis; | |
}; | |
axis.innerTickSize = function(x) { | |
if (!arguments.length) return innerTickSize; | |
innerTickSize = +x; | |
return axis; | |
}; | |
axis.outerTickSize = function(x) { | |
if (!arguments.length) return outerTickSize; | |
outerTickSize = +x; | |
return axis; | |
}; | |
axis.tickPadding = function(x) { | |
if (!arguments.length) return tickPadding; | |
tickPadding = +x; | |
return axis; | |
}; | |
axis.tickSubdivide = function() { | |
return arguments.length && axis; | |
}; | |
return axis; | |
}; | |
var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { | |
top: 1, | |
right: 1, | |
bottom: 1, | |
left: 1 | |
}; | |
function d3_svg_axisX(selection, x0, x1) { | |
selection.attr("transform", function(d) { | |
var v0 = x0(d); | |
return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; | |
}); | |
} | |
function d3_svg_axisY(selection, y0, y1) { | |
selection.attr("transform", function(d) { | |
var v0 = y0(d); | |
return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; | |
}); | |
} | |
d3.svg.brush = function() { | |
var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; | |
function brush(g) { | |
g.each(function() { | |
var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); | |
var background = g.selectAll(".background").data([ 0 ]); | |
background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); | |
g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); | |
var resize = g.selectAll(".resize").data(resizes, d3_identity); | |
resize.exit().remove(); | |
resize.enter().append("g").attr("class", function(d) { | |
return "resize " + d; | |
}).style("cursor", function(d) { | |
return d3_svg_brushCursor[d]; | |
}).append("rect").attr("x", function(d) { | |
return /[ew]$/.test(d) ? -3 : null; | |
}).attr("y", function(d) { | |
return /^[ns]/.test(d) ? -3 : null; | |
}).attr("width", 6).attr("height", 6).style("visibility", "hidden"); | |
resize.style("display", brush.empty() ? "none" : null); | |
var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; | |
if (x) { | |
range = d3_scaleRange(x); | |
backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); | |
redrawX(gUpdate); | |
} | |
if (y) { | |
range = d3_scaleRange(y); | |
backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); | |
redrawY(gUpdate); | |
} | |
redraw(gUpdate); | |
}); | |
} | |
brush.event = function(g) { | |
g.each(function() { | |
var event_ = event.of(this, arguments), extent1 = { | |
x: xExtent, | |
y: yExtent, | |
i: xExtentDomain, | |
j: yExtentDomain | |
}, extent0 = this.__chart__ || extent1; | |
this.__chart__ = extent1; | |
if (d3_transitionInheritId) { | |
d3.select(this).transition().each("start.brush", function() { | |
xExtentDomain = extent0.i; | |
yExtentDomain = extent0.j; | |
xExtent = extent0.x; | |
yExtent = extent0.y; | |
event_({ | |
type: "brushstart" | |
}); | |
}).tween("brush:brush", function() { | |
var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); | |
xExtentDomain = yExtentDomain = null; | |
return function(t) { | |
xExtent = extent1.x = xi(t); | |
yExtent = extent1.y = yi(t); | |
event_({ | |
type: "brush", | |
mode: "resize" | |
}); | |
}; | |
}).each("end.brush", function() { | |
xExtentDomain = extent1.i; | |
yExtentDomain = extent1.j; | |
event_({ | |
type: "brush", | |
mode: "resize" | |
}); | |
event_({ | |
type: "brushend" | |
}); | |
}); | |
} else { | |
event_({ | |
type: "brushstart" | |
}); | |
event_({ | |
type: "brush", | |
mode: "resize" | |
}); | |
event_({ | |
type: "brushend" | |
}); | |
} | |
}); | |
}; | |
function redraw(g) { | |
g.selectAll(".resize").attr("transform", function(d) { | |
return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; | |
}); | |
} | |
function redrawX(g) { | |
g.select(".extent").attr("x", xExtent[0]); | |
g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); | |
} | |
function redrawY(g) { | |
g.select(".extent").attr("y", yExtent[0]); | |
g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); | |
} | |
function brushstart() { | |
var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; | |
var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); | |
if (d3.event.changedTouches) { | |
w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); | |
} else { | |
w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); | |
} | |
g.interrupt().selectAll("*").interrupt(); | |
if (dragging) { | |
origin[0] = xExtent[0] - origin[0]; | |
origin[1] = yExtent[0] - origin[1]; | |
} else if (resizing) { | |
var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); | |
offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; | |
origin[0] = xExtent[ex]; | |
origin[1] = yExtent[ey]; | |
} else if (d3.event.altKey) center = origin.slice(); | |
g.style("pointer-events", "none").selectAll(".resize").style("display", null); | |
d3.select("body").style("cursor", eventTarget.style("cursor")); | |
event_({ | |
type: "brushstart" | |
}); | |
brushmove(); | |
function keydown() { | |
if (d3.event.keyCode == 32) { | |
if (!dragging) { | |
center = null; | |
origin[0] -= xExtent[1]; | |
origin[1] -= yExtent[1]; | |
dragging = 2; | |
} | |
d3_eventPreventDefault(); | |
} | |
} | |
function keyup() { | |
if (d3.event.keyCode == 32 && dragging == 2) { | |
origin[0] += xExtent[1]; | |
origin[1] += yExtent[1]; | |
dragging = 0; | |
d3_eventPreventDefault(); | |
} | |
} | |
function brushmove() { | |
var point = d3.mouse(target), moved = false; | |
if (offset) { | |
point[0] += offset[0]; | |
point[1] += offset[1]; | |
} | |
if (!dragging) { | |
if (d3.event.altKey) { | |
if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; | |
origin[0] = xExtent[+(point[0] < center[0])]; | |
origin[1] = yExtent[+(point[1] < center[1])]; | |
} else center = null; | |
} | |
if (resizingX && move1(point, x, 0)) { | |
redrawX(g); | |
moved = true; | |
} | |
if (resizingY && move1(point, y, 1)) { | |
redrawY(g); | |
moved = true; | |
} | |
if (moved) { | |
redraw(g); | |
event_({ | |
type: "brush", | |
mode: dragging ? "move" : "resize" | |
}); | |
} | |
} | |
function move1(point, scale, i) { | |
var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; | |
if (dragging) { | |
r0 -= position; | |
r1 -= size + position; | |
} | |
min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; | |
if (dragging) { | |
max = (min += position) + size; | |
} else { | |
if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); | |
if (position < min) { | |
max = min; | |
min = position; | |
} else { | |
max = position; | |
} | |
} | |
if (extent[0] != min || extent[1] != max) { | |
if (i) yExtentDomain = null; else xExtentDomain = null; | |
extent[0] = min; | |
extent[1] = max; | |
return true; | |
} | |
} | |
function brushend() { | |
brushmove(); | |
g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); | |
d3.select("body").style("cursor", null); | |
w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); | |
dragRestore(); | |
event_({ | |
type: "brushend" | |
}); | |
} | |
} | |
brush.x = function(z) { | |
if (!arguments.length) return x; | |
x = z; | |
resizes = d3_svg_brushResizes[!x << 1 | !y]; | |
return brush; | |
}; | |
brush.y = function(z) { | |
if (!arguments.length) return y; | |
y = z; | |
resizes = d3_svg_brushResizes[!x << 1 | !y]; | |
return brush; | |
}; | |
brush.clamp = function(z) { | |
if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; | |
if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; | |
return brush; | |
}; | |
brush.extent = function(z) { | |
var x0, x1, y0, y1, t; | |
if (!arguments.length) { | |
if (x) { | |
if (xExtentDomain) { | |
x0 = xExtentDomain[0], x1 = xExtentDomain[1]; | |
} else { | |
x0 = xExtent[0], x1 = xExtent[1]; | |
if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); | |
if (x1 < x0) t = x0, x0 = x1, x1 = t; | |
} | |
} | |
if (y) { | |
if (yExtentDomain) { | |
y0 = yExtentDomain[0], y1 = yExtentDomain[1]; | |
} else { | |
y0 = yExtent[0], y1 = yExtent[1]; | |
if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); | |
if (y1 < y0) t = y0, y0 = y1, y1 = t; | |
} | |
} | |
return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; | |
} | |
if (x) { | |
x0 = z[0], x1 = z[1]; | |
if (y) x0 = x0[0], x1 = x1[0]; | |
xExtentDomain = [ x0, x1 ]; | |
if (x.invert) x0 = x(x0), x1 = x(x1); | |
if (x1 < x0) t = x0, x0 = x1, x1 = t; | |
if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; | |
} | |
if (y) { | |
y0 = z[0], y1 = z[1]; | |
if (x) y0 = y0[1], y1 = y1[1]; | |
yExtentDomain = [ y0, y1 ]; | |
if (y.invert) y0 = y(y0), y1 = y(y1); | |
if (y1 < y0) t = y0, y0 = y1, y1 = t; | |
if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; | |
} | |
return brush; | |
}; | |
brush.clear = function() { | |
if (!brush.empty()) { | |
xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; | |
xExtentDomain = yExtentDomain = null; | |
} | |
return brush; | |
}; | |
brush.empty = function() { | |
return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; | |
}; | |
return d3.rebind(brush, event, "on"); | |
}; | |
var d3_svg_brushCursor = { | |
n: "ns-resize", | |
e: "ew-resize", | |
s: "ns-resize", | |
w: "ew-resize", | |
nw: "nwse-resize", | |
ne: "nesw-resize", | |
se: "nwse-resize", | |
sw: "nesw-resize" | |
}; | |
var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; | |
var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; | |
var d3_time_formatUtc = d3_time_format.utc; | |
var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); | |
d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; | |
function d3_time_formatIsoNative(date) { | |
return date.toISOString(); | |
} | |
d3_time_formatIsoNative.parse = function(string) { | |
var date = new Date(string); | |
return isNaN(date) ? null : date; | |
}; | |
d3_time_formatIsoNative.toString = d3_time_formatIso.toString; | |
d3_time.second = d3_time_interval(function(date) { | |
return new d3_date(Math.floor(date / 1e3) * 1e3); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 1e3); | |
}, function(date) { | |
return date.getSeconds(); | |
}); | |
d3_time.seconds = d3_time.second.range; | |
d3_time.seconds.utc = d3_time.second.utc.range; | |
d3_time.minute = d3_time_interval(function(date) { | |
return new d3_date(Math.floor(date / 6e4) * 6e4); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 6e4); | |
}, function(date) { | |
return date.getMinutes(); | |
}); | |
d3_time.minutes = d3_time.minute.range; | |
d3_time.minutes.utc = d3_time.minute.utc.range; | |
d3_time.hour = d3_time_interval(function(date) { | |
var timezone = date.getTimezoneOffset() / 60; | |
return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 36e5); | |
}, function(date) { | |
return date.getHours(); | |
}); | |
d3_time.hours = d3_time.hour.range; | |
d3_time.hours.utc = d3_time.hour.utc.range; | |
d3_time.month = d3_time_interval(function(date) { | |
date = d3_time.day(date); | |
date.setDate(1); | |
return date; | |
}, function(date, offset) { | |
date.setMonth(date.getMonth() + offset); | |
}, function(date) { | |
return date.getMonth(); | |
}); | |
d3_time.months = d3_time.month.range; | |
d3_time.months.utc = d3_time.month.utc.range; | |
function d3_time_scale(linear, methods, format) { | |
function scale(x) { | |
return linear(x); | |
} | |
scale.invert = function(x) { | |
return d3_time_scaleDate(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return linear.domain().map(d3_time_scaleDate); | |
linear.domain(x); | |
return scale; | |
}; | |
function tickMethod(extent, count) { | |
var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); | |
return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { | |
return d / 31536e6; | |
}), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; | |
} | |
scale.nice = function(interval, skip) { | |
var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); | |
if (method) interval = method[0], skip = method[1]; | |
function skipped(date) { | |
return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; | |
} | |
return scale.domain(d3_scale_nice(domain, skip > 1 ? { | |
floor: function(date) { | |
while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); | |
return date; | |
}, | |
ceil: function(date) { | |
while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); | |
return date; | |
} | |
} : interval)); | |
}; | |
scale.ticks = function(interval, skip) { | |
var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { | |
range: interval | |
}, skip ]; | |
if (method) interval = method[0], skip = method[1]; | |
return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); | |
}; | |
scale.tickFormat = function() { | |
return format; | |
}; | |
scale.copy = function() { | |
return d3_time_scale(linear.copy(), methods, format); | |
}; | |
return d3_scale_linearRebind(scale, linear); | |
} | |
function d3_time_scaleDate(t) { | |
return new Date(t); | |
} | |
var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; | |
var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; | |
var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { | |
return d.getMilliseconds(); | |
} ], [ ":%S", function(d) { | |
return d.getSeconds(); | |
} ], [ "%I:%M", function(d) { | |
return d.getMinutes(); | |
} ], [ "%I %p", function(d) { | |
return d.getHours(); | |
} ], [ "%a %d", function(d) { | |
return d.getDay() && d.getDate() != 1; | |
} ], [ "%b %d", function(d) { | |
return d.getDate() != 1; | |
} ], [ "%B", function(d) { | |
return d.getMonth(); | |
} ], [ "%Y", d3_true ] ]); | |
var d3_time_scaleMilliseconds = { | |
range: function(start, stop, step) { | |
return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); | |
}, | |
floor: d3_identity, | |
ceil: d3_identity | |
}; | |
d3_time_scaleLocalMethods.year = d3_time.year; | |
d3_time.scale = function() { | |
return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); | |
}; | |
var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { | |
return [ m[0].utc, m[1] ]; | |
}); | |
var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { | |
return d.getUTCMilliseconds(); | |
} ], [ ":%S", function(d) { | |
return d.getUTCSeconds(); | |
} ], [ "%I:%M", function(d) { | |
return d.getUTCMinutes(); | |
} ], [ "%I %p", function(d) { | |
return d.getUTCHours(); | |
} ], [ "%a %d", function(d) { | |
return d.getUTCDay() && d.getUTCDate() != 1; | |
} ], [ "%b %d", function(d) { | |
return d.getUTCDate() != 1; | |
} ], [ "%B", function(d) { | |
return d.getUTCMonth(); | |
} ], [ "%Y", d3_true ] ]); | |
d3_time_scaleUtcMethods.year = d3_time.year.utc; | |
d3_time.scale.utc = function() { | |
return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); | |
}; | |
d3.text = d3_xhrType(function(request) { | |
return request.responseText; | |
}); | |
d3.json = function(url, callback) { | |
return d3_xhr(url, "application/json", d3_json, callback); | |
}; | |
function d3_json(request) { | |
return JSON.parse(request.responseText); | |
} | |
d3.html = function(url, callback) { | |
return d3_xhr(url, "text/html", d3_html, callback); | |
}; | |
function d3_html(request) { | |
var range = d3_document.createRange(); | |
range.selectNode(d3_document.body); | |
return range.createContextualFragment(request.responseText); | |
} | |
d3.xml = d3_xhrType(function(request) { | |
return request.responseXML; | |
}); | |
if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; | |
}();</script> | |
<script type="text/javascript"> | |
(function() { | |
var radians = Math.PI / 180; | |
d3.scale.cubehelix = function() { | |
return d3.scale.linear() | |
.range([d3.hsl(300, .5, 0), d3.hsl(-240, .5, 1)]) | |
.interpolate(d3.interpolateCubehelix); | |
}; | |
d3.interpolateCubehelix = d3_interpolateCubehelix(1); | |
d3.interpolateCubehelix.gamma = d3_interpolateCubehelix; | |
function d3_interpolateCubehelix(γ) { | |
return function(a, b) { | |
a = d3.hsl(a); | |
b = d3.hsl(b); | |
var ah = (a.h + 120) * radians, | |
bh = (b.h + 120) * radians - ah, | |
as = a.s, | |
bs = b.s - as, | |
al = a.l, | |
bl = b.l - al; | |
if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; | |
if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; | |
return function(t) { | |
var h = ah + bh * t, | |
l = Math.pow(al + bl * t, γ), | |
a = (as + bs * t) * l * (1 - l), | |
cosh = Math.cos(h), | |
sinh = Math.sin(h); | |
return "#" | |
+ hex(l + a * (-0.14861 * cosh + 1.78277 * sinh)) | |
+ hex(l + a * (-0.29227 * cosh - 0.90649 * sinh)) | |
+ hex(l + a * (+1.97294 * cosh)); | |
}; | |
}; | |
} | |
function hex(v) { | |
var s = (v = v <= 0 ? 0 : v >= 1 ? 255 : v * 255 | 0).toString(16); | |
return v < 0x10 ? "0" + s : s; | |
} | |
})(); | |
</script> | |
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css"> | |
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script> | |
<script>/** | |
* @license | |
* 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 | |
* 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 | |
* 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 | |
*/ | |
// @version 0.7.20 | |
!function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomponents.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOpts){if(location.search.slice(1).split("&").forEach(function(e){var t,r=e.split("=");r[0]&&(t=r[0].match(/wc-(.+)/))&&(n[t[1]]=r[1]||!0)}),t)for(var r,o=0;r=t.attributes[o];o++)"src"!==r.name&&(n[r.name]=r.value||!0);if(n.log&&n.log.split){var i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={}}n.shadow=n.shadow||n.shadowdom||n.polyfill,"native"===n.shadow?n.shadow=!1:n.shadow=n.shadow||!HTMLElement.prototype.createShadowRoot,n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=n.register),WebComponents.flags=n}(),WebComponents.flags.shadow&&("undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:function(t,n){var r=t[this.name];return r&&r[0]===t?r[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return t&&t[0]===e?(t[0]=t[1]=void 0,!0):!1},has:function(e){var t=e[this.name];return t?t[0]===e:!1}},window.WeakMap=n}(),window.ShadowDOMPolyfill={},function(e){"use strict";function t(){if("undefined"!=typeof chrome&&chrome.app&&chrome.app.runtime)return!1;if(navigator.getDeviceStorage)return!1;try{var e=new Function("return true;");return e()}catch(t){return!1}}function n(e){if(!e)throw new Error("Assertion failed")}function r(e,t){for(var n=W(t),r=0;r<n.length;r++){var o=n[r];A(e,o,F(t,o))}return e}function o(e,t){for(var n=W(t),r=0;r<n.length;r++){var o=n[r];switch(o){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":continue}A(e,o,F(t,o))}return e}function i(e,t){for(var n=0;n<t.length;n++)if(t[n]in e)return t[n]}function a(e,t,n){U.value=n,A(e,t,U)}function s(e,t){var n=e.__proto__||Object.getPrototypeOf(e);if(q)try{W(n)}catch(r){n=n.__proto__}var o=R.get(n);if(o)return o;var i=s(n),a=E(i);return g(n,a,t),a}function c(e,t){w(e,t,!0)}function l(e,t){w(t,e,!1)}function u(e){return/^on[a-z]+$/.test(e)}function d(e){return/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(e)}function p(e){return k&&d(e)?new Function("return this.__impl4cf1e782hg__."+e):function(){return this.__impl4cf1e782hg__[e]}}function h(e){return k&&d(e)?new Function("v","this.__impl4cf1e782hg__."+e+" = v"):function(t){this.__impl4cf1e782hg__[e]=t}}function f(e){return k&&d(e)?new Function("return this.__impl4cf1e782hg__."+e+".apply(this.__impl4cf1e782hg__, arguments)"):function(){return this.__impl4cf1e782hg__[e].apply(this.__impl4cf1e782hg__,arguments)}}function m(e,t){try{return Object.getOwnPropertyDescriptor(e,t)}catch(n){return B}}function w(t,n,r,o){for(var i=W(t),a=0;a<i.length;a++){var s=i[a];if("polymerBlackList_"!==s&&!(s in n||t.polymerBlackList_&&t.polymerBlackList_[s])){q&&t.__lookupGetter__(s);var c,l,d=m(t,s);if("function"!=typeof d.value){var w=u(s);c=w?e.getEventHandlerGetter(s):p(s),(d.writable||d.set||V)&&(l=w?e.getEventHandlerSetter(s):h(s));var v=V||d.configurable;A(n,s,{get:c,set:l,configurable:v,enumerable:d.enumerable})}else r&&(n[s]=f(s))}}}function v(e,t,n){if(null!=e){var r=e.prototype;g(r,t,n),o(t,e)}}function g(e,t,r){var o=t.prototype;n(void 0===R.get(e)),R.set(e,t),I.set(o,e),c(e,o),r&&l(o,r),a(o,"constructor",t),t.prototype=o}function b(e,t){return R.get(t.prototype)===e}function y(e){var t=Object.getPrototypeOf(e),n=s(t),r=E(n);return g(t,r,e),r}function E(e){function t(t){e.call(this,t)}var n=Object.create(e.prototype);return n.constructor=t,t.prototype=n,t}function _(e){return e&&e.__impl4cf1e782hg__}function S(e){return!_(e)}function T(e){if(null===e)return null;n(S(e));var t=e.__wrapper8e3dd93a60__;return null!=t?t:e.__wrapper8e3dd93a60__=new(s(e,e))(e)}function M(e){return null===e?null:(n(_(e)),e.__impl4cf1e782hg__)}function O(e){return e.__impl4cf1e782hg__}function L(e,t){t.__impl4cf1e782hg__=e,e.__wrapper8e3dd93a60__=t}function N(e){return e&&_(e)?M(e):e}function C(e){return e&&!_(e)?T(e):e}function j(e,t){null!==t&&(n(S(e)),n(void 0===t||_(t)),e.__wrapper8e3dd93a60__=t)}function D(e,t,n){G.get=n,A(e.prototype,t,G)}function H(e,t){D(e,t,function(){return T(this.__impl4cf1e782hg__[t])})}function x(e,t){e.forEach(function(e){t.forEach(function(t){e.prototype[t]=function(){var e=C(this);return e[t].apply(e,arguments)}})})}var R=new WeakMap,I=new WeakMap,P=Object.create(null),k=t(),A=Object.defineProperty,W=Object.getOwnPropertyNames,F=Object.getOwnPropertyDescriptor,U={value:void 0,configurable:!0,enumerable:!1,writable:!0};W(window);var q=/Firefox/.test(navigator.userAgent),B={get:function(){},set:function(e){},configurable:!0,enumerable:!0},V=function(){var e=Object.getOwnPropertyDescriptor(Node.prototype,"nodeType");return e&&!e.get&&!e.set}(),G={get:void 0,configurable:!0,enumerable:!0};e.addForwardingProperties=c,e.assert=n,e.constructorTable=R,e.defineGetter=D,e.defineWrapGetter=H,e.forwardMethodsToWrapper=x,e.isIdentifierName=d,e.isWrapper=_,e.isWrapperFor=b,e.mixin=r,e.nativePrototypeTable=I,e.oneOf=i,e.registerObject=y,e.registerWrapper=v,e.rewrap=j,e.setWrapper=L,e.unsafeUnwrap=O,e.unwrap=M,e.unwrapIfNeeded=N,e.wrap=T,e.wrapIfNeeded=C,e.wrappers=P}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t,n){return{index:e,removed:t,addedCount:n}}function n(){}var r=0,o=1,i=2,a=3;n.prototype={calcEditDistances:function(e,t,n,r,o,i){for(var a=i-o+1,s=n-t+1,c=new Array(a),l=0;a>l;l++)c[l]=new Array(s),c[l][0]=l;for(var u=0;s>u;u++)c[0][u]=u;for(var l=1;a>l;l++)for(var u=1;s>u;u++)if(this.equals(e[t+u-1],r[o+l-1]))c[l][u]=c[l-1][u-1];else{var d=c[l-1][u]+1,p=c[l][u-1]+1;c[l][u]=p>d?d:p}return c},spliceOperationsFromEditDistances:function(e){for(var t=e.length-1,n=e[0].length-1,s=e[t][n],c=[];t>0||n>0;)if(0!=t)if(0!=n){var l,u=e[t-1][n-1],d=e[t-1][n],p=e[t][n-1];l=p>d?u>d?d:u:u>p?p:u,l==u?(u==s?c.push(r):(c.push(o),s=u),t--,n--):l==d?(c.push(a),t--,s=d):(c.push(i),n--,s=p)}else c.push(a),t--;else c.push(i),n--;return c.reverse(),c},calcSplices:function(e,n,s,c,l,u){var d=0,p=0,h=Math.min(s-n,u-l);if(0==n&&0==l&&(d=this.sharedPrefix(e,c,h)),s==e.length&&u==c.length&&(p=this.sharedSuffix(e,c,h-d)),n+=d,l+=d,s-=p,u-=p,s-n==0&&u-l==0)return[];if(n==s){for(var f=t(n,[],0);u>l;)f.removed.push(c[l++]);return[f]}if(l==u)return[t(n,[],s-n)];for(var m=this.spliceOperationsFromEditDistances(this.calcEditDistances(e,n,s,c,l,u)),f=void 0,w=[],v=n,g=l,b=0;b<m.length;b++)switch(m[b]){case r:f&&(w.push(f),f=void 0),v++,g++;break;case o:f||(f=t(v,[],0)),f.addedCount++,v++,f.removed.push(c[g]),g++;break;case i:f||(f=t(v,[],0)),f.addedCount++,v++;break;case a:f||(f=t(v,[],0)),f.removed.push(c[g]),g++}return f&&w.push(f),w},sharedPrefix:function(e,t,n){for(var r=0;n>r;r++)if(!this.equals(e[r],t[r]))return r;return n},sharedSuffix:function(e,t,n){for(var r=e.length,o=t.length,i=0;n>i&&this.equals(e[--r],t[--o]);)i++;return i},calculateSplices:function(e,t){return this.calcSplices(e,0,e.length,t,0,t.length)},equals:function(e,t){return e===t}},e.ArraySplice=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(){a=!1;var e=i.slice(0);i=[];for(var t=0;t<e.length;t++)(0,e[t])()}function n(e){i.push(e),a||(a=!0,r(t,0))}var r,o=window.MutationObserver,i=[],a=!1;if(o){var s=1,c=new o(t),l=document.createTextNode(s);c.observe(l,{characterData:!0}),r=function(){s=(s+1)%2,l.data=s}}else r=window.setTimeout;e.setEndOfMicrotask=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.scheduled_||(e.scheduled_=!0,f.push(e),m||(u(n),m=!0))}function n(){for(m=!1;f.length;){var e=f;f=[],e.sort(function(e,t){return e.uid_-t.uid_});for(var t=0;t<e.length;t++){var n=e[t];n.scheduled_=!1;var r=n.takeRecords();i(n),r.length&&n.callback_(r,n)}}}function r(e,t){this.type=e,this.target=t,this.addedNodes=new p.NodeList,this.removedNodes=new p.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function o(e,t){for(;e;e=e.parentNode){var n=h.get(e);if(n)for(var r=0;r<n.length;r++){var o=n[r];o.options.subtree&&o.addTransientObserver(t)}}}function i(e){for(var t=0;t<e.nodes_.length;t++){var n=e.nodes_[t],r=h.get(n);if(!r)return;for(var o=0;o<r.length;o++){var i=r[o];i.observer===e&&i.removeTransientObservers()}}}function a(e,n,o){for(var i=Object.create(null),a=Object.create(null),s=e;s;s=s.parentNode){var c=h.get(s);if(c)for(var l=0;l<c.length;l++){var u=c[l],d=u.options;if((s===e||d.subtree)&&("attributes"!==n||d.attributes)&&("attributes"!==n||!d.attributeFilter||null===o.namespace&&-1!==d.attributeFilter.indexOf(o.name))&&("characterData"!==n||d.characterData)&&("childList"!==n||d.childList)){var p=u.observer;i[p.uid_]=p,("attributes"===n&&d.attributeOldValue||"characterData"===n&&d.characterDataOldValue)&&(a[p.uid_]=o.oldValue)}}}for(var f in i){var p=i[f],m=new r(n,e);"name"in o&&"namespace"in o&&(m.attributeName=o.name,m.attributeNamespace=o.namespace),o.addedNodes&&(m.addedNodes=o.addedNodes),o.removedNodes&&(m.removedNodes=o.removedNodes),o.previousSibling&&(m.previousSibling=o.previousSibling),o.nextSibling&&(m.nextSibling=o.nextSibling),void 0!==a[f]&&(m.oldValue=a[f]),t(p),p.records_.push(m)}}function s(e){if(this.childList=!!e.childList,this.subtree=!!e.subtree,"attributes"in e||!("attributeOldValue"in e||"attributeFilter"in e)?this.attributes=!!e.attributes:this.attributes=!0,"characterDataOldValue"in e&&!("characterData"in e)?this.characterData=!0:this.characterData=!!e.characterData,!this.attributes&&(e.attributeOldValue||"attributeFilter"in e)||!this.characterData&&e.characterDataOldValue)throw new TypeError;if(this.characterData=!!e.characterData,this.attributeOldValue=!!e.attributeOldValue,this.characterDataOldValue=!!e.characterDataOldValue,"attributeFilter"in e){if(null==e.attributeFilter||"object"!=typeof e.attributeFilter)throw new TypeError;this.attributeFilter=w.call(e.attributeFilter)}else this.attributeFilter=null}function c(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++v,this.scheduled_=!1}function l(e,t,n){this.observer=e,this.target=t,this.options=n,this.transientObservedNodes=[]}var u=e.setEndOfMicrotask,d=e.wrapIfNeeded,p=e.wrappers,h=new WeakMap,f=[],m=!1,w=Array.prototype.slice,v=0;c.prototype={constructor:c,observe:function(e,t){e=d(e);var n,r=new s(t),o=h.get(e);o||h.set(e,o=[]);for(var i=0;i<o.length;i++)o[i].observer===this&&(n=o[i],n.removeTransientObservers(),n.options=r);n||(n=new l(this,e,r),o.push(n),this.nodes_.push(e))},disconnect:function(){this.nodes_.forEach(function(e){for(var t=h.get(e),n=0;n<t.length;n++){var r=t[n];if(r.observer===this){t.splice(n,1);break}}},this),this.records_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}},l.prototype={addTransientObserver:function(e){if(e!==this.target){t(this.observer),this.transientObservedNodes.push(e);var n=h.get(e);n||h.set(e,n=[]),n.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[];for(var t=0;t<e.length;t++)for(var n=e[t],r=h.get(n),o=0;o<r.length;o++)if(r[o]===this){r.splice(o,1);break}}},e.enqueueMutation=a,e.registerTransientObservers=o,e.wrappers.MutationObserver=c,e.wrappers.MutationRecord=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){this.root=e,this.parent=t}function n(e,t){if(e.treeScope_!==t){e.treeScope_=t;for(var r=e.shadowRoot;r;r=r.olderShadowRoot)r.treeScope_.parent=t;for(var o=e.firstChild;o;o=o.nextSibling)n(o,t)}}function r(n){if(n instanceof e.wrappers.Window,n.treeScope_)return n.treeScope_;var o,i=n.parentNode;return o=i?r(i):new t(n,null),n.treeScope_=o}t.prototype={get renderer(){return this.root instanceof e.wrappers.ShadowRoot?e.getRendererForHost(this.root.host):null},contains:function(e){for(;e;e=e.parent)if(e===this)return!0;return!1}},e.TreeScope=t,e.getTreeScope=r,e.setTreeScope=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e instanceof G.ShadowRoot}function n(e){return A(e).root}function r(e,r){var s=[],c=e;for(s.push(c);c;){var l=a(c);if(l&&l.length>0){for(var u=0;u<l.length;u++){var p=l[u];if(i(p)){var h=n(p),f=h.olderShadowRoot;f&&s.push(f)}s.push(p)}c=l[l.length-1]}else if(t(c)){if(d(e,c)&&o(r))break;c=c.host,s.push(c)}else c=c.parentNode,c&&s.push(c)}return s}function o(e){if(!e)return!1;switch(e.type){case"abort":case"error":case"select":case"change":case"load":case"reset":case"resize":case"scroll":case"selectstart":return!0}return!1}function i(e){return e instanceof HTMLShadowElement}function a(t){return e.getDestinationInsertionPoints(t)}function s(e,t){if(0===e.length)return t;t instanceof G.Window&&(t=t.document);for(var n=A(t),r=e[0],o=A(r),i=l(n,o),a=0;a<e.length;a++){var s=e[a];if(A(s)===i)return s}return e[e.length-1]}function c(e){for(var t=[];e;e=e.parent)t.push(e);return t}function l(e,t){for(var n=c(e),r=c(t),o=null;n.length>0&&r.length>0;){var i=n.pop(),a=r.pop();if(i!==a)break;o=i}return o}function u(e,t,n){t instanceof G.Window&&(t=t.document);var o,i=A(t),a=A(n),s=r(n,e),o=l(i,a);o||(o=a.root);for(var c=o;c;c=c.parent)for(var u=0;u<s.length;u++){var d=s[u];if(A(d)===c)return d}return null}function d(e,t){return A(e)===A(t)}function p(e){if(!K.get(e)&&(K.set(e,!0),f(V(e),V(e.target)),P)){var t=P;throw P=null,t}}function h(e){switch(e.type){case"load":case"beforeunload":case"unload":return!0}return!1}function f(t,n){if($.get(t))throw new Error("InvalidStateError");$.set(t,!0),e.renderAllPending();var o,i,a;if(h(t)&&!t.bubbles){var s=n;s instanceof G.Document&&(a=s.defaultView)&&(i=s,o=[])}if(!o)if(n instanceof G.Window)a=n,o=[];else if(o=r(n,t),!h(t)){var s=o[o.length-1];s instanceof G.Document&&(a=s.defaultView)}return ne.set(t,o),m(t,o,a,i)&&w(t,o,a,i)&&v(t,o,a,i),J.set(t,re),Y["delete"](t,null),$["delete"](t),t.defaultPrevented}function m(e,t,n,r){var o=oe;if(n&&!g(n,e,o,t,r))return!1;for(var i=t.length-1;i>0;i--)if(!g(t[i],e,o,t,r))return!1;return!0}function w(e,t,n,r){var o=ie,i=t[0]||n;return g(i,e,o,t,r)}function v(e,t,n,r){for(var o=ae,i=1;i<t.length;i++)if(!g(t[i],e,o,t,r))return;n&&t.length>0&&g(n,e,o,t,r)}function g(e,t,n,r,o){var i=z.get(e);if(!i)return!0;var a=o||s(r,e);if(a===e){if(n===oe)return!0;n===ae&&(n=ie)}else if(n===ae&&!t.bubbles)return!0;if("relatedTarget"in t){var c=B(t),l=c.relatedTarget;if(l){if(l instanceof Object&&l.addEventListener){var d=V(l),p=u(t,e,d);if(p===a)return!0}else p=null;Z.set(t,p)}}J.set(t,n);var h=t.type,f=!1;X.set(t,a),Y.set(t,e),i.depth++;for(var m=0,w=i.length;w>m;m++){var v=i[m];if(v.removed)f=!0;else if(!(v.type!==h||!v.capture&&n===oe||v.capture&&n===ae))try{if("function"==typeof v.handler?v.handler.call(e,t):v.handler.handleEvent(t),ee.get(t))return!1}catch(g){P||(P=g)}}if(i.depth--,f&&0===i.depth){var b=i.slice();i.length=0;for(var m=0;m<b.length;m++)b[m].removed||i.push(b[m])}return!Q.get(t)}function b(e,t,n){this.type=e,this.handler=t,this.capture=Boolean(n)}function y(e,t){if(!(e instanceof se))return V(T(se,"Event",e,t));var n=e;return be||"beforeunload"!==n.type||this instanceof M?void U(n,this):new M(n)}function E(e){return e&&e.relatedTarget?Object.create(e,{relatedTarget:{value:B(e.relatedTarget)}}):e}function _(e,t,n){var r=window[e],o=function(t,n){return t instanceof r?void U(t,this):V(T(r,e,t,n))};if(o.prototype=Object.create(t.prototype),n&&W(o.prototype,n),r)try{F(r,o,new r("temp"))}catch(i){F(r,o,document.createEvent(e))}return o}function S(e,t){return function(){arguments[t]=B(arguments[t]);var n=B(this);n[e].apply(n,arguments)}}function T(e,t,n,r){if(ve)return new e(n,E(r));var o=B(document.createEvent(t)),i=we[t],a=[n];return Object.keys(i).forEach(function(e){var t=null!=r&&e in r?r[e]:i[e];"relatedTarget"===e&&(t=B(t)),a.push(t)}),o["init"+t].apply(o,a),o}function M(e){y.call(this,e)}function O(e){return"function"==typeof e?!0:e&&e.handleEvent}function L(e){switch(e){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function N(e){U(e,this)}function C(e){return e instanceof G.ShadowRoot&&(e=e.host),B(e)}function j(e,t){var n=z.get(e);if(n)for(var r=0;r<n.length;r++)if(!n[r].removed&&n[r].type===t)return!0;return!1}function D(e,t){for(var n=B(e);n;n=n.parentNode)if(j(V(n),t))return!0;return!1}function H(e){k(e,Ee)}function x(t,n,o,i){e.renderAllPending();var a=V(_e.call(q(n),o,i));if(!a)return null;var c=r(a,null),l=c.lastIndexOf(t);return-1==l?null:(c=c.slice(0,l),s(c,t))}function R(e){return function(){var t=te.get(this);return t&&t[e]&&t[e].value||null}}function I(e){var t=e.slice(2);return function(n){var r=te.get(this);r||(r=Object.create(null),te.set(this,r));var o=r[e];if(o&&this.removeEventListener(t,o.wrapped,!1),"function"==typeof n){var i=function(t){var r=n.call(this,t);r===!1?t.preventDefault():"onbeforeunload"===e&&"string"==typeof r&&(t.returnValue=r)};this.addEventListener(t,i,!1),r[e]={value:n,wrapped:i}}}}var P,k=e.forwardMethodsToWrapper,A=e.getTreeScope,W=e.mixin,F=e.registerWrapper,U=e.setWrapper,q=e.unsafeUnwrap,B=e.unwrap,V=e.wrap,G=e.wrappers,z=(new WeakMap,new WeakMap),K=new WeakMap,$=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,J=new WeakMap,Q=new WeakMap,ee=new WeakMap,te=new WeakMap,ne=new WeakMap,re=0,oe=1,ie=2,ae=3;b.prototype={equals:function(e){return this.handler===e.handler&&this.type===e.type&&this.capture===e.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var se=window.Event;se.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},y.prototype={get target(){return X.get(this)},get currentTarget(){return Y.get(this)},get eventPhase(){return J.get(this)},get path(){var e=ne.get(this);return e?e.slice():[]},stopPropagation:function(){Q.set(this,!0)},stopImmediatePropagation:function(){Q.set(this,!0),ee.set(this,!0)}};var ce=function(){var e=document.createEvent("Event");return e.initEvent("test",!0,!0),e.preventDefault(),e.defaultPrevented}();ce||(y.prototype.preventDefault=function(){this.cancelable&&(q(this).preventDefault(),Object.defineProperty(this,"defaultPrevented",{get:function(){return!0},configurable:!0}))}),F(se,y,document.createEvent("Event"));var le=_("UIEvent",y),ue=_("CustomEvent",y),de={get relatedTarget(){var e=Z.get(this);return void 0!==e?e:V(B(this).relatedTarget)}},pe=W({initMouseEvent:S("initMouseEvent",14)},de),he=W({initFocusEvent:S("initFocusEvent",5)},de),fe=_("MouseEvent",le,pe),me=_("FocusEvent",le,he),we=Object.create(null),ve=function(){try{new window.FocusEvent("focus")}catch(e){return!1}return!0}();if(!ve){var ge=function(e,t,n){if(n){var r=we[n];t=W(W({},r),t)}we[e]=t};ge("Event",{bubbles:!1,cancelable:!1}),ge("CustomEvent",{detail:null},"Event"),ge("UIEvent",{view:null,detail:0},"Event"),ge("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),ge("FocusEvent",{relatedTarget:null},"UIEvent")}var be=window.BeforeUnloadEvent;M.prototype=Object.create(y.prototype),W(M.prototype,{get returnValue(){return q(this).returnValue},set returnValue(e){q(this).returnValue=e}}),be&&F(be,M);var ye=window.EventTarget,Ee=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(e){var t=e.prototype;Ee.forEach(function(e){Object.defineProperty(t,e+"_",{value:t[e]})})}),N.prototype={addEventListener:function(e,t,n){if(O(t)&&!L(e)){var r=new b(e,t,n),o=z.get(this);if(o){for(var i=0;i<o.length;i++)if(r.equals(o[i]))return}else o=[],o.depth=0,z.set(this,o);o.push(r);var a=C(this);a.addEventListener_(e,p,!0)}},removeEventListener:function(e,t,n){n=Boolean(n);var r=z.get(this);if(r){for(var o=0,i=!1,a=0;a<r.length;a++)r[a].type===e&&r[a].capture===n&&(o++,r[a].handler===t&&(i=!0,r[a].remove()));if(i&&1===o){var s=C(this);s.removeEventListener_(e,p,!0)}}},dispatchEvent:function(t){var n=B(t),r=n.type;K.set(n,!1),e.renderAllPending();var o;D(this,r)||(o=function(){},this.addEventListener(r,o,!0));try{return B(this).dispatchEvent_(n)}finally{o&&this.removeEventListener(r,o,!0)}}},ye&&F(ye,N);var _e=document.elementFromPoint;e.elementFromPoint=x,e.getEventHandlerGetter=R,e.getEventHandlerSetter=I,e.wrapEventTargetMethods=H,e.wrappers.BeforeUnloadEvent=M,e.wrappers.CustomEvent=ue,e.wrappers.Event=y,e.wrappers.EventTarget=N,e.wrappers.FocusEvent=me,e.wrappers.MouseEvent=fe,e.wrappers.UIEvent=le}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){Object.defineProperty(e,t,m)}function n(e){l(e,this)}function r(){this.length=0,t(this,"length")}function o(e){for(var t=new r,o=0;o<e.length;o++)t[o]=new n(e[o]);return t.length=o,t}function i(e){a.call(this,e)}var a=e.wrappers.UIEvent,s=e.mixin,c=e.registerWrapper,l=e.setWrapper,u=e.unsafeUnwrap,d=e.wrap,p=window.TouchEvent;if(p){var h;try{h=document.createEvent("TouchEvent")}catch(f){return}var m={enumerable:!1};n.prototype={get target(){return d(u(this).target)}};var w={configurable:!0,enumerable:!0,get:null};["clientX","clientY","screenX","screenY","pageX","pageY","identifier","webkitRadiusX","webkitRadiusY","webkitRotationAngle","webkitForce"].forEach(function(e){w.get=function(){return u(this)[e]},Object.defineProperty(n.prototype,e,w)}),r.prototype={item:function(e){return this[e]}},i.prototype=Object.create(a.prototype),s(i.prototype,{get touches(){return o(u(this).touches)},get targetTouches(){return o(u(this).targetTouches)},get changedTouches(){return o(u(this).changedTouches)},initTouchEvent:function(){throw new Error("Not implemented")}}),c(p,i,h),e.wrappers.Touch=n,e.wrappers.TouchEvent=i,e.wrappers.TouchList=r}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){Object.defineProperty(e,t,s)}function n(){this.length=0,t(this,"length")}function r(e){if(null==e)return e;for(var t=new n,r=0,o=e.length;o>r;r++)t[r]=a(e[r]);return t.length=o,t}function o(e,t){e.prototype[t]=function(){return r(i(this)[t].apply(i(this),arguments))}}var i=e.unsafeUnwrap,a=e.wrap,s={enumerable:!1};n.prototype={item:function(e){return this[e]}},t(n.prototype,"item"),e.wrappers.NodeList=n,e.addWrapNodeListMethod=o,e.wrapNodeList=r}(window.ShadowDOMPolyfill),function(e){"use strict";e.wrapHTMLCollection=e.wrapNodeList,e.wrappers.HTMLCollection=e.wrappers.NodeList}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){O(e instanceof _)}function n(e){var t=new T;return t[0]=e,t.length=1,t}function r(e,t,n){N(t,"childList",{removedNodes:n,previousSibling:e.previousSibling,nextSibling:e.nextSibling})}function o(e,t){N(e,"childList",{removedNodes:t})}function i(e,t,r,o){if(e instanceof DocumentFragment){var i=s(e);U=!0;for(var a=i.length-1;a>=0;a--)e.removeChild(i[a]),i[a].parentNode_=t;U=!1;for(var a=0;a<i.length;a++)i[a].previousSibling_=i[a-1]||r,i[a].nextSibling_=i[a+1]||o;return r&&(r.nextSibling_=i[0]),o&&(o.previousSibling_=i[i.length-1]),i}var i=n(e),c=e.parentNode;return c&&c.removeChild(e),e.parentNode_=t,e.previousSibling_=r,e.nextSibling_=o,r&&(r.nextSibling_=e),o&&(o.previousSibling_=e),i}function a(e){if(e instanceof DocumentFragment)return s(e);var t=n(e),o=e.parentNode;return o&&r(e,o,t),t}function s(e){for(var t=new T,n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t.length=n,o(e,t),t}function c(e){return e}function l(e,t){R(e,t),e.nodeIsInserted_()}function u(e,t){for(var n=C(t),r=0;r<e.length;r++)l(e[r],n)}function d(e){R(e,new M(e,null))}function p(e){for(var t=0;t<e.length;t++)d(e[t])}function h(e,t){var n=e.nodeType===_.DOCUMENT_NODE?e:e.ownerDocument;n!==t.ownerDocument&&n.adoptNode(t)}function f(t,n){if(n.length){var r=t.ownerDocument;if(r!==n[0].ownerDocument)for(var o=0;o<n.length;o++)e.adoptNodeNoRemove(n[o],r)}}function m(e,t){f(e,t);var n=t.length;if(1===n)return P(t[0]);for(var r=P(e.ownerDocument.createDocumentFragment()),o=0;n>o;o++)r.appendChild(P(t[o]));return r}function w(e){if(void 0!==e.firstChild_)for(var t=e.firstChild_;t;){var n=t;t=t.nextSibling_,n.parentNode_=n.previousSibling_=n.nextSibling_=void 0}e.firstChild_=e.lastChild_=void 0}function v(e){if(e.invalidateShadowRenderer()){for(var t=e.firstChild;t;){O(t.parentNode===e);var n=t.nextSibling,r=P(t),o=r.parentNode;o&&X.call(o,r),t.previousSibling_=t.nextSibling_=t.parentNode_=null,t=n}e.firstChild_=e.lastChild_=null}else for(var n,i=P(e),a=i.firstChild;a;)n=a.nextSibling,X.call(i,a),a=n}function g(e){var t=e.parentNode;return t&&t.invalidateShadowRenderer()}function b(e){for(var t,n=0;n<e.length;n++)t=e[n],t.parentNode.removeChild(t)}function y(e,t,n){var r;if(r=A(n?q.call(n,I(e),!1):B.call(I(e),!1)),t){for(var o=e.firstChild;o;o=o.nextSibling)r.appendChild(y(o,!0,n));if(e instanceof F.HTMLTemplateElement)for(var i=r.content,o=e.content.firstChild;o;o=o.nextSibling)i.appendChild(y(o,!0,n))}return r}function E(e,t){if(!t||C(e)!==C(t))return!1;for(var n=t;n;n=n.parentNode)if(n===e)return!0;return!1}function _(e){O(e instanceof V),S.call(this,e),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0,this.treeScope_=void 0}var S=e.wrappers.EventTarget,T=e.wrappers.NodeList,M=e.TreeScope,O=e.assert,L=e.defineWrapGetter,N=e.enqueueMutation,C=e.getTreeScope,j=e.isWrapper,D=e.mixin,H=e.registerTransientObservers,x=e.registerWrapper,R=e.setTreeScope,I=e.unsafeUnwrap,P=e.unwrap,k=e.unwrapIfNeeded,A=e.wrap,W=e.wrapIfNeeded,F=e.wrappers,U=!1,q=document.importNode,B=window.Node.prototype.cloneNode,V=window.Node,G=window.DocumentFragment,z=(V.prototype.appendChild,V.prototype.compareDocumentPosition),K=V.prototype.isEqualNode,$=V.prototype.insertBefore,X=V.prototype.removeChild,Y=V.prototype.replaceChild,Z=/Trident|Edge/.test(navigator.userAgent),J=Z?function(e,t){try{X.call(e,t)}catch(n){if(!(e instanceof G))throw n}}:function(e,t){X.call(e,t)};_.prototype=Object.create(S.prototype),D(_.prototype,{appendChild:function(e){return this.insertBefore(e,null)},insertBefore:function(e,n){t(e);var r;n?j(n)?r=P(n):(r=n,n=A(r)):(n=null,r=null),n&&O(n.parentNode===this);var o,s=n?n.previousSibling:this.lastChild,c=!this.invalidateShadowRenderer()&&!g(e);if(o=c?a(e):i(e,this,s,n),c)h(this,e),w(this),$.call(I(this),P(e),r);else{s||(this.firstChild_=o[0]),n||(this.lastChild_=o[o.length-1],void 0===this.firstChild_&&(this.firstChild_=this.firstChild));var l=r?r.parentNode:I(this);l?$.call(l,m(this,o),r):f(this,o)}return N(this,"childList",{addedNodes:o,nextSibling:n,previousSibling:s}),u(o,this),e},removeChild:function(e){if(t(e),e.parentNode!==this){for(var r=!1,o=(this.childNodes,this.firstChild);o;o=o.nextSibling)if(o===e){r=!0;break}if(!r)throw new Error("NotFoundError")}var i=P(e),a=e.nextSibling,s=e.previousSibling;if(this.invalidateShadowRenderer()){var c=this.firstChild,l=this.lastChild,u=i.parentNode;u&&J(u,i),c===e&&(this.firstChild_=a),l===e&&(this.lastChild_=s),s&&(s.nextSibling_=a),a&&(a.previousSibling_=s),e.previousSibling_=e.nextSibling_=e.parentNode_=void 0}else w(this),J(I(this),i);return U||N(this,"childList",{removedNodes:n(e),nextSibling:a,previousSibling:s}),H(this,e),e},replaceChild:function(e,r){t(e);var o;if(j(r)?o=P(r):(o=r,r=A(o)),r.parentNode!==this)throw new Error("NotFoundError");var s,c=r.nextSibling,l=r.previousSibling,p=!this.invalidateShadowRenderer()&&!g(e);return p?s=a(e):(c===e&&(c=e.nextSibling),s=i(e,this,l,c)),p?(h(this,e),w(this),Y.call(I(this),P(e),o)):(this.firstChild===r&&(this.firstChild_=s[0]),this.lastChild===r&&(this.lastChild_=s[s.length-1]),r.previousSibling_=r.nextSibling_=r.parentNode_=void 0,o.parentNode&&Y.call(o.parentNode,m(this,s),o)),N(this,"childList",{addedNodes:s,removedNodes:n(r),nextSibling:c,previousSibling:l}),d(r),u(s,this),r},nodeIsInserted_:function(){for(var e=this.firstChild;e;e=e.nextSibling)e.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:A(I(this).parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:A(I(this).firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:A(I(this).lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:A(I(this).nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:A(I(this).previousSibling)},get parentElement(){for(var e=this.parentNode;e&&e.nodeType!==_.ELEMENT_NODE;)e=e.parentNode;return e},get textContent(){for(var e="",t=this.firstChild;t;t=t.nextSibling)t.nodeType!=_.COMMENT_NODE&&(e+=t.textContent);return e},set textContent(e){null==e&&(e="");var t=c(this.childNodes);if(this.invalidateShadowRenderer()){if(v(this),""!==e){var n=I(this).ownerDocument.createTextNode(e);this.appendChild(n)}}else w(this),I(this).textContent=e;var r=c(this.childNodes);N(this,"childList",{addedNodes:r,removedNodes:t}),p(t),u(r,this)},get childNodes(){for(var e=new T,t=0,n=this.firstChild;n;n=n.nextSibling)e[t++]=n;return e.length=t,e},cloneNode:function(e){return y(this,e)},contains:function(e){return E(this,W(e))},compareDocumentPosition:function(e){return z.call(I(this),k(e))},isEqualNode:function(e){return K.call(I(this),k(e))},normalize:function(){for(var e,t,n=c(this.childNodes),r=[],o="",i=0;i<n.length;i++)t=n[i],t.nodeType===_.TEXT_NODE?e||t.data.length?e?(o+=t.data,r.push(t)):e=t:this.removeChild(t):(e&&r.length&&(e.data+=o,b(r)),r=[],o="",e=null,t.childNodes.length&&t.normalize());e&&r.length&&(e.data+=o,b(r))}}),L(_,"ownerDocument"),x(V,_,document.createDocumentFragment()),delete _.prototype.querySelector,delete _.prototype.querySelectorAll,_.prototype=D(Object.create(S.prototype),_.prototype),e.cloneNode=y,e.nodeWasAdded=l,e.nodeWasRemoved=d,e.nodesWereAdded=u,e.nodesWereRemoved=p,e.originalInsertBefore=$,e.originalRemoveChild=X,e.snapshotNodeList=c,e.wrappers.Node=_}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n,r,o){for(var i=null,a=null,s=0,c=t.length;c>s;s++)i=b(t[s]),!o&&(a=v(i).root)&&a instanceof e.wrappers.ShadowRoot||(r[n++]=i);return n}function n(e){return String(e).replace(/\/deep\/|::shadow|>>>/g," ")}function r(e){return String(e).replace(/:host\(([^\s]+)\)/g,"$1").replace(/([^\s]):host/g,"$1").replace(":host","*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content|>>>/g," ")}function o(e,t){for(var n,r=e.firstElementChild;r;){if(r.matches(t))return r;if(n=o(r,t))return n;r=r.nextElementSibling}return null}function i(e,t){return e.matches(t)}function a(e,t,n){var r=e.localName;return r===t||r===n&&e.namespaceURI===j}function s(){return!0}function c(e,t,n){return e.localName===n}function l(e,t){return e.namespaceURI===t}function u(e,t,n){return e.namespaceURI===t&&e.localName===n}function d(e,t,n,r,o,i){for(var a=e.firstElementChild;a;)r(a,o,i)&&(n[t++]=a),t=d(a,t,n,r,o,i),a=a.nextElementSibling;return t}function p(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,null);if(c instanceof N)s=S.call(c,i);else{if(!(c instanceof C))return d(this,r,o,n,i,null);s=_.call(c,i)}return t(s,r,o,a)}function h(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=M.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=T.call(c,i,a)}return t(s,r,o,!1)}function f(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=L.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=O.call(c,i,a)}return t(s,r,o,!1)}var m=e.wrappers.HTMLCollection,w=e.wrappers.NodeList,v=e.getTreeScope,g=e.unsafeUnwrap,b=e.wrap,y=document.querySelector,E=document.documentElement.querySelector,_=document.querySelectorAll,S=document.documentElement.querySelectorAll,T=document.getElementsByTagName,M=document.documentElement.getElementsByTagName,O=document.getElementsByTagNameNS,L=document.documentElement.getElementsByTagNameNS,N=window.Element,C=window.HTMLDocument||window.Document,j="http://www.w3.org/1999/xhtml",D={ | |
querySelector:function(t){var r=n(t),i=r!==t;t=r;var a,s=g(this),c=v(this).root;if(c instanceof e.wrappers.ShadowRoot)return o(this,t);if(s instanceof N)a=b(E.call(s,t));else{if(!(s instanceof C))return o(this,t);a=b(y.call(s,t))}return a&&!i&&(c=v(a).root)&&c instanceof e.wrappers.ShadowRoot?o(this,t):a},querySelectorAll:function(e){var t=n(e),r=t!==e;e=t;var o=new w;return o.length=p.call(this,i,0,o,e,r),o}},H={matches:function(t){return t=r(t),e.originalMatches.call(g(this),t)}},x={getElementsByTagName:function(e){var t=new m,n="*"===e?s:a;return t.length=h.call(this,n,0,t,e,e.toLowerCase()),t},getElementsByClassName:function(e){return this.querySelectorAll("."+e)},getElementsByTagNameNS:function(e,t){var n=new m,r=null;return r="*"===e?"*"===t?s:c:"*"===t?l:u,n.length=f.call(this,r,0,n,e||null,t),n}};e.GetElementsByInterface=x,e.SelectorsInterface=D,e.MatchesInterface=H}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;return e}function n(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.previousSibling;return e}var r=e.wrappers.NodeList,o={get firstElementChild(){return t(this.firstChild)},get lastElementChild(){return n(this.lastChild)},get childElementCount(){for(var e=0,t=this.firstElementChild;t;t=t.nextElementSibling)e++;return e},get children(){for(var e=new r,t=0,n=this.firstElementChild;n;n=n.nextElementSibling)e[t++]=n;return e.length=t,e},remove:function(){var e=this.parentNode;e&&e.removeChild(this)}},i={get nextElementSibling(){return t(this.nextSibling)},get previousElementSibling(){return n(this.previousSibling)}},a={getElementById:function(e){return/[ \t\n\r\f]/.test(e)?null:this.querySelector('[id="'+e+'"]')}};e.ChildNodeInterface=i,e.NonElementParentNodeInterface=a,e.ParentNodeInterface=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}var n=e.ChildNodeInterface,r=e.wrappers.Node,o=e.enqueueMutation,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=window.CharacterData;t.prototype=Object.create(r.prototype),i(t.prototype,{get nodeValue(){return this.data},set nodeValue(e){this.data=e},get textContent(){return this.data},set textContent(e){this.data=e},get data(){return s(this).data},set data(e){var t=s(this).data;o(this,"characterData",{oldValue:t}),s(this).data=e}}),i(t.prototype,n),a(c,t,document.createTextNode("")),e.wrappers.CharacterData=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e>>>0}function n(e){r.call(this,e)}var r=e.wrappers.CharacterData,o=(e.enqueueMutation,e.mixin),i=e.registerWrapper,a=window.Text;n.prototype=Object.create(r.prototype),o(n.prototype,{splitText:function(e){e=t(e);var n=this.data;if(e>n.length)throw new Error("IndexSizeError");var r=n.slice(0,e),o=n.slice(e);this.data=r;var i=this.ownerDocument.createTextNode(o);return this.parentNode&&this.parentNode.insertBefore(i,this.nextSibling),i}}),i(a,n,document.createTextNode("")),e.wrappers.Text=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return i(e).getAttribute("class")}function n(e,t){a(e,"attributes",{name:"class",namespace:null,oldValue:t})}function r(t){e.invalidateRendererBasedOnAttribute(t,"class")}function o(e,o,i){var a=e.ownerElement_;if(null==a)return o.apply(e,i);var s=t(a),c=o.apply(e,i);return t(a)!==s&&(n(a,s),r(a)),c}if(!window.DOMTokenList)return void console.warn("Missing DOMTokenList prototype, please include a compatible classList polyfill such as http://goo.gl/uTcepH.");var i=e.unsafeUnwrap,a=e.enqueueMutation,s=DOMTokenList.prototype.add;DOMTokenList.prototype.add=function(){o(this,s,arguments)};var c=DOMTokenList.prototype.remove;DOMTokenList.prototype.remove=function(){o(this,c,arguments)};var l=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(){return o(this,l,arguments)}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n){var r=t.parentNode;if(r&&r.shadowRoot){var o=e.getRendererForHost(r);o.dependsOnAttribute(n)&&o.invalidate()}}function n(e,t,n){u(e,"attributes",{name:t,namespace:null,oldValue:n})}function r(e){a.call(this,e)}var o=e.ChildNodeInterface,i=e.GetElementsByInterface,a=e.wrappers.Node,s=e.ParentNodeInterface,c=e.SelectorsInterface,l=e.MatchesInterface,u=(e.addWrapNodeListMethod,e.enqueueMutation),d=e.mixin,p=(e.oneOf,e.registerWrapper),h=e.unsafeUnwrap,f=e.wrappers,m=window.Element,w=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(e){return m.prototype[e]}),v=w[0],g=m.prototype[v],b=new WeakMap;r.prototype=Object.create(a.prototype),d(r.prototype,{createShadowRoot:function(){var t=new f.ShadowRoot(this);h(this).polymerShadowRoot_=t;var n=e.getRendererForHost(this);return n.invalidate(),t},get shadowRoot(){return h(this).polymerShadowRoot_||null},setAttribute:function(e,r){var o=h(this).getAttribute(e);h(this).setAttribute(e,r),n(this,e,o),t(this,e)},removeAttribute:function(e){var r=h(this).getAttribute(e);h(this).removeAttribute(e),n(this,e,r),t(this,e)},get classList(){var e=b.get(this);if(!e){if(e=h(this).classList,!e)return;e.ownerElement_=this,b.set(this,e)}return e},get className(){return h(this).className},set className(e){this.setAttribute("class",e)},get id(){return h(this).id},set id(e){this.setAttribute("id",e)}}),w.forEach(function(e){"matches"!==e&&(r.prototype[e]=function(e){return this.matches(e)})}),m.prototype.webkitCreateShadowRoot&&(r.prototype.webkitCreateShadowRoot=r.prototype.createShadowRoot),d(r.prototype,o),d(r.prototype,i),d(r.prototype,s),d(r.prototype,c),d(r.prototype,l),p(m,r,document.createElementNS(null,"x")),e.invalidateRendererBasedOnAttribute=t,e.matchesNames=w,e.originalMatches=g,e.wrappers.Element=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";case" ":return" "}}function n(e){return e.replace(L,t)}function r(e){return e.replace(N,t)}function o(e){for(var t={},n=0;n<e.length;n++)t[e[n]]=!0;return t}function i(e){if(e.namespaceURI!==D)return!0;var t=e.ownerDocument.doctype;return t&&t.publicId&&t.systemId}function a(e,t){switch(e.nodeType){case Node.ELEMENT_NODE:for(var o,a=e.tagName.toLowerCase(),c="<"+a,l=e.attributes,u=0;o=l[u];u++)c+=" "+o.name+'="'+n(o.value)+'"';return C[a]?(i(e)&&(c+="/"),c+">"):c+">"+s(e)+"</"+a+">";case Node.TEXT_NODE:var d=e.data;return t&&j[t.localName]?d:r(d);case Node.COMMENT_NODE:return"<!--"+e.data+"-->";default:throw console.error(e),new Error("not implemented")}}function s(e){e instanceof O.HTMLTemplateElement&&(e=e.content);for(var t="",n=e.firstChild;n;n=n.nextSibling)t+=a(n,e);return t}function c(e,t,n){var r=n||"div";e.textContent="";var o=T(e.ownerDocument.createElement(r));o.innerHTML=t;for(var i;i=o.firstChild;)e.appendChild(M(i))}function l(e){m.call(this,e)}function u(e,t){var n=T(e.cloneNode(!1));n.innerHTML=t;for(var r,o=T(document.createDocumentFragment());r=n.firstChild;)o.appendChild(r);return M(o)}function d(t){return function(){return e.renderAllPending(),S(this)[t]}}function p(e){w(l,e,d(e))}function h(t){Object.defineProperty(l.prototype,t,{get:d(t),set:function(n){e.renderAllPending(),S(this)[t]=n},configurable:!0,enumerable:!0})}function f(t){Object.defineProperty(l.prototype,t,{value:function(){return e.renderAllPending(),S(this)[t].apply(S(this),arguments)},configurable:!0,enumerable:!0})}var m=e.wrappers.Element,w=e.defineGetter,v=e.enqueueMutation,g=e.mixin,b=e.nodesWereAdded,y=e.nodesWereRemoved,E=e.registerWrapper,_=e.snapshotNodeList,S=e.unsafeUnwrap,T=e.unwrap,M=e.wrap,O=e.wrappers,L=/[&\u00A0"]/g,N=/[&\u00A0<>]/g,C=o(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),j=o(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D="http://www.w3.org/1999/xhtml",H=/MSIE/.test(navigator.userAgent),x=window.HTMLElement,R=window.HTMLTemplateElement;l.prototype=Object.create(m.prototype),g(l.prototype,{get innerHTML(){return s(this)},set innerHTML(e){if(H&&j[this.localName])return void(this.textContent=e);var t=_(this.childNodes);this.invalidateShadowRenderer()?this instanceof O.HTMLTemplateElement?c(this.content,e):c(this,e,this.tagName):!R&&this instanceof O.HTMLTemplateElement?c(this.content,e):S(this).innerHTML=e;var n=_(this.childNodes);v(this,"childList",{addedNodes:n,removedNodes:t}),y(t),b(n,this)},get outerHTML(){return a(this,this.parentNode)},set outerHTML(e){var t=this.parentNode;if(t){t.invalidateShadowRenderer();var n=u(t,e);t.replaceChild(n,this)}},insertAdjacentHTML:function(e,t){var n,r;switch(String(e).toLowerCase()){case"beforebegin":n=this.parentNode,r=this;break;case"afterend":n=this.parentNode,r=this.nextSibling;break;case"afterbegin":n=this,r=this.firstChild;break;case"beforeend":n=this,r=null;break;default:return}var o=u(n,t);n.insertBefore(o,r)},get hidden(){return this.hasAttribute("hidden")},set hidden(e){e?this.setAttribute("hidden",""):this.removeAttribute("hidden")}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(p),["scrollLeft","scrollTop"].forEach(h),["focus","getBoundingClientRect","getClientRects","scrollIntoView"].forEach(f),E(x,l,document.createElement("b")),e.wrappers.HTMLElement=l,e.getInnerHTML=s,e.setInnerHTML=c}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.HTMLCanvasElement;t.prototype=Object.create(n.prototype),r(t.prototype,{getContext:function(){var e=i(this).getContext.apply(i(this),arguments);return e&&a(e)}}),o(s,t,document.createElement("canvas")),e.wrappers.HTMLCanvasElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=window.HTMLContentElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get select(){return this.getAttribute("select")},set select(e){this.setAttribute("select",e)},setAttribute:function(e,t){n.prototype.setAttribute.call(this,e,t),"select"===String(e).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),i&&o(i,t),e.wrappers.HTMLContentElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=window.HTMLFormElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get elements(){return i(a(this).elements)}}),o(s,t,document.createElement("form")),e.wrappers.HTMLFormElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e,t){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var o=i(document.createElement("img"));r.call(this,o),a(o,this),void 0!==e&&(o.width=e),void 0!==t&&(o.height=t)}var r=e.wrappers.HTMLElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLImageElement;t.prototype=Object.create(r.prototype),o(s,t,document.createElement("img")),n.prototype=t.prototype,e.wrappers.HTMLImageElement=t,e.wrappers.Image=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=(e.mixin,e.wrappers.NodeList,e.registerWrapper),o=window.HTMLShadowElement;t.prototype=Object.create(n.prototype),t.prototype.constructor=t,o&&r(o,t),e.wrappers.HTMLShadowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){if(!e.defaultView)return e;var t=d.get(e);if(!t){for(t=e.implementation.createHTMLDocument("");t.lastChild;)t.removeChild(t.lastChild);d.set(e,t)}return t}function n(e){for(var n,r=t(e.ownerDocument),o=c(r.createDocumentFragment());n=e.firstChild;)o.appendChild(n);return o}function r(e){if(o.call(this,e),!p){var t=n(e);u.set(this,l(t))}}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.wrap,u=new WeakMap,d=new WeakMap,p=window.HTMLTemplateElement;r.prototype=Object.create(o.prototype),i(r.prototype,{constructor:r,get content(){return p?l(s(this).content):u.get(this)}}),p&&a(p,r),e.wrappers.HTMLTemplateElement=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.registerWrapper,o=window.HTMLMediaElement;o&&(t.prototype=Object.create(n.prototype),r(o,t,document.createElement("audio")),e.wrappers.HTMLMediaElement=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var t=i(document.createElement("audio"));r.call(this,t),a(t,this),t.setAttribute("preload","auto"),void 0!==e&&t.setAttribute("src",e)}var r=e.wrappers.HTMLMediaElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLAudioElement;s&&(t.prototype=Object.create(r.prototype),o(s,t,document.createElement("audio")),n.prototype=t.prototype,e.wrappers.HTMLAudioElement=t,e.wrappers.Audio=n)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e.replace(/\s+/g," ").trim()}function n(e){o.call(this,e)}function r(e,t,n,i){if(!(this instanceof r))throw new TypeError("DOM object constructor cannot be called as a function.");var a=c(document.createElement("option"));o.call(this,a),s(a,this),void 0!==e&&(a.text=e),void 0!==t&&a.setAttribute("value",t),n===!0&&a.setAttribute("selected",""),a.selected=i===!0}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.rewrap,c=e.unwrap,l=e.wrap,u=window.HTMLOptionElement;n.prototype=Object.create(o.prototype),i(n.prototype,{get text(){return t(this.textContent)},set text(e){this.textContent=t(String(e))},get form(){return l(c(this).form)}}),a(u,n,document.createElement("option")),r.prototype=n.prototype,e.wrappers.HTMLOptionElement=n,e.wrappers.Option=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=window.HTMLSelectElement;t.prototype=Object.create(n.prototype),r(t.prototype,{add:function(e,t){"object"==typeof t&&(t=i(t)),i(this).add(i(e),t)},remove:function(e){return void 0===e?void n.prototype.remove.call(this):("object"==typeof e&&(e=i(e)),void i(this).remove(e))},get form(){return a(i(this).form)}}),o(s,t,document.createElement("select")),e.wrappers.HTMLSelectElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=e.wrapHTMLCollection,c=window.HTMLTableElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get caption(){return a(i(this).caption)},createCaption:function(){return a(i(this).createCaption())},get tHead(){return a(i(this).tHead)},createTHead:function(){return a(i(this).createTHead())},createTFoot:function(){return a(i(this).createTFoot())},get tFoot(){return a(i(this).tFoot)},get tBodies(){return s(i(this).tBodies)},createTBody:function(){return a(i(this).createTBody())},get rows(){return s(i(this).rows)},insertRow:function(e){return a(i(this).insertRow(e))}}),o(c,t,document.createElement("table")),e.wrappers.HTMLTableElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableSectionElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get rows(){return i(a(this).rows)},insertRow:function(e){return s(a(this).insertRow(e))}}),o(c,t,document.createElement("thead")),e.wrappers.HTMLTableSectionElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableRowElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get cells(){return i(a(this).cells)},insertCell:function(e){return s(a(this).insertCell(e))}}),o(c,t,document.createElement("tr")),e.wrappers.HTMLTableRowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e.localName){case"content":return new n(e);case"shadow":return new o(e);case"template":return new i(e)}r.call(this,e)}var n=e.wrappers.HTMLContentElement,r=e.wrappers.HTMLElement,o=e.wrappers.HTMLShadowElement,i=e.wrappers.HTMLTemplateElement,a=(e.mixin,e.registerWrapper),s=window.HTMLUnknownElement;t.prototype=Object.create(r.prototype),a(s,t),e.wrappers.HTMLUnknownElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Element,r=e.wrappers.HTMLElement,o=e.registerWrapper,i=(e.defineWrapGetter,e.unsafeUnwrap),a=e.wrap,s=e.mixin,c="http://www.w3.org/2000/svg",l=window.SVGElement,u=document.createElementNS(c,"title");if(!("classList"in u)){var d=Object.getOwnPropertyDescriptor(n.prototype,"classList");Object.defineProperty(r.prototype,"classList",d),delete n.prototype.classList}t.prototype=Object.create(n.prototype),s(t.prototype,{get ownerSVGElement(){return a(i(this).ownerSVGElement)}}),o(l,t,document.createElementNS(c,"title")),e.wrappers.SVGElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){p.call(this,e)}var n=e.mixin,r=e.registerWrapper,o=e.unwrap,i=e.wrap,a=window.SVGUseElement,s="http://www.w3.org/2000/svg",c=i(document.createElementNS(s,"g")),l=document.createElementNS(s,"use"),u=c.constructor,d=Object.getPrototypeOf(u.prototype),p=d.constructor;t.prototype=Object.create(d),"instanceRoot"in l&&n(t.prototype,{get instanceRoot(){return i(o(this).instanceRoot)},get animatedInstanceRoot(){return i(o(this).animatedInstanceRoot)}}),r(a,t,l),e.wrappers.SVGUseElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.SVGElementInstance;s&&(t.prototype=Object.create(n.prototype),r(t.prototype,{get correspondingElement(){return a(i(this).correspondingElement)},get correspondingUseElement(){return a(i(this).correspondingUseElement)},get parentNode(){return a(i(this).parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return a(i(this).firstChild)},get lastChild(){return a(i(this).lastChild)},get previousSibling(){return a(i(this).previousSibling)},get nextSibling(){return a(i(this).nextSibling)}}),o(s,t),e.wrappers.SVGElementInstance=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){o(e,this)}var n=e.mixin,r=e.registerWrapper,o=e.setWrapper,i=e.unsafeUnwrap,a=e.unwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.CanvasRenderingContext2D;n(t.prototype,{get canvas(){return c(i(this).canvas)},drawImage:function(){arguments[0]=s(arguments[0]),i(this).drawImage.apply(i(this),arguments)},createPattern:function(){return arguments[0]=a(arguments[0]),i(this).createPattern.apply(i(this),arguments)}}),r(l,t,document.createElement("canvas").getContext("2d")),e.wrappers.CanvasRenderingContext2D=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){i(e,this)}var n=e.addForwardingProperties,r=e.mixin,o=e.registerWrapper,i=e.setWrapper,a=e.unsafeUnwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.WebGLRenderingContext;if(l){r(t.prototype,{get canvas(){return c(a(this).canvas)},texImage2D:function(){arguments[5]=s(arguments[5]),a(this).texImage2D.apply(a(this),arguments)},texSubImage2D:function(){arguments[6]=s(arguments[6]),a(this).texSubImage2D.apply(a(this),arguments)}});var u=Object.getPrototypeOf(l.prototype);u!==Object.prototype&&n(u,t.prototype);var d=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};o(l,t,d),e.wrappers.WebGLRenderingContext=t}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Node,r=e.GetElementsByInterface,o=e.NonElementParentNodeInterface,i=e.ParentNodeInterface,a=e.SelectorsInterface,s=e.mixin,c=e.registerObject,l=e.registerWrapper,u=window.DocumentFragment;t.prototype=Object.create(n.prototype),s(t.prototype,i),s(t.prototype,a),s(t.prototype,r),s(t.prototype,o),l(u,t,document.createDocumentFragment()),e.wrappers.DocumentFragment=t;var d=c(document.createComment(""));e.wrappers.Comment=d}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(u(e).ownerDocument.createDocumentFragment());n.call(this,t),c(t,this);var o=e.shadowRoot;f.set(this,o),this.treeScope_=new r(this,a(o||e)),h.set(this,e)}var n=e.wrappers.DocumentFragment,r=e.TreeScope,o=e.elementFromPoint,i=e.getInnerHTML,a=e.getTreeScope,s=e.mixin,c=e.rewrap,l=e.setInnerHTML,u=e.unsafeUnwrap,d=e.unwrap,p=e.wrap,h=new WeakMap,f=new WeakMap;t.prototype=Object.create(n.prototype),s(t.prototype,{constructor:t,get innerHTML(){return i(this)},set innerHTML(e){l(this,e),this.invalidateShadowRenderer()},get olderShadowRoot(){return f.get(this)||null},get host(){return h.get(this)||null},invalidateShadowRenderer:function(){return h.get(this).invalidateShadowRenderer()},elementFromPoint:function(e,t){return o(this,this.ownerDocument,e,t)},getSelection:function(){return document.getSelection()},get activeElement(){var e=d(this).ownerDocument.activeElement;if(!e||!e.nodeType)return null;var t=p(e);if(t===this.host)return null;for(;!this.contains(t)&&!this.host.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}}),e.wrappers.ShadowRoot=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(e).root;return t instanceof h?t.host:null}function n(t,n){if(t.shadowRoot){n=Math.min(t.childNodes.length-1,n);var r=t.childNodes[n];if(r){var o=e.getDestinationInsertionPoints(r);if(o.length>0){var i=o[0].parentNode;i.nodeType==Node.ELEMENT_NODE&&(t=i)}}}return t}function r(e){return e=u(e),t(e)||e}function o(e){a(e,this)}var i=e.registerWrapper,a=e.setWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.unwrapIfNeeded,u=e.wrap,d=e.getTreeScope,p=window.Range,h=e.wrappers.ShadowRoot;o.prototype={get startContainer(){return r(s(this).startContainer)},get endContainer(){return r(s(this).endContainer)},get commonAncestorContainer(){return r(s(this).commonAncestorContainer)},setStart:function(e,t){e=n(e,t),s(this).setStart(l(e),t)},setEnd:function(e,t){e=n(e,t),s(this).setEnd(l(e),t)},setStartBefore:function(e){s(this).setStartBefore(l(e))},setStartAfter:function(e){s(this).setStartAfter(l(e))},setEndBefore:function(e){s(this).setEndBefore(l(e))},setEndAfter:function(e){s(this).setEndAfter(l(e))},selectNode:function(e){s(this).selectNode(l(e))},selectNodeContents:function(e){s(this).selectNodeContents(l(e))},compareBoundaryPoints:function(e,t){return s(this).compareBoundaryPoints(e,c(t))},extractContents:function(){return u(s(this).extractContents())},cloneContents:function(){return u(s(this).cloneContents())},insertNode:function(e){s(this).insertNode(l(e))},surroundContents:function(e){s(this).surroundContents(l(e))},cloneRange:function(){return u(s(this).cloneRange())},isPointInRange:function(e,t){return s(this).isPointInRange(l(e),t)},comparePoint:function(e,t){return s(this).comparePoint(l(e),t)},intersectsNode:function(e){return s(this).intersectsNode(l(e))},toString:function(){return s(this).toString()}},p.prototype.createContextualFragment&&(o.prototype.createContextualFragment=function(e){return u(s(this).createContextualFragment(e))}),i(window.Range,o,document.createRange()),e.wrappers.Range=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.previousSibling_=e.previousSibling,e.nextSibling_=e.nextSibling,e.parentNode_=e.parentNode}function n(n,o,i){var a=x(n),s=x(o),c=i?x(i):null;if(r(o),t(o),i)n.firstChild===i&&(n.firstChild_=i),i.previousSibling_=i.previousSibling;else{n.lastChild_=n.lastChild,n.lastChild===n.firstChild&&(n.firstChild_=n.firstChild);var l=R(a.lastChild);l&&(l.nextSibling_=l.nextSibling)}e.originalInsertBefore.call(a,s,c)}function r(n){var r=x(n),o=r.parentNode;if(o){var i=R(o);t(n),n.previousSibling&&(n.previousSibling.nextSibling_=n),n.nextSibling&&(n.nextSibling.previousSibling_=n),i.lastChild===n&&(i.lastChild_=n),i.firstChild===n&&(i.firstChild_=n),e.originalRemoveChild.call(o,r)}}function o(e){P.set(e,[])}function i(e){var t=P.get(e);return t||P.set(e,t=[]),t}function a(e){for(var t=[],n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t}function s(){for(var e=0;e<F.length;e++){var t=F[e],n=t.parentRenderer;n&&n.dirty||t.render()}F=[]}function c(){T=null,s()}function l(e){var t=A.get(e);return t||(t=new h(e),A.set(e,t)),t}function u(e){var t=j(e).root;return t instanceof C?t:null}function d(e){return l(e.host)}function p(e){this.skip=!1,this.node=e,this.childNodes=[]}function h(e){this.host=e,this.dirty=!1,this.invalidateAttributes(),this.associateNode(e)}function f(e){for(var t=[],n=e.firstChild;n;n=n.nextSibling)E(n)?t.push.apply(t,i(n)):t.push(n);return t}function m(e){if(e instanceof L)return e;if(e instanceof O)return null;for(var t=e.firstChild;t;t=t.nextSibling){var n=m(t);if(n)return n}return null}function w(e,t){i(t).push(e);var n=k.get(e);n?n.push(t):k.set(e,[t])}function v(e){return k.get(e)}function g(e){k.set(e,void 0)}function b(e,t){var n=t.getAttribute("select");if(!n)return!0;if(n=n.trim(),!n)return!0;if(!(e instanceof M))return!1;if(!q.test(n))return!1;try{return e.matches(n)}catch(r){return!1}}function y(e,t){var n=v(t);return n&&n[n.length-1]===e}function E(e){return e instanceof O||e instanceof L}function _(e){return e.shadowRoot}function S(e){for(var t=[],n=e.shadowRoot;n;n=n.olderShadowRoot)t.push(n);return t}var T,M=e.wrappers.Element,O=e.wrappers.HTMLContentElement,L=e.wrappers.HTMLShadowElement,N=e.wrappers.Node,C=e.wrappers.ShadowRoot,j=(e.assert,e.getTreeScope),D=(e.mixin,e.oneOf),H=e.unsafeUnwrap,x=e.unwrap,R=e.wrap,I=e.ArraySplice,P=new WeakMap,k=new WeakMap,A=new WeakMap,W=D(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),F=[],U=new I;U.equals=function(e,t){return x(e.node)===t},p.prototype={append:function(e){var t=new p(e);return this.childNodes.push(t),t},sync:function(e){if(!this.skip){for(var t=this.node,o=this.childNodes,i=a(x(t)),s=e||new WeakMap,c=U.calculateSplices(o,i),l=0,u=0,d=0,p=0;p<c.length;p++){for(var h=c[p];d<h.index;d++)u++,o[l++].sync(s);for(var f=h.removed.length,m=0;f>m;m++){var w=R(i[u++]);s.get(w)||r(w)}for(var v=h.addedCount,g=i[u]&&R(i[u]),m=0;v>m;m++){var b=o[l++],y=b.node;n(t,y,g),s.set(y,!0),b.sync(s)}d+=v}for(var p=d;p<o.length;p++)o[p].sync(s)}}},h.prototype={render:function(e){if(this.dirty){this.invalidateAttributes();var t=this.host;this.distribution(t);var n=e||new p(t);this.buildRenderTree(n,t);var r=!e;r&&n.sync(),this.dirty=!1}},get parentRenderer(){return j(this.host).renderer},invalidate:function(){if(!this.dirty){this.dirty=!0;var e=this.parentRenderer;if(e&&e.invalidate(),F.push(this),T)return;T=window[W](c,0)}},distribution:function(e){this.resetAllSubtrees(e),this.distributionResolution(e)},resetAll:function(e){E(e)?o(e):g(e),this.resetAllSubtrees(e)},resetAllSubtrees:function(e){for(var t=e.firstChild;t;t=t.nextSibling)this.resetAll(t);e.shadowRoot&&this.resetAll(e.shadowRoot),e.olderShadowRoot&&this.resetAll(e.olderShadowRoot)},distributionResolution:function(e){if(_(e)){for(var t=e,n=f(t),r=S(t),o=0;o<r.length;o++)this.poolDistribution(r[o],n);for(var o=r.length-1;o>=0;o--){var i=r[o],a=m(i);if(a){var s=i.olderShadowRoot;s&&(n=f(s));for(var c=0;c<n.length;c++)w(n[c],a)}this.distributionResolution(i)}}for(var l=e.firstChild;l;l=l.nextSibling)this.distributionResolution(l)},poolDistribution:function(e,t){if(!(e instanceof L))if(e instanceof O){var n=e;this.updateDependentAttributes(n.getAttribute("select"));for(var r=!1,o=0;o<t.length;o++){var e=t[o];e&&b(e,n)&&(w(e,n),t[o]=void 0,r=!0)}if(!r)for(var i=n.firstChild;i;i=i.nextSibling)w(i,n)}else for(var i=e.firstChild;i;i=i.nextSibling)this.poolDistribution(i,t)},buildRenderTree:function(e,t){for(var n=this.compose(t),r=0;r<n.length;r++){var o=n[r],i=e.append(o);this.buildRenderTree(i,o)}if(_(t)){var a=l(t);a.dirty=!1}},compose:function(e){for(var t=[],n=e.shadowRoot||e,r=n.firstChild;r;r=r.nextSibling)if(E(r)){this.associateNode(n);for(var o=i(r),a=0;a<o.length;a++){var s=o[a];y(r,s)&&t.push(s)}}else t.push(r);return t},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(e){if(e){var t=this.attributes;/\.\w+/.test(e)&&(t["class"]=!0),/#\w+/.test(e)&&(t.id=!0),e.replace(/\[\s*([^\s=\|~\]]+)/g,function(e,n){t[n]=!0})}},dependsOnAttribute:function(e){return this.attributes[e]},associateNode:function(e){H(e).polymerShadowRenderer_=this}};var q=/^(:not\()?[*.#[a-zA-Z_|]/;N.prototype.invalidateShadowRenderer=function(e){var t=H(this).polymerShadowRenderer_;return t?(t.invalidate(),!0):!1},O.prototype.getDistributedNodes=L.prototype.getDistributedNodes=function(){return s(),i(this)},M.prototype.getDestinationInsertionPoints=function(){return s(),v(this)||[]},O.prototype.nodeIsInserted_=L.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var e,t=u(this);t&&(e=d(t)),H(this).polymerShadowRenderer_=e,e&&e.invalidate()},e.getRendererForHost=l,e.getShadowTrees=S,e.renderAllPending=s,e.getDestinationInsertionPoints=v,e.visual={insertBefore:n,remove:r}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t){if(window[t]){r(!e.wrappers[t]);var c=function(e){n.call(this,e)};c.prototype=Object.create(n.prototype),o(c.prototype,{get form(){return s(a(this).form)}}),i(window[t],c,document.createElement(t.slice(4,-7))),e.wrappers[t]=c}}var n=e.wrappers.HTMLElement,r=e.assert,o=e.mixin,i=e.registerWrapper,a=e.unwrap,s=e.wrap,c=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLTextAreaElement"];c.forEach(t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r(e,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unsafeUnwrap,i=e.unwrap,a=e.unwrapIfNeeded,s=e.wrap,c=window.Selection;t.prototype={get anchorNode(){return s(o(this).anchorNode)},get focusNode(){return s(o(this).focusNode)},addRange:function(e){o(this).addRange(a(e))},collapse:function(e,t){o(this).collapse(a(e),t)},containsNode:function(e,t){return o(this).containsNode(a(e),t)},getRangeAt:function(e){return s(o(this).getRangeAt(e))},removeRange:function(e){o(this).removeRange(i(e))},selectAllChildren:function(e){o(this).selectAllChildren(e instanceof ShadowRoot?o(e.host):a(e))},toString:function(){return o(this).toString()}},c.prototype.extend&&(t.prototype.extend=function(e,t){o(this).extend(a(e),t)}),n(window.Selection,t,window.getSelection()),e.wrappers.Selection=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r(e,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unsafeUnwrap,i=e.unwrapIfNeeded,a=e.wrap,s=window.TreeWalker;t.prototype={get root(){return a(o(this).root)},get currentNode(){return a(o(this).currentNode)},set currentNode(e){o(this).currentNode=i(e)},get filter(){return o(this).filter},parentNode:function(){return a(o(this).parentNode())},firstChild:function(){return a(o(this).firstChild())},lastChild:function(){return a(o(this).lastChild())},previousSibling:function(){return a(o(this).previousSibling())},previousNode:function(){return a(o(this).previousNode())},nextNode:function(){return a(o(this).nextNode())}},n(s,t),e.wrappers.TreeWalker=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){u.call(this,e),this.treeScope_=new w(this,null)}function n(e){var n=document[e];t.prototype[e]=function(){return j(n.apply(N(this),arguments))}}function r(e,t){x.call(N(t),C(e)),o(e,t)}function o(e,t){e.shadowRoot&&t.adoptNode(e.shadowRoot),e instanceof m&&i(e,t);for(var n=e.firstChild;n;n=n.nextSibling)o(n,t)}function i(e,t){var n=e.olderShadowRoot;n&&t.adoptNode(n)}function a(e){L(e,this)}function s(e,t){ | |
var n=document.implementation[t];e.prototype[t]=function(){return j(n.apply(N(this),arguments))}}function c(e,t){var n=document.implementation[t];e.prototype[t]=function(){return n.apply(N(this),arguments)}}var l=e.GetElementsByInterface,u=e.wrappers.Node,d=e.ParentNodeInterface,p=e.NonElementParentNodeInterface,h=e.wrappers.Selection,f=e.SelectorsInterface,m=e.wrappers.ShadowRoot,w=e.TreeScope,v=e.cloneNode,g=e.defineGetter,b=e.defineWrapGetter,y=e.elementFromPoint,E=e.forwardMethodsToWrapper,_=e.matchesNames,S=e.mixin,T=e.registerWrapper,M=e.renderAllPending,O=e.rewrap,L=e.setWrapper,N=e.unsafeUnwrap,C=e.unwrap,j=e.wrap,D=e.wrapEventTargetMethods,H=(e.wrapNodeList,new WeakMap);t.prototype=Object.create(u.prototype),b(t,"documentElement"),b(t,"body"),b(t,"head"),g(t,"activeElement",function(){var e=C(this).activeElement;if(!e||!e.nodeType)return null;for(var t=j(e);!this.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode"].forEach(n);var x=document.adoptNode,R=document.getSelection;S(t.prototype,{adoptNode:function(e){return e.parentNode&&e.parentNode.removeChild(e),r(e,this),e},elementFromPoint:function(e,t){return y(this,this,e,t)},importNode:function(e,t){return v(e,t,N(this))},getSelection:function(){return M(),new h(R.call(C(this)))},getElementsByName:function(e){return f.querySelectorAll.call(this,"[name="+JSON.stringify(String(e))+"]")}});var I=document.createTreeWalker,P=e.wrappers.TreeWalker;if(t.prototype.createTreeWalker=function(e,t,n,r){var o=null;return n&&(n.acceptNode&&"function"==typeof n.acceptNode?o={acceptNode:function(e){return n.acceptNode(j(e))}}:"function"==typeof n&&(o=function(e){return n(j(e))})),new P(I.call(C(this),C(e),t,o,r))},document.registerElement){var k=document.registerElement;t.prototype.registerElement=function(t,n){function r(e){return e?void L(e,this):i?document.createElement(i,t):document.createElement(t)}var o,i;if(void 0!==n&&(o=n.prototype,i=n["extends"]),o||(o=Object.create(HTMLElement.prototype)),e.nativePrototypeTable.get(o))throw new Error("NotSupportedError");for(var a,s=Object.getPrototypeOf(o),c=[];s&&!(a=e.nativePrototypeTable.get(s));)c.push(s),s=Object.getPrototypeOf(s);if(!a)throw new Error("NotSupportedError");for(var l=Object.create(a),u=c.length-1;u>=0;u--)l=Object.create(l);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(e){var t=o[e];t&&(l[e]=function(){j(this)instanceof r||O(this),t.apply(j(this),arguments)})});var d={prototype:l};i&&(d["extends"]=i),r.prototype=o,r.prototype.constructor=r,e.constructorTable.set(l,r),e.nativePrototypeTable.set(o,l);k.call(C(this),t,d);return r},E([window.HTMLDocument||window.Document],["registerElement"])}E([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"]),E([window.HTMLBodyElement,window.HTMLHeadElement,window.HTMLHtmlElement],_),E([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","createTreeWalker","elementFromPoint","getElementById","getElementsByName","getSelection"]),S(t.prototype,l),S(t.prototype,d),S(t.prototype,f),S(t.prototype,p),S(t.prototype,{get implementation(){var e=H.get(this);return e?e:(e=new a(C(this).implementation),H.set(this,e),e)},get defaultView(){return j(C(this).defaultView)}}),T(window.Document,t,document.implementation.createHTMLDocument("")),window.HTMLDocument&&T(window.HTMLDocument,t),D([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]);var A=document.implementation.createDocument;a.prototype.createDocument=function(){return arguments[2]=C(arguments[2]),j(A.apply(N(this),arguments))},s(a,"createDocumentType"),s(a,"createHTMLDocument"),c(a,"hasFeature"),T(window.DOMImplementation,a),E([window.DOMImplementation],["createDocument","createDocumentType","createHTMLDocument","hasFeature"]),e.adoptNodeNoRemove=r,e.wrappers.DOMImplementation=a,e.wrappers.Document=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.wrappers.Selection,o=e.mixin,i=e.registerWrapper,a=e.renderAllPending,s=e.unwrap,c=e.unwrapIfNeeded,l=e.wrap,u=window.Window,d=window.getComputedStyle,p=window.getDefaultComputedStyle,h=window.getSelection;t.prototype=Object.create(n.prototype),u.prototype.getComputedStyle=function(e,t){return l(this||window).getComputedStyle(c(e),t)},p&&(u.prototype.getDefaultComputedStyle=function(e,t){return l(this||window).getDefaultComputedStyle(c(e),t)}),u.prototype.getSelection=function(){return l(this||window).getSelection()},delete window.getComputedStyle,delete window.getDefaultComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(e){u.prototype[e]=function(){var t=l(this||window);return t[e].apply(t,arguments)},delete window[e]}),o(t.prototype,{getComputedStyle:function(e,t){return a(),d.call(s(this),c(e),t)},getSelection:function(){return a(),new r(h.call(s(this)))},get document(){return l(s(this).document)}}),p&&(t.prototype.getDefaultComputedStyle=function(e,t){return a(),p.call(s(this),c(e),t)}),i(u,t,window),e.wrappers.Window=t}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrap,n=window.DataTransfer||window.Clipboard,r=n.prototype.setDragImage;r&&(n.prototype.setDragImage=function(e,n,o){r.call(this,t(e),n,o)})}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t;t=e instanceof i?e:new i(e&&o(e)),r(t,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unwrap,i=window.FormData;i&&(n(i,t,new i),e.wrappers.FormData=t)}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrapIfNeeded,n=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.send=function(e){return n.call(this,t(e))}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=n[e],r=window[t];if(r){var o=document.createElement(e),i=o.constructor;window[t]=i}}var n=(e.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(n).forEach(t),Object.getOwnPropertyNames(e.wrappers).forEach(function(t){window[t]=e.wrappers[t]})}(window.ShadowDOMPolyfill),function(e){function t(e,t){var n="";return Array.prototype.forEach.call(e,function(e){n+=e.textContent+"\n\n"}),t||(n=n.replace(d,"")),n}function n(e){var t=document.createElement("style");return t.textContent=e,t}function r(e){var t=n(e);document.head.appendChild(t);var r=[];if(t.sheet)try{r=t.sheet.cssRules}catch(o){}else console.warn("sheet not found",t);return t.parentNode.removeChild(t),r}function o(){C.initialized=!0,document.body.appendChild(C);var e=C.contentDocument,t=e.createElement("base");t.href=document.baseURI,e.head.appendChild(t)}function i(e){C.initialized||o(),document.body.appendChild(C),e(C.contentDocument),document.body.removeChild(C)}function a(e,t){if(t){var o;if(e.match("@import")&&D){var a=n(e);i(function(e){e.head.appendChild(a.impl),o=Array.prototype.slice.call(a.sheet.cssRules,0),t(o)})}else o=r(e),t(o)}}function s(e){e&&l().appendChild(document.createTextNode(e))}function c(e,t){var r=n(e);r.setAttribute(t,""),r.setAttribute(x,""),document.head.appendChild(r)}function l(){return j||(j=document.createElement("style"),j.setAttribute(x,""),j[x]=!0),j}var u={strictStyling:!1,registry:{},shimStyling:function(e,n,r){var o=this.prepareRoot(e,n,r),i=this.isTypeExtension(r),a=this.makeScopeSelector(n,i),s=t(o,!0);s=this.scopeCssText(s,a),e&&(e.shimmedStyle=s),this.addCssToDocument(s,n)},shimStyle:function(e,t){return this.shimCssText(e.textContent,t)},shimCssText:function(e,t){return e=this.insertDirectives(e),this.scopeCssText(e,t)},makeScopeSelector:function(e,t){return e?t?"[is="+e+"]":e:""},isTypeExtension:function(e){return e&&e.indexOf("-")<0},prepareRoot:function(e,t,n){var r=this.registerRoot(e,t,n);return this.replaceTextInStyles(r.rootStyles,this.insertDirectives),this.removeStyles(e,r.rootStyles),this.strictStyling&&this.applyScopeToContent(e,t),r.scopeStyles},removeStyles:function(e,t){for(var n,r=0,o=t.length;o>r&&(n=t[r]);r++)n.parentNode.removeChild(n)},registerRoot:function(e,t,n){var r=this.registry[t]={root:e,name:t,extendsName:n},o=this.findStyles(e);r.rootStyles=o,r.scopeStyles=r.rootStyles;var i=this.registry[r.extendsName];return i&&(r.scopeStyles=i.scopeStyles.concat(r.scopeStyles)),r},findStyles:function(e){if(!e)return[];var t=e.querySelectorAll("style");return Array.prototype.filter.call(t,function(e){return!e.hasAttribute(R)})},applyScopeToContent:function(e,t){e&&(Array.prototype.forEach.call(e.querySelectorAll("*"),function(e){e.setAttribute(t,"")}),Array.prototype.forEach.call(e.querySelectorAll("template"),function(e){this.applyScopeToContent(e.content,t)},this))},insertDirectives:function(e){return e=this.insertPolyfillDirectivesInCssText(e),this.insertPolyfillRulesInCssText(e)},insertPolyfillDirectivesInCssText:function(e){return e=e.replace(p,function(e,t){return t.slice(0,-2)+"{"}),e.replace(h,function(e,t){return t+" {"})},insertPolyfillRulesInCssText:function(e){return e=e.replace(f,function(e,t){return t.slice(0,-1)}),e.replace(m,function(e,t,n,r){var o=e.replace(t,"").replace(n,"");return r+o})},scopeCssText:function(e,t){var n=this.extractUnscopedRulesFromCssText(e);if(e=this.insertPolyfillHostInCssText(e),e=this.convertColonHost(e),e=this.convertColonHostContext(e),e=this.convertShadowDOMSelectors(e),t){var e,r=this;a(e,function(n){e=r.scopeRules(n,t)})}return e=e+"\n"+n,e.trim()},extractUnscopedRulesFromCssText:function(e){for(var t,n="";t=w.exec(e);)n+=t[1].slice(0,-1)+"\n\n";for(;t=v.exec(e);)n+=t[0].replace(t[2],"").replace(t[1],t[3])+"\n\n";return n},convertColonHost:function(e){return this.convertColonRule(e,E,this.colonHostPartReplacer)},convertColonHostContext:function(e){return this.convertColonRule(e,_,this.colonHostContextPartReplacer)},convertColonRule:function(e,t,n){return e.replace(t,function(e,t,r,o){if(t=O,r){for(var i,a=r.split(","),s=[],c=0,l=a.length;l>c&&(i=a[c]);c++)i=i.trim(),s.push(n(t,i,o));return s.join(",")}return t+o})},colonHostContextPartReplacer:function(e,t,n){return t.match(g)?this.colonHostPartReplacer(e,t,n):e+t+n+", "+t+" "+e+n},colonHostPartReplacer:function(e,t,n){return e+t.replace(g,"")+n},convertShadowDOMSelectors:function(e){for(var t=0;t<N.length;t++)e=e.replace(N[t]," ");return e},scopeRules:function(e,t){var n="";return e&&Array.prototype.forEach.call(e,function(e){if(e.selectorText&&e.style&&void 0!==e.style.cssText)n+=this.scopeSelector(e.selectorText,t,this.strictStyling)+" {\n ",n+=this.propertiesFromRule(e)+"\n}\n\n";else if(e.type===CSSRule.MEDIA_RULE)n+="@media "+e.media.mediaText+" {\n",n+=this.scopeRules(e.cssRules,t),n+="\n}\n\n";else try{e.cssText&&(n+=e.cssText+"\n\n")}catch(r){e.type===CSSRule.KEYFRAMES_RULE&&e.cssRules&&(n+=this.ieSafeCssTextFromKeyFrameRule(e))}},this),n},ieSafeCssTextFromKeyFrameRule:function(e){var t="@keyframes "+e.name+" {";return Array.prototype.forEach.call(e.cssRules,function(e){t+=" "+e.keyText+" {"+e.style.cssText+"}"}),t+=" }"},scopeSelector:function(e,t,n){var r=[],o=e.split(",");return o.forEach(function(e){e=e.trim(),this.selectorNeedsScoping(e,t)&&(e=n&&!e.match(O)?this.applyStrictSelectorScope(e,t):this.applySelectorScope(e,t)),r.push(e)},this),r.join(", ")},selectorNeedsScoping:function(e,t){if(Array.isArray(t))return!0;var n=this.makeScopeMatcher(t);return!e.match(n)},makeScopeMatcher:function(e){return e=e.replace(/\[/g,"\\[").replace(/\]/g,"\\]"),new RegExp("^("+e+")"+S,"m")},applySelectorScope:function(e,t){return Array.isArray(t)?this.applySelectorScopeList(e,t):this.applySimpleSelectorScope(e,t)},applySelectorScopeList:function(e,t){for(var n,r=[],o=0;n=t[o];o++)r.push(this.applySimpleSelectorScope(e,n));return r.join(", ")},applySimpleSelectorScope:function(e,t){return e.match(L)?(e=e.replace(O,t),e.replace(L,t+" ")):t+" "+e},applyStrictSelectorScope:function(e,t){t=t.replace(/\[is=([^\]]*)\]/g,"$1");var n=[" ",">","+","~"],r=e,o="["+t+"]";return n.forEach(function(e){var t=r.split(e);r=t.map(function(e){var t=e.trim().replace(L,"");return t&&n.indexOf(t)<0&&t.indexOf(o)<0&&(e=t.replace(/([^:]*)(:*)(.*)/,"$1"+o+"$2$3")),e}).join(e)}),r},insertPolyfillHostInCssText:function(e){return e.replace(M,b).replace(T,g)},propertiesFromRule:function(e){var t=e.style.cssText;e.style.content&&!e.style.content.match(/['"]+|attr/)&&(t=t.replace(/content:[^;]*;/g,"content: '"+e.style.content+"';"));var n=e.style;for(var r in n)"initial"===n[r]&&(t+=r+": initial; ");return t},replaceTextInStyles:function(e,t){e&&t&&(e instanceof Array||(e=[e]),Array.prototype.forEach.call(e,function(e){e.textContent=t.call(this,e.textContent)},this))},addCssToDocument:function(e,t){e.match("@import")?c(e,t):s(e)}},d=/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,p=/\/\*\s*@polyfill ([^*]*\*+([^\/*][^*]*\*+)*\/)([^{]*?){/gim,h=/polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim,f=/\/\*\s@polyfill-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,m=/(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,w=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,v=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,g="-shadowcsshost",b="-shadowcsscontext",y=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)",E=new RegExp("("+g+y,"gim"),_=new RegExp("("+b+y,"gim"),S="([>\\s~+[.,{:][\\s\\S]*)?$",T=/\:host/gim,M=/\:host-context/gim,O=g+"-no-combinator",L=new RegExp(g,"gim"),N=(new RegExp(b,"gim"),[/>>>/g,/::shadow/g,/::content/g,/\/deep\//g,/\/shadow\//g,/\/shadow-deep\//g,/\^\^/g,/\^/g]),C=document.createElement("iframe");C.style.display="none";var j,D=navigator.userAgent.match("Chrome"),H="shim-shadowdom",x="shim-shadowdom-css",R="no-shim";if(window.ShadowDOMPolyfill){s("style { display: none !important; }\n");var I=ShadowDOMPolyfill.wrap(document),P=I.querySelector("head");P.insertBefore(l(),P.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){e.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var t="link[rel=stylesheet]["+H+"]",n="style["+H+"]";HTMLImports.importer.documentPreloadSelectors+=","+t,HTMLImports.importer.importsPreloadSelectors+=","+t,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,t,n].join(",");var r=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(e){if(!e[x]){var t=e.__importElement||e;if(!t.hasAttribute(H))return void r.call(this,e);e.__resource&&(t=e.ownerDocument.createElement("style"),t.textContent=e.__resource),HTMLImports.path.resolveUrlsInStyle(t,e.href),t.textContent=u.shimStyle(t),t.removeAttribute(H,""),t.setAttribute(x,""),t[x]=!0,t.parentNode!==P&&(e.parentNode===P?P.replaceChild(t,e):this.addElementToDocument(t)),t.__importParsed=!0,this.markParsingComplete(e),this.parseNext()}};var o=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(e){return"link"===e.localName&&"stylesheet"===e.rel&&e.hasAttribute(H)?e.__resource:o.call(this,e)}}})}e.ShadowCSS=u}(window.WebComponents)),function(e){window.ShadowDOMPolyfill?(window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}}(window.WebComponents),function(e){"use strict";function t(e){return void 0!==p[e]}function n(){s.call(this),this._isInvalid=!0}function r(e){return""==e&&n.call(this),e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&127>t&&-1==[34,35,60,62,63,96].indexOf(t)?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&127>t&&-1==[34,35,60,62,96].indexOf(t)?e:encodeURIComponent(e)}function a(e,a,s){function c(e){b.push(e)}var l=a||"scheme start",u=0,d="",v=!1,g=!1,b=[];e:for(;(e[u-1]!=f||0==u)&&!this._isInvalid;){var y=e[u];switch(l){case"scheme start":if(!y||!m.test(y)){if(a){c("Invalid scheme.");break e}d="",l="no scheme";continue}d+=y.toLowerCase(),l="scheme";break;case"scheme":if(y&&w.test(y))d+=y.toLowerCase();else{if(":"!=y){if(a){if(f==y)break e;c("Code point not allowed in scheme: "+y);break e}d="",u=0,l="no scheme";continue}if(this._scheme=d,d="",a)break e;t(this._scheme)&&(this._isRelative=!0),l="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==y?(this._query="?",l="query"):"#"==y?(this._fragment="#",l="fragment"):f!=y&&" "!=y&&"\n"!=y&&"\r"!=y&&(this._schemeData+=o(y));break;case"no scheme":if(s&&t(s._scheme)){l="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=y||"/"!=e[u+1]){c("Expected /, got: "+y),l="relative";continue}l="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),f==y){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==y||"\\"==y)"\\"==y&&c("\\ is an invalid code point."),l="relative slash";else if("?"==y)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,l="query";else{if("#"!=y){var E=e[u+1],_=e[u+2];("file"!=this._scheme||!m.test(y)||":"!=E&&"|"!=E||f!=_&&"/"!=_&&"\\"!=_&&"?"!=_&&"#"!=_)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),l="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,l="fragment"}break;case"relative slash":if("/"!=y&&"\\"!=y){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),l="relative path";continue}"\\"==y&&c("\\ is an invalid code point."),l="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=y){c("Expected '/', got: "+y),l="authority ignore slashes";continue}l="authority second slash";break;case"authority second slash":if(l="authority ignore slashes","/"!=y){c("Expected '/', got: "+y);continue}break;case"authority ignore slashes":if("/"!=y&&"\\"!=y){l="authority";continue}c("Expected authority, got: "+y);break;case"authority":if("@"==y){v&&(c("@ already seen."),d+="%40"),v=!0;for(var S=0;S<d.length;S++){var T=d[S];if(" "!=T&&"\n"!=T&&"\r"!=T)if(":"!=T||null!==this._password){var M=o(T);null!==this._password?this._password+=M:this._username+=M}else this._password="";else c("Invalid whitespace in authority.")}d=""}else{if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){u-=d.length,d="",l="host";continue}d+=y}break;case"file host":if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){2!=d.length||!m.test(d[0])||":"!=d[1]&&"|"!=d[1]?0==d.length?l="relative path start":(this._host=r.call(this,d),d="",l="relative path start"):l="relative path";continue}" "==y||"\n"==y||"\r"==y?c("Invalid whitespace in file host."):d+=y;break;case"host":case"hostname":if(":"!=y||g){if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){if(this._host=r.call(this,d),d="",l="relative path start",a)break e;continue}" "!=y&&"\n"!=y&&"\r"!=y?("["==y?g=!0:"]"==y&&(g=!1),d+=y):c("Invalid code point in host/hostname: "+y)}else if(this._host=r.call(this,d),d="",l="port","hostname"==a)break e;break;case"port":if(/[0-9]/.test(y))d+=y;else{if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y||a){if(""!=d){var O=parseInt(d,10);O!=p[this._scheme]&&(this._port=O+""),d=""}if(a)break e;l="relative path start";continue}" "==y||"\n"==y||"\r"==y?c("Invalid code point in port: "+y):n.call(this)}break;case"relative path start":if("\\"==y&&c("'\\' not allowed in path."),l="relative path","/"!=y&&"\\"!=y)continue;break;case"relative path":if(f!=y&&"/"!=y&&"\\"!=y&&(a||"?"!=y&&"#"!=y))" "!=y&&"\n"!=y&&"\r"!=y&&(d+=o(y));else{"\\"==y&&c("\\ not allowed in relative path.");var L;(L=h[d.toLowerCase()])&&(d=L),".."==d?(this._path.pop(),"/"!=y&&"\\"!=y&&this._path.push("")):"."==d&&"/"!=y&&"\\"!=y?this._path.push(""):"."!=d&&("file"==this._scheme&&0==this._path.length&&2==d.length&&m.test(d[0])&&"|"==d[1]&&(d=d[0]+":"),this._path.push(d)),d="","?"==y?(this._query="?",l="query"):"#"==y&&(this._fragment="#",l="fragment")}break;case"query":a||"#"!=y?f!=y&&" "!=y&&"\n"!=y&&"\r"!=y&&(this._query+=i(y)):(this._fragment="#",l="fragment");break;case"fragment":f!=y&&" "!=y&&"\n"!=y&&"\r"!=y&&(this._fragment+=y)}u++}}function s(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function c(e,t){void 0===t||t instanceof c||(t=new c(String(t))),this._url=e,s.call(this);var n=e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");a.call(this,n,null,t)}var l=!1;if(!e.forceJURL)try{var u=new URL("b","http://a");u.pathname="c%20d",l="http://a/c%20d"===u.href}catch(d){}if(!l){var p=Object.create(null);p.ftp=21,p.file=0,p.gopher=70,p.http=80,p.https=443,p.ws=80,p.wss=443;var h=Object.create(null);h["%2e"]=".",h[".%2e"]="..",h["%2e."]="..",h["%2e%2e"]="..";var f=void 0,m=/[a-zA-Z]/,w=/[a-zA-Z0-9\+\-\.]/;c.prototype={toString:function(){return this.href},get href(){if(this._isInvalid)return this._url;var e="";return(""!=this._username||null!=this._password)&&(e=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+e+this.host:"")+this.pathname+this._query+this._fragment},set href(e){s.call(this),a.call(this,e)},get protocol(){return this._scheme+":"},set protocol(e){this._isInvalid||a.call(this,e+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"host")},get hostname(){return this._host},set hostname(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"hostname")},get port(){return this._port},set port(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(e){!this._isInvalid&&this._isRelative&&(this._path=[],a.call(this,e,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(e){!this._isInvalid&&this._isRelative&&(this._query="?","?"==e[0]&&(e=e.slice(1)),a.call(this,e,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment},set hash(e){this._isInvalid||(this._fragment="#","#"==e[0]&&(e=e.slice(1)),a.call(this,e,"fragment"))},get origin(){var e;if(this._isInvalid||!this._scheme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"mailto":return"null"}return e=this.host,e?this._scheme+"://"+e:""}};var v=e.URL;v&&(c.createObjectURL=function(e){return v.createObjectURL.apply(v,arguments)},c.revokeObjectURL=function(e){v.revokeObjectURL(e)}),e.URL=c}}(self),function(e){function t(e){y.push(e),b||(b=!0,m(r))}function n(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function r(){b=!1;var e=y;y=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var n=e.takeRecords();o(e),n.length&&(e.callback_(n,e),t=!0)}),t&&r()}function o(e){e.nodes_.forEach(function(t){var n=w.get(t);n&&n.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){for(var n=e;n;n=n.parentNode){var r=w.get(n);if(r)for(var o=0;o<r.length;o++){var i=r[o],a=i.options;if(n===e||a.subtree){var s=t(a);s&&i.enqueue(s)}}}}function a(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++E}function s(e,t){this.type=e,this.target=t,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function c(e){var t=new s(e.type,e.target);return t.addedNodes=e.addedNodes.slice(),t.removedNodes=e.removedNodes.slice(),t.previousSibling=e.previousSibling,t.nextSibling=e.nextSibling,t.attributeName=e.attributeName,t.attributeNamespace=e.attributeNamespace,t.oldValue=e.oldValue,t}function l(e,t){return _=new s(e,t)}function u(e){return S?S:(S=c(_),S.oldValue=e,S)}function d(){_=S=void 0}function p(e){return e===S||e===_}function h(e,t){return e===t?e:S&&p(e)?S:null}function f(e,t,n){this.observer=e,this.target=t,this.options=n,this.transientObservedNodes=[]}if(!e.JsMutationObserver){var m,w=new WeakMap;if(/Trident|Edge/.test(navigator.userAgent))m=setTimeout;else if(window.setImmediate)m=window.setImmediate;else{var v=[],g=String(Math.random());window.addEventListener("message",function(e){if(e.data===g){var t=v;v=[],t.forEach(function(e){e()})}}),m=function(e){v.push(e),window.postMessage(g,"*")}}var b=!1,y=[],E=0;a.prototype={observe:function(e,t){if(e=n(e),!t.childList&&!t.attributes&&!t.characterData||t.attributeOldValue&&!t.attributes||t.attributeFilter&&t.attributeFilter.length&&!t.attributes||t.characterDataOldValue&&!t.characterData)throw new SyntaxError;var r=w.get(e);r||w.set(e,r=[]);for(var o,i=0;i<r.length;i++)if(r[i].observer===this){o=r[i],o.removeListeners(),o.options=t;break}o||(o=new f(this,e,t),r.push(o),this.nodes_.push(e)),o.addListeners()},disconnect:function(){this.nodes_.forEach(function(e){for(var t=w.get(e),n=0;n<t.length;n++){var r=t[n];if(r.observer===this){r.removeListeners(),t.splice(n,1);break}}},this),this.records_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}};var _,S;f.prototype={enqueue:function(e){var n=this.observer.records_,r=n.length;if(n.length>0){var o=n[r-1],i=h(o,e);if(i)return void(n[r-1]=i)}else t(this.observer);n[r]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=w.get(e);t||w.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=w.get(e),n=0;n<t.length;n++)if(t[n]===this){t.splice(n,1);break}},this)},handleEvent:function(e){switch(e.stopImmediatePropagation(),e.type){case"DOMAttrModified":var t=e.attrName,n=e.relatedNode.namespaceURI,r=e.target,o=new l("attributes",r);o.attributeName=t,o.attributeNamespace=n;var a=e.attrChange===MutationEvent.ADDITION?null:e.prevValue;i(r,function(e){return!e.attributes||e.attributeFilter&&e.attributeFilter.length&&-1===e.attributeFilter.indexOf(t)&&-1===e.attributeFilter.indexOf(n)?void 0:e.attributeOldValue?u(a):o});break;case"DOMCharacterDataModified":var r=e.target,o=l("characterData",r),a=e.prevValue;i(r,function(e){return e.characterData?e.characterDataOldValue?u(a):o:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(e.target);case"DOMNodeInserted":var s,c,p=e.target;"DOMNodeInserted"===e.type?(s=[p],c=[]):(s=[],c=[p]);var h=p.previousSibling,f=p.nextSibling,o=l("childList",e.target.parentNode);o.addedNodes=s,o.removedNodes=c,o.previousSibling=h,o.nextSibling=f,i(e.relatedNode,function(e){return e.childList?o:void 0})}d()}},e.JsMutationObserver=a,e.MutationObserver||(e.MutationObserver=a,a._isPolyfilled=!0)}}(self),function(e){"use strict";if(!window.performance){var t=Date.now();window.performance={now:function(){return Date.now()-t}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var e=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return e?function(t){return e(function(){t(performance.now())})}:function(e){return window.setTimeout(e,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(e){clearTimeout(e)}}());var n=function(){var e=document.createEvent("Event");return e.initEvent("foo",!0,!0),e.preventDefault(),e.defaultPrevented}();if(!n){var r=Event.prototype.preventDefault;Event.prototype.preventDefault=function(){this.cancelable&&(r.call(this),Object.defineProperty(this,"defaultPrevented",{get:function(){return!0},configurable:!0}))}}var o=/Trident/.test(navigator.userAgent);if((!window.CustomEvent||o&&"function"!=typeof window.CustomEvent)&&(window.CustomEvent=function(e,t){t=t||{};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,Boolean(t.bubbles),Boolean(t.cancelable),t.detail),n},window.CustomEvent.prototype=window.Event.prototype),!window.Event||o&&"function"!=typeof window.Event){var i=window.Event;window.Event=function(e,t){t=t||{};var n=document.createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelable)),n},window.Event.prototype=i.prototype}}(window.WebComponents),window.HTMLImports=window.HTMLImports||{flags:{}},function(e){function t(e,t){t=t||f,r(function(){i(e,t)},t)}function n(e){return"complete"===e.readyState||e.readyState===v}function r(e,t){if(n(t))e&&e();else{var o=function(){("complete"===t.readyState||t.readyState===v)&&(t.removeEventListener(g,o),r(e,t))};t.addEventListener(g,o)}}function o(e){e.target.__loaded=!0}function i(e,t){function n(){c==l&&e&&e({allImports:s,loadedImports:u,errorImports:d})}function r(e){o(e),u.push(this), | |
c++,n()}function i(e){d.push(this),c++,n()}var s=t.querySelectorAll("link[rel=import]"),c=0,l=s.length,u=[],d=[];if(l)for(var p,h=0;l>h&&(p=s[h]);h++)a(p)?(u.push(this),c++,n()):(p.addEventListener("load",r),p.addEventListener("error",i));else n()}function a(e){return d?e.__loaded||e["import"]&&"loading"!==e["import"].readyState:e.__importParsed}function s(e){for(var t,n=0,r=e.length;r>n&&(t=e[n]);n++)c(t)&&l(t)}function c(e){return"link"===e.localName&&"import"===e.rel}function l(e){var t=e["import"];t?o({target:e}):(e.addEventListener("load",o),e.addEventListener("error",o))}var u="import",d=Boolean(u in document.createElement("link")),p=Boolean(window.ShadowDOMPolyfill),h=function(e){return p?window.ShadowDOMPolyfill.wrapIfNeeded(e):e},f=h(document),m={get:function(){var e=window.HTMLImports.currentScript||document.currentScript||("complete"!==document.readyState?document.scripts[document.scripts.length-1]:null);return h(e)},configurable:!0};Object.defineProperty(document,"_currentScript",m),Object.defineProperty(f,"_currentScript",m);var w=/Trident/.test(navigator.userAgent),v=w?"complete":"interactive",g="readystatechange";d&&(new MutationObserver(function(e){for(var t,n=0,r=e.length;r>n&&(t=e[n]);n++)t.addedNodes&&s(t.addedNodes)}).observe(document.head,{childList:!0}),function(){if("loading"===document.readyState)for(var e,t=document.querySelectorAll("link[rel=import]"),n=0,r=t.length;r>n&&(e=t[n]);n++)l(e)}()),t(function(e){window.HTMLImports.ready=!0,window.HTMLImports.readyTime=(new Date).getTime();var t=f.createEvent("CustomEvent");t.initCustomEvent("HTMLImportsLoaded",!0,!0,e),f.dispatchEvent(t)}),e.IMPORT_LINK_TYPE=u,e.useNative=d,e.rootDocument=f,e.whenReady=t,e.isIE=w}(window.HTMLImports),function(e){var t=[],n=function(e){t.push(e)},r=function(){t.forEach(function(t){t(e)})};e.addModule=n,e.initializeModules=r}(window.HTMLImports),window.HTMLImports.addModule(function(e){var t=/(url\()([^)]*)(\))/g,n=/(@import[\s]+(?!url\())([^;]*)(;)/g,r={resolveUrlsInStyle:function(e,t){var n=e.ownerDocument,r=n.createElement("a");return e.textContent=this.resolveUrlsInCssText(e.textContent,t,r),e},resolveUrlsInCssText:function(e,r,o){var i=this.replaceUrls(e,o,r,t);return i=this.replaceUrls(i,o,r,n)},replaceUrls:function(e,t,n,r){return e.replace(r,function(e,r,o,i){var a=o.replace(/["']/g,"");return n&&(a=new URL(a,n).href),t.href=a,a=t.href,r+"'"+a+"'"+i})}};e.path=r}),window.HTMLImports.addModule(function(e){var t={async:!0,ok:function(e){return e.status>=200&&e.status<300||304===e.status||0===e.status},load:function(n,r,o){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}r.call(o,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,r=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};r.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,r=e.length;r>n&&(t=e[n]);n++)this.require(t);this.checkDone()},addNode:function(e){this.inflight++,this.require(e),this.checkDone()},require:function(e){var t=e.src||e.href;e.__nodeUrl=t,this.dedupe(t,e)||this.fetch(t,e)},dedupe:function(e,t){if(this.pending[e])return this.pending[e].push(t),!0;return this.cache[e]?(this.onload(e,t,this.cache[e]),this.tail(),!0):(this.pending[e]=[t],!1)},fetch:function(e,r){if(n.load&&console.log("fetch",e,r),e)if(e.match(/^data:/)){var o=e.split(","),i=o[0],a=o[1];a=i.indexOf(";base64")>-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,r,null,a)}.bind(this),0)}else{var s=function(t,n,o){this.receive(e,r,t,n,o)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,r,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,r,o){this.cache[e]=r;for(var i,a=this.pending[e],s=0,c=a.length;c>s&&(i=a[s]);s++)this.onload(e,i,r,n,o),this.tail();this.pending[e]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},e.Loader=r}),window.HTMLImports.addModule(function(e){var t=function(e){this.addCallback=e,this.mo=new MutationObserver(this.handler.bind(this))};t.prototype={handler:function(e){for(var t,n=0,r=e.length;r>n&&(t=e[n]);n++)"childList"===t.type&&t.addedNodes.length&&this.addedNodes(t.addedNodes)},addedNodes:function(e){this.addCallback&&this.addCallback(e);for(var t,n=0,r=e.length;r>n&&(t=e[n]);n++)t.children&&t.children.length&&this.addedNodes(t.children)},observe:function(e){this.mo.observe(e,{childList:!0,subtree:!0})}},e.Observer=t}),window.HTMLImports.addModule(function(e){function t(e){return"link"===e.localName&&e.rel===u}function n(e){var t=r(e);return"data:text/javascript;charset=utf-8,"+encodeURIComponent(t)}function r(e){return e.textContent+o(e)}function o(e){var t=e.ownerDocument;t.__importedScripts=t.__importedScripts||0;var n=e.ownerDocument.baseURI,r=t.__importedScripts?"-"+t.__importedScripts:"";return t.__importedScripts++,"\n//# sourceURL="+n+r+".js\n"}function i(e){var t=e.ownerDocument.createElement("style");return t.textContent=e.textContent,a.resolveUrlsInStyle(t),t}var a=e.path,s=e.rootDocument,c=e.flags,l=e.isIE,u=e.IMPORT_LINK_TYPE,d="link[rel="+u+"]",p={documentSelectors:d,importsSelectors:[d,"link[rel=stylesheet]:not([type])","style:not([type])","script:not([type])",'script[type="application/javascript"]','script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},dynamicElements:[],parseNext:function(){var e=this.nextToParse();e&&this.parse(e)},parse:function(e){if(this.isParsed(e))return void(c.parse&&console.log("[%s] is already parsed",e.localName));var t=this[this.map[e.localName]];t&&(this.markParsing(e),t.call(this,e))},parseDynamic:function(e,t){this.dynamicElements.push(e),t||this.parseNext()},markParsing:function(e){c.parse&&console.log("parsing",e),this.parsingElement=e},markParsingComplete:function(e){e.__importParsed=!0,this.markDynamicParsingComplete(e),e.__importElement&&(e.__importElement.__importParsed=!0,this.markDynamicParsingComplete(e.__importElement)),this.parsingElement=null,c.parse&&console.log("completed",e)},markDynamicParsingComplete:function(e){var t=this.dynamicElements.indexOf(e);t>=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,r=function(o){e.removeEventListener("load",r),e.removeEventListener("error",r),t&&t(o),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",r),e.addEventListener("error",r),l&&"style"===e.localName){var o=!1;if(-1==e.textContent.indexOf("@import"))o=!0;else if(e.sheet){o=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;s>c&&(i=a[c]);c++)i.type===CSSRule.IMPORT_RULE&&(o=o&&Boolean(i.styleSheet))}o&&setTimeout(function(){e.dispatchEvent(new CustomEvent("load",{bubbles:!1}))})}},parseScript:function(t){var r=document.createElement("script");r.__importElement=t,r.src=t.src?t.src:n(t),e.currentScript=t,this.trackElement(r,function(t){r.parentNode&&r.parentNode.removeChild(r),e.currentScript=null}),this.addElementToDocument(r)},nextToParse:function(){return this._mayParse=[],!this.parsingElement&&(this.nextToParseInDoc(s)||this.nextToParseDynamic())},nextToParseInDoc:function(e,n){if(e&&this._mayParse.indexOf(e)<0){this._mayParse.push(e);for(var r,o=e.querySelectorAll(this.parseSelectorsForNode(e)),i=0,a=o.length;a>i&&(r=o[i]);i++)if(!this.isParsed(r))return this.hasResource(r)?t(r)?this.nextToParseInDoc(r.__doc,r):r:void 0}return n},nextToParseDynamic:function(){return this.dynamicElements[0]},parseSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===s?this.documentSelectors:this.importsSelectors},isParsed:function(e){return e.__importParsed},needsDynamicParsing:function(e){return this.dynamicElements.indexOf(e)>=0},hasResource:function(e){return t(e)&&void 0===e.__doc?!1:!0}};e.parser=p,e.IMPORT_SELECTOR=d}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function r(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function o(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var o=n.createElement("base");o.setAttribute("href",t),n.baseURI||r(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(o),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,l=e.Loader,u=e.Observer,d=e.parser,p={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){h.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);h.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,r,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=r,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:o(r,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}d.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),d.parseNext()},loadedAll:function(){d.parseNext()}},h=new l(p.loaded.bind(p),p.loadedAll.bind(p));if(p.observer=new u,!document.baseURI){var f={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",f),Object.defineProperty(c,"baseURI",f)}e.importer=p,e.importLoader=h}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,r={added:function(e){for(var r,o,i,a,s=0,c=e.length;c>s&&(a=e[s]);s++)r||(r=a.ownerDocument,o=t.isParsed(r)),i=this.shouldLoadNode(a),i&&n.loadNode(a),this.shouldParseNode(a)&&o&&t.parseDynamic(a,i)},shouldLoadNode:function(e){return 1===e.nodeType&&o.call(e,n.loadSelectorsForNode(e))},shouldParseNode:function(e){return 1===e.nodeType&&o.call(e,t.parseSelectorsForNode(e))}};n.observer.addCallback=r.added.bind(r);var o=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector}),function(e){function t(){window.HTMLImports.importer.bootDocument(r)}var n=e.initializeModules;e.isIE;if(!e.useNative){n();var r=e.rootDocument;"complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?t():document.addEventListener("DOMContentLoaded",t)}}(window.HTMLImports),window.CustomElements=window.CustomElements||{flags:{}},function(e){var t=e.flags,n=[],r=function(e){n.push(e)},o=function(){n.forEach(function(t){t(e)})};e.addModule=r,e.initializeModules=o,e.hasNative=Boolean(document.registerElement),e.isIE=/Trident/.test(navigator.userAgent),e.useNative=!t.register&&e.hasNative&&!window.ShadowDOMPolyfill&&(!window.HTMLImports||window.HTMLImports.useNative)}(window.CustomElements),window.CustomElements.addModule(function(e){function t(e,t){n(e,function(e){return t(e)?!0:void r(e,t)}),r(e,t)}function n(e,t,r){var o=e.firstElementChild;if(!o)for(o=e.firstChild;o&&o.nodeType!==Node.ELEMENT_NODE;)o=o.nextSibling;for(;o;)t(o,r)!==!0&&n(o,t,r),o=o.nextElementSibling;return null}function r(e,n){for(var r=e.shadowRoot;r;)t(r,n),r=r.olderShadowRoot}function o(e,t){i(e,t,[])}function i(e,t,n){if(e=window.wrap(e),!(n.indexOf(e)>=0)){n.push(e);for(var r,o=e.querySelectorAll("link[rel="+a+"]"),s=0,c=o.length;c>s&&(r=o[s]);s++)r["import"]&&i(r["import"],t,n);t(e)}}var a=window.HTMLImports?window.HTMLImports.IMPORT_LINK_TYPE:"none";e.forDocumentTree=o,e.forSubtree=t}),window.CustomElements.addModule(function(e){function t(e,t){return n(e,t)||r(e,t)}function n(t,n){return e.upgrade(t,n)?!0:void(n&&a(t))}function r(e,t){b(e,function(e){return n(e,t)?!0:void 0})}function o(e){S.push(e),_||(_=!0,setTimeout(i))}function i(){_=!1;for(var e,t=S,n=0,r=t.length;r>n&&(e=t[n]);n++)e();S=[]}function a(e){E?o(function(){s(e)}):s(e)}function s(e){e.__upgraded__&&!e.__attached&&(e.__attached=!0,e.attachedCallback&&e.attachedCallback())}function c(e){l(e),b(e,function(e){l(e)})}function l(e){E?o(function(){u(e)}):u(e)}function u(e){e.__upgraded__&&e.__attached&&(e.__attached=!1,e.detachedCallback&&e.detachedCallback())}function d(e){for(var t=e,n=window.wrap(document);t;){if(t==n)return!0;t=t.parentNode||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&t.host}}function p(e){if(e.shadowRoot&&!e.shadowRoot.__watched){g.dom&&console.log("watching shadow-root for: ",e.localName);for(var t=e.shadowRoot;t;)m(t),t=t.olderShadowRoot}}function h(e,n){if(g.dom){var r=n[0];if(r&&"childList"===r.type&&r.addedNodes&&r.addedNodes){for(var o=r.addedNodes[0];o&&o!==document&&!o.host;)o=o.parentNode;var i=o&&(o.URL||o._URL||o.host&&o.host.localName)||"";i=i.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",n.length,i||"")}var a=d(e);n.forEach(function(e){"childList"===e.type&&(T(e.addedNodes,function(e){e.localName&&t(e,a)}),T(e.removedNodes,function(e){e.localName&&c(e)}))}),g.dom&&console.groupEnd()}function f(e){for(e=window.wrap(e),e||(e=window.wrap(document));e.parentNode;)e=e.parentNode;var t=e.__observer;t&&(h(e,t.takeRecords()),i())}function m(e){if(!e.__observer){var t=new MutationObserver(h.bind(this,e));t.observe(e,{childList:!0,subtree:!0}),e.__observer=t}}function w(e){e=window.wrap(e),g.dom&&console.group("upgradeDocument: ",e.baseURI.split("/").pop());var n=e===window.wrap(document);t(e,n),m(e),g.dom&&console.groupEnd()}function v(e){y(e,w)}var g=e.flags,b=e.forSubtree,y=e.forDocumentTree,E=window.MutationObserver._isPolyfilled&&g["throttle-attached"];e.hasPolyfillMutations=E,e.hasThrottledAttached=E;var _=!1,S=[],T=Array.prototype.forEach.call.bind(Array.prototype.forEach),M=Element.prototype.createShadowRoot;M&&(Element.prototype.createShadowRoot=function(){var e=M.call(this);return window.CustomElements.watchShadow(this),e}),e.watchShadow=p,e.upgradeDocumentTree=v,e.upgradeDocument=w,e.upgradeSubtree=r,e.upgradeAll=t,e.attached=a,e.takeRecords=f}),window.CustomElements.addModule(function(e){function t(t,r){if("template"===t.localName&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t),!t.__upgraded__&&t.nodeType===Node.ELEMENT_NODE){var o=t.getAttribute("is"),i=e.getRegisteredDefinition(t.localName)||e.getRegisteredDefinition(o);if(i&&(o&&i.tag==t.localName||!o&&!i["extends"]))return n(t,i,r)}}function n(t,n,o){return a.upgrade&&console.group("upgrade:",t.localName),n.is&&t.setAttribute("is",n.is),r(t,n),t.__upgraded__=!0,i(t),o&&e.attached(t),e.upgradeSubtree(t,o),a.upgrade&&console.groupEnd(),t}function r(e,t){Object.__proto__?e.__proto__=t.prototype:(o(e,t.prototype,t["native"]),e.__proto__=t.prototype)}function o(e,t,n){for(var r={},o=t;o!==n&&o!==HTMLElement.prototype;){for(var i,a=Object.getOwnPropertyNames(o),s=0;i=a[s];s++)r[i]||(Object.defineProperty(e,i,Object.getOwnPropertyDescriptor(o,i)),r[i]=1);o=Object.getPrototypeOf(o)}}function i(e){e.createdCallback&&e.createdCallback()}var a=e.flags;e.upgrade=t,e.upgradeWithDefinition=n,e.implementPrototype=r}),window.CustomElements.addModule(function(e){function t(t,r){var c=r||{};if(!t)throw new Error("document.registerElement: first argument `name` must not be empty");if(t.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(t)+"'.");if(o(t))throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '"+String(t)+"'. The type name is invalid.");if(l(t))throw new Error("DuplicateDefinitionError: a type with name '"+String(t)+"' is already registered");return c.prototype||(c.prototype=Object.create(HTMLElement.prototype)),c.__name=t.toLowerCase(),c.lifecycle=c.lifecycle||{},c.ancestry=i(c["extends"]),a(c),s(c),n(c.prototype),u(c.__name,c),c.ctor=d(c),c.ctor.prototype=c.prototype,c.prototype.constructor=c.ctor,e.ready&&v(document),c.ctor}function n(e){if(!e.setAttribute._polyfilled){var t=e.setAttribute;e.setAttribute=function(e,n){r.call(this,e,n,t)};var n=e.removeAttribute;e.removeAttribute=function(e){r.call(this,e,null,n)},e.setAttribute._polyfilled=!0}}function r(e,t,n){e=e.toLowerCase();var r=this.getAttribute(e);n.apply(this,arguments);var o=this.getAttribute(e);this.attributeChangedCallback&&o!==r&&this.attributeChangedCallback(e,r,o)}function o(e){for(var t=0;t<_.length;t++)if(e===_[t])return!0}function i(e){var t=l(e);return t?i(t["extends"]).concat([t]):[]}function a(e){for(var t,n=e["extends"],r=0;t=e.ancestry[r];r++)n=t.is&&t.tag;e.tag=n||e.__name,n&&(e.is=e.__name)}function s(e){if(!Object.__proto__){var t=HTMLElement.prototype;if(e.is){var n=document.createElement(e.tag);t=Object.getPrototypeOf(n)}for(var r,o=e.prototype,i=!1;o;)o==t&&(i=!0),r=Object.getPrototypeOf(o),r&&(o.__proto__=r),o=r;i||console.warn(e.tag+" prototype not found in prototype chain for "+e.is),e["native"]=t}}function c(e){return b(M(e.tag),e)}function l(e){return e?S[e.toLowerCase()]:void 0}function u(e,t){S[e]=t}function d(e){return function(){return c(e)}}function p(e,t,n){return e===T?h(t,n):O(e,t)}function h(e,t){e&&(e=e.toLowerCase()),t&&(t=t.toLowerCase());var n=l(t||e);if(n){if(e==n.tag&&t==n.is)return new n.ctor;if(!t&&!n.is)return new n.ctor}var r;return t?(r=h(e),r.setAttribute("is",t),r):(r=M(e),e.indexOf("-")>=0&&y(r,HTMLElement),r)}function f(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return g(e),e}}var m,w=e.isIE,v=e.upgradeDocumentTree,g=e.upgradeAll,b=e.upgradeWithDefinition,y=e.implementPrototype,E=e.useNative,_=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],S={},T="http://www.w3.org/1999/xhtml",M=document.createElement.bind(document),O=document.createElementNS.bind(document);m=Object.__proto__||E?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},f(Node.prototype,"cloneNode"),f(document,"importNode"),w&&!function(){var e=document.importNode;document.importNode=function(){var t=e.apply(document,arguments);if(t.nodeType==t.DOCUMENT_FRAGMENT_NODE){var n=document.createDocumentFragment();return n.appendChild(t),n}return t}}(),document.registerElement=t,document.createElement=h,document.createElementNS=p,e.registry=S,e["instanceof"]=m,e.reservedTagList=_,e.getRegisteredDefinition=l,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,r=e.initializeModules;e.isIE;if(n){var o=function(){};e.watchShadow=o,e.upgrade=o,e.upgradeAll=o,e.upgradeDocumentTree=o,e.upgradeSubtree=o,e.takeRecords=o,e["instanceof"]=function(e,t){return e instanceof t}}else r();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){Function.prototype.bind||(Function.prototype.bind=function(e){var t=this,n=Array.prototype.slice.call(arguments,1);return function(){var r=n.slice();return r.push.apply(r,arguments),t.apply(e,r)}})}(window.WebComponents),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents),function(e){window.Platform=e}(window.WebComponents);</script> | |
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css"> | |
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script> | |
<title></title> | |
<style> | |
html, body, #full{ | |
width: 100%; | |
height: 100%; | |
margin: 0px; | |
padding: 0px; | |
} | |
</style> | |
<!-- Bootstrap --> | |
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | |
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> | |
<!--[if lt IE 9]> | |
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> | |
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> | |
<![endif]--> | |
</head> | |
<body><div hidden="" by-vulcanize=""><dom-module id="paper-menu-shared-styles" assetpath="bower_components/paper-menu/"> | |
<template> | |
<style> | |
/* need a wrapper element to make this higher specificity than the :host rule in paper-item */ | |
.selectable-content > ::content > .iron-selected { | |
font-weight: bold; | |
@apply(--paper-menu-selected-item); | |
} | |
.selectable-content > ::content > [disabled] { | |
color: var(--paper-menu-disabled-color, --disabled-text-color); | |
} | |
.selectable-content > ::content > *:focus { | |
position: relative; | |
outline: 0; | |
@apply(--paper-menu-focused-item); | |
} | |
.selectable-content > ::content > *:focus:after { | |
@apply(--layout-fit); | |
background: currentColor; | |
opacity: var(--dark-divider-opacity); | |
content: ''; | |
@apply(--paper-menu-focused-item-after); | |
} | |
.selectable-content > ::content > *[colored]:focus:after { | |
opacity: 0.26; | |
} | |
</style> | |
</template> | |
</dom-module> | |
<dom-module id="paper-menu" assetpath="bower_components/paper-menu/"> | |
<template> | |
<style include="paper-menu-shared-styles"></style> | |
<style> | |
:host { | |
display: block; | |
padding: 8px 0; | |
background: var(--paper-menu-background-color, --primary-background-color); | |
color: var(--paper-menu-color, --primary-text-color); | |
@apply(--paper-menu); | |
} | |
</style> | |
<div class="selectable-content"> | |
<content></content> | |
</div> | |
</template> | |
<script> | |
(function() { | |
Polymer({ | |
is: 'paper-menu', | |
behaviors: [ | |
Polymer.IronMenuBehavior | |
] | |
}); | |
})(); | |
</script> | |
</dom-module> | |
<dom-module id="paper-item-shared-styles" assetpath="bower_components/paper-item/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
position: relative; | |
min-height: var(--paper-item-min-height, 48px); | |
padding: 0px 16px; | |
} | |
:host([hidden]) { | |
display: none !important; | |
} | |
:host(.iron-selected) { | |
font-weight: var(--paper-item-selected-weight, bold); | |
@apply(--paper-item-selected); | |
} | |
:host([disabled]) { | |
color: var(--paper-item-disabled-color, --disabled-text-color); | |
@apply(--paper-item-disabled); | |
} | |
:host(:focus) { | |
position: relative; | |
outline: 0; | |
@apply(--paper-item-focused); | |
} | |
:host(:focus):before { | |
@apply(--layout-fit); | |
background: currentColor; | |
content: ''; | |
opacity: var(--dark-divider-opacity); | |
pointer-events: none; | |
@apply(--paper-item-focused-before); | |
} | |
</style> | |
</template> | |
</dom-module> | |
<dom-module id="paper-item" assetpath="bower_components/paper-item/"> | |
<template> | |
<style include="paper-item-shared-styles"></style> | |
<style> | |
:host { | |
@apply(--layout-horizontal); | |
@apply(--layout-center); | |
@apply(--paper-font-subhead); | |
@apply(--paper-item); | |
} | |
</style> | |
<content></content> | |
</template> | |
<script> | |
Polymer({ | |
is: 'paper-item', | |
behaviors: [ | |
Polymer.PaperItemBehavior | |
] | |
}); | |
</script> | |
</dom-module> | |
<dom-module id="paper-input-char-counter" assetpath="bower_components/paper-input/"> | |
<template> | |
<style> | |
:host { | |
display: inline-block; | |
float: right; | |
@apply(--paper-font-caption); | |
@apply(--paper-input-char-counter); | |
} | |
:host-context([dir="rtl"]) { | |
float: left; | |
} | |
</style> | |
<span>[[_charCounterStr]]</span> | |
</template> | |
</dom-module> | |
<script> | |
Polymer({ | |
is: 'paper-input-char-counter', | |
behaviors: [ | |
Polymer.PaperInputAddonBehavior | |
], | |
properties: { | |
_charCounterStr: { | |
type: String, | |
value: '0' | |
} | |
}, | |
update: function(state) { | |
if (!state.inputElement) { | |
return; | |
} | |
state.value = state.value || ''; | |
// Account for the textarea's new lines. | |
var str = state.value.replace(/(\r\n|\n|\r)/g, '--').length; | |
if (state.inputElement.hasAttribute('maxlength')) { | |
str += '/' + state.inputElement.getAttribute('maxlength'); | |
} | |
this._charCounterStr = str; | |
} | |
}); | |
</script> | |
<dom-module id="paper-input-container" assetpath="bower_components/paper-input/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
padding: 8px 0; | |
@apply(--paper-input-container); | |
} | |
:host[inline] { | |
display: inline-block; | |
} | |
:host([disabled]) { | |
pointer-events: none; | |
opacity: 0.33; | |
@apply(--paper-input-container-disabled); | |
} | |
.floated-label-placeholder { | |
@apply(--paper-font-caption); | |
} | |
.underline { | |
position: relative; | |
} | |
.focused-line { | |
@apply(--layout-fit); | |
background: var(--paper-input-container-focus-color, --default-primary-color); | |
height: 2px; | |
-webkit-transform-origin: center center; | |
transform-origin: center center; | |
-webkit-transform: scale3d(0,1,1); | |
transform: scale3d(0,1,1); | |
@apply(--paper-input-container-underline-focus); | |
} | |
.underline.is-highlighted .focused-line { | |
-webkit-transform: none; | |
transform: none; | |
-webkit-transition: -webkit-transform 0.25s; | |
transition: transform 0.25s; | |
@apply(--paper-transition-easing); | |
} | |
.underline.is-invalid .focused-line { | |
background: var(--paper-input-container-invalid-color, --google-red-500); | |
-webkit-transform: none; | |
transform: none; | |
-webkit-transition: -webkit-transform 0.25s; | |
transition: transform 0.25s; | |
@apply(--paper-transition-easing); | |
} | |
.unfocused-line { | |
@apply(--layout-fit); | |
height: 1px; | |
background: var(--paper-input-container-color, --secondary-text-color); | |
@apply(--paper-input-container-underline); | |
} | |
:host([disabled]) .unfocused-line { | |
border-bottom: 1px dashed; | |
border-color: var(--paper-input-container-color, --secondary-text-color); | |
background: transparent; | |
@apply(--paper-input-container-underline-disabled); | |
} | |
.label-and-input-container { | |
@apply(--layout-flex-auto); | |
@apply(--layout-relative); | |
width: 100%; | |
max-width: 100%; | |
} | |
.input-content { | |
@apply(--layout-horizontal); | |
@apply(--layout-center); | |
position: relative; | |
} | |
.input-content ::content label, | |
.input-content ::content .paper-input-label { | |
position: absolute; | |
top: 0; | |
right: 0; | |
left: 0; | |
width: 100%; | |
font: inherit; | |
color: var(--paper-input-container-color, --secondary-text-color); | |
@apply(--paper-font-common-nowrap); | |
@apply(--paper-font-subhead); | |
@apply(--paper-input-container-label); | |
} | |
.input-content.label-is-floating ::content label, | |
.input-content.label-is-floating ::content .paper-input-label { | |
-webkit-transform: translateY(-75%) scale(0.75); | |
transform: translateY(-75%) scale(0.75); | |
-webkit-transition: -webkit-transform 0.25s, width 0.25s; | |
transition: transform 0.25s, width 0.25s; | |
-webkit-transform-origin: left top; | |
transform-origin: left top; | |
/* Since we scale to 75/100 of the size, we actually have 100/75 of the | |
original space now available */ | |
width: 133%; | |
@apply(--paper-transition-easing); | |
@apply(--paper-input-container-label-floating); | |
} | |
:host-context([dir="rtl"]) .input-content.label-is-floating ::content label, | |
:host-context([dir="rtl"]) .input-content.label-is-floating ::content .paper-input-label { | |
/* TODO(noms): Figure out why leaving the width at 133% before the animation | |
* actually makes | |
* it wider on the right side, not left side, as you would expect in RTL */ | |
width: 100%; | |
-webkit-transform-origin: right top; | |
transform-origin: right top; | |
} | |
.input-content.label-is-highlighted ::content label, | |
.input-content.label-is-highlighted ::content .paper-input-label { | |
color: var(--paper-input-container-focus-color, --default-primary-color); | |
@apply(--paper-input-container-label-focus); | |
} | |
.input-content.is-invalid ::content label, | |
.input-content.is-invalid ::content .paper-input-label { | |
color: var(--paper-input-container-invalid-color, --google-red-500); | |
} | |
.input-content.label-is-hidden ::content label, | |
.input-content.label-is-hidden ::content .paper-input-label { | |
visibility: hidden; | |
} | |
.input-content ::content input, | |
.input-content ::content textarea, | |
.input-content ::content iron-autogrow-textarea, | |
.input-content ::content .paper-input-input { | |
position: relative; /* to make a stacking context */ | |
outline: none; | |
box-shadow: none; | |
padding: 0; | |
width: 100%; | |
max-width: 100%; | |
background: transparent; | |
border: none; | |
color: var(--paper-input-container-input-color, --primary-text-color); | |
-webkit-appearance: none; | |
text-align: inherit; | |
@apply(--paper-font-subhead); | |
@apply(--paper-input-container-input); | |
} | |
::content [prefix] { | |
@apply(--paper-font-subhead); | |
@apply(--paper-input-prefix); | |
@apply(--layout-flex-none); | |
} | |
::content [suffix] { | |
@apply(--paper-font-subhead); | |
@apply(--paper-input-suffix); | |
@apply(--layout-flex-none); | |
} | |
/* Firefox sets a min-width on the input, which can cause layout issues */ | |
.input-content ::content input { | |
min-width: 0; | |
} | |
.input-content ::content textarea { | |
resize: none; | |
} | |
.add-on-content { | |
position: relative; | |
} | |
.add-on-content.is-invalid ::content * { | |
color: var(--paper-input-container-invalid-color, --google-red-500); | |
} | |
.add-on-content.is-highlighted ::content * { | |
color: var(--paper-input-container-focus-color, --default-primary-color); | |
} | |
</style> | |
<template is="dom-if" if="[[!noLabelFloat]]"> | |
<div class="floated-label-placeholder"> </div> | |
</template> | |
<div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]"> | |
<content select="[prefix]" id="prefix"></content> | |
<div class="label-and-input-container" id="labelAndInputContainer"> | |
<content select=":not([add-on]):not([prefix]):not([suffix])"></content> | |
</div> | |
<content select="[suffix]"></content> | |
</div> | |
<div class$="[[_computeUnderlineClass(focused,invalid)]]"> | |
<div class="unfocused-line"></div> | |
<div class="focused-line"></div> | |
</div> | |
<div class$="[[_computeAddOnContentClass(focused,invalid)]]"> | |
<content id="addOnContent" select="[add-on]"></content> | |
</div> | |
</template> | |
</dom-module> | |
<script> | |
Polymer({ | |
is: 'paper-input-container', | |
properties: { | |
/** | |
* Set to true to disable the floating label. The label disappears when the input value is | |
* not null. | |
*/ | |
noLabelFloat: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* Set to true to always float the floating label. | |
*/ | |
alwaysFloatLabel: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* The attribute to listen for value changes on. | |
*/ | |
attrForValue: { | |
type: String, | |
value: 'bind-value' | |
}, | |
/** | |
* Set to true to auto-validate the input value when it changes. | |
*/ | |
autoValidate: { | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* True if the input is invalid. This property is set automatically when the input value | |
* changes if auto-validating, or when the `iron-input-validate` event is heard from a child. | |
*/ | |
invalid: { | |
observer: '_invalidChanged', | |
type: Boolean, | |
value: false | |
}, | |
/** | |
* True if the input has focus. | |
*/ | |
focused: { | |
readOnly: true, | |
type: Boolean, | |
value: false, | |
notify: true | |
}, | |
_addons: { | |
type: Array | |
// do not set a default value here intentionally - it will be initialized lazily when a | |
// distributed child is attached, which may occur before configuration for this element | |
// in polyfill. | |
}, | |
_inputHasContent: { | |
type: Boolean, | |
value: false | |
}, | |
_inputSelector: { | |
type: String, | |
value: 'input,textarea,.paper-input-input' | |
}, | |
_boundOnFocus: { | |
type: Function, | |
value: function() { | |
return this._onFocus.bind(this); | |
} | |
}, | |
_boundOnBlur: { | |
type: Function, | |
value: function() { | |
return this._onBlur.bind(this); | |
} | |
}, | |
_boundOnInput: { | |
type: Function, | |
value: function() { | |
return this._onInput.bind(this); | |
} | |
}, | |
_boundValueChanged: { | |
type: Function, | |
value: function() { | |
return this._onValueChanged.bind(this); | |
} | |
} | |
}, | |
listeners: { | |
'addon-attached': '_onAddonAttached', | |
'iron-input-validate': '_onIronInputValidate' | |
}, | |
get _valueChangedEvent() { | |
return this.attrForValue + '-changed'; | |
}, | |
get _propertyForValue() { | |
return Polymer.CaseMap.dashToCamelCase(this.attrForValue); | |
}, | |
get _inputElement() { | |
return Polymer.dom(this).querySelector(this._inputSelector); | |
}, | |
get _inputElementValue() { | |
return this._inputElement[this._propertyForValue] || this._inputElement.value; | |
}, | |
ready: function() { | |
if (!this._addons) { | |
this._addons = []; | |
} | |
this.addEventListener('focus', this._boundOnFocus, true); | |
this.addEventListener('blur', this._boundOnBlur, true); | |
if (this.attrForValue) { | |
this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged); | |
} else { | |
this.addEventListener('input', this._onInput); | |
} | |
}, | |
attached: function() { | |
// Only validate when attached if the input already has a value. | |
if (this._inputElementValue != '') { | |
this._handleValueAndAutoValidate(this._inputElement); | |
} else { | |
this._handleValue(this._inputElement); | |
} | |
}, | |
_onAddonAttached: function(event) { | |
if (!this._addons) { | |
this._addons = []; | |
} | |
var target = event.target; | |
if (this._addons.indexOf(target) === -1) { | |
this._addons.push(target); | |
if (this.isAttached) { | |
this._handleValue(this._inputElement); | |
} | |
} | |
}, | |
_onFocus: function() { | |
this._setFocused(true); | |
}, | |
_onBlur: function() { | |
this._setFocused(false); | |
this._handleValueAndAutoValidate(this._inputElement); | |
}, | |
_onInput: function(event) { | |
this._handleValueAndAutoValidate(event.target); | |
}, | |
_onValueChanged: function(event) { | |
this._handleValueAndAutoValidate(event.target); | |
}, | |
_handleValue: function(inputElement) { | |
var value = this._inputElementValue; | |
// type="number" hack needed because this.value is empty until it's valid | |
if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) { | |
this._inputHasContent = true; | |
} else { | |
this._inputHasContent = false; | |
} | |
this.updateAddons({ | |
inputElement: inputElement, | |
value: value, | |
invalid: this.invalid | |
}); | |
}, | |
_handleValueAndAutoValidate: function(inputElement) { | |
if (this.autoValidate) { | |
var valid; | |
if (inputElement.validate) { | |
valid = inputElement.validate(this._inputElementValue); | |
} else { | |
valid = inputElement.checkValidity(); | |
} | |
this.invalid = !valid; | |
} | |
// Call this last to notify the add-ons. | |
this._handleValue(inputElement); | |
}, | |
_onIronInputValidate: function(event) { | |
this.invalid = this._inputElement.invalid; | |
}, | |
_invalidChanged: function() { | |
if (this._addons) { | |
this.updateAddons({invalid: this.invalid}); | |
} | |
}, | |
/** | |
* Call this to update the state of add-ons. | |
* @param {Object} state Add-on state. | |
*/ | |
updateAddons: function(state) { | |
for (var addon, index = 0; addon = this._addons[index]; index++) { | |
addon.update(state); | |
} | |
}, | |
_computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) { | |
var cls = 'input-content'; | |
if (!noLabelFloat) { | |
var label = this.querySelector('label'); | |
if (alwaysFloatLabel || _inputHasContent) { | |
cls += ' label-is-floating'; | |
// If the label is floating, ignore any offsets that may have been | |
// applied from a prefix element. | |
this.$.labelAndInputContainer.style.position = 'static'; | |
if (invalid) { | |
cls += ' is-invalid'; | |
} else if (focused) { | |
cls += " label-is-highlighted"; | |
} | |
} else { | |
// When the label is not floating, it should overlap the input element. | |
if (label) { | |
this.$.labelAndInputContainer.style.position = 'relative'; | |
} | |
} | |
} else { | |
if (_inputHasContent) { | |
cls += ' label-is-hidden'; | |
} | |
} | |
return cls; | |
}, | |
_computeUnderlineClass: function(focused, invalid) { | |
var cls = 'underline'; | |
if (invalid) { | |
cls += ' is-invalid'; | |
} else if (focused) { | |
cls += ' is-highlighted' | |
} | |
return cls; | |
}, | |
_computeAddOnContentClass: function(focused, invalid) { | |
var cls = 'add-on-content'; | |
if (invalid) { | |
cls += ' is-invalid'; | |
} else if (focused) { | |
cls += ' is-highlighted' | |
} | |
return cls; | |
} | |
}); | |
</script> | |
<dom-module id="paper-input-error" assetpath="bower_components/paper-input/"> | |
<template> | |
<style> | |
:host { | |
display: inline-block; | |
visibility: hidden; | |
color: var(--paper-input-container-invalid-color, --google-red-500); | |
@apply(--paper-font-caption); | |
@apply(--paper-input-error); | |
position: absolute; | |
left:0; | |
right:0; | |
} | |
:host([invalid]) { | |
visibility: visible; | |
}; | |
</style> | |
<content></content> | |
</template> | |
</dom-module> | |
<script> | |
Polymer({ | |
is: 'paper-input-error', | |
behaviors: [ | |
Polymer.PaperInputAddonBehavior | |
], | |
properties: { | |
/** | |
* True if the error is showing. | |
*/ | |
invalid: { | |
readOnly: true, | |
reflectToAttribute: true, | |
type: Boolean | |
} | |
}, | |
update: function(state) { | |
this._setInvalid(state.invalid); | |
} | |
}); | |
</script> | |
<dom-module id="paper-input" assetpath="bower_components/paper-input/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
} | |
input::-webkit-input-placeholder { | |
color: var(--paper-input-container-color, --secondary-text-color); | |
} | |
input:-moz-placeholder { | |
color: var(--paper-input-container-color, --secondary-text-color); | |
} | |
input::-moz-placeholder { | |
color: var(--paper-input-container-color, --secondary-text-color); | |
} | |
input:-ms-input-placeholder { | |
color: var(--paper-input-container-color, --secondary-text-color); | |
} | |
</style> | |
<paper-input-container no-label-float="[[noLabelFloat]]" always-float-label="[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[autoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]"> | |
<content select="[prefix]"></content> | |
<label hidden$="[[!label]]">[[label]]</label> | |
<input is="iron-input" id="input" aria-labelledby$="[[_ariaLabelledBy]]" aria-describedby$="[[_ariaDescribedBy]]" disabled$="[[disabled]]" bind-value="{{value}}" invalid="{{invalid}}" prevent-invalid-input="[[preventInvalidInput]]" allowed-pattern="[[allowedPattern]]" validator="[[validator]]" type$="[[type]]" pattern$="[[pattern]]" required$="[[required]]" autocomplete$="[[autocomplete]]" autofocus$="[[autofocus]]" inputmode$="[[inputmode]]" minlength$="[[minlength]]" maxlength$="[[maxlength]]" min$="[[min]]" max$="[[max]]" step$="[[step]]" name$="[[name]]" placeholder$="[[placeholder]]" readonly$="[[readonly]]" list$="[[list]]" size$="[[size]]" autocapitalize$="[[autocapitalize]]" autocorrect$="[[autocorrect]]" on-change="_onChange" tabindex$="[[tabindex]]" autosave$="[[autosave]]" results$="[[results]]" accept$="[[accept]]" multiple$="[[multiple]]"> | |
<content select="[suffix]"></content> | |
<template is="dom-if" if="[[errorMessage]]"> | |
<paper-input-error>[[errorMessage]]</paper-input-error> | |
</template> | |
<template is="dom-if" if="[[charCounter]]"> | |
<paper-input-char-counter></paper-input-char-counter> | |
</template> | |
</paper-input-container> | |
</template> | |
</dom-module> | |
<script> | |
Polymer({ | |
is: 'paper-input', | |
behaviors: [ | |
Polymer.IronFormElementBehavior, | |
Polymer.PaperInputBehavior | |
] | |
}); | |
</script> | |
<dom-module id="carto-map" assetpath="components/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
} | |
#map{ | |
width: 100%; | |
height: 100%; | |
} | |
</style> | |
<div id="map"></div> | |
</template> | |
<script> | |
Polymer({ | |
is: '', | |
properties:{ | |
viz:{ | |
type: String, | |
value: null | |
}, | |
table:{ | |
type: String, | |
value: null, | |
notify: true | |
}, | |
user:{ | |
type: String, | |
value: null, | |
notify:true | |
}, | |
sql:{ | |
type: String, | |
value: null, | |
observer: 'updateSQL' | |
}, | |
css:{ | |
type: String, | |
value: null, | |
observer: 'updateCSS' | |
}, | |
center:{ | |
type: Array, | |
value: null, | |
observer: 'updateLocation' | |
}, | |
zoom:{ | |
type: Number, | |
value: null, | |
observer: 'updateLocation' | |
} | |
}, | |
ready:function(){ | |
this.settingMovement=false; | |
if(this.viz && this.user ){ | |
this.createVizMap() | |
} | |
else{ | |
this.createCustomMap() | |
} | |
}, | |
updateSQL:function(sql){ | |
data_layer = this.getDataLayer() | |
if(data_layer){data_layer.setSQL(sql)} | |
}, | |
updateCSS:function(){ | |
if(!this.css){return} | |
data_layer = this.getDataLayer() | |
if(data_layer){ | |
console.log("setting css", this.css) | |
data_layer.setCartoCSS(this.css) | |
} | |
else{ | |
setTimeout(this.updateCSS.bind(this), 200) | |
console.log("no data layer") | |
} | |
}, | |
getDataLayer:function(){ | |
if (this.layers){ | |
return this.layers.filter((l)=>l.type=='layergroup')[0] | |
} | |
else{ | |
return null | |
} | |
}, | |
createVizMap:function(){ | |
cartodb.createVis(this.$.map, `http://${this.user}.cartodb.com/api/v2/viz/${this.viz}/viz.json`).done(function(map,layers){ | |
this.map = map.getNativeMap() | |
this.layers = layers | |
this.map.on('move',this.mapMoved.bind(this)) | |
this.fire('mapLoaded') | |
}.bind(this)); | |
}, | |
updateLocation:function(loc){ | |
this.settingMovement =true | |
if(this.map){ | |
this.map.setView(loc.center, loc.zoom, {animate:false, reset:false}) | |
} | |
this.settingMovement = false | |
}, | |
mapMoved:function(loc,e){ | |
center = this.map.getCenter() | |
zoom = this.map.getZoom() | |
if(this.settingMovement==false){ | |
this.fire('moved',{center:center, zoom:zoom}) | |
} | |
} | |
}); | |
</script> | |
</dom-module> | |
<dom-module id="carto-css-continuious-color-ramp" assetpath="components/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
} | |
</style> | |
</template> | |
<script> | |
Polymer({ | |
is: 'carto-css-continuious-color-ramp', | |
properties:{ | |
css:{ | |
type: String, | |
notify:true | |
}, | |
cartoCSS:{ | |
computed: 'calculateCartoCSS(stops,colors,interpolation,steps,variable,table,property)', | |
notify: true | |
}, | |
stops:{ | |
type: Array, | |
value: [] | |
}, | |
colors:{ | |
type: Array, | |
value: [] | |
}, | |
interpolation:{ | |
type: String | |
}, | |
steps:{ | |
type: Number | |
}, | |
variable:{ | |
type: String | |
}, | |
table:{ | |
type: String | |
}, | |
property:{ | |
type: String | |
} | |
}, | |
getInterpolationFunction: function(name){ | |
return { hsl: d3.interpolateHsl, hcl: d3.interpolateHcl, lab: d3.interpolateLab, cubehelix: d3.interpolateCubehelix, rgb : d3.interpolateRgb }[name]; | |
}, | |
calculateCartoCSS:function(stops,colors,interpolation,stepsS,variable,table,property){ | |
console.log( "HERE", stops, colors,interpolation, stepsS,variable,table,property) | |
steps = parseInt(stepsS) | |
var stepsArray = Array.apply(null, Array(steps)).map((s,index)=> (index+1)*1.0/steps ) | |
var stopValues = Array.apply(null, Array(stops.length)).map((s,index)=> index*1.0/(stops.length-1) ) | |
valueRamp = d3.scale.linear().domain(stopValues).range(stops) | |
interpFunc = this.getInterpolationFunction(interpolation) | |
colorRamp = d3.scale.linear().domain(stops).range(colors).interpolate(interpFunc) | |
values = stepsArray.map((v) => valueRamp(v) ) | |
colorValues = values.map((c)=>colorRamp(c)) | |
values.reverse() | |
colorValues.reverse() | |
cssRules = colorValues.map((r,index)=> `[${variable} <= ${values[index]}] { ${property} : ${r}; }`).join("\n") | |
result = `#${table}{ | |
polygon-opacity: 1.0; | |
line-color: #FFF; | |
line-width: 0; | |
line-opacity: 1; | |
${cssRules} | |
}` | |
console.log(result) | |
this.css = result | |
return result | |
} | |
}); | |
</script> | |
</dom-module> | |
<dom-module id="carto-query" assetpath="components/"> | |
<script> | |
Polymer({ | |
is: 'carto-query', | |
properties:{ | |
user:{ | |
type: String | |
}, | |
query:{ | |
type: String | |
}, | |
key:{ | |
type: String | |
}, | |
url:{ | |
computed: 'generateURL(user,key, fullQuery)', | |
observer: 'queryChanged' | |
}, | |
auto:{ | |
type: Boolean, | |
value:true, | |
}, | |
result:{ | |
type: Array, | |
notify: true, | |
value: null | |
}, | |
status:{ | |
type: String, | |
notify: true, | |
value: "ready" | |
}, | |
bounds:{ | |
type: Array, | |
value: null | |
}, | |
fullQuery:{ | |
computed: 'buildQuery(query,bounds)', | |
notify: true | |
} | |
}, | |
queryChanged:function(){ | |
if(this.auto){ | |
this.run() | |
} | |
}, | |
buildQuery: function(query,bounds){ | |
if(bounds){ | |
return `select * from ( ${this.query} ) subq where subq.the_geom && ST_MakeEnvelope(${this.bounds[0][0]}, ${this.bounds[0][1]}, ${this.bounds[1][0]}, ${this.bounds[1][1]}, 4326)` | |
} | |
else{ | |
return `select * from ${this.query}` | |
} | |
}, | |
run:function(){ | |
this.status='runing' | |
fetch(this.url).then((result)=>result.json()).then((result)=> this.gotResult(result.rows)) | |
}, | |
gotResult:function(result){ | |
console.log("result is ", result) | |
this.result = result | |
this.status = 'ready' | |
}, | |
generateURL:function(user,key){ | |
if(this.user && this.query && this.key){ | |
return `https://${this.user}.cartodb.com/api/v2/sql?q=${this.query}&api_key=${key}` | |
} | |
else{ | |
return null | |
} | |
} | |
}); | |
</script> | |
</dom-module> | |
<dom-module id="carto-color-picker" assetpath="components/"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
width: 100%; | |
height: 100%; | |
} | |
.container{ | |
width:100%; | |
height:100%; | |
margin:0px; | |
padding: 0px; | |
position:relative; | |
} | |
#mapcontainer{ | |
height: 100%; | |
width:100%; | |
display:inline-block; | |
} | |
.map{ | |
height:100%; | |
width: 100%; | |
} | |
#controlls{ | |
position:absolute; | |
height: 100%; | |
width: 20%; | |
display:inline-block; | |
right:0px; | |
top:0px; | |
z-index:100; | |
background-color: rgba(255,255,255,0.9); | |
padding:20px | |
} | |
</style> | |
<div class="container"> | |
<div id="mapcontainer"> | |
<carto-map style="" class="map" viz="{{viz}}" css="{{css}}" user="{{user}}"></carto-map> | |
</div> | |
<div id="controlls"> | |
<paper-input value="{{viz}}" label="Viz id"></paper-input> | |
<paper-input value="{{stops_str}}" label="Stops : [0,2,3,4]"></paper-input> | |
<paper-input value="{{colors_str}}" label="colors: ['red', 'blue' ...]"></paper-input> | |
<paper-input value="{{steps}}" label="steps"></paper-input> | |
<paper-input value="{{table}}" label="table"></paper-input> | |
<paper-input value="{{user}}" label="user"></paper-input> | |
<paper-input value="{{variable}}" label="variable"></paper-input> | |
<paper-menu attr-for-selected="name" selected="{{interpolation}}"> | |
<paper-item name="hcl">HCL</paper-item> | |
<paper-item name="hsl">HSL</paper-item> | |
<paper-item name="lab">LAB</paper-item> | |
<paper-item name="cubehelix">CubeHelix</paper-item> | |
<paper-item name="rgb">RGB</paper-item> | |
</paper-menu> | |
</div> | |
</div> | |
<carto-css-continuious-color-ramp css="{{css}}" stops="{{stops}}" steps="{{steps}}" colors="{{colors}}" interpolation="{{interpolation}}" property="polygon-fill" variable="{{variable}}" table="{{table}}"> | |
</carto-css-continuious-color-ramp> | |
</template> | |
<script> | |
Polymer({ | |
is: '', | |
properties:{ | |
viz:{ | |
type: String, | |
value: "ed9a25d2-b96b-11e5-a0e3-0e5db1731f59" | |
}, | |
stops_str:{ | |
type:String, | |
value:'0,0.2,0.3,0.4,1' | |
}, | |
stops:{ | |
computed: 'slice(stops_str)', | |
type:Array | |
}, | |
colors:{ | |
computed: 'slice(colors_str)', | |
type:Array | |
}, | |
colors_str:{ | |
type:String, | |
value: '#FFFFFF,#B4D79D,#FBFDBA,#FBFCBA,#D7C19D,#CDAA63,#9FCEFD' | |
}, | |
interpolation:{ | |
type: String, | |
value: 'hcl' | |
}, | |
steps:{ | |
type :Number, | |
value: 100 | |
}, | |
user:{ | |
type:String, | |
value: 'stuartlynn' | |
}, | |
table:{ | |
type:String, | |
value:'uber_output_test_1' | |
}, | |
variable:{ | |
type: String, | |
value: 'prediction' | |
} | |
}, | |
observers:[ | |
'updateHash(steps,user,interpolation,colors_str,stops_str,viz)' | |
], | |
ready:function(){ | |
this.hashReady=false | |
this.parseHash() | |
}, | |
parseHash:function(){ | |
h = window.location.hash | |
console.log("HASH IS ", h) | |
h.slice(1,h.length-1).split("|").forEach(function(v){ | |
console.log("V is ", v) | |
p = v.split(":") | |
console.log("P is ", p) | |
this[p[0]]=p[1] | |
}.bind(this)) | |
this.hashReady=true | |
}, | |
updateHash:function(steps,user,interpolation,colors_str,stops_str,viz){ | |
if(this.hashReady){ | |
hash_str = `steps:${steps}|user:${user}|interpolation:${interpolation}|colors_str:${colors_str}|stops_str:${stops_str}|viz:${viz}` | |
window.location.hash=hash_str | |
} | |
}, | |
slice:function(str){ | |
return str.split(',') | |
} | |
}); | |
</script> | |
</dom-module> | |
</div> | |
<template id="t" is="dom-bind"> | |
<carto-color-picker id="full"></carto-color-picker> | |
</template> | |
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> | |
</body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment