minifiedjs-rails 0.0.1.beta

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