// 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 require() 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 require is very simple and will only support Minified and other libraries designed * for Minfied, but no real AMD libraries. 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 undefined. * * @see ##define() allows you to define modules that can be obtained using require(). */ /*$ * @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, * define() will not be set and you can use the AMD loader's (more powerful) variant. * * Minified's versions of require() and define() 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: *
 * 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');
 * 
* * @param name the name of the module to request. In Minified's implementation, only 'minified' is supported. * @param factoryFunction is a function(require) 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. *
require
A reference to ##require(). While you could use require() from the global * context, this would prevent backward compatibility with AMD.
*
(callback return value)
The reference to be returned by ##require().
* * @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 define() 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.} */ 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: :|:|... // e.g. 0:no item|1:one item|>=2:# items // ="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: *
  • 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.
  • *
  • 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. *
* * @example A simple promise that is fulfilled after 1 second, using Minified's invocation syntax: *
var p = _.promise();
   * setTimeout(function() {
   *     p.fire(true);
   * }, 1000);
   * 
* * @example Request three files in parallel. When all three have been downloaded, concatenate them into a single string. *
   * 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);
   * });
   * 
* * @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. * * fire() 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: *
var p = _.promise();
     * setTimeout(function() {
     *     p.fire(true, []);
     * }, 1000);
     * 
* * @example Call fire() without a context: *
var p = _.promise(function(resolve, reject) {
     *     setTimeout(resolve.fire, 1000);
     * });
     * 
* * @param newState true to set the Promise to fulfilled, false to set the state as rejected. If you pass null or * undefined, 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. * * stop() can be invoked as a function without context ('this'). Every promise has its own instance. * * @return In some cases, the stop() 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. *
     * 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);
     * 
*/ 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 (onSuccess) or an error occurred (onError). The callbacks will be called after * then() returned, from the browser's event loop. * You can chain then() invocations, as then() 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. * * Note: 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 then() handler throws an exception, this will not be caught and the promise returned by * then will not be automatically rejected. * * @example Simple handler for an HTTP request. Handles only success and ignores errors. *
     * $.request('get', '/weather.html')
     *     .then(function(txt) {
     *        alert('Got response!');
     *     });
     * 
* * @example Including an error handler. *
     * $.request('get', '/weather.html')
     *     .then(function(txt) {
     *        alert('Got response!');
     *     }, function(err) {
     *        alert('Error!');
     *     }));
     * 
* * @example Chained handler. *
     * $.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');
     *     });
     * 
* * @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 then(). 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 null or undefined 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 then(). 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 null or undefined 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 ##then() with the same function for both arguments. It shares all of its semantics. * * @example Simple handler for a HTTP request. *
     * $.request('get', '/weather.html')
     *     .always(function() {
     *        alert('Got response or error!');
     *     });
     * 
* * @param callback a function to be called when the operation has been finished, no matter what its result was. The exact arguments depend on the operation and may * vary depending on whether it succeeded or not. If the function returns a ##promise#Promise##, that Promise will * be evaluated to determine the state of the returned Promise. If provided and it returns regularly, the returned promise will * have success status. If it throws an error, the returned Promise will be in the error state. * @return a new ##promise#Promise## object. Its state is determined by the callback. */ obj['always'] = function(func) { return then(func, func); }; /*$ * @id error * @group REQUEST * @name promise.error() * @syntax promise.error(callback) * @configurable default * @module WEB, UTIL * Registers a callback that will be called when the operation failed. * This is a convenience function that will invoke ##then() with only the second argument set. It shares all of its semantics. * * @example Simple handler for a HTTP request. *
     * $.request('get', '/weather.html')
     *     .error(function() {
     *        alert('Got error!');
     *     });
     * 
* * @param callback a function to be called when the operation has failed. The exact arguments depend on the operation. If the function returns a ##promise#Promise##, that Promise will * be evaluated to determine the state of the returned Promise. If it returns regularly, the returned Promise will * have success status. If it throws an error, the returned Promise will be in error state. * @return a new ##promise#Promise## object. Its state is determined by the callback. */ obj['error'] = function(func) { return then(0, func); }; return obj; } ///#/snippet extrasFunctions ///#snippet extrasDocs /*$ * @id length * @group SELECTORS * @requires dollar * @name list.length * @syntax length * @module WEB, UTIL * * Contains the number of elements in the ##list#Minified list##. * * @example With Web module: *
   * var list = $('input');
   * var myValues = {};
   * for (var i = 0; i < list.length; i++)
   *    myValues[list[i].name] = list[i].value;
   * 
* * @example With Util module: *
   * var list = _(1, 2, 3);
   * var sum = 0;
   * for (var i = 0; i < list.length; i++)
   *    sum += list[i];
   * 
*/ /*$ * @stop */ ///#/snippet extrasDocs ///#snippet utilM /* * syntax: M(list, assimilateSublists) * M(null, singleElement) * * */ /** @constructor */ function M(list, assimilateSublists) { var self = this, idx = 0; if (list) for (var i = 0, len = list.length; i < len; i++) { var item = list[i]; if (assimilateSublists && isList(item)) for (var j = 0, len2 = item.length; j < len2; j++) self[idx++] = item[j]; else self[idx++] = item; } else self[idx++] = assimilateSublists; self['length'] = idx; self['_'] = true; } function _() { return new M(arguments, true); } ///#/snippet utilM //// LIST FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// copyObj({ ///#snippet utilListFuncs /*$ * @id each * @group LIST * @requires * @configurable default * @name .each() * @altname _.each() * @syntax list.each(callback) * @syntax list.each(callback, ctx) * @syntax _.each(list, callback) * @syntax _.each(list, callback, ctx) * @module UTIL, WEB * Invokes the given function once for each item in the list. The function will be called with the item as first parameter and * the zero-based index as second. Unlike JavaScript's built-in forEach() it will be invoked for each item in the list, * even if it is undefined. * * @example Creates the sum of all list entries. *
     * var sum = 0;
     * _(17, 4, 22).each(function(item, index) {
     *     sum += item;
     * });
     * 
* * @example The previous example with a native array: *
     * var sum = 0;
     * _.each([17, 4, 22], function(item, index) {
     *     sum += item;
     * });
     * 
* * @example This goes through all h2 elements of the class 'section' on a web page and changes their content: *
     * $('h2.section').each(function(item, index) {
     *     item.innerHTML = 'Section ' + index + ': ' + item.innerHTML;
     * });
     * 
