diff --git a/bower.json b/bower.json index 23cad42d..60ab621b 100644 --- a/bower.json +++ b/bower.json @@ -22,6 +22,7 @@ "dependencies": { "fancybox": "~2.1.5", "jquery": "~2.1.3", - "menu": "~0.7.7" + "menu": "~0.7.7", + "promise-polyfill": "~2.0.0" } } diff --git a/lib/client/cloudcmd.js b/lib/client/cloudcmd.js index d733bb0d..a212a539 100644 --- a/lib/client/cloudcmd.js +++ b/lib/client/cloudcmd.js @@ -6,13 +6,13 @@ var CloudCmd; CloudCmd = load; function load(prefix) { - var lib = 'lib/', + var urlFiles, + lib = 'lib/', client = 'client/', files = [ 'util', 'join', 'format', - 'promise', 'cloudfunc', client + 'dom', client + 'events', @@ -27,9 +27,11 @@ var CloudCmd; client + 'key' ].map(function(name) { return lib + name + '.js'; - }), - - urlFiles = getJoinURL(files); + }); + + files.unshift('/modules/promise-polyfill/Promise.js'); + + urlFiles = getJoinURL(files); if (!prefix) prefix = '/cloudcmd'; diff --git a/modules/promise-polyfill/.bower.json b/modules/promise-polyfill/.bower.json new file mode 100644 index 00000000..1a48962f --- /dev/null +++ b/modules/promise-polyfill/.bower.json @@ -0,0 +1,38 @@ +{ + "name": "promise-polyfill", + "version": "2.0.0", + "homepage": "https://github.com/taylorhakes/promise-polyfill", + "authors": [ + "Taylor Hakes" + ], + "description": "Lightweight promise polyfill for the browser and node. A+ Compliant.", + "main": "Promise.js", + "moduleType": [ + "globals", + "node" + ], + "keywords": [ + "promise", + "es6", + "polyfill", + "html5" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "_release": "2.0.0", + "_resolution": { + "type": "version", + "tag": "2.0.0", + "commit": "970996440115e6c5ec0dc84a15e00fc04b34651f" + }, + "_source": "git://github.com/taylorhakes/promise-polyfill.git", + "_target": "~2.0.0", + "_originalSource": "promise-polyfill", + "_direct": true +} \ No newline at end of file diff --git a/modules/promise-polyfill/Gruntfile.js b/modules/promise-polyfill/Gruntfile.js new file mode 100644 index 00000000..ef1cbfaa --- /dev/null +++ b/modules/promise-polyfill/Gruntfile.js @@ -0,0 +1,23 @@ +module.exports = function(grunt) { + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + uglify: { + options: { + banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n' + }, + dist: { + files: { + 'Promise.min.js': ['Promise.js'] + } + } + } + + }); + + grunt.loadNpmTasks('grunt-contrib-uglify'); + + grunt.registerTask('build', ['uglify']); + +}; diff --git a/modules/promise-polyfill/LICENSE b/modules/promise-polyfill/LICENSE new file mode 100644 index 00000000..94b9dac3 --- /dev/null +++ b/modules/promise-polyfill/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014 Taylor Hakes +Copyright (c) 2014 Forbes Lindesay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/lib/promise.js b/modules/promise-polyfill/Promise.js similarity index 88% rename from lib/promise.js rename to modules/promise-polyfill/Promise.js index a095b193..9c55485b 100644 --- a/lib/promise.js +++ b/modules/promise-polyfill/Promise.js @@ -1,183 +1,186 @@ -/* - * version: 1.1.2 - * url: https://github.com/taylorhakes/promise-polyfill - */ - -(function(global) { - if(typeof module !== 'undefined' && module.exports) { - module.exports = global.Promise ? global.Promise : Promise; - } else if (!global.Promise) { - global.Promise = Promise; - } - - // Use polyfill for setImmediate for performance gains - var asap = global.setImmediate || function(fn) { setTimeout(fn, 1); }; - - // Polyfill for Function.prototype.bind - function bind(fn, thisArg) { - return function() { - fn.apply(thisArg, arguments); - } - } - - var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]" }; - - function Promise(fn) { - if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); - if (typeof fn !== 'function') throw new TypeError('not a function'); - this._state = null; - this._value = null; - this._deferreds = [] - - doResolve(fn, bind(resolve, this), bind(reject, this)) - } - - function handle(deferred) { - var me = this; - if (this._state === null) { - this._deferreds.push(deferred); - return - } - asap(function() { - var cb = me._state ? deferred.onFulfilled : deferred.onRejected - if (cb === null) { - (me._state ? deferred.resolve : deferred.reject)(me._value); - return; - } - var ret; - try { - ret = cb(me._value); - } - catch (e) { - deferred.reject(e); - return; - } - deferred.resolve(ret); - }) - } - - function resolve(newValue) { - try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.'); - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then; - if (typeof then === 'function') { - doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this)); - return; - } - } - this._state = true; - this._value = newValue; - finale.call(this); - } catch (e) { reject.call(this, e); } - } - - function reject(newValue) { - this._state = false; - this._value = newValue; - finale.call(this); - } - - function finale() { - for (var i = 0, len = this._deferreds.length; i < len; i++) { - handle.call(this, this._deferreds[i]); - } - this._deferreds = null; - } - - function Handler(onFulfilled, onRejected, resolve, reject){ - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; - this.onRejected = typeof onRejected === 'function' ? onRejected : null; - this.resolve = resolve; - this.reject = reject; - } - - /** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ - function doResolve(fn, onFulfilled, onRejected) { - var done = false; - try { - fn(function (value) { - if (done) return; - done = true; - onFulfilled(value); - }, function (reason) { - if (done) return; - done = true; - onRejected(reason); - }) - } catch (ex) { - if (done) return; - done = true; - onRejected(ex); - } - } - - Promise.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); - }; - - Promise.prototype.then = function(onFulfilled, onRejected) { - var me = this; - return new Promise(function(resolve, reject) { - handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject)); - }) - }; - - Promise.all = function () { - var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments); - - return new Promise(function (resolve, reject) { - if (args.length === 0) return resolve([]); - var remaining = args.length; - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then; - if (typeof then === 'function') { - then.call(val, function (val) { res(i, val) }, reject); - return; - } - } - args[i] = val; - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex); - } - } - for (var i = 0; i < args.length; i++) { - res(i, args[i]); - } - }); - }; - - Promise.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise) { - return value; - } - - return new Promise(function (resolve) { - resolve(value); - }); - }; - - Promise.reject = function (value) { - return new Promise(function (resolve, reject) { - reject(value); - }); - }; - - Promise.race = function (values) { - return new Promise(function (resolve, reject) { - for(var i = 0, len = values.length; i < len; i++) { - values[i].then(resolve, reject); - } - }); - }; -})(this); \ No newline at end of file +(function() { + var root; + + if (typeof window === 'object' && window) { + root = window; + } else { + root = global; + } + + // Use polyfill for setImmediate for performance gains + var asap = Promise.immediateFn || root.setImmediate || function(fn) { setTimeout(fn, 1); }; + + // Polyfill for Function.prototype.bind + function bind(fn, thisArg) { + return function() { + fn.apply(thisArg, arguments); + } + } + + var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]" }; + + function Promise(fn) { + if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + this._state = null; + this._value = null; + this._deferreds = [] + + doResolve(fn, bind(resolve, this), bind(reject, this)) + } + + function handle(deferred) { + var me = this; + if (this._state === null) { + this._deferreds.push(deferred); + return + } + asap(function() { + var cb = me._state ? deferred.onFulfilled : deferred.onRejected + if (cb === null) { + (me._state ? deferred.resolve : deferred.reject)(me._value); + return; + } + var ret; + try { + ret = cb(me._value); + } + catch (e) { + deferred.reject(e); + return; + } + deferred.resolve(ret); + }) + } + + function resolve(newValue) { + try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.'); + if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + var then = newValue.then; + if (typeof then === 'function') { + doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this)); + return; + } + } + this._state = true; + this._value = newValue; + finale.call(this); + } catch (e) { reject.call(this, e); } + } + + function reject(newValue) { + this._state = false; + this._value = newValue; + finale.call(this); + } + + function finale() { + for (var i = 0, len = this._deferreds.length; i < len; i++) { + handle.call(this, this._deferreds[i]); + } + this._deferreds = null; + } + + function Handler(onFulfilled, onRejected, resolve, reject){ + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.resolve = resolve; + this.reject = reject; + } + + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + function doResolve(fn, onFulfilled, onRejected) { + var done = false; + try { + fn(function (value) { + if (done) return; + done = true; + onFulfilled(value); + }, function (reason) { + if (done) return; + done = true; + onRejected(reason); + }) + } catch (ex) { + if (done) return; + done = true; + onRejected(ex); + } + } + + Promise.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; + + Promise.prototype.then = function(onFulfilled, onRejected) { + var me = this; + return new Promise(function(resolve, reject) { + handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject)); + }) + }; + + Promise.all = function () { + var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments); + + return new Promise(function (resolve, reject) { + if (args.length === 0) return resolve([]); + var remaining = args.length; + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + if (typeof then === 'function') { + then.call(val, function (val) { res(i, val) }, reject); + return; + } + } + args[i] = val; + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + + Promise.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise) { + return value; + } + + return new Promise(function (resolve) { + resolve(value); + }); + }; + + Promise.reject = function (value) { + return new Promise(function (resolve, reject) { + reject(value); + }); + }; + + Promise.race = function (values) { + return new Promise(function (resolve, reject) { + for(var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = Promise; + } else if (!root.Promise) { + root.Promise = Promise; + } +})(); \ No newline at end of file diff --git a/modules/promise-polyfill/Promise.min.js b/modules/promise-polyfill/Promise.min.js new file mode 100644 index 00000000..f3ee36e6 --- /dev/null +++ b/modules/promise-polyfill/Promise.min.js @@ -0,0 +1,2 @@ +/*! promise-polyfill 2.0.0 */ +!function(){function a(a,b){return function(){a.apply(b,arguments)}}function b(b){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof b)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],h(b,a(d,this),a(e,this))}function c(a){var b=this;return null===this._state?void this._deferreds.push(a):void j(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(e){return void a.reject(e)}a.resolve(d)})}function d(b){try{if(b===this)throw new TypeError("A promise cannot be resolved with itself.");if(b&&("object"==typeof b||"function"==typeof b)){var c=b.then;if("function"==typeof c)return void h(a(c,b),a(d,this),a(e,this))}this._state=!0,this._value=b,f.call(this)}catch(g){e.call(this,g)}}function e(a){this._state=!1,this._value=a,f.call(this)}function f(){for(var a=0,b=this._deferreds.length;b>a;a++)c.call(this,this._deferreds[a]);this._deferreds=null}function g(a,b,c,d){this.onFulfilled="function"==typeof a?a:null,this.onRejected="function"==typeof b?b:null,this.resolve=c,this.reject=d}function h(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(e){if(d)return;d=!0,c(e)}}var i;i="object"==typeof window&&window?window:global;var j=b.immediateFn||i.setImmediate||function(a){setTimeout(a,1)},k=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};b.prototype["catch"]=function(a){return this.then(null,a)},b.prototype.then=function(a,d){var e=this;return new b(function(b,f){c.call(e,new g(a,d,b,f))})},b.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&k(arguments[0])?arguments[0]:arguments);return new b(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(i){c(i)}}if(0===a.length)return b([]);for(var e=a.length,f=0;fd;d++)a[d].then(b,c)})},"undefined"!=typeof module&&module.exports?module.exports=b:i.Promise||(i.Promise=b)}(); \ No newline at end of file diff --git a/modules/promise-polyfill/README.md b/modules/promise-polyfill/README.md new file mode 100644 index 00000000..627946d3 --- /dev/null +++ b/modules/promise-polyfill/README.md @@ -0,0 +1,55 @@ + + Promises/A+ logo + +Promise [![Build Status](https://travis-ci.org/taylorhakes/promise-polyfill.png?branch=master)](https://travis-ci.org/taylorhakes/promise-polyfill) +============= + +Lightweight promise polyfill for the browser and node. A+ Compliant. It is a perfect polyfill IE, Firefox or any other browser that does not support native promises. + +This implementation is based on [then/promise](https://github.com/then/promise). It has been changed to use the prototype for performance and memory reasons. + +For API information about Promises, please check out this article [HTML5Rocks article](http://www.html5rocks.com/en/tutorials/es6/promises/). + +It is extremely lightweight. ***< 1kb Gzipped*** + +## Downloads + +- [Promise](https://raw.github.com/taylorhakes/promise-polyfill/master/Promise.js) +- [Promise-min](https://raw.github.com/taylorhakes/promise-polyfill/master/Promise.min.js) + +### Node +``` +npm install promise-polyfill +``` + +## Simple use +``` +var prom = new Promise(function(resolve, reject) { + // do a thing, possibly async, then… + + if (/* everything turned out fine */) { + resolve("Stuff worked!"); + } + else { + reject(new Error("It broke")); + } +}); + +// Do something when async done +prom.then(function() { + ... +}); +``` +## Performance +By default promise-polyfill uses `setImmediate`, but falls back to `setTimeout` for executing asynchronously. If a browser does not support `setImmediate`, you may see performance issues. +Use a `setImmediate` polyfill to fix this issue. [setAsap](https://github.com/taylorhakes/setAsap) or [setImmediate](https://github.com/YuzuJS/setImmediate) work well. + +## Testing +``` +npm install +npm test +``` + +## License +MIT diff --git a/modules/promise-polyfill/bower.json b/modules/promise-polyfill/bower.json new file mode 100644 index 00000000..8ee7394d --- /dev/null +++ b/modules/promise-polyfill/bower.json @@ -0,0 +1,28 @@ +{ + "name": "promise-polyfill", + "version": "1.1.4", + "homepage": "https://github.com/taylorhakes/promise-polyfill", + "authors": [ + "Taylor Hakes" + ], + "description": "Lightweight promise polyfill for the browser and node. A+ Compliant.", + "main": "Promise.js", + "moduleType": [ + "globals", + "node" + ], + "keywords": [ + "promise", + "es6", + "polyfill", + "html5" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/modules/promise-polyfill/package.json b/modules/promise-polyfill/package.json new file mode 100644 index 00000000..75afee05 --- /dev/null +++ b/modules/promise-polyfill/package.json @@ -0,0 +1,26 @@ +{ + "name": "promise-polyfill", + "version": "2.0.0", + "description": "Lightweight promise polyfill. A+ compliant", + "main": "Promise.js", + "scripts": { + "test": "./node_modules/.bin/promises-aplus-tests tests/adapter.js" + }, + "repository": { + "type": "git", + "url": "https://taylorhakes@github.com/taylorhakes/promise-polyfill.git" + }, + "author": "Taylor Hakes", + "license": "MIT", + "bugs": { + "url": "https://github.com/taylorhakes/promise-polyfill/issues" + }, + "homepage": "https://github.com/taylorhakes/promise-polyfill", + "devDependencies": { + "promises-aplus-tests": "*", + "grunt": "^0.4.4", + "grunt-contrib-uglify": "^0.4.0" + }, + "keywords": ["promise", "promise-polyfill", "ES6", "promises-aplus"], + "dependencies": {} +}