xgraph-adapter/Tests/WebViewer/Static/bower_components/polymer/lib/legacy/legacy-element-mixin.html

1004 lines
35 KiB
HTML

<!--
@license
Copyright (c) 2017 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
-->
<link rel="import" href="../../../shadycss/apply-shim.html">
<link rel="import" href="../mixins/element-mixin.html">
<link rel="import" href="../mixins/gesture-event-listeners.html">
<link rel="import" href="../mixins/dir-mixin.html">
<link rel="import" href="../utils/mixin.html">
<link rel="import" href="../utils/import-href.html">
<link rel="import" href="../utils/render-status.html">
<link rel="import" href="../utils/unresolved.html">
<link rel="import" href="polymer.dom.html">
<script>
(function() {
'use strict';
let styleInterface = window.ShadyCSS;
/**
* Element class mixin that provides Polymer's "legacy" API intended to be
* backward-compatible to the greatest extent possible with the API
* found on the Polymer 1.x `Polymer.Base` prototype applied to all elements
* defined using the `Polymer({...})` function.
*
* @mixinFunction
* @polymer
* @appliesMixin Polymer.ElementMixin
* @appliesMixin Polymer.GestureEventListeners
* @property isAttached {boolean} Set to `true` in this element's
* `connectedCallback` and `false` in `disconnectedCallback`
* @memberof Polymer
* @summary Element class mixin that provides Polymer's "legacy" API
*/
Polymer.LegacyElementMixin = Polymer.dedupingMixin((base) => {
/**
* @constructor
* @extends {base}
* @implements {Polymer_ElementMixin}
* @implements {Polymer_GestureEventListeners}
* @implements {Polymer_DirMixin}
*/
const legacyElementBase = Polymer.DirMixin(Polymer.GestureEventListeners(Polymer.ElementMixin(base)));
/**
* Map of simple names to touch action names
* @dict
*/
const DIRECTION_MAP = {
'x': 'pan-x',
'y': 'pan-y',
'none': 'none',
'all': 'auto'
};
/**
* @polymer
* @mixinClass
* @extends {legacyElementBase}
* @implements {Polymer_LegacyElementMixin}
* @unrestricted
*/
class LegacyElement extends legacyElementBase {
constructor() {
super();
/** @type {boolean} */
this.isAttached;
/** @type {WeakMap<!Element, !Object<string, !Function>>} */
this.__boundListeners;
/** @type {Object<string, Function>} */
this._debouncers;
// Ensure listeners are applied immediately so that they are
// added before declarative event listeners. This allows an element to
// decorate itself via an event prior to any declarative listeners
// seeing the event. Note, this ensures compatibility with 1.x ordering.
this._applyListeners();
}
/**
* Legacy callback called during the `constructor`, for overriding
* by the user.
* @return {void}
*/
created() {}
/**
* Provides an implementation of `connectedCallback`
* which adds Polymer legacy API's `attached` method.
* @return {void}
* @override
*/
connectedCallback() {
super.connectedCallback();
this.isAttached = true;
this.attached();
}
/**
* Legacy callback called during `connectedCallback`, for overriding
* by the user.
* @return {void}
*/
attached() {}
/**
* Provides an implementation of `disconnectedCallback`
* which adds Polymer legacy API's `detached` method.
* @return {void}
* @override
*/
disconnectedCallback() {
super.disconnectedCallback();
this.isAttached = false;
this.detached();
}
/**
* Legacy callback called during `disconnectedCallback`, for overriding
* by the user.
* @return {void}
*/
detached() {}
/**
* Provides an override implementation of `attributeChangedCallback`
* which adds the Polymer legacy API's `attributeChanged` method.
* @param {string} name Name of attribute.
* @param {?string} old Old value of attribute.
* @param {?string} value Current value of attribute.
* @return {void}
* @override
*/
attributeChangedCallback(name, old, value) {
if (old !== value) {
super.attributeChangedCallback(name, old, value);
this.attributeChanged(name, old, value);
}
}
/**
* Legacy callback called during `attributeChangedChallback`, for overriding
* by the user.
* @param {string} name Name of attribute.
* @param {?string} old Old value of attribute.
* @param {?string} value Current value of attribute.
* @return {void}
*/
attributeChanged(name, old, value) {} // eslint-disable-line no-unused-vars
/**
* Overrides the default `Polymer.PropertyEffects` implementation to
* add support for class initialization via the `_registered` callback.
* This is called only when the first instance of the element is created.
*
* @return {void}
* @override
* @suppress {invalidCasts}
*/
_initializeProperties() {
let proto = Object.getPrototypeOf(this);
if (!proto.hasOwnProperty('__hasRegisterFinished')) {
proto.__hasRegisterFinished = true;
this._registered();
}
super._initializeProperties();
this.root = /** @type {HTMLElement} */(this);
this.created();
}
/**
* Called automatically when an element is initializing.
* Users may override this method to perform class registration time
* work. The implementation should ensure the work is performed
* only once for the class.
* @protected
* @return {void}
*/
_registered() {}
/**
* Overrides the default `Polymer.PropertyEffects` implementation to
* add support for installing `hostAttributes` and `listeners`.
*
* @return {void}
* @override
*/
ready() {
this._ensureAttributes();
super.ready();
}
/**
* Ensures an element has required attributes. Called when the element
* is being readied via `ready`. Users should override to set the
* element's required attributes. The implementation should be sure
* to check and not override existing attributes added by
* the user of the element. Typically, setting attributes should be left
* to the element user and not done here; reasonable exceptions include
* setting aria roles and focusability.
* @protected
* @return {void}
*/
_ensureAttributes() {}
/**
* Adds element event listeners. Called when the element
* is being readied via `ready`. Users should override to
* add any required element event listeners.
* In performance critical elements, the work done here should be kept
* to a minimum since it is done before the element is rendered. In
* these elements, consider adding listeners asynchronously so as not to
* block render.
* @protected
* @return {void}
*/
_applyListeners() {}
/**
* Converts a typed JavaScript value to a string.
*
* Note this method is provided as backward-compatible legacy API
* only. It is not directly called by any Polymer features. To customize
* how properties are serialized to attributes for attribute bindings and
* `reflectToAttribute: true` properties as well as this method, override
* the `_serializeValue` method provided by `Polymer.PropertyAccessors`.
*
* @param {*} value Value to deserialize
* @return {string | undefined} Serialized value
*/
serialize(value) {
return this._serializeValue(value);
}
/**
* Converts a string to a typed JavaScript value.
*
* Note this method is provided as backward-compatible legacy API
* only. It is not directly called by any Polymer features. To customize
* how attributes are deserialized to properties for in
* `attributeChangedCallback`, override `_deserializeValue` method
* provided by `Polymer.PropertyAccessors`.
*
* @param {string} value String to deserialize
* @param {*} type Type to deserialize the string to
* @return {*} Returns the deserialized value in the `type` given.
*/
deserialize(value, type) {
return this._deserializeValue(value, type);
}
/**
* Serializes a property to its associated attribute.
*
* Note this method is provided as backward-compatible legacy API
* only. It is not directly called by any Polymer features.
*
* @param {string} property Property name to reflect.
* @param {string=} attribute Attribute name to reflect.
* @param {*=} value Property value to reflect.
* @return {void}
*/
reflectPropertyToAttribute(property, attribute, value) {
this._propertyToAttribute(property, attribute, value);
}
/**
* Sets a typed value to an HTML attribute on a node.
*
* Note this method is provided as backward-compatible legacy API
* only. It is not directly called by any Polymer features.
*
* @param {*} value Value to serialize.
* @param {string} attribute Attribute name to serialize to.
* @param {Element} node Element to set attribute to.
* @return {void}
*/
serializeValueToAttribute(value, attribute, node) {
this._valueToNodeAttribute(/** @type {Element} */ (node || this), value, attribute);
}
/**
* Copies own properties (including accessor descriptors) from a source
* object to a target object.
*
* @param {Object} prototype Target object to copy properties to.
* @param {Object} api Source object to copy properties from.
* @return {Object} prototype object that was passed as first argument.
*/
extend(prototype, api) {
if (!(prototype && api)) {
return prototype || api;
}
let n$ = Object.getOwnPropertyNames(api);
for (let i=0, n; (i<n$.length) && (n=n$[i]); i++) {
let pd = Object.getOwnPropertyDescriptor(api, n);
if (pd) {
Object.defineProperty(prototype, n, pd);
}
}
return prototype;
}
/**
* Copies props from a source object to a target object.
*
* Note, this method uses a simple `for...in` strategy for enumerating
* properties. To ensure only `ownProperties` are copied from source
* to target and that accessor implementations are copied, use `extend`.
*
* @param {!Object} target Target object to copy properties to.
* @param {!Object} source Source object to copy properties from.
* @return {!Object} Target object that was passed as first argument.
*/
mixin(target, source) {
for (let i in source) {
target[i] = source[i];
}
return target;
}
/**
* Sets the prototype of an object.
*
* Note this method is provided as backward-compatible legacy API
* only. It is not directly called by any Polymer features.
* @param {Object} object The object on which to set the prototype.
* @param {Object} prototype The prototype that will be set on the given
* `object`.
* @return {Object} Returns the given `object` with its prototype set
* to the given `prototype` object.
*/
chainObject(object, prototype) {
if (object && prototype && object !== prototype) {
object.__proto__ = prototype;
}
return object;
}
/* **** Begin Template **** */
/**
* Calls `importNode` on the `content` of the `template` specified and
* returns a document fragment containing the imported content.
*
* @param {HTMLTemplateElement} template HTML template element to instance.
* @return {!DocumentFragment} Document fragment containing the imported
* template content.
*/
instanceTemplate(template) {
let content = this.constructor._contentForTemplate(template);
let dom = /** @type {!DocumentFragment} */
(document.importNode(content, true));
return dom;
}
/* **** Begin Events **** */
/**
* Dispatches a custom event with an optional detail value.
*
* @param {string} type Name of event type.
* @param {*=} detail Detail value containing event-specific
* payload.
* @param {{ bubbles: (boolean|undefined), cancelable: (boolean|undefined), composed: (boolean|undefined) }=}
* options Object specifying options. These may include:
* `bubbles` (boolean, defaults to `true`),
* `cancelable` (boolean, defaults to false), and
* `node` on which to fire the event (HTMLElement, defaults to `this`).
* @return {!Event} The new event that was fired.
*/
fire(type, detail, options) {
options = options || {};
detail = (detail === null || detail === undefined) ? {} : detail;
let event = new Event(type, {
bubbles: options.bubbles === undefined ? true : options.bubbles,
cancelable: Boolean(options.cancelable),
composed: options.composed === undefined ? true: options.composed
});
event.detail = detail;
let node = options.node || this;
node.dispatchEvent(event);
return event;
}
/**
* Convenience method to add an event listener on a given element,
* late bound to a named method on this element.
*
* @param {Element} node Element to add event listener to.
* @param {string} eventName Name of event to listen for.
* @param {string} methodName Name of handler method on `this` to call.
* @return {void}
*/
listen(node, eventName, methodName) {
node = /** @type {!Element} */ (node || this);
let hbl = this.__boundListeners ||
(this.__boundListeners = new WeakMap());
let bl = hbl.get(node);
if (!bl) {
bl = {};
hbl.set(node, bl);
}
let key = eventName + methodName;
if (!bl[key]) {
bl[key] = this._addMethodEventListenerToNode(
node, eventName, methodName, this);
}
}
/**
* Convenience method to remove an event listener from a given element,
* late bound to a named method on this element.
*
* @param {Element} node Element to remove event listener from.
* @param {string} eventName Name of event to stop listening to.
* @param {string} methodName Name of handler method on `this` to not call
anymore.
* @return {void}
*/
unlisten(node, eventName, methodName) {
node = /** @type {!Element} */ (node || this);
let bl = this.__boundListeners && this.__boundListeners.get(node);
let key = eventName + methodName;
let handler = bl && bl[key];
if (handler) {
this._removeEventListenerFromNode(node, eventName, handler);
bl[key] = null;
}
}
/**
* Override scrolling behavior to all direction, one direction, or none.
*
* Valid scroll directions:
* - 'all': scroll in any direction
* - 'x': scroll only in the 'x' direction
* - 'y': scroll only in the 'y' direction
* - 'none': disable scrolling for this node
*
* @param {string=} direction Direction to allow scrolling
* Defaults to `all`.
* @param {Element=} node Element to apply scroll direction setting.
* Defaults to `this`.
* @return {void}
*/
setScrollDirection(direction, node) {
Polymer.Gestures.setTouchAction(/** @type {Element} */ (node || this), DIRECTION_MAP[direction] || 'auto');
}
/* **** End Events **** */
/**
* Convenience method to run `querySelector` on this local DOM scope.
*
* This function calls `Polymer.dom(this.root).querySelector(slctr)`.
*
* @param {string} slctr Selector to run on this local DOM scope
* @return {Element} Element found by the selector, or null if not found.
*/
$$(slctr) {
return this.root.querySelector(slctr);
}
/**
* Return the element whose local dom within which this element
* is contained. This is a shorthand for
* `this.getRootNode().host`.
* @this {Element}
*/
get domHost() {
let root = this.getRootNode();
return (root instanceof DocumentFragment) ? /** @type {ShadowRoot} */ (root).host : root;
}
/**
* Force this element to distribute its children to its local dom.
* This should not be necessary as of Polymer 2.0.2 and is provided only
* for backwards compatibility.
* @return {void}
*/
distributeContent() {
if (window.ShadyDOM && this.shadowRoot) {
ShadyDOM.flush();
}
}
/**
* Returns a list of nodes that are the effective childNodes. The effective
* childNodes list is the same as the element's childNodes except that
* any `<content>` elements are replaced with the list of nodes distributed
* to the `<content>`, the result of its `getDistributedNodes` method.
* @return {!Array<!Node>} List of effective child nodes.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
*/
getEffectiveChildNodes() {
const thisEl = /** @type {Element} */ (this);
const domApi = /** @type {Polymer.DomApi} */(Polymer.dom(thisEl));
return domApi.getEffectiveChildNodes();
}
/**
* Returns a list of nodes distributed within this element that match
* `selector`. These can be dom children or elements distributed to
* children that are insertion points.
* @param {string} selector Selector to run.
* @return {!Array<!Node>} List of distributed elements that match selector.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
*/
queryDistributedElements(selector) {
const thisEl = /** @type {Element} */ (this);
const domApi = /** @type {Polymer.DomApi} */(Polymer.dom(thisEl));
return domApi.queryDistributedElements(selector);
}
/**
* Returns a list of elements that are the effective children. The effective
* children list is the same as the element's children except that
* any `<content>` elements are replaced with the list of elements
* distributed to the `<content>`.
*
* @return {!Array<!Node>} List of effective children.
*/
getEffectiveChildren() {
let list = this.getEffectiveChildNodes();
return list.filter(function(/** @type {!Node} */ n) {
return (n.nodeType === Node.ELEMENT_NODE);
});
}
/**
* Returns a string of text content that is the concatenation of the
* text content's of the element's effective childNodes (the elements
* returned by <a href="#getEffectiveChildNodes>getEffectiveChildNodes</a>.
*
* @return {string} List of effective children.
*/
getEffectiveTextContent() {
let cn = this.getEffectiveChildNodes();
let tc = [];
for (let i=0, c; (c = cn[i]); i++) {
if (c.nodeType !== Node.COMMENT_NODE) {
tc.push(c.textContent);
}
}
return tc.join('');
}
/**
* Returns the first effective childNode within this element that
* match `selector`. These can be dom child nodes or elements distributed
* to children that are insertion points.
* @param {string} selector Selector to run.
* @return {Node} First effective child node that matches selector.
*/
queryEffectiveChildren(selector) {
let e$ = this.queryDistributedElements(selector);
return e$ && e$[0];
}
/**
* Returns a list of effective childNodes within this element that
* match `selector`. These can be dom child nodes or elements distributed
* to children that are insertion points.
* @param {string} selector Selector to run.
* @return {!Array<!Node>} List of effective child nodes that match selector.
*/
queryAllEffectiveChildren(selector) {
return this.queryDistributedElements(selector);
}
/**
* Returns a list of nodes distributed to this element's `<slot>`.
*
* If this element contains more than one `<slot>` in its local DOM,
* an optional selector may be passed to choose the desired content.
*
* @param {string=} slctr CSS selector to choose the desired
* `<slot>`. Defaults to `content`.
* @return {!Array<!Node>} List of distributed nodes for the `<slot>`.
*/
getContentChildNodes(slctr) {
let content = this.root.querySelector(slctr || 'slot');
return content ? /** @type {Polymer.DomApi} */(Polymer.dom(content)).getDistributedNodes() : [];
}
/**
* Returns a list of element children distributed to this element's
* `<slot>`.
*
* If this element contains more than one `<slot>` in its
* local DOM, an optional selector may be passed to choose the desired
* content. This method differs from `getContentChildNodes` in that only
* elements are returned.
*
* @param {string=} slctr CSS selector to choose the desired
* `<content>`. Defaults to `content`.
* @return {!Array<!HTMLElement>} List of distributed nodes for the
* `<slot>`.
* @suppress {invalidCasts}
*/
getContentChildren(slctr) {
let children = /** @type {!Array<!HTMLElement>} */(this.getContentChildNodes(slctr).filter(function(n) {
return (n.nodeType === Node.ELEMENT_NODE);
}));
return children;
}
/**
* Checks whether an element is in this element's light DOM tree.
*
* @param {?Node} node The element to be checked.
* @return {boolean} true if node is in this element's light DOM tree.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
*/
isLightDescendant(node) {
const thisNode = /** @type {Node} */ (this);
return thisNode !== node && thisNode.contains(node) &&
thisNode.getRootNode() === node.getRootNode();
}
/**
* Checks whether an element is in this element's local DOM tree.
*
* @param {!Element} node The element to be checked.
* @return {boolean} true if node is in this element's local DOM tree.
*/
isLocalDescendant(node) {
return this.root === node.getRootNode();
}
/**
* No-op for backwards compatibility. This should now be handled by
* ShadyCss library.
* @param {*} container Unused
* @param {*} shouldObserve Unused
* @return {void}
*/
scopeSubtree(container, shouldObserve) { // eslint-disable-line no-unused-vars
}
/**
* Returns the computed style value for the given property.
* @param {string} property The css property name.
* @return {string} Returns the computed css property value for the given
* `property`.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
*/
getComputedStyleValue(property) {
return styleInterface.getComputedStyleValue(/** @type {!Element} */(this), property);
}
// debounce
/**
* Call `debounce` to collapse multiple requests for a named task into
* one invocation which is made after the wait time has elapsed with
* no new request. If no wait time is given, the callback will be called
* at microtask timing (guaranteed before paint).
*
* debouncedClickAction(e) {
* // will not call `processClick` more than once per 100ms
* this.debounce('click', function() {
* this.processClick();
* } 100);
* }
*
* @param {string} jobName String to identify the debounce job.
* @param {function():void} callback Function that is called (with `this`
* context) when the wait time elapses.
* @param {number} wait Optional wait time in milliseconds (ms) after the
* last signal that must elapse before invoking `callback`
* @return {!Object} Returns a debouncer object on which exists the
* following methods: `isActive()` returns true if the debouncer is
* active; `cancel()` cancels the debouncer if it is active;
* `flush()` immediately invokes the debounced callback if the debouncer
* is active.
*/
debounce(jobName, callback, wait) {
this._debouncers = this._debouncers || {};
return this._debouncers[jobName] = Polymer.Debouncer.debounce(
this._debouncers[jobName]
, wait > 0 ? Polymer.Async.timeOut.after(wait) : Polymer.Async.microTask
, callback.bind(this));
}
/**
* Returns whether a named debouncer is active.
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {boolean} Whether the debouncer is active (has not yet fired).
*/
isDebouncerActive(jobName) {
this._debouncers = this._debouncers || {};
let debouncer = this._debouncers[jobName];
return !!(debouncer && debouncer.isActive());
}
/**
* Immediately calls the debouncer `callback` and inactivates it.
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {void}
*/
flushDebouncer(jobName) {
this._debouncers = this._debouncers || {};
let debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.flush();
}
}
/**
* Cancels an active debouncer. The `callback` will not be called.
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {void}
*/
cancelDebouncer(jobName) {
this._debouncers = this._debouncers || {};
let debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.cancel();
}
}
/**
* Runs a callback function asynchronously.
*
* By default (if no waitTime is specified), async callbacks are run at
* microtask timing, which will occur before paint.
*
* @param {!Function} callback The callback function to run, bound to `this`.
* @param {number=} waitTime Time to wait before calling the
* `callback`. If unspecified or 0, the callback will be run at microtask
* timing (before paint).
* @return {number} Handle that may be used to cancel the async job.
*/
async(callback, waitTime) {
return waitTime > 0 ? Polymer.Async.timeOut.run(callback.bind(this), waitTime) :
~Polymer.Async.microTask.run(callback.bind(this));
}
/**
* Cancels an async operation started with `async`.
*
* @param {number} handle Handle returned from original `async` call to
* cancel.
* @return {void}
*/
cancelAsync(handle) {
handle < 0 ? Polymer.Async.microTask.cancel(~handle) :
Polymer.Async.timeOut.cancel(handle);
}
// other
/**
* Convenience method for creating an element and configuring it.
*
* @param {string} tag HTML element tag to create.
* @param {Object=} props Object of properties to configure on the
* instance.
* @return {!Element} Newly created and configured element.
*/
create(tag, props) {
let elt = document.createElement(tag);
if (props) {
if (elt.setProperties) {
elt.setProperties(props);
} else {
for (let n in props) {
elt[n] = props[n];
}
}
}
return elt;
}
/**
* Convenience method for importing an HTML document imperatively.
*
* This method creates a new `<link rel="import">` element with
* the provided URL and appends it to the document to start loading.
* In the `onload` callback, the `import` property of the `link`
* element will contain the imported document contents.
*
* @param {string} href URL to document to load.
* @param {?function(!Event):void=} onload Callback to notify when an import successfully
* loaded.
* @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import
* unsuccessfully loaded.
* @param {boolean=} optAsync True if the import should be loaded `async`.
* Defaults to `false`.
* @return {!HTMLLinkElement} The link element for the URL to be loaded.
*/
importHref(href, onload, onerror, optAsync) { // eslint-disable-line no-unused-vars
let loadFn = onload ? onload.bind(this) : null;
let errorFn = onerror ? onerror.bind(this) : null;
return Polymer.importHref(href, loadFn, errorFn, optAsync);
}
/**
* Polyfill for Element.prototype.matches, which is sometimes still
* prefixed.
*
* @param {string} selector Selector to test.
* @param {!Element=} node Element to test the selector against.
* @return {boolean} Whether the element matches the selector.
*/
elementMatches(selector, node) {
return Polymer.dom.matchesSelector(/** @type {!Element} */ (node || this), selector);
}
/**
* Toggles an HTML attribute on or off.
*
* @param {string} name HTML attribute name
* @param {boolean=} bool Boolean to force the attribute on or off.
* When unspecified, the state of the attribute will be reversed.
* @param {Element=} node Node to target. Defaults to `this`.
* @return {void}
*/
toggleAttribute(name, bool, node) {
node = /** @type {Element} */ (node || this);
if (arguments.length == 1) {
bool = !node.hasAttribute(name);
}
if (bool) {
node.setAttribute(name, '');
} else {
node.removeAttribute(name);
}
}
/**
* Toggles a CSS class on or off.
*
* @param {string} name CSS class name
* @param {boolean=} bool Boolean to force the class on or off.
* When unspecified, the state of the class will be reversed.
* @param {Element=} node Node to target. Defaults to `this`.
* @return {void}
*/
toggleClass(name, bool, node) {
node = /** @type {Element} */ (node || this);
if (arguments.length == 1) {
bool = !node.classList.contains(name);
}
if (bool) {
node.classList.add(name);
} else {
node.classList.remove(name);
}
}
/**
* Cross-platform helper for setting an element's CSS `transform` property.
*
* @param {string} transformText Transform setting.
* @param {Element=} node Element to apply the transform to.
* Defaults to `this`
* @return {void}
*/
transform(transformText, node) {
node = /** @type {Element} */ (node || this);
node.style.webkitTransform = transformText;
node.style.transform = transformText;
}
/**
* Cross-platform helper for setting an element's CSS `translate3d`
* property.
*
* @param {number} x X offset.
* @param {number} y Y offset.
* @param {number} z Z offset.
* @param {Element=} node Element to apply the transform to.
* Defaults to `this`.
* @return {void}
*/
translate3d(x, y, z, node) {
node = /** @type {Element} */ (node || this);
this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
}
/**
* Removes an item from an array, if it exists.
*
* If the array is specified by path, a change notification is
* generated, so that observers, data bindings and computed
* properties watching that path can update.
*
* If the array is passed directly, **no change
* notification is generated**.
*
* @param {string | !Array<number|string>} arrayOrPath Path to array from which to remove the item
* (or the array itself).
* @param {*} item Item to remove.
* @return {Array} Array containing item removed.
*/
arrayDelete(arrayOrPath, item) {
let index;
if (Array.isArray(arrayOrPath)) {
index = arrayOrPath.indexOf(item);
if (index >= 0) {
return arrayOrPath.splice(index, 1);
}
} else {
let arr = Polymer.Path.get(this, arrayOrPath);
index = arr.indexOf(item);
if (index >= 0) {
return this.splice(arrayOrPath, index, 1);
}
}
return null;
}
// logging
/**
* Facades `console.log`/`warn`/`error` as override point.
*
* @param {string} level One of 'log', 'warn', 'error'
* @param {Array} args Array of strings or objects to log
* @return {void}
*/
_logger(level, args) {
// accept ['foo', 'bar'] and [['foo', 'bar']]
if (Array.isArray(args) && args.length === 1 && Array.isArray(args[0])) {
args = args[0];
}
switch(level) {
case 'log':
case 'warn':
case 'error':
console[level](...args);
}
}
/**
* Facades `console.log` as an override point.
*
* @param {...*} args Array of strings or objects to log
* @return {void}
*/
_log(...args) {
this._logger('log', args);
}
/**
* Facades `console.warn` as an override point.
*
* @param {...*} args Array of strings or objects to log
* @return {void}
*/
_warn(...args) {
this._logger('warn', args);
}
/**
* Facades `console.error` as an override point.
*
* @param {...*} args Array of strings or objects to log
* @return {void}
*/
_error(...args) {
this._logger('error', args);
}
/**
* Formats a message using the element type an a method name.
*
* @param {string} methodName Method name to associate with message
* @param {...*} args Array of strings or objects to log
* @return {Array} Array with formatting information for `console`
* logging.
*/
_logf(methodName, ...args) {
return ['[%s::%s]', this.is, methodName, ...args];
}
}
LegacyElement.prototype.is = '';
return LegacyElement;
});
})();
</script>