* * @param list a list to iterate. Can be an array, a ##list#Minified list## or any other array-like structure with * length property. * @param callback The callback function(item, index) to invoke for each list element. *
item
The current list element.
*
index
The second the zero-based index of the current element.
*
this
The given context if not null. Otherwise the list.
* The callback's return value will be ignored. * @param ctx optional a context to pass to the callback as 'this'. Only supported in UTIL module. * @return the list * * @see ##per() works like each(), but wraps the list elements in a list. * @see ##find() can be used instead of each() if you need to abort the loop. * @see ##eachObj() iterates through the properties of an object. */ 'each': listBind(each), /*$ * @id equals * @group LIST * @requires * @configurable default * @name .equals() * @altname _.equals() * @syntax list.equals(otherObject) * @syntax _.equals(thisObject, otherObject) * @module UTIL * Checks whether two values, lists or objects are equal in a deep comparison. * * First equals() checks whether it got a function as parameter. * If yes, it will be invoked without arguments and equals() calls itself recursively with the function's result. * * Once both values are no functions anymore, the values will be evaluated, If the first value is... *
  • ...null or undefined, they are only equal if the other one is also either null or undefined.
  • *
  • ...a value as defined by ##_.isValue(), but not a Date, they are equal if the other value is the same type and is equal according to the '==' operator.
  • *
  • ...a Date, they are equal if the other value is a Date representing the same time.
  • *
  • ...a list or array, they are equal if the other value is also either a list or an array, has the same number of items and all items equal the items of the other * list at the same position. The equality of list items is determined recursively using the same rules, so you can also nest lists.
  • *
  • ...a function, it will be invoked without arguments and its return value is evaluated using these rules as if the value has been passed.
  • *
  • ...any other object, they are equal if they contain exactly the same keys (as defined by ##_.eachObj()) and all values are equal as determined using these rules * recursively.
  • *
* * Please note that, according to the rules, a ##list#Minified list## is equal to an array, as long as their content is equal. equals does not * differentiate between null and undefined. * * equals is commutative. If you swap the parameters, the result is the same as long as no functions are involved. * * @example Compare a list and an array: *
     *  _.equals([1, 2, 3], _(1, 2, 3));  // returns true
     * 
* * @example Same result, but with a list method: *
     *  _(1, 2, 3).equals([1, 2, 3]);  // returns true
     * 
* * @param thisObject The first reference to evaluate. * @param otherObject The second reference to evaluate. * @return true if both references are equal. False otherwise. */ 'equals': listBind(equals), /*$ * @id find * @group LIST * @requires * @configurable default * @name .find() * @altname _.find() * @syntax list.find(findFunc) * @syntax list.find(element) * @syntax list.find(findFunc, startIndex) * @syntax list.find(element, startIndex) * @syntax _.find(list, findFunc) * @syntax _.find(list, element) * @syntax _.find(list, findFunc, startIndex) * @syntax _.find(list, element, startIndex) * @module WEB, UTIL * Finds a specific value in the list. There are two ways of calling find(): *
    *
  1. With a value as argument. Then find() will search for the first occurrence of an identical value in the list, * using the '===' operator for comparisons, and return the index. If it is not found, * find() returns undefined.
  2. *
  3. With a callback function. find() will then call the given function for each list element until the function * returns a value that is not null or undefined. This value will be returned.
  4. *
* * find() can also be used as an alternative to ##each() if you need to abort the loop. * * @example Finds the first negative number in the list: *
     * var i = _(1, 2, -4, 5, 2, -1).find(function(value, index) { if (value < 0) return index; }); // returns 2
     * 
* @example Finds the index of the first 5 in the array: *
     * var i = _.find([3, 6, 7, 6, 5, 4, 5], 5); // returns 4 (index of first 5)
     * 
* * @example Determines the position of the element with the id '#wanted' among all li elements: *
     * var elementIndex = $('li').find($$('#wanted'));
     * 
* * @example Goes through the elements to find the first div that has the class 'myClass', and returns this element: *
     * var myClassElement = $('div').find(function(e) { if ($(e).is('.myClass')) return e; });
     * 
* * @param list A list to use as input. Can be an array, a ##list#Minified list## or any other array-like structure with * length property. * @param findFunc The callback function(item, index) that will be invoked for every list item until it returns a non-null value: *
item
The current list element.
index
The second the zero-based index of the current element.
*
this
This list.
*
(callback return value)
If the callback returns something other than null or * undefined, find() will return it directly. Otherwise it will continue.
* @param element the element to search for * @param startIndex optional the 0-based index of the first element to search. * @return if called with an element, either the element's index in the list or undefined if not found. If called with a callback function, * it returns either the value returned by the callback or undefined. * * @see ##findLast() is the equivalent to find() for the list's end. */ 'find': listBind(find), /*$ * @stop */ dummySort:0 , ///#/snippet utilListFuncs ///#snippet webListFuncs /*$ * @id select * @group SELECTORS * @requires dollar * @configurable default * @name .select() * @syntax list.select(selector) * @syntax list.select(selector, childrenOnly) * @module WEB * Executes a selector with the list as context. list.select(selector, childrenOnly) is equivalent * to $(selector, list, childrenOnly). * * @example Returns a list of all list elements: *
     * var parents = $('ol.myList').select('li', true);
     * 
* * @example Returns a list of all child elements: *
     * var children = $('.myElements').select('*', true);
     * 
* * @param selector a selector or any other valid first argument for #dollar#$(). * @param childrenOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not * true, all descendants of the context will be included. * @return the new list containing the selected descendants. * * @see ##only() executes a selector on the list elements, instead of their descendants. */ 'select': function(selector, childOnly) { return $(selector, this, childOnly); }, /*$ * @id get * @group SELECTORS * @requires dollar * @configurable default * @name .get() * @syntax list.get(name) * @syntax list.get(name, toNumber) * @syntax list.get(list) * @syntax list.get(list, toNumber) * @syntax list.get(map) * @syntax list.get(map, toNumber) * @module WEB * Retrieves properties, attributes and styles from the list's first element. The syntax to request those values is mostly identical with ##set(). You can either * get a single value if you specify only one name, or get an object map when you specify several names using an array or an object map. * * The name parameter defines what kind of data you are reading. The following name schemes are supported: * * * * * * * * * * * * *
Name SchemaExampleSets what?Description
nameinnerHTMLPropertyA name without prefix of '$' or '@' gets a property of the object.
@name@hrefAttributeGets the HTML attribute using getAttribute().
%name%phoneData-AttributeGets a data attribute using getAttribute(). Data attributes are * attributes whose names start with 'data-'. '%myattr' and '@data-myattr' are equivalent.
$name$fontSizeCSS PropertyGets a style using the element's style object. * The syntax for the CSS styles is camel-case (e.g. "$backgroundColor", not "$background-color"). Shorthand properties like "border" or "margin" are * not supported. You must use the full name, e.g. "$marginTop". Minified will try to determine the effective style * and thus will return the value set in style sheets if not overwritten using a regular style.
$$CSS ClassesA simple $ returns the CSS classes of the element and is identical with "className".
$$$$StyleReads the element's style attribute in a browser-independent way. On legacy IEs it uses * style.cssText, and on everything else just the "style" attribute.
$$show$$showShow/HideReturns 1 if the element is visible and 0 if it is not visible. An element counts as * visible if '$visibility' is not 'hidden' and '$display' is not 'none'. Other properties will be ignored, even if they can also be used to hide the element.
$$fade$$fadeFade EffectThe name '$$fade' returns the opacity of the element as a value between 0 and 1. * '$$fade' will also automatically evaluate the element's 'visibility' and 'display' styles to find out whether the element is actually visible.
$$slide$$slideSlide Effect'$$slide' returns the height of the element in pixels with a 'px' suffix and is equivalent to '$height'. * Please note that you can pass that 'px' value to '$$slide' in ##set(), which will then set the according '$height'.
$$scrollX, $$scrollY$$scrollYScroll CoordinatesThe names '$$scrollX' and * '$$scrollY' can be used on $(window) to retrieve the scroll coordinates of the document. * The coordinates are specified in pixels without a 'px' unit postfix.
* * @example Retrieves the id, title attribute and the background color of the element '#myElement': *
     * var id = $('#myElement).get('id');
     * var title = $('#myElement).get('@title');
     * var bgColor = $('#myElement).get('$backgroundColor');
     * 
* * @example Retrieves the id, title attribute and the background color of the element '#myElement' as a map: *
     * var m = $('#myElement).get(['id', '@title', '$backgroundColor']);
     * var id = m.id;
     * var title = m['@title'];
     * var bgColor = m.$backgroundColor;
     * 
* * @example Uses ##get() and ##set() to reposition an element: *
     * var coords = $('#myElement').get({$top: 0, $left: 0}, true);
     * coords.$top = coords.$top + 10 + 'px';
     * coords.$left = coords.$left + 20 + 'px';
     * $('#myElement').set(coords);
     * 
* Please note that the values of $top and $left in the get() invocation do not matter and will be ignored! * * @param name the name of a single property or attribute to modify. Unprefixed names set properties, a '$' prefix sets CSS styles and * '@' sets attributes. Please see the table above for special properties and other options. * @param list in order to retrieve more than one value, you can specify several names in an array or list. get() will then return an object map * containing the values. * @param map if you specify an object that is neither list nor string, get() will use it as a map of property names. Each property name will be requested. * The values of the properties in the map will be ignored. get() will then return a new object map containing of results. * @param toNumber if 'true', get() converts all returned values into numbers. If they are strings, * get() removes any non-numeric characters before the conversion. This is useful when you request * a CSS property such as '$marginTop' that returns a value with a unit suffix, like "21px". get() will convert it * into a number and return 21. If the returned value is not parsable as a number, NaN will be returned. * @return if get() was called with a single name, it returns the corresponding value. * If a list or map was given, get() returns a new object map with the names as keys and the values as values. * It returns undefined if the list is empty. * * @see ##set() sets values using the same property syntax. */ 'get': function(spec, toNumber) { var self = this; var element = self[0]; if (element) { if (isString(spec)) { var match = /^(\W*)(.*)/.exec(replace(spec, /^%/,'@data-')); var prefix = match[1]; var s; if (getter[prefix]) s = getter[prefix](this, match[2]); else if (spec == '$') s = self['get']('className'); else if (spec == '$$') { s = self['get']('@style'); } else if (spec == '$$slide') s = self['get']('$height'); else if (spec == '$$fade' || spec == '$$show') { if (self['get']('$visibility') == 'hidden' || self['get']('$display') == 'none') s = 0; else if (spec == '$$fade') { s = isNaN(self['get']('$opacity', true)) ? 1 : self['get']('$opacity', true); } else // $$show s = 1; } else if (prefix == '$') { s = _window['getComputedStyle'](element, _null)['getPropertyValue'](replace(match[2], /[A-Z]/g, function (match2) { return '-' + match2.toLowerCase(); })); } else if (prefix == '@') s = element.getAttribute(match[2]); else s = element[match[2]]; return toNumber ? extractNumber(s) : s; } else { var r = {}; (isList(spec) ? flexiEach : eachObj)(spec, function(name) { r[name] = self['get'](name, toNumber); }); return r; } } }, /*$ * @id set * @group SELECTORS * @requires dollar get * @configurable default * @name .set() * @syntax list.set(name, value) * @syntax list.set(properties) * @syntax list.set(cssClasses) * @module WEB * * Modifies the list's elements by setting their properties, attributes, CSS styles and/or CSS classes. You can either supply a * single name and value to set only one property, or you can provide an object that contains name/value pairs to describe more than one property. * More complex operations can be accomplished by supplying functions as values. They will then be called for each element that will * be set. * * The name parameter defines what kind of data you are setting. The following name schemes are supported: * * * * * * * * * * * * * *
Name SchemaExampleSets what?Description
nameinnerHTMLPropertyA name without prefix of '$' or '@' sets a property of the object.
@name@hrefAttributeSets the HTML attribute using setAttribute(). In order to stay compatible with Internet Explorer 7 and earlier, * you should not set the attributes '@class' and '@style'. Instead use '$' and '$$' as shown below.
%name%phoneData-AttributeSets a data attribute using setAttribute(). Data attributes are * attributes whose names start with 'data-'. '%myattr' and '@data-myattr' are equivalent.
$name$fontSizeCSS PropertySets a style using the element's style object. * The syntax for the CSS styles is camel-case (e.g. "$backgroundColor", not "$background-color").
$$CSS ClassesA simple $ modifies the element's CSS classes using the object's className property. The value is a * space-separated list of class names. If prefixed with '-' the class is removed, a '+' prefix adds the class and a class name without prefix toggles the class. * The name '$' can also be omitted if set is called with class names as only argument.
$$$$StyleSets the element's style attribute in a browser-independent way.
$$show$$showShow/HideIf true or a number not 0, it will make sure the element is visible by * making sure '$display' is not 'none' and by setting '$visibility' to 'visible'. Please see ##show() for details. If the value is false or 0, it * will be hidden by setting '$display' to 'none'.
$$fade$$fadeFade EffectThe name '$$fade' sets the opacity of the element in a browser-independent way. The value must be a number * between 0 and 1. '$$fade' will also automatically control the element's 'visibility' style. If the value is 0, * the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to * 'visible'. '$$fade' only works with block elements.
$$slide$$slideSlide EffectThe name '$$slide' allows a vertical slide-out or slide-in effect. The value must be a number * between 0 and 1 and will be used to set the element's '$height'. '$$slide' will also automatically control the element's 'visibility' * style. If the value is 0, the element's visibility will automatically be set to 'hidden'. If the value is larger, * the visibility will be set to 'visible'. '$$slide' only works with block elements and will not set the * element's margin or padding. If you need a margin or padding, you should wrap the elements in a simple <div>.
$$scrollX, $$scrollY$$scrollYScroll CoordinatesThe names '$$scrollX' and * '$$scrollY' can be used on $(window) to set the scroll coordinates of the document. * The coordinates are specified in pixels, but must not use a 'px' unit postfix.
* * @example Unchecking checkboxes: *
     * $('input.checkbox').set('checked', false);
     * 
* * @example Changing the innerHTML property of an element: *
     * $('#toc').set('innerHTML', 'Content');
     * 
* * @example Changing attributes: *
     * $('a.someLinks').set('@href', 'http://www.example.com/');
     * 
* * @example Removing attributes: *
     * $('a.someLinks').set('@title', null);
     * 
* * @example Changing styles: *
     * $('.bigText').set('$fontSize', 'x-large');
     * 
* * @example Adding and removing CSS classes: *
     * $('.myElem').set('$', '+myClass -otherClass');
     * 
* * @example Toggling a CSS class: *
     * $('.myElem').set('$', 'on');
     * 
* * @example Shortcut for CSS manipulation: *
     * $('.myElem').set('+myClass -otherClass on');
     * 
* * @example Making an element transparent: *
     * $('.seeThrough').set('$$fade', 0.5);
     * 
* * @example Making an element visible. Note that $$fade will set the element's display style to 'block' and visibility style to 'visible'. *
     * $('.myElem').set('$$fade', 1);
     * 
* * @example Using a map to change several properties: *
     * $('input.checkbox').set({checked: false,
     *                          '@title': 'Check this'});
     * 
* * @example Changing CSS with a map: *
     * $('.importantText').set({$fontSize: 'x-large',
     *                          $color: 'black',
     *                          $backgroundColor: 'red',
     *                          $: '+selected -default'});
     * 
* * @example You can specify a function as value to modify a value instead of just setting it: *
     * $('h2').set('innerHTML', function(oldValue, index) {
     *     return 'Chapter ' + index + ': ' + oldValue.toUpperCase();
     * });
     * 
* * @param name the name of a single property or attribute to modify. Unprefixed names set properties, a '$' prefix sets CSS styles and * '@' sets attributes. Please see the table above for special properties and other options. * @param value the value to set. If value is null and name specified an attribute, the attribute will be removed. * If dollar ('$') has been passed as name, the value can contain space-separated CSS class names. If prefixed with a '+' the class will be added, * with a '-' prefix the class will be removed. Without prefix, the class will be toggled. * If value is a function, the function(oldValue, index, obj) will be invoked for each list element * to evaluate the new value: *
oldValue
The old value of the property to be changed, as returned by ##get(). * For the CSS style names, this is the computed style of the property
*
index
The list index of the object owning the property
*
obj
The list element owning the property.
*
(callback return value)
The value to be set.
* Functions are not supported by '$'. * @param properties a Object as map containing names as keys and the values to set as map values. See above for the name and value syntax. * @param cssClasses if set() is invoked with a string as single argument, the name "$" (CSS classes) is assumed and the argument is the * value. See above for CSS syntax. * Instead of a string, you can also specify a function(oldValue, index, obj) to modify the existing classes. * @return the list * * @see ##get() retrieves values using the same property syntax. * @see ##animate() animates values using the same property syntax. * @see ##toggle() can toggle between two sets of values. * @see ##dial() allows smooth transitions between two sets of values. */ 'set': function (name, value) { var self = this; if (value !== undef) { var match = /^(\W*)(.*)/.exec(replace(replace(name, /^\$float$/, 'cssFloat'), /^%/,'@data-')); var prefix = match[1]; if (setter[prefix]) setter[prefix](this, match[2], value); else if (name == '$$fade') { this['set']({'$visibility': value ? 'visible' : 'hidden', '$opacity': value}); } else if (name == '$$slide') { self['set']({'$visibility': value ? 'visible' : 'hidden', '$overflow': 'hidden', '$height': /px/.test(value) ? value : function(oldValue, idx, element) { return getNaturalHeight($(element), value);} }); } else if (name == '$$show') { if (value) self['set']({'$visibility': value ? 'visible' : 'hidden', '$display': ''}) // that value? part is only for gzip ['set']({'$display': function(oldVal) { // set for 2nd time: now we get the stylesheet's $display return oldVal == 'none' ? 'block' : oldVal; }}); else self['set']({'$display': 'none'}); } else if (name == '$$') { self['set']('@style', value); } else flexiEach(this, function(obj, c) { var newValue = isFunction(value) ? value($(obj)['get'](name), c, obj) : value; if (prefix == '$') { if (match[2]) obj['style'][match[2]] = newValue; else { flexiEach(newValue && newValue.split(/\s+/), function(clzz) { var cName = replace(clzz, /^[+-]/); if (/^\+/.test(clzz)) obj['classList'].add(cName); else if (/^-/.test(clzz)) obj['classList'].remove(cName); else obj['classList'].toggle(cName); }); } } else if (name == '$$scrollX') obj['scroll'](newValue, $(obj)['get']('$$scrollY')); else if (name == '$$scrollY') obj['scroll']($(obj)['get']('$$scrollX'), newValue); else if (prefix == '@') { if (newValue == _null) obj.removeAttribute(match[2]); else obj.setAttribute(match[2], newValue); } else obj[match[2]] = newValue; }); } else if (isString(name) || isFunction(name)) self['set']('$', name); else eachObj(name, function(n,v) { self['set'](n, v); }); return self; }, /*$ * @id add * @group ELEMENT * @requires dollar each * @configurable default * @name .add() * @syntax list.add(text) * @syntax list.add(node) * @syntax list.add(list) * @syntax list.add(factoryFunction) * @module WEB * Adds the given node(s) as children to the list's HTML elements. If a string has been given, it will be added as text node. * DOM nodes will be added directly. If you pass a list, all its elements will be added using the rules above. * * When you pass a DOM node and the target list has more than one element, the original node will be added to the first list element, * and ##clone#clones## to all following list elements. * * ##EE(), ##HTML() and ##clone() are compatible with add() and can help you create new HTML nodes. * * @example Using the following HTML: *
     * <div id="comments">Here is some text.<br/></div>
     * 
* The next line appends a text node to the div: *
     * $('#comments').add('Some additional text.');
     * 
* This results in: *
     * <div id="comments">Here is some text.<br/>Some additional text.</div>
     * 
* * @example Using the following HTML: *
     * <ul id="myList">
     *   <li>First list entry</li>
     *   <li>Second list entry</li>
     * </ul>
     * 
* The following Javascript adds an element to the list: *
     * $('#myList').add(EE('li', 'My extra point');
     * 
* This results in *
     * <ul id="myList">
     *   <li>First list entry</li>
     *   <li>Second list entry</li>
     *   <li>My extra point</li>
     * </ul>
     * 
* * @example Use a list to add several elements at once: *
     * $('#comments').add([
     *      EE('br'),
     *     'Some text',
     *     EE('span', {'className': 'highlight'}, 'Some highlighted text')
     * ]);
     * 
* * @example If you need to customize the content, you can write a factory function: *
     * $('.chapter').add(function(parent, index) { return EE('h2', 'Chapter number ' + index); });
     * 
* * @param text a string or number to add as text node * @param node a DOM node to add to the list. If the list has more than one element, the given node will be added to the first element. * For all additional elements, the node will be cloned using ##clone(). * @param list a list containing text and/or nodes. May also contain nested lists with nodes or text.. * @param factoryFunction a function(listItem, listIndex) that will be invoked for each list element to create the nodes: *
listItem
The list element that will receive the new children.
*
listIndex
The index of the list element that will receive the new children.
*
(callback return value)
The node(s) to be added to the list element. * Can be either a string for a text node, an HTML element or a list containing strings and/or DOM nodes. * If a function is returned, it will be invoked recursively with the same arguments.
* @return the current list * * @see ##fill() works like add(), but deletes all children before adding the new nodes. * @see ##addFront() adds nodes as first child, not as last. * @see ##addAfter() adds nodes not as children but as siblings. * @see ##addBefore() also adds nodes not as children but as siblings. * @see ##replace() replaces existing nodes. */ 'add': function (children, addFunction) { return this['each'](function(e, index) { var lastAdded; function appendChildren(c) { if (isList(c)) flexiEach(c, appendChildren); else if (isFunction(c)) appendChildren(c(e, index)); else if (c != _null) { // must check null, as 0 is a valid parameter var n = isNode(c) ? c : document.createTextNode(c); if (lastAdded) lastAdded['parentNode']['insertBefore'](n, lastAdded['nextSibling']); else if (addFunction) addFunction(n, e, e['parentNode']); else e.appendChild(n); lastAdded = n; } } appendChildren(index &&!isFunction(children) ? clone(children) : children); }); }, /*$ * @id on * @group EVENTS * @requires dollar each * @configurable default * @name .on() * @syntax list.on(names, eventHandler) * @syntax list.on(selector, names, eventHandler) * @syntax list.on(names, customFunc, args) * @syntax list.on(selector, names, customFunc, args) * @syntax list.on(names, eventHandler, bubbleSelector) * @syntax list.on(names, customFunc, args, bubbleSelector) * @module WEB * Registers the function as event handler for all items in the list. * * By default, Minified cancels event propagation and disables element's default behavior for all elements that have an event handler. * You can override this, either by prefixing the event name with a '|', or by prefixing them with '?' and returning a true * in the handler. Both will reinstate the original JavaScript behavior. * * Handlers are called with the original event object as first argument, the index of the source element in the * list as second argument and 'this' set to the source element of the event (e.g. the button that has been clicked). * * Instead of the event objects, you can also pass an array of arguments that will be passed instead of event object and index. * * Optionally you can specify two a selector strings to qualify only certain events. The first one is a selector * that allows you to select only specific children of the list elements. This is mostly useful for adding events to DOM trees * generated using ##HTML() or ##EE(). * * The second type of selector is the bubble selector that allows you to receive only events that bubbled up from * elements matching the selector. The selector is executed in the context of the element you registered on to identify whether the * original target of the event qualifies. If not, the handler is not called. * * Minified always registers event handlers with event bubbling enabled. Event capture is not supported. * * Event handlers can be unregistered using #off#$.off(). * * @example Adds a handler to all divs which paints the div background color to red when clicked. *
     * $('div').on('click', function() {
     *    this.style.backgroundColor = 'red';    // 'this' contains the element that caused the event
     * });
     * 
* * @example Registers a handler to call a method setStatus('running') using an inline function: *
     * $('#myButton').on('click', function() {
     *    setStatus('running');
     * });
     * 
* The previous example can bere written like this, using on()'s args parameter: *
     * $('#myButton').on('click', setStatus, ['running']);
     * 
* * @example Adds two handlers on an input field. The event names are prefixed with '|' and thus keep their original behavior: *
     * $('#myInput').on('|keypress |keydown', function() {
     *    // do something
     * });
     * 
* * @example Adds a click handler that will abort the operation by returning false, unless the user confirms it: *
     * $('#myLink').on('?click', function() {
     *    return window.confirm('Really leave?');
     * });
     * 
* * @example Adds a button and registers a click handler for it using a sub-selector. *
     * $('#myForm').add(HTML("<li><button>click me</button></li>").on('button', 'click', myClickHandler));
     * 
* * @example Adds listeners for all clicks on a table's rows using the bubble selector 'tr'. *
     * $('#table').on('change', 'tr', function(event, index, selectedIndex) {
     *    alert("Click on table row number: " + selectedIndex);
     * }, 'tr');
     * 
* Please note that bubble selectors will even listen to events for * table rows that have been added after you registered for the events. * * @param selector optional a selector string for ##dollar#$()## to register the event only on those children of the list elements that * match the selector. * Supports all valid parameters for $() except functions. * @param names the space-separated names of the events to register for, e.g. 'click'. Case-sensitive. The 'on' prefix in front of * the name must not used. You can register the handler for more than one event by specifying several * space-separated event names. If the name is prefixed * with '|' (pipe), the event will be passed through and the event's default actions will be executed by the browser. * If the name is prefixed with '?', the event will only be passed through if the handler returns true. * @param eventHandler the callback function(event, index) to invoke when the event has been triggered: *
*
event
The original DOM event object.
*
index
The index of the target object in the ##list#Minified list## .
*
this
A ##list#Minified list## containing the target element as only item (same as event.target).
*
(callback return value)
The return value will only be used if the event name prefix was '?'. * Then, a return value false will stop all further processing of the event and disable event bubbling. * true will keep the event alive.
*
* @param customFunc a function to be called instead of a regular event handler with the arguments given in args. * 'this' will be a ##list#Minified list## containing the target element as only item (same element as event.target). * @param args optional an array of arguments to pass to the custom callback function instead of the event objects. If omitted, the function is * called as event handler with the event object as argument. * @param bubbleSelector optional a selector string for ##dollar#$()## to receive only events that bubbled up from an * element that matches this selector. * Supports all valid parameters for $() except functions. Analog to ##is(), * the selector is optimized for the simple patterns '.classname', 'tagname' and 'tagname.classname'. * @return the list * @see ##off() allows you to unregister an event handler. * @see ##onClick() as a shortcut for 'click' events. * @see ##onOver() to simplify mouseover/mouseout events. * @see ##onFocus() as convenient way to register for focus events. * @see ##onChange() to get notified when an input's content changes. */ 'on': on, /*$ * @id trigger * @group EVENTS * @requires on each * @configurable default * @name .trigger() * @syntax list.trigger(name) * @syntax list.trigger(name, eventObject) * @module WEB * * Triggers event handlers registered with ##on(). * Any event that has been previously registered using ##on() can be invoked with trigger(). Please note that * it will not simulate the default behavior on the elements, such as a form submit when you click on a submit button. Event bubbling * is supported, thus unless there's an event handler that cancels the event, the event will be triggered on all parent elements. * * * @example Simulates a 'click' event on the button. *
     * $('#myButton').trigger('click');
     * 
* * @param name a single event name to trigger * @param eventObj optional an object to pass to the event handler, provided the handler does not have custom arguments. * Anything you pass here will be directly given to event handlers as event object, so you need to know what * they expect. * @return the list * @see ##on() registers events that can be triggered. */ 'trigger': function (eventName, eventObj) { return this['each'](function(element, index) { var bubbleOn = true, el = element; while(el && bubbleOn) { eachObj(el['M'], function(id, f) { bubbleOn = bubbleOn && f(eventName, eventObj, element); }); el = el['parentNode']; } }); } /*$ * @stop */ // @cond !trigger dummyTrigger:0 , ///#/snippet webListFuncs ///#snippet extrasListFuncs /*$ * @id ht * @group ELEMENT * @requires set template * @configurable default * @name .ht() * @syntax list.ht(templateString, object...) * @syntax list.ht(templateFunction, object...) * @syntax list.ht(idSelector, object...) * @module WEB+UTIL * Replaces the content of the list elements with the HTML generated using the given template. The template uses * ##template() syntax and HTML-escaped its output using ##escapeHtml(). * * @example When you have a HTML snippet like this: *
     * <div id="price"></div>
     * 
* Then you can format the price value like this: *
     * var price = 14.9;
     * $('#price').ht('<b>${{::0.00}}</b>', price);
     * 
* Results in: *
     * <div id="price"><b>$14.90</b></div>
     * 
* * @example Render a list of names: *
     * var names = [ {first: 'James', last: 'Sullivan'},
     *               {first: 'Michael', last: 'Wazowski'} ];
     * $('#list').ht('<h2>{{listName}}</h2>'+
     *               '<ul>{{each n: names}}<li>{{n.first}} {{n.last}}</li>{{/each}}</ul>',
     *               {listName: 'Guys', names: names});
     * 
* The code creates this: *
     * <h2>Guys</h2>
     * <ul><li>James Sullivan<li><li>Michael Wazowski</li></ul>
     * 
* * @example You can store templates in <script> tags. First you need to create a <script> tag with a type not * supported by the browser and put your template in there, like this: *
<script id="myTimeTpl" type="minified-template">The time is {{HH:mm:ss}}.</script>
* Then you can specify the tag's id directly to access it: *
$('#timeDisplay').ht('#myTimeTpl', new Date());
* * @param templateString the template using ##template() syntax. Please note, because this is a template, you should * avoid creating the template itself dynamically, as compiling templates is expensive and * Minified will cache only a limited number of templates. Exception: If the template string does not use * any template functionality (no {{}}), it does not need to be compiled and won't be cached.
* The template will use ##escapeHtml() as escape function, so all template substitutions will be HTML-escaped, * unless you use triple curly-braces. * @param templateFunction instead of a HTML template, ht() can also use a template function, e.g. one * created by ##template(). It will be invoked with the object as only argument. * @param idSelector if you pass an ID CSS selector in the form "#myScript", Minified will recognize this and use the content * of the specified <script> element as template. This allows you to put your template into * a <script> tag with a non-JavaScript type (see example). Any string that starts with '#' and does not * contain any spaces is used as selector. * @param object optional one or more objects to pass to the template. If object is not set, the template is called with undefined * as object. If exactly one object is given, it is passed directly to the template. If you specify more than one * object, they are ##merge#merged##. * @return the current list * * @see ##HTML() creates only the nodes and can be used with ##add() and other methods to add the nodes to the DOM, giving you more flexibility than ht(). */ 'ht': function(htmlTemplate, object) { var o = arguments.length > 2 ? merge(sub(arguments, 1)) : object; return this['set']('innerHTML', isFunction(htmlTemplate) ? htmlTemplate(o) : /{{/.test(htmlTemplate) ? formatHtml(htmlTemplate, o) : /^#\S+$/.test(htmlTemplate) ? formatHtml($$(htmlTemplate)['text'], o) : htmlTemplate); } /*$ * @stop */ // @cond !ht dummyHt:0 ///#/snippet extrasListFuncs }, M.prototype); //// DOLLAR FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// copyObj({ ///#snippet webDollarFuncs /*$ * @id request * @group REQUEST * @requires * @configurable default * @name $.request() * @syntax $.request(method, url) * @syntax $.request(method, url, data) * @syntax $.request(method, url, data, settings) * @module WEB * Initiates a HTTP request to the given URL, using XMLHttpRequest. It returns a ##promiseClass#Promise## object that allows you to obtain the result. * * @example Invokes a REST web service and parses the resulting document using JSON: *
     * $.request('get', 'http://service.example.com/weather', {zipcode: 90210})
     *    .then(function(txt) {
     *         var json = $.parseJSON(txt);
     *         $('#weatherResult').fill('Today's forecast is is: ' + json.today.forecast);
     *    })
     *    .error(function(status, statusText, responseText) {
     *         $('#weatherResult').fill('The weather service was not available.');
     *    });
     * 
* * @example Sending a JSON object to a REST web service: *
     * var myRequest = {         // create a request object that can be serialized via JSON
     *      request: 'register',
     *      entries: [
     *        {name: 'Joe',
     *      	    job: 'Plumber'
     *        }
     *      ]};
     *
     * function failureHandler() {
     *   $('#registrationResult').fill('Registration failed');
     * }
     *
     * $.request('post', 'http://service.example.com/directory', $.toJSON(myRequest))
     *     .then(function(txt) {
     *        if (txt == 'OK')
     *             $('#registrationResult').fill('Registration succeeded');
     *        else
     *              failureHandler();
     *        })
     *     .error(failureHandler);
     * 
* * @example Using HTTP authentication and a custom XMLHttpRequest property. *
var handler = $.request('get', 'http://service.example.com/userinfo', null, {xhr: {withCredentials: true}, user: 'me', pass: 'secret'});
* * * @param method the HTTP method, e.g. 'get', 'post' or 'head' (rule of thumb: use 'post' for requests that change data * on the server, and 'get' to request data). Not case sensitive. * @param url the server URL to request. May be a relative URL (relative to the document) or an absolute URL. Note that unless you do something * fancy on the server (keyword to google: Access-Control-Allow-Origin), you can only call URLs on the server your script originates from. * @param data optional data to send in the request, either as POST body or as URL parameters. It can be either a plain object as map of * parameters (for all HTTP methods), a string (for all HTTP methods), a DOM document ('post' only) or a FormData object ('post' only). * If the method is 'post', it will be sent as body, otherwise parameters are appended to the URL. In order to send several parameters with the * same name, use an array of values in the map. Use null as value for a parameter without value. * @param settings optional a map of additional parameters. Supports the following properties (all optional): *
headers
a map of HTTP headers to add to the request. Note that you should use the proper capitalization for the * header 'Content-Type', if you set it, because otherwise it may be overwritten.
*
xhr
a map of properties to set in the XMLHttpRequest object before the request is sent, for example {withCredentials: true}.
*
user
username for HTTP authentication, together with the pass parameter
*
pass
password for HTTP authentication, together with the user parameter
*
* @return a ##promiseClass#Promise## containing the request's status. If the request has successfully completed with a HTTP status 2xx, * the promise's completion handler will be called as function(text, xhr): *
text
The response sent by the server as text.
*
xhr
The XMLHttpRequest used for the request. This allows you to retrieve the response in different * formats (e.g. responseXml for an XML document), to retrieve headers and more.
* The failure handler will be called as function(statusCode, statusText, text): *
statusCode
The HTTP status (never 200; 0 if no HTTP request took place).
*
text
The response's body text, if there was any, or the exception as string if the browser threw one.
*
xhr
The XMLHttpRequest used for the request. This allows you to retrieve the response in different * formats (e.g. responseXml for an XML document), to retrieve headers and more..
* The returned promise supports ##stop(). Calling stop() will invoke the XHR's abort() method. * The underlying XmlHttpRequest can also be obtained from the promise's xhr property. * * @see ##values() serializes an HTML form in a format ready to be sent by $.request. * @see ##$.parseJSON() can be used to parse JSON responses. * @see ##$.toJSON() can create JSON messages. * @see ##_.format() can be useful for creating REST-like URLs, if you use JavaScript's built-in escape() function. */ 'request': function (method, url, data, settings0) { var settings = settings0 || {}; var xhr, callbackCalled = 0, prom = promise(), dataIsMap = data && (data['constructor'] == settings['constructor']); try { prom['xhr'] = xhr = new XMLHttpRequest(); prom['stop0'] = function() { xhr['abort'](); }; // @condend if (dataIsMap) { // if data is parameter map... data = collector(eachObj, data, function processParam(paramName, paramValue) { return collector(flexiEach, paramValue, function(v) { return encodeURIComponent(paramName) + ((v != _null) ? '=' + encodeURIComponent(v) : ''); }); }).join('&'); } if (data != _null && !/post/i.test(method)) { url += '?' + data; data = _null; } xhr['open'](method, url, true, settings['user'], settings['pass']); if (dataIsMap && /post/i.test(method)) xhr['setRequestHeader']('Content-Type', 'application/x-www-form-urlencoded'); eachObj(settings['headers'], function(hdrName, hdrValue) { xhr['setRequestHeader'](hdrName, hdrValue); }); eachObj(settings['xhr'], function(name, value) { xhr[name] = value; }); xhr['onreadystatechange'] = function() { if (xhr['readyState'] == 4 && !callbackCalled++) { if (xhr['status'] >= 200 && xhr['status'] < 300) prom['fire'](true, [xhr['responseText'], xhr]); else prom['fire'](false, [xhr['status'], xhr['responseText'], xhr]); } }; xhr['send'](data); } catch (e) { if (!callbackCalled) prom['fire'](false, [0, _null, toString(e)]); } return prom; }, /* * JSON Module. Uses browser built-ins or json.org implementation if available. Otherwise its own implementation, * originally based on public domain implementation http://www.JSON.org/json2.js / http://www.JSON.org/js.html. * Extremely simplified code, made variables local, removed all side-effects (especially new properties for String, Date and Number). */ /*$ * @id ready * @group EVENTS * @requires ready_vars ready_init * @configurable default * @name $.ready() * @syntax $.ready(handler) * @module WEB * Registers a handler to be called as soon as the HTML has been fully loaded in the browser. Does not necessarily wait for images and other elements, * only the main HTML document needs to be complete. On older browsers it is the same as window.onload. * * If you call ready() after the page is completed, the handler is scheduled for invocation in the event loop as soon as possible. * * A shortcut for ready() is to call ##dollar#$()## with the handler function. It does the same with fewer characters. * * @example Registers a handler that sets some text in an element: *
     * $.ready(function() {
     *   $('#someElement').fill('ready() called');
     * });
     * 
* * @param handler the function() to be called when the HTML is ready. * @see ##dollar#$()## calls ready() when invoked with a function, offering a more convenient syntax. */ 'ready': ready, /*$ * @id off * @group EVENTS * @requires on * @configurable default * @name $.off() * @syntax $.off(handler) * @module WEB * Removes the given event handler. The call will be ignored if the given handler has not been registered using ##on(). * If the handler has been registered for more than one element or event, it will be removed from all instances. * * Please note that you can not unregister event handlers registered using ##onOver() or ##onChange(). * * @example Adds a handler to an element: *
     * function myEventHandler() {
     *    this.style.backgroundColor = 'red';        // 'this' contains the element that caused the event
     * }
     * $('#myElement').on('click', myEventHandler);  // add event handler
     *
     * window.setInterval(function() {               // after 5s, remove event handler
     *    $.off(myEventHandler);
     * }, 5000);
     * 
* * @param handler the handler to unregister, as given to ##on(). It must be a handler that has previously been registered using ##on(). * If the handler is not registered as event handler, the function does nothing. * * @see ##on() registers an event handler. */ 'off': off /*$ * @stop */ // @cond !off dummyOff:null , ///#/snippet webDollarFuncs ///#snippet extrasDollarFuncs /*$ * @id wait * @group EVENTS * @configurable default * @requires promise * @name $.wait() * @syntax $.wait() * @syntax $.wait(durationMs) * @syntax $.wait(durationMs, args) * @module WEB+UTIL * * Creates a new ##promise#Promise## that will be fulfilled as soon as the specified number of milliseconds have passed. This is mainly useful for animation, * because it allows you to chain delays into your animation chain. * * The operation can be interrupted by calling the promise's ##stop() function. * * @example Chained animation using Promise callbacks. The element is first moved to the position 200/0, then to 200/200, waits for 50ms * and finally moves to 100/100. *
     * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
     * div.animate({$left: '200px', $top: '0px'}, 600, 0)
     *    .then(function() {
     *           div.animate({$left: '200px', $top: '200px'}, 800, 0);
     *    }).then(function() {
     *    	     return _.wait(50);
     *    }).then(function() {
     *           div.animate({$left: '100px', $top: '100px'}, 400);
     *    });
     * });
     * 
* * * @param durationMs optional the number of milliseconds to wait. If omitted, the promise will be fulfilled as soon as the browser can run it * from the event loop. * @param args optional an array or list of arguments to pass to the promise handler * @return a ##promise#Promise## object that will be fulfilled when the time is over, or fail when the promise's ##stop() has been called. * The promise argument of a fulfilled promise is the args parameter as given to wait(). The returned promise supports ##stop() * to interrupt the promise. */ 'wait': function(durationMs, args) { var p = promise(); var id = setTimeout(function() { p['fire'](true, args); }, durationMs); p['stop0'] = function() { p['fire'](false); clearTimeout(id); }; return p; } /*$ * @stop */ // @cond !wait dummyWait:0 ///#/snippet extrasDollarFuncs }, $); //// UNDERSCORE FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// copyObj({ ///#snippet utilUnderscoreFuncs // @condblock each 'each': each, // @condend // @condblock each 'toObject': toObject, // @condend // @condblock find 'find': find, // @condend // @condblock equals 'equals': equals, // @condend /*$ * @id copyobj * @group OBJECT * @requires * @configurable default * @name _.copyObj() * @syntax _.copyObj(from) * @syntax _.copyObj(from, to) * @module UTIL * Copies every property of the first object into the second object. The properties are copied as shallow-copies. * * @example Copying properties: *
var target = {a:3, c: 3};
     * _.copyObj({a: 1, b: 2}, target); // target is now {a: 1, b: 2, c: 3}
* * @example Inline property merge: *
var target = _.copyObj({a: 1, b: 2}, {a:3, c: 3}); // target is now {a: 1, b: 2, c: 3}
* * @example Duplicating an object: *
var target = _.copyObj({a: 1, b: 2}); // target is now {a: 1, b: 2}
* * @param from the object to copy from * @param to optional the object to copy to. If not given, a new object will be created. * @return the object that has been copied to * * @see ##_.extend() is very similar to copyObj(), but with a slightly different syntax. * @see ##_.merge() copies a list of objects into a new object. */ 'copyObj': copyObj, /*$ * @id extend * @group OBJECT * @requires * @configurable default * @name _.extend() * @syntax _.extend(target, src...) * @module UTIL * Copies every property of the source objects into the first object. The source objects are specified using variable arguments. * There can be more than one. * The properties are copied as shallow-copies. * * Please note: Unlike jQuery, extend does not directly add a function to extend Minified, although * you can use it to for this. To add a function to ##list#Minified lists##, add a property to * ##M#MINI.M##. If you want to extend $ or _, just assign the new function(s) as property. * * @example Copying properties: *
var target = {a:3, c: 3};
     * _.extend(target, {a: 1, b: 2}); // target is now {a: 1, b: 2, c: 3}
* * @example Using several source values: *
var extend = _.extend({a: 1, b: 2}, {a:3, c: 3}, {d: 5}); // target is now {a: 1, b: 2, c: 3, d: 5}
* * @param target the object to copy to * @param src the object(s) to copy from. Variable argument, there can be any number of sources. Nulls and undefined * parameters will be ignored. * @return the target * * @see ##_.copyObj() is very similar to extend(), but with a slightly different and more straightforward syntax. * @see ##_.merge() copies a list of objects into a new object. */ 'extend': function(target) { return merge(sub(arguments, 1), target); }, /*$ * @id eachobj * @group OBJECT * @requires * @configurable default * @name _.eachObj() * @syntax _.eachObj(obj, callback) * @syntax _.eachObj(obj, callback, ctx) * @module UTIL * Invokes the given function once for each property of the given object. The callback is not invoked for inherited properties. * * @example Dumps all properties of an object. *
     * var s = '';
     * _.eachObj({a: 1, b: 5, c: 2}, function(key, value) {
     *     s += 'key=' + key + ' value=' + value + '\n';
     * });
     * 
* * @param obj the object to use * @param callback The callback function(key, value) to invoke for each property. *
key
The name of the current property.
*
value
The value of the current property.
*
this
The given context. If not set, the object itself.
* The callback's return value will be ignored. * @param ctx optional a context to pass to the callback as 'this'. * @return the object * * @see ##_.each() iterates through a list. */ 'eachObj': eachObj, /*$ * @id isobject * @group TYPE * @requires * @configurable default * @name _.isObject() * @syntax _.isObject(obj) * @module UTIL * Checks whether the given reference is an object as defined by typeof. * * @param obj the object to test * @return true if the object is an object, false otherwise. */ 'isObject': isObject, /*$ * @id format * @group FORMAT * @requires template * @configurable default * @name _.format() * @syntax _.format() * @syntax _.format(template, object) * @syntax _.format(template, object, escapeFunction) * @module UTIL * Formats an object using a ##template#template##. The template syntax is shared with ##_.template(). The only difference is that * format() frees you from the extra step of creating the template. In any case, whether you use * format() or ##_.template(), the template will be cached. Be careful when you create templates dynamically, as * every template is cached and consumes memory.
* If you only want to format a single value, use ##_.formatValue(). * * @example Format a name: *
var s = _.formatHtml("{{first}} {{last}}", {first: 'Tim', last: 'Taylor'});
* * @example Format a list of dates: *
var s = _.format("{{each}}{{this :: yyyy-MM-dd}}{{/each}}", dateList);
* * @param template The ##template#template## as a string. The template, once created, will be cached. * @param object the object to format * @param escapeFunction optional The callback function(inputString) that will be used * to escape all output: *
inputString
The string to escape.
*
(callback return value)
The escaped string.
* If no escapeFunction has been given, the output will not be escaped. * ##_.escapeHtml() can be used as an escape function for HTML, and ##_.escapeRegExp() for regular expressions. * JavaScript's built-in escape() function can escape URL components. * See ##_.htmlFormat() for a version of format() that already includes HTML escaping. * @return the string created by the template * * @see ##_.template() creates a template function, using the same syntax. * @see ##_.formatHtml() is a variant of format() with HTML-escpaping built it. * @see ##_.formatValue() formats a single number or date. * @see ##_.escapeRegExp() can be used by format() to escape regular expressions. */ 'format': function(tpl, object, escapeFunction) { return template(tpl, escapeFunction)(object); }, /*$ * @id template * @group FORMAT * @requires date_constants * @configurable default * @name _.template() * @syntax _.template(template) * @syntax _.template(template, escapeFunction) * @module UTIL * Parses a Handlebars-like template to create a reusable template function. * * The syntax of the template uses a syntax that superficially looks like * Handlebars. Unlike Handlebars, it is based on raw JavaScript expressions and thus gives you * complete freedom, but also offers you shortcuts for formatting, iteration and conditionals. * * Every template can receive exactly one object as input. If you need more than one value as input, put all required values * into an object. * * Use double curly braces to embed a JavaScript expression and insert its result: *
{{a}} plus {{b}} is {{a+b}}
* * To use such a template, create it with template() and then execute the resulting function: *
var myTemplate = _.template('{{a}} plus {{b}} is {{a+b}}');
     * var result = myTemplate({a: 5, b: 7});
* If you pass an object as input, its properties will be mapped using JavaScript's with * statement and are available as variables throughout the template. * * If you have only a simple value to render, you can pass it directly and access it through the pre-defined * variable obj: *
var myTemplate = _.template('The result is {{obj}}.');
     * var result = myTemplate(17);
* Alternatively, you could also access the input as this, but be aware that JavaScript wraps simples types * such as Number and Boolean. this is the default, so you can omit it to get the same result: *
var myTemplate = _.template('The result is {{ }}.');
     * var result = myTemplate(17);
* * Minified templates can use ##_.formatValue() formats directly. Just separate them from the expression by * a double-colon: *
The price is {{obj::#.00}}.
* * Conditions can be expressed using if and else: *
Hello {{if visits==0}}New{{else if visits<10}}Returning{{else}}Regular{{/if}} Customer.
* You can use any JavaScript expression as condition. * * Use each to iterate through a list: *
var myTemplate = _.template(
     * 	   '{{each names}}{{this.firstName}} {{this.lastName}}{{/each}}');
     * var result = myTemplate({names: [{firstName: 'Joe', lastName: 'Jones'},
     *                                  {firstName: 'Marc', lastName: 'Meyer'}]});
* each will iterate through the members of the given object. It * calls its body for each item and put a reference to the item into this. * Optionally, you can specify up to two variables to store the value in and * the zero-based index of the current item: *
var myTemplate = _.template(
     * 	   '{{each value, index: names}}{{index}}. {{value.firstName}} {{value.lastName}}{{/each}}');
     * 
* * If you do not pass an expression to each, it will take the list from this: *
var myTemplate = _.template('{{each value:}}{{value}};{{/each}}');
     * var result = myTemplate([1, 2, 3]);
* * Beside lists, you can also iterate through the properties of an object. The property name will be stored * in the first given parameter and the value in this and the second parameter: *
var myTemplate = _.template('{{each key, value: nicknames}}{{key}}: {{value}}{{/each}}');
     * var result = myTemplate({nicknames: {Matt: 'Matthew', John: 'Jonathan'} });
* * Shorter version of the previous example that uses this for the value: *
var myTemplate = _.template('{{each key: nicknames}}{{key}}: {{this}}{{/each}}');
* * If you do not need the key, you can omit the variable specification: *
var myTemplate = _.template('{{each nicknames}}{{this}}{{/each}}');
* * You can define your own variables, using the regular JavaScript syntax, with 'var': *
var myTemplate = _.template('{{var s=very.long.name, sum=a+b;}}{{s.desc}}, {{sum}}');
* * In some situations, it may be inevitable to embed raw JavaScript in the template. * To embed JavaScript code, prefix the code with a '#': *
var myTemplate = _.template(
     *     '{{each}}{{#var sum = 0; for (var i = 0; i < 3; i++) sum += this.numbers[i]; }}{{sum}}{{/each}}');
     * var result = myTemplate([['Foreword', 'Intro'], ['Something', 'Something else']]);
* * * By default, all output will be escaped. You can prevent this by using triple-curly-braces: *
Here's the original: {{{rawText}}}
. * * The template's JavaScript code is executed in a sandbox without access to global variables. Minified defines the * following variables for you: * * * * * * * *
NameDesciption
thisThe template object outside of each. Inside eachs, the current value.
objThe parameter given to the template function.
_A reference to Minified Util.
escThe escape function given when the template has been defined. If no function has been given, * a default function that returns the input unmodified.
printA function(text,...) that appends one or more strings to the template result.
eachA function(listOrObject, eachCallback) that can iterate over lists or object properties. * The eachCallback is a function(key, value) for objects or function(value, index) * for arrays that will be invoked for each item. *
* * Every template you create is already cached, so it not an expensive operation to call ##_.template() a second * time with the same template. However, because of caching, you should be careful when creating templates * dynamically, as this will fill the cache up quickly. * * @param template The template as a string using the syntax described below. * @param escapeFunction optional The callback function(inputString) that will be used * to escape all output: *
inputString
The string to escape.
*
(callback return value)
The escaped string.
* If no escapeFunction has been given, the output will not be escaped. * ##_.escapeHtml() can be used as an escape function for HTML, and ##_.escapeRegExp() for regular expressions. * JavaScript's built-in escape() function can escape URL components. * @return the value returned by the last invocation of func * * @see ##_.format() shares template()'s syntax but returns the result directly. * @see ##_.formatHtml() is a variant of format() with HTML escaping. * @see ##_.escapeHtml() can be used by template() to escape HTML. * @see ##_.escapeRegExp() can be used by template() to escape regular expressions. * @see ##HTML() creates a HTML element tree from a template. */ 'template': template, /*$ * @id formathtml * @group FORMAT * @requires template * @configurable default * @name _.formatHtml() * @syntax _.formatHtml() * @syntax _.formatHtml(template, object) * @module UTIL * Formats an object using a ##template#template## with HTML escaping for the output. * The template syntax is shared with ##_.template(). Output in double curly braces is automatically escaped using ##_.escapeHtml(). * formatHtml() just creates a new template with HTML escaping and invokes it immediately. * The template will be cached. Be careful when you create templates dynamically, as * every template is cached and consumes memory.
* If you only want to format a single value, use ##_.formatValue(). * * @example Format a name: *
var s = _.formatHtml("{{first}} {{last}}", {first: 'Tim', last: 'Taylor'});
* * @example Format a list of dates: *
var s = _.formatHtml("{{each}}{{::yyyy-MM-dd}}{{/each}}", dateList);
* * @param template The ##template#template## as a string. The template, once created, will be cached. * @param object the object to format * @return the string created by the template * * @see ##ht() works uses formatHtml to set element's innerHTML. * @see ##HTML() create HTML nodes using formatHtml. * @see ##_.template() creates a template function, using the same syntax. * @see ##_.format() allows you to specify alternative escape mechanisms. */ 'formatHtml': formatHtml /*$ * @stop */ // @cond !format dummyFormatHtml:0 , ///#/snippet utilUnderscoreFuncs ///#snippet extrasUnderscoreFuncs // @condblock promise 'promise': promise // @condend promise /*$ * @stop */ // @cond !promise dummyPromise:0 ///#/snippet extrasUnderscoreFuncs }, _); ////INITIALIZATION //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///#snippet webInit /*$ * @id ready_init * @dependency */ document.addEventListener("DOMContentLoaded", function() { callList(DOMREADY_HANDLER); DOMREADY_HANDLER = _null; }, false); /*$ @stop */ ///#/snippet webInit return { ///#snippet extrasExports /*$ * @id html * @group ELEMENT * @requires template ht * @configurable default * @name HTML() * @syntax HTML(templateString, object...) * @syntax HTML(templateFunction, object...) * @syntax HTML(idSelector, object...) * @module WEB * Creates a ##list#list## of HTML nodes from the given HTML template. The list is compatible with ##add(), ##fill() and related methods. * The template uses the ##template() syntax with ##escapeHtml() escaping for values. * * Please note that the function HTML will not be automatically exported by Minified. You should always import it * using the recommended import statement: *
     * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE, HTML = MINI.HTML;
     * 
* * @example Creating a HTML element showing a number: *
     * <div id="price">-</div>
     * 
* Then the price can be set like this: *
     * var price = 14.9;
     * $('#price').fill(HTML('<b>${{::0.99}}</b>', price));
     * 
* Results in: *
     * <div id="price"><b>$14.90</b></div>
     * 
* * @example Adding elements to an existing list: *
     * var names = [ {first: 'James', last: 'Sullivan'},
     *               {first: 'Michael', last: 'Wazowski'} ];
     * $('#list').add(HTML('{{each}}<li>{{this.first}} {{this.last}}</li>{{/each}}', names);
     * 
* The code adds this to #list: *
     * <li>James Sullivan<li><li>Michael Wazowski</li>
     * 
* * @example You can store templates in <script> tags. First you need to create a <script> tag with a type not * supported by the browser and put your template in there, like this: *
<script id="myTimeTpl" type="minified-template">The time is {{HH:mm:ss}}.</script>
* Then you can specify the tag's id directly to access it: *
$('#timeDisplay').fill(HTML('#myTimeTpl', new Date()));
* * @param templateString the template using ##template() syntax. Please note, because this is a template, you should * avoid creating the template itself dynamically, as compiling templates is expensive and * Minified will cache only a limited number of templates. Exception: If the template string does not use * any template functionality (no {{}}), it does not need to be compiled and won't be cached. * The template will use ##escapeHtml() as escape function, so all template substitutions will be HTML-escaped, * unless you use triple curly-braces. * @param templateFunction instead of a HTML template HTML() also accepts a template function, e.g. one * created by ##template(). It will be invoked with the object as only argument. * @param idSelector if you pass an ID CSS selector in the form "#myScript", Minified will recognize this and use the content * of the specified <script> element as template. This allows you to put your template into * a <script> tag with a non-JavaScript type (see example). Any string that starts with '#' and does not * contain any spaces is used as selector. * @param object optional one or more objects to pass to the template. If object is not set, the template is called with undefined * as object. If exactly one object is given, it is passed directly to the template. If you specify more than one * object, they are ##merge#merged##. * @return the list containing the new HTML nodes * * @see ##ht() is a shortcut for fill(HTML()). * @see ##EE() is a different way of creating HTML nodes. */ 'HTML': function () { var div = EE('div'); return _(call(div['ht'], div, arguments)[0].childNodes); }, /*$ * @stop */ ///#/snippet extrasExports ///#snippet utilExports /*$ * @id underscore * @group LIST * @name _() * @syntax _(item...) * @configurable default * @module UTIL * Creates a new Minified list. Supports variable arguments so you can add items directly to the list. For arguments that are lists * (as defined by ##_.isList()), the list content will be added to the new list. Unlike #dollar#$()#, this is not done recursively * and thus you can create a list of lists by wrapping arguments in a list. Another difference between _() and $() * is that $() will automatically remove null values while _() will keep them. * * @example Creating an empty list: *
_()
* * @example Creating a list with three items: *
_(1, 2, 3)
* * @example Creating the same list, but by passing an array. One array level will be flattened: *
_([1, 2, 3])
* * @example Creating a list containing the arrays [1, 2] and [3, 4]. *
_([[1, 2], [3, 4]])
* * @example Merging two lists: *
var a = _("a", "b", "c");
     * var b = _("x", "y", "z");
     * var merged = _(a, b);    // contains _("a", "b", "c", "x", "y", "z")
     * 
* * @example Adding two elements to a list: *
var a = _(1, 2, 3);
     * var a4 = _(a, 4);       // contains _(1, 2, 3, 4)
     * 
* * @example Mixing different list types and single elements: *
_(1, [], [2, 3], _(), _(4, 5)); // same content as _(1, 2, 3, 4, 5)
* * @param item an item to add to the new list. If it is a list (as defined by ##_.isList()), its content will be to the new * ##Minified list#list## (but NOT recursively). */ '_': _, /*$ * @stop */ ///#/snippet utilExports ///#snippet webExports /*$ * @id dollar * @group SELECTORS * @requires * @dependency yes * @name $() * @syntax $() * @syntax $(selector) * @syntax $(selector, context) * @syntax $(selector, context, childOnly) * @syntax $(list) * @syntax $(list, context) * @syntax $(list, context, childOnly) * @syntax $(object) * @syntax $(object, context) * @syntax $(object, context, childOnly) * @syntax $(domreadyFunction) * @module WEB * Creates a new ##list#Minified list##, or register a DOMReady-handler. * The most common usage is with a CSS-like selector. $() will then create a list containing all elements of the current HTML * document that fulfill the filter conditions. Alternatively you can also specify a list of objects or a single object. * Nested lists will automatically be flattened, and nulls will automatically be removed from the resulting list. * If you call $() without any arguments, it will return an empty list. * * Additionally, you can specify a second argument to provide a context. Contexts only make sense if you selected * HTML nodes with the first parameter. Then the context limits the resulting list to include only those nodes * that are descendants of the context nodes. The context can be either a selector, a list or a single HTML node, and will be * processed like the first argument. A third arguments allows you to limit the list to * only those elements that are direct children of the context nodes (so a child of a child would be filtered out). * * The lists created by $() are the same type as the ##list#Minified lists## created by Util's #underscore#_() constructor and other * Util methods. All Util methods work on lists created by $(). If you want to add your own methods to those lists, * use ##M#MINI.M##. * * As a special shortcut, if you pass a function to $(), it will be registered using #ready#$.ready() to be executed * when the DOM model is complete. * * @example A simple selector to find an element by id. *
     * var l0 = $('#myElementId');
     * 
* * @example You can pass an object reference to create a list containing only this element: *
     * var l1 = $(document.getElementById('myElementId'));
     * 
* * @example Lists and arrays will be copied: *
     * var l2 = $([elementA, elementB, elementC]);
     * 
* * @example Lists will be automatically flattened and nulls removed. So this list l3 has the same content as l2: *
     * var l3 = $([elementA, [elementB, null, elementC], null]);
     * 
* * @example This is a simple selector to find all elements with the given class. *
     * var l4 = $('.myClass');
     * 
* * @example A selector to find all elements of the given type. *
     * var l5 = $('input'); // finds all input elements
     * 
* * @example A selector to find all elements with the given type and class. *
     * var l6 = $('input.myRadio'); // finds all input elements with class 'myRadio'
     * 
* * @example A selector to find all elements that are descendants of the given element. *
     * var l7 = $('#myForm input'); // finds all input elements contained in the element myForm
     * 
* * @example A selector to find all elements that have either a CSS class 'a' or class 'b': *
     * var l8 = $('.a, .b'); // finds all elements that have class a or class b
     * 
* * @example A selector that finds all elements that are descendants of the element myDivision, are inside an element with the * class .myForm and are input elements: *
     * var l9 = $('#myDivision .myForm input');
     * 
* * @example Contexts can make it easier to specify ancestors: *
     * var l10 = $('.myRadio', '#formA, #formB, #formC');
     * 
* The result is identical to: *
     * var l10 = $('#formA .myRadio, #formB .myRadio, #formC .myRadio');
     * 
* * @example Using one of the list functions, ##set(), on the list, and setting the element's text color. '$' at the beginning of the property name sets a CSS value. *
     * $('#myElementId').set('$color', 'red');
     * 
* * @example Most list methods return the list you invoked them on, allowing you to chain them: *
     * $('#myForm .myRadio').addClass('uncheckedRadio')
     *                      .set('checked', true)
     *                      .on('click', function() {
     *                             $(this).set({@: 'uncheckedRadio');
     *                      });
     * 
* * @example Using $() as a #ready#$.ready() shortcut: *
     * $(function() {
     *   // in here you can safely work with the HTML document
     * });
     * 
* * @param selector a simple, CSS-like selector for HTML elements. It supports '#id' (lookup by id), '.class' (lookup by class), * 'element' (lookup by elements) and 'element.class' (combined class and element). Use commas to combine several selectors. * You can also join two or more selectors by space to find elements which are descendants of the previous selectors. * For example, use 'div' to find all div elements, '.header' to find all elements containing a class name called 'header', and * 'a.popup' for all a elements with the class 'popup'. To find all elements with 'header' or 'footer' class names, * write '.header, .footer'. To find all divs elements below the element with the id 'main', use '#main div'. * The selector "*" will return all elements. * @param list a list to copy. It can be an array, another Minified list, a DOM nodelist or anything else that has a length property and * allows read access by index. A shallow copy of the list will be returned. Nulls will be automatically removed from the copy. Nested lists * will be flattened, so the result only contains nodes. * @param object an object to create a single-element list containing only the object. If the argument is null, an empty list will be returned. * @param domreadyFunction a function to be registered using #ready#$.ready(). * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection. The context can be specified as * a selector, a list or using a single object, just like the first argument. * The returned list will contain only descendants of the context nodes. All others will be filtered out. * @param childOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not * true, all descendants of the context will be included. * @return the array-like ##list#Minified list## object containing the content specified by the selector. * Please note that if the first argument was a list, the existing order will be kept. If the first argument was a simple selector, the nodes are in document order. * If you combined several selectors using commas, only the individual results of the selectors will keep the document order, * but will then be joined to form a single list. This list will * not be in document order anymore, unless you use a build without legacy IE support. * Duplicate nodes will be removed from selectors, but not from lists. * * @see #underscore#_() is Util's alternative constructor for ##list#Minified lists## * @see ##dollardollar#$$()## works like $(), but returns the resulting list's first element. */ '$': $, /*$ * @id dollardollar * @group SELECTORS * @requires * @configurable default * @name $$() * @syntax $(selector) * @syntax $(selector, context) * @syntax $(selector, context, childOnly) * @shortcut $$() - It is recommended that you assign MINI.$$ to a variable $$. * @module WEB * Returns a DOM object containing the first match of the given selector, or undefined if no match was found. * $$ allows you to easily access an element directly. It is the equivalent to writing $(selector)[0]. * * Please note that the function $$ will not be automatically exported by Minified. You should always import it * using the recommended import statement: *
     * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
     * 
* * @example Select the checkbox 'myCheckbox': *
     * $$('#myCheckbox').checked = true;
     * 
* * @param selector a simple, CSS-like selector for the element. Uses the same syntax as #dollar#$(). The most common * parameter for this function is the id selector with the syntax "#id". * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection. The context can be specified as * a selector, a list or using a single object, just like the first argument. * The returned list will contain only descendants of the context nodes. All others will be filtered out. * @param childOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not * true, all descendants of the context will be included. * @return a DOM object of the first match, or undefined if the selector did not return at least one match * * @see ##dollar#$()## creates a list using the selector, instead of returning only the first result. */ '$$': $$, /*$ * @id M * @name M * @syntax MINI.M * @module WEB, UTIL * * Exposes the internal class used by all ##list#Minified lists##. This is mainly intended to allow you adding your * own functions. * * @example Adding a function printLength() to M: *
     * MINI.M.prototype.printLength = function() { console.log(this.length); };
     * 
*/ 'M': M, /*$ * @id getter * @requires get * @name MINI.getter * @syntax MINI.getter * @module WEB * * Exposes a map of prefix handlers used by ##get(). You can add support for a new prefix in get() * by adding a function to this map. The prefix can be any string consisting solely of non-alphanumeric characters * that's not already used by Minified. * * You must not replace getters by a new map, but must always modify the existing map. * * The function's signature is function(list, name) where *
list
Is the Minified list to get the value from. By convention you should always use only the first element. The list is * non-empty and the first elememt can't be null or undefined (get() automatically returns undefined in * all other case).
*
name
The name of the property. That's the part AFTER the prefix.
*
(callback return value)
The value to return to the user.
* * @example Adding a shortcut '||' for accessing border style properties: *
     * MINI.getter['||'] = function(list, name) {
     * 	return list.get('$border' + name.replace(/^[a-z]/, function(a) { return a.toUpperCase()});
     * };
     *
     * var borderColor = $('#box').get('||color'); // same as '$borderColor'
     * var borderLeftRadius = $('#box').get('||leftRadius'); // same as '$borderLeftRadius'
     * 
* * @example Adding XLink attribute support to get(). This is useful if you work with SVG. The prefix is '>'. *
     * MINI.getter['>'] = function(list, name) {
     * 	return list[0].getAttributeNS('http://www.w3.org/1999/xlink', name);
     * };
     *
     * var xlinkHref = $('#svgLink').get('>href');
     * 
*/ 'getter': getter, /*$ * @id setter * @requires set * @name MINI.setter * @syntax MINI.setter * @module WEB * * Exposes a map of prefix handlers used by ##set(). You can add support for a new prefix in set() * by adding a function to this map. The prefix can be any string consisting solely of non-alphanumeric characters * that's not already used by Minified. * * You must not replace setters by a new map, but must always modify the existing map. * * The function's signature is function(list, name, value) where *
list
Is the Minified list to use.
*
name
The name of the property. That's the part AFTER the prefix.
*
value
Either the value to set, or a callback function to create the value that you must call for each * value (see ##set() ).
*
* * If you provide complete ##get() and ##set() support for a prefix, you are also able to use it in other Minified * function such as ##animate() and ##toggle(). * * @example Adding a shortcut '||' for accessing border style properties. As it's just calling ##set() for an existing * property, it is not required to extra code for the callback. *
     * MINI.setter['||'] = function(list, name, value) {
     * 	list.set('$border' + name.replace(/^[a-z]/, function(a) { return a.toUpperCase()}, value);
     * };
     *
     * $('#box').set('||color', 'red');   // same as set('$borderColor', 'red')
     * $('#box').set('||leftRadius', 4);  // same as set('$borderLeftRadius', 4)
     * 
* * @example Adding XLink attribute support to set(). This is useful if you work with SVG. The prefix is '>'. *
     * MINI.setter['>'] = function(list, name, value) {
     * 	list.each(function(obj, index) {
     * 		var v;
     * 		if (_.isFunction(value))
     * 			v = value(obj.getAttributeNS('http://www.w3.org/1999/xlink', name), index, obj);
     * 		else
     * 			v = value;
     *
     *		if (v == null)
     *			obj.removeAttributeNS('http://www.w3.org/1999/xlink', name);
     *		else
     *			obj.setAttributeNS('http://www.w3.org/1999/xlink', name, v);
     *	});
     * };
     *
     * $('#svgLink').set('>href', 'http://minifiedjs.com/');
     * 
*/ 'setter': setter /*$ * @stop */ ///#/snippet webExports }; ///#snippet commonAmdEnd }); ///#/snippet commonAmdEnd ///#snippet webDocs /*$ * @id list * @name Minified Lists * @module WEB, UTIL * * Minified lists are Array-like objects provided by Minified. Like a regular JavaScript array, * they provide a length property and you can access their content using the index operator (a[5]). * However, they do not provide the same methods as JavaScript's native array and are designed to be immutable, so * there is no direct way to add something to a Minified list. Instead Minified provides a number of functions and methods * that take a list and create a modified copy which, for example, may contain additional elements. * * Minified lists are typically created either using the Web module's #dollar#$() function or with the Util module's * #underscore#_() function, but many functions in the Util module also return a Minified list. * * The Util module provides a function ##_.array() that converts a Minified list to a regular JavaScript array. */ /*$ * @id promiseClass * @name Promise * @module WEB, UTIL * * Promises are objects that represent the future result of an asynchronous operation. When you start such an operation, using #request#$.request(), * ##animate(), or ##wait(), you will get a Promise object that allows you to get the result as soon as the operation is finished. * * Minified's full distribution ships with a Promises/A+-compliant implementation of Promises that should * be able to interoperate with most other Promises implementations. Minified's Web module in stand-alone distribution comes with a limited implementation. * See below for details. * * What may be somewhat surprising about this Promises specification is that the only standard-compliant way to access the result is to * register callbacks. They will be invoked as soon as the operation is finished. * If the operation already ended when you register the callbacks, the callback will then just be called from the event loop as soon * as possible (but never while the ##then() you register them with is still running).
* This design forces you to handle the operation result asynchronously and disencourages 'bad' techniques such as polling. * * The central method of a Promise, and indeed the only required function in Promises/A+, is ##then(). It allows you to register * two callback methods, one for success (called 'fulfillment' in Promises/A+ terminology) and one for failures (called 'rejection' in Promises/A+). * * This example shows you how to use then(): *
 * $.request('get', 'http://example.com/weather?zip=90210')
 *  .then(function success(result) {
 *      alert('The weather is ' + result);
 *  }, function error(exception) {
 *  	alert('Something went wrong');
 *  });
 * 
* * What makes Promises so special is that ##then() itself returns a new Promise, which is based on the Promise then() was called on, but can be * modified by the outcome of callbacks. Both arguments to then() are optional, and you can also write the code like this: *
 * $.request('get', 'http://example.com/weather?zip=90210')
 *  .then(function success(result) {
 *      alert('The weather is ' + result);
 *  })
 *  .then(null, function error(exception) {
 *  	alert('Something went wrong');
 *  });
 * 
* * Because the first ##then() returns a new Promise based on the original Promise, the second then() will handle errors of the request just like * the first one did. There is only one subtle difference in the second example: the error handler will not only be called if the request failed, * but also when the request succeded but the success handler threw an exception. That's one of the two differences between the original Promise and * the Promise returned by then(). Any exception thrown in a callback causes the new Promise to be in error state. * * Before I show you the second difference between the original Promise and the new Promise, let me make the example a bit more readable * by using ##error(), which is not part of Promises/A+, but a simple extension by Minified. It just registers the failure callback without * forcing you to specify null as first argument: *
 * $.request('get', 'http://example.com/weather?zip=90210')
 *  .then(function success(result) {
 *      alert('The weather is ' + result);
 *  })
 *  .error(function error(exception) {  // error(callback) is equivalent to then(null, callback)
 *  	alert('Something went wrong');
 *  });
 * 
* * A very powerful capability of Promises is that you can easily chain them. If a ##then() callback returns a value, the new Promise returned * by then() will be marked as success (fulfilled) and this value is the result of the operation. If a callback returns a Promise, * the new Promise will assume the state of the returned Promise. You can use the latter to create chains of asynchronous operations, * but you still need only a single error handler for all of them and you do not need to nest functions to achieve this: *
 * $.request('get', 'http://example.com/zipcode?location=Beverly+Hills,+CA')
 *  .then(function(resultZip) {
 *      return $.request('get', 'http://example.com/weather', {zip: resultZip});
 *  })
 *  .then(function(resultWeather) {
 *      alert('The weather in Beverly Hills is ' + resultWeather);
 *  })
 *  .error(function(exception) {
 *  	alert('Something went wrong');
 *  });
 * 
* * Only the full Minified distribution allows you to create promises yourself, using the ##promise() function. The Promises/A+ * specification does not specify how to fulfill a promise, but in Minified's implementation every Promise object has a function fire() * that needs to be called when the promise result is ready. It requires two arguments. * The first is a boolean, true for a successful operation and false for a failure. The second is an array or list containing the * arguments to call the corresponding ##then() handler with. * * The following example is a function, similar to ##wait(), that returns a Promise which succeeds after the given amount * of milliseconds has passed. * It then fulfills the promise with the number of milliseconds as argument. * *
 * function timeout(durationMs) {
 *		var p = _.promise();
 *		setTimeout(function() { p.fire(true, [durationMs]); }, durationMs);
 *		return p;
 * }
 * 
* Call it like this: *
 * timeout(1000).then(function(ms) { window.alert(ms+ ' milliseconds have passed.'); });
 * 
* *

Limited Promises Implementation in Web module

* If you use only the Web module, instead of the full implementation, the promises implementation is not fully Promises/A+ compliant. * One major difference is that it does not allow you create promises yourself. The only way to get a promise in the Web module * is from functions like ##animate() and ##request(). The other difference is that the interoperability with other promises frameworks * is limited, even though it should be good enough most of the time. * * There are two things you may run into when you use Web's simplified implementation with a complete implementation: *
  1. The simplified implementation does not support recursive thenables. So when you register callbacks with ##then(), * you can return a promise or a thenable, but only if that promise is not also returning a promise.
  2. *
  3. Many corner cases required by the Promises/A+ specification are not handled. When interoperating using * reasonable implementations, you may never run into this, but Promises/A+ has detailed rules for things like ##then() * methods implemented as dynamic getter and returning a new value on each invocation or throwing exceptions. If you need * a water-proof implementation, you need to use the complete implementation in Minified's full package.
*/ /*$ * @stop */ ///#/snippet webDocs