Move to vendor folder
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
---
|
||||
|
||||
script: Array.stableSort.js
|
||||
|
||||
description: Add a stable sort algorithm for all browsers
|
||||
|
||||
license: MIT-style license.
|
||||
|
||||
authors:
|
||||
- Yorick Sijsling
|
||||
|
||||
requires:
|
||||
core/1.3: '*'
|
||||
|
||||
provides:
|
||||
- [Array.stableSort, Array.mergeSort]
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var defaultSortFunction = function(a, b) {
|
||||
return a > b ? 1 : (a < b ? -1 : 0);
|
||||
}
|
||||
|
||||
Array.implement({
|
||||
|
||||
stableSort: function(compare) {
|
||||
// I would love some real feature recognition. Problem is that an unstable algorithm sometimes/often gives the same result as an unstable algorithm.
|
||||
return (Browser.chrome || Browser.firefox2 || Browser.opera9) ? this.mergeSort(compare) : this.sort(compare);
|
||||
},
|
||||
|
||||
mergeSort: function(compare, token) {
|
||||
compare = compare || defaultSortFunction;
|
||||
if (this.length > 1) {
|
||||
// Split and sort both parts
|
||||
var right = this.splice(Math.floor(this.length / 2)).mergeSort(compare);
|
||||
var left = this.splice(0).mergeSort(compare); // 'this' is now empty.
|
||||
|
||||
// Merge parts together
|
||||
while (left.length > 0 || right.length > 0) {
|
||||
this.push(
|
||||
right.length === 0 ? left.shift()
|
||||
: left.length === 0 ? right.shift()
|
||||
: compare(left[0], right[0]) > 0 ? right.shift()
|
||||
: left.shift());
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1,955 +0,0 @@
|
||||
/*global setImmediate: false, setTimeout: false, console: false */
|
||||
(function () {
|
||||
|
||||
var async = {};
|
||||
|
||||
// global on the server, window in the browser
|
||||
var root, previous_async;
|
||||
|
||||
root = this;
|
||||
if (root != null) {
|
||||
previous_async = root.async;
|
||||
}
|
||||
|
||||
async.noConflict = function () {
|
||||
root.async = previous_async;
|
||||
return async;
|
||||
};
|
||||
|
||||
function only_once(fn) {
|
||||
var called = false;
|
||||
return function() {
|
||||
if (called) throw new Error("Callback was already called.");
|
||||
called = true;
|
||||
fn.apply(root, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
//// cross-browser compatiblity functions ////
|
||||
|
||||
var _each = function (arr, iterator) {
|
||||
if (arr.forEach) {
|
||||
return arr.forEach(iterator);
|
||||
}
|
||||
for (var i = 0; i < arr.length; i += 1) {
|
||||
iterator(arr[i], i, arr);
|
||||
}
|
||||
};
|
||||
|
||||
var _map = function (arr, iterator) {
|
||||
if (arr.map) {
|
||||
return arr.map(iterator);
|
||||
}
|
||||
var results = [];
|
||||
_each(arr, function (x, i, a) {
|
||||
results.push(iterator(x, i, a));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
var _reduce = function (arr, iterator, memo) {
|
||||
if (arr.reduce) {
|
||||
return arr.reduce(iterator, memo);
|
||||
}
|
||||
_each(arr, function (x, i, a) {
|
||||
memo = iterator(memo, x, i, a);
|
||||
});
|
||||
return memo;
|
||||
};
|
||||
|
||||
var _keys = function (obj) {
|
||||
if (Object.keys) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
var keys = [];
|
||||
for (var k in obj) {
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
keys.push(k);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
|
||||
//// exported async module functions ////
|
||||
|
||||
//// nextTick implementation with browser-compatible fallback ////
|
||||
if (typeof process === 'undefined' || !(process.nextTick)) {
|
||||
if (typeof setImmediate === 'function') {
|
||||
async.nextTick = function (fn) {
|
||||
// not a direct alias for IE10 compatibility
|
||||
setImmediate(fn);
|
||||
};
|
||||
async.setImmediate = async.nextTick;
|
||||
}
|
||||
else {
|
||||
async.nextTick = function (fn) {
|
||||
setTimeout(fn, 0);
|
||||
};
|
||||
async.setImmediate = async.nextTick;
|
||||
}
|
||||
}
|
||||
else {
|
||||
async.nextTick = process.nextTick;
|
||||
if (typeof setImmediate !== 'undefined') {
|
||||
async.setImmediate = setImmediate;
|
||||
}
|
||||
else {
|
||||
async.setImmediate = async.nextTick;
|
||||
}
|
||||
}
|
||||
|
||||
async.each = function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
_each(arr, function (x) {
|
||||
iterator(x, only_once(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
if (completed >= arr.length) {
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.forEach = async.each;
|
||||
|
||||
async.eachSeries = function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
var iterate = function () {
|
||||
iterator(arr[completed], function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
if (completed >= arr.length) {
|
||||
callback(null);
|
||||
}
|
||||
else {
|
||||
iterate();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
iterate();
|
||||
};
|
||||
async.forEachSeries = async.eachSeries;
|
||||
|
||||
async.eachLimit = function (arr, limit, iterator, callback) {
|
||||
var fn = _eachLimit(limit);
|
||||
fn.apply(null, [arr, iterator, callback]);
|
||||
};
|
||||
async.forEachLimit = async.eachLimit;
|
||||
|
||||
var _eachLimit = function (limit) {
|
||||
|
||||
return function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length || limit <= 0) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
var started = 0;
|
||||
var running = 0;
|
||||
|
||||
(function replenish () {
|
||||
if (completed >= arr.length) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
while (running < limit && started < arr.length) {
|
||||
started += 1;
|
||||
running += 1;
|
||||
iterator(arr[started - 1], function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
running -= 1;
|
||||
if (completed >= arr.length) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
replenish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var doParallel = function (fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [async.each].concat(args));
|
||||
};
|
||||
};
|
||||
var doParallelLimit = function(limit, fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [_eachLimit(limit)].concat(args));
|
||||
};
|
||||
};
|
||||
var doSeries = function (fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [async.eachSeries].concat(args));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (err, v) {
|
||||
results[x.index] = v;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
};
|
||||
async.map = doParallel(_asyncMap);
|
||||
async.mapSeries = doSeries(_asyncMap);
|
||||
async.mapLimit = function (arr, limit, iterator, callback) {
|
||||
return _mapLimit(limit)(arr, iterator, callback);
|
||||
};
|
||||
|
||||
var _mapLimit = function(limit) {
|
||||
return doParallelLimit(limit, _asyncMap);
|
||||
};
|
||||
|
||||
// reduce only has a series version, as doing reduce in parallel won't
|
||||
// work in many situations.
|
||||
async.reduce = function (arr, memo, iterator, callback) {
|
||||
async.eachSeries(arr, function (x, callback) {
|
||||
iterator(memo, x, function (err, v) {
|
||||
memo = v;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, memo);
|
||||
});
|
||||
};
|
||||
// inject alias
|
||||
async.inject = async.reduce;
|
||||
// foldl alias
|
||||
async.foldl = async.reduce;
|
||||
|
||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
||||
var reversed = _map(arr, function (x) {
|
||||
return x;
|
||||
}).reverse();
|
||||
async.reduce(reversed, memo, iterator, callback);
|
||||
};
|
||||
// foldr alias
|
||||
async.foldr = async.reduceRight;
|
||||
|
||||
var _filter = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (v) {
|
||||
if (v) {
|
||||
results.push(x);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
callback(_map(results.sort(function (a, b) {
|
||||
return a.index - b.index;
|
||||
}), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.filter = doParallel(_filter);
|
||||
async.filterSeries = doSeries(_filter);
|
||||
// select alias
|
||||
async.select = async.filter;
|
||||
async.selectSeries = async.filterSeries;
|
||||
|
||||
var _reject = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (v) {
|
||||
if (!v) {
|
||||
results.push(x);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
callback(_map(results.sort(function (a, b) {
|
||||
return a.index - b.index;
|
||||
}), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.reject = doParallel(_reject);
|
||||
async.rejectSeries = doSeries(_reject);
|
||||
|
||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x, function (result) {
|
||||
if (result) {
|
||||
main_callback(x);
|
||||
main_callback = function () {};
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback();
|
||||
});
|
||||
};
|
||||
async.detect = doParallel(_detect);
|
||||
async.detectSeries = doSeries(_detect);
|
||||
|
||||
async.some = function (arr, iterator, main_callback) {
|
||||
async.each(arr, function (x, callback) {
|
||||
iterator(x, function (v) {
|
||||
if (v) {
|
||||
main_callback(true);
|
||||
main_callback = function () {};
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback(false);
|
||||
});
|
||||
};
|
||||
// any alias
|
||||
async.any = async.some;
|
||||
|
||||
async.every = function (arr, iterator, main_callback) {
|
||||
async.each(arr, function (x, callback) {
|
||||
iterator(x, function (v) {
|
||||
if (!v) {
|
||||
main_callback(false);
|
||||
main_callback = function () {};
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback(true);
|
||||
});
|
||||
};
|
||||
// all alias
|
||||
async.all = async.every;
|
||||
|
||||
async.sortBy = function (arr, iterator, callback) {
|
||||
async.map(arr, function (x, callback) {
|
||||
iterator(x, function (err, criteria) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
}
|
||||
else {
|
||||
callback(null, {value: x, criteria: criteria});
|
||||
}
|
||||
});
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
else {
|
||||
var fn = function (left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
};
|
||||
callback(null, _map(results.sort(fn), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.auto = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
var keys = _keys(tasks);
|
||||
if (!keys.length) {
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
var results = {};
|
||||
|
||||
var listeners = [];
|
||||
var addListener = function (fn) {
|
||||
listeners.unshift(fn);
|
||||
};
|
||||
var removeListener = function (fn) {
|
||||
for (var i = 0; i < listeners.length; i += 1) {
|
||||
if (listeners[i] === fn) {
|
||||
listeners.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
var taskComplete = function () {
|
||||
_each(listeners.slice(0), function (fn) {
|
||||
fn();
|
||||
});
|
||||
};
|
||||
|
||||
addListener(function () {
|
||||
if (_keys(results).length === keys.length) {
|
||||
callback(null, results);
|
||||
callback = function () {};
|
||||
}
|
||||
});
|
||||
|
||||
_each(keys, function (k) {
|
||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
||||
var taskCallback = function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
if (err) {
|
||||
var safeResults = {};
|
||||
_each(_keys(results), function(rkey) {
|
||||
safeResults[rkey] = results[rkey];
|
||||
});
|
||||
safeResults[k] = args;
|
||||
callback(err, safeResults);
|
||||
// stop subsequent errors hitting callback multiple times
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
results[k] = args;
|
||||
async.setImmediate(taskComplete);
|
||||
}
|
||||
};
|
||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
||||
var ready = function () {
|
||||
return _reduce(requires, function (a, x) {
|
||||
return (a && results.hasOwnProperty(x));
|
||||
}, true) && !results.hasOwnProperty(k);
|
||||
};
|
||||
if (ready()) {
|
||||
task[task.length - 1](taskCallback, results);
|
||||
}
|
||||
else {
|
||||
var listener = function () {
|
||||
if (ready()) {
|
||||
removeListener(listener);
|
||||
task[task.length - 1](taskCallback, results);
|
||||
}
|
||||
};
|
||||
addListener(listener);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.waterfall = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor !== Array) {
|
||||
var err = new Error('First argument to waterfall must be an array of functions');
|
||||
return callback(err);
|
||||
}
|
||||
if (!tasks.length) {
|
||||
return callback();
|
||||
}
|
||||
var wrapIterator = function (iterator) {
|
||||
return function (err) {
|
||||
if (err) {
|
||||
callback.apply(null, arguments);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
var next = iterator.next();
|
||||
if (next) {
|
||||
args.push(wrapIterator(next));
|
||||
}
|
||||
else {
|
||||
args.push(callback);
|
||||
}
|
||||
async.setImmediate(function () {
|
||||
iterator.apply(null, args);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
wrapIterator(async.iterator(tasks))();
|
||||
};
|
||||
|
||||
var _parallel = function(eachfn, tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor === Array) {
|
||||
eachfn.map(tasks, function (fn, callback) {
|
||||
if (fn) {
|
||||
fn(function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
callback.call(null, err, args);
|
||||
});
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
else {
|
||||
var results = {};
|
||||
eachfn.each(_keys(tasks), function (k, callback) {
|
||||
tasks[k](function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
results[k] = args;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async.parallel = function (tasks, callback) {
|
||||
_parallel({ map: async.map, each: async.each }, tasks, callback);
|
||||
};
|
||||
|
||||
async.parallelLimit = function(tasks, limit, callback) {
|
||||
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
|
||||
};
|
||||
|
||||
async.series = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor === Array) {
|
||||
async.mapSeries(tasks, function (fn, callback) {
|
||||
if (fn) {
|
||||
fn(function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
callback.call(null, err, args);
|
||||
});
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
else {
|
||||
var results = {};
|
||||
async.eachSeries(_keys(tasks), function (k, callback) {
|
||||
tasks[k](function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
results[k] = args;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async.iterator = function (tasks) {
|
||||
var makeCallback = function (index) {
|
||||
var fn = function () {
|
||||
if (tasks.length) {
|
||||
tasks[index].apply(null, arguments);
|
||||
}
|
||||
return fn.next();
|
||||
};
|
||||
fn.next = function () {
|
||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
||||
};
|
||||
return fn;
|
||||
};
|
||||
return makeCallback(0);
|
||||
};
|
||||
|
||||
async.apply = function (fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return function () {
|
||||
return fn.apply(
|
||||
null, args.concat(Array.prototype.slice.call(arguments))
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
var _concat = function (eachfn, arr, fn, callback) {
|
||||
var r = [];
|
||||
eachfn(arr, function (x, cb) {
|
||||
fn(x, function (err, y) {
|
||||
r = r.concat(y || []);
|
||||
cb(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, r);
|
||||
});
|
||||
};
|
||||
async.concat = doParallel(_concat);
|
||||
async.concatSeries = doSeries(_concat);
|
||||
|
||||
async.whilst = function (test, iterator, callback) {
|
||||
if (test()) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.whilst(test, iterator, callback);
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
async.doWhilst = function (iterator, test, callback) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (test()) {
|
||||
async.doWhilst(iterator, test, callback);
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.until = function (test, iterator, callback) {
|
||||
if (!test()) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.until(test, iterator, callback);
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
async.doUntil = function (iterator, test, callback) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (!test()) {
|
||||
async.doUntil(iterator, test, callback);
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.queue = function (worker, concurrency) {
|
||||
if (concurrency === undefined) {
|
||||
concurrency = 1;
|
||||
}
|
||||
function _insert(q, data, pos, callback) {
|
||||
if(data.constructor !== Array) {
|
||||
data = [data];
|
||||
}
|
||||
_each(data, function(task) {
|
||||
var item = {
|
||||
data: task,
|
||||
callback: typeof callback === 'function' ? callback : null
|
||||
};
|
||||
|
||||
if (pos) {
|
||||
q.tasks.unshift(item);
|
||||
} else {
|
||||
q.tasks.push(item);
|
||||
}
|
||||
|
||||
if (q.saturated && q.tasks.length === concurrency) {
|
||||
q.saturated();
|
||||
}
|
||||
async.setImmediate(q.process);
|
||||
});
|
||||
}
|
||||
|
||||
var workers = 0;
|
||||
var q = {
|
||||
tasks: [],
|
||||
concurrency: concurrency,
|
||||
saturated: null,
|
||||
empty: null,
|
||||
drain: null,
|
||||
push: function (data, callback) {
|
||||
_insert(q, data, false, callback);
|
||||
},
|
||||
unshift: function (data, callback) {
|
||||
_insert(q, data, true, callback);
|
||||
},
|
||||
process: function () {
|
||||
if (workers < q.concurrency && q.tasks.length) {
|
||||
var task = q.tasks.shift();
|
||||
if (q.empty && q.tasks.length === 0) {
|
||||
q.empty();
|
||||
}
|
||||
workers += 1;
|
||||
var next = function () {
|
||||
workers -= 1;
|
||||
if (task.callback) {
|
||||
task.callback.apply(task, arguments);
|
||||
}
|
||||
if (q.drain && q.tasks.length + workers === 0) {
|
||||
q.drain();
|
||||
}
|
||||
q.process();
|
||||
};
|
||||
var cb = only_once(next);
|
||||
worker(task.data, cb);
|
||||
}
|
||||
},
|
||||
length: function () {
|
||||
return q.tasks.length;
|
||||
},
|
||||
running: function () {
|
||||
return workers;
|
||||
}
|
||||
};
|
||||
return q;
|
||||
};
|
||||
|
||||
async.cargo = function (worker, payload) {
|
||||
var working = false,
|
||||
tasks = [];
|
||||
|
||||
var cargo = {
|
||||
tasks: tasks,
|
||||
payload: payload,
|
||||
saturated: null,
|
||||
empty: null,
|
||||
drain: null,
|
||||
push: function (data, callback) {
|
||||
if(data.constructor !== Array) {
|
||||
data = [data];
|
||||
}
|
||||
_each(data, function(task) {
|
||||
tasks.push({
|
||||
data: task,
|
||||
callback: typeof callback === 'function' ? callback : null
|
||||
});
|
||||
if (cargo.saturated && tasks.length === payload) {
|
||||
cargo.saturated();
|
||||
}
|
||||
});
|
||||
async.setImmediate(cargo.process);
|
||||
},
|
||||
process: function process() {
|
||||
if (working) return;
|
||||
if (tasks.length === 0) {
|
||||
if(cargo.drain) cargo.drain();
|
||||
return;
|
||||
}
|
||||
|
||||
var ts = typeof payload === 'number'
|
||||
? tasks.splice(0, payload)
|
||||
: tasks.splice(0);
|
||||
|
||||
var ds = _map(ts, function (task) {
|
||||
return task.data;
|
||||
});
|
||||
|
||||
if(cargo.empty) cargo.empty();
|
||||
working = true;
|
||||
worker(ds, function () {
|
||||
working = false;
|
||||
|
||||
var args = arguments;
|
||||
_each(ts, function (data) {
|
||||
if (data.callback) {
|
||||
data.callback.apply(null, args);
|
||||
}
|
||||
});
|
||||
|
||||
process();
|
||||
});
|
||||
},
|
||||
length: function () {
|
||||
return tasks.length;
|
||||
},
|
||||
running: function () {
|
||||
return working;
|
||||
}
|
||||
};
|
||||
return cargo;
|
||||
};
|
||||
|
||||
var _console_fn = function (name) {
|
||||
return function (fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
fn.apply(null, args.concat([function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (typeof console !== 'undefined') {
|
||||
if (err) {
|
||||
if (console.error) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
else if (console[name]) {
|
||||
_each(args, function (x) {
|
||||
console[name](x);
|
||||
});
|
||||
}
|
||||
}
|
||||
}]));
|
||||
};
|
||||
};
|
||||
async.log = _console_fn('log');
|
||||
async.dir = _console_fn('dir');
|
||||
/*async.info = _console_fn('info');
|
||||
async.warn = _console_fn('warn');
|
||||
async.error = _console_fn('error');*/
|
||||
|
||||
async.memoize = function (fn, hasher) {
|
||||
var memo = {};
|
||||
var queues = {};
|
||||
hasher = hasher || function (x) {
|
||||
return x;
|
||||
};
|
||||
var memoized = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
var key = hasher.apply(null, args);
|
||||
if (key in memo) {
|
||||
callback.apply(null, memo[key]);
|
||||
}
|
||||
else if (key in queues) {
|
||||
queues[key].push(callback);
|
||||
}
|
||||
else {
|
||||
queues[key] = [callback];
|
||||
fn.apply(null, args.concat([function () {
|
||||
memo[key] = arguments;
|
||||
var q = queues[key];
|
||||
delete queues[key];
|
||||
for (var i = 0, l = q.length; i < l; i++) {
|
||||
q[i].apply(null, arguments);
|
||||
}
|
||||
}]));
|
||||
}
|
||||
};
|
||||
memoized.memo = memo;
|
||||
memoized.unmemoized = fn;
|
||||
return memoized;
|
||||
};
|
||||
|
||||
async.unmemoize = function (fn) {
|
||||
return function () {
|
||||
return (fn.unmemoized || fn).apply(null, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
async.times = function (count, iterator, callback) {
|
||||
var counter = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
counter.push(i);
|
||||
}
|
||||
return async.map(counter, iterator, callback);
|
||||
};
|
||||
|
||||
async.timesSeries = function (count, iterator, callback) {
|
||||
var counter = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
counter.push(i);
|
||||
}
|
||||
return async.mapSeries(counter, iterator, callback);
|
||||
};
|
||||
|
||||
async.compose = function (/* functions... */) {
|
||||
var fns = Array.prototype.reverse.call(arguments);
|
||||
return function () {
|
||||
var that = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
async.reduce(fns, args, function (newargs, fn, cb) {
|
||||
fn.apply(that, newargs.concat([function () {
|
||||
var err = arguments[0];
|
||||
var nextargs = Array.prototype.slice.call(arguments, 1);
|
||||
cb(err, nextargs);
|
||||
}]))
|
||||
},
|
||||
function (err, results) {
|
||||
callback.apply(that, [err].concat(results));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var _applyEach = function (eachfn, fns /*args...*/) {
|
||||
var go = function () {
|
||||
var that = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
return eachfn(fns, function (fn, cb) {
|
||||
fn.apply(that, args.concat([cb]));
|
||||
},
|
||||
callback);
|
||||
};
|
||||
if (arguments.length > 2) {
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
return go.apply(this, args);
|
||||
}
|
||||
else {
|
||||
return go;
|
||||
}
|
||||
};
|
||||
async.applyEach = doParallel(_applyEach);
|
||||
async.applyEachSeries = doSeries(_applyEach);
|
||||
|
||||
async.forever = function (fn, callback) {
|
||||
function next(err) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
fn(next);
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
// AMD / RequireJS
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
define([], function () {
|
||||
return async;
|
||||
});
|
||||
}
|
||||
// Node.js
|
||||
else if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = async;
|
||||
}
|
||||
// included directly via <script> tag
|
||||
else {
|
||||
root.async = async;
|
||||
}
|
||||
|
||||
}());
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.Check
|
||||
description: Class to represent a checkbox
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event]
|
||||
provides: Form.Check
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.Check = new Class({
|
||||
Implements: [Events, Options],
|
||||
options: {
|
||||
checked: false,
|
||||
disabled: false
|
||||
},
|
||||
bound: {},
|
||||
checked: false,
|
||||
config: {
|
||||
checkedClass: 'checked',
|
||||
disabledClass: 'disabled',
|
||||
elementClass: 'check',
|
||||
highlightedClass: 'highlighted',
|
||||
storage: 'Form.Check::data'
|
||||
},
|
||||
disabled: false,
|
||||
element: null,
|
||||
input: null,
|
||||
label: null,
|
||||
value: null,
|
||||
initialize: function(input, options) {
|
||||
this.setOptions(options);
|
||||
this.bound = {
|
||||
disable: this.disable.bind(this),
|
||||
enable: this.enable.bind(this),
|
||||
highlight: this.highlight.bind(this),
|
||||
removeHighlight: this.removeHighlight.bind(this),
|
||||
keyToggle: this.keyToggle.bind(this),
|
||||
toggle: this.toggle.bind(this)
|
||||
};
|
||||
var bound = this.bound;
|
||||
input = this.input = $(input);
|
||||
var id = input.get('id');
|
||||
this.label = document.getElement('label[for=' + id + ']');
|
||||
this.element = new Element('div', {
|
||||
'class': input.get('class') + ' ' + this.config.elementClass,
|
||||
id: id ? id + 'Check' : '',
|
||||
events: {
|
||||
click: bound.toggle,
|
||||
mouseenter: bound.highlight,
|
||||
mouseleave: bound.removeHighlight
|
||||
}
|
||||
});
|
||||
this.input.addEvents({
|
||||
keypress: bound.keyToggle,
|
||||
keydown: bound.keyToggle,
|
||||
keyup: bound.keyToggle
|
||||
});
|
||||
if (this.label) { this.label.addEvent('click', bound.toggle); }
|
||||
this.element.wraps(input);
|
||||
this.value = input.get('value');
|
||||
if (this.input.checked) { this.check(); } else { this.uncheck(); }
|
||||
if (this.input.disabled) { this.disable(); } else { this.enable(); }
|
||||
input.store(this.config.storage, this).addEvents({
|
||||
blur: bound.removeHighlight,
|
||||
focus: bound.highlight
|
||||
});
|
||||
this.fireEvent('create', this);
|
||||
},
|
||||
check: function() {
|
||||
this.element.addClass(this.config.checkedClass);
|
||||
this.input.set('checked', 'checked').focus();
|
||||
this.checked = true;
|
||||
this.fireEvent('check', this);
|
||||
},
|
||||
disable: function() {
|
||||
this.element.addClass(this.config.disabledClass);
|
||||
this.input.set('disabled', 'disabled');
|
||||
this.disabled = true;
|
||||
this.fireEvent('disable', this);
|
||||
},
|
||||
enable: function() {
|
||||
this.element.removeClass(this.config.disabledClass);
|
||||
this.input.erase('disabled');
|
||||
this.disabled = false;
|
||||
this.fireEvent('enable', this);
|
||||
},
|
||||
highlight: function() {
|
||||
this.element.addClass(this.config.highlightedClass);
|
||||
this.fireEvent('highlight', this);
|
||||
},
|
||||
removeHighlight: function() {
|
||||
this.element.removeClass(this.config.highlightedClass);
|
||||
this.fireEvent('removeHighlight', this);
|
||||
},
|
||||
keyToggle: function(e) {
|
||||
var evt = (e);
|
||||
if (evt.key === 'space') { this.toggle(e); }
|
||||
},
|
||||
toggle: function(e) {
|
||||
var evt;
|
||||
if (this.disabled) { return this; }
|
||||
if (e) {
|
||||
evt = (e).stopPropagation();
|
||||
if (evt.target.tagName.toLowerCase() !== 'a') {
|
||||
evt.stop();
|
||||
}
|
||||
}
|
||||
if (this.checked) {
|
||||
this.uncheck();
|
||||
} else {
|
||||
this.check();
|
||||
}
|
||||
this.fireEvent('change', this);
|
||||
this.input.fireEvent('change', this);
|
||||
return this;
|
||||
},
|
||||
uncheck: function() {
|
||||
this.element.removeClass(this.config.checkedClass);
|
||||
this.input.erase('checked');
|
||||
this.checked = false;
|
||||
this.fireEvent('uncheck', this);
|
||||
}
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.CheckGroup
|
||||
description: Class to represent a group of Form.Check wrapped checkboxes
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Check]
|
||||
provides: Form.CheckGroup
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.CheckGroup = new Class({
|
||||
Implements: [Events,Options],
|
||||
options: {
|
||||
checkOptions: {},
|
||||
initialValues: {}
|
||||
},
|
||||
checks: [],
|
||||
initialize: function(group,options) {
|
||||
if (!Form.Check) { throw 'required Class Form.Check not found'; }
|
||||
this.setOptions(options);
|
||||
group = $(group);
|
||||
if (!group) { return this; }
|
||||
var checkboxes = group.getElements('input[type=checkbox]');
|
||||
checkboxes.each(this.addCheck,this);
|
||||
},
|
||||
addCheck: function(checkbox) {
|
||||
var initialValues = this.options.initialValues[checkbox.get('name')];
|
||||
var checkOptions = {};
|
||||
checkOptions.checked = initialValues ? initialValues.contains(checkbox.get('value')) : checkbox.get('checked');
|
||||
checkOptions.disabled = checkbox.get('disabled');
|
||||
checkbox.store('Form.CheckGroup::data',this);
|
||||
var check = checkbox.retrieve('Form.Check::data') || new Form.Check(checkbox, Object.append(checkOptions,this.options.checkOptions));
|
||||
this.checks.push(check);
|
||||
},
|
||||
checkAll: function() {
|
||||
this.checks.each(function(check) { if (!check.checked) { check.toggle(); } });
|
||||
},
|
||||
disable: function() {
|
||||
this.checks.each(function(check) { check.disable(); });
|
||||
this.fireEvent('disable',this);
|
||||
},
|
||||
enable: function() {
|
||||
this.checks.each(function(check) { check.enable(); });
|
||||
this.fireEvent('enable',this);
|
||||
},
|
||||
uncheckAll: function() {
|
||||
this.checks.each(function(check) { if (check.checked) { check.toggle(); } });
|
||||
}
|
||||
});
|
||||
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.Dropdown
|
||||
description: Class to represent a select input
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.SelectOption]
|
||||
provides: Form.Dropdown
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.Dropdown = new Class({
|
||||
Implements: [Events,Options],
|
||||
options: {
|
||||
excludedValues: [],
|
||||
initialValue: null,
|
||||
mouseLeaveDelay: 350,
|
||||
selectOptions: {},
|
||||
typeDelay: 500
|
||||
},
|
||||
bound: {},
|
||||
dropdownOptions: [],
|
||||
element: null,
|
||||
events: {},
|
||||
highlighted: null,
|
||||
input: null,
|
||||
open: true,
|
||||
selected: null,
|
||||
selection: null,
|
||||
typed: { lastKey: null, value: null, timer: null, pressed: null, shortlist: [], startkey: null },
|
||||
value: null,
|
||||
initialize: function(select,options) {
|
||||
this.setOptions(options);
|
||||
select = $(select);
|
||||
this.bound = {
|
||||
collapse: this.collapse.bind(this),
|
||||
expand: this.expand.bind(this),
|
||||
focus: this.focus.bind(this),
|
||||
highlightOption: this.highlightOption.bind(this),
|
||||
keydown: this.keydown.bind(this),
|
||||
keypress: this.keypress.bind(this),
|
||||
mouseenterDropdown: this.mouseenterDropdown.bind(this),
|
||||
mouseleaveDropdown: this.mouseleaveDropdown.bind(this),
|
||||
mousemove: this.mousemove.bind(this),
|
||||
removeHighlightOption: this.removeHighlightOption.bind(this),
|
||||
select: this.select.bind(this),
|
||||
toggle: this.toggle.bind(this)
|
||||
};
|
||||
this.events = { mouseenter: this.bound.mouseenterDropdown, mouseleave: this.bound.mouseleaveDropdown };
|
||||
this.value = this.options.initialValue;
|
||||
this.initializeCreateElements(select);
|
||||
var optionElements = select.getElements('option');
|
||||
this.updateOptions(optionElements);
|
||||
this.element.replaces(select);
|
||||
document.addEvent('click', this.bound.collapse);
|
||||
var eventName = Browser.ie || Browser.webkit ? 'keydown' : 'keypress';
|
||||
var target = Browser.ie ? $(document.body) : window;
|
||||
target.addEvent('keydown',this.bound.keydown).addEvent(eventName,this.bound.keypress);
|
||||
},
|
||||
initializeCreateElements: function(select) {
|
||||
var id = select.get('id');
|
||||
var dropdown = new Element('div', {
|
||||
'class': (select.get('class') + ' select').trim(),
|
||||
'id': (id && id !== '') ? id + 'Dropdown' : ''
|
||||
});
|
||||
var menu = new Element('div', {'class': 'menu'});
|
||||
var list = new Element('div', {'class': 'list'});
|
||||
var options = new Element('ul', {'class': 'options'});
|
||||
dropdown.adopt(menu.adopt(list.adopt(options)));
|
||||
var dropdownSelection = new Element('div', {
|
||||
'class': 'selection',
|
||||
events: {click: this.bound.toggle}
|
||||
});
|
||||
var dropdownBackground = new Element('div', { 'class': 'dropdownBackground' });
|
||||
var selection = new Element('span', { 'class': 'selectionDisplay' });
|
||||
var input = new Element('input', {
|
||||
type:'text',
|
||||
id: id,
|
||||
name: select.get('name'),
|
||||
events: {
|
||||
focus: this.bound.focus
|
||||
}
|
||||
});
|
||||
dropdownSelection.adopt(dropdownBackground, selection, input);
|
||||
dropdown.adopt(dropdownSelection);
|
||||
this.element = dropdown;
|
||||
this.selection = selection;
|
||||
this.input = input;
|
||||
return options;
|
||||
},
|
||||
collapse: function(e) {
|
||||
this.open = false;
|
||||
this.element.removeClass('active').removeClass('dropdown-active');
|
||||
if (this.selected) { this.selected.removeHighlight(); }
|
||||
this.element.removeEvents(this.events);
|
||||
this.fireEvent('collapse', [this, e]);
|
||||
},
|
||||
deselect: function(option) {
|
||||
option.deselect();
|
||||
},
|
||||
destroy: function() {
|
||||
this.element = null;
|
||||
this.selection = null;
|
||||
this.input = null;
|
||||
},
|
||||
disable: function() {
|
||||
this.collapse();
|
||||
this.input.set('disabled', 'disabled').removeEvents({blur:this.bound.blur, focus:this.bound.focus});
|
||||
this.selection.getParent().removeEvent('click', this.bound.toggle);
|
||||
this.fireEvent('disable', this);
|
||||
},
|
||||
enable: function() {
|
||||
this.input.erase('disabled').addEvents({blur:this.bound.blur, focus:this.bound.focus});
|
||||
this.selection.getParent().addEvent('click', this.bound.toggle);
|
||||
this.fireEvent('enable', this);
|
||||
},
|
||||
expand: function(e) {
|
||||
clearTimeout(this.collapseInterval);
|
||||
var evt = e ? (e).stop() : null;
|
||||
this.open = true;
|
||||
this.input.focus();
|
||||
this.element.addClass('active').addClass('dropdown-active');
|
||||
if (this.selected) { this.selected.highlight(); }
|
||||
this.element.addEvents(this.events);
|
||||
this.fireEvent('expand', [this, e]);
|
||||
},
|
||||
focus: function(e) {
|
||||
this.expand();
|
||||
},
|
||||
foundMatch: function(e) {
|
||||
var typed = this.typed;
|
||||
var shortlist = typed.shortlist;
|
||||
var value = typed.value;
|
||||
var i = 0;
|
||||
var optionsLength = shortlist.length;
|
||||
var excludedValues = this.options.excludedValues;
|
||||
var found = false;
|
||||
if (!optionsLength) { return; }
|
||||
var option;
|
||||
do {
|
||||
option = shortlist[i];
|
||||
if (option.text.toLowerCase().indexOf(value) === 0 && !excludedValues.contains(option.value)) {
|
||||
found = true;
|
||||
option.highlight(e);
|
||||
typed.pressed = i + 1;
|
||||
i = optionsLength;
|
||||
}
|
||||
i = i + 1;
|
||||
} while(i < optionsLength);
|
||||
return found;
|
||||
},
|
||||
highlightOption: function(option) {
|
||||
if (this.highlighted) { this.highlighted.removeHighlight(); }
|
||||
this.highlighted = option;
|
||||
},
|
||||
isOpen: function() {
|
||||
return this.open;
|
||||
},
|
||||
keydown: function(e) {
|
||||
if (!this.open) { return; }
|
||||
this.dropdownOptions.each(function(option) { option.disable(); });
|
||||
document.addEvent('mousemove', this.bound.mousemove);
|
||||
},
|
||||
keypress: function(e) {
|
||||
if (!this.open) { return; }
|
||||
(e).stop();
|
||||
|
||||
var code = e.code, key = e.key;
|
||||
|
||||
var typed = this.typed;
|
||||
var match, i, options, option, optionsLength, found, first, excludedValues, shortlist;
|
||||
switch(code) {
|
||||
case 38: // up
|
||||
case 37: // left
|
||||
if (typed.pressed > 0) { typed.pressed = typed.pressed - 1; }
|
||||
if (!this.highlighted) { this.dropdownOptions.getLast().highlight(e); break; }
|
||||
match = this.highlighted.element.getPrevious();
|
||||
match = match ? match.retrieve('Form.SelectOption::data') : this.dropdownOptions.getLast();
|
||||
match.highlight(e);
|
||||
break;
|
||||
case 40: // down
|
||||
case 39: // right
|
||||
if (typed.shortlist.length > 0) { typed.pressed = typed.pressed + 1; }
|
||||
if (!this.highlighted) { this.dropdownOptions[0].highlight(e); break; }
|
||||
match = this.highlighted.element.getNext();
|
||||
match = match ? match.retrieve('Form.SelectOption::data') : this.dropdownOptions[0];
|
||||
match.highlight(e);
|
||||
break;
|
||||
case 13: // enter
|
||||
e.stop();
|
||||
case 9: // tab - skips the stop event but selects the item
|
||||
this.highlighted.select();
|
||||
break;
|
||||
case 27: // esc
|
||||
e.stop();
|
||||
this.toggle();
|
||||
break;
|
||||
case 32: // space
|
||||
default: // anything else
|
||||
if (!(code >= 48 && code <= 122 && (code <= 57 || (code >= 65 && code <= 90) || code >=97) || code === 32)) {
|
||||
break;
|
||||
}
|
||||
if (evt.control || evt.alt || evt.meta) { return; }
|
||||
// alphanumeric or space
|
||||
key = code === 32 ? ' ' : key;
|
||||
clearTimeout(typed.timer);
|
||||
options = this.dropdownOptions;
|
||||
optionsLength = options.length;
|
||||
excludedValues = this.options.excludedValues;
|
||||
if (typed.timer === null) { // timer is expired
|
||||
typed.shortlist = [];
|
||||
if (key === typed.lastKey || key === typed.startkey) { // get next
|
||||
typed.pressed = typed.pressed + 1;
|
||||
typed.value = key;
|
||||
} else { // get first
|
||||
typed = this.resetTyped();
|
||||
typed.value = key;
|
||||
typed.startkey = key;
|
||||
typed.pressed = 1;
|
||||
}
|
||||
typed.timer = this.resetTyped.delay(500, this);
|
||||
} else {
|
||||
if (key === typed.lastKey) { // check for match, if no match get next
|
||||
typed.value = typed.value + key;
|
||||
if (this.foundMatch(e)) { // got a match so break
|
||||
typed.timer = this.resetTyped.delay(500, this);
|
||||
break;
|
||||
} else { // no match fall through
|
||||
typed.shortlist = [];
|
||||
typed.value = key;
|
||||
typed.pressed = typed.pressed + 1;
|
||||
typed.timer = null;
|
||||
}
|
||||
} else { // reset timer, get first match, set pressed to found position
|
||||
typed.timer = this.resetTyped.delay(500, this);
|
||||
typed.value = typed.value + key;
|
||||
typed.startkey = typed.value.substring(0, 1);
|
||||
typed.lastKey = key;
|
||||
this.foundMatch(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
typed.lastKey = key;
|
||||
shortlist = typed.shortlist;
|
||||
i = 0;
|
||||
found = 0;
|
||||
do {
|
||||
option = options[i];
|
||||
if (option.text.toLowerCase().indexOf(key) === 0 && !excludedValues.contains(option.value)) {
|
||||
if (found === 0) { first = option; }
|
||||
found = found + 1;
|
||||
if (found === typed.pressed) { option.highlight(e); }
|
||||
shortlist.push(option);
|
||||
}
|
||||
i = i + 1;
|
||||
} while(i < optionsLength);
|
||||
if (typed.pressed > found) {
|
||||
first.highlight(e);
|
||||
typed.pressed = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
mouseenterDropdown: function() {
|
||||
clearTimeout(this.collapseInterval);
|
||||
},
|
||||
mouseleaveDropdown: function() {
|
||||
this.collapseInterval = this.options.mouseLeaveDelay ? this.collapse.delay(this.options.mouseLeaveDelay,this) : null;
|
||||
},
|
||||
mousemove: function() {
|
||||
this.dropdownOptions.each(function(option) { option.enable(); });
|
||||
document.removeEvent('mousemove', this.bound.mousemove);
|
||||
},
|
||||
removeHighlightOption: function(option) {
|
||||
this.highlighted = null;
|
||||
},
|
||||
reset: function() {
|
||||
if (this.options.initialValue) {
|
||||
this.dropdownOptions.each(function(o) {
|
||||
if (o.value === this.options.initialValue) { o.select(); }
|
||||
}, this);
|
||||
} else {
|
||||
this.dropdownOptions[0].select();
|
||||
}
|
||||
},
|
||||
resetTyped: function() {
|
||||
var typed = this.typed;
|
||||
typed.value = null;
|
||||
typed.timer = null;
|
||||
return typed;
|
||||
},
|
||||
select: function(option, e) {
|
||||
this.dropdownOptions.each(this.deselect);
|
||||
this.selection.set('html', option.element.get('html'));
|
||||
var oldValue = this.value;
|
||||
this.value = option.value;
|
||||
this.input.set('value', option.value);
|
||||
this.selected = option;
|
||||
this.fireEvent('select', [this, e]);
|
||||
if (oldValue && oldValue !== this.value) { this.fireEvent('change', [this, e]); }
|
||||
this.collapse(e);
|
||||
},
|
||||
toggle: function(e) {
|
||||
if (this.open) { this.collapse(e); }
|
||||
else { this.expand(e); }
|
||||
},
|
||||
updateOptions: function(optionElements) {
|
||||
var optionsList = this.element.getElement('ul').empty(),
|
||||
dropdownOptions = this.dropdownOptions.empty(),
|
||||
selectOptions = this.options.selectOptions;
|
||||
optionElements.each(function(opt) {
|
||||
var option = new Form.SelectOption(opt, selectOptions);
|
||||
option.addEvents({
|
||||
'onHighlight':this.bound.highlightOption,
|
||||
'onRemoveHighlight':this.bound.removeHighlightOption,
|
||||
'onSelect':this.bound.select
|
||||
}).owner = this;
|
||||
if (option.value === this.options.initialValue || opt.get('selected')) { this.select(option); }
|
||||
dropdownOptions.push(option);
|
||||
optionsList.adopt(option.element);
|
||||
}, this);
|
||||
if (!this.selected && optionElements[0]) { optionElements[0].retrieve('Form.SelectOption::data').select(); }
|
||||
}
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.Radio
|
||||
description: Class to represent a radio button
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Check]
|
||||
provides: Form.Radio
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.Radio = new Class({
|
||||
Extends: Form.Check,
|
||||
config: {
|
||||
elementClass: 'radio',
|
||||
storage: 'Form.Radio::data'
|
||||
},
|
||||
initialize: function(input,options) {
|
||||
this.parent(input,options);
|
||||
},
|
||||
toggle: function(e) {
|
||||
if (this.element.hasClass('checked') || this.disabled) { return; }
|
||||
var evt;
|
||||
if (e) { evt = (e).stop(); }
|
||||
if (this.checked) {
|
||||
this.uncheck();
|
||||
} else {
|
||||
this.check();
|
||||
}
|
||||
this.fireEvent(this.checked ? 'onCheck' : 'onUncheck',this);
|
||||
this.fireEvent('onChange',this);
|
||||
}
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.RadioGroup
|
||||
description: Class to represent a group of Form.Radio buttons
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Radio]
|
||||
provides: Form.RadioGroup
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.RadioGroup = new Class({
|
||||
Implements: [Events,Options],
|
||||
options: {
|
||||
radioOptions: {},
|
||||
initialValues: {}
|
||||
},
|
||||
bound: {},
|
||||
radios: [],
|
||||
value: null,
|
||||
initialize: function(group,options) {
|
||||
if (!Form.Radio) { throw 'required Class Form.Radio not found'; }
|
||||
this.setOptions(options);
|
||||
this.bound = { select: this.select.bind(this) };
|
||||
group = $(group);
|
||||
if (!group) { return this; }
|
||||
var radios = group.getElements('input[type=radio]');
|
||||
radios.each(this.addCheck,this);
|
||||
},
|
||||
addCheck: function(radio,i) {
|
||||
var initialValues = this.options.initialValues[radio.get('name')];
|
||||
var radioOptions = {};
|
||||
radioOptions.checked = initialValues ? initialValues.contains(radio.get('value')) : radio.get('checked');
|
||||
radioOptions.disabled = radio.get('disabled');
|
||||
var check = (radio.retrieve('Form.Radio::data')
|
||||
|| new Form.Radio(radio,Object.append(radioOptions,this.options.radioOptions)));
|
||||
check.addEvent('onCheck',this.bound.select);
|
||||
if (check.checked) { i ? this.changed(check) : this.value = check.value; }
|
||||
radio.store('Form.RadioGroup::data',this);
|
||||
this.radios.push(check);
|
||||
},
|
||||
changed: function(radio) {
|
||||
this.value = radio.value;
|
||||
this.fireEvent('onChange',this);
|
||||
},
|
||||
disable: function() {
|
||||
this.radios.each(function(radio) { radio.disable(); });
|
||||
},
|
||||
enable: function() {
|
||||
this.radios.each(function(radio) { radio.enable(); });
|
||||
},
|
||||
select: function(checkedRadio) {
|
||||
this.radios.each(function(radio) {
|
||||
if (radio.checked && radio.value !== checkedRadio.value) { radio.uncheck(); }
|
||||
});
|
||||
if (checkedRadio.value !== this.value) { this.changed(checkedRadio); }
|
||||
}
|
||||
});
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Form.SelectOption
|
||||
description: Class to represent an option for Form.Dropdown
|
||||
authors: Bryan J Swift (@bryanjswift)
|
||||
license: MIT-style license.
|
||||
requires: [Core/Class.Extras, Core/Element, Core/Element.Event]
|
||||
provides: Form.SelectOption
|
||||
...
|
||||
*/
|
||||
if (typeof window.Form === 'undefined') { window.Form = {}; }
|
||||
|
||||
Form.SelectOption = new Class({
|
||||
Implements: [Events, Options],
|
||||
options: {
|
||||
optionTag: 'li',
|
||||
selected: false
|
||||
},
|
||||
config: {
|
||||
highlightedClass: 'highlighted',
|
||||
optionClass: 'option',
|
||||
selectedClass: 'selected'
|
||||
},
|
||||
element: null,
|
||||
bound: {},
|
||||
option: null,
|
||||
selected: false,
|
||||
text: null,
|
||||
value: null,
|
||||
initialize: function(option, options) {
|
||||
this.setOptions(options);
|
||||
option = $(option);
|
||||
this.option = option;
|
||||
this.bound = {
|
||||
deselect: this.deselect.bind(this),
|
||||
highlight: this.highlight.bind(this),
|
||||
removeHighlight: this.removeHighlight.bind(this),
|
||||
select: this.select.bind(this)
|
||||
};
|
||||
this.text = option.get('text');
|
||||
this.value = option.get('value');
|
||||
this.element = new Element(this.options.optionTag, {
|
||||
'class': (option.get('class') + ' ' + this.config.optionClass).trim(),
|
||||
'html': option.get('html'),
|
||||
'events': {
|
||||
click: this.bound.select,
|
||||
mouseenter: this.bound.highlight,
|
||||
mouseleave: this.bound.removeHighlight
|
||||
}
|
||||
});
|
||||
this.element.store('Form.SelectOption::data', this);
|
||||
option.store('Form.SelectOption::data', this);
|
||||
},
|
||||
deselect: function(e) {
|
||||
this.fireEvent('onDeselect', [this, e]);
|
||||
this.element.removeClass(this.config.selectedClass).addEvent('click', this.bound.select);
|
||||
this.selected = false;
|
||||
},
|
||||
destroy: function() {
|
||||
this.element = null;
|
||||
this.bound = null;
|
||||
this.option = null;
|
||||
},
|
||||
disable: function() {
|
||||
this.element.removeEvents({
|
||||
mouseenter: this.bound.highlight,
|
||||
mouseleave: this.bound.removeHighlight
|
||||
});
|
||||
this.fireEvent('onDisable', this);
|
||||
},
|
||||
enable: function() {
|
||||
this.element.addEvents({
|
||||
mouseenter: this.bound.highlight,
|
||||
mouseleave: this.bound.removeHighlight
|
||||
});
|
||||
this.fireEvent('onEnable', this);
|
||||
},
|
||||
highlight: function(e) {
|
||||
this.fireEvent('onHighlight', [this, e]);
|
||||
this.element.addClass(this.config.highlightedClass);
|
||||
return this;
|
||||
},
|
||||
removeHighlight: function(e) {
|
||||
this.fireEvent('onRemoveHighlight', [this, e]);
|
||||
this.element.removeClass(this.config.highlightedClass);
|
||||
return this;
|
||||
},
|
||||
select: function(e) {
|
||||
this.fireEvent('onSelect', [this, e]);
|
||||
this.element.addClass(this.config.selectedClass).removeEvent('click', this.bound.select);
|
||||
this.selected = true;
|
||||
}
|
||||
});
|
||||
@@ -1,176 +0,0 @@
|
||||
// packager build History/*
|
||||
/*
|
||||
---
|
||||
|
||||
name: Class.Binds
|
||||
|
||||
description: Alternate Class.Binds Implementation
|
||||
|
||||
authors: Scott Kyle (@appden), Christoph Pojer (@cpojer)
|
||||
|
||||
license: MIT-style license.
|
||||
|
||||
requires: [Core/Class, Core/Function]
|
||||
|
||||
provides: Class.Binds
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
Class.Binds = new Class({
|
||||
|
||||
$bound: {},
|
||||
|
||||
bound: function(name){
|
||||
return this.$bound[name] ? this.$bound[name] : this.$bound[name] = this[name].bind(this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
name: History
|
||||
|
||||
description: History Management via popstate or hashchange.
|
||||
|
||||
authors: Christoph Pojer (@cpojer)
|
||||
|
||||
license: MIT-style license.
|
||||
|
||||
requires: [Core/Events, Core/Element.Event, Class-Extras/Class.Binds]
|
||||
|
||||
provides: History
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
(function(){
|
||||
|
||||
var events = Element.NativeEvents,
|
||||
location = window.location,
|
||||
base = location.pathname,
|
||||
history = window.history,
|
||||
hasPushState = ('pushState' in history),
|
||||
event = hasPushState ? 'popstate' : 'hashchange';
|
||||
|
||||
this.History = new new Class({
|
||||
|
||||
Implements: [Class.Binds, Events],
|
||||
|
||||
initialize: hasPushState ? function(){
|
||||
events[event] = 2;
|
||||
window.addEvent(event, this.bound('pop'));
|
||||
} : function(){
|
||||
events[event] = 1;
|
||||
window.addEvent(event, this.bound('pop'));
|
||||
|
||||
this.hash = location.hash;
|
||||
var hashchange = ('onhashchange' in window);
|
||||
if (!(hashchange && (document.documentMode === undefined || document.documentMode > 7)))
|
||||
this.timer = this.check.periodical(200, this);
|
||||
},
|
||||
|
||||
push: hasPushState ? function(url, title, state){
|
||||
if (base && base != url) base = null;
|
||||
|
||||
history.pushState(state || null, title || null, url);
|
||||
this.onChange(url, state);
|
||||
} : function(url){
|
||||
location.hash = url;
|
||||
},
|
||||
|
||||
replace: hasPushState ? function(url, title, state){
|
||||
history.replaceState(state || null, title || null, url);
|
||||
} : function(url){
|
||||
this.hash = '#' + url;
|
||||
this.push(url);
|
||||
},
|
||||
|
||||
pop: hasPushState ? function(event){
|
||||
var url = location.pathname;
|
||||
if (url == base){
|
||||
base = null;
|
||||
return;
|
||||
}
|
||||
this.onChange(url, event.event.state);
|
||||
} : function(){
|
||||
var hash = location.hash;
|
||||
if (this.hash == hash) return;
|
||||
|
||||
this.hash = hash;
|
||||
this.onChange(hash.substr(1));
|
||||
},
|
||||
|
||||
onChange: function(url, state){
|
||||
this.fireEvent('change', [url, state || {}]);
|
||||
},
|
||||
|
||||
back: function(){
|
||||
history.back();
|
||||
},
|
||||
|
||||
forward: function(){
|
||||
history.forward();
|
||||
},
|
||||
|
||||
getPath: function(){
|
||||
return hasPushState ? location.pathname : location.hash.substr(1);
|
||||
},
|
||||
|
||||
hasPushState: function(){
|
||||
return hasPushState;
|
||||
},
|
||||
|
||||
check: function(){
|
||||
if (this.hash != location.hash) this.pop();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
name: History.handleInitialState
|
||||
|
||||
description: Provides a helper method to handle the initial state of your application.
|
||||
|
||||
authors: Christoph Pojer (@cpojer)
|
||||
|
||||
license: MIT-style license.
|
||||
|
||||
requires: [History]
|
||||
|
||||
provides: History.handleInitialState
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
History.handleInitialState = function(base){
|
||||
if (!base) base = '';
|
||||
var location = window.location,
|
||||
pathname = location.pathname.substr(base.length),
|
||||
hash = location.hash,
|
||||
hasPushState = History.hasPushState();
|
||||
|
||||
if (!hasPushState && pathname.length > 1){
|
||||
window.location = (base || '/') + '#' + pathname;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hash || hash.length <= 1) return false;
|
||||
if (hasPushState){
|
||||
(function(){
|
||||
History.push(hash.substr(1));
|
||||
}).delay(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pathname || pathname == '/') return false;
|
||||
window.location = (base || '/') + hash;
|
||||
return true;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
---
|
||||
name: Fx.Tween.CSS3.Replacement
|
||||
script: Fx.Tween.CSS3.Replacement.js
|
||||
license: MIT-style license.
|
||||
description: Same behavior like Fx.Tween but tries to use native CSS3 transition if possible (Overwrites Fx.Tween).
|
||||
copyright: Copyright (c) 2010, Dipl.-Ing. (FH) André Fiedler <kontakt at visualdrugs dot net>, based on code by eskimoblood (mootools users group)
|
||||
authors: [André Fiedler, eskimoblood]
|
||||
|
||||
requires: [Core/Class.Extras, Core/Element.Event, Core/Element.Style, Core/Fx.Tween]
|
||||
|
||||
provides: [Fx.Tween]
|
||||
...
|
||||
*/
|
||||
|
||||
Element.NativeEvents.transitionend = 2;
|
||||
Element.NativeEvents.webkitTransitionEnd = 2;
|
||||
Element.NativeEvents.oTransitionEnd = 2;
|
||||
Element.NativeEvents.msTransitionEnd = 2;
|
||||
|
||||
Element.Events.transitionend = {
|
||||
base: Browser.safari || Browser.chrome ? 'webkitTransitionEnd' : (Browser.opera ? 'oTransitionEnd' : (Browser.ie && Browser.version > 8 ? 'msTransitionEnd' : 'transitionend'))
|
||||
};
|
||||
|
||||
Event.implement({
|
||||
|
||||
getPropertyName: function(){
|
||||
return this.event.propertyName;
|
||||
},
|
||||
|
||||
getElapsedTime: function(nativeTime){
|
||||
return nativeTime ? this.event.elapsedTime : (this.event.elapsedTime * 1000).toInt();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Element.implement({
|
||||
|
||||
supportStyle: function(style){
|
||||
var value = this.style[style];
|
||||
return !!(value || value === '');
|
||||
},
|
||||
|
||||
supportVendorStyle: function(style){
|
||||
var prefixedStyle = null;
|
||||
return this.supportStyle(style) ? style : ['webkit', 'Moz', 'o', 'ms'].some(function(prefix){
|
||||
prefixedStyle = prefix + style.capitalize();
|
||||
return this.supportStyle(prefixedStyle);
|
||||
}, this) ? prefixedStyle : null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Fx.TweenCSS2 = Fx.Tween;
|
||||
|
||||
Fx.Tween = new Class({
|
||||
|
||||
Extends: Fx.TweenCSS2,
|
||||
|
||||
transitionTimings: {
|
||||
'linear' : '0,0,1,1',
|
||||
'expo:in' : '0.71,0.01,0.83,0',
|
||||
'expo:out' : '0.14,1,0.32,0.99',
|
||||
'expo:in:out' : '0.85,0,0.15,1',
|
||||
'circ:in' : '0.34,0,0.96,0.23',
|
||||
'circ:out' : '0,0.5,0.37,0.98',
|
||||
'circ:in:out' : '0.88,0.1,0.12,0.9',
|
||||
'sine:in' : '0.22,0.04,0.36,0',
|
||||
'sine:out' : '0.04,0,0.5,1',
|
||||
'sine:in:out' : '0.37,0.01,0.63,1',
|
||||
'quad:in' : '0.14,0.01,0.49,0',
|
||||
'quad:out' : '0.01,0,0.43,1',
|
||||
'quad:in:out' : '0.47,0.04,0.53,0.96',
|
||||
'cubic:in' : '0.35,0,0.65,0',
|
||||
'cubic:out' : '0.09,0.25,0.24,1',
|
||||
'cubic:in:out' : '0.66,0,0.34,1',
|
||||
'quart:in' : '0.69,0,0.76,0.17',
|
||||
'quart:out' : '0.26,0.96,0.44,1',
|
||||
'quart:in:out' : '0.76,0,0.24,1',
|
||||
'quint:in' : '0.64,0,0.78,0',
|
||||
'quint:out' : '0.22,1,0.35,1',
|
||||
'quint:in:out' : '0.9,0,0.1,1'
|
||||
},
|
||||
|
||||
initialize: function(element, options){
|
||||
options.transition = options.transition || 'sine:in:out';
|
||||
this.parent(element, options);
|
||||
if (typeof this.options.transition != 'string') alert('Only short notated transitions (like \'sine:in\') are supported by Fx.Tween.CSS3');
|
||||
this.options.transition = this.options.transition.toLowerCase();
|
||||
this.transition = this.element.supportVendorStyle('transition');
|
||||
this.css3Supported = !!this.transition && !!this.transitionTimings[this.options.transition];
|
||||
},
|
||||
|
||||
check: function(){
|
||||
if (!this.boundComplete) return true;
|
||||
return this.parent();
|
||||
},
|
||||
|
||||
start: function(property, from, to){
|
||||
if (this.css3Supported){
|
||||
if (!this.check(property, from, to)) return this;
|
||||
var args = Array.flatten(arguments);
|
||||
this.property = this.options.property || args.shift();
|
||||
var parsed = this.prepare(this.element, this.property, args);
|
||||
this.from = parsed.from;
|
||||
this.to = parsed.to;
|
||||
this.boundComplete = function(event){
|
||||
if (event.getPropertyName() == this.property /* && event.getElapsedTime() == this.options.duration */ ){
|
||||
this.element.removeEvent('transitionend', this.boundComplete);
|
||||
this.boundComplete = null;
|
||||
this.fireEvent('complete', this);
|
||||
}
|
||||
}.bind(this);
|
||||
this.element.addEvent('transitionend', this.boundComplete);
|
||||
var trans = function(){
|
||||
this.element.setStyle(this.transition, this.property + ' ' + this.options.duration + 'ms cubic-bezier(' + this.transitionTimings[this.options.transition] + ')');
|
||||
this.element.setStyle(this.property, this.to[0].value + this.options.unit);
|
||||
}.bind(this);
|
||||
if (args[1]){
|
||||
this.element.setStyle(this.transition, 'none');
|
||||
this.element.setStyle(this.property, this.from[0].value + this.options.unit);
|
||||
trans.delay(0.1);
|
||||
} else
|
||||
trans();
|
||||
this.fireEvent('start', this);
|
||||
return this;
|
||||
}
|
||||
return this.parent(property, from, to);
|
||||
},
|
||||
|
||||
cancel: function(){
|
||||
if (this.css3Supported){
|
||||
this.element.setStyle(this.transition, 'none');
|
||||
this.element.removeEvent('transitionend', this.boundComplete);
|
||||
this.boundComplete = null;
|
||||
}
|
||||
this.parent();
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,301 +0,0 @@
|
||||
//fgnass.github.com/spin.js#v1.2.4
|
||||
(function(window, document, undefined) {
|
||||
|
||||
/**
|
||||
* Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
||||
var prefixes = ['webkit', 'Moz', 'ms', 'O']; /* Vendor prefixes */
|
||||
var animations = {}; /* Animation rules keyed by their name */
|
||||
var useCssAnimations;
|
||||
|
||||
/**
|
||||
* Utility function to create elements. If no tag name is given,
|
||||
* a DIV is created. Optionally properties can be passed.
|
||||
*/
|
||||
function createEl(tag, prop) {
|
||||
var el = document.createElement(tag || 'div');
|
||||
var n;
|
||||
|
||||
for(n in prop) {
|
||||
el[n] = prop[n];
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends children and returns the parent.
|
||||
*/
|
||||
function ins(parent /* child1, child2, ...*/) {
|
||||
for (var i=1, n=arguments.length; i<n; i++) {
|
||||
parent.appendChild(arguments[i]);
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new stylesheet to hold the @keyframe or VML rules.
|
||||
*/
|
||||
var sheet = function() {
|
||||
var el = createEl('style');
|
||||
ins(document.getElementsByTagName('head')[0], el);
|
||||
return el.sheet || el.styleSheet;
|
||||
}();
|
||||
|
||||
/**
|
||||
* Creates an opacity keyframe animation rule and returns its name.
|
||||
* Since most mobile Webkits have timing issues with animation-delay,
|
||||
* we create separate rules for each line/segment.
|
||||
*/
|
||||
function addAnimation(alpha, trail, i, lines) {
|
||||
var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-');
|
||||
var start = 0.01 + i/lines*100;
|
||||
var z = Math.max(1-(1-alpha)/trail*(100-start) , alpha);
|
||||
var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
|
||||
var pre = prefix && '-'+prefix+'-' || '';
|
||||
|
||||
if (!animations[name]) {
|
||||
sheet.insertRule(
|
||||
'@' + pre + 'keyframes ' + name + '{' +
|
||||
'0%{opacity:'+z+'}' +
|
||||
start + '%{opacity:'+ alpha + '}' +
|
||||
(start+0.01) + '%{opacity:1}' +
|
||||
(start+trail)%100 + '%{opacity:'+ alpha + '}' +
|
||||
'100%{opacity:'+ z + '}' +
|
||||
'}', 0);
|
||||
animations[name] = 1;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries various vendor prefixes and returns the first supported property.
|
||||
**/
|
||||
function vendor(el, prop) {
|
||||
var s = el.style;
|
||||
var pp;
|
||||
var i;
|
||||
|
||||
if(s[prop] !== undefined) return prop;
|
||||
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
|
||||
for(i=0; i<prefixes.length; i++) {
|
||||
pp = prefixes[i]+prop;
|
||||
if(s[pp] !== undefined) return pp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets multiple style properties at once.
|
||||
*/
|
||||
function css(el, prop) {
|
||||
for (var n in prop) {
|
||||
el.style[vendor(el, n)||n] = prop[n];
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in default values.
|
||||
*/
|
||||
function merge(obj) {
|
||||
for (var i=1; i < arguments.length; i++) {
|
||||
var def = arguments[i];
|
||||
for (var n in def) {
|
||||
if (obj[n] === undefined) obj[n] = def[n];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute page-offset of the given element.
|
||||
*/
|
||||
function pos(el) {
|
||||
var o = {x:el.offsetLeft, y:el.offsetTop};
|
||||
while((el = el.offsetParent)) {
|
||||
o.x+=el.offsetLeft;
|
||||
o.y+=el.offsetTop;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
var defaults = {
|
||||
lines: 12, // The number of lines to draw
|
||||
length: 7, // The length of each line
|
||||
width: 5, // The line thickness
|
||||
radius: 10, // The radius of the inner circle
|
||||
color: '#000', // #rgb or #rrggbb
|
||||
speed: 1, // Rounds per second
|
||||
trail: 100, // Afterglow percentage
|
||||
opacity: 1/4, // Opacity of the lines
|
||||
fps: 20, // Frames per second when using setTimeout()
|
||||
zIndex: 2e9, // Use a high z-index by default
|
||||
className: 'spinner', // CSS class to assign to the element
|
||||
top: 'auto', // center vertically
|
||||
left: 'auto' // center horizontally
|
||||
};
|
||||
|
||||
/** The constructor */
|
||||
var Spinner = function Spinner(o) {
|
||||
if (!this.spin) return new Spinner(o);
|
||||
this.opts = merge(o || {}, Spinner.defaults, defaults);
|
||||
};
|
||||
|
||||
Spinner.defaults = {};
|
||||
Spinner.prototype = {
|
||||
spin: function(target) {
|
||||
this.stop();
|
||||
var self = this;
|
||||
var o = self.opts;
|
||||
var el = self.el = css(createEl(0, {className: o.className}), {position: 'relative', zIndex: o.zIndex});
|
||||
var mid = o.radius+o.length+o.width;
|
||||
var ep; // element position
|
||||
var tp; // target position
|
||||
|
||||
if (target) {
|
||||
target.insertBefore(el, target.firstChild||null);
|
||||
tp = pos(target);
|
||||
ep = pos(el);
|
||||
css(el, {
|
||||
left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : o.left+mid) + 'px',
|
||||
top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : o.top+mid) + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
el.setAttribute('aria-role', 'progressbar');
|
||||
self.lines(el, self.opts);
|
||||
|
||||
if (!useCssAnimations) {
|
||||
// No CSS animation support, use setTimeout() instead
|
||||
var i = 0;
|
||||
var fps = o.fps;
|
||||
var f = fps/o.speed;
|
||||
var ostep = (1-o.opacity)/(f*o.trail / 100);
|
||||
var astep = f/o.lines;
|
||||
|
||||
!function anim() {
|
||||
i++;
|
||||
for (var s=o.lines; s; s--) {
|
||||
var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity);
|
||||
self.opacity(el, o.lines-s, alpha, o);
|
||||
}
|
||||
self.timeout = self.el && setTimeout(anim, ~~(1000/fps));
|
||||
}();
|
||||
}
|
||||
return self;
|
||||
},
|
||||
stop: function() {
|
||||
var el = this.el;
|
||||
if (el) {
|
||||
clearTimeout(this.timeout);
|
||||
if (el.parentNode) el.parentNode.removeChild(el);
|
||||
this.el = undefined;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
lines: function(el, o) {
|
||||
var i = 0;
|
||||
var seg;
|
||||
|
||||
function fill(color, shadow) {
|
||||
return css(createEl(), {
|
||||
position: 'absolute',
|
||||
width: (o.length+o.width) + 'px',
|
||||
height: o.width + 'px',
|
||||
background: color,
|
||||
boxShadow: shadow,
|
||||
transformOrigin: 'left',
|
||||
transform: 'rotate(' + ~~(360/o.lines*i) + 'deg) translate(' + o.radius+'px' +',0)',
|
||||
borderRadius: (o.width>>1) + 'px'
|
||||
});
|
||||
}
|
||||
for (; i < o.lines; i++) {
|
||||
seg = css(createEl(), {
|
||||
position: 'absolute',
|
||||
top: 1+~(o.width/2) + 'px',
|
||||
transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
|
||||
opacity: o.opacity,
|
||||
animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite'
|
||||
});
|
||||
if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}));
|
||||
ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')));
|
||||
}
|
||||
return el;
|
||||
},
|
||||
opacity: function(el, i, val) {
|
||||
if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// VML rendering for IE
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Check and init VML support
|
||||
*/
|
||||
!function() {
|
||||
var s = css(createEl('group'), {behavior: 'url(#default#VML)'});
|
||||
var i;
|
||||
|
||||
if (!vendor(s, 'transform') && s.adj) {
|
||||
|
||||
// VML support detected. Insert CSS rules ...
|
||||
for (i=4; i--;) sheet.addRule(['group', 'roundrect', 'fill', 'stroke'][i], 'behavior:url(#default#VML)');
|
||||
|
||||
Spinner.prototype.lines = function(el, o) {
|
||||
var r = o.length+o.width;
|
||||
var s = 2*r;
|
||||
|
||||
function grp() {
|
||||
return css(createEl('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s});
|
||||
}
|
||||
|
||||
var margin = -(o.width+o.length)*2+'px';
|
||||
var g = css(grp(), {position: 'absolute', top: margin, left: margin});
|
||||
|
||||
var i;
|
||||
|
||||
function seg(i, dx, filter) {
|
||||
ins(g,
|
||||
ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
|
||||
ins(css(createEl('roundrect', {arcsize: 1}), {
|
||||
width: r,
|
||||
height: o.width,
|
||||
left: o.radius,
|
||||
top: -o.width>>1,
|
||||
filter: filter
|
||||
}),
|
||||
createEl('fill', {color: o.color, opacity: o.opacity}),
|
||||
createEl('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (o.shadow) {
|
||||
for (i = 1; i <= o.lines; i++) {
|
||||
seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
|
||||
}
|
||||
}
|
||||
for (i = 1; i <= o.lines; i++) seg(i);
|
||||
return ins(el, g);
|
||||
};
|
||||
Spinner.prototype.opacity = function(el, i, val, o) {
|
||||
var c = el.firstChild;
|
||||
o = o.shadow && o.lines || 0;
|
||||
if (c && i+o < c.childNodes.length) {
|
||||
c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild;
|
||||
if (c) c.opacity = val;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
useCssAnimations = vendor(s, 'animation');
|
||||
}
|
||||
}();
|
||||
|
||||
window.Spinner = Spinner;
|
||||
|
||||
})(window, document);
|
||||
Reference in New Issue
Block a user