minifiedjs-rails 0.0.1.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ var l=!0,p=null,r=!1;if(/^u/.test(typeof define)){var J={};this.define=function(y,s){J[y]=s()};this.require=function(y){return J[y]}}define("minified",function(){function y(a){return a!=p?""+a:""}function s(a){return"string"==typeof a}function t(a){return"function"==typeof a&&!a.item}function B(a){return a&&a.nodeType}function u(a){return a&&a.length!=p&&!s(a)&&!B(a)&&!t(a)}function z(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c]);return a}function h(a,b){for(var c=0;a&&c<a.length;c++)b(a[c],c);return a}function H(a,b){var c=[];h(a,function(a,e){b(a,e)&&c.push(a)});return c}function v(a,b){var c=[];h(a,function(a,e){u(a=b(a,e))?h(a,function(a){c.push(a)}):a!=p&&c.push(a)});return c}function K(a,b){var c=[];z(a,function(a,e){u(a=b(a,e))?h(a,function(a){c.push(a)}):a!=p&&c.push(a)});return c}function m(a,b,c){return y(a).replace(b,c||"")}function A(a){return parseFloat(m(a,/^[^\d-]+/))}function L(a){var b={$position:"absolute",$visibility:"hidden",$display:"block",$height:p},c=a.get(b);a.set(b);b=a.get("$height",l);a.set(c);return b}function M(a){a()}function N(){h(E,M);E=p}function O(a){E?E.push(a):n.setTimeout(a,0)}function P(a,b,c,d){return function(){var e=w(x.createElement(a));u(b)||"object"!=typeof b?e.add(b):e.set(b).add(c);d&&d(e);return e}}function I(){function a(a,e){b==p&&(b=a,c=e,n.setTimeout(function(){h(d,M)},0))}var b,c=[],d=[],e=a.then=function(a,e){function f(){try{var d=b?a:e;if(t(d)){var f=d.apply(p,c);f&&t(f.then)?f.then(function(a){k(l,[a])},function(a){k(r,[a])}):k(l,[f])}else k(b,c)}catch(h){k(r,[h])}}var k=I();b!=p?n.setTimeout(f,0):d.push(f);return k};a.always=function(a){return e(a,a)};a.error=function(a){return e(0,a)};return a}function Q(a){return T[a]||"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}function w(a,b,c){return t(a)?O(a):new D(C(a,b,c))}function C(a,b,c){function d(a){a=function S(a){return u(a)?v(a,S):a}(a);return e?H(a,function(a){for(;a=a.parentNode;){if(a===e)return l;if(c)return r}}):a}var e,j,g,f,k;if(b&&1!=(b=C(b)).length)return v(b,function(b){return C(a,b,c)});e=b&&b[0];if(!s(a))return d(u(a)?a:[a]);if(1<(b=a.split(/\s*,\s*/)).length)return v(b,function(a){return C(a,e,c)});if(b=/(\S+)\s+(.+)$/.exec(a))return C(b[2],C(b[1],e),c);if(a!=(b=m(a,/^#/)))return d([x.getElementById(b)]);e=e||x;j=(b=/([^.]*)\.?([^.]*)/.exec(a))[1];f=b[2];b=(g=e.getElementsByClassName&&f)?e.getElementsByClassName(f):e.getElementsByTagName(j||"*");if(j=g?j:f)k=RegExp("\\b"+j+"\\b","i"),b=H(b,function(a){return k.test(a[g?"nodeName":"className"])});return e?d(b):b}function D(a){for(var b=this.length=a.length,c=0;c<b;c++)this[c]=a[c]}var n=this,x=document,E=[],F=[],U=n.requestAnimationFrame||function(a){n.setTimeout(a,33)},G=!!x.all&&!E.map,T={" ":"\\t","\r":"\\r","\n":"\\n",'"':'\\"',"\\":"\\\\"};z({each:function(a){return h(this,a)},filter:function(a){return new D(H(this,a))},collect:function(a){return new D(v(this,a))},sub:function(a,b){var c=0>a?this.length+a:a,d=0<=b?b:this.length+(b||0);return new D(H(this,function(a,b){return b>=c&&b<d}))},find:function(a){for(var b,c=t(a)?a:function(b,c){if(a===b)return c},d=0;d<this.length;d++)if((b=c(this[d],d))!=p)return b},hasClass:function(a){var b=RegExp("\\b"+a+"\\b");return this.find(function(a){return b.test(a.className)?a:p})},remove:function(){h(this,function(a){a.parentNode.removeChild(a)})},text:function(){function a(b){var c=B(b);return 1==c?v(b.childNodes,a):5>c?b.data:p}return v(this,a).join("")},get:function(a,b){var c=this,d=c[0];if(d){if(s(a)){var e=m(a,/^[$@]/),j;j="$"==a?d.className:"$$"==a?G?d.style.cssText:d.getAttribute("style"):/\$\$/.test(a)&&("hidden"==d.style.visibility||"none"==d.style.display)?0:"$$fade"==a?isNaN(j=G?A(d.style.filter)/100:A(d.style.opacity))?1:j:"$$slide"==a?c.get("$height"):/^\$/.test(a)?n.getComputedStyle?n.getComputedStyle(d,p).getPropertyValue(m(e,/[A-Z]/g,function(a){return"-"+a.toLowerCase()})):(d.currentStyle||d.style)[e]:/^@/.test(a)?d.getAttribute(e):d[e];return b?A(j):j}var g={};(u(a)?h:z)(a,function(a){g[a]=c.get(a,b)});return g}},set:function(a,b){var c=this,d;void 0!==b?"$$fade"==a||"$$slide"==a?c.set({$visibility:0<(d=A(b))?"visible":"hidden",$display:"block"}).set("$$fade"==a?G?{$filter:"alpha(opacity = "+100*d+")",$zoom:1}:{$opacity:d}:{$height:/px$/.test(b)?b:function(a,b,c){return d*(d&&L(w(c)))+"px"},$overflow:"hidden"}):h(c,function(c,d){var g=m(a,/^[@$]/),f=c.className||"",k=/^\$/.test(a)?c.style:c,q=t(b)?b(w(c).get(a),d,c):b;"$"==a?q!=p&&(h(q.split(/\s+/),function(a){var b=m(a,/^[+-]/),c=f;f=m(f,RegExp("\\b"+b+"\\b"));if(/^\+/.test(a)||b==a&&c==f)f+=" "+b}),c.className=m(f,/^\s+|\s+(?=\s|$)/g)):"$$"==a?G?k.cssText=q:q!=p?c.setAttribute("style",q):c.removeAttribute("style"):/^@/.test(a)?q!=p?k.setAttribute(g,q):k.removeAttribute(g):k[g]=q}):s(a)||t(a)?c.set("$",a):z(a,function(a,b){c.set(a,b)});return c},add:function(a,b){return h(this,function(c,d){var e;(function g(a){u(a)?h(a,g):t(a)?g(a(c,d)):a!=p&&(a=B(a)?a:x.createTextNode(a),e?e.parentNode.insertBefore(a,e.nextSibling):b?b(a,c,c.parentNode):c.appendChild(a),e=a)})(B(a)&&d?p:a)})},fill:function(a){return h(this,function(a){w(a.childNodes).remove()}).add(a)},addBefore:function(a){return this.add(a,function(a,c,d){d.insertBefore(a,c)})},addAfter:function(a){return this.add(a,function(a,c,d){d.insertBefore(a,c.nextSibling)})},addFront:function(a){return this.add(a,function(a,c){c.insertBefore(a,c.firstChild)})},replace:function(a){return this.add(a,function(a,c,d){d.replaceChild(a,c)})},clone:function(a){return new D(v(this,function(b){var c=B(b);if(1==c){var d={$:b.className||p,$$:G?b.style.cssText:b.getAttribute("style")};h(b.attributes,function(a){var c=a.name;"id"!=c&&"style"!=c&&"class"!=c&&b.getAttribute(c)&&(d["@"+c]=a.value)});return P(b.tagName,d,w(b.childNodes).clone(),a)}return 5>c?b.data:p}))},animate:function(a,b,c,d){var e=this,j=[],g=/-?[\d.]+/,f,k=I(),q=t(c)?c:function(a,b,d){return a+d*(b-a)*(c+(1-c)*d*(3-2*d))};d=d||{};d.time=0;d.stop=function(){f();k(r)};b=b||500;c=c||0;h(e,function(c){var b={a:w(c),c:{}};z(b.b=b.a.get(a),function(c,d){var e=a[c];"$$slide"==c&&(e=e*L(b.a)+"px");b.c[c]=/^[+-]=/.test(e)?m(e.substr(2),g,A(d)+A(m(e,/\+?=/))):e});j.push(b)});f=w.loop(function(a){function c(a,b){return/^#/.test(a)?parseInt(6<a.length?a.substr(1+2*b,2):(a=a.charAt(1+b))+a,16):parseInt(m(a,/[^\d,]+/g).split(",")[b])}d.time=a;a>=b||0>a?(h(j,function(a){a.a.set(a.c)}),f(),d.time=p,k(l,[e])):h(j,function(d){z(d.b,function(e,f){var j="rgb(",k=d.c[e],h=a/b;if(/^#|rgb\(/.test(k))for(var n=0;3>n;n++)j+=Math.round(q(c(f,n),c(k,n),h))+(2>n?",":")");else j=m(k,g,y(q(A(f),A(k),h)));d.a.set(e,j)})})});return k},toggle:function(a,b,c,d){var e=this,j={},g=r,f=/\b(?=\w)/g;return!b?e.toggle(m(a,f,"-"),m(a,f,"+")):e.set(a)&&function(f){f!==g&&(g=f===l||f===r?f:!g,c?e.animate(g?b:a,j.stop?j.stop()||j.time:c,d,j):e.set(g?b:a))}},on:function(a,b,c,d){return h(this,function(e,j){h(a.split(/\s/),function(a){function f(e){e=e||n.event;if((!b.apply(d?c:e.target,d||c||[e,j])||d)&&a==k)e.stopPropagation&&(e.preventDefault(),e.stopPropagation()),e.returnValue=r,e.cancelBubble=l}var k=m(a,/\|/);(b.M=b.M||[]).push({e:e,h:f,n:k});e.addEventListener?e.addEventListener(k,f,l):e.attachEvent("on"+k,f)})})}},function(a,b){D.prototype[a]=b});z({request:function(a,b,c,d,e,j){var g,f=c,k=0,h=I();try{g=n.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Msxml2.XMLHTTP.3.0"),c!=p&&(d=d||{},!s(c)&&!B(c)&&(f=K(c,function R(a,b){return u(b)?v(b,function(b){return R(a,b)}):encodeURIComponent(a)+(b!=p?"="+encodeURIComponent(b):"")}).join("&")),/post/i.test(a)?!B(c)&&!s(c)&&!d["Content-Type"]&&(d["Content-Type"]="application/x-www-form-urlencoded"):(b+="?"+f,f=p)),g.open(a,b,l,e,j),z(d,function(a,b){g.setRequestHeader(a,b)}),g.onreadystatechange=function(){4==g.readyState&&!k++&&(200==g.status?h(l,[g.responseText,g.responseXML]):h(r,[g.status,g.statusText,g.responseText]))},g.send(f)}catch(m){k||h(r,[0,p,y(m)])}return h},toJSON:function b(c){return c==p?""+c:s(c=c.valueOf())?'"'+m(c,/[\\\"\x00-\x1f\x22\x5c]/g,Q)+'"':u(c)?"["+v(c,b).join()+"]":"object"==typeof c?"{"+K(c,function(c,e){return b(c)+":"+b(e)}).join()+"}":y(c)},parseJSON:n.JSON?n.JSON.parse:function(b){b=m(b,/[\x00\xad\u0600-\uffff]/g,Q);if(/^[[\],:{}\s]*$/.test(m(m(b,/\\["\\\/bfnrtu]/g),/"[^"\\\n\r]*"|true|false|null|[\d.eE+-]+/g)))return eval("("+b+")")},ready:O,setCookie:function(b,c,d,e,j,g){x.cookie=b+"="+(g?c:escape(c))+(d?"; expires="+("object"==typeof d?d:new Date((new Date).getTime()+864e5*d)).toUTCString():"")+"; path="+(e?escapeURI(e):"/")+(j?"; domain="+escape(j):"")},getCookie:function(b,c){var d,e=(d=RegExp("(^|;)\\s*"+b+"=([^;]*)").exec(x.cookie))&&d[2];return c?e:e&&unescape(e)},loop:function(b){var c={d:b,f:(new Date).getTime(),b:function(){for(var b=0;b<F.length;b++)F[b]===c&&F.splice(b--,1)}};2>F.push(c)&&function e(){h(F,function(b){b.d(Math.max(0,(new Date).getTime()-b.f),b.b)}).length&&U(e)}();return c.b},wait:function(b,c){var d=I();n.setTimeout(function(){d(l,c)},b||0);return d},off:function(b){h(b.M,function(b){b.e.removeEventListener?b.e.removeEventListener(b.n,b.h,l):b.e.detachEvent("on"+b.n,b.h)});b.M=p}},function(b,c){w[b]=c});n.onload=N;x.addEventListener&&x.addEventListener("DOMContentLoaded",N,r);return{$:w,$$:function(b){return C(b)[0]},EE:P}});
@@ -0,0 +1,2900 @@
1
+ /*
2
+ * Minified-web.js - Complete library for JavaScript interaction in less than 4kb
3
+ *
4
+ * Public Domain. Use, modify and distribute it any way you like. No attribution required.
5
+ *
6
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
7
+ *
8
+ * Contains code based on https://github.com/douglascrockford/JSON-js (also Public Domain).
9
+ *
10
+ * https://github.com/timjansen/minified.js
11
+ */
12
+
13
+ /*
14
+ * When you read this code, please keep in mind that it is optimized to produce small and gzip'able code
15
+ * after being minimized with Closure (http://closure-compiler.appspot.com). Run-time performance and readability
16
+ * should be acceptable, but are not a primary concern.
17
+ *
18
+ *
19
+ * Various comment annotations control the builder in parser-src.js / builder-src.js. This file should always work without the builder,
20
+ * but only the builder allows you to remove functions.
21
+ *
22
+ * Here's a short summary of that the non-documenting tags mean.
23
+ *
24
+ * Multi-Line Comments:
25
+ * - @id marks the beginning of an optional block. It ends with the next @id block, or the next @stop comment.
26
+ * - @requires defines the ids that the current block depends on. They will always be available.
27
+ * - @configurable the block can be selected in the GUI. If the value is 'default', it is a enabled by default. If it is 'optional', it is not.
28
+ * - @dependency if set, the block is only used as a dependency and won't show up in builder or documentation
29
+ * - @name a name for builder and reference docs
30
+ * - @doc if 'no', the section will not be displayed in reference docs, only in builder
31
+ * - @module the module(s), comma-separated. Can be WEB, UTIL or APP
32
+ *
33
+ * Single-Line Comments
34
+ * - @cond id defines that the code following after the id will be included if the block id is enabled
35
+ * - @cond !id include the following line only if the block id is disabled
36
+ * - @condblock id will include all following lines if id is enabled until the next @condend. @condblocks can be nested.
37
+ * - @condend ends a @condblock
38
+ */
39
+
40
+ // ==ClosureCompiler==
41
+ // @output_file_name minified.js
42
+ // @compilation_level ADVANCED_OPTIMIZATIONS
43
+ // ==/ClosureCompiler==
44
+
45
+ /*$
46
+ * @id require
47
+ * @name require()
48
+ * @syntax require(name)
49
+ * @group OPTIONS
50
+ * @module WEB, UTIL, APP
51
+ * Returns a reference to a module. If you do not use an AMD loader to load Minified, just call <var>require()</var> with the
52
+ * argument 'minified' to get a reference to Minified.
53
+ * If you do use an AMD loader, Minified will not define this function and you can use the AMD loader to obtain the
54
+ * reference to Minified.
55
+ * Minified's version of <var>require</var> is very simple and will only support Minified, but <strong>no other libraries</strong>. You can not
56
+ * use it to load other modules, and it will be incompatible with all non-AMD libraries that also define a function
57
+ * of the same name. If you need to work with several libraries, you need a real AMD loader.
58
+ *
59
+ * @param name the name of the module to request. In Minified's implementation, only 'minified' is supported.
60
+ * @return the reference to Minified if 'minified' had been used as name. <var>undefined</var> otherwise.
61
+ */
62
+
63
+ /*$
64
+ * @id amdsupport
65
+ * @name AMD support
66
+ * @configurable default
67
+ * @group OPTIONS
68
+ * @doc no
69
+ * @module WEB, UTIL
70
+ * If enabled, Minified will work correctly with AMD frameworks. If not, it will just provide a global
71
+ * function ##require(), which can be used only to load 'minified'.
72
+ */
73
+ if (/^u/.test(typeof define)) { // no AMD support available ? define a minimal version
74
+ var def = {};
75
+ this['define'] = function(name, f) {def[name] = f();};
76
+ this['require'] = function(name) { return def[name]; };
77
+ }
78
+
79
+ define('minified', function() {
80
+ /*$
81
+ * @stop
82
+ */
83
+ // @cond !amdsupport (function() {
84
+
85
+ //// GLOBAL VARIABLES ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86
+
87
+ /**
88
+ * @const
89
+ */
90
+ var _window = this;
91
+
92
+ /**
93
+ * @const
94
+ */
95
+ var _document = document;
96
+
97
+ /**
98
+ * @const
99
+ * @type {!string}
100
+ */
101
+ var BACKSLASHB = '\\b';
102
+ /** @const */
103
+ var undef;
104
+
105
+ var PUSH = [].push;
106
+
107
+ /*$
108
+ * @id ready_vars
109
+ * @dependency
110
+ */
111
+ /** @type {!Array.<function()>} */
112
+ var DOMREADY_HANDLER = [];
113
+
114
+ /*$
115
+ * @id animation_vars
116
+ * @dependency
117
+ */
118
+ /** @type {!Array.<{c:!function(), t:!number, s:!function()}>} */
119
+ var ANIMATION_HANDLERS = []; // global list of {c: <callback function>, t: <timestamp>, s:<stop function>} currently active
120
+
121
+ /** @type {!function()} */
122
+ var REQUEST_ANIMATION_FRAME = _window['requestAnimationFrame'] || function(callback) {
123
+ delay(callback, 33); // 30 fps as fallback
124
+ };
125
+
126
+ /*$
127
+ * @id fadeslide
128
+ * @requires animate set
129
+ * @group ANIMATION
130
+ * @configurable default
131
+ * @doc no
132
+ * @name Support for $$fade and $$slide
133
+ */
134
+ /*$
135
+ * @stop
136
+ */
137
+
138
+ //// GLOBAL FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139
+
140
+ /** @param s {?} */
141
+ function toString(s) { // wrapper for Closure optimization
142
+ return s!=null ? ''+s : '';
143
+ }
144
+ /**
145
+ * @param s {?}
146
+ * @param o {string}
147
+ */
148
+ function isType(s,o) {
149
+ return typeof s == o;
150
+ }
151
+ /** @param s {?} */
152
+ function isString(s) {
153
+ return isType(s, 'string');
154
+ }
155
+ function isFunction(f) {
156
+ return isType(f, 'function') && !f['item']; // item check as work-around webkit bug 14547
157
+ }
158
+ function isObject(f) {
159
+ return isType(f, 'object');
160
+ }
161
+ function isNode(n) {
162
+ return n && n['nodeType'];
163
+ }
164
+ function isList(v) {
165
+ return v && v.length != null && !isString(v) && !isNode(v) && !isFunction(v);
166
+ }
167
+ function eachObj(obj, cb) {
168
+ for (var n in obj)
169
+ if (obj.hasOwnProperty(n))
170
+ cb(n, obj[n]);
171
+ return obj;
172
+ }
173
+ function each(list, cb) {
174
+ for (var i = 0; list && i < list.length; i++)
175
+ cb(list[i], i);
176
+ return list;
177
+ }
178
+ function filter(list, filterFunc) {
179
+ var r = [];
180
+ each(list, function(node,index) {
181
+ if (filterFunc(node,index))
182
+ r.push(node);
183
+ });
184
+ return r;
185
+ }
186
+ function collect(obj, collectFunc) {
187
+ var result = [];
188
+ each(obj, function (a, b) {
189
+ if (isList(a = collectFunc(a, b))) // caution: extreme variable re-using of 'a'
190
+ each(a, function(rr) { result.push(rr); });
191
+ else if (a != null)
192
+ result.push(a);
193
+ });
194
+ return result;
195
+ }
196
+ function collectObj(obj, collectFunc) { // warning: 1:1 copy of collect(), with one diff... good for gzip..
197
+ var result = [];
198
+ eachObj(obj, function (a, b) {
199
+ if (isList(a = collectFunc(a, b))) // caution: extreme variable re-using of 'a'
200
+ each(a, function(rr) { result.push(rr); });
201
+ else if (a != null)
202
+ result.push(a);
203
+ });
204
+ return result;
205
+ }
206
+ function replace(s, regexp, sub) {
207
+ return toString(s).replace(regexp, sub||'');
208
+ }
209
+ function delay(f, delayMs) {
210
+ _window.setTimeout(f, delayMs||0);
211
+ }
212
+ function extractNumber(v) {
213
+ return parseFloat(replace(v, /^[^\d-]+/));
214
+ }
215
+
216
+ function getNaturalHeight(elementList) {
217
+ var q = {'$position': 'absolute', '$visibility': 'hidden', '$display': 'block', '$height': null};
218
+ var oldStyles = elementList['get'](q);
219
+ elementList['set'](q);
220
+ var h = elementList['get']('$height', true);
221
+ elementList['set'](oldStyles);
222
+ return h;
223
+ }
224
+
225
+ function now() {
226
+ return new Date().getTime();
227
+ }
228
+
229
+ function callArg(f) {f();}
230
+
231
+ // for ready()
232
+ function triggerDomReady() {
233
+ each(DOMREADY_HANDLER, callArg);
234
+ DOMREADY_HANDLER = null;
235
+ }
236
+
237
+ function ready(handler) {
238
+ // @cond debug if (typeof handler != 'function') error("First argument must be a function");
239
+ if (DOMREADY_HANDLER)
240
+ DOMREADY_HANDLER.push(handler);
241
+ else
242
+ delay(handler);
243
+ }
244
+
245
+ function $$(selector) {
246
+ return dollarRaw(selector)[0];
247
+ }
248
+
249
+ function EE(elementName, attributes, children, onCreate) {
250
+ // @cond debug if (!elementName) error("EE() requires the element name.");
251
+ // @cond debug if (/:/.test(elementName)) error("The element name can not create a colon (':').");
252
+
253
+ return function() {
254
+ var list = $(_document.createElement(elementName));
255
+ (isList(attributes) || !isObject(attributes)) ? list['add'](attributes) : list['set'](attributes)['add'](children);
256
+ if (onCreate)
257
+ onCreate(list);
258
+ return list;
259
+ };
260
+ }
261
+
262
+ function promise() {
263
+ var state; // undefined/null = pending, true = fulfilled, false = rejected
264
+ var values = []; // an array of values as arguments for the then() handlers
265
+ var deferred = []; // functions to call when set() is invoked
266
+
267
+ var set = function (newState, newValues) {
268
+ if (state == null) {
269
+ state = newState;
270
+ values = newValues;
271
+ delay(function() {
272
+ each(deferred, callArg);
273
+ });
274
+ }
275
+ };
276
+ /*$
277
+ * @id then
278
+ * @group REQUEST
279
+ * @name promise.then()
280
+ * @syntax promise.then()
281
+ * @syntax promise.then(onSuccess)
282
+ * @syntax promise.then(onSuccess, onError)
283
+ *
284
+ * @module WEB, UTIL
285
+ * Registers two callbacks that will be invoked when the ##promise#Promise##'s asynchronous operation finished
286
+ * successfully (<var>onSuccess</var>) or an error occurred (<var>onError</var>). The callbacks will be called after
287
+ * <var>then()</var> returned, from the browser's event loop.
288
+ * Minified implements the Promises/A+ specification, allowing interoperability with other Promises frameworks.
289
+ * You can chain <var>then()</var> invocations, as <var>then()</var> returns another Promise object that you can attach to.
290
+ *
291
+ * @example Simple handler for an HTTP request. Handles only success and ignores errors.
292
+ * <pre>
293
+ * $.request('get', '/weather.html')
294
+ * .then(function(txt) {
295
+ * alert('Got response!');
296
+ * });
297
+ * </pre>
298
+ *
299
+ * @example Including an error handler.
300
+ * <pre>
301
+ * $.request('get', '/weather.html')
302
+ * .then(function(txt) {
303
+ * alert('Got response!');
304
+ * }, function(err) {
305
+ * alert('Error!');
306
+ * }));
307
+ * </pre>
308
+ *
309
+ * @example Chained handler.
310
+ * <pre>
311
+ * $.request('get', '/weather.do')
312
+ * .then(function(txt) {
313
+ * showWeather(txt);
314
+ * }
315
+ * .then(function() {
316
+ * return $.request('get', '/traffic.do');
317
+ * }
318
+ * .then(function(txt) {
319
+ * showTraffic(txt);
320
+ * }
321
+ * .then(function() {
322
+ * alert('All result displayed');
323
+ * }, function() {
324
+ * alert('An error occurred');
325
+ * });
326
+ * </pre>
327
+ *
328
+ * @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.
329
+ * If the function returns a ##promise#Promise##, that Promise will be evaluated to determine the state of the promise returned by <var>then()</var>. If it returns any other value, the
330
+ * returned Promise will also succeed. If the function throws an error, the returned Promise will be in error state.
331
+ * Pass <var>null</var> or <var>undefined</var> if you do not need the success handler.
332
+ * @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
333
+ * be evaluated to determine the state of the Promise returned by <var>then()</var>. If it returns anything else, the returned Promise will
334
+ * have success status. If the function throws an error, the returned Promise will be in the error state.
335
+ * You can pass <var>null</var> or <var>undefined</var> if you do not need the error handler.
336
+ * @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.
337
+ * If no callback has been provided and the original Promise changes to that state, the new Promise will change to that state as well.
338
+ */
339
+ var then = set['then'] = function(onFulfilled, onRejected) {
340
+ var newPromise = promise();
341
+ var callCallbacks = function() {
342
+ try {
343
+ var f = (state ? onFulfilled : onRejected);
344
+ if (isFunction(f)) {
345
+ var r = f.apply(null, values);
346
+ if (r && isFunction(r['then']))
347
+ r['then'](function(value){newPromise(true,[value]);}, function(value){newPromise(false,[value]);});
348
+ else
349
+ newPromise(true, [r]);
350
+ }
351
+ else
352
+ newPromise(state, values);
353
+ }
354
+ catch (e) {
355
+ newPromise(false, [e]);
356
+ }
357
+ };
358
+ if (state != null)
359
+ delay(callCallbacks);
360
+ else
361
+ deferred.push(callCallbacks);
362
+ return newPromise;
363
+ };
364
+ /*$
365
+ * @id always
366
+ * @group REQUEST
367
+ * @name promise.always()
368
+ * @syntax promise.always(callback)
369
+ * @module WEB, UTIL
370
+ * Registers a callback that will always be called when the ##promise#Promise##'s operation ended, no matter whether the operation succeeded or not.
371
+ * This is a convenience function that will call ##then() with the same function for both arguments. It shares all of its semantics.
372
+ *
373
+ * @example Simple handler for a HTTP request.
374
+ * <pre>
375
+ * $.request('get', '/weather.html')
376
+ * .always(function() {
377
+ * alert('Got response or error!');
378
+ * });
379
+ * </pre>
380
+ *
381
+ * @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
382
+ * vary depending on whether it succeeded or not. If the function returns a ##promise#Promise##, that Promise will
383
+ * be evaluated to determine the state of the returned Promise. If provided and it returns regularly, the returned promise will
384
+ * have success status. If it throws an error, the returned Promise will be in the error state.
385
+ * @return a new ##promise#Promise## object. Its state is determined by the callback.
386
+ */
387
+ set['always'] = function(func) { return then(func, func); };
388
+
389
+ /*$
390
+ * @id error
391
+ * @group REQUEST
392
+ * @name promise.error()
393
+ * @syntax promise.error(callback)
394
+ * @module WEB, UTIL
395
+ * Registers a callback that will be called when the operation failed.
396
+ * This is a convenience function that will invoke ##then() with the only the second argument set. It shares all of its semantics.
397
+ *
398
+ * @example Simple handler for a HTTP request.
399
+ * <pre>
400
+ * $.request('get', '/weather.html')
401
+ * .error(function() {
402
+ * alert('Got error!');
403
+ * });
404
+ * </pre>
405
+ *
406
+ * @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
407
+ * be evaluated to determine the state of the returned Promise. If it returns regularly, the returned Promise will
408
+ * have success status. If it throws an error, the returned Promise will be in error state.
409
+ * @return a new ##promise#Promise## object. Its state is determined by the callback.
410
+ */
411
+ set['error'] = function(func) { return then(0, func); };
412
+ return set;
413
+ }
414
+
415
+ /*$
416
+ * @id ucode
417
+ * @dependency
418
+ */
419
+
420
+ /*$
421
+ * @stop
422
+ */
423
+
424
+ function $(selector, context, childOnly) {
425
+ // @condblock ready
426
+ // isList(selector) is no joke, older Webkit versions return a function for childNodes...
427
+ return isFunction(selector) ? ready(selector) : new M(dollarRaw(selector, context, childOnly));
428
+ // @condend
429
+ // @cond !ready return new M(dollarRaw(selector, context));
430
+ }
431
+
432
+ /*$
433
+ * @id debug
434
+ * @group OPTIONS
435
+ * (TBD) @configurable optional
436
+ * @doc no
437
+ * @name Debugging Support
438
+ */
439
+ function error(msg) {
440
+ if (_window.console) console.log(msg);
441
+ throw Exception("Minified debug error: " + msg);
442
+ }
443
+ // @cond debug MINI['debug'] = true;
444
+
445
+ /*$
446
+ * @id dollarraw
447
+ * @requires
448
+ * @dependency yes
449
+ */
450
+ function dollarRaw(selector, context, childOnly) {
451
+
452
+ function filterElements(list) { // converts into array, makes sure context is respected
453
+ var retList = (function flatten(a) { // flatten list, keep non-lists, remove nulls
454
+ return isList(a) ? collect(a, flatten) : a;
455
+ })(list);
456
+ if (parent)
457
+ return filter(retList, function(node) {
458
+ var a = node;
459
+ while (a = a.parentNode) {
460
+ if (a === parent)
461
+ return true;
462
+ if (childOnly)
463
+ return false;
464
+ }
465
+ // fall through to return undef
466
+ });
467
+ else
468
+ return retList;
469
+ }
470
+
471
+ var parent, steps, dotPos, subSelectors;
472
+ var elements, regexpFilter, useGEbC, className, elementName, reg;
473
+
474
+ if (context && (context = dollarRaw(context)).length != 1) // if not exactly one node, iterate through all and concat
475
+ return collect(context, function(ci) { return dollarRaw(selector, ci, childOnly);});
476
+ parent = context && context[0]; // note that context may have changed in the previous two lines!! you can't move this line
477
+
478
+ if (!isString(selector))
479
+ return filterElements(isList(selector) ? selector : [selector]);
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+ elements = (parent || _document).querySelectorAll(selector);
489
+ return parent ? filterElements(elements) : elements;
490
+ };
491
+
492
+ /*$
493
+ * @id length
494
+ * @group SELECTORS
495
+ * @requires dollar
496
+ * @name .length
497
+ * @syntax length
498
+ * @module WEB, UTIL
499
+ *
500
+ * Contains the number of elements in the list.
501
+ *
502
+ * @example
503
+ * <pre>
504
+ * var list = $('input');
505
+ * var myValues = {};
506
+ * for (var i = 0; i &lt; list.length; i++)
507
+ * myValues[list[i].name] = list[i].value;
508
+ * </pre>
509
+ */
510
+ // empty, always defined below
511
+
512
+ /*$
513
+ * @id listctor
514
+ */
515
+ /** @constructor */
516
+ function M(array) {
517
+ var len = this['length'] = array.length;
518
+ for (var i = 0; i < len; i++)
519
+ this[i] = array[i];
520
+ }
521
+
522
+ //// LIST FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
523
+
524
+ eachObj({
525
+ /*$
526
+ * @id each
527
+ * @group SELECTORS
528
+ * @requires dollar
529
+ * @configurable default
530
+ * @name .each()
531
+ * @syntax each(callback)
532
+ * @module WEB, UTIL
533
+ * Invokes the given function once for each item in the list. The function will be called with the item as first parameter and
534
+ * the zero-based index as second.
535
+ *
536
+ * @example This goes through all h2 elements of the class 'section' and changes their content:
537
+ * <pre>
538
+ * $('h2.section').each(function(item, index) {
539
+ * item.innerHTML = 'Section ' + index + ': ' + item.innerHTML;
540
+ * });
541
+ * </pre>
542
+ *
543
+ * @param callback The callback <code>function(item, index)</code> to invoke for each list element.
544
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd></dl>
545
+ * The callback's return value will be ignored.
546
+ * @return the list
547
+ */
548
+ 'each': function (callback) {
549
+ return each(this, callback);
550
+ },
551
+
552
+ /*$
553
+ * @id filter
554
+ * @group SELECTORS
555
+ * @requires dollar
556
+ * @configurable default
557
+ * @name .filter()
558
+ * @syntax filter(filterFunc)
559
+ * @module WEB, UTIL
560
+ * Creates a new ##list#Minified list## that contains only those items approved by the given callback function. The function is
561
+ * called once for each item.
562
+ * If the callback function returns true, the item is shallow-copied in the new list, otherwise it will be removed.
563
+ *
564
+ * @example Creates a list of all unchecked checkboxes.
565
+ * <pre>
566
+ * var list = $('input').filter(function(item) {
567
+ * return item.getAttribute('type') == 'checkbox' && item.checked;
568
+ * });
569
+ * </pre>
570
+ *
571
+ * @param filterFunc The filter callback <code>function(item, index)</code> that decides which elements to include:
572
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
573
+ * <dt class="returnValue">(callback return value)</dt><dd><var>true</var> to include the item in the new list, <var>false</var> to omit it.</dd></dl>
574
+ * @return the new, filtered ##list#list##
575
+ */
576
+ 'filter': function(filterFunc) {
577
+ return new M(filter(this, filterFunc));
578
+ },
579
+
580
+ /*$
581
+ * @id collect
582
+ * @group SELECTORS
583
+ * @requires dollar
584
+ * @configurable default
585
+ * @name .collect()
586
+ * @syntax collect(collectFunc)
587
+ * @module WEB, UTIL
588
+ * Creates a new ##list#Minified list## from the current list using the given callback function.
589
+ * The callback is invoked once for each element of the current list. The callback results will be added to the result list.
590
+ * The callback can return
591
+ * <ul>
592
+ * <li>an array or another list-like object. Its content will be appended to the resulting list.</li>
593
+ * <li>a regular object which will be appended to the list</li>
594
+ * <li><var>null</var> (or <var>undefined</var>), which means that no object will be added to the list.
595
+ * If you need to add <var>null</var> or <var>undefined</var> to the result list, put it into a single-element array.</li>
596
+ * </ul>
597
+ *
598
+ *
599
+ * @example Goes through input elements. If they are text inputs, their value will be added to the list:
600
+ * <pre>
601
+ * var texts = $('input').collect(function(input) {
602
+ * if (input.getAttribute('type') != null || input.getAttribute('type') == 'text')
603
+ * return input.value;
604
+ * else
605
+ * return null; // ignore
606
+ * });
607
+ * </pre>
608
+ *
609
+ * @example Creates a list of all children of the selected list.
610
+ * <pre>
611
+ * var childList = $('.mySections').collect(function(node) {
612
+ * return node.childNodes; // adds a while list of nodes
613
+ * });
614
+ * </pre>
615
+ *
616
+ * @example Goes through selected input elements. For each hit, the innerHTML is added twice, once in lower case and once in upper case:
617
+ * <pre>
618
+ * var elements = $('input.myTexts').collect(function(item) {
619
+ * return [item.innerHTML.toLowerCase(), item.innerHTML.toUpperCase()];
620
+ * });
621
+ * </pre>
622
+ *
623
+ * @param collectFunc The callback <code>function(item, index)</code> to invoke for each item:
624
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
625
+ * <dt class="returnValue">(callback return value)</dt><dd>If the callback returns a list, its elements will be added to
626
+ * the result list. Other objects will also be added. Nulls and <var>undefined</var> will be ignored and be not added to
627
+ * the new result list. </dd></dl>
628
+ * @return the new ##list#list##
629
+ */
630
+ 'collect': function(collectFunc) {
631
+ return new M(collect(this, collectFunc));
632
+ },
633
+
634
+ /*$
635
+ * @id sub
636
+ * @group SELECTORS
637
+ * @requires filter
638
+ * @configurable default
639
+ * @name .sub()
640
+ * @syntax sub(startIndex)
641
+ * @syntax sub(startIndex, endIndex)
642
+ * @module WEB, UTIL
643
+ * Returns a new ##list#Minified list## containing only the elements in the specified range. If there are no elements in the range,
644
+ * an empty list is returned.
645
+ * Negative indices are supported and will be added to the list's length, thus allowing you to specify ranges at the list's end.
646
+ *
647
+ * @example Adds some text the 3rd to 5th list elements:
648
+ * <pre>
649
+ * $('#myList li').sub(3, 6).add('Hello');
650
+ * </pre>
651
+ *
652
+ * @example Clears all elements but the first:
653
+ * <pre>
654
+ * $('#myList li').sub(1).fill();
655
+ * </pre>
656
+ *
657
+ * @example Changes the class of the last list element:
658
+ * <pre>
659
+ * $('#myList li').sub(-1).set('+lastItem');
660
+ * </pre>
661
+ *
662
+ * @param startIndex the 0-based position of the sub-list start. If negative, the list's length is added and the position is relative
663
+ * to the list's end.
664
+ * @param endIndex optional the 0-based position of the sub-list end. If negative, the list's length is added and the position is relative
665
+ * to the list's end. If omitted or null, all elements following the <var>startIndex</var> are included in the result.
666
+ * @return a new ##list#list## containing only the items in the index range.
667
+ */
668
+ 'sub': function(startIndex, endIndex) {
669
+ var self = this;
670
+ var s = (startIndex < 0 ? self['length']+startIndex : startIndex);
671
+ var e = endIndex >= 0 ? endIndex : self['length'] + (endIndex || 0);
672
+ return new M(filter(self, function(o, index) {
673
+ return index >= s && index < e;
674
+ }));
675
+ },
676
+
677
+ /*$
678
+ * @id find
679
+ * @group SELECTORS
680
+ * @requires
681
+ * @configurable default
682
+ * @name .find()
683
+ * @syntax find(findFunc)
684
+ * @syntax find(element)
685
+ * @module WEB, UTIL
686
+ * Finds a specific value in the list. There are two ways of calling <var>find()</var>:
687
+ * <ol>
688
+ * <li>With an element as argument. Then <var>find()</var> will search for the first occurrence of that element in the list
689
+ * and return the index. If it is not found, <var>find()</var> returns <var>undefined</var>.</li>
690
+ * <li>With a callback function. <var>find()</var> will then call the given function for each list element until the function
691
+ * returns a value that is not <var>null</var> or <var>undefined</var>. This value will be returned.</li>
692
+ * </ol>
693
+ *
694
+ * @example Determines the position of the element with the id '#wanted' among all li elements:
695
+ * <pre>
696
+ * var elementIndex = $('li').find($$('#wanted'));
697
+ * </pre>
698
+ *
699
+ * @example Goes through the elements to find the first div that has the class 'myClass', and returns this element:
700
+ * <pre>
701
+ * var myClassElement = $('div').find(function(e) { if ($(e).hasClass('myClass')) return e; });
702
+ * </pre>
703
+ *
704
+ * @param findFunc The callback <code>function(item, index)</code> that will be invoked for every list item until it returns a non-null value:
705
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
706
+ * <dt class="returnValue">(callback return value)</dt><dd>If the callback returns something other than <var>null</var> or
707
+ * <var>undefined</var>, <var>find()</var> will return it directly. Otherwise it will continue. </dd></dl>
708
+ * @param element the element to search for
709
+ * @return if called with an element, either the element's index in the list or <var>undefined</var> if not found. If called with a callback function,
710
+ * it returns either the value returned by the callback or <var>undefined</var>.
711
+ */
712
+ 'find': function(findFunc) {
713
+ var self = this, r;
714
+ var f = isFunction(findFunc) ? findFunc : function(obj, index) { if (findFunc === obj) return index; };
715
+ for (var i = 0; i < self.length; i++)
716
+ if ((r = f(self[i], i)) != null)
717
+ return r;
718
+ },
719
+
720
+ /*$
721
+ * @id hasclass
722
+ * @group SELECTORS
723
+ * @requires find
724
+ * @configurable default
725
+ * @name .hasClass()
726
+ * @syntax hasClass(className)
727
+ * @module WEB
728
+ * Checks whether at least one HTML element in the list has the given CSS class name.
729
+ * If yes, the first element that matches is returned. Otherwise the function returns <var>undefined</var>. List elements that do not
730
+ * have a <var>className</var> property will be ignored.
731
+ *
732
+ * @example Checks whether the element 'myElement' has the class 'myClass'. If yes, it sets the text color to red.
733
+ * <pre>
734
+ * if($('#myElement').hasClass('myClass'))
735
+ * $('#myElement').set('$color', 'red');
736
+ * </pre>
737
+ *
738
+ * @param className the class to to find
739
+ * @return the first element that has the given class, or <var>undefined</var> if not found
740
+ */
741
+ 'hasClass': function(className) {
742
+ var regexp = new RegExp(BACKSLASHB + className + BACKSLASHB);
743
+ return this['find'](function(e) { return regexp.test(e.className) ? e : null; });
744
+ },
745
+
746
+ /*$
747
+ * @id remove
748
+ * @group SELECTORS
749
+ * @requires dollar
750
+ * @configurable default
751
+ * @name .remove()
752
+ * @syntax remove()
753
+ * @module WEB
754
+ * Removes all nodes of the list from the DOM tree.
755
+ *
756
+ * @example Removes the element with the id 'myContainer', including all children, from the DOM tree.
757
+ * <pre>
758
+ * $('#myContainer').remove();
759
+ * </pre>
760
+ */
761
+ 'remove': function() {
762
+ each(this, function(obj) {obj.parentNode.removeChild(obj);});
763
+ },
764
+
765
+ /*$
766
+ * @id text
767
+ * @group SELECTORS
768
+ * @requires dollar
769
+ * @configurable default
770
+ * @name .text()
771
+ * @syntax text()
772
+ * @module WEB
773
+ * Returns the concatenated text content of all nodes in the list.
774
+ * This is done by going recursively through all elements and their children. The values of text and CDATA nodes
775
+ * will be appended to the resulting string.
776
+ *
777
+ * Please note that, unlike jQuery's <var>text()</var>, Minified's will not set text content. Use ##fill() to do this.
778
+ *
779
+ * @example Returns the text of the element with the id 'myContainer'.
780
+ * <pre>
781
+ * var content = $('#myContainer').text();
782
+ * </pre>
783
+ */
784
+ 'text': function () {
785
+ function extractString(e) {
786
+ var nodeType = isNode(e);
787
+ if (nodeType == 1)
788
+ return collect(e['childNodes'], extractString);
789
+ else if (nodeType < 5) // 2 is impossible (attribute), so only 3 (text) and 4 (cdata)..
790
+ return e['data'];
791
+ else
792
+ return null;
793
+ }
794
+ return collect(this, extractString)['join']('');
795
+ },
796
+
797
+ /*$
798
+ * @id get
799
+ * @group SELECTORS
800
+ * @requires dollar
801
+ * @configurable default
802
+ * @name .get()
803
+ * @syntax get(name)
804
+ * @syntax get(name, toNumber)
805
+ * @syntax get(list)
806
+ * @syntax get(list, toNumber)
807
+ * @syntax get(map)
808
+ * @syntax get(map, toNumber)
809
+ * @module WEB
810
+ * 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
811
+ * get a single value if you specify only one name, or get a name->value map when you specify several names using an array or a map.
812
+ *
813
+ * @example Retrieves the id, title attribute and the background color of the element '#myElement':
814
+ * <pre>
815
+ * var id = $('#myElement).get('id');
816
+ * var title = $('#myElement).get('@title');
817
+ * var bgColor = $('#myElement).get('$backgroundColor');
818
+ * </pre>
819
+ *
820
+ * @example Retrieves the id, title attribute and the background color of the element '#myElement' as a map:
821
+ * <pre>
822
+ * var m = $('#myElement).get(['id', '@title', '$backgroundColor']);
823
+ * var id = m.id;
824
+ * var title = m['@title'];
825
+ * var bgColor = m.$backgroundColor;
826
+ * </pre>
827
+ *
828
+ * @example Uses ##get() and ##set() to reposition an element:
829
+ * <pre>
830
+ * var coords = $('#myElement').get({$top: 0, $left: 0}, true);
831
+ * coords.$top = coords.$top + 10 + 'px';
832
+ * coords.$left = coords.$left + 20 + 'px';
833
+ * $('#myElement').set(coords);
834
+ * </pre>
835
+ * Please note that the values of $top and $left in the <var>get()</var> invocation do not matter and will be ignored!
836
+ *
837
+ * @param name the name of the property, attribute or style. To retrieve a JavaScript property, just use its name without prefix. To get an attribute value,
838
+ * prefix the name with a '@'. A '$' prefix will retrieve a CSS style. The syntax for the CSS styles is camel-case (e.g. "backgroundColor", not "background-color").
839
+ * 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
840
+ * and thus will return the value set in style sheets if not overwritten using a regular style.
841
+ * Using just '$' as name will retrieve the 'className' property of the object, a space-separated list of all CSS classes.
842
+ * The special name '$$' will set the element's style attribute in a browser independent way.
843
+ * '$$fade' returns a value between 0 and 1 that specifies the element's
844
+ * opacity. '$$slide' returns the height of the element in pixels, with a 'px' suffix. Both '$$fade' and '$$slide' will also check the CSS styles 'visibility' and 'display'
845
+ * to determine whether the object is visible at all. If not, they will return 0.
846
+ * @param list in order to retrieve more than one value, you can specify several names in an array or list. <var>get()</var> will then return a name->value map of results.
847
+ * @param map if you specify an object that is neither list nor string, <var>get()</var> will use it as a map of property names. Each property name will be requested. The values of the properties in
848
+ * the map will be ignored. <var>get()</var> will then return a name->value map of results.
849
+ * @param toNumber if 'true', <var>get()</var> converts all returned values into numbers. If they are strings,
850
+ * <var>get()</var> removes any non-numeric characters before the conversion. This is useful when you request
851
+ * a CSS property such as '$marginTop' that returns a value with a unit suffix, like "21px". <var>get()</var> will convert it
852
+ * into a number and return 21. If the returned value is not parsable as a number, <var>NaN</var> will be returned.
853
+ * @return if <var>get()</var> was called with a single name, it returns the corresponding value.
854
+ * If a list or map was given, <var>get()</var> returns a new map with the names as keys and the values as values.
855
+ * Always returns <var>undefined</var> if the list is empty.
856
+ */
857
+ 'get': function(spec, toNumber) {
858
+ var self = this, element = self[0];
859
+
860
+ if (element) {
861
+ if (isString(spec)) {
862
+ var name = replace(spec, /^[$@]/);
863
+ var s;
864
+ if (spec == '$')
865
+ s = element.className;
866
+ else if (spec == '$$') {
867
+ s = element.getAttribute('style');
868
+ }
869
+ // @condblock fadeslide
870
+ else if (/\$\$/.test(spec) && (element['style']['visibility'] == 'hidden' || element['style']['display'] == 'none')) {
871
+ s = 0;
872
+ }
873
+ else if (spec == '$$fade') {
874
+ s = isNaN(s =
875
+ extractNumber(element['style']['opacity'])
876
+ ) ? 1 : s;
877
+ }
878
+ else if (spec == '$$slide') {
879
+ s = self['get']('$height');
880
+ }
881
+ // @condend fadeslide
882
+ else if (/^\$/.test(spec)) {
883
+ s = _window.getComputedStyle(element, null).getPropertyValue(replace(name, /[A-Z]/g, function (match) { return '-' + match.toLowerCase(); }));
884
+ }
885
+ else if (/^@/.test(spec))
886
+ s = element.getAttribute(name);
887
+ else
888
+ s = element[name];
889
+ return toNumber ? extractNumber(s) : s;
890
+ }
891
+ else {
892
+ var r = {};
893
+ (isList(spec) ? each : eachObj)(spec, function(name) {
894
+ r[name] = self['get'](name, toNumber);
895
+ });
896
+ return r;
897
+ }
898
+ }
899
+ },
900
+
901
+ /*$
902
+ * @id set
903
+ * @group SELECTORS
904
+ * @requires dollar get
905
+ * @configurable default
906
+ * @name .set()
907
+ * @syntax set(name, value)
908
+ * @syntax set(properties)
909
+ * @syntax set(cssClasses)
910
+ * @module WEB
911
+ *
912
+ * Modifies the list's elements by setting their properties, attributes, CSS styles and/or CSS classes. You can either supply a
913
+ * 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.
914
+ * More complex operations can be accomplished by supplying a function as value. It will then be called for each element that will
915
+ * be set.
916
+ *
917
+ * The name given to <var>set()</var> defines what kind of data you are setting. The following name schemes are supported:
918
+ *
919
+ * <table>
920
+ * <tr><th>Name Schema</th><th>Example</th><th>Sets what?</th><th>Description</th></tr>
921
+ * <tr><td>name</td><td>innerHTML</td><td>Property</td><td>A name without prefix of '$' or '@' sets a property of the object.</td></tr>
922
+ * <tr><td>@name</td><td>@href</td><td>Attribute</td><td>Sets the HTML attribute using setAttribute(). In order to stay compatible with Internet Explorer 7 and earlier,
923
+ * you should not set the attributes '@class' and '@style'. Instead use '$' and '$$' as shown below.</td></tr>
924
+ * <tr><td>$name</td><td>$fontSize</td><td>CSS Property</td><td>Sets a style using the element's <var>style</var> object.</td></tr>
925
+ * <tr><td>$</td><td>$</td><td>CSS Classes</td><td>A simple <var>$</var> modifies the element's CSS classes using the object's <var>className</var> property. The value is a
926
+ * 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.
927
+ * The name '$' can also be omitted if <var>set</var> is called with class names as only argument.</td></tr>
928
+ * <tr><td>$$</td><td>$$</td><td>Style</td><td>Sets the element's style attribute in a browser-independent way.</td></tr>
929
+ * <tr><td>$$fade</td><td>$$fade</td><td>Fade Effect</td><td>The name '$$fade' sets the opacity of the element in a browser-independent way. The value must be a number
930
+ * between 0 and 1. '$$fade' will also automatically control the element's 'visibility' and 'display' styles. If the value is 0,
931
+ * the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to
932
+ * 'visible' and the display style to 'block'. '$$fade' only works with block elements.</td></tr>
933
+ * <tr><td>$$slide</td><td>$$slide</td><td>Slide Effect</td><td>The name '$$slide' allows a vertical slide-out or slide-in effect. The value must be a number
934
+ * between 0 and 1. '$$slide' will also automatically control the element's 'visibility' and 'display' styles. If the value is 0,
935
+ * the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to
936
+ * 'visible' and the display style to 'block'. '$$slide' only works with block elements.</td></tr>
937
+ * </table>
938
+ *
939
+ * @example Unchecking checkboxes:
940
+ * <pre>
941
+ * $('input.checkbox').set('checked', false);
942
+ * </pre>
943
+ *
944
+ * @example Changing the <var>innerHTML</var property of an element:
945
+ * <pre>
946
+ * $('#toc').set('innerHTML', 'Content');
947
+ * </pre>
948
+ *
949
+ * @example Changing attributes:
950
+ * <pre>
951
+ * $('a.someLinks').set('@href', 'http://www.example.com/');
952
+ * </pre>
953
+ *
954
+ * @example Removing attributes:
955
+ * <pre>
956
+ * $('a.someLinks').set('@title', null);
957
+ * </pre>
958
+ *
959
+ * @example Changing styles:
960
+ * <pre>
961
+ * $('.bigText').set('$font-size', 'x-large');
962
+ * </pre>
963
+ *
964
+ * @example Adding and removing CSS classes:
965
+ * <pre>
966
+ * $('.myElem').set('$', '+myClass -otherClass');
967
+ * </pre>
968
+ *
969
+ * @example Toggling a CSS class:
970
+ * <pre>
971
+ * $('.myElem').set('$', 'on');
972
+ * </pre>
973
+ *
974
+ * @example Shortcut for CSS manipulation:
975
+ * <pre>
976
+ * $('.myElem').set('+myClass -otherClass on');
977
+ * </pre>
978
+ *
979
+ * @example Making an element transparent:
980
+ * <pre>
981
+ * $('.seeThrough').set('$$fade', 0.5);
982
+ * </pre>
983
+ *
984
+ * @example Making an element visible. Note that $$fade will set the element's display style to 'block' and visibility style to 'visible'.
985
+ * <pre>
986
+ * $('.myElem').set('$$fade', 1);
987
+ * </pre>
988
+ *
989
+ * @example Using a map to change several properties:
990
+ * <pre>
991
+ * $('input.checkbox').set({checked: false,
992
+ * 'parentNode.@title': 'Check this'});
993
+ * </pre>
994
+ *
995
+ * @example Changing CSS with a map:
996
+ * <pre>
997
+ * $('.importantText').set({$fontSize: 'x-large',
998
+ * $color: 'black',
999
+ * $backgroundColor: 'red',
1000
+ * $: '+selected -default'});
1001
+ * </pre>
1002
+ *
1003
+ * @example You can specify a function as value to modify a value instead of just setting it:
1004
+ * <pre>
1005
+ * $('h2').set('innerHTML', function(oldValue, index) {
1006
+ * return 'Chapter ' + index + ': ' + oldValue.toUpperCase();
1007
+ * });
1008
+ * </pre>
1009
+ *
1010
+ * @param name the name of a single property or attribute to modify. If prefixed with '@', it is treated as a DOM element's attribute.
1011
+ * A dollar ('$') prefix is a shortcut for CSS styles. A simple dollar ('$') as name modifies CSS classes.
1012
+ * The special name '$$' allows you to set the <var>style</var> attribute in a browser independent way.
1013
+ * The special name '$$fade' and '$$slide' create fade and slide effects, and both expect a value between 0 and 1.
1014
+ *
1015
+ *
1016
+ * @param value the value to set. If value is null and name specified an attribute, the attribute will be removed.
1017
+ * If a dollar ('$') has been passed as name, the value can contain space-separated CSS class names. If prefixed with a '+' the class will be added,
1018
+ * with a '-' prefix the class will be removed. Without prefix, the class will be toggled.
1019
+ * If <var>value</var> is a function, the <code>function(oldValue, index, obj)</code> will be invoked for each list element
1020
+ * to evaluate the new value:
1021
+ * <dl><dt>oldValue</dt><dd>The old value of the property to be changed, as returned by ##get().
1022
+ * For the CSS style names, this is the computed style of the property </dd>
1023
+ * <dt>index</dt><dd>The list index of the object owning the property</dd>
1024
+ * <dt>obj</dt><dd>The list element owning the property.<dd>
1025
+ * <dt class="returnValue">(callback return value)</dt><dd>The value to be set.</dd></dl>
1026
+ * Functions are not supported by '$'.
1027
+ * @param properties a Object as map containing names as keys and the values to set as map values. See above for the name syntax.
1028
+ * @param cssClasses if <var>set()</var> is invoked with a string as single argument, the name "$" (CSS classes) is used and the argument is the
1029
+ * value. See above for CSS syntax.
1030
+ * Instead of a string, you can also specify a <code>function(oldValue, index, obj)</code> to modify the existing classes.
1031
+ * @return the list
1032
+ */
1033
+ 'set': function (name, value) {
1034
+ function setAttr(obj, n, v) {
1035
+ if (v != null)
1036
+ obj.setAttribute(n, v);
1037
+ else
1038
+ obj.removeAttribute(n);
1039
+ }
1040
+ var self = this, v;
1041
+ // @cond debug if (name == null) error("First argument must be set!");
1042
+ if (value !== undef) {
1043
+ // @cond debug if (!/string/i.test(typeof name)) error('If second argument is given, the first one must be a string specifying the property name");
1044
+
1045
+ // @condblock fadeslide
1046
+ if (name == '$$fade' || name == '$$slide') {
1047
+ self.set({'$visibility': (v = extractNumber(value)) > 0 ? 'visible' : 'hidden', '$display': 'block'})
1048
+ .set((name == '$$fade') ? (
1049
+ {'$opacity': v})
1050
+ :
1051
+ {'$height': /px$/.test(value) ? value : function(oldValue, idx, element) { return v * (v && getNaturalHeight($(element))) + 'px';},
1052
+ '$overflow': 'hidden'}
1053
+ );
1054
+ }
1055
+ else
1056
+ // @condend fadeslide
1057
+ each(self, function(obj, c) {
1058
+ var nameClean = replace(name, /^[@$]/);
1059
+ var className = obj['className'] || '';
1060
+ var newObj = /^\$/.test(name) ? obj.style : obj;
1061
+ var newValue = isFunction(value) ? value($(obj).get(name), c, obj) : value;
1062
+ if (name == '$') {
1063
+ if (newValue != null) {
1064
+ each(newValue.split(/\s+/), function(clzz) {
1065
+ var cName = replace(clzz, /^[+-]/);
1066
+ var oldClassName = className;
1067
+ className = replace(className, new RegExp(BACKSLASHB + cName + BACKSLASHB));
1068
+ if (/^\+/.test(clzz) || (cName==clzz && oldClassName == className)) // for + and toggle-add
1069
+ className += ' ' + cName;
1070
+ });
1071
+ obj['className'] = replace(className, /^\s+|\s+(?=\s|$)/g);
1072
+ }
1073
+ }
1074
+ else if (name == '$$') {
1075
+ setAttr(obj, 'style', newValue);
1076
+ }
1077
+ else if (!/^@/.test(name))
1078
+ newObj[nameClean] = newValue;
1079
+ else
1080
+ setAttr(newObj, nameClean, newValue);
1081
+ });
1082
+ }
1083
+ else if (isString(name) || isFunction(name))
1084
+ self.set('$', name);
1085
+ else
1086
+ eachObj(name, function(n,v) { self.set(n, v); });
1087
+ return self;
1088
+ },
1089
+
1090
+ /*$
1091
+ * @id add
1092
+ * @group ELEMENT
1093
+ * @requires dollar
1094
+ * @configurable default
1095
+ * @name .add()
1096
+ * @syntax add(text)
1097
+ * @syntax add(factoryFunction)
1098
+ * @syntax add(list)
1099
+ * @syntax add(node)
1100
+ * @module WEB
1101
+ * Adds the given node(s) as content to the list's HTML elements. If a string has been given, it will be added as text node.
1102
+ * If you pass a function, it will be invoked for each list element to create the node to add. This is called a factory function. It can return all
1103
+ * values allowed by <var>add()</var>, including another function to be called.
1104
+ * If you pass a list or a function returning a list, all its elements will be added using the rules above.
1105
+ *
1106
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1107
+ * does not allow adding it more than once. You should use a factory function to add DOM elements to more than one list element. ##EE()
1108
+ * and ##clone() are two simple ways to create factory functions.
1109
+ *
1110
+ * @example Using the following HTML:
1111
+ * <pre>
1112
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;/div>
1113
+ * </pre>
1114
+ * The next line appends a text node to the given 'comment' div:
1115
+ * <pre>
1116
+ * $('#comments').add('Some additional text.');
1117
+ * </pre>
1118
+ * This results in:
1119
+ * <pre>
1120
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;Some additional text./div>
1121
+ * </pre>
1122
+ *
1123
+ * @example Using the following HTML:
1124
+ * <pre>
1125
+ * &lt;ul id="myList">
1126
+ * &lt;li>First list entry&lt;/li>
1127
+ * &lt;li>Second list entry&lt;/li>
1128
+ * &lt;/ul>
1129
+ * </pre>
1130
+ * The following Javascript adds an element to the list:
1131
+ * <pre>
1132
+ * $('#myList').add(EE('li', 'My extra point');
1133
+ * </pre>
1134
+ * This results in
1135
+ * <pre>
1136
+ * &lt;ul id="myList">
1137
+ * &lt;li>First list entry&lt;/li>
1138
+ * &lt;li>Second list entry&lt;/li>
1139
+ * &lt;li>My extra point&lt;/li>
1140
+ * &lt;/ul>
1141
+ * </pre>
1142
+ *
1143
+ * @example Use a list to add several elements at once:
1144
+ * <pre>
1145
+ * $('#comments').add([
1146
+ * EE('br'),
1147
+ * 'Some text',
1148
+ * EE('span', {'className': 'highlight'}, 'Some highlighted text')
1149
+ * ]);
1150
+ * </pre>
1151
+ *
1152
+ * @example You can implement functions to create elements depending on the context:
1153
+ * <pre>
1154
+ * $('.chapter').add(function(parent, index) { return EE('h2', 'Chapter number ' + index); });
1155
+ * </pre>
1156
+ *
1157
+ * @param text a string or number to add as text node
1158
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1159
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1160
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1161
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1162
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1163
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1164
+ * @param list a list containing text, functions, nodes or more lists. Please note that if you have DOM nodes in this list
1165
+ * and attempt to add them to more than one element, the result is undefined. You should always use factories
1166
+ * if you add DOM nodes to more than one element.
1167
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1168
+ * @return the current list
1169
+ */
1170
+ 'add': function (children, addFunction) {
1171
+ return each(this, function(e, index) {
1172
+ var lastAdded;
1173
+ (function appendChildren(c) {
1174
+ if (isList(c))
1175
+ each(c, appendChildren);
1176
+ else if (isFunction(c))
1177
+ appendChildren(c(e, index));
1178
+ else if (c != null) { // must check null, as 0 is a valid parameter
1179
+ var n = isNode(c) ? c : _document.createTextNode(c);
1180
+ if (lastAdded)
1181
+ lastAdded.parentNode.insertBefore(n, lastAdded.nextSibling);
1182
+ else if (addFunction)
1183
+ addFunction(n, e, e.parentNode);
1184
+ else
1185
+ e.appendChild(n);
1186
+ lastAdded = n;
1187
+ }
1188
+ })(isNode(children) && index ? null : children);
1189
+ });
1190
+ },
1191
+
1192
+ /*$
1193
+ * @id fill
1194
+ * @group ELEMENT
1195
+ * @requires dollar add remove
1196
+ * @configurable default
1197
+ * @name .fill()
1198
+ * @syntax fill()
1199
+ * @syntax fill(text)
1200
+ * @syntax fill(factoryFunction)
1201
+ * @syntax fill(list)
1202
+ * @syntax fill(node)
1203
+ * @module WEB
1204
+ * Sets the content of the list's HTML elements, replacing old content. If a string has been given, it will be added as text node.
1205
+ * If you pass a function, it will be invoked for each list member to create a node. The function prototype is <code>function(parent, index)</code>.
1206
+ * It can return all values allowed by <var>fill()</var>, including another function to be called.
1207
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1208
+ *
1209
+ * It is also possible to pass a DOM node, but it will be set <strong>only in the first element of the list</strong>, because DOM
1210
+ * does not allow adding it more than once.
1211
+ *
1212
+ * Call <var>fill()</var> without arguments to remove all children from a node.
1213
+ *
1214
+ * @example Using the following HTML:
1215
+ * <pre>
1216
+ * &lt;div id="status">Done&lt;/div>
1217
+ * </pre>
1218
+ * <var>fill()</var> with a simple string replaces the element's content with the text:
1219
+ * <pre>
1220
+ * $('#status').fill('Please Wait..');
1221
+ * </pre>
1222
+ * Results in:
1223
+ * <pre>
1224
+ * &lt;div id="status">Please Wait..&lt;/div>
1225
+ * </pre>
1226
+ *
1227
+ * @example Pass an Element Factory to replace the old content with that:
1228
+ * <pre>
1229
+ * $('#status').fill(EE('span', {'className': 'bold'}, 'Please Wait...'));
1230
+ * </pre>
1231
+ * With the previous example's HTML, this would create this:
1232
+ * <pre>
1233
+ * &lt;div id="status">&lt;span class='bold'>Please Wait..&lt;/span>&lt;/div>
1234
+ * </pre>
1235
+ *
1236
+ * @example You can also pass a list of elements and texts:
1237
+ * <pre>
1238
+ * $('#status').fill(['Here', EE('br'), 'are', EE('br'), 'four', EE('br'), 'lines.]);
1239
+ * </pre>
1240
+ *
1241
+ * @example Or a complete structure built using EE:
1242
+ * <pre>
1243
+ * $('#myListContainer').fill([
1244
+ * EE('h2', 'My List'),
1245
+ * EE('ol', [EE('li', 'First Item'), EE('li', 'Second Item'), EE('li', 'Third Item')])
1246
+ * ]);
1247
+ * </pre>
1248
+ *
1249
+ * @example You can write a factory function that re-creates the list for every instance:
1250
+ * <pre>
1251
+ * $('.listContainers').fill(function(e, index) { return [
1252
+ * EE('h2', 'List Number '+index),
1253
+ * EE('ol', [EE('li', 'First Item'),
1254
+ * EE('li', 'Second Item'),
1255
+ * EE('li', 'Third Item')
1256
+ * ])]});
1257
+ * </pre>
1258
+ *
1259
+ * @example <var>fill()</var> without arguments deletes the content of the list elements:
1260
+ * <pre>
1261
+ * $('.listContainers').fill();
1262
+ * </pre>
1263
+ *
1264
+ * @param text a string to set as text node of the list elements
1265
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1266
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1267
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1268
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1269
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1270
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1271
+
1272
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1273
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1274
+ * Minified list contains more than one item.
1275
+ * @param node a DOM node to set <strong>only in the first element</strong> of the list.
1276
+
1277
+ * @return the current list
1278
+ */
1279
+ 'fill': function (children) {
1280
+ return each(this, function(e) { $(e.childNodes)['remove'](); }).add(children);
1281
+ },
1282
+
1283
+ /*$
1284
+ * @id addbefore
1285
+ * @group ELEMENT
1286
+ * @requires dollar add
1287
+ * @configurable default
1288
+ * @name .addBefore()
1289
+ * @syntax addBefore(text)
1290
+ * @syntax addBefore(factoryFunction)
1291
+ * @syntax addBefore(list)
1292
+ * @syntax addBefore(node)
1293
+ * @module WEB
1294
+ * Inserts the given text or element(s) as sibling in front of each HTML element in the list.
1295
+ * If a string has been given, it will be added as text node.
1296
+ * If you pass a function, it will be invoked for each list element to create the new node, with the arguments <code>function(parent, index)</code>.
1297
+ * It can return all values allowed by <var>addBefore()</var>, including another function to be called.
1298
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1299
+ *
1300
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1301
+ * does not allow adding it more than once.
1302
+ *
1303
+ * @example Using the following HTML:
1304
+ * <pre>
1305
+ * &lt;div>
1306
+ * <div id="mainText">Here is some text</div>
1307
+ * &lt;/div>
1308
+ * </pre>
1309
+ * addBefore() adds text in front of the selected list items.
1310
+ * <pre>
1311
+ * $('#mainText').addBefore('COMMENT');
1312
+ * </pre>
1313
+ * This results in:
1314
+ * <pre>
1315
+ * &lt;div>
1316
+ * COMMENT
1317
+ * &lt;div id="mainText">Here is some text&lt;/div>
1318
+ * &lt;/div>
1319
+ * </pre>
1320
+ *
1321
+ * @example You can also pass an Element Factory:
1322
+ * <pre>
1323
+ * $('#mainText').addBefore(EE('span', {'className': 'important'}, 'WARNING'));
1324
+ * </pre>
1325
+ * With the previous example's HTML, this would create this HTML:
1326
+ * <pre>
1327
+ * &lt;div>
1328
+ * &lt;span class="important">WARNING&lt;/span>
1329
+ * &lt;div id="mainText">Here is some text&lt;/div>
1330
+ * &lt;/div>
1331
+ * </pre>
1332
+ *
1333
+ * @example Lists of elements and nodes are possible as well.
1334
+ * <pre>
1335
+ * $('#status').addBefore([EE('hr'), 'WARNING']);
1336
+ * </pre>
1337
+ *
1338
+ * @param text a string to add as text node of the list elements
1339
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1340
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1341
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1342
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1343
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1344
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1345
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1346
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1347
+ * Minified list contains more than one item.
1348
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1349
+ * @return the current list
1350
+ */
1351
+ 'addBefore': function (children) {
1352
+ return this.add(children, function(newNode, refNode, parent) { parent.insertBefore(newNode, refNode); });
1353
+ },
1354
+
1355
+ /*$
1356
+ * @id addafter
1357
+ * @group ELEMENT
1358
+ * @requires dollar add
1359
+ * @configurable default
1360
+ * @name .addAfter()
1361
+ * @syntax addAfter(text)
1362
+ * @syntax addAfter(factoryFunction)
1363
+ * @syntax addAfter(list)
1364
+ * @syntax addAfter(node)
1365
+ * @module WEB
1366
+ * Inserts the given text or element(s) as sibling after each HTML element in the list.
1367
+ * If a string has been given, it will be added as text node.
1368
+ * If you pass a function, it will be invoked for each list element to create the node(s) to add. It can return all values
1369
+ * allowed by <var>addAfter()</var>, including another function to be called.
1370
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1371
+ *
1372
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1373
+ * does not allow adding it more than once.
1374
+ *
1375
+ * @example Using the following HTML:
1376
+ * <pre>
1377
+ * &lt;div>
1378
+ * &lt;div id="mainText">Here is some text&lt;/div>
1379
+ * &lt;/div>
1380
+ * </pre>
1381
+ * Use addAfter() with a simple string to add a text node.
1382
+ * <pre>
1383
+ * $('#mainText').addAfter('Disclaimer: bla bla bla');
1384
+ * </pre>
1385
+ * This results in the following HTML:
1386
+ * <pre>
1387
+ * &lt;div>
1388
+ * &lt;div id="mainText">Here is some text&lt;/div>
1389
+ * Disclaimer: bla bla bla
1390
+ * &lt;/div>
1391
+ * </pre>
1392
+ *
1393
+ * @example You can also pass an Element Factory:
1394
+ * <pre>
1395
+ * $('#mainText').addAfter(EE('span', {'className': 'disclaimer'}, 'Disclaimer: bla bla bla'));
1396
+ * </pre>
1397
+ * With the previous example's HTML, this would create this:
1398
+ * <pre>
1399
+ * &lt;div>
1400
+ * &lt;div id="mainText">Disclaimer: bla bla bla&lt;/div>
1401
+ * &lt;span class="disclaimer">WARNING&lt;/span>
1402
+ * &lt;/div>
1403
+ * </pre>
1404
+ *
1405
+ * @param text a string to add as text node of the list elements
1406
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1407
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1408
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1409
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1410
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1411
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1412
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1413
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1414
+ * Minified list contains more than one item.
1415
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1416
+ * @return the current list
1417
+ */
1418
+ 'addAfter': function (children) {
1419
+ return this.add(children, function(newNode, refNode, parent) { parent.insertBefore(newNode, refNode.nextSibling); });
1420
+ },
1421
+
1422
+ /*$
1423
+ * @id addfront
1424
+ * @group ELEMENT
1425
+ * @requires dollar add
1426
+ * @configurable default
1427
+ * @name .addFront()
1428
+ * @syntax addFront(text)
1429
+ * @syntax addFront(factoryFunction)
1430
+ * @syntax addFront(list)
1431
+ * @syntax addFront(node)
1432
+ * @module WEB
1433
+ * Adds the given node(s) as children to the list's HTML elements. Unlike ##add(), the new nodes will be the first children and not the last.
1434
+ * If a string has been given, it will be added as text node.
1435
+ * If you pass a function, it will be invoked for each list element to create node(s) with the arguments <code>function(parent, index)</code>.
1436
+ * It can return all values allowed by <var>addFront()</var>, including another function to be called.
1437
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1438
+ *
1439
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1440
+ * does not allow adding it more than once.
1441
+ *
1442
+ * @example Using the following HTML:
1443
+ * <pre>
1444
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;/div>
1445
+ * </pre>
1446
+ * Add a text to the given 'comment' div:
1447
+ * <pre>
1448
+ * $('#comments').addFront('Some additional text. ');
1449
+ * </pre>
1450
+ * This results in:
1451
+ * <pre>
1452
+ * &lt;div id="comments">Some additional text. Here is some text.&lt;br/>&lt;/div>
1453
+ * </pre>
1454
+ *
1455
+ * @example Using the following HTML:
1456
+ * <pre>
1457
+ * &lt;ul id="myList">
1458
+ * &lt;li>First list entry&lt;/li>
1459
+ * &lt;li>Second list entry&lt;/li>
1460
+ * &lt;/ul>
1461
+ * </pre>
1462
+ * The following Javascript adds an element to the list:
1463
+ * <pre>
1464
+ * $('#myList').addFront(EE('li', 'My extra point'));
1465
+ * </pre>
1466
+ * This results in
1467
+ * <pre>
1468
+ * &lt;ul id="myList">
1469
+ * &lt;li>My extra point&lt;/li>
1470
+ * &lt;li>First list entry&lt;/li>
1471
+ * &lt;li>Second list entry&lt;/li>
1472
+ * &lt;/ul>
1473
+ * </pre>
1474
+ *
1475
+ * @example Use a list to add several elements at once:
1476
+ * <pre>
1477
+ * $('#comments').addFront([
1478
+ * EE('br'),
1479
+ * 'Some text',
1480
+ * EE('span', {'className': 'highlight'}, 'Some highlighted text')
1481
+ * ]);
1482
+ * </pre>
1483
+ *
1484
+ * @param text a string to add as text node of the list elements
1485
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1486
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1487
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1488
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1489
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1490
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1491
+
1492
+ * @param list a list containing text, functions, nodes or nested lists containing those items. Please note that if you have DOM nodes in this list
1493
+ * and attempt to add them to more than one element, the result is undefined.
1494
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1495
+ * @return the current list
1496
+ */
1497
+ 'addFront': function (children) {
1498
+ return this.add(children, function(newNode, refNode) { refNode.insertBefore(newNode, refNode.firstChild); });
1499
+ },
1500
+
1501
+ /*$
1502
+ * @id replace
1503
+ * @group ELEMENT
1504
+ * @requires dollar add
1505
+ * @configurable default
1506
+ * @name .replace()
1507
+ * @syntax replace(text)
1508
+ * @syntax replace(factoryFunction)
1509
+ * @syntax replace(list)
1510
+ * @syntax replace(node)
1511
+ * @module WEB
1512
+ * Replaces the list items with the the given node(s) in the DOM tree.
1513
+ * If a string has been given, it will be set as text node.
1514
+ * If you pass a function, it will be invoked for each list element to create node(s) with the arguments <code>function(parent, index)</code>.
1515
+ * It can return all values allowed by <var>replace()</var>, including another function to be called.
1516
+ * If you pass a list or a function returns a list, all its elements will be set using the rules above.
1517
+ *
1518
+ * It is also possible to pass a DOM node, but it will replace <strong>only the first element of the list</strong>, because DOM
1519
+ * does not allow adding it more than once.
1520
+ *
1521
+ * @example Using the following HTML:
1522
+ * <pre>
1523
+ * &lt;div id="comments">
1524
+ * &lt;div id="commentOne">My old comment.&lt;/div>
1525
+ * &lt;/div>
1526
+ * </pre>
1527
+ * This replaces the div 'commentOne':
1528
+ * <pre>
1529
+ * $('#commentOne').replace('Some new comment.');
1530
+ * </pre>
1531
+ * The resulting HTML is:
1532
+ * <pre>
1533
+ * &lt;div id="comments">
1534
+ * Some new comment.
1535
+ * &lt;/div>
1536
+ * </pre>
1537
+ * Please note that not only the text has changed, but the whole &lt;div> has been replaced. If you only want to replace the element's text content
1538
+ * you should use ##fill() instead of <var>replace()</var>.
1539
+ *
1540
+ * @example Using the following HTML:
1541
+ * <pre>
1542
+ * &lt;ul id="myList">
1543
+ * &lt;li>First list entry&lt;/li>
1544
+ * &lt;li>Second list entry&lt;/li>
1545
+ * &lt;/ul>
1546
+ * </pre>
1547
+ * The following example will replace <strong>only the first &lt;li> element</strong>:
1548
+ * <pre>
1549
+ * $('#myList li').sub(0, 1).replace(EE('li', 'My extra point'));
1550
+ * </pre>
1551
+ * This results in
1552
+ * <pre>
1553
+ * &lt;ul id="myList">
1554
+ * &lt;li>My extra point&lt;/li>
1555
+ * &lt;li>Second list entry&lt;/li>
1556
+ * &lt;/ul>
1557
+ * </pre>
1558
+ *
1559
+ *
1560
+ * @param text a text for the text nodes that replace the list elements
1561
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to determine its content:
1562
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1563
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1564
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1565
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1566
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1567
+ * @param node content to replace <strong>only to the first element</strong> of the list with. The content can be a string for a text node,
1568
+ * an HTML node or a list containing strings and/or HTML node.
1569
+ * @return the current list
1570
+ */
1571
+ 'replace': function (children) {
1572
+ return this.add(children, function(newNode, refNode, parent) { parent.replaceChild(newNode, refNode); });
1573
+ },
1574
+
1575
+ /*$
1576
+ * @id clone
1577
+ * @group ELEMENT
1578
+ * @requires dollar ee
1579
+ * @configurable default
1580
+ * @name .clone()
1581
+ * @syntax clone()
1582
+ * @syntax clone(onCreate)
1583
+ * @module WEB
1584
+ * Creates a ##list#Minified list## of strings and Element Factories that return clones of the list's HTML elements. An Element Factory is a function
1585
+ * that creates a Minified list of fresh DOM nodes. You can pass the list to ##add(), ##fill() or similar functions to re-create the cloned nodes.
1586
+ *
1587
+ * <var>clone()</var> is very limited in what it will clone. Only elements, their attributes, text nodes and CDATA will be cloned.
1588
+ * Modifications of the elements, such as event handlers, will not be cloned.
1589
+ *
1590
+ * Please note that id attributes will be automatically skipped by the Element Factory. This allows you to address the element to clone by id
1591
+ * without having to worry about duplicate ids in the result.
1592
+ *
1593
+ * @example Using the following HTML:
1594
+ * <pre>
1595
+ * &lt;div id="comments">
1596
+ * &lt;div id="comment1">My comment.&lt;/div>
1597
+ * &lt;/div>
1598
+ * </pre>
1599
+ * Creating a clone factory:
1600
+ * <pre>
1601
+ * var myCloneFactory = $('#comment1').clone();
1602
+ * </pre>
1603
+ * Creating a clone and adding it below the existing one:
1604
+ * <pre>
1605
+ * $('#comments').add(myCloneFactory);
1606
+ * </pre>
1607
+ *
1608
+ * @example Creating an event handler for a clone:
1609
+ * <pre>
1610
+ * var buttonCloner = $('#myButton').clone(function(newButton) {
1611
+ * newButton.on('click', function() { alert('Cloned button clicked'); });
1612
+ * });
1613
+ * $('#buttonContainer').add(buttonCloner);
1614
+ * </pre>
1615
+ *
1616
+ * @param onCreate optional A <code>function(elementList)</code> that will be called for each top-level element created by the Element
1617
+ * Factory:
1618
+ * <dl><dt>elementList</dt><dd>The newly created element wrapped in a Minified list. </dd></dl>
1619
+ * The function's return value will be ignored.
1620
+ * The callback allows you, for example, to add event handlers to the element using ##on().
1621
+ * Please note that the callback will be not be called for cloned text nodes. If you clone
1622
+ * more than one element, <var>onCreate</var> will be invoked for each element.
1623
+ * @return the list of Element Factory functions and strings to create clones
1624
+ */
1625
+ 'clone': function (onCreate) {
1626
+ return new M(collect(this, function(e) {
1627
+ var nodeType = isNode(e);
1628
+ if (nodeType == 1) {
1629
+ var attrs = {
1630
+ };
1631
+ each(e['attributes'], function(a) {
1632
+ var attrName = a['name'];
1633
+ if (attrName != 'id'
1634
+ ) {
1635
+ attrs['@'+attrName] = a['value'];
1636
+ }
1637
+ });
1638
+ return EE(e['tagName'], attrs, $(e['childNodes'])['clone'](), onCreate);
1639
+ }
1640
+ else if (nodeType < 5) // 2 is impossible (attribute), so only 3 (text) and 4 (cdata)..
1641
+ return e['data'];
1642
+ else
1643
+ return null;
1644
+ }));
1645
+ },
1646
+
1647
+ /*$
1648
+ * @id animate
1649
+ * @group ANIMATION
1650
+ * @requires loop dollar set get
1651
+ * @configurable default
1652
+ * @name .animate()
1653
+ * @syntax animate(properties)
1654
+ * @syntax animate(properties, durationMs)
1655
+ * @syntax animate(properties, durationMs, linearity)
1656
+ * @syntax animate(properties, durationMs, interpolationFunc)
1657
+ * @syntax animate(properties, durationMs, linearity, state)
1658
+ * @syntax animate(properties, durationMs, interpolationFunc, state)
1659
+ * @module WEB
1660
+ * Animates the items of the list by modifying their properties, CSS styles and attributes. <var>animate()</var> can work with numbers, strings that contain exactly one
1661
+ * number, and with colors in the CSS notations 'rgb(r,g,b)', '#rrggbb' or '#rgb'.
1662
+ *
1663
+ * When you invoke the function, it will first read all old values from the object and extract their numbers and colors. These start values will be compared to
1664
+ * the destination values that have been specified in the given properties. Then <var>animate()</var> will create a background task using ##$.loop() that updates the
1665
+ * specified properties in frequent intervals so that they transition to their destination values.
1666
+ *
1667
+ * The start values will be obtained using ##get(). It is recommended to set the start values using ##set() before you start the animation, even if this is not
1668
+ * always required.
1669
+ *
1670
+ * You can define the kind of transition using the <var>linearity</var> parameter. If you omit it or pass 0, animate's default algorithm will cause a smooth transition
1671
+ * from the start value to the end value. If you pass 1, the transition will be linear, with a sudden start and end of the animation. Any value between 0 and 1
1672
+ * is also allowed and will give you a transition that is 'somewhat smooth'.
1673
+ *
1674
+ * Instead of the <var>linearity</var> function you can also provide your own interpolation <code>function(startValue, endValue, t)</code> which will be
1675
+ * called every time an interpolated value is required. <var>startValue</var> and <var>endValue</var> define the start and end values. <var>t</var>
1676
+ * is a value between 0 and 1 that specifies the state of the transition. The function should return <var>startValue</var> for 0 and
1677
+ * <var>endValue</var> for 1. For values between 0 and 1, the function should return a transitional value.
1678
+ *
1679
+ * If the start value of a property is a string containing a number, <var>animate()</var> will always ignore all the surrounding text and use the destination value as a template
1680
+ * for the value to write. This can cause problems if you mix units in CSS. For example, if the start value is '10%' and you specify an end value of '20px', animate
1681
+ * will do an animation from '10px' to '20px'. It is not able to convert units.
1682
+ *
1683
+ * <var>animate()</var> does not only support strings with units, but any string containing exactly one number. This allows you, among other things, with IE-specific CSS properties.
1684
+ * For example, you can transition from a start value 'alpha(opacity = 0)' to 'alpha(opacity = 100)'.
1685
+ *
1686
+ * When you animate colors, <var>animate()</var> is able to convert between the three notations rgb(r,g,b), #rrggbb or #rgb. You can use them interchangeably, but you can not
1687
+ * use color names such as 'red'.
1688
+ *
1689
+ * You can prefix any number, including numbers with units, with "-=" or "+=" in order to specify a value relative to the starting value. The new value will be added
1690
+ * to or substracted from the start value to determine the end value.
1691
+ *
1692
+ * To allow more complex animation, <var>animate()</var> returns a ##promise#Promise## that is fulfulled when the animation has finished.
1693
+ *
1694
+ * @example Move an element.
1695
+ * <pre>
1696
+ * $('#myMovingDiv').set({$left: '0px', $top: '0px'}) // start values
1697
+ * .animate({$left: '50px', $top: '100px'}, 1000); // animation
1698
+ * </pre>
1699
+ *
1700
+ * @example Using relative values for animation:
1701
+ * <pre>
1702
+ * $('#myMovingDiv').set({$left: '100px', $top: '100px'}) // start values
1703
+ * .animate({$left: '-=50px', $top: '+=100px'}, 1000); // animation
1704
+ * </pre>
1705
+ *
1706
+ * @example Change the color of an element:
1707
+ * <pre>
1708
+ * $('#myBlushingDiv').set({$backgroundColor: '#000000'})
1709
+ * .animate({$backgroundColor: '#ff0000'}, 1000);
1710
+ * </pre>
1711
+ *
1712
+ * @example Fade-out effect:
1713
+ * <pre>
1714
+ * $('#myFadingDiv').animate({$$fade: 0}, 1000);
1715
+ * </pre>
1716
+ *
1717
+ * @example Slide-in effect:
1718
+ * <pre>
1719
+ * $('#myInvisibleDiv').animate({$$slide: 1}, 1000);
1720
+ * </pre>
1721
+ *
1722
+ * @example Chained animation using ##promise#Promise## callbacks. The element is first moved to the position 200/0, then to 200/200
1723
+ * and finally moves to 100/100.
1724
+ * <pre>
1725
+ * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
1726
+ * div.animate({$left: '200px', $top: '0px'}, 600, 0)
1727
+ * .then(function() {
1728
+ * return div.animate({$left: '200px', $top: '200px'}, 800, 0);
1729
+ * }).then(function() {
1730
+ * return div.animate({$left: '100px', $top: '100px'}, 400);
1731
+ * });
1732
+ * });
1733
+ * </pre>
1734
+ * </pre>
1735
+ *
1736
+ *
1737
+ * @param properties a property map describing the end values of the corresponding properties. The names can use the
1738
+ * set() syntax ('@' prefix for attributes, '$' for styles, '$$fade' for fading and '$$slide' for slide effects).
1739
+ * Values must be either numbers, numbers with units (e.g. "2 px") or colors ('rgb(r,g,b)', '#rrggbb' or '#rgb').
1740
+ * Number values, including those with units, can be prefixed with "+=" or "-=", meaning that the value is relative
1741
+ * to the original value and should be added or subtracted.
1742
+ * @param durationMs optional the duration of the animation in milliseconds. Default: 500ms.
1743
+ * @param linearity optional defines whether the animation should be linear (1), very smooth (0) or something in between. Default: 0.
1744
+ * @param interpolationFunc optional an interpolation <code>function(startValue, endValue, t)</code> which will be
1745
+ * called every time an interpolated value is required:
1746
+ * <dl>
1747
+ * <dt>startValue</dt><dd>The start value of the transition.</dd>
1748
+ * <dt>endValue</dt><dd>The end value of the transition.</dd>
1749
+ * <dt>t</dt><dd>A value between 0 and 1 that specifies the state of the transition.</dd>
1750
+ * <dt class="returnValue">(callback return value)</dt><dd>The value at the time <var>t</var>.</dd>
1751
+ * </dl>
1752
+ * @param state optional if set, the animation controller will write information about its state in this object. When <var>animate()</var> returns,
1753
+ * there will be a <var>stop()</var> function in the property <var>state.stop</var> that can be used to abort the animation.
1754
+ * The property <var>state.time</var> will be continously updated while the animation is running
1755
+ * and contains the number of milliseconds that have passed from the start, allowing you to track the progress of the animation.
1756
+ * If the animation finished, controller writes null into <var>state.time</var>. <var>state.stop</var> will not be
1757
+ * modified and can still be safely invoked even when the animation ended.
1758
+ * @return a ##promise#Promise## object to monitor the animation's progress.
1759
+ * It is fulfilled when the animation ended, and rejected if the animation had been stopped.
1760
+ * The fulfillment handler will be called as <code>function(list)</code>:
1761
+ * <dl><dt>list</dt><dd>A reference to the animated list.</dd></dl>
1762
+ * The rejection handler is called as <code>function()</code> without arguments.
1763
+ */
1764
+ 'animate': function (properties, durationMs, linearity, state) {
1765
+ // @cond debug if (!properties || typeof properties == 'string') error('First parameter must be a map of properties (e.g. "{top: 0, left: 0}") ');
1766
+ // @cond debug if (linearity && !isFunction(linearity) && (linearity < 0 || linearity > 1)) error('Third parameter must be at least 0 and not larger than 1.');
1767
+ // @cond debug var colorRegexp = /^(rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)|#\w{3}|#\w{6})\s*$/i;
1768
+ var self = this;
1769
+ var initState = []; // for each item contains a map {s:{}, e:{}, o} s/e are property name -> startValue of start/end. The item is in o.
1770
+ var numRegExp = /-?[\d.]+/;
1771
+ var loopStop;
1772
+ var prom = promise();
1773
+ var interpolate = isFunction(linearity) ? linearity : function(startValue, endValue, t) {
1774
+ return startValue + t * (endValue - startValue) * (linearity + (1-linearity) * t * (3 - 2*t));
1775
+ };
1776
+ state = state || {};
1777
+ state['time'] = 0;
1778
+ state['stop'] = function() { loopStop(); prom(false); };
1779
+ durationMs = durationMs || 500;
1780
+ linearity = linearity || 0;
1781
+
1782
+ // find start values
1783
+ each(self, function(li) {
1784
+ var p = {o:$(li), e:{}};
1785
+ eachObj(p.s = p.o.get(properties), function(name, start) {
1786
+ var dest = properties[name];
1787
+ if (name == '$$slide')
1788
+ dest = dest*getNaturalHeight(p.o) + 'px';
1789
+ p.e[name] = /^[+-]=/.test(dest) ?
1790
+ replace(dest.substr(2), numRegExp, extractNumber(start) + extractNumber(replace(dest, /\+?=/)))
1791
+ : dest;
1792
+ });
1793
+ initState.push(p);
1794
+ });
1795
+
1796
+ // start animation
1797
+ loopStop = $.loop(function(timePassedMs) {
1798
+ function getColorComponent(colorCode, index) {
1799
+ return (/^#/.test(colorCode)) ?
1800
+ parseInt(colorCode.length > 6 ? colorCode.substr(1+index*2, 2) : ((colorCode=colorCode.charAt(1+index))+colorCode), 16)
1801
+ :
1802
+ parseInt(replace(colorCode, /[^\d,]+/g).split(',')[index]);
1803
+ }
1804
+
1805
+ state['time'] = timePassedMs;
1806
+ if (timePassedMs >= durationMs || timePassedMs < 0) {
1807
+ each(initState, function(isi) { // set destination values
1808
+ isi.o.set(isi.e);
1809
+ });
1810
+ loopStop();
1811
+ state['time'] = null;
1812
+ prom(true, [self]);
1813
+ }
1814
+ else
1815
+ each(initState, function(isi) {
1816
+ eachObj(isi.s, function(name, start) {
1817
+ var newValue = 'rgb(', end=isi.e[name];
1818
+ var t = timePassedMs/durationMs;
1819
+ if (/^#|rgb\(/.test(end)) { // color in format '#rgb' or '#rrggbb' or 'rgb(r,g,b)'?
1820
+ for (var i = 0; i < 3; i++)
1821
+ newValue += Math.round(interpolate(getColorComponent(start, i), getColorComponent(end, i), t)) + (i < 2 ? ',' : ')');
1822
+ }
1823
+ else
1824
+ newValue = replace(end, numRegExp, toString(interpolate(extractNumber(start), extractNumber(end), t)));
1825
+ isi.o.set(name, newValue);
1826
+ });
1827
+ });
1828
+ });
1829
+ return prom;
1830
+ },
1831
+
1832
+ /*$
1833
+ * @id toggle
1834
+ * @group ANIMATION
1835
+ * @requires animate set
1836
+ * @configurable default
1837
+ * @name .toggle()
1838
+ * @syntax toggle(cssClasses)
1839
+ * @syntax toggle(state1, state2)
1840
+ * @syntax toggle(state1, state2, durationMs)
1841
+ * @syntax toggle(state1, state2, durationMs, linearity)
1842
+ * @syntax toggle(state1, state2, durationMs, interpolationFunction)
1843
+ * @module WEB
1844
+ *
1845
+ * Creates a function that switches between the two given states for the list. The states use the ##set() property syntax. You can also
1846
+ * just pass a string of CSS classes, as you do with <var>set()</var>.
1847
+ *
1848
+ * If no duration is given, the returned function changes the state immediately using ##set(). If a duration has been passed, the returned function
1849
+ * uses ##animate() to smoothly transition the state. If the returned function is invoked while an animation is running, it interrupts the
1850
+ * animation and returns to the other state.
1851
+ *
1852
+ * @example Creates a toggle function that changes the background color of the page.
1853
+ * <pre>
1854
+ * var light = $('body').set({$backgroundColor: #000}, {$backgroundColor: #fff});
1855
+ * light(); // toggles state to second state
1856
+ * light(false); // sets first state (background color to #000).
1857
+ * light(true); // sets second state (background color to #fff).
1858
+ * light(); // toggles state to first state
1859
+ * </pre>
1860
+ *
1861
+ * @example Takes the previous function, but adds it as an onclick event handler that toggles the color.
1862
+ * <pre>
1863
+ * var light = $('body').toggle({$backgroundColor: #000}, {$backgroundColor: #fff});
1864
+ * $('#mySwitch').on('click', light);
1865
+ * </pre>
1866
+ *
1867
+ * @example Using an animated transition by passing a duration:
1868
+ * <pre>
1869
+ * var dimmer = $('body').toggle({$backgroundColor: #000}, {$backgroundColor: #fff}, 500);
1870
+ * $('#mySwitch').on('click', dimmer);
1871
+ * </pre>
1872
+ *
1873
+ * @example Toggling CSS classes using the full syntax:
1874
+ * <pre>
1875
+ * var t = $('#myElement').toggle({$: '-myClass1 -myClass2'}, {$: '+myClass1 +myClass2'});
1876
+ * $('#myController').on('click', t);
1877
+ * </pre>
1878
+ *
1879
+ * @example There is a shortcut for toggling CSS classes. Just list them space-separated in a string:
1880
+ * <pre>
1881
+ * var t = $('#myElement').toggle('myClass1 myClass2');
1882
+ * </pre>
1883
+ *
1884
+ * @param cssClasses a string containing space-separated CSS class names to toggle. Classes are disabled in the first state
1885
+ * and enabled in the second.
1886
+ * @param state1 a property map in ##set() syntax describing the initial state of the properties. The properties will automatically be set when the
1887
+ * <var>toggle()</var> function is created. The properties will be set for all elements of the list.
1888
+ * @param state2 a property map describing the second state of the properties. Uses ##set() syntax, like the other state.
1889
+ * @param durationMs optional if set, the duration of the animation in milliseconds. By default, there is no animation and the
1890
+ * properties will be changed immediately.
1891
+ * @param linearity optional defines whether the animation should be linear (1), very smooth (0) or something in between. Default: 0. Ignored if durationMs is 0.
1892
+ * @param interpolationFunc optional an interpolation <code>function(startValue, endValue, t)</code> for the animation which will be called every
1893
+ * time an interpolated value is required:
1894
+ * <dl>
1895
+ * <dt>startValue</dt><dd>The start value of the transition.</dd>
1896
+ * <dt>endValue</dt><dd>The end value of the transition.</dd>
1897
+ * <dt>t</dt><dd>A value between 0 and 1 that specifies the state of the transition.</dd>
1898
+ * <dt class="returnValue">(callback return value)</dt><dd>The value at the time <var>t</var>.</dd>
1899
+ * </dl>
1900
+ * @return a toggle function <code>function(newState)</code> that will toggle between the two states, or set a specific state.
1901
+ * <dl>
1902
+ * <dt>newState (optional)</dt><dd>If a boolean <var>true</var or <var>false</var> is given,
1903
+ * the toggle will set the first or second state, respectively. If called with any other value, or without a value,
1904
+ * the function toggles to the other state.</dd></dl>
1905
+ */
1906
+ 'toggle': function(state1, state2, durationMs, linearity) {
1907
+ var self = this;
1908
+ var animState = {};
1909
+ var state = false, regexg = /\b(?=\w)/g;
1910
+
1911
+ return !state2 ?
1912
+ self['toggle'](replace(state1, regexg, '-'), replace(state1, regexg, '+')) :
1913
+ self['set'](state1) &&
1914
+ function(newState) {
1915
+ if (newState === state)
1916
+ return;
1917
+ state = newState===true||newState===false ? newState : !state;
1918
+
1919
+ if (durationMs)
1920
+ self['animate'](state ? state2 : state1, animState['stop'] ? (animState['stop']() || animState['time']) : durationMs, linearity, animState);
1921
+ else
1922
+ self['set'](state ? state2 : state1);
1923
+ };
1924
+ },
1925
+
1926
+ /*$
1927
+ * @id on
1928
+ * @group EVENTS
1929
+ * @requires dollar
1930
+ * @configurable default
1931
+ * @name .on()
1932
+ * @syntax on(names, eventHandler)
1933
+ * @syntax on(names, customFunc, args)
1934
+ * @syntax on(names, customFunc, fThis, args)
1935
+ * @module WEB
1936
+ * Registers the function as event handler for all items in the list.
1937
+ *
1938
+ * By default, Minified cancels event propagation and the element's default behaviour for all elements that have an event handler.
1939
+ * You can override this by prefixing the event name with a '|' or by returning a 'true' value in the handler, which will reinstate
1940
+ * the original JavaScript behaviour.
1941
+ *
1942
+ * Handlers are called with the original event object as first argument, the index of the source element in the
1943
+ * list as second argument and 'this' set to the source element of the event (e.g. the button that has been clicked).
1944
+ *
1945
+ * Instead of the event objects, you can also pass an array of arguments and a new value for 'this' to the callback.
1946
+ * When you pass arguments, the handler's return value is always ignored and the event with unnamed prefixes
1947
+ * will always be cancelled.
1948
+ *
1949
+ * Event handlers can be unregistered using #off#$.off().
1950
+ *
1951
+ * @example Adds a handler to all divs which paints the div background color to red when clicked.
1952
+ * <pre>
1953
+ * $('div').on('click', function() {
1954
+ * this.style.backgroundColor = 'red'; // 'this' contains the element that caused the event
1955
+ * });
1956
+ * </pre>
1957
+ *
1958
+ * @example Registers a handler to call a method setStatus('running') using an inline function:
1959
+ * <pre>
1960
+ * $('#myButton').on('click', function() {
1961
+ * myObject.setStatus('running');
1962
+ * });
1963
+ * </pre>
1964
+ * The previous example can bere written like this, using <var>on()</var>'s <var>args</var> and <var>fThis</var> parameters:
1965
+ * <pre>
1966
+ * $('#myButton').on('click', myObject.setStatus, myObject, ['running']);
1967
+ * </pre>
1968
+ *
1969
+ * @example Adds two handlers on an input field. The event names are prefixed with '|' and thus keep their original behaviour:
1970
+ * <pre>
1971
+ * $('#myInput').on('|keypress |keydown', function() {
1972
+ * // do something
1973
+ * });
1974
+ * </pre>
1975
+ *
1976
+ * @param names the space-separated names of the events to register for, e.g. 'click'. Case-sensitive. The 'on' prefix in front of
1977
+ * the name must not used. You can register the handler for more than one event by specifying several
1978
+ * space-separated event names. If the name is prefixed
1979
+ * with '|' (pipe), the handler's return value is ignored and the event will be passed through the event's default actions will
1980
+ * be executed by the browser.
1981
+ * @param eventHandler the callback <code>function(event, index)</code> to invoke when the event has been triggered:
1982
+ * <dl>
1983
+ * <dt>event</dt><dd>The original DOM event object.</dd>
1984
+ * <dt>index</dt><dd>The index of the target object in the ##list#Minified list## .</dd>
1985
+ * <dt class="returnValue">(callback return value)</dt><dd>Unless the handler returns <var>true</var>
1986
+ * or the event name is prefixed by '|', all further processing of the event will be
1987
+ * stopped and event bubbling will be disabled.</dd>
1988
+ * </dl>
1989
+ * 'this' is set to the element that caused the event.
1990
+ * @param customFunc a function to be called instead of a regular event handler with the arguments given in <var>args</var>
1991
+ * and optionally the 'this' context given using <var>fThis</var>.
1992
+ * @param fThis optional an value for 'this' in the custom callback, as alternative to the event target
1993
+ * @param args optional an array of arguments to pass to the custom callback function instead of the event objects.
1994
+ * If you pass custom arguments, the return value of the handler will always be ignored.
1995
+ * @return the list
1996
+ */
1997
+ 'on': function (eventName, handler, fThisOrArgs, args) {
1998
+ // @cond debug if (!(name && handler)) error("Both parameters to on() are required!");
1999
+ // @cond debug if (/^on/i.test(name)) error("The event name looks invalid. Don't use an 'on' prefix (e.g. use 'click', not 'onclick'");
2000
+ return each(this, function(el, index) {
2001
+ each(eventName.split(/\s/), function(namePrefixed) {
2002
+ var name = replace(namePrefixed, /\|/);
2003
+ var h = function(event) {
2004
+ var e = event || _window.event;
2005
+ // @cond debug try {
2006
+ if ((!handler.apply(args ? fThisOrArgs : e.target, args || fThisOrArgs || [e, index]) || args) && namePrefixed==name) {
2007
+ e.preventDefault();
2008
+ e.stopPropagation();
2009
+ }
2010
+ // @cond debug } catch (ex) { error("Error in event handler \""+name+"\": "+ex); }
2011
+ };
2012
+ (handler['M'] = handler['M'] || []).push({'e':el, 'h':h, 'n': name});
2013
+ el.addEventListener(name, h, true); // W3C DOM
2014
+ });
2015
+ });
2016
+ }
2017
+
2018
+ /*$
2019
+ * @stop
2020
+ */
2021
+ // @cond !on dummy:null
2022
+ }, function(n, v) {M.prototype[n]=v;});
2023
+
2024
+ //// MINI FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2025
+
2026
+ eachObj({
2027
+ /*$
2028
+ * @id request
2029
+ * @group REQUEST
2030
+ * @requires
2031
+ * @configurable default
2032
+ * @name $.request()
2033
+ * @syntax $.request(method, url)
2034
+ * @syntax $.request(method, url, data)
2035
+ * @syntax $.request(method, url, data, onSuccess)
2036
+ * @syntax $.request(method, url, data, onSuccess, onFailure)
2037
+ * @syntax $.request(method, url, data, onSuccess, onFailure, headers)
2038
+ * @syntax $.request(method, url, data, onSuccess, onFailure, headers, username, password)
2039
+ * @module WEB
2040
+ * Initiates a HTTP request to the given URL, using XMLHttpRequest. It returns a ##promise#Promise## object that allows you to obtain the result.
2041
+ *
2042
+ * @example Invokes a REST web service and parse the resulting document using JSON:
2043
+ * <pre>
2044
+ * $.request('get', 'http://service.example.com/weather', {zipcode: 90210})
2045
+ * .then(function(txt) {
2046
+ * var json = $.parseJSON(txt);
2047
+ * $('#weatherResult').fill('Today's forecast is is: ' + json.today.forecast);
2048
+ * })
2049
+ * .error(function(status, statusText, responseText) {
2050
+ * $('#weatherResult').fill('The weather service was not available.');
2051
+ * });
2052
+ * </pre>
2053
+ *
2054
+ * @example Sending a JSON object to a REST web service:
2055
+ * <pre>
2056
+ * var myRequest = { // create a request object that can be serialized via JSON
2057
+ * request: 'register',
2058
+ * entries: [
2059
+ * {name: 'Joe',
2060
+ * job: 'Plumber'
2061
+ * }]};
2062
+ *
2063
+ * function failureHandler() {
2064
+ * $('#registrationResult').fill('Registration failed');
2065
+ * }
2066
+ *
2067
+ * $.request('post', 'http://service.example.com/directory', $.toJSON(myRequest))
2068
+ * .then(function(txt) {
2069
+ * if (txt == 'OK')
2070
+ * $('#registrationResult').fill('Registration succeeded');
2071
+ * else
2072
+ * failureHandler();
2073
+ * })
2074
+ * .error(failureHandler);
2075
+ * </pre>
2076
+ *
2077
+ *
2078
+ * @param method the HTTP method, e.g. 'get', 'post' or 'head' (rule of thumb: use 'post' for requests that change data
2079
+ * on the server, and 'get' to request data). Not case sensitive.
2080
+ * @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
2081
+ * fancy on the server (keyword to google: Access-Control-Allow-Origin), you can only call URLs on the server your script originates from.
2082
+ * @param data optional data to send in the request, either as POST body or as URL parameters. It can be either an object as map of
2083
+ * parameters (for all HTTP methods), a string (for all HTTP methods) or a DOM document ('post' only). If the method is
2084
+ * 'post', it will be sent as body, otherwise parameters are appended to the URL. In order to send several parameters with the
2085
+ * same name, use an array of values in the map. Use null as value for a parameter without value.
2086
+ * @param headers optional a map of HTTP headers to add to the request. Note that you should use the proper capitalization for the
2087
+ * header 'Content-Type', if you set it, because otherwise it may be overwritten.
2088
+ * @param username optional username to be used for HTTP authentication, together with the password parameter
2089
+ * @param password optional password for HTTP authentication
2090
+ * @return a ##promise#Promise## containing the request's status. If the request has successfully completed with HTTP status 200,
2091
+ * the success handler will be called as <code>function(text, xml)</code>:
2092
+ * <dl><dt>text</dt><dd>The response sent by the server as text.</dd>
2093
+ * <dt>xml</dt><dd>If the response was a XML document, the DOM <var>Document</var>. Otherwise null.</a>.</dd></dl>
2094
+ * The failure handler will be called as <code>function(statusCode, statusText, text)</code>:
2095
+ * <dl><dt>statusCode</dt><dd>The HTTP status (never 200; 0 if no HTTP request took place).</dd>
2096
+ * <dt>statusText</dt><dd>The HTTP status text (or null, if the browser threw an exception).</dd>
2097
+ * <dt>text</dt><dd>the response's body text, if there was any, or the exception as string if the browser threw one.</a>.</dd></dl>
2098
+ */
2099
+ 'request': function (method, url, data, headers, username, password) {
2100
+ // @cond debug if (!method) error("request() requires a HTTP method as first argument.");
2101
+ // @cond debug if (!url) error("request() requires a url as second argument.");
2102
+ // @cond debug if (onSuccess && typeof onSuccess != 'function') error("request()'s fourth argument is optional, but if it is set, it must be a function.");
2103
+ // @cond debug if (onFailure && typeof onFailure != 'function') error("request()'s fifth argument is optional, but if it is set, it must be a function.");
2104
+ // @cond debug if (username && !password) error("If the user name is set (7th argument), you must also provide a password as 8th argument."); method = method.toUpperCase();
2105
+ /** @const */ var ContentType = 'Content-Type';
2106
+ var xhr, body = data, callbackCalled = 0, prom = promise();
2107
+ try {
2108
+ xhr = new XMLHttpRequest();
2109
+ if (data != null) {
2110
+ headers = headers || {};
2111
+ if (!isString(data) && !isNode(data)) { // if data is parameter map...
2112
+ body = collectObj(data, function processParam(paramName, paramValue) {
2113
+ if (isList(paramValue))
2114
+ return collect(paramValue, function(v) {return processParam(paramName, v);});
2115
+ else
2116
+ return encodeURIComponent(paramName) + ((paramValue != null) ? '=' + encodeURIComponent(paramValue) : '');
2117
+ }).join('&');
2118
+ }
2119
+
2120
+ if (!/post/i.test(method)) {
2121
+ url += '?' + body;
2122
+ body = null;
2123
+ }
2124
+ else if (!isNode(data) && !isString(data) && !headers[ContentType])
2125
+ headers[ContentType] = 'application/x-www-form-urlencoded';
2126
+ }
2127
+
2128
+ xhr.open(method, url, true, username, password);
2129
+ eachObj(headers, function(hdrName, hdrValue) {
2130
+ xhr.setRequestHeader(hdrName, hdrValue);
2131
+ });
2132
+
2133
+ xhr.onreadystatechange = function() {
2134
+ if (xhr.readyState == 4 && !callbackCalled++) {
2135
+ if (xhr.status == 200) {
2136
+ prom(true, [xhr.responseText, xhr.responseXML]);
2137
+ }
2138
+ else
2139
+ prom(false, [xhr.status, xhr.statusText, xhr.responseText]);
2140
+ }
2141
+ };
2142
+
2143
+ xhr.send(body);
2144
+ }
2145
+ catch (e) {
2146
+ if (!callbackCalled)
2147
+ prom(false, [0, null, toString(e)]);
2148
+ }
2149
+ return prom;
2150
+ },
2151
+
2152
+ /*
2153
+ * JSON Module. Uses browser built-ins or json.org implementation if available. Otherwise its own implementation,
2154
+ * originally based on public domain implementation http://www.JSON.org/json2.js / http://www.JSON.org/js.html.
2155
+ * Extremely simplified code, made variables local, removed all side-effects (especially new properties for String, Date and Number).
2156
+ */
2157
+
2158
+ /*$
2159
+ * @id tojson
2160
+ * @group JSON
2161
+ * @requires ucode
2162
+ * @configurable default
2163
+ * @name $.toJSON()
2164
+ * @syntax $.toJSON(value)
2165
+ * @module WEB
2166
+ * Converts the given value into a JSON string. The value may be a map-like object, an array or list, a string, number, boolean or null.
2167
+ * If you build Minified without Internet Explorer compatibility, this is just an alias for <var>JSON.stringify</var>.
2168
+ *
2169
+ * The following types are supported by the built-in implementation:
2170
+ * <ul>
2171
+ * <li>Objects (direct properties will be serialized)</li>
2172
+ * <li>Arrays/Lists (with <var>length</var> property)</li>
2173
+ * <li>Strings</li>
2174
+ * <li>Numbers</li>
2175
+ * <li>Boolean</li>
2176
+ * <li>null</li>
2177
+ * </ul>
2178
+ * Any other types in your JSON tree, especially Dates, should be converted into Strings by you.
2179
+ *
2180
+ * @example Converts an object into a JSON object:
2181
+ * <pre>
2182
+ * var myObj = {name: 'Fruits', roles: ['apple', 'banana', 'orange']};
2183
+ * var jsonString = $.toJSON(myObj);
2184
+ * </pre>
2185
+ *
2186
+ * @param value the value (map-like object, array/list, string, number, boolean or null)
2187
+ * @return the JSON string
2188
+ */
2189
+ 'toJSON': _window.JSON && JSON.stringify,
2190
+
2191
+ /*$
2192
+ * @id parsejson
2193
+ * @group JSON
2194
+ * @requires ucode
2195
+ * @configurable default
2196
+ * @name $.parseJSON()
2197
+ * @syntax $.parseJSON(text)
2198
+ * @module WEB
2199
+ * Parses a string containing JSON and returns the de-serialized object.
2200
+ * If the browser's built-in function <var>JSON.parse</var> is defined, which it is in pretty all browsers except
2201
+ * Internet Explorer 7 and earlier, it will be used. This is mainly to prevent possible security problems caused
2202
+ * by the use of <var>eval</var> in the implementation. Only in browsers without
2203
+ * <var>JSON.parse</var> Minified's own implementation will be used.
2204
+ *
2205
+ * If you use a Minified build without Internet Explorer 7 compatibility, <var>JSON.parse</var> will always be used.
2206
+ *
2207
+ * @example Parsing a JSON string:
2208
+ * <pre>
2209
+ * var jsonString = "{name: 'Fruits', roles: ['apple', 'banana', 'orange']}";
2210
+ * var myObj = $.parseJSON(jsonString);
2211
+ * </pre>
2212
+ *
2213
+ * @param text the JSON string
2214
+ * @return the resulting JavaScript object. <var>Undefined</var> if not valid.
2215
+ */
2216
+ 'parseJSON': _window.JSON && JSON.parse,
2217
+
2218
+ /*$
2219
+ * @id ready
2220
+ * @group EVENTS
2221
+ * @requires ready_vars ready_init
2222
+ * @configurable default
2223
+ * @name $.ready()
2224
+ * @syntax $.ready(handler)
2225
+ * @module WEB
2226
+ * Registers a handler to be called as soon as the HTML has been fully loaded. Does not necessarily wait for images and other elements,
2227
+ * only the main HTML document needs to be complete. On older browsers, it is the same as <var>window.onload</var>.
2228
+ *
2229
+ * If you call <var>ready()</var> after the page is completed, the handler is scheduled for invocation in the event loop as soon as possible.
2230
+ *
2231
+ * @example Registers a handler that sets some text in an element:
2232
+ * <pre>
2233
+ * $.ready(function() {
2234
+ * $('#someElement').fill('ready() called');
2235
+ * });
2236
+ * </pre>
2237
+ *
2238
+ * @param handler the <code>function()</code> to be called when the HTML is ready.
2239
+ */
2240
+ 'ready': ready,
2241
+
2242
+ /*$
2243
+ * @id setcookie
2244
+ * @group COOKIE
2245
+ * @configurable default
2246
+ * @name $.setCookie()
2247
+ * @syntax $.setCookie(name, value)
2248
+ * @syntax $.setCookie(name, value, dateOrDays)
2249
+ * @syntax $.setCookie(name, value, dateOrDays, path)
2250
+ * @syntax $.setCookie(name, value, dateOrDays, path, domain)
2251
+ * @module WEB
2252
+ * Creates, updates or deletes a cookie. If there is an an existing cookie
2253
+ * of the same name, will be overwritten with the new value and settings.
2254
+ *
2255
+ * To delete a cookie, overwrite it with an expiration date in the past. The easiest way to do this is to
2256
+ * use <code>-1</code> as third argument.
2257
+ *
2258
+ * @example Reads the existing cookie 'numberOfVisits', increases the number and stores it:
2259
+ * <pre>
2260
+ * var visits = $.getCookie('numberOfVisits');
2261
+ * $.setCookie('numberOfVisits',
2262
+ * visits ? (parseInt(visits) + 1) : 1, // if cookie not set, start with 1
2263
+ * 365); // store for 365 days
2264
+ * </pre>
2265
+ *
2266
+ * @example Deletes the cookie 'numberOfVisits':
2267
+ * <pre>
2268
+ * $.setCookie('numberOfVisits', '', -1);
2269
+ * </pre>
2270
+ *
2271
+ * @param name the name of the cookie. This should ideally be an alphanumeric name, as it will not be escaped by Minified and this
2272
+ * guarantees compatibility with all systems.
2273
+ * If it contains a '=', it is guaranteed not to work, because it breaks the cookie syntax.
2274
+ * @param value the value of the cookie. All characters can be used. Non-Alphanumeric other than "*@-_+./" will be escaped using the
2275
+ * JavaScript <var>escape()</var> function, unless you set the optional <var>dontEscape</var> parameter.
2276
+ * @param dateOrDays optional specifies when the cookie expires. Can be either a Date object or a number that specifies the
2277
+ * amount of days. If not set, the cookie has a session lifetime, which means it will be deleted as soon as the
2278
+ * browser has been closed. If the number negative or the date in the past, the cookie will be deleted.
2279
+ * @param path optional if set, the cookie will be restricted to documents in the given path. Otherwise it is valid
2280
+ * for the whole domain. This is rarely needed and defaults to '/'.
2281
+ * @param domain optional if set, you use it to specify the domain (e.g. example.com) which can read the cookie. If you don't set it,
2282
+ * the domain which hosts the current document is used. This parameter is rarely used, because there are only very
2283
+ * few use cases in which this makes sense.
2284
+ * @param dontEscape optional if set, the cookie value is not escaped. Note that without escaping you can not use every possible
2285
+ * character (e.g. ";" will break the cookie), but it may be needed for interoperability with systems that need
2286
+ * some non-alphanumeric characters unescaped or use a different escaping algorithm.
2287
+ */
2288
+ 'setCookie': function(name, value, dateOrDays, path, domain, dontEscape) {
2289
+ // @cond debug if (!name) error('Cookie name must be set!');
2290
+ // @cond debug if (/[^\w\d-_%]/.test(name)) error('Cookie name must not contain non-alphanumeric characters other than underscore and minus. Please escape them using encodeURIComponent().');
2291
+ _document.cookie = name + '=' + (dontEscape ? value : escape(value)) +
2292
+ (dateOrDays ? ('; expires='+(isObject(dateOrDays) ? dateOrDays : new Date(now() + dateOrDays * 8.64E7)).toUTCString()) : '') +
2293
+ '; path=' + (path ? escapeURI(path) : '/') + (domain ? ('; domain=' + escape(domain)) : '');
2294
+ },
2295
+
2296
+ /*$
2297
+ * @id getcookie
2298
+ * @group COOKIE
2299
+ * @requires
2300
+ * @configurable default
2301
+ * @name $.getCookie()
2302
+ * @syntax $.getCookie(name)
2303
+ * @syntax $.getCookie(name, dontUnescape)
2304
+ * @module WEB
2305
+ * Tries to find the cookie with the given name and returns it.
2306
+ *
2307
+ * @example Reads the existing cookie 'numberOfVisits' and displays the number in the element 'myCounter':
2308
+ * <pre>
2309
+ * var visits = $.getCookie('numberOfVisits');
2310
+ * if (!visits) // check whether cookie set. Null if not
2311
+ * $('#myCounter').set('innerHML', 'Your first visit.');
2312
+ * else
2313
+ * $('#myCounter').set('innerHTML', 'Visit No ' + visits);
2314
+ * </pre>
2315
+ *
2316
+ * @param name the name of the cookie. Should consist of alphanumeric characters, percentage, minus and underscore only, as it will not be escaped.
2317
+ * You may want to escape the name using <var>encodeURIComponent()</var> for all other characters.
2318
+ * @param dontUnescape optional if set and true, the value will be returned unescaped. Use this parameter only if the value has been encoded
2319
+ * in a special way, and not with the JavaScript <var>encode()</var> method.
2320
+ * @return the value of the cookie, or null if not found. Unless <var>dontUnescape</var> has been set, the value has been unescaped
2321
+ * using JavaScript's <code>unescape()</code> function.
2322
+ */
2323
+ 'getCookie': function(name, dontUnescape) {
2324
+ // @cond debug if (!name) error('Cookie name must be set!');
2325
+ // @cond debug if (/[^\w\d-_%]/.test(name)) error('Cookie name must not contain non-alphanumeric characters other than underscore and minus. Please escape them using encodeURIComponent().');
2326
+ var regexp, match = (regexp = new RegExp('(^|;)\\s*'+name+'=([^;]*)').exec(_document.cookie)) && regexp[2];
2327
+ return dontUnescape ? match : match && unescape(match);
2328
+ },
2329
+
2330
+ /*$
2331
+ * @id loop
2332
+ * @group ANIMATION
2333
+ * @requires animation_vars
2334
+ * @configurable default
2335
+ * @name $.loop()
2336
+ * @syntax $.loop(paintCallback)
2337
+ * @module WEB
2338
+ * Runs an animation loop. The given callback method will be invoked repeatedly to create a new animation frame.
2339
+ * In modern browsers, <var>requestAnimationFrame</var> will be used to invoke the callback every time the browser is ready for a new
2340
+ * animation frame.
2341
+ * The exact frequency is determined by the browser and may vary depending on factors such as the time needed to
2342
+ * render the current page, the screen's framerate and whether the page is currently visible to the user.
2343
+ * In older browsers, the callback function will be invoked approximately every 33 milliseconds.
2344
+ *
2345
+ * An animation loop runs indefinitely. To stop it, you have two options:
2346
+ * <ul><li><var>$.loop()</var> returns a <var>stop()</var> function. If you invoke it, the animation loops ends</li>
2347
+ * <li>The animation callback receives the same <var>stop()</var> function as second argument, so the callback can end the animation itself</li>
2348
+ * </ul>
2349
+ *
2350
+ * @example Animates a div by moving along in a circle.
2351
+ * <pre>
2352
+ * var myDiv = $$('#myAnimatedDiv');
2353
+ * var rotationsPerMs = 1000; // one rotation per second
2354
+ * var radius = 100;
2355
+ * var d = 3000; // duration in ms
2356
+ * $.loop(function(t, stopFunc) {
2357
+ * if (t > d) { // time is up: call stopFunc()!
2358
+ * stopFunc();
2359
+ * return;
2360
+ * }
2361
+ *
2362
+ * var a = 2 * Math.PI * t / rotationsPerMs // angular position
2363
+ * myDiv.style.left = (radius * Math.cos(a) + ' px';
2364
+ * myDiv.style.top = (radius * Math.sin(a) + ' px';
2365
+ * });
2366
+ * </pre>
2367
+ *
2368
+ * @param paintCallback a callback <code>function(timestamp, stopFunc)</code> to invoke for painting. Parameters given to callback:
2369
+ * <dl>
2370
+ * <dt>timestamp</dt><dd>The number of miliseconds since animation start.</dd>
2371
+ * <dt>stop</dt><dd>Call this <code>function()</code> to stop the currently running animation.</dd>
2372
+ * </dl>
2373
+ * The callback's return value will be ignored.
2374
+ * @return a <code>function()</code> that stops the currently running animation. This is the same function that is also given to the callback.
2375
+ */
2376
+ 'loop': function(paintCallback) {
2377
+ var entry = {c: paintCallback, t: now()};
2378
+ entry.s = function() {
2379
+ for (var i = 0; i < ANIMATION_HANDLERS.length; i++) // can't use each() or filter() here, list may be modified during run!!
2380
+ if (ANIMATION_HANDLERS[i] === entry)
2381
+ ANIMATION_HANDLERS.splice(i--, 1);
2382
+ };
2383
+
2384
+ if (ANIMATION_HANDLERS.push(entry) < 2) { // if first handler..
2385
+ (function raFunc() {
2386
+ if (each(ANIMATION_HANDLERS, function(a) {a.c(Math.max(0, now() - a.t), a.s);}).length) // check len after run, in case the callback invoked stop func
2387
+ REQUEST_ANIMATION_FRAME(raFunc);
2388
+ })();
2389
+ }
2390
+ return entry.s;
2391
+ },
2392
+
2393
+ /*$
2394
+ * @id wait
2395
+ * @configurable default
2396
+ * @requires
2397
+ * @name $.wait()
2398
+ * @syntax $.wait()
2399
+ * @syntax $.wait(durationMs)
2400
+ * @module WEB
2401
+ *
2402
+ * Creates a new promise that will be fulfilled as soon as the specified number of milliseconds have passed. This is mainly useful for animation,
2403
+ * because it allows you to chain delays into your animation chain.
2404
+ *
2405
+ * @example Chained animation using ##promise#Promise## callbacks. The element is first moved to the position 200/0, then to 200/200, waits for 50ms
2406
+ * and finally moves to 100/100.
2407
+ * <pre>
2408
+ * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
2409
+ * div.animate({$left: '200px', $top: '0px'}, 600, 0)
2410
+ * .then(function() {
2411
+ * div.animate({$left: '200px', $top: '200px'}, 800, 0);
2412
+ * }).then(function() {
2413
+ * return $.wait(50);
2414
+ * }).then(function() {
2415
+ * div.animate({$left: '100px', $top: '100px'}, 400);
2416
+ * });
2417
+ * });
2418
+ * </pre>
2419
+ *
2420
+ *
2421
+ * @param durationMs optional the number of milliseconds to wait. If omitted, the promise will be fulfilled as soon as the browser can run it
2422
+ * from the event loop.
2423
+ * @param args optional an array of arguments to pass to the promise handler
2424
+ * @return a ##promise#Promise## object that will be fulfilled when the time is over. It will never fail. The promise argument is the
2425
+ * <var>args</var> parameter as given to <var>wait()</var>.
2426
+ */
2427
+ 'wait': function(durationMs, args) {
2428
+ var p = promise();
2429
+ delay(function() {p(true, args);}, durationMs);
2430
+ return p;
2431
+ },
2432
+
2433
+ /*$
2434
+ * @id off
2435
+ * @group EVENTS
2436
+ * @requires on
2437
+ * @configurable default
2438
+ * @name $.off()
2439
+ * @syntax $.off(handler)
2440
+ * @module WEB
2441
+ * Removes the given event handler. The call will be ignored if the given handler has not been registered using ##on().
2442
+ * If the handler has been registered for more than one element or event, it will be removed from all instances.
2443
+ *
2444
+ * @example Adds a handler to an element:
2445
+ * <pre>
2446
+ * function myEventHandler() {
2447
+ * this.style.backgroundColor = 'red'; // 'this' contains the element that caused the event
2448
+ * }
2449
+ * $('#myElement').on('click', myEventHandler); // add event handler
2450
+ *
2451
+ * window.setInterval(function() { // after 5s, remove event handler
2452
+ * $.off(myEventHandler);
2453
+ * }, 5000);
2454
+ * </pre>
2455
+ *
2456
+ * @param handler the handler to unregister, as given to ##on(). It must be a handler that has previously been registered using ##on().
2457
+ * If the handler is not registered as event handler, the function does nothing.
2458
+ */
2459
+ 'off': function (handler) {
2460
+ // @cond debug if (!handler || !handler['M']) error("No handler given or handler invalid.");
2461
+ each(handler['M'], function(h) {
2462
+ h['e'].removeEventListener(h['n'], h['h'], true); // W3C DOM
2463
+ });
2464
+ handler['M'] = null;
2465
+ }
2466
+
2467
+ /*$
2468
+ * @stop
2469
+ */
2470
+ // @cond !off dummy:null
2471
+
2472
+ }, function(n, v) {$[n]=v;});
2473
+
2474
+ //// GLOBAL INITIALIZATION ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2475
+
2476
+ /*$
2477
+ * @id ready_init
2478
+ * @dependency
2479
+ */
2480
+
2481
+ _document.addEventListener("DOMContentLoaded", triggerDomReady, false);
2482
+ /*$
2483
+ @stop
2484
+ */
2485
+
2486
+ // @condblock amdsupport
2487
+ return {
2488
+ // @condend amdsupport
2489
+
2490
+ // @cond !amdsupport var MINI = {
2491
+
2492
+ /*$
2493
+ * @id dollar
2494
+ * @group SELECTORS
2495
+ * @requires dollarraw
2496
+ * @dependency yes
2497
+ * @name $()
2498
+ * @syntax $(selector)
2499
+ * @syntax $(selector, context)
2500
+ * @syntax $(selector, context, childOnly)
2501
+ * @syntax $(list)
2502
+ * @syntax $(list, context)
2503
+ * @syntax $(list, context, childOnly)
2504
+ * @syntax $(object)
2505
+ * @syntax $(object, context)
2506
+ * @syntax $(object, context, childOnly)
2507
+ * @syntax $(domreadyFunction)
2508
+ * @module WEB
2509
+ * Creates a new ##list#Minified list##, or register a DOMReady-handler.
2510
+ * The most common usage is with a CSS-like selector. <var$()</var> will then create a list containing all elements of the current HTML
2511
+ * document that fulfill the filter conditions. Alternatively you can also specify a list of objects or a single object.
2512
+ * Nested lists will automatically be flattened, and nulls will automatically be removed from the resulting list.
2513
+ *
2514
+ * Additionally, you can specify a second argument to provide a context. Contexts only make sense if you selected only
2515
+ * HTML nodes with the first parameter. Then the context limits the resulting list to include only those nodes
2516
+ * that are descendants of the context nodes. The context can be either a selector, a list or a single HTML node, and will be
2517
+ * processed like the first argument. A third arguments allows you to limit the list to
2518
+ * only those elements that are direct children of the context nodes (so a child of a child would be filtered out).
2519
+ *
2520
+ *
2521
+ * As a special shortcut, if you pass a function to <var>$()</var>, it will be registered using #ready#$.ready() to be executed
2522
+ * when the DOM model is complete.
2523
+ *
2524
+ * @example A simple selector to find an element by id.
2525
+ * <pre>
2526
+ * var l0 = $('#myElementId');
2527
+ * </pre>
2528
+ *
2529
+ * @example You can pass a reference to a DOM node to the function to receive a list containing only this node:
2530
+ * <pre>
2531
+ * var l1 = $(document.getElementById('myElementId'));
2532
+ * </pre>
2533
+ *
2534
+ * @example Lists and arrays will be copied:
2535
+ * <pre>
2536
+ * var l2 = $([elementA, elementB, elementC]);
2537
+ * </pre>
2538
+ *
2539
+ * @example Lists will be automatically flattened and nulls removed. So this list <var>l3</var> has the same content as <var>l2</var>:
2540
+ * <pre>
2541
+ * var l3 = $([elementA, [elementB, null, elementC], null]);
2542
+ * </pre>
2543
+ *
2544
+ * @example This is a simple selector to find all elements with the given class.
2545
+ * <pre>
2546
+ * var l4 = $('.myClass');
2547
+ * </pre>
2548
+ *
2549
+ * @example A selector to find all elements with the given name.
2550
+ * <pre>
2551
+ * var l5 = $('input'); // finds all input elements
2552
+ * </pre>
2553
+ *
2554
+ * @example A selector to find all elements with the given name and class.
2555
+ * <pre>
2556
+ * var l6 = $('input.myRadio'); // finds all input elements with class 'myRadio'
2557
+ * </pre>
2558
+ *
2559
+ * @example A selector to find all elements that are descendants of the given element.
2560
+ * <pre>
2561
+ * var l7 = $('#myForm input'); // finds all input elements that are in the element with the id myForm
2562
+ * </pre>
2563
+ *
2564
+ * @example A selector to find all elements that have either CSS class 'a' or class 'b':
2565
+ * <pre>
2566
+ * var l8 = $('.a, .b'); // finds all elements that have either the class a or class b
2567
+ * </pre>
2568
+ *
2569
+ * @example A selector that finds all elements that are descendants of the element myDivision, are inside a .myForm class and are input elements:
2570
+ * <pre>
2571
+ * var l9 = $('#myDivision .myForm input');
2572
+ * </pre>
2573
+ *
2574
+ * @example Using contexts to make it easier to specify ancestors:
2575
+ * <pre>
2576
+ * var l10 = $('.myRadio', '#formA, #formB, #formC');
2577
+ * </pre>
2578
+ * The result is identical to:
2579
+ * <pre>
2580
+ * var l10 = $('#formA .myRadio, #formB .myRadio, #formC .myRadio');
2581
+ * </pre>
2582
+ *
2583
+ * @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.
2584
+ * <pre>
2585
+ * $('#myElementId').set('$color', 'red');
2586
+ * </pre>
2587
+ *
2588
+ * @example Most list methods return the list you invoked them on, allowing you to chain them:
2589
+ * <pre>
2590
+ * $('#myForm .myRadio').addClass('uncheckedRadio')
2591
+ * .set('checked', true)
2592
+ * .on('click', function() {
2593
+ * $(this).set({@: 'uncheckedRadio');
2594
+ * });
2595
+ * </pre>
2596
+ *
2597
+ * @example Using $() as a #ready#$.ready() shortcut:
2598
+ * <pre>
2599
+ * $(function() {
2600
+ * // in here you can safely work with the HTML document
2601
+ * });
2602
+ * </pre>
2603
+ *
2604
+ * @param selector a simple, CSS-like selector for HTML elements. It supports '#id' (lookup by id), '.class' (lookup by class),
2605
+ * 'element' (lookup by elements) and 'element.class' (combined class and element). Use commas to combine several selectors.
2606
+ * You can also join two or more selectors by space to find elements which are descendants of the previous selectors.
2607
+ * For example, use 'div' to find all div elements, '.header' to find all elements containing a class name called 'header', and
2608
+ * 'a.popup' for all a elements with the class 'popup'. To find all elements with 'header' or 'footer' class names,
2609
+ * write '.header, .footer'. To find all divs elements below the element with the id 'main', use '#main div'.
2610
+ * The selector "*" will return all elements.
2611
+ * @param list a list to copy. It can be an array, another Minified list, a DOM nodelist or anything else that has a <var>length</var> property and
2612
+ * allows read access by index. A shallow copy of the list will be returned. Nulls will be automatically removed from the copy. Nested lists
2613
+ * will be flattened, so the result only contains nodes.
2614
+ * @param object a object to create a single-element list containing only the object. If the object argument is null, an empty list will be returned.
2615
+ * @param domreadyFunction a function to be registered using #ready#$.ready().
2616
+ * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection, using the same syntax variants as the
2617
+ * first argument. If given, the returned list contains only descendants of the context nodes, all others will be filtered out.
2618
+ * @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
2619
+ * true, all descendants of the context will be included.
2620
+ * @return the array-like ##list#Minified list## object containing the content specified by the selector.
2621
+ * Please note that duplicates (e.g. created using the comma-syntax or several context nodes) will not be removed. If the first argument was a list,
2622
+ * 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
2623
+ * 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,
2624
+ * not be in document order anymore, unless you use a build without legacy IE support.
2625
+ */
2626
+ '$': $,
2627
+
2628
+ /*$
2629
+ * @id dollardollar
2630
+ * @group SELECTORS
2631
+ * @requires dollarraw
2632
+ * @configurable default
2633
+ * @name $$()
2634
+ * @syntax $$(selector)
2635
+ * @shortcut $$() - It is recommended that you assign MINI.$$ to a variable $$.
2636
+ * @module WEB
2637
+ * Returns a DOM object containing the first match of the given selector, or <var>undefined</var> if no match was found.
2638
+ * <var>$$</var> allows you to easily access an element directly. It is the equivalent to writing "$(selector)[0]".
2639
+ *
2640
+ * Please note that the function <var>$$</var> will not be automatically exported by Minified. You should always import it
2641
+ * using the recommended import statement:
2642
+ * <pre>
2643
+ * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
2644
+ * </pre>
2645
+ *
2646
+ * @example Select the checkbox 'myCheckbox':
2647
+ * <pre>
2648
+ * $$('#myCheckbox').checked = true;
2649
+ * </pre>
2650
+ *
2651
+ * @param selector a simple, CSS-like selector for the element. Uses the full syntax described in #dollar#$(). The most common
2652
+ * parameter for this function is the id selector with the syntax "#id".
2653
+ * @return a DOM object of the first match, or <var>undefined</var> if the selector did not return at least one match
2654
+ */
2655
+ '$$': $$,
2656
+
2657
+ /*$
2658
+ * @id ee
2659
+ * @group ELEMENT
2660
+ * @requires dollar set add
2661
+ * @configurable default
2662
+ * @name EE()
2663
+ * @syntax EE(elementName)
2664
+ * @syntax EE(elementName, properties)
2665
+ * @syntax EE(elementName, children)
2666
+ * @syntax EE(elementName, properties, children)
2667
+ * @syntax EE(elementName, properties, children, onCreate)
2668
+ * @shortcut EE() - It is recommended that you assign MINI.EE to a variable EE.
2669
+ * @module WEB
2670
+ * Creates a new Element Factory. An Element Factory is a function without arguments that returns a ##list#Minified list##
2671
+ * containing a newly created DOM element, optionally with attributes and children.
2672
+ * Typically it will be used to insert elements into the DOM tree using ##add() or a similar function.
2673
+ *
2674
+ * Please note that the function <var>EE</var> will not be automatically exported by Minified. You should always import it
2675
+ * using the recommended import statement:
2676
+ * <pre>
2677
+ * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
2678
+ * </pre>
2679
+ *
2680
+ * @example Creating a simple factory for a &lt;span> element with some text:
2681
+ * <pre>
2682
+ * var mySpan = EE('span', 'Hello World');
2683
+ * </pre>
2684
+ * creates a factory to produce this:
2685
+ * <pre>
2686
+ * &lt;span>Hello World&lt;/span>
2687
+ * </pre>
2688
+ *
2689
+ * @example Adding the 'Hello World; &lt;span> element to all elements with the class '.greeting':
2690
+ * <pre>
2691
+ * $('.greeting').add(EE('span', 'Hello World'));
2692
+ *
2693
+ * @example Creating a factory for a &lt;span> element with style and some text:
2694
+ * <pre>
2695
+ * var span2 = EE('span', {'@title': 'Greetings'}, 'Hello World');
2696
+ * </pre>
2697
+ * The factory creates this:
2698
+ * <pre>
2699
+ * &lt;span title="Greetings">Hello World&lt;/span>
2700
+ * </pre>
2701
+ *
2702
+ * @example Creating a &lt;form> element with two text fields, labels and a submit button:
2703
+ * <pre>var myForm = EE('form', {'@method': 'post'}, [
2704
+ * EE('label', {'@for': 'nameInput'}, 'Name:'),
2705
+ * EE('input', {'@id': 'nameInput', '@type': 'input'}),
2706
+ * EE('br'),
2707
+ * EE('label', {'@for': 'ageInput'}, 'Age:'),
2708
+ * EE('input', {'@id': 'ageInput', '@type': 'input'}),
2709
+ * EE('br'),
2710
+ * EE('input', {'@type': 'submit, '@value': 'Join'})
2711
+ * ]);
2712
+ * </pre>
2713
+ * results in (newlines and indentation added for readability):
2714
+ * <pre>
2715
+ * &lt;form method="post>
2716
+ * &lt;label for="nameInput">Name:&lt;/label>
2717
+ * &lt;input id="nameInput" type="input"/>
2718
+ * &lt;br/>
2719
+ * &lt;label for="ageInput"/>Age:&lt;/label>
2720
+ * &lt;input id="ageInput" type="input"/>
2721
+ * &lt;br/>
2722
+ * &lt;input value="Join" type="submit"/>
2723
+ * &lt;/form>
2724
+ * </pre>
2725
+ *
2726
+ * @example If you only want to add an attribute under a certain condition,
2727
+ * a simple trick is to pass null as value if you do not need it:
2728
+ * <pre>
2729
+ * var myInput = EE('input', {
2730
+ * '@id': 'myCheckbox',
2731
+ * '@type': 'checkbox',
2732
+ * '@checked': shouldBeChecked() ? 'checked' : null
2733
+ * });
2734
+ * </pre>
2735
+ *
2736
+ * @example You can set styles directly using a $ prefix for the name:
2737
+ * <pre>
2738
+ * var myStylesSpan = EE('span', {$color: "red", $fontWeight: "bold"}, "I'm styled");
2739
+ * </pre>
2740
+ *
2741
+ * @example To add event handlers, use the fourth argument:
2742
+ * <pre>
2743
+ * var myStylesSpan = EE('input', {'@name': "myInput"}, null, function(e) {
2744
+ * e.on('change', inputChanged);
2745
+ * });
2746
+ * </pre>
2747
+ *
2748
+ * @param elementName the element name to create (e.g. 'div')
2749
+ * @param properties optional an object which contains a map of attributes and other values. Uses the ##set() syntax:
2750
+ * Attribute values are prefixed with '@', CSS styles with '$' and regular properties can be set without prefix.
2751
+ * If the attribute value is null, the attribute will omitted (styles and properties can be set to null).
2752
+ * In order to stay compatible with Internet Explorer 7 and earlier, you should not set the
2753
+ * attributes '@class' and '@style'. Instead set the property 'className' instead of '@class' and set
2754
+ * styles using the '$' syntax.
2755
+ * @param children optional a node or a list of nodes to be added as children. Strings will be converted to text nodes.
2756
+ * Functions will be invoked and their return value will be used. Lists can be
2757
+ * nested and will then automatically be flattened. Null elements in lists will be ignored.
2758
+ * The syntax is exactly like ##add().
2759
+ * @param onCreate optional a <code>function(elementList)</code> that will be called each time an element had been created.
2760
+ * <dl><dt>elementList</dt><dd>The newly created element wrapped in a Minified list. </dd></dl>
2761
+ * The function's return value will be ignored.
2762
+ * The callback allows you, for example, to add event handlers to the element using ##on().
2763
+ * @return a Element Factory function, which returns a Minified list containing the DOM HTMLElement that has been created or modified as only element
2764
+ */
2765
+ 'EE': EE
2766
+
2767
+ /*$
2768
+ * @stop
2769
+ */
2770
+ // @cond !ee dummy:null
2771
+ };
2772
+ // @cond !amdsupport _window['require'] = function(n) { if (n == 'minified') return MINI; };
2773
+
2774
+ // @condblock amdsupport
2775
+ });
2776
+ // @condend amdsupport
2777
+
2778
+ // @cond !amdsupport })();
2779
+
2780
+ /*$
2781
+ * @id list
2782
+ * @name Minified Lists
2783
+ * @module WEB, UTIL
2784
+ *
2785
+ * <i>Minified lists</i> are Array-like objects provided by Minified. Like a regular JavaScript array,
2786
+ * they provide a <var>length</var> property and you can access their content using the index operator (<code>a[5]</code>).
2787
+ * However, they do not provide the same methods as JavaScript's native array.
2788
+ *
2789
+ * Minified lists are usually created using the #dollar#$()</a></code> function. You can
2790
+ * also use <code>$()</code> to convert a JavaScript array into a Minified list, just be aware that <code>$()</code> will
2791
+ * remove nulls from the lists and will flatten nested lists.
2792
+ *
2793
+ * There is currently no function to convert a Minified list into a JavaScript array. The upcoming Utility module
2794
+ * will provide one though.
2795
+ *
2796
+ * The Minified Web module provides HTML-node oriented functions like ##set() to modify a list of nodes. It also has a
2797
+ * number of helper methods for working with Minified lists:
2798
+ * <ul>
2799
+ * <li>##collect() creates a new list using the collect function which can
2800
+ * transform list elements or collect data from them ("map() on steriods")</li>
2801
+ * <li>##each() iterates through all list elements</li>
2802
+ * <li>##filter() creates a new list that contains only elements that pass the
2803
+ * filter function's test</li>
2804
+ * <li>##find() finds a list element or its position</li>
2805
+ * <li>##sub() creates a list that copies the elements from the specified index range </li>
2806
+ * </ul>
2807
+ */
2808
+
2809
+ /*$
2810
+ * @id promise
2811
+ * @name Promise
2812
+ * @module WEB, UTIL
2813
+ *
2814
+ * <i>Promises</i> are objects that represent the result of an asynchronous operation. When you start such an operation, using #request#$.request(),
2815
+ * ##animate(), or ##wait(), you will get a Promise object that allows you to get the result as soon as the operation is finished.
2816
+ *
2817
+ * Minified ships with a <a href="http://promises-aplus.github.io/promises-spec/">Promises/A+</a>-compliant implementation of Promises that should
2818
+ * be able to interoperate with most other Promises implementations.
2819
+ *
2820
+ * What may be somewhat surprising about this Promises specification is that there is no direct way to find out the state of the operation.
2821
+ * There is neither a property nor a function to find out what the result is or whether it is available. Instead, you always have to
2822
+ * register callbacks to find out the result. They will be invoked as soon as the operation is finished.
2823
+ * If the operation already ended when you register the callbacks, the callback will then just be called from the event loop as soon
2824
+ * as possible (but never while the ##then() you register them with is still running).<br/>
2825
+ * This design forces you to handle the operation result asynchronously and disencourages 'bad' techniques such as polling.
2826
+ *
2827
+ * The central method of a Promises, and indeed the only required function in Promises/A+, is ##then(). It allows you to register
2828
+ * two callback methods, one for success (called 'fulfillment' in Promises/A+ terminology) and one for failures (called 'rejection' in Promises/A+).
2829
+ *
2830
+ * This example shows you how to use <var>then()</var>:
2831
+ * <pre>
2832
+ * $.request('get', 'http://example.com/weather?zip=90210')
2833
+ * .then(function success(result) {
2834
+ * alert('The weather is ' + result);
2835
+ * }, function error(exception) {
2836
+ * alert('Something went wrong');
2837
+ * });
2838
+ * </pre>
2839
+ *
2840
+ * What makes Promises so special is that ##then() itself returns a new Promise, which is based on the Promise <var>then()</var> was called on, but can be
2841
+ * modified by the outcome of callbacks. Both arguments to <var>then()</var> are optional, and you can also write the code like this:
2842
+ * <pre>
2843
+ * $.request('get', 'http://example.com/weather?zip=90210')
2844
+ * .then(function success(result) {
2845
+ * alert('The weather is ' + result);
2846
+ * })
2847
+ * .then(null, function error(exception) {
2848
+ * alert('Something went wrong');
2849
+ * });
2850
+ * </pre>
2851
+ *
2852
+ * Because the first ##then() returns a new Promise based on the original Promise, the second <var>then()</var> will handle errors of the request just like
2853
+ * 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,
2854
+ * 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
2855
+ * the Promise returned by <var>then()</var>. Any exception thrown in a callback causes the new Promise to be in error state.
2856
+ *
2857
+ * Before I show you the second difference between the original Promise and the new Promise, let me make the example a bit more readable
2858
+ * by using ##error(), which is not part of Promises/A+, but a simple extension by Minified. It just registers the failure callback without
2859
+ * forcing you to specify <var>null</var> as first argument:
2860
+ * <pre>
2861
+ * $.request('get', 'http://example.com/weather?zip=90210')
2862
+ * .then(function success(result) {
2863
+ * alert('The weather is ' + result);
2864
+ * })
2865
+ * .error(function error(exception) { // error(callback) is equivalent to then(null, callback)
2866
+ * alert('Something went wrong');
2867
+ * });
2868
+ * </pre>
2869
+ *
2870
+ * A very powerful capability of Promises is that you can easily chain them. If a ##then() callback returns a value, the new Promise returned
2871
+ * by <var>then()</var> will be marked as success (fulfilled) and this value is the result of the operation. If a callback returns a Promise,
2872
+ * the new Promise will assume the state of the returned Promise. You can use the latter to create chains of asynchronous operations,
2873
+ * but you still need only a single error handler for all of them and you do not need to nest functions to achieve this:
2874
+ * <pre>
2875
+ * $.request('get', 'http://example.com/zipcode?location=Beverly+Hills,+CA')
2876
+ * .then(function(resultZip) {
2877
+ * return $.request('get', 'http://example.com/weather', {zip: resultZip});
2878
+ * })
2879
+ * .then(function(resultWeather) {
2880
+ * alert('The weather in Beverly Hills is ' + resultWeather);
2881
+ * })
2882
+ * .error(function(exception) {
2883
+ * alert('Something went wrong');
2884
+ * });
2885
+ * </pre>
2886
+ *
2887
+ * Sometimes you want to just be notified of the end of an operation but are not interested in the outcome. For these cases, if you just had
2888
+ * the Promises/A+-compliant ##then() method, you would have to register the same callback handler twice. This is not very convenient,
2889
+ * especially when you define the handler function inline. Therefore Minified comes with a second small extension, ##always():
2890
+ *
2891
+ * <pre>
2892
+ * $.request('post', 'http://example.com/pageHit', {pageId: 12345})
2893
+ * .always(function() { // always(callback) is equivalent to then(callback, callback)
2894
+ * pageCountDone();
2895
+ * });
2896
+ * </pre>
2897
+ *
2898
+ * Please note that the Minified Web module only returns Promises, but it <strong>does not allow you to create Promises</strong> directly. The upcoming
2899
+ * Minified App module will allow this though.
2900
+ */