/*
* 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
*/
(function(scope) {
/**
* @class polymer-base
*/
var utils = {
/**
* Invokes a function asynchronously. The context of the callback
* function is bound to 'this' automatically. Returns a handle which may
* be passed to cancelAsync to cancel the
* asynchronous call.
*
* @method async
* @param {Function|String} method
* @param {any|Array} args
* @param {number} timeout
*/
async: function(method, args, timeout) {
// when polyfilling Object.observe, ensure changes
// propagate before executing the async method
Polymer.flush();
// second argument to `apply` must be an array
args = (args && args.length) ? args : [args];
// function to invoke
var fn = function() {
(this[method] || method).apply(this, args);
}.bind(this);
// execute `fn` sooner or later
var handle = timeout ? setTimeout(fn, timeout) :
requestAnimationFrame(fn);
// NOTE: switch on inverting handle to determine which time is used.
return timeout ? handle : ~handle;
},
/**
* Cancels a pending callback that was scheduled via
* async.
*
* @method cancelAsync
* @param {handle} handle Handle of the `async` to cancel.
*/
cancelAsync: function(handle) {
if (handle < 0) {
cancelAnimationFrame(~handle);
} else {
clearTimeout(handle);
}
},
/**
* Fire an event.
*
* @method fire
* @returns {Object} event
* @param {string} type An event name.
* @param {any} detail
* @param {Node} onNode Target node.
* @param {Boolean} bubbles Set false to prevent bubbling, defaults to true
* @param {Boolean} cancelable Set false to prevent cancellation, defaults to true
*/
fire: function(type, detail, onNode, bubbles, cancelable) {
var node = onNode || this;
var detail = detail === null || detail === undefined ? {} : detail;
var event = new CustomEvent(type, {
bubbles: bubbles !== undefined ? bubbles : true,
cancelable: cancelable !== undefined ? cancelable : true,
detail: detail
});
node.dispatchEvent(event);
return event;
},
/**
* Fire an event asynchronously.
*
* @method asyncFire
* @param {string} type An event name.
* @param detail
* @param {Node} toNode Target node.
*/
asyncFire: function(/*inType, inDetail*/) {
this.async("fire", arguments);
},
/**
* Remove class from old, add class to anew, if they exist.
*
* @param classFollows
* @param anew A node.
* @param old A node
* @param className
*/
classFollows: function(anew, old, className) {
if (old) {
old.classList.remove(className);
}
if (anew) {
anew.classList.add(className);
}
},
/**
* Inject HTML which contains markup bound to this element into
* a target element (replacing target element content).
*
* @param String html to inject
* @param Element target element
*/
injectBoundHTML: function(html, element) {
var template = document.createElement('template');
template.innerHTML = html;
var fragment = this.instanceTemplate(template);
if (element) {
element.textContent = '';
element.appendChild(fragment);
}
return fragment;
}
};
// no-operation function for handy stubs
var nop = function() {};
// null-object for handy stubs
var nob = {};
// deprecated
utils.asyncMethod = utils.async;
// exports
scope.api.instance.utils = utils;
scope.nop = nop;
scope.nob = nob;
})(Polymer);