diff options
author | Wilson Page <wilsonpage@me.com> | 2015-02-13 19:49:50 +0000 |
---|---|---|
committer | Wilson Page <wilsonpage@me.com> | 2016-01-04 12:21:44 +0000 |
commit | 4ade1a6b6b14fcef9686ab9eb03e6e4951b948fc (patch) | |
tree | 1cf3226ef4b51cbd069bc01ca15343f081646657 /extensions | |
parent | 6c4958941d2c86cdfa6dc17a8b286399f3f71729 (diff) | |
download | fastdom-origin/v1-beta.zip fastdom-origin/v1-beta.tar.gz fastdom-origin/v1-beta.tar.bz2 |
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/fastdom-promised.js | 77 | ||||
-rw-r--r-- | extensions/fastdom-sandbox.js | 147 |
2 files changed, 224 insertions, 0 deletions
diff --git a/extensions/fastdom-promised.js b/extensions/fastdom-promised.js new file mode 100644 index 0000000..e002072 --- /dev/null +++ b/extensions/fastdom-promised.js @@ -0,0 +1,77 @@ +!(function() { + +/** + * Wraps fastdom in a Promise API + * for improved control-flow. + * + * @example + * + * // returning a result + * fastdom.measure(() => el.clientWidth) + * .then(result => ...); + * + * // returning promises from tasks + * fastdom.measure(() => { + * var w = el1.clientWidth; + * return fastdom.mutate(() => el2.style.width = w + 'px'); + * }).then(() => console.log('all done')); + * + * // clearing pending tasks + * var promise = fastdom.measure(...) + * fastdom.clear(promise); + * + * @type {Object} + */ +var exports = { + initialize: function() { + this._tasks = new Map(); + }, + + mutate: function(fn, ctx) { + return create(this, 'mutate', fn, ctx); + }, + + measure: function(fn, ctx) { + return create(this, 'measure', fn, ctx); + }, + + clear: function(promise) { + var tasks = this._tasks; + var task = tasks.get(promise); + this.fastdom.clear(task); + tasks.delete(task); + } +}; + +/** + * Create a fastdom task wrapped in + * a 'cancellable' Promise. + * + * @param {FastDom} fastdom + * @param {String} type - 'measure'|'muatate' + * @param {Function} fn + * @return {Promise} + */ +function create(promised, type, fn, ctx) { + var tasks = promised._tasks; + var fastdom = promised.fastdom; + var task; + + var promise = new Promise(function(resolve, reject) { + task = fastdom[type](function() { + tasks.delete(promise); + try { resolve(fn()); } + catch (e) { reject(e); } + }, ctx); + }); + + tasks.set(promise, task); + return promise; +} + +// Expose to CJS, AMD or global +if ((typeof define)[0] == 'f') define(function() { return exports; }); +else if ((typeof module)[0] == 'o') module.exports = exports; +else window.fastdomPromised = exports; + +})();
\ No newline at end of file diff --git a/extensions/fastdom-sandbox.js b/extensions/fastdom-sandbox.js new file mode 100644 index 0000000..39afc28 --- /dev/null +++ b/extensions/fastdom-sandbox.js @@ -0,0 +1,147 @@ +(function(exports) { + +/** + * Mini logger + * + * @return {Function} + */ +var debug = 0 ? console.log.bind(console, '[fastdom-sandbox]') : function() {}; + +/** + * Exports + */ + +/** + * Create a new `Sandbox`. + * + * Scheduling tasks via a sandbox is + * useful because you can clear all + * sandboxed tasks in one go. + * + * This is handy when working with view + * components. You can create one sandbox + * per component and call `.clear()` when + * tearing down. + * + * @example + * + * var sandbox = fastdom.sandbox(); + * + * sandbox.measure(function() { console.log(1); }); + * sandbox.measure(function() { console.log(2); }); + * + * fastdom.measure(function() { console.log(3); }); + * fastdom.measure(function() { console.log(4); }); + * + * sandbox.clear(); + * + * // => 3 + * // => 4 + * + * @return {Sandbox} + * @public + */ +exports.sandbox = function() { + return new Sandbox(this.fastdom); +}; + +/** + * Initialize a new `Sandbox` + * + * @param {FastDom} fastdom + */ + +function Sandbox(fastdom) { + this.fastdom = fastdom; + this.tasks = []; + debug('initialized'); +} + +/** + * Schedule a 'measure' task. + * + * @param {Function} fn + * @param {Object} ctx + * @return {Object} can be passed to .clear() + */ +Sandbox.prototype.measure = function(fn, ctx) { + var tasks = this.tasks; + var task = this.fastdom.measure(function() { + tasks.splice(tasks.indexOf(task)); + fn.call(ctx); + }); + + tasks.push(task); + return task; +}; + +/** + * Schedule a 'mutate' task. + * + * @param {Function} fn + * @param {Object} ctx + * @return {Object} can be passed to .clear() + */ +Sandbox.prototype.mutate = function(fn, ctx) { + var tasks = this.tasks; + var task = this.fastdom.mutate(function() { + tasks.splice(tasks.indexOf(task)); + fn.call(ctx); + }); + + this.tasks.push(task); + return task; +}; + +/** + * Clear a single task or is no task is + * passsed, all tasks in the `Sandbox`. + * + * @param {Object} task (optional) + */ + +Sandbox.prototype.clear = function(task) { + if (!arguments.length) clearAll(this.fastdom, this.tasks); + remove(this.tasks, task); + return this.fastdom.clear(task); +}; + +/** + * Clears all the given tasks from + * the given `FastDom`. + * + * @param {FastDom} fastdom + * @param {Array} tasks + * @private + */ + +function clearAll(fastdom, tasks) { + debug('clear all', fastdom, tasks); + var i = tasks.length; + while (i--) { + fastdom.clear(tasks[i]); + tasks.splice(i, 1); + } +} + +/** + * Remove an item from an Array. + * + * @param {Array} array + * @param {*} item + * @return {Boolean} + */ +function remove(array, item) { + var index = array.indexOf(item); + return !!~index && !!array.splice(index, 1); +} + +/** + * Expose + */ + +if ((typeof define)[0] == 'f') define(function() { return exports; }); +else if ((typeof module)[0] == 'o') module.exports = exports; +else window.fastdomSandbox = exports; + +})({}); |