pebble-clay
Version:
Pebble Config Framework
1,382 lines (1,272 loc) • 160 kB
JavaScript
// minified.js config start -- use this comment to re-create a configuration in the Builder
// - Only sections add, always, amdsupport, copyobj, dollardollar,
// - each, eachobj, equals, error, extend, find, format, formathtml, get, ht,
// - html, isobject, off, on, ready, request, select, set, template, trigger,
// - underscore, wait.
// WARNING! This file is autogenerated from minified-master.js and others.
/*
* Minified.js - Lightweight Client-Side JavaScript Library (full package)
* Version: Version 2014 beta 5 b2
*
* Public Domain. Use, modify and distribute it any way you like. No attribution required.
* To the extent possible under law, Tim Jansen has waived all copyright and related or neighboring rights to Minified.
* Please see http://creativecommons.org/publicdomain/zero/1.0/.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*
* Contains code based on https://github.com/douglascrockford/JSON-js (also Public Domain).
*
* https://github.com/timjansen/minified.js
*/
// ==ClosureCompiler==
// @output_file_name minified.js
// @compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
/*$
* @id ALL
* @doc no
* @required
* This id allows identifying whether both Web and Util are available.
*/
///#snippet commonAmdStart
/*$
* @id require
* @name require()
* @syntax require(name)
* @group OPTIONS
* @module WEB, UTIL
* Returns a reference to a module. If you do not use an AMD loader to load Minified, just call <var>require()</var> with the
* argument 'minified' to get a reference to Minified. You can also access all modules defined using ##define().
*
* If you do use an AMD loader, Minified will not define this function and you can use the AMD loader to obtain the
* reference to Minified.
* Minified's version of <var>require</var> is very simple and will only support Minified and other libraries designed
* for Minfied, but <strong>no real AMD libraries</strong>. If you need to work with libraries requiring AMD, you need a real AMD loader.
*
* @param name the name of the module to request. Minified is available as 'minified'.
* @return the reference to the module. Use the name 'minified' to get Minified. You can also access any modules defined using
* ##define(). If the name is unknown, it returns <var>undefined</var>.
*
* @see ##define() allows you to define modules that can be obtained using <var>require()</var>.
*/
/*$
* @id define
* @name define()
* @syntax define(name, factoryFunction)
* @group OPTIONS
* @module WEB, UTIL
* Defines a module that can be returned by ##require(), in case you don't have a AMD loader. If you have a AMD loader before you include Minified,
* <var>define()</var> will not be set and you can use the AMD loader's (more powerful) variant.
*
* Minified's versions of <var>require()</var> and <var>define()</var> are very simple and can not resolve things like circular references.
* Also, they are not AMD-compatible and only useful for simple modules. If you need to work with real AMD libraries that are not written
* for Minified, you need a real AMD loader.
*
* @example Creates a simple module and uses it:
* <pre>
* define('makeGreen', function(require) {
* var MINI = require('minified'), $ = MINI.$; // obtain own ref to Minified
* return function(list) {
* $(list).set({$color: '#0f0', $backgroundColor: '#050'});
* });
* });
*
* var makeGreen = require('makeGreen');
* makeGreen('.notGreenEnough');
* </pre>
*
* @param name the name of the module to request. In Minified's implementation, only 'minified' is supported.
* @param factoryFunction is a <code>function(require)</code> will be called the first time the name is defined to obtain the module
* reference. It received a reference to ##require() (which is required for AMD backward-compatibility) and
* must return the value that is returned by ##require(). The function will only be called once, its result will
* be cached.
* <dl><dt>require</dt><dd>A reference to ##require(). While you could use <var>require()</var> from the global
* context, this would prevent backward compatibility with AMD.</dd>
* <dt class="returnValue">(callback return value)</dt><dd>The reference to be returned by ##require().</dd></dl>
*
* @see ##require() can be used to obtain references defined with ##define().
*/
/*$
* @id amdsupport
* @name AMD stubs
* @configurable default
* @group OPTIONS
* @doc no
* @module WEB, UTIL
* If enabled, Minified will create stubs so you can use it without an AMD framework.
* It requires AMD's <code>define()</code> function.
*/
if (/^u/.test(typeof define)) { // no AMD support available ? define a minimal version
(function(def){
var require = this['require'] = function(name) { return def[name]; };
this['define'] = function(name, f) { def[name] = def[name] || f(require); };
})({});
}
/*$
* @stop
*/
define('minified', function() {
///#/snippet commonAmdStart
///#snippet webVars
/*$
* @id WEB
* @doc no
* @required
* This id allows identifying whether the Web module is available.
*/
/**
* @const
*/
var _window = window;
/**
* @const
* @type {!string}
*/
var MINIFIED_MAGIC_NODEID = 'Nia';
/**
* @const
* @type {!string}
*/
var MINIFIED_MAGIC_PREV = 'NiaP';
var setter = {}, getter = {};
var idSequence = 1; // used as node id to identify nodes, and as general id for other maps
/*$
* @id ready_vars
* @dependency
*/
/** @type {!Array.<function()>} */
var DOMREADY_HANDLER = /^[ic]/.test(document['readyState']) ? _null : []; // check for 'interactive' and 'complete'
/*$
* @stop
*/
///#/snippet webVars
///#snippet utilVars
/*$
* @id UTIL
* @doc no
* @required
* This id allows identifying whether the Util module is available.
*/
var _null = null;
/** @const */
var undef;
/*$
* @id date_constants
* @dependency
*/
function val3(v) {return v.substr(0,3);}
var MONTH_LONG_NAMES = split('January,February,March,April,May,June,July,August,September,October,November,December', /,/g);
var MONTH_SHORT_NAMES = map(MONTH_LONG_NAMES, val3); // ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var WEEK_LONG_NAMES = split('Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday', /,/g);
var WEEK_SHORT_NAMES = map(WEEK_LONG_NAMES, val3);
var MERIDIAN_NAMES = split('am,pm', /,/g);
var MERIDIAN_NAMES_FULL = split('am,am,am,am,am,am,am,am,am,am,am,am,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm', /,/g);
var FORMAT_DATE_MAP = {
'y': ['FullYear', nonOp],
'Y': ['FullYear', function(d) { return d % 100; }],
'M': ['Month', plusOne],
'n': ['Month', MONTH_SHORT_NAMES],
'N': ['Month', MONTH_LONG_NAMES],
'd': ['Date', nonOp],
'm': ['Minutes', nonOp],
'H': ['Hours', nonOp],
'h': ['Hours', function(d) { return (d % 12) || 12; }],
'k': ['Hours', plusOne],
'K': ['Hours', function(d) { return d % 12; }],
's': ['Seconds', nonOp],
'S': ['Milliseconds', nonOp],
'a': ['Hours', MERIDIAN_NAMES_FULL],
'w': ['Day', WEEK_SHORT_NAMES],
'W': ['Day', WEEK_LONG_NAMES],
'z': ['TimezoneOffset', function(d, dummy, timezone) {
if (timezone)
return timezone;
var sign = d > 0 ? '-' : '+';
var off = d < 0 ? -d : d;
return sign + pad(2, Math.floor(off/60)) + pad(2, off%60);
}]
};
var PARSE_DATE_MAP = {
'y': 0, // placeholder -> ctorIndex
'Y': [0, -2000],
'M': [1,1], // placeholder -> [ctorIndex, offset|value array]
'n': [1, MONTH_SHORT_NAMES],
'N': [1, MONTH_LONG_NAMES],
'd': 2,
'm': 4,
'H': 3,
'h': 3,
'K': [3,1],
'k': [3,1],
's': 5,
'S': 6,
'a': [3, MERIDIAN_NAMES]
};
/*$
* @stop
*/
/** @const */
var MAX_CACHED_TEMPLATES = 99;
var templateCache={}; // template -> function
var templates = []; // list of MAX_CACHED_TEMPLATES templates
///#/snippet utilVars
///#snippet commonFunctions
/** @param s {?} */
function toString(s) {
return s!=_null ? ''+s : '';
}
/**
* @param s {?}
* @param o {string}
*/
function isType(s,o) {
return typeof s == o;
}
/** @param s {?} */
function isString(s) {
return isType(s, 'string');
}
function isObject(f) {
return !!f && isType(f, 'object');
}
function isNode(n) {
return n && n['nodeType'];
}
function isNumber(n) {
return isType(n, 'number');
}
function isDate(n) {
return isObject(n) && !!n['getDay'];
}
function isBool(n) {
return n === true || n === false;
}
function isValue(n) {
var type = typeof n;
return type == 'object' ? !!(n && n['getDay']) : (type == 'string' || type == 'number' || isBool(n));
}
function nonOp(v) {
return v;
}
function plusOne(d) {
return d+1;
}
function replace(s, regexp, sub) {
return toString(s).replace(regexp, sub != _null ? sub : '');
}
function escapeRegExp(s) {
return replace(s, /[\\\[\]\/{}()*+?.$|^-]/g, "\\$&");
}
function trim(s) {
return replace(s, /^\s+|\s+$/g);
}
function eachObj(obj, cb, ctx) {
for (var n in obj)
if (obj.hasOwnProperty(n))
cb.call(ctx || obj, n, obj[n]);
return obj;
}
function each(list, cb, ctx) {
if (list)
for (var i = 0; i < list.length; i++)
cb.call(ctx || list, list[i], i);
return list;
}
function filter(list, filterFuncOrObject, ctx) {
var r = [];
var f = isFunction(filterFuncOrObject) ? filterFuncOrObject : function(value) { return filterFuncOrObject != value; };
each(list, function(value, index) {
if (f.call(ctx || list, value, index))
r.push(value);
});
return r;
}
function collector(iterator, obj, collectFunc, ctx) {
var result = [];
iterator(obj, function (a, b) {
if (isList(a = collectFunc.call(ctx || obj, a, b))) // extreme variable reusing: a is now the callback result
each(a, function(rr) { result.push(rr); });
else if (a != _null)
result.push(a);
});
return result;
}
function collectObj(obj, collectFunc, ctx) {
return collector(eachObj, obj, collectFunc, ctx);
}
function collect(list, collectFunc, ctx) {
return collector(each, list, collectFunc, ctx);
}
function keyCount(obj) {
var c = 0;
eachObj(obj, function(key) { c++; });
return c;
}
function keys(obj) { // use Object.keys? in IE>=9
var list = [];
eachObj(obj, function(key) { list.push(key); });
return list;
}
function map(list, mapFunc, ctx) {
var result = [];
each(list, function(item, index) {
result.push(mapFunc.call(ctx || list, item, index));
});
return result;
}
function startsWith(base, start) {
if (isList(base)) {
var s2 = _(start); // convert start as we don't know whether it is a list yet
return equals(sub(base, 0, s2.length), s2);
}
else
return start != _null && base.substr(0, start.length) == start;
}
function endsWith(base, end) {
if (isList(base)) {
var e2 = _(end);
return equals(sub(base, -e2.length), e2) || !e2.length;
}
else
return end != _null && base.substr(base.length - end.length) == end;
}
function reverse(list) {
var len = list.length;
if (isList(list))
return new M(map(list, function() { return list[--len]; }));
else
return replace(list, /[\s\S]/g, function() { return list.charAt(--len); });
}
function toObject(list, value) {
var obj = {};
each(list, function(item, index) {
obj[item] = value;
});
return obj;
}
function copyObj(from, to) {
var dest = to || {};
for (var name in from)
dest[name] = from[name];
return dest;
}
function merge(list, target) {
var o = target;
for (var i = 0; i < list.length; i++)
o = copyObj(list[i], o);
return o;
}
function getFindFunc(findFunc) {
return isFunction(findFunc) ? findFunc : function(obj, index) { if (findFunc === obj) return index; };
}
function getFindIndex(list, index, defaultIndex) {
return index == _null ? defaultIndex : index < 0 ? Math.max(list.length+index, 0) : Math.min(list.length, index);
}
function find(list, findFunc, startIndex, endIndex) {
var f = getFindFunc(findFunc);
var e = getFindIndex(list, endIndex, list.length);
var r;
for (var i = getFindIndex(list, startIndex, 0); i < e; i++)
if ((r = f.call(list, list[i], i)) != _null)
return r;
}
function findLast(list, findFunc, startIndex, endIndex) {
var f = getFindFunc(findFunc);
var e = getFindIndex(list, endIndex, -1);
var r;
for (var i = getFindIndex(list, startIndex, list.length-1); i > e; i--)
if ((r = f.call(list, list[i], i)) != _null)
return r;
}
function sub(list, startIndex, endIndex) {
var r = [];
if (list) {
var e = getFindIndex(list, endIndex, list.length);
for (var i = getFindIndex(list, startIndex, 0); i < e; i++)
r.push(list[i]);
}
return r;
}
function array(list) {
return map(list, nonOp);
}
function unite(list) {
return function() {
return new M(callList(list, arguments));
};
}
function uniq(list) {
var found = {};
return filter(list, function(item) {
if (found[item])
return false;
else
return found[item] = 1;
});
}
function intersection(list, otherList) {
var keys = toObject(otherList, 1);
return filter(list, function(item) {
var r = keys[item];
keys[item] = 0;
return r;
});
}
function contains(list, value) { // TODO: can Array.indexOf be used in >IE8?
for (var i = 0; i < list.length; i++)
if (list[i] == value)
return true;
return false;
}
// equals if a and b have the same elements and all are equal. Supports getters.
function equals(x, y) {
var a = isFunction(x) ? x() : x;
var b = isFunction(y) ? y() : y;
var aKeys;
if (a == b)
return true;
else if (a == _null || b == _null)
return false;
else if (isValue(a) || isValue(b))
return isDate(a) && isDate(b) && +a==+b;
else if (isList(a)) {
return (a.length == b.length) &&
!find(a, function(val, index) {
if (!equals(val, b[index]))
return true;
});
}
else {
return !isList(b) &&
((aKeys = keys(a)).length == keyCount(b)) &&
!find(aKeys, function(key) {
if (!equals(a[key],b[key]))
return true;
});
}
}
function call(f, fThisOrArgs, args) {
if (isFunction(f))
return f.apply(args && fThisOrArgs, map(args || fThisOrArgs, nonOp));
}
function callList(list, fThisOrArgs, args) {
return map(list, function(f) { return call(f, fThisOrArgs, args);});
}
function bind(f, fThis, beforeArgs, afterArgs) {
return function() {
return call(f, fThis, collect([beforeArgs, arguments, afterArgs], nonOp));
};
}
function partial(f, beforeArgs, afterArgs) {
return bind(f, this, beforeArgs, afterArgs);
}
function pad(digits, number) {
var signed = number < 0 ? '-' : '';
var preDecimal = (signed?-number:number).toFixed(0);
while (preDecimal.length < digits)
preDecimal = '0' + preDecimal;
return signed + preDecimal;
}
function processNumCharTemplate(tpl, input, fwd) {
var inHash;
var inputPos = 0;
var rInput = fwd ? input : reverse(input);
var s = (fwd ? tpl : reverse(tpl)).replace(/./g, function(tplChar) {
if (tplChar == '0') {
inHash = false;
return rInput.charAt(inputPos++) || '0';
}
else if (tplChar == '#') {
inHash = true;
return rInput.charAt(inputPos++) || '';
}
else
return inHash && !rInput.charAt(inputPos) ? '' : tplChar;
});
return fwd ? s : (input.substr(0, input.length - inputPos) + reverse(s));
}
function getTimezone(match, idx, refDate) { // internal helper, see below
if (idx == _null || !match)
return 0;
return parseFloat(match[idx]+match[idx+1])*60 + parseFloat(match[idx]+match[idx+2]) + refDate.getTimezoneOffset();
}
// formats number with format string (e.g. "#.000", "#,#", "00000", "000.00", "000.000.000,00", "000,000,000.##")
// choice syntax: <cmp><value>:<format>|<cmp><value>:<format>|...
// e.g. 0:no item|1:one item|>=2:# items
// <value>="null" used to compare with nulls.
// choice also works with strings or bools, e.g. ERR:error|WAR:warning|FAT:fatal|ok
function formatValue(fmt, value) {
var format = replace(fmt, /^\?/);
if (isDate(value)) {
var timezone, match;
if (match = /^\[(([+-])(\d\d)(\d\d))\]\s*(.*)/.exec(format)) {
timezone = match[1];
value = dateAdd(value, 'minutes', getTimezone(match, 2, value));
format = match[5];
}
return replace(format, /(\w)(\1*)(?:\[([^\]]+)\])?/g, function(s, placeholderChar, placeholderDigits, params) {
var val = FORMAT_DATE_MAP[placeholderChar];
if (val) {
var d = value['get' + val[0]]();
var optionArray = (params && params.split(','));
if (isList(val[1]))
d = (optionArray || val[1])[d];
else
d = val[1](d, optionArray, timezone);
if (d != _null && !isString(d))
d = pad(placeholderDigits.length+1, d);
return d;
}
else
return s;
});
}
else
return find(format.split(/\s*\|\s*/), function(fmtPart) {
var match, numFmtOrResult;
if (match = /^([<>]?)(=?)([^:]*?)\s*:\s*(.*)$/.exec(fmtPart)) {
var cmpVal1 = value, cmpVal2 = +(match[3]);
if (isNaN(cmpVal2) || !isNumber(cmpVal1)) {
cmpVal1 = (cmpVal1==_null) ? "null" : toString(cmpVal1); // not ""+value, because undefined is treated as null here
cmpVal2 = match[3];
}
if (match[1]) {
if ((!match[2] && cmpVal1 == cmpVal2 ) ||
(match[1] == '<' && cmpVal1 > cmpVal2) ||
(match[1] == '>' && cmpVal1 < cmpVal2))
return _null;
}
else if (cmpVal1 != cmpVal2)
return _null;
numFmtOrResult = match[4];
}
else
numFmtOrResult = fmtPart;
if (isNumber(value))
return numFmtOrResult.replace(/[0#](.*[0#])?/, function(numFmt) {
var decimalFmt = /^([^.]+)(\.)([^.]+)$/.exec(numFmt) || /^([^,]+)(,)([^,]+)$/.exec(numFmt);
var signed = value < 0 ? '-' : '';
var numData = /(\d+)(\.(\d+))?/.exec((signed?-value:value).toFixed(decimalFmt ? decimalFmt[3].length:0));
var preDecimalFmt = decimalFmt ? decimalFmt[1] : numFmt;
var postDecimal = decimalFmt ? processNumCharTemplate(decimalFmt[3], replace(numData[3], /0+$/), true) : '';
return (signed ? '-' : '') +
(preDecimalFmt == '#' ? numData[1] : processNumCharTemplate(preDecimalFmt, numData[1])) +
(postDecimal.length ? decimalFmt[2] : '') +
postDecimal;
});
else
return numFmtOrResult;
});
}
// returns date; null if optional and not set; undefined if parsing failed
function parseDate(fmt, date) {
var indexMap = {}; // contains reGroupPosition -> typeLetter or [typeLetter, value array]
var reIndex = 1;
var timezoneOffsetMatch;
var timezoneIndex;
var match;
var format = replace(fmt, /^\?/);
if (format!=fmt && !trim(date))
return _null;
if (match = /^\[([+-])(\d\d)(\d\d)\]\s*(.*)/.exec(format)) {
timezoneOffsetMatch = match;
format = match[4];
}
var parser = new RegExp(format.replace(/(.)(\1*)(?:\[([^\]]*)\])?/g, function(wholeMatch, placeholderChar, placeholderDigits, param) {
if (/[dmhkyhs]/i.test(placeholderChar)) {
indexMap[reIndex++] = placeholderChar;
var plen = placeholderDigits.length+1;
return "(\\d"+(plen<2?"+":("{1,"+plen+"}"))+")";
}
else if (placeholderChar == 'z') {
timezoneIndex = reIndex;
reIndex += 3;
return "([+-])(\\d\\d)(\\d\\d)";
}
else if (/[Nna]/.test(placeholderChar)) {
indexMap[reIndex++] = [placeholderChar, param && param.split(',')];
return "([a-zA-Z\\u0080-\\u1fff]+)";
}
else if (/w/i.test(placeholderChar))
return "[a-zA-Z\\u0080-\\u1fff]+";
else if (/\s/.test(placeholderChar))
return "\\s+";
else
return escapeRegExp(wholeMatch);
}));
if (!(match = parser.exec(date)))
return undef;
var ctorArgs = [0, 0, 0, 0, 0, 0, 0];
for (var i = 1; i < reIndex; i++) {
var matchVal = match[i];
var indexEntry = indexMap[i];
if (isList(indexEntry)) { // for a, n or N
var placeholderChar = indexEntry[0];
var mapEntry = PARSE_DATE_MAP[placeholderChar];
var ctorIndex = mapEntry[0];
var valList = indexEntry[1] || mapEntry[1];
var listValue = find(valList, function(v, index) { if (startsWith(matchVal.toLowerCase(), v.toLowerCase())) return index; });
if (listValue == _null)
return undef;
if (placeholderChar == 'a')
ctorArgs[ctorIndex] += listValue * 12;
else
ctorArgs[ctorIndex] = listValue;
}
else if (indexEntry) { // for numeric values (yHmMs)
var value = parseFloat(matchVal);
var mapEntry = PARSE_DATE_MAP[indexEntry];
if (isList(mapEntry))
ctorArgs[mapEntry[0]] += value - mapEntry[1];
else
ctorArgs[mapEntry] += value;
}
}
var d = new Date(ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4], ctorArgs[5], ctorArgs[6]);
return dateAdd(d, 'minutes', -getTimezone(timezoneOffsetMatch, 1, d) - getTimezone(match, timezoneIndex, d));
}
// format ?##00,00##
// returns number; null if optional and not set; undefined if parsing failed
function parseNumber(fmt, value) {
var format = replace(fmt, /^\?/);
if (format!=fmt && !trim(value))
return _null;
var decSep = (/(^|[^0#.,])(,|[0#.]*,[0#]+|[0#]+\.[0#]+\.[0#.,]*)($|[^0#.,])/.test(format)) ? ',' : '.';
var r = parseFloat(replace(replace(replace(value, decSep == ',' ? /\./g : /,/g), decSep, '.'), /^[^\d-]*(-?\d)/, '$1'));
return isNaN(r) ? undef : r;
}
function now() {
return new Date();
}
function dateClone(date) {
return new Date(+date);
}
function capWord(w) {
return w.charAt(0).toUpperCase() + w.substr(1);
}
function dateAddInline(d, cProp, value) {
d['set'+cProp](d['get'+cProp]() + value);
return d;
}
function dateAdd(date, property, value) {
if (value == _null)
return dateAdd(now(), date, property);
return dateAddInline(dateClone(date), capWord(property), value);
}
function dateMidnight(date) {
var od = date || now();
return new Date(od.getFullYear(), od.getMonth(), od.getDate());
}
function dateDiff(property, date1, date2) {
var d1t = +date1;
var d2t = +date2;
var dt = d2t - d1t;
if (dt < 0)
return -dateDiff(property, date2, date1);
var propValues = {'milliseconds': 1, 'seconds': 1000, 'minutes': 60000, 'hours': 3600000};
var ft = propValues[property];
if (ft)
return dt / ft;
var cProp = capWord(property);
var calApproxValues = {'fullYear': 8.64e7*365, 'month': 8.64e7*365/12, 'date': 8.64e7}; // minimum values, a little bit below avg values
var minimumResult = Math.floor((dt / calApproxValues[property])-2); // -2 to remove the imperfections caused by the values above
var d = dateAddInline(new Date(d1t), cProp, minimumResult);
for (var i = minimumResult; i < minimumResult*1.2+4; i++) { // try out 20% more than needed, just to be sure
if (+dateAddInline(d, cProp, 1) > d2t)
return i;
}
// should never ever be reached
}
function ucode(a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}
function escapeJavaScriptString(s) {
return replace(s, /[\x00-\x1f'"\u2028\u2029]/g, ucode);
}
// reimplemented split for IE8
function split(str, regexp) {
return str.split(regexp);
}
function template(template, escapeFunction) {
if (templateCache[template])
return templateCache[template];
else {
var funcBody = 'with(_.isObject(obj)?obj:{}){'+
map(split(template, /{{|}}}?/g), function(chunk, index) {
var match, c1 = trim(chunk), c2 = replace(c1, /^{/), escapeSnippet = (c1==c2) ? 'esc(' : '';
if (index%2) { // odd means JS code
if (match = /^each\b(\s+([\w_]+(\s*,\s*[\w_]+)?)\s*:)?(.*)/.exec(c2))
return 'each('+(trim(match[4])?match[4]:'this')+', function('+match[2]+'){';
else if (match = /^if\b(.*)/.exec(c2))
return 'if('+match[1]+'){';
else if (match = /^else\b\s*(if\b(.*))?/.exec(c2))
return '}else ' + (match[1] ? 'if('+match[2] +')' : '')+'{';
else if (match = /^\/(if)?/.exec(c2))
return match[1] ? '}\n' : '});\n';
else if (match = /^(var\s.*)/.exec(c2))
return match[1]+';';
else if (match = /^#(.*)/.exec(c2))
return match[1];
else if (match = /(.*)::\s*(.*)/.exec(c2))
return 'print('+escapeSnippet+'_.formatValue("'+escapeJavaScriptString(match[2])+'",'+(trim(match[1])?match[1]:'this')+(escapeSnippet&&')')+'));\n';
else
return 'print('+escapeSnippet+(trim(c2)?c2:'this')+(escapeSnippet&&')')+');\n';
}
else if (chunk){
return 'print("'+escapeJavaScriptString(chunk)+'");\n';
}
}).join('')+'}';
var f = (new Function('obj', 'each', 'esc', 'print', '_', funcBody));
var t = function(obj, thisContext) {
var result = [];
f.call(thisContext || obj, obj, function(obj, func) {
if (isList(obj))
each(obj, function(value, index) { func.call(value, value, index); });
else
eachObj(obj, function(key, value) { func.call(value, key, value); });
}, escapeFunction || nonOp, function() {call(result['push'], result, arguments);}, _);
return result.join('');
};
if (templates.push(t) > MAX_CACHED_TEMPLATES)
delete templateCache[templates.shift()];
return templateCache[template] = t;
}
}
function escapeHtml(s) {
return replace(s, /[<>'"&]/g, function(s) {
return '&#'+s.charCodeAt(0)+';';
});
}
function formatHtml(tpl, obj) {
return template(tpl, escapeHtml)(obj);
}
function listBindArray(func) {
return function(arg1, arg2) {
return new M(func(this, arg1, arg2));
};
}
function listBind(func) {
return function(arg1, arg2, arg3) {
return func(this, arg1, arg2, arg3);
};
}
function funcArrayBind(func) {
return function(arg1, arg2, arg3) {
return new M(func(arg1, arg2, arg3));
};
}
///#/snippet commonFunctions
///#snippet webFunctions
// note: only the web version has the f.item check
function isFunction(f) {
return typeof f == 'function' && !f['item']; // item check as work-around for webkit bug 14547
}
function isList(v) {
return v && v.length != _null && !isString(v) && !isNode(v) && !isFunction(v) && v !== _window;
}
// used by IE impl of on() only
function push(obj, prop, value) {
(obj[prop] = (obj[prop] || [])).push(value);
}
// used by IE impl of on()/off() only
function removeFromArray(array, value) {
for (var i = 0; array && i < array.length; i++)
if (array[i] === value)
array['splice'](i--, 1);
}
function extractNumber(v) {
return parseFloat(replace(v, /^[^\d-]+/));
}
// retrieves the node id of the element, create one if needed.
function getNodeId(el) {
return (el[MINIFIED_MAGIC_NODEID] = (el[MINIFIED_MAGIC_NODEID] || ++idSequence));
}
// collect variant that filters out duplicate nodes from the given list, returns a new array
function collectUniqNodes(list, func) {
var result = [];
var nodeIds = {};
var currentNodeId;
flexiEach(list, function(value) {
flexiEach(func(value), function(node) {
if (!nodeIds[currentNodeId = getNodeId(node)]) {
result.push(node);
nodeIds[currentNodeId] = true;
}
});
});
return result;
}
// finds out the 'natural' height of the first element, the one if $$slide=1
function getNaturalHeight(elementList, factor) {
var q = {'$position': 'absolute', '$visibility': 'hidden', '$display': 'block', '$height': _null};
var oldStyles = elementList['get'](q);
var h = elementList['set'](q)['get']('clientHeight');
elementList['set'](oldStyles);
return h*factor + 'px';
}
// @condblock !ie8compatibility
function on(subSelector, eventSpec, handler, args, bubbleSelector) {
if (isFunction(eventSpec))
return this['on'](_null, subSelector, eventSpec, handler, args);
else if (isString(args))
return this['on'](subSelector, eventSpec, handler, _null, args);
else
return this['each'](function(baseElement, index) {
flexiEach(subSelector ? dollarRaw(subSelector, baseElement) : baseElement, function(registeredOn) {
flexiEach(toString(eventSpec).split(/\s/), function(namePrefixed) {
var name = replace(namePrefixed, /[?|]/g);
var prefix = replace(namePrefixed, /[^?|]/g);
var capture = (name == 'blur' || name == 'focus') && !!bubbleSelector; // bubble selectors for 'blur' and 'focus' registered as capuring!
var triggerId = idSequence++;
// returns true if processing should be continued
function triggerHandler(eventName, event, target) {
var match = !bubbleSelector;
var el = bubbleSelector ? target : registeredOn;
if (bubbleSelector) {
var selectorFilter = getFilterFunc(bubbleSelector, registeredOn);
while (el && el != registeredOn && !(match = selectorFilter(el)))
el = el['parentNode'];
}
return (!match) || (name != eventName) || ((handler.apply($(el), args || [event, index]) && prefix=='?') || prefix == '|');
};
function eventHandler(event) {
if (!triggerHandler(name, event, event['target'])) {
event['preventDefault']();
event['stopPropagation']();
}
};
registeredOn.addEventListener(name, eventHandler, capture);
if (!registeredOn['M'])
registeredOn['M'] = {};
registeredOn['M'][triggerId] = triggerHandler; // to be called by trigger()
handler['M'] = collector(flexiEach, [handler['M'], function () { // this function will be called by off()
registeredOn.removeEventListener(name, eventHandler, capture);
delete registeredOn['M'][triggerId];
}], nonOp);
});
});
});
}
// @condend !ie8compatibility
// @condblock !ie8compatibility
function off(handler) {
callList(handler['M']);
handler['M'] = _null;
}
// @condend !ie8compatibility
// for remove & window.unload, IE only
function detachHandlerList(dummy, handlerList) {
flexiEach(handlerList, function(h) {
h.element.detachEvent('on'+h.eventType, h.handlerFunc);
});
}
function ready(handler) {
if (DOMREADY_HANDLER)
DOMREADY_HANDLER.push(handler);
else
setTimeout(handler, 0);
}
function $$(selector, context, childrenOnly) {
return dollarRaw(selector, context, childrenOnly)[0];
}
function EE(elementName, attributes, children) {
var e = $(document.createElement(elementName));
// @condblock UTIL
// this attributes != null check is only required with Util's isObject() implementation. Web's isObject() is simpler.
return (isList(attributes) || (attributes != _null && !isObject(attributes)) ) ? e['add'](attributes) : e['set'](attributes)['add'](children);
// @condend UTIL
// @cond !UTIL return (isList(attributes) || (!isObject(attributes)) ) ? e['add'](attributes) : e['set'](attributes)['add'](children);
}
function clone(listOrNode) {
return collector(flexiEach, listOrNode, function(e) {
var c;
if (isList(e))
return clone(e);
else if (isNode(e)) {
c = e['cloneNode'](true);
c['removeAttribute'] && c['removeAttribute']('id');
return c;
}
else
return e;
});
}
/*$
* @stop
*/
function $(selector, context, childOnly) {
// @condblock ready
return isFunction(selector) ? ready(selector) : new M(dollarRaw(selector, context, childOnly));
// @condend
// @cond !ready return new M(dollarRaw(selector, context));
}
// implementation of $ that does not produce a Minified list, but just an array
// @condblock !ie7compatibility
function dollarRaw(selector, context, childOnly) {
function flatten(a) { // flatten list, keep non-lists, remove nulls
return isList(a) ? collector(flexiEach, a, flatten) : a;
}
function filterElements(list) { // converts into array, makes sure context is respected
return filter(collector(flexiEach, list, flatten), function(node) {
var a = node;
while (a = a['parentNode'])
if (a == context[0] || childOnly)
return a == context[0];
// fall through to return undef
});
}
if (context) {
if ((context = dollarRaw(context)).length != 1)
return collectUniqNodes(context, function(ci) { return dollarRaw(selector, ci, childOnly);});
else if (isString(selector)) {
if (isNode(context[0]) != 1)
return [];
else
return childOnly ? filterElements(context[0].querySelectorAll(selector)) : context[0].querySelectorAll(selector);
}
else
return filterElements(selector);
}
else if (isString(selector))
return document.querySelectorAll(selector);
else
return collector(flexiEach, selector, flatten);
};
// @condend !ie7compatibility
// If context is set, live updates will be possible.
// Please note that the context is not evaluated for the '*' and 'tagname.classname' patterns, because context is used only
// by on(), and in on() only nodes in the right context will be checked
function getFilterFunc(selector, context) {
function wordRegExpTester(name, prop) {
var re = RegExp('(^|\\s+)' + name + '(?=$|\\s)', 'i');
return function(obj) {return name ? re.test(obj[prop]) : true;};
}
var nodeSet = {};
var dotPos = nodeSet;
if (isFunction(selector))
return selector;
else if (isNumber(selector))
return function(v, index) { return index == selector; };
else if (!selector || selector == '*' ||
(isString(selector) && (dotPos = /^([\w-]*)\.?([\w-]*)$/.exec(selector)))) {
var nodeNameFilter = wordRegExpTester(dotPos[1], 'tagName');
var classNameFilter = wordRegExpTester(dotPos[2], 'className');
return function(v) {
return isNode(v) == 1 && nodeNameFilter(v) && classNameFilter(v);
};
}
else if (context)
return function(v) {
return $(selector, context)['find'](v)!=_null; // live search instead of node set, for on()
};
else {
$(selector)['each'](function(node) {
nodeSet[getNodeId(node)] = true;
});
return function(v) {
return nodeSet[getNodeId(v)];
};
}
}
function getInverseFilterFunc(selector) {
var f = getFilterFunc(selector);
return function(v) {return f(v) ? _null : true;};
}
///#/snippet webFunctions
///#snippet extrasFunctions
function flexiEach(list, cb) {
if (isList(list))
each(list, cb);
else if (list != _null)
cb(list, 0);
return list;
}
function Promise() {
this['state'] = null;
this['values'] = [];
this['parent'] = null;
}
/*$
* @id promise
* @name _.promise()
* @syntax _.promise()
* @syntax _.promise(otherPromises...)
* @module WEB+UTIL
*
* Creates a new ##promiseClass#Promise##, optionally assimilating other promises. If no other promise is given,
* a fresh new promise is returned.
*
* The returned promise provides the methods ##fulfill() and ##reject() that can be called directly to change the promise's state,
* as well as the more powerful ##fire().
*
* If one promise is given as parameter, the new promise assimilates the given promise as-is, and just forwards
* fulfillment and rejection with the original values.
*
* If more than one promise are given, it will assimilate all of them with slightly different rules:
* <ul><li>the new promise is fulfilled if all assimilated promises have been fulfilled. The fulfillment values
* of all assimilated promises are given to the handler as arguments. Note that the fulfillment values themselves are always
* arrays, as a promise can have several fulfillment values in Minified's implementation.</li>
* <li>when one of the promises is rejected, the new promise is rejected immediately. The rejection handler gets the
* promises rejection value (first argument if it got several) as first argument, an array of the result values
* of all promises as a second (that means one array of arguments for each promise), and the index of the failed
* promise as third.
* </li></ul>
*
* @example A simple promise that is fulfilled after 1 second, using Minified's invocation syntax:
* <pre>var p = _.promise();
* setTimeout(function() {
* p.fire(true);
* }, 1000);
* </pre>
*
* @example Request three files in parallel. When all three have been downloaded, concatenate them into a single string.
* <pre>
* var files = _('fileA.txt', 'fileA.txt', 'fileC.txt');
* var content;
* _.promise(files.map(function(file) {
* return $.request('get', '/txts/' + file);
* })).then(function(fileRslt1, fileRslt2, fileRslt3) {
* content = _(fileRslt1, fileRslt2, fileRslt3).map( function(result) { return result[0]; }).join('');
* }).error(function(status, response, xhr, url) {
* alert('failed to load file '+url);
* });
* </pre>
*
* @param otherPromises one or more promises to assimilate (varargs). You can also pass lists of promises.
* @return the new promise.
*/
function promise() {
var deferred = []; // this function calls the functions supplied by then()
var assimilatedPromises = arguments;
var assimilatedNum = assimilatedPromises.length;
var numCompleted = 0; // number of completed, assimilated promises
var rejectionHandlerNum = 0;
var obj = new Promise();
obj['errHandled'] = function() {
rejectionHandlerNum++;
if (obj['parent'])
obj['parent']['errHandled']();
};
/*$
* @id fire
* @name promise.fire()
* @syntax _.fire(newState)
* @syntax _.fire(newState, values)
* @module WEB+UTIL
*
* Changes the state of the promise into either fulfilled or rejected. This will also notify all ##then() handlers. If the promise
* already has a state, the call will be ignored.
*
* <var>fire()</var> can be invoked as a function without context ('this'). Every promise has its own instance.
*
* @example A simple promise that is fulfilled after 1 second, using Minified's invocation syntax:
* <pre>var p = _.promise();
* setTimeout(function() {
* p.fire(true, []);
* }, 1000);
* </pre>
*
* @example Call <var>fire()</var> without a context:
* <pre>var p = _.promise(function(resolve, reject) {
* setTimeout(resolve.fire, 1000);
* });
* </pre>
*
* @param newState <var>true</var> to set the Promise to fulfilled, <var>false</var> to set the state as rejected. If you pass <var>null</var> or
* <var>undefined</var>, the promise's state does not change.
* @param values optional an array of values to pass to ##then() handlers as arguments. You can also pass a non-list argument, which will then
* be passed as only argument.
* @return the promise
*/
var fire = obj['fire'] = function(newState, newValues) {
if (obj['state'] == null && newState != null) {
obj['state'] = !!newState;
obj['values'] = isList(newValues) ? newValues : [newValues];
setTimeout(function() {
each(deferred, function(f) {f();});
}, 0);
}
return obj;
};
// use promise varargs
each(assimilatedPromises, function assimilate(promise, index) {
try {
if (promise['then'])
promise['then'](function(v) {
var then;
if ((isObject(v) || isFunction(v)) && isFunction(then = v['then']))
assimilate(v, index);
else {
obj['values'][index] = array(arguments);
if (++numCompleted == assimilatedNum)
fire(true, assimilatedNum < 2 ? obj['values'][index] : obj['values']);
}
},
function(e) {
obj['values'][index] = array(arguments);
fire(false, assimilatedNum < 2 ? obj['values'][index] : [obj['values'][index][0], obj['values'], index]);
});
else
promise(function() {fire(true, array(arguments));}, function() {fire(false, array(arguments)); });
}
catch (e) {
fire(false, [e, obj['values'], index]);
}
});
/*$
* @id stop
* @name promise.stop()
* @syntax promise.stop()
* @module WEB+UTIL
* Stops an ongoing operation, if supported. Currently the only promises supporting this are those returned by ##request(), ##animate(), ##wait() and
* ##asyncEach().
* stop() invocation will be propagated over promises returned by ##then() and promises assimilated by ##promise(). You only need to invoke stop
* with the last promise, and all dependent promises will automatically stop as well.
*
* <var>stop()</var> can be invoked as a function without context ('this'). Every promise has its own instance.
*
* @return In some cases, the <var>stop()</var> can return a value. This is currently only done by ##animate() and ##wait(), which will return the actual duration.
* ##asyncEach()'s promise will also return any value it got from the promise that it stopped.
*
* @example Animation chain that can be stopped.
* <pre>
* var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
* var prom = div.animate({$left: '200px', $top: '0px'}, 600, 0)
* .then(function() {
* return _.promise(div.animate({$left: '200px', $top: '200px'}, 800, 0),
* div.animate({$backgroundColor: '#f00'}, 200));
* }).then(function() {
* return div.animate({$left: '100px', $top: '100px'}, 400);
* });
*
* $('#stopButton').on('click', prom.stop);
* </pre>
*/
obj['stop'] = function() {
each(assimilatedPromises, function(promise) {
if (promise['stop'])
promise['stop']();
});
return obj['stop0'] && call(obj['stop0']);
};
/*$
* @id then
* @name promise.then()
* @syntax promise.then()
* @syntax promise.then(onSuccess)
* @syntax promise.then(onSuccess, onError)
*
* @module WEB
* Registers two callbacks that will be invoked when the ##promise#Promise##'s asynchronous operation finished
* successfully (<var>onSuccess</var>) or an error occurred (<var>onError</var>). The callbacks will be called after
* <var>then()</var> returned, from the browser's event loop.
* You can chain <var>then()</var> invocations, as <var>then()</var> returns another Promise object that you can attach to.
*
* The full distribution of Minified implements the Promises/A+ specification, allowing interoperability with other Promises frameworks.
*
* <strong>Note:</strong> If you use the Web module, you will get a simplified Promises implementation that cuts some corners. The most notable
* difference is that when a <code>then()</code> handler throws an exception, this will not be caught and the promise returned by
* <code>then</code> will not be automatically rejected.
*
* @example Simple handler for an HTTP request. Handles only success and ignores errors.
* <pre>
* $.request('get', '/weather.html')
* .then(function(txt) {
* alert('Got response!');
* });
* </pre>
*
* @example Including an error handler.
* <pre>
* $.request('get', '/weather.html')
* .then(function(txt) {
* alert('Got response!');
* }, function(err) {
* alert('Error!');
* }));
* </pre>
*
* @example Chained handler.
* <pre>
* $.request('get', '/weather.do')
* .then(function(txt) {
* showWeather(txt);
* }
* .then(function() {
* return $.request('get', '/traffic.do');
* }
* .then(function(txt) {
* showTraffic(txt);
* }
* .then(function() {
* alert('All result displayed');
* }, function() {
* alert('An error occurred');
* });
* </pre>
*
* @param onSuccess optional a callback function to be called when the operation has been completed successfully. The exact arguments it receives depend on the operation.
* If the function returns a ##promise#Promise##, that Promise will be evaluated to determine the state of the promise returned by <var>then()</var>. If it returns any other value, the
* returned Promise will also succeed. If the function throws an error, the returned Promise will be in error state.
* Pass <var>null</var> or <var>undefined</var> if you do not need the success handler.
* @param onError optional a callback function to be called when the operation failed. The exact arguments it receives depend on the operation. If the function returns a ##promise#Promise##, that promise will
* be evaluated to determine the state of the Promise returned by <var>then()</var>. If it returns anything else, the returned Promise will
* have success status. If the function throws an error, the returned Promise will be in the error state.
* You can pass <var>null</var> or <var>undefined</var> if you do not need the error handler.
* @return a new ##promise#Promise## object. If you specified a callback for success or error, the new Promises's state will be determined by that callback if it is called.
* If no callback has been provided and the original Promise changes to that state, the new Promise will change to that state as well.
*/
var then = obj['then'] = function (onFulfilled, onRejected) {
var promise2 = promise();
var callCallbacks = function() {
try {
var f = (obj['state'] ? onFulfilled : onRejected);
if (isFunction(f)) {
(function resolve(x) {
try {
var then, cbCalled = 0;
if ((isObject(x) || isFunction(x)) && isFunction(then = x['then'])) {
if (x === promise2)
throw new TypeError();
then.call(x, function(x) { if (!cbCalled++) resolve(x); }, function(value) { if (!cbCalled++) promise2['fire'](false, [value]);});
promise2['stop0'] = x['stop'];
}
else
promise2['fire'](true, [x]);
}
catch(e) {
if (!(cbCalled++)) {
promise2['fire'](false, [e]);
if (!rejectionHandlerNum)
throw e;
}
}
})(call(f, undef, obj['values']));
}
else
promise2['fire'](obj['state'], obj['values']);
}
catch (e) {
promise2['fire'](false, [e]);
if (!rejectionHandlerNum)
throw e;
}
};
if (isFunction(onRejected))
obj['errHandled']();
promise2['stop0'] = obj['stop'];
promise2['parent'] = obj;
if (obj['state'] != null)
setTimeout(callCallbacks, 0);
else
deferred.push(callCallbacks);
return promise2;
};
/*$
* @id always
* @group REQUEST
* @name promise.always()
* @syntax promise.always(callback)
* @configurable default
* @module WEB+UTIL
* Registers a callback that will always be called when the ##promise#Promise##'s operation ended, no matter whether the operation succeeded or not.
* This is a convenience function that will call ##th