PageSourceSearch

https://fragilestatesindex.org/wp-content/plugins/wp_rokbox/assets/js/rokbox.js?ver=2.50.7

js fragilestatesindex.org collected 2026-10-02 03:25:27 UTC 118,449 bytes, 3,152 lines download raw bytes

1/*
2---
3provides: moofx
4version: 3.1.0
5description: A CSS3-enabled javascript animation library
6homepage: http://moofx.it
7author: Valerio Proietti <@kamicane> (http://mad4milk.net)
8license: MIT (http://mootools.net/license.txt)
9includes: cubic-bezier by Arian Stolwijk (https://github.com/arian/cubic-bezier)
10...
11*/
12
13(function(modules) {
14    var cache = {}, require = function(id) {
15        var module = cache[id];
16        if (!module) {
17            module = cache[id] = {};
18            var exports = module.exports = {};
19            modules[id].call(exports, require, module, exports, window);
20        }
21        return module.exports;
22    };
23    window["moofx"] = require("0");
24})({
25    "0": function(require, module, exports, global) {
26        /*          .-   3
27.-.-..-..-.-|-._.
28' ' '`-'`-' ' ' '
29*/
30                "use strict";
31
32        // color and timer
33        var color = require("1"), frame = require("2");
34
35        // if we're in a browser we need ./browser, otherwise ./fx
36        var moofx = typeof document !== "undefined" ? require("7") : require("b");
37
38        moofx.requestFrame = function(callback) {
39            frame.request(callback);
40            return this;
41        };
42
43        moofx.cancelFrame = function(callback) {
44            frame.cancel(callback);
45            return this;
46        };
47
48        moofx.color = color;
49
50        // and export moofx
51        module.exports = moofx;
52    },
53    "1": function(require, module, exports, global) {
54        /*
55color
56*/
57                "use strict";
58
59        var colors = {
60            maroon: "#800000",
61            red: "#ff0000",
62            orange: "#ffA500",
63            yellow: "#ffff00",
64            olive: "#808000",
65            purple: "#800080",
66            fuchsia: "#ff00ff",
67            white: "#ffffff",
68            lime: "#00ff00",
69            green: "#008000",
70            navy: "#000080",
71            blue: "#0000ff",
72            aqua: "#00ffff",
73            teal: "#008080",
74            black: "#000000",
75            silver: "#c0c0c0",
76            gray: "#808080",
77            transparent: "#0000"
78        };
79
80        var RGBtoRGB = function(r, g, b, a) {
81            if (a == null || a === "") a = 1;
82            r = parseFloat(r);
83            g = parseFloat(g);
84            b = parseFloat(b);
85            a = parseFloat(a);
86            if (!(r <= 255 && r >= 0 && g <= 255 && g >= 0 && b <= 255 && b >= 0 && a <= 1 && a >= 0)) return null;
87            return [ Math.round(r), Math.round(g), Math.round(b), a ];
88        };
89
90        var HEXtoRGB = function(hex) {
91            if (hex.length === 3) hex += "f";
92            if (hex.length === 4) {
93                var h0 = hex.charAt(0), h1 = hex.charAt(1), h2 = hex.charAt(2), h3 = hex.charAt(3);
94                hex = h0 + h0 + h1 + h1 + h2 + h2 + h3 + h3;
95            }
96            if (hex.length === 6) hex += "ff";
97            var rgb = [];
98            for (var i = 0, l = hex.length; i < l; i += 2) rgb.push(parseInt(hex.substr(i, 2), 16) / (i === 6 ? 255 : 1));
99            return rgb;
100        };
101
102        // HSL to RGB conversion from:
103        // http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
104        // thank you!
105        var HUEtoRGB = function(p, q, t) {
106            if (t < 0) t += 1;
107            if (t > 1) t -= 1;
108            if (t < 1 / 6) return p + (q - p) * 6 * t;
109            if (t < 1 / 2) return q;
110            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
111            return p;
112        };
113
114        var HSLtoRGB = function(h, s, l, a) {
115            var r, b, g;
116            if (a == null || a === "") a = 1;
117            h = parseFloat(h) / 360;
118            s = parseFloat(s) / 100;
119            l = parseFloat(l) / 100;
120            a = parseFloat(a) / 1;
121            if (h > 1 || h < 0 || s > 1 || s < 0 || l > 1 || l < 0 || a > 1 || a < 0) return null;
122            if (s === 0) {
123                r = b = g = l;
124            } else {
125                var q = l < .5 ? l * (1 + s) : l + s - l * s;
126                var p = 2 * l - q;
127                r = HUEtoRGB(p, q, h + 1 / 3);
128                g = HUEtoRGB(p, q, h);
129                b = HUEtoRGB(p, q, h - 1 / 3);
130            }
131            return [ r * 255, g * 255, b * 255, a ];
132        };
133
134        var keys = [];
135
136        for (var c in colors) keys.push(c);
137
138        var shex = "(?:#([a-f0-9]{3,8}))", sval = "\\s*([.\\d%]+)\\s*", sop = "(?:,\\s*([.\\d]+)\\s*)?", slist = "\\(" + [ sval, sval, sval ] + sop + "\\)", srgb = "(?:rgb)a?", shsl = "(?:hsl)a?", skeys = "(" + keys.join("|") + ")";
139
140        var xhex = RegExp(shex, "i"), xrgb = RegExp(srgb + slist, "i"), xhsl = RegExp(shsl + slist, "i");
141
142        var color = function(input, array) {
143            if (input == null) return null;
144            input = (input + "").replace(/\s+/, "");
145            var match = colors[input];
146            if (match) {
147                return color(match, array);
148            } else if (match = input.match(xhex)) {
149                input = HEXtoRGB(match[1]);
150            } else if (match = input.match(xrgb)) {
151                input = match.slice(1);
152            } else if (match = input.match(xhsl)) {
153                input = HSLtoRGB.apply(null, match.slice(1));
154            } else return null;
155            if (!(input && (input = RGBtoRGB.apply(null, input)))) return null;
156            if (array) return input;
157            if (input[3] === 1) input.splice(3, 1);
158            return "rgb" + (input.length === 4 ? "a" : "") + "(" + input + ")";
159        };
160
161        color.x = RegExp([ skeys, shex, srgb + slist, shsl + slist ].join("|"), "gi");
162
163        module.exports = color;
164    },
165    "2": function(require, module, exports, global) {
166        /*
167requestFrame / cancelFrame
168*/
169                "use strict";
170
171        var array = require("3");
172
173        var requestFrame = global.requestAnimationFrame || global.webkitRequestAnimationFrame || global.mozRequestAnimationFrame || global.oRequestAnimationFrame || global.msRequestAnimationFrame || function(callback) {
174            return setTimeout(callback, 1e3 / 60);
175        };
176
177        var callbacks = [];
178
179        var iterator = function(time) {
180            var split = callbacks.splice(0, callbacks.length);
181            for (var i = 0, l = split.length; i < l; i++) split[i](time || (time = +new Date()));
182        };
183
184        var cancel = function(callback) {
185            var io = array.indexOf(callbacks, callback);
186            if (io > -1) callbacks.splice(io, 1);
187        };
188
189        var request = function(callback) {
190            var i = callbacks.push(callback);
191            if (i === 1) requestFrame(iterator);
192            return function() {
193                cancel(callback);
194            };
195        };
196
197        exports.request = request;
198
199        exports.cancel = cancel;
200    },
201    "3": function(require, module, exports, global) {
202        /*
203array
204 - array es5 shell
205*/
206                "use strict";
207
208        var array = require("4")["array"];
209
210        var names = ("pop,push,reverse,shift,sort,splice,unshift,concat,join,slice,toString,indexOf,lastIndexOf,forEach,every,some" + ",filter,map,reduce,reduceRight").split(",");
211
212        for (var methods = {}, i = 0, name, method; name = names[i++]; ) if (method = Array.prototype[name]) methods[name] = method;
213
214        if (!methods.filter) methods.filter = function(fn, context) {
215            var results = [];
216            for (var i = 0, l = this.length >>> 0; i < l; i++) if (i in this) {
217                var value = this[i];
218                if (fn.call(context, value, i, this)) results.push(value);
219            }
220            return results;
221        };
222
223        if (!methods.indexOf) methods.indexOf = function(item, from) {
224            for (var l = this.length >>> 0, i = from < 0 ? Math.max(0, l + from) : from || 0; i < l; i++) {
225                if (i in this && this[i] === item) return i;
226            }
227            return -1;
228        };
229
230        if (!methods.map) methods.map = function(fn, context) {
231            var length = this.length >>> 0, results = Array(length);
232            for (var i = 0, l = length; i < l; i++) {
233                if (i in this) results[i] = fn.call(context, this[i], i, this);
234            }
235            return results;
236        };
237
238        if (!methods.every) methods.every = function(fn, context) {
239            for (var i = 0, l = this.length >>> 0; i < l; i++) {
240                if (i in this && !fn.call(context, this[i], i, this)) return false;
241            }
242            return true;
243        };
244
245        if (!methods.some) methods.some = function(fn, context) {
246            for (var i = 0, l = this.length >>> 0; i < l; i++) {
247                if (i in this && fn.call(context, this[i], i, this)) return true;
248            }
249            return false;
250        };
251
252        if (!methods.forEach) methods.forEach = function(fn, context) {
253            for (var i = 0, l = this.length >>> 0; i < l; i++) {
254                if (i in this) fn.call(context, this[i], i, this);
255            }
256        };
257
258        var toString = Object.prototype.toString;
259
260        array.isArray = Array.isArray || function(self) {
261            return toString.call(self) === "[object Array]";
262        };
263
264        module.exports = array.implement(methods);
265    },
266    "4": function(require, module, exports, global) {
267        /*
268shell
269*/
270                "use strict";
271
272        var prime = require("5"), type = require("6");
273
274        var slice = Array.prototype.slice;
275
276        var ghost = prime({
277            constructor: function ghost(self) {
278                this.valueOf = function() {
279                    return self;
280                };
281                this.toString = function() {
282                    return self + "";
283                };
284                this.is = function(object) {
285                    return self === object;
286                };
287            }
288        });
289
290        var shell = function(self) {
291            if (self == null || self instanceof ghost) return self;
292            var g = shell[type(self)];
293            return g ? new g(self) : self;
294        };
295
296        var register = function() {
297            var g = prime({
298                inherits: ghost
299            });
300            return prime({
301                constructor: function(self) {
302                    return new g(self);
303                },
304                define: function(key, descriptor) {
305                    var method = descriptor.value;
306                    this[key] = function(self) {
307                        return arguments.length > 1 ? method.apply(self, slice.call(arguments, 1)) : method.call(self);
308                    };
309                    g.prototype[key] = function() {
310                        return shell(method.apply(this.valueOf(), arguments));
311                    };
312                    prime.define(this.prototype, key, descriptor);
313                    return this;
314                }
315            });
316        };
317
318        for (var types = "string,number,array,object,date,function,regexp".split(","), i = types.length; i--; ) shell[types[i]] = register();
319
320        module.exports = shell;
321    },
322    "5": function(require, module, exports, global) {
323        /*
324prime
325 - prototypal inheritance
326*/
327                "use strict";
328
329        var has = function(self, key) {
330            return Object.hasOwnProperty.call(self, key);
331        };
332
333        var each = function(object, method, context) {
334            for (var key in object) if (method.call(context, object[key], key, object) === false) break;
335            return object;
336        };
337
338        if (!{
339            valueOf: 0
340        }.propertyIsEnumerable("valueOf")) {
341            // fix for stupid IE enumeration bug
342            var buggy = "constructor,toString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString".split(",");
343            var proto = Object.prototype;
344            each = function(object, method, context) {
345                for (var key in object) if (method.call(context, object[key], key, object) === false) return object;
346                for (var i = 0; key = buggy[i]; i++) {
347                    var value = object[key];
348                    if ((value !== proto[key] || has(object, key)) && method.call(context, value, key, object) === false) break;
349                }
350                return object;
351            };
352        }
353
354        var create = Object.create || function(self) {
355            var constructor = function() {};
356            constructor.prototype = self;
357            return new constructor();
358        };
359
360        var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
361
362        var define = Object.defineProperty;
363
364        try {
365            var obj = {
366                a: 1
367            };
368            getOwnPropertyDescriptor(obj, "a");
369            define(obj, "a", {
370                value: 2
371            });
372        } catch (e) {
373            getOwnPropertyDescriptor = function(object, key) {
374                return {
375                    value: object[key]
376                };
377            };
378            define = function(object, key, descriptor) {
379                object[key] = descriptor.value;
380                return object;
381            };
382        }
383
384        var implement = function(proto) {
385            each(proto, function(value, key) {
386                if (key !== "constructor" && key !== "define" && key !== "inherits") this.define(key, getOwnPropertyDescriptor(proto, key) || {
387                    writable: true,
388                    enumerable: true,
389                    configurable: true,
390                    value: value
391                });
392            }, this);
393            return this;
394        };
395
396        var prime = function(proto) {
397            var superprime = proto.inherits;
398            // if our nice proto object has no own constructor property
399            // then we proceed using a ghosting constructor that all it does is
400            // call the parent's constructor if it has a superprime, else an empty constructor
401            // proto.constructor becomes the effective constructor
402            var constructor = has(proto, "constructor") ? proto.constructor : superprime ? function() {
403                return superprime.apply(this, arguments);
404            } : function() {};
405            if (superprime) {
406                var superproto = superprime.prototype;
407                // inherit from superprime
408                var cproto = constructor.prototype = create(superproto);
409                // setting constructor.parent to superprime.prototype
410                // because it's the shortest possible absolute reference
411                constructor.parent = superproto;
412                cproto.constructor = constructor;
413            }
414            // inherit (kindof inherit) define
415            constructor.define = proto.define || superprime && superprime.define || function(key, descriptor) {
416                define(this.prototype, key, descriptor);
417                return this;
418            };
419            // copy implement (this should never change)
420            constructor.implement = implement;
421            // finally implement proto and return constructor
422            return constructor.implement(proto);
423        };
424
425        prime.has = has;
426
427        prime.each = each;
428
429        prime.create = create;
430
431        prime.define = define;
432
433        module.exports = prime;
434    },
435    "6": function(require, module, exports, global) {
436        /*
437type
438*/
439                "use strict";
440
441        var toString = Object.prototype.toString, types = /number|object|array|string|function|date|regexp|boolean/;
442
443        var type = function(object) {
444            if (object == null) return "null";
445            var string = toString.call(object).slice(8, -1).toLowerCase();
446            if (string === "number" && isNaN(object)) return "null";
447            if (types.test(string)) return string;
448            return "object";
449        };
450
451        module.exports = type;
452    },
453    "7": function(require, module, exports, global) {
454        /*
455MooFx
456*/
457                "use strict";
458
459        // requires
460        var color = require("1"), frame = require("2");
461
462        var cancelFrame = frame.cancel, requestFrame = frame.request;
463
464        var prime = require("5"), array = require("3"), string = require("8");
465
466        var camelize = string.camelize, clean = string.clean, capitalize = string.capitalize;
467
468        var map = array.map, forEach = array.forEach, indexOf = array.indexOf;
469
470        var elements = require("a");
471
472        var fx = require("b");
473
474        // util
475        var hyphenated = {};
476
477        var hyphenate = function(self) {
478            return hyphenated[self] || (hyphenated[self] = string.hyphenate(self));
479        };
480
481        var round = function(n) {
482            return Math.round(n * 1e3) / 1e3;
483        };
484
485        // compute > node > property
486        var compute = global.getComputedStyle ? function(node) {
487            var cts = getComputedStyle(node);
488            return function(property) {
489                return cts ? cts.getPropertyValue(hyphenate(property)) : "";
490            };
491        } : /*(css3)?*/ function(node) {
492            var cts = node.currentStyle;
493            return function(property) {
494                return cts ? cts[camelize(property)] : "";
495            };
496        };
497
498        /*:null*/
499        // pixel ratio retriever
500        var test = document.createElement("div");
501
502        var cssText = "border:none;margin:none;padding:none;visibility:hidden;position:absolute;height:0;";
503
504        // returns the amount of pixels that takes to make one of the unit
505        var pixelRatio = function(element, u) {
506            var parent = element.parentNode, ratio = 1;
507            if (parent) {
508                test.style.cssText = cssText + ("width:100" + u + ";");
509                parent.appendChild(test);
510                ratio = test.offsetWidth / 100;
511                parent.removeChild(test);
512            }
513            return ratio;
514        };
515
516        // mirror 4 values
517        var mirror4 = function(values) {
518            var length = values.length;
519            if (length === 1) values.push(values[0], values[0], values[0]); else if (length === 2) values.push(values[0], values[1]); else if (length === 3) values.push(values[1]);
520            return values;
521        };
522
523        // regular expressions strings
524        var sLength = "([-.\\d]+)(%|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vm)", sLengthNum = sLength + "?", sBorderStyle = "none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset|inherit";
525
526        // regular expressions
527        var rgLength = RegExp(sLength, "g"), rLengthNum = RegExp(sLengthNum), rg
527LengthNum = RegExp(sLengthNum, "g"), rBorderStyle = RegExp(sBorderStyle);
528
529        // normalize > css
530        var parseString = function(value) {
531            return value == null ? "" : value + "";
532        };
533
534        var parseOpacity = function(value, normalize) {
535            if (value == null || value === "") return normalize ? "1" : "";
536            return isFinite(value = +value) ? value < 0 ? "0" : value + "" : "1";
537        };
538
539        try {
540            test.style.color = "rgba(0,0,0,0.5)";
541        } catch (e) {}
542
543        var rgba = /^rgba/.test(test.style.color);
544
545        var parseColor = function(value, normalize) {
546            var black = "rgba(0,0,0,1)", c;
547            if (!value || !(c = color(value, true))) return normalize ? black : "";
548            if (normalize) return "rgba(" + c + ")";
549            var alpha = c[3];
550            if (alpha === 0) return "transparent";
551            return !rgba || alpha === 1 ? "rgb(" + c.slice(0, 3) + ")" : "rgba(" + c + ")";
552        };
553
554        var parseLength = function(value, normalize) {
555            if (value == null || value === "") return normalize ? "0px" : "";
556            var match = string.match(value, rLengthNum);
557            return match ? match[1] + (match[2] || "px") : value;
558        };
559
560        var parseBorderStyle = function(value, normalize) {
561            if (value == null || value === "") return normalize ? "none" : "";
562            var match = value.match(rBorderStyle);
563            return match ? value : normalize ? "none" : "";
564        };
565
566        var parseBorder = function(value, normalize) {
567            var normalized = "0px none rgba(0,0,0,1)";
568            if (value == null || value === "") return normalize ? normalized : "";
569            if (value === 0 || value === "none") return normalize ? normalized : value + "";
570            var c;
571            value = value.replace(color.x, function(match) {
572                c = match;
573                return "";
574            });
575            var s = value.match(rBorderStyle), l = value.match(rgLengthNum);
576            return clean([ parseLength(l ? l[0] : "", normalize), parseBorderStyle(s ? s[0] : "", normalize), parseColor(c, normalize) ].join(" "));
577        };
578
579        var parseShort4 = function(value, normalize) {
580            if (value == null || value === "") return normalize ? "0px 0px 0px 0px" : "";
581            return clean(mirror4(map(clean(value).split(" "), function(v) {
582                return parseLength(v, normalize);
583            })).join(" "));
584        };
585
586        var parseShadow = function(value, normalize, len) {
587            var transparent = "rgba(0,0,0,0)", normalized = len === 3 ? transparent + " 0px 0px 0px" : transparent + " 0px 0px 0px 0px";
588            if (value == null || value === "") return normalize ? normalized : "";
589            if (value === "none") return normalize ? normalized : value;
590            var colors = [], value = clean(value).replace(color.x, function(match) {
591                colors.push(match);
592                return "";
593            });
594            return map(value.split(","), function(shadow, i) {
595                var c = parseColor(colors[i], normalize), inset = /inset/.test(shadow), lengths = shadow.match(rgLengthNum) || [ "0px" ];
596                lengths = map(lengths, function(m) {
597                    return parseLength(m, normalize);
598                });
599                while (lengths.length < len) lengths.push("0px");
600                var ret = inset ? [ "inset", c ] : [ c ];
601                return ret.concat(lengths).join(" ");
602            }).join(", ");
603        };
604
605        var parse = function(value, normalize) {
606            if (value == null || value === "") return "";
607            // cant normalize "" || null
608            return value.replace(color.x, function(match) {
609                return parseColor(match, normalize);
610            }).replace(rgLength, function(match) {
611                return parseLength(match, normalize);
612            });
613        };
614
615        // get && set
616        var getters = {}, setters = {}, parsers = {}, aliases = {};
617
618        var getter = function(key) {
619            return getters[key] || (getters[key] = function() {
620                var alias = aliases[key] || key, parser = parsers[key] || parse;
621                return function() {
622                    return parser(compute(this)(alias), true);
623                };
624            }());
625        };
626
627        var setter = function(key) {
628            return setters[key] || (setters[key] = function() {
629                var alias = aliases[key] || key, parser = parsers[key] || parse;
630                return function(value) {
631                    this.style[alias] = parser(value, false);
632                };
633            }());
634        };
635
636        // parsers
637        var trbl = [ "Top", "Right", "Bottom", "Left" ], tlbl = [ "TopLeft", "TopRight", "BottomRight", "BottomLeft" ];
638
639        forEach(trbl, function(d) {
640            var bd = "border" + d;
641            forEach([ "margin" + d, "padding" + d, bd + "Width", d.toLowerCase() ], function(n) {
642                parsers[n] = parseLength;
643            });
644            parsers[bd + "Color"] = parseColor;
645            parsers[bd + "Style"] = parseBorderStyle;
646            // borderDIR
647            parsers[bd] = parseBorder;
648            getters[bd] = function() {
649                return [ getter(bd + "Width").call(this), getter(bd + "Style").call(this), getter(bd + "Color").call(this) ].join(" ");
650            };
651        });
652
653        forEach(tlbl, function(d) {
654            parsers["border" + d + "Radius"] = parseLength;
655        });
656
657        parsers.color = parsers.backgroundColor = parseColor;
658
659        parsers.width = parsers.height = parsers.minWidth = parsers.minHeight = parsers.maxWidth = parsers.maxHeight = parsers.fontSize = parsers.backgroundSize = parseLength;
660
661        // margin + padding
662        forEach([ "margin", "padding" ], function(name) {
663            parsers[name] = parseShort4;
664            getters[name] = function() {
665                return map(trbl, function(d) {
666                    return getter(name + d).call(this);
667                }, this).join(" ");
668            };
669        });
670
671        // borders
672        // borderDIRWidth, borderDIRStyle, borderDIRColor
673        parsers.borderWidth = parseShort4;
674
675        parsers.borderStyle = function(value, normalize) {
676            if (value == null || value === "") return normalize ? mirror4([ "none" ]).join(" ") : "";
677            value = clean(value).split(" ");
678            return clean(mirror4(map(value, function(v) {
679                parseBorderStyle(v, normalize);
680            })).join(" "));
681        };
682
683        parsers.borderColor = function(value, normalize) {
684            if (!value || !(value = string.match(value, color.x))) return normalize ? mirror4([ "rgba(0,0,0,1)" ]).join(" ") : "";
685            return clean(mirror4(map(value, function(v) {
686                return parseColor(v, normalize);
687            })).join(" "));
688        };
689
690        forEach([ "Width", "Style", "Color" ], function(name) {
691            getters["border" + name] = function() {
692                return map(trbl, function(d) {
693                    return getter("border" + d + name).call(this);
694                }, this).join(" ");
695            };
696        });
697
698        // borderRadius
699        parsers.borderRadius = parseShort4;
700
701        getters.borderRadius = function() {
702            return map(tlbl, function(d) {
703                return getter("border" + d + "Radius").call(this);
704            }, this).join(" ");
705        };
706
707        // border
708        parsers.border = parseBorder;
709
710        getters.border = function() {
711            var pvalue;
712            for (var i = 0; i < trbl.length; i++) {
713                var value = getter("border" + trbl[i]).call(this);
714                if (pvalue && value !== pvalue) return null;
715                pvalue = value;
716            }
717            return pvalue;
718        };
719
720        // zIndex
721        parsers.zIndex = parseString;
722
723        // opacity
724        parsers.opacity = parseOpacity;
725
726        /*(css3)?*/
727        var filterName = test.style.MsFilter != null && "MsFilter" || test.style.filter != null && "filter";
728
729        if (filterName && test.style.opacity == null) {
730            var matchOp = /alpha\(opacity=([\d.]+)\)/i;
731            setters.opacity = function(value) {
732                value = (value = parseOpacity(value)) === "1" ? "" : "alpha(opacity=" + Math.round(value * 100) + ")";
733                var filter = compute(this)(filterName);
734                return this.style[filterName] = matchOp.test(filter) ? filter.replace(matchOp, value) : filter + " " + value;
735            };
736            getters.opacity = function() {
737                var match = compute(this)(filterName).match(matchOp);
738                return (!match ? 1 : match[1] / 100) + "";
739            };
740        }
741
742        /*:*/
743        var parseBoxShadow = parsers.boxShadow = function(value, normalize) {
744            return parseShadow(value, normalize, 4);
745        };
746
747        var parseTextShadow = parsers.textShadow = function(value, normalize) {
748            return parseShadow(value, normalize, 3);
749        };
750
751        // Aliases
752        forEach([ "Webkit", "Moz", "ms", "O", null ], function(prefix) {
753            forEach([ "transition", "transform", "transformOrigin", "transformStyle", "perspective", "perspectiveOrigin", "backfaceVisibility" ], function(style) {
754                var cc = prefix ? prefix + capitalize(style) : style;
755                if (prefix === "ms") hyphenated[cc] = "-ms-" + hyphenate(style);
756                if (test.style[cc] != null) aliases[style] = cc;
757            });
758        });
759
760        var transitionName = aliases.transition, transformName = aliases.transform;
761
762        // manually disable css3 transitions in Opera, because they do not work properly.
763        if (transitionName === "OTransition") transitionName = null;
764
765        // this takes care of matrix decomposition on browsers that support only 2d transforms but no CSS3 transitions.
766        // basically, IE9 (and Opera as well, since we disabled CSS3 transitions manually)
767        var parseTransform2d, Transform2d;
768
769        /*(css3)?*/
770        if (!transitionName && transformName) (function() {
771            var unmatrix = require("d");
772            var v = "\\s*([-\\d\\w.]+)\\s*";
773            var rMatrix = RegExp("matrix\\(" + [ v, v, v, v, v, v ] + "\\)");
774            var decomposeMatrix = function(matrix) {
775                var d = unmatrix.apply(null, matrix.match(rMatrix).slice(1)) || [ [ 0, 0 ], 0, 0, [ 0, 0 ] ];
776                return [ "translate(" + map(d[0], function(v) {
777                    return round(v) + "px";
778                }) + ")", "rotate(" + round(d[1] * 180 / Math.PI) + "deg)", "skewX(" + round(d[2] * 180 / Math.PI) + "deg)", "scale(" + map(d[3], round) + ")" ].join(" ");
779            };
780            var def0px = function(value) {
781                return value || "0px";
782            }, def1 = function(value) {
783                return value || "1";
784            }, def0deg = function(value) {
785                return value || "0deg";
786            };
787            var transforms = {
788                translate: function(value) {
789                    if (!value) value = "0px,0px";
790                    var values = value.split(",");
791                    if (!values[1]) values[1] = "0px";
792                    return map(values, clean) + "";
793                },
794                translateX: def0px,
795                translateY: def0px,
796                scale: function(value) {
797                    if (!value) value = "1,1";
798                    var values = value.split(",");
799                    if (!values[1]) values[1] = values[0];
800                    return map(values, clean) + "";
801                },
802                scaleX: def1,
803                scaleY: def1,
804                rotate: def0deg,
805                skewX: def0deg,
806                skewY: def0deg
807            };
808            Transform2d = prime({
809                constructor: function(transform) {
810                    var names = this.names = [];
811                    var values = this.values = [];
812                    transform.replace(/(\w+)\(([-.\d\s\w,]+)\)/g, function(match, name, value) {
813                        names.push(name);
814                        values.push(value);
815                    });
816                },
817                identity: function() {
818                    var functions = [];
819                    forEach(this.names, function(name) {
820                        var fn = transforms[name];
821                        if (fn) functions.push(name + "(" + fn() + ")");
822                    });
823                    return functions.join(" ");
824                },
825                sameType: function(transformObject) {
826                    return this.names.toString() === transformObject.names.toString();
827                },
828                // this is, basically, cheating.
829                // retrieving the matrix value from the dom, rather than calculating it
830                decompose: function() {
831                    var transform = this.toString();
832                    test.style.cssText = cssText + hyphenate(transformName) + ":" + transform + ";";
833                    document.body.appendChild(test);
834                    var m = compute(test)(transformName);
835                    if (!m || m === "none") m = "matrix(1, 0, 0, 1, 0, 0)";
836                    document.body.removeChild(test);
837                    return decomposeMatrix(m);
838                }
839            });
840            Transform2d.prototype.toString = function(clean) {
841                var values = this.values, functions = [];
842                forEach(this.names, function(name, i) {
843                    var fn = transforms[name];
844                    if (!fn) return;
845                    var value = fn(values[i]);
846                    if (!clean || value !== fn()) functions.push(name + "(" + value + ")");
847                });
848                return functions.length ? functions.join(" ") : "none";
849            };
850            Transform2d.union = function(from, to) {
851                if (from === to) return;
852                // nothing to do
853                var fromMap, toMap;
854                if (from === "none") {
855                    toMap = new Transform2d(to);
856                    to = toMap.toString();
857                    from = toMap.identity();
858                    fromMap = new Transform2d(from);
859                } else if (to === "none") {
860                    fromMap = new Transform2d(from);
861                    from = fromMap.toString();
862                    to = fromMap.identity();
863                    toMap = new Transform2d(to);
864                } else {
865                    fromMap = new Transform2d(from);
866                    from = fromMap.toString();
867                    toMap = new Transform2d(to);
868                    to = toMap.toString();
869                }
870                if (from === to) return;
871                // nothing to do
872                if (!fromMap.sameType(toMap)) {
873                    from = fromMap.decompose();
874                    to = toMap.decompose();
875                }
876                if (from === to) return;
877                // nothing to do
878                return [ from, to ];
879            };
880            // this parser makes sure it never gets "matrix"
881            parseTransform2d = parsers.transform = function(transform) {
882                if (!transform || transform === "none") return "none";
883                return new Transform2d(rMatrix.test(transform) ? decomposeMatrix(transform) : transform).toString(true);
884            };
885            // this getter makes sure we read from the dom only the first time
886            // this way we save the actual transform and not "matrix"
887            // setting matrix() will use parseTransform2d as well, thus setting the decomposed matrix
888            getters.transform = function() {
889                var s = this.style;
890                return s[transformName] || (s[transformName] = parseTransform2d(compute(this)(transformName)));
891            };
892        })();
893
894        /*:*/
895        // tries to match from and to values
896        var prepare = function(node, property, to) {
897            var parser = parsers[property] || parse, from = getter(property).call(node), // "normalized" by the getter
898            to = parser(to, true);
899            // normalize parsed property
900            if (from === to) return;
901            if (parser === parseLength || parser === parseBorder || parser === parseShort4) {
902                var toAll = to.match(rgLength), i = 0;
903                // this should always match something
904                if (toAll) from = from.replace(rgLength, function(fromFull, fromValue, fromUnit) {
905                    var toFull = toAll[i++], toMatched = toFull.match(rLengthNum), toUnit = toMatched[2];
906                    if (fromUnit !== toUnit) {
907                        var fromPixels = fromUnit === "px" ? fromValue : pixelRatio(node, fromUnit) * fromValue;
908                        return round(fromPixels / pixelRatio(node, toUnit)) + toUnit;
909                    }
910                    return fromFull;
911                });
912                if (i > 0) setter(property).call(node, from);
913            } else if (parser === parseTransform2d) {
914                // IE9/Opera
915                return Transform2d.union(from, to);
916            }
917            /*:*/
918            return from !== to ? [ from, to ] : null;
919        };
920
921        // BrowserAnimation
922        var BrowserAnimation = prime({
923            inherits: fx,
924            constructor: function BrowserAnimation(node, property) {
925                var _getter = getter(property), _setter = setter(property);
926                this.get = function() {
927                    return _getter.call(node);
928                };
929                this.set = function(value) {
930                    return _setter.call(node, value);
931                };
932                BrowserAnimation.parent.constructor.call(this, this.set);
933                this.node = node;
934                this.property = property;
935            }
936        });
937
938        var JSAnimation;
939
940        /*(css3)?*/
941        JSAnimation = prime({
942            inherits: BrowserAnimation,
943            constructor: function JSAnimation() {
944                return JSAnimation.parent.constructor.apply(this, arguments);
945            },
946            start: function(to) {
947                this.stop();
948                if (this.duration === 0) {
949                    this.cancel(to);
950                    return this;
951                }
952                var fromTo = prepare(this.node, this.property, to);
953                if (!fromTo) {
954                    this.cancel(to);
955                    return this;
956                }
957                JSAnimation.parent.start.apply(this, fromTo);
958                if (!this.cancelStep) return this;
959                // the animation would have started but we need additional checks
960                var parser = parsers[this.property] || parse;
961                // complex interpolations JSAnimation can't handle
962                // even CSS3 animation gracefully fail with some of those edge cases
963                // other "simple" properties, such as `border` can have different templates
964                // because of string properties like "solid" and "dashed"
965                if ((parser === parseBoxShadow || parser === parseTextShadow || parser === parse) && this.templateFrom !== this.templateTo) {
966                    this.cancelStep();
967                    delete this.cancelStep;
968                    this.cancel(to);
969                }
970                return this;
971            },
972            parseEquation: function(equation) {
973                if (typeof equation === "string") return JSAnimation.parent.parseEquation.call(this, equation);
974            }
975        });
976
977        /*:*/
978        // CSSAnimation
979        var remove3 = function(value, a, b, c) {
980            var index = indexOf(a, value);
981            if (index !== -1) {
982                a.splice(index, 1);
983                b.splice(index, 1);
984                c.splice(index, 1);
985            }
986        };
987
988        var CSSAnimation = prime({
989            inherits: BrowserAnimation,
990            constructor: function CSSAnimation(node, property) {
991                CSSAnimation.parent.constructor.call(this, node, property);
992                this.hproperty = hyphenate(aliases[property] || property);
993                var self = this;
994                this.bSetTransitionCSS = function(time) {
995                    self.setTransitionCSS(time);
996                };
997                this.bSetStyleCSS = function(time) {
998                    self.setStyleCSS(time);
999                };
1000                this.bComplete = function() {
1001                    self.complete();
1002                };
1003            },
1004            start: function(to) {
1005                this.stop();
1006                if (this.duration === 0) {
1007                    this.cancel(to);
1008                    return this;
1009                }
1010                var fromTo = prepare(this.node, this.property, to);
1011                if (!fromTo) {
1012                    this.cancel(to);
1013                    return this;
1014                }
1015                this.to = fromTo[1];
1016                // setting transition styles immediately will make good browsers behave weirdly
1017                // because DOM changes are always deferred, so we requestFrame
1018                this.cancelSetTransitionCSS = requestFrame(this.bSetTransitionCSS);
1019                return this;
1020            },
1021            setTransitionCSS: function(time) {
1022                delete this.cancelSetTransitionCSS;
1023                this.resetCSS(true);
1024                // firefox flickers if we set css for transition as well as styles at the same time
1025                // so, other than deferring transition styles we defer actual styles as well on a requestFrame
1026                this.cancelSetStyleCSS = requestFrame(this.bSetStyleCSS);
1027            },
1028            setStyleCSS: function(time) {
1029                delete this.cancelSetStyleCSS;
1030                var duration = this.duration;
1031                // we use setTimeout instead of transitionEnd because some browsers (looking at you foxy)
1032                // incorrectly set event.propertyName, so we cannot check which animation we are canceling
1033                this.cancelComplete = setTimeout(this.bComplete, duration);
1034                this.endTime = time + duration;
1035                this.set(this.to);
1036            },
1037            complete: function() {
1038                delete this.cancelComplete;
1039                this.resetCSS();
1040                this.callback(this.endTime);
1041            },
1042            stop: function(hard) {
1043                if (this.cancelExit) {
1044                    this.cancelExit();
1045                    delete this.cancelExit;
1046                } else if (this.cancelSetTransitionCSS) {
1047                    // if cancelSetTransitionCSS is set, means nothing is set yet
1048                    this.cancelSetTransitionCSS();
1049                    //so we cancel and we're good
1050                    delete this.cancelSetTransitionCSS;
1051                } else if (this.cancelSetStyleCSS) {
1052                    // if cancelSetStyleCSS is set, means transition css has been set, but no actual styles.
1053                    this.cancelSetStyleCSS();
1054                    delete this.cancelSetStyleCSS;
1055                    // if its a hard stop (and not another start on top of the current animation)
1056                    // we need to reset the transition CSS
1057                    if (hard) this.resetCSS();
1058                } else if (this.cancelComplete) {
1059                    // if cancelComplete is set, means style and transition css have been set, not yet completed.
1060                    clearTimeout(this.cancelComplete);
1061                    delete this.cancelComplete;
1062                    // if its a hard stop (and not another start on top of the current animation)
1063                    // we need to reset the transition CSS set the current animation styles
1064                    if (hard) {
1065                        this.resetCSS();
1066                        this.set(this.get());
1067                    }
1068                }
1069                return this;
1070            },
1071            resetCSS: function(inclusive) {
1072                var rules = compute(this.node), properties = (rules(transitionName + "Property").replace(/\s+/g, "") || "all").split(","), durations = (rules(transitionName + "Duration").replace(/\s+/g, "") || "0s").split(","), equations = (rules(transitionName + "TimingFunction").replace(/\s+/g, "") || "ease").match(/cubic-bezier\([\d-.,]+\)|([a-z-]+)/g);
1073                remove3("all", properties, durations, equations);
1074                remove3(this.hproperty, properties, durations, equations);
1075                if (inclusive) {
1076                    properties.push(this.hproperty);
1077                    durations.push(this.duration + "ms");
1078                    equations.push("cubic-bezier(" + this.equation + ")");
1079                }
1080                var nodeStyle = this.node.style;
1081                nodeStyle[transitionName + "Property"] = properties;
1082                nodeStyle[transitionName + "Duration"] = durations;
1083                nodeStyle[transitionName + "TimingFunction"] = equations;
1084            },
1085            parseEquation: function(equation) {
1086                if (typeof equation === "string") return CSSAnimation.parent.parseEquation.call(this, equation, true);
1087            }
1088        });
1089
1090        // elements methods
1091        var BaseAnimation = transitionName ? CSSAnimation : JSAnimation;
1092
1093        var moofx = function(x, y) {
1094            return typeof x === "function" ? fx(x) : elements(x, y);
1095        };
1096
1097        elements.implement({
1098            // {properties}, options or
1099            // property, value options
1100            animate: function(A, B, C) {
1101                var styles = A, options = B;
1102                if (typeof A === "string") {
1103                    styles = {};
1104                    styles[A] = B;
1105                    options = C;
1106                }
1107                if (options == null) options = {};
1108                var type = typeof options;
1109                options = type === "function" ? {
1110                    callback: options
1111                } : type === "string" || type === "number" ? {
1112                    duration: options
1113                } : options;
1114                var callback = options.callback || function() {}, completed = 0, length = 0;
1115                options.callback = function(t) {
1116                    if (++completed === length) callback(t);
1117                };
1118                for (var property in styles) {
1119                    var value = styles[property], property = camelize(property);
1120                    this.forEach(function(node) {
1121                        length++;
1122                        var self = elements(node), anims = self._animations || (self._animations = {});
1123                        var anim = anims[property] || (anims[property] = new BaseAnimation(node, property));
1124                        anim.setOptions(options).start(value);
1125                    });
1126                }
1127                return this;
1128            },
1129            // {properties} or
1130            // property, value
1131            style: function(A, B) {
1132                var styles = A;
1133                if (typeof A === "string") {
1134                    styles = {};
1135                    styles[A] = B;
1136                }
1137                for (var property in styles) {
1138                    var value = styles[property], set = setter(property = camelize(property));
1139                    this.forEach(function(node) {
1140                        var self = elements(node), anims = self._animations, anim;
1141                        if (anims && (anim = anims[property])) anim.stop(true);
1142                        set.call(node, value);
1143                    });
1144                }
1145                return this;
1146            },
1147            compute: function(property) {
1148                property = camelize(property);
1149                var node = this[0];
1150                // return default matrix for transform, instead of parsed (for consistency)
1151                if (property === "transform" && parseTransform2d) return compute(node)(transformName);
1152                var value = getter(property).call(node);
1153                // unit conversion to `px`
1154                return value != null ? value.replace(rgLength, function(match, value, unit) {
1155                    return unit === "px" ? match : pixelRatio(node, unit) * value + "px";
1156                }) : "";
1157            }
1158        });
1159
1160        moofx.parse = function(property, value, normalize) {
1161            return (parsers[camelize(property)] || parse)(value, normalize);
1162        };
1163
1164        module.exports = moofx;
1165    },
1166    "8": function(require, module, exports, global) {
1167        /*
1168string methods
1169 - string shell
1170*/
1171                "use strict";
1172
1173        var string = require("9");
1174
1175        string.implement({
1176            clean: function() {
1177                return string.trim((this + "").replace(/\s+/g, " "));
1178            },
1179            camelize: function() {
1180                return (this + "").replace(/-\D/g, function(match) {
1181                    return match.charAt(1).toUpperCase();
1182                });
1183            },
1184            hyphenate: function() {
1185                return (this + "").replace(/[A-Z]/g, function(match) {
1186                    return "-" + match.toLowerCase();
1187                });
1188            },
1189            capitalize: function() {
1190                return (this + "").replace(/\b[a-z]/g, function(match) {
1191                    return match.toUpperCase();
1192                });
1193            },
1194            escape: function() {
1195                return (this + "").replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
1196            },
1197            number: function() {
1198                return parseFloat(this);
1199            }
1200        });
1201
1202        if (typeof JSON !== "undefined") string.implement({
1203            decode: function() {
1204                return JSON.parse(this);
1205            }
1206        });
1207
1208        module.exports = string;
1209    },
1210    "9": function(require, module, exports, global) {
1211        /*
1212string
1213 - string es5 shell
1214*/
1215                "use strict";
1216
1217        var string = require("4")["string"];
1218
1219        var names = ("charAt,charCodeAt,concat,contains,endsWith,indexOf,lastIndexOf,localeCompare,match,replace,search,slice,split" + ",startsWith,substr,substring,toLocaleLowerCase,toLocaleUpperCase,toLowerCase,toString,toUpperCase,trim,valueOf").split(",");
1220
1221        for (var methods = {}, i = 0, name, method; name = names[i++]; ) if (method = String.prototype[name]) methods[name] = method;
1222
1223        if (!methods.trim) methods.trim = function() {
1224            return (this + "").replace(/^\s+|\s+$/g, "");
1225        };
1226
1227        module.exports = string.implement(methods);
1228    },
1229    a: function(require, module, exports, global) {
1230        /*
1231elements
1232*/
1233                "use strict";
1234
1235        var prime = require("5"), array = require("3").prototype;
1236
1237        // uniqueID
1238        var uniqueIndex = 0;
1239
1240        var uniqueID = function(n) {
1241            return n === global ? "global" : n.uniqueNumber || (n.uniqueNumber = "n:" + (uniqueIndex++).toString(36));
1242        };
1243
1244        var instances = {};
1245
1246        // elements prime
1247        var $ = prime({
1248            constructor: function $(n, context) {
1249                if (n == null) return this && this.constructor === $ ? new elements() : null;
1250                var self = n;
1251                if (n.constructor !== elements) {
1252                    self = new elements();
1253                    var uid;
1254                    if (typeof n === "string") {
1255                        if (!self.search) return null;
1256                        self[self.length++] = context || document;
1257                        return self.search(n);
1258                    }
1259                    if (n.nodeType || n === global) {
1260                        self[self.length++] = n;
1261                    } else if (n.length) {
1262                        // this could be an array, or any object with a length attribute,
1263                        // including another instance of elements from another interface.
1264                        var uniques = {};
1265                        for (var i = 0, l = n.length; i < l; i++) {
1266                            // perform elements flattening
1267                            var nodes = $(n[i], context);
1268                            if (nodes && nodes.length) for (var j = 0, k = nodes.length; j < k; j++) {
1269                                var node = nodes[j];
1270                                uid = uniqueID(node);
1271                                if (!uniques[uid]) {
1272                                    self[self.length++] = node;
1273                                    uniques[uid] = true;
1274                                }
1275                            }
1276                        }
1277                    }
1278                }
1279                if (!self.length) return null;
1280                // when length is 1 always use the same elements instance
1281                if (self.length === 1) {
1282                    uid = uniqueID(self[0]);
1283                    return instances[uid] || (instances[uid] = self);
1284                }
1285                return self;
1286            }
1287        });
1288
1289        var elements = prime({
1290            inherits: $,
1291            constructor: function elements() {
1292                this.length = 0;
1293            },
1294            unlink: function() {
1295                return this.map(function(node, i) {
1296                    delete instances[uniqueID(node)];
1297                    return node;
1298                });
1299            },
1300            // straight es5 prototypes (or emulated methods)
1301            forEach: array.forEach,
1302            map: array.map,
1303            filter: array.filter,
1304            every: array.every,
1305            some: array.some
1306        });
1307
1308        module.exports = $;
1309    },
1310    b: function(require, module, exports, global) {
1311        /*
1312fx
1313*/
1314                "use strict";
1315
1316        var prime = require("5"), requestFrame = require("2").request, bezier = require("c");
1317
1318        var map = require("3").map;
1319
1320        var sDuration = "([\\d.]+)(s|ms)?", sCubicBezier = "cubic-bezier\\(([-.\\d]+),([-.\\d]+),([-.\\d]+),([-.\\d]+)\\)";
1321
1322        var rDuration = RegExp(sDuration), rCubicBezier = RegExp(sCubicBezier), rgCubicBezier = RegExp(sCubicBezier, "g");
1323
1324        // equations collection
1325        var equations = {
1326            "default": "cubic-bezier(0.25, 0.1, 0.25, 1.0)",
1327            linear: "cubic-bezier(0, 0, 1, 1)",
1328            "ease-in": "cubic-bezier(0.42, 0, 1.0, 1.0)",
1329            "ease-out": "cubic-bezier(0, 0, 0.58, 1.0)",
1330            "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1.0)"
1331        };
1332
1333        equations.ease = equations["default"];
1334
1335        var compute = function(from, to, delta) {
1336            return (to - from) * delta + from;
1337        };
1338
1339        var divide = function(string) {
1340            var numbers = [];
1341            var template = (string + "").replace(/[-.\d]+/g, function(number) {
1342                numbers.push(+number);
1343                return "@";
1344            });
1345            return [ numbers, template ];
1346        };
1347
1348        var Fx = prime({
1349            constructor: function Fx(render, options) {
1350                // set options
1351                this.setOptions(options);
1352                // renderer
1353                this.render = render || function() {};
1354                // bound functions
1355                var self = this;
1356                this.bStep = function(t) {
1357                    return self.step(t);
1358                };
1359                this.bExit = function(time) {
1360                    self.exit(time);
1361                };
1362            },
1363            setOptions: function(options) {
1364                if (options == null) options = {};
1365                if (!(this.duration = this.parseDuration(options.duration || "500ms"))) throw new Error("invalid duration");
1366                if (!(this.equation = this.parseEquation(options.equation || "default"))) throw new Error("invalid equation");
1367                this.callback = options.callback || function() {};
1368                return this;
1369            },
1370            parseDuration: function(duration) {
1371                if (duration = (duration + "").match(rDuration)) {
1372                    var time = +duration[1], unit = duration[2] || "ms";
1373                    if (unit === "s") return time * 1e3;
1374                    if (unit === "ms") return time;
1375                }
1376            },
1377            parseEquation: function(equation, array) {
1378                var type = typeof equation;
1379                if (type === "function") {
1380                    // function
1381                    return equation;
1382                } else if (type === "string") {
1383                    // cubic-bezier string
1384                    equation = equations[equation] || equation;
1385                    var match = equation.replace(/\s+/g, "").match(rCubicBezier);
1386                    if (match) {
1387                        equation = map(match.slice(1), function(v) {
1388                            return +v;
1389                        });
1390                        if (array) return equation;
1391                        if (equation.toString() === "0,0,1,1") return function(x) {
1392                            return x;
1393                        };
1394                        type = "object";
1395                    }
1396                }
1397                if (type === "object") {
1398                    // array
1399                    return bezier(equation[0], equation[1], equation[2], equation[3], 1e3 / 60 / this.duration / 4);
1400                }
1401            },
1402            cancel: function(to) {
1403                this.to = to;
1404                this.cancelExit = requestFrame(this.bExit);
1405            },
1406            exit: function(time) {
1407                this.render(this.to);
1408                delete this.cancelExit;
1409                this.callback(time);
1410            },
1411            start: function(from, to) {
1412                this.stop();
1413                if (this.duration === 0) {
1414                    this.cancel(to);
1415                    return this;
1416                }
1417                this.isArray = false;
1418                this.isNumber = false;
1419                var fromType = typeof from, toType = typeof to;
1420                if (fromType === "object" && toType === "object") {
1421                    this.isArray = true;
1422                } else if (fromType === "number" && toType === "number") {
1423                    this.isNumber = true;
1424                }
1425                var from_ = divide(from), to_ = divide(to);
1426                this.from = from_[0];
1427                this.to = to_[0];
1428                this.templateFrom = from_[1];
1429                this.templateTo = to_[1];
1430                if (this.from.length !== this.to.length || this.from.toString() === this.to.toString()) {
1431                    this.cancel(to);
1432                    return this;
1433                }
1434                delete this.time;
1435                this.length = this.from.length;
1436                this.cancelStep = requestFrame(this.bStep);
1437                return this;
1438            },
1439            stop: function() {
1440                if (this.cancelExit) {
1441                    this.cancelExit();
1442                    delete this.cancelExit;
1443                } else if (this.cancelStep) {
1444                    this.cancelStep();
1445                    delete this.cancelStep;
1446                }
1447                return this;
1448            },
1449            step: function(now) {
1450                this.time || (this.time = now);
1451                var factor = (now - this.time) / this.duration;
1452                if (factor > 1) factor = 1;
1453                var delta = this.equation(factor), from = this.from, to = this.to, tpl = this.templateTo;
1454                for (var i = 0, l = this.length; i < l; i++) {
1455                    var f = from[i], t = to[i];
1456                    tpl = tpl.replace("@", t !== f ? compute(f, t, delta) : t);
1457                }
1458                this.render(this.isArray ? tpl.split(",") : this.isNumber ? +tpl : tpl, factor);
1459                if (factor !== 1) {
1460                    this.cancelStep = requestFrame(this.bStep);
1461                } else {
1462                    delete this.cancelStep;
1463                    this.callback(now);
1464                }
1465            }
1466        });
1467
1468        var fx = function(render) {
1469            var ffx = new Fx(render);
1470            return {
1471                start: function(from, to, options) {
1472                    var type = typeof options;
1473                    ffx.setOptions(type === "function" ? {
1474                        callback: options
1475                    } : type === "string" || type === "number" ? {
1476                        duration: options
1477                    } : options).start(from, to);
1478                    return this;
1479                },
1480                stop: function() {
1481                    ffx.stop();
1482                    return this;
1483                }
1484            };
1485        };
1486
1487        fx.prototype = Fx.prototype;
1488
1489        module.exports = fx;
1490    },
1491    c: function(require, module, exports, global) {
1492                module.exports = function(x1, y1, x2, y2, epsilon) {
1493            var curveX = function(t) {
1494                var v = 1 - t;
1495                return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
1496            };
1497            var curveY = function(t) {
1498                var v = 1 - t;
1499                return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
1500            };
1501            var derivativeCurveX = function(t) {
1502                var v = 1 - t;
1503                return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2;
1504            };
1505            return function(t) {
1506                var x = t, t0, t1, t2, x2, d2, i;
1507                // First try a few iterations of Newton's method -- normally very fast.
1508                for (t2 = x, i = 0; i < 8; i++) {
1509                    x2 = curveX(t2) - x;
1510                    if (Math.abs(x2) < epsilon) return curveY(t2);
1511                    d2 = derivativeCurveX(t2);
1512                    if (Math.abs(d2) < 1e-6) break;
1513                    t2 = t2 - x2 / d2;
1514                }
1515                t0 = 0, t1 = 1, t2 = x;
1516                if (t2 < t0) return curveY(t0);
1517                if (t2 >
1517 t1) return curveY(t1);
1518                // Fallback to the bisection method for reliability.
1519                while (t0 < t1) {
1520                    x2 = curveX(t2);
1521                    if (Math.abs(x2 - x) < epsilon) return curveY(t2);
1522                    if (x > x2) t0 = t2; else t1 = t2;
1523                    t2 = (t1 - t0) * .5 + t0;
1524                }
1525                // Failure
1526                return curveY(t2);
1527            };
1528        };
1529    },
1530    d: function(require, module, exports, global) {
1531        /*
1532Unmatrix 2d
1533 - a crude implementation of the slightly bugged pseudo code in http://www.w3.org/TR/css3-2d-transforms/#matrix-decomposition
1534*/
1535                "use strict";
1536
1537        // returns the length of the passed vector
1538        var length = function(a) {
1539            return Math.sqrt(a[0] * a[0] + a[1] * a[1]);
1540        };
1541
1542        // normalizes the length of the passed point to 1
1543        var normalize = function(a) {
1544            var l = length(a);
1545            return l ? [ a[0] / l, a[1] / l ] : [ 0, 0 ];
1546        };
1547
1548        // returns the dot product of the passed points
1549        var dot = function(a, b) {
1550            return a[0] * b[0] + a[1] * b[1];
1551        };
1552
1553        // returns the principal value of the arc tangent of
1554        // y/x, using the signs of both arguments to determine
1555        // the quadrant of the return value
1556        var atan2 = Math.atan2;
1557
1558        var combine = function(a, b, ascl, bscl) {
1559            return [ ascl * a[0] + bscl * b[0], ascl * a[1] + bscl * b[1] ];
1560        };
1561
1562        module.exports = function(a, b, c, d, tx, ty) {
1563            // Make sure the matrix is invertible
1564            if (a * d - b * c === 0) return false;
1565            // Take care of translation
1566            var translate = [ tx, ty ];
1567            // Put the components into a 2x2 matrix
1568            var m = [ [ a, b ], [ c, d ] ];
1569            // Compute X scale factor and normalize first row.
1570            var scale = [ length(m[0]) ];
1571            m[0] = normalize(m[0]);
1572            // Compute shear factor and make 2nd row orthogonal to 1st.
1573            var skew = dot(m[0], m[1]);
1574            m[1] = combine(m[1], m[0], 1, -skew);
1575            // Now, compute Y scale and normalize 2nd row.
1576            scale[1] = length(m[1]);
1577            // m[1] = normalize(m[1]) //
1578            skew /= scale[1];
1579            // Now, get the rotation out
1580            var rotate = atan2(m[0][1], m[0][0]);
1581            return [ translate, rotate, skew, scale ];
1582        };
1583    }
1584});
1585// packager build Mobile/Browser.Mobile Mobile/Click Mobile/Pinch Mobile/Swipe Mobile/Touchhold
1586/*
1587---
1588
1589name: Browser.Mobile
1590
1591description: Provides useful information about the browser environment
1592
1593authors: Christoph Pojer (@cpojer)
1594
1595license: MIT-style license.
1596
1597requires: [Core/Browser]
1598
1599provides: Browser.Mobile
1600
1601...
1602*/
1603
1604(function(){
1605
1606Browser.Device = {
1607    name: 'other'
1608};
1609
1610if (Browser.Platform.ios){
1611    var device = navigator.userAgent.toLowerCase().match(/(ip(ad|od|hone))/)[0];
1612
1613    Browser.Device[device] = true;
1614    Browser.Device.name = device;
1615}
1616
1617if (this.devicePixelRatio == 2)
1618    Browser.hasHighResolution = true;
1619
1620Browser.isMobile = !['mac', 'linux', 'win'].contains(Browser.Platform.name);
1621
1622}).call(this);
1623
1624
1625/*
1626---
1627
1628name: Element.defineCustomEvent
1629
1630description: Allows to create custom events based on other custom events.
1631
1632authors: Christoph Pojer (@cpojer)
1633
1634license: MIT-style license.
1635
1636requires: [Core/Element.Event]
1637
1638provides: Element.defineCustomEvent
1639
1640...
1641*/
1642
1643(function(){
1644
1645[Element, Window, Document].invoke('implement', {hasEvent: function(event){
1646    var events = this.retrieve('events'),
1647        list = (events && events[event]) ? events[event].values : null;
1648    if (list){
1649        var i = list.length;
1650        while (i--) if (i in list){
1651            return true;
1652        }
1653    }
1654    return false;
1655}});
1656
1657var wrap = function(custom, method, extended){
1658    method = custom[method];
1659    extended = custom[extended];
1660
1661    return function(fn, name){
1662        if (extended && !this.hasEvent(name)) extended.call(this, fn, name);
1663        if (method) method.call(this, fn, name);
1664    };
1665};
1666
1667var inherit = function(custom, base, method){
1668    return function(fn, name){
1669        base[method].call(this, fn, name);
1670        custom[method].call(this, fn, name);
1671    };
1672};
1673
1674var events = Element.Events;
1675
1676Element.defineCustomEvent = function(name, custom){
1677    var base = events[custom.base];
1678
1679    custom.onAdd = wrap(custom, 'onAdd', 'onSetup');
1680    custom.onRemove = wrap(custom, 'onRemove', 'onTeardown');
1681
1682    events[name] = base ? Object.append({}, custom, {
1683
1684        base: base.base,
1685
1686        condition: function(event, name){
1687            return (!base.condition || base.condition.call(this, event, name)) &&
1688                (!custom.condition || custom.condition.call(this, event, name));
1689        },
1690
1691        onAdd: inherit(custom, base, 'onAdd'),
1692        onRemove: inherit(custom, base, 'onRemove')
1693
1694    }) : custom;
1695
1696    return this;
1697};
1698
1699Element.enableCustomEvents = function(){
1700  Object.each(events, function(event, name){
1701    if (event.onEnable) event.onEnable.call(event, name);
1702  });
1703};
1704
1705Element.disableCustomEvents = function(){
1706  Object.each(events, function(event, name){
1707    if (event.onDisable) event.onDisable.call(event, name);
1708  });
1709};
1710
1711})();
1712
1713
1714/*
1715---
1716
1717name: Browser.Features.Touch
1718
1719description: Checks whether the used Browser has touch events
1720
1721authors: Christoph Pojer (@cpojer)
1722
1723license: MIT-style license.
1724
1725requires: [Core/Browser]
1726
1727provides: Browser.Features.Touch
1728
1729...
1730*/
1731
1732Browser.Features.Touch = (function(){
1733    try {
1734        document.createEvent('TouchEvent').initTouchEvent('touchstart');
1735        return true;
1736    } catch (exception){}
1737
1738    return false;
1739})();
1740
1741// Android doesn't have a touch delay and dispatchEvent does not fire the handler
1742Browser.Features.iOSTouch = (function(){
1743    var name = 'cantouch', // Name does not matter
1744        html = document.html,
1745        hasTouch = false;
1746
1747    if (!html.addEventListener) return false;
1748
1749    var handler = function(){
1750        html.removeEventListener(name, handler, true);
1751        hasTouch = true;
1752    };
1753
1754    try {
1755        html.addEventListener(name, handler, true);
1756        var event = document.createEvent('TouchEvent');
1757        event.initTouchEvent(name);
1758        html.dispatchEvent(event);
1759        return hasTouch;
1760    } catch (exception){}
1761
1762    handler(); // Remove listener
1763    return false;
1764})();
1765
1766
1767/*
1768---
1769
1770name: Touch
1771
1772description: Provides a custom touch event on mobile devices
1773
1774authors: Christoph Pojer (@cpojer)
1775
1776license: MIT-style license.
1777
1778requires: [Core/Element.Event, Custom-Event/Element.defineCustomEvent, Browser.Features.Touch]
1779
1780provides: Touch
1781
1782...
1783*/
1784
1785(function(){
1786
1787var preventDefault = function(event){
1788    if (!event.target || event.target.tagName.toLowerCase() != 'select')
1789        event.preventDefault();
1790};
1791
1792var disabled;
1793
1794Element.defineCustomEvent('touch', {
1795
1796    base: 'touchend',
1797
1798    condition: function(event){
1799        if (disabled || event.targetTouches.length != 0) return false;
1800
1801        var touch = event.changedTouches[0],
1802            target = document.elementFromPoint(touch.clientX, touch.clientY);
1803
1804        do {
1805            if (target == this) return true;
1806        } while (target && (target = target.parentNode));
1807
1808        return false;
1809    },
1810
1811    onSetup: function(){
1812        this.addEvent('touchstart', preventDefault);
1813    },
1814
1815    onTeardown: function(){
1816        this.removeEvent('touchstart', preventDefault);
1817    },
1818
1819    onEnable: function(){
1820        disabled = false;
1821    },
1822
1823    onDisable: function(){
1824        disabled = true;
1825    }
1826
1827});
1828
1829})();
1830
1831
1832/*
1833---
1834
1835name: Click
1836
1837description: Provides a replacement for click events on mobile devices
1838
1839authors: Christoph Pojer (@cpojer)
1840
1841license: MIT-style license.
1842
1843requires: [Touch]
1844
1845provides: Click
1846
1847...
1848*/
1849
1850if (Browser.Features.iOSTouch) (function(){
1851
1852var name = 'click';
1853delete Element.NativeEvents[name];
1854
1855Element.defineCustomEvent(name, {
1856
1857    base: 'touchend'
1858
1859});
1860
1861})();
1862
1863
1864/*
1865---
1866
1867name: Pinch
1868
1869description: Provides a custom pinch event for touch devices
1870
1871authors: Christopher Beloch (@C_BHole), Christoph Pojer (@cpojer)
1872
1873license: MIT-style license.
1874
1875requires: [Core/Element.Event, Custom-Event/Element.defineCustomEvent, Browser.Features.Touch]
1876
1877provides: Pinch
1878
1879...
1880*/
1881
1882if (Browser.Features.Touch) (function(){
1883
1884var name = 'pinch',
1885    thresholdKey = name + ':threshold',
1886    disabled, active;
1887
1888var events = {
1889
1890    touchstart: function(event){
1891        if (event.targetTouches.length == 2) active = true;
1892    },
1893
1894    touchmove: function(event){
1895        if (disabled || !active) return;
1896
1897        event.preventDefault();
1898
1899        var threshold = this.retrieve(thresholdKey, 0.5);
1900        if (event.scale < (1 + threshold) && event.scale > (1 - threshold)) return;
1901
1902        active = false;
1903        event.pinch = (event.scale > 1) ? 'in' : 'out';
1904        this.fireEvent(name, event);
1905    }
1906
1907};
1908
1909Element.defineCustomEvent(name, {
1910
1911    onSetup: function(){
1912        this.addEvents(events);
1913    },
1914
1915    onTeardown: function(){
1916        this.removeEvents(events);
1917    },
1918
1919    onEnable: function(){
1920        disabled = false;
1921    },
1922
1923    onDisable: function(){
1924        disabled = true;
1925    }
1926
1927});
1928
1929})();
1930
1931
1932/*
1933---
1934
1935name: Swipe
1936
1937description: Provides a custom swipe event for touch devices
1938
1939authors: Christopher Beloch (@C_BHole), Christoph Pojer (@cpojer), Ian Collins (@3n)
1940
1941license: MIT-style license.
1942
1943requires: [Core/Element.Event, Custom-Event/Element.defineCustomEvent, Browser.Features.Touch]
1944
1945provides: Swipe
1946
1947...
1948*/
1949
1950(function(){
1951
1952var name = 'swipe',
1953    distanceKey = name + ':distance',
1954    cancelKey = name + ':cancelVertical',
1955    dflt = 50;
1956
1957var start = {}, disabled, active;
1958
1959var clean = function(){
1960    active = false;
1961};
1962
1963var events = {
1964
1965    touchstart: function(event){
1966        if (event.touches.length > 1) return;
1967
1968        var touch = event.touches[0];
1969        active = true;
1970        start = {x: touch.pageX, y: touch.pageY};
1971    },
1972
1973    touchmove: function(event){
1974        if (disabled || !active) return;
1975
1976        var touch = event.changedTouches[0],
1977            end = {x: touch.pageX, y: touch.pageY};
1978        if (this.retrieve(cancelKey) && Math.abs(start.y - end.y) > 10){
1979            active = false;
1980            return;
1981        }
1982
1983        var distance = this.retrieve(distanceKey, dflt),
1984            delta = end.x - start.x,
1985            isLeftSwipe = delta < -distance,
1986            isRightSwipe = delta > distance;
1987
1988        if (!isRightSwipe && !isLeftSwipe)
1989            return;
1990
1991        event.preventDefault();
1992        active = false;
1993        event.direction = (isLeftSwipe ? 'left' : 'right');
1994        event.start = start;
1995        event.end = end;
1996
1997        this.fireEvent(name, event);
1998    },
1999
2000    touchend: clean,
2001    touchcancel: clean
2002
2003};
2004
2005Element.defineCustomEvent(name, {
2006
2007    onSetup: function(){
2008        this.addEvents(events);
2009    },
2010
2011    onTeardown: function(){
2012        this.removeEvents(events);
2013    },
2014
2015    onEnable: function(){
2016        disabled = false;
2017    },
2018
2019    onDisable: function(){
2020        disabled = true;
2021        clean();
2022    }
2023
2024});
2025
2026})();
2027
2028
2029/*
2030---
2031
2032name: Touchhold
2033
2034description: Provides a custom touchhold event for touch devices
2035
2036authors: Christoph Pojer (@cpojer)
2037
2038license: MIT-style license.
2039
2040requires: [Core/Element.Event, Custom-Event/Element.defineCustomEvent, Browser.Features.Touch]
2041
2042provides: Touchhold
2043
2044...
2045*/
2046
2047(function(){
2048
2049var name = 'touchhold',
2050    delayKey = name + ':delay',
2051    disabled, timer;
2052
2053var clear = function(e){
2054    clearTimeout(timer);
2055};
2056
2057var events = {
2058
2059    touchstart: function(event){
2060        if (event.touches.length > 1){
2061            clear();
2062            return;
2063        }
2064
2065        timer = (function(){
2066            this.fireEvent(name, event);
2067        }).delay(this.retrieve(delayKey) || 750, this);
2068    },
2069
2070    touchmove: clear,
2071    touchcancel: clear,
2072    touchend: clear
2073
2074};
2075
2076Element.defineCustomEvent(name, {
2077
2078    onSetup: function(){
2079        this.addEvents(events);
2080    },
2081
2082    onTeardown: function(){
2083        this.removeEvents(events);
2084    },
2085
2086    onEnable: function(){
2087        disabled = false;
2088    },
2089
2090    onDisable: function(){
2091        disabled = true;
2092        clear();
2093    }
2094
2095});
2096
2097})();
2098
2099((function(){
2100
2101	if (typeof this.RokBox == 'undefined') this.RokBox = {};
2102
2103	this.RokBox.Media = new Class({
2104
2105		Implements: [Options, Events],
2106
2107		options:{
2108			data: 'rokbox',
2109
2110			formats: {
2111				image: {
2112					matcher: /(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$)/i,
2113					params : {},
2114					type   : 'image'
2115				},
2116
2117				iframe: {
2118					matcher: '',
2119					params: {},
2120					type: 'iframe'
2121				},
2122
2123				audio: {
2124					matcher: /(\.(mp3|wav|ogg)((\?|#).*)?$)/i,
2125					params : {
2126						autoplay: 'autoplay',
2127						controls: 'controls'
2128					},
2129					type   : 'audio'
2130				},
2131
2132				video: {
2133					matcher: /(\.(ogm|ogv|webm|mp4|swf)((\?|#).*)?$)/i,
2134					params : {
2135						autoplay: 'autoplay',
2136						controls: 'controls'
2137					},
2138					type   : 'video'
2139				},
2140
2141				youtube: {
2142					matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i,
2143					params  : {
2144						autoplay    : 1,
2145						autohide    : 1,
2146						fs          : 1,
2147						rel         : 0,
2148						hd          : 1,
2149						vq			: 'hd1080',
2150						wmode       : 'opaque',
2151						enablejsapi : 1
2152					},
2153					type : 'iframe',
2154					url  : '//www.youtube.com/embed/$3'
2155				},
2156				vimeo : {
2157					matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/,
2158					params  : {
2159						autoplay      : 1,
2160						hd            : 1,
2161						show_title    : 1,
2162						show_byline   : 1,
2163						show_portrait : 0,
2164						fullscreen    : 1
2165					},
2166					type : 'iframe',
2167					url  : '//player.vimeo.com/video/$1'
2168				},
2169				metacafe : {
2170					matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/,
2171					params  : {
2172						flashVars: "playerVars=autoPlay=yes"
2173					},
2174					type    : 'swf',
2175					aspect  : {w: 600, h: 338},
2176					url     : function(rez, params, obj) {
2177						return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf';
2178					}
2179				},
2180				dailymotion : {
2181					matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
2182					params  : {
2183						additionalInfos : 0,
2184						autoStart : 1
2185					},
2186					type : 'swf',
2187					url  : '//www.dailymotion.com/swf/video/$1'
2188				},
2189				twitvid : {
2190					matcher : /(twitvid|telly)\.com\/([a-zA-Z0-9_\-\?\=]+)/i,
2191					params  : {
2192						autoplay : 1
2193					},
2194					type : 'iframe',
2195					url  : '//www.$1.com/embed.php?guid=$2'
2196				},
2197				spotify : {
2198					matcher : /open\.spotify\.com\/([a-zA-Z0-9\/]+)/i,
2199					params  : {},
2200					type    : 'iframe',
2201					aspect  : {w: 300, h: 380},
2202					url     : function(rez, params){
2203						return '//embed.spotify.com/?uri=' + rez[1].split('/').join(':');
2204					}
2205				},
2206				twitpic : {
2207					matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i,
2208					type : 'image',
2209					url  : '//twitpic.com/show/full/$1/'
2210				},
2211				instagram : {
2212					matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
2213					type : 'image',
2214					url  : '//$1/p/$2/media/?size=l'
2215				},
2216				google_maps : {
2217					matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i,
2218					type    : 'iframe',
2219					aspect  : {w: 640, h: 480},
2220					url     : function(rez, params) {
2221						return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed');
2222					}
2223				}
2224			}
2225		},
2226
2227		initialize: function(options){
2228			this.setOptions(options);
2229		},
2230
2231		format: function(url){
2232			var format = this.getFormat(url),
2233				matcher = url.match(format.matcher ? format.matcher : ''),
2234				params = format.params || {};
2235
2236			if (typeof format.url == 'function'){
2237				return format.url.call(this, matcher, params);
2238			}
2239
2240			url = format.url || url;
2241
2242			matcher.forEach(function(value, key){
2243				url = url.replace( '$' + key, value || '' );
2244			}, this);
2245
2246			params = Object.toQueryString(params);
2247			if (params.length) {
2248				url += (url.indexOf('?') > 0 ? '&' : '?') + params;
2249			}
2250
2251			return url;
2252		},
2253
2254		getFormat: function(url){
2255			var format;
2256
2257			Object.forEach(this.options.formats, function(obj, type){
2258				if (obj.matcher && url.match(obj.matcher)) format = obj;
2259			});
2260
2261			return format || 'iframe';
2262		},
2263
2264		getType: function(url){
2265			var match;
2266
2267			Object.forEach(this.options.formats, function(obj, type){
2268				if (obj.matcher && url.match(obj.matcher)) match = obj.type;
2269			});
2270
2271			return match || 'iframe';
2272		},
2273
2274		getAspect: function(url){
2275			var match;
2276
2277			Object.forEach(this.options.formats, function(obj, type){
2278				if (obj.matcher && url.match(obj.matcher)) match = obj.aspect;
2279			});
2280
2281			return match || this.options.formats.iframe.aspect || {w: 1280, h: 720};
2282		},
2283
2284		getParams: function(url){
2285			var match;
2286
2287			Object.forEach(this.options.formats, function(obj, type){
2288				if (obj.matcher && url.match(obj.matcher)) match = obj.params;
2289			});
2290
2291			return match || {};
2292		}
2293	});
2294
2295})());
2296((function(){
2297
2298    if (typeof this.rokbox != 'undefined') return;
2299    if (typeof this.RokBox == 'undefined') this.RokBox = {};
2300
2301    var RokBox = this.RokBox;
2302
2303    var isWebkit = navigator.userAgent.match(/Webkit/i),
2304        isSafari6 = navigator.userAgent.match(/Version\/6.+Safari/i),
2305        isIE8 = navigator.userAgent.match(/MSIE\s8.0.+Trident/i),
2306        isiOS = ( navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false );
2307
2308    String.implement({
2309        htmlEncode: function(){
2310            return this.replace(/&[^(#\d+;|a-z+;)]/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
2311        },
2312
2313        htmlDecode: function(){
2314            return this.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"');
2315        }
2316    });
2317
2318    this.RokBox.Class = new Class({
2319
2320        Implements: [Options, Events],
2321
2322        options:{
2323            data: 'rokbox'
2324        },
2325
2326        initialize: function(options){
2327            this.setOptions(options, RokBoxSettings || {});
2328            Browser.Features.Touch = (function(){ return !!('ontouchstart' in window); })();
2329
2330            this.bound = {
2331                resize: null
2332            };
2333
2334            this._build();
2335            this.attach();
2336            this.isFitting = false;
2337            this.isTouch = Browser.Features.Touch;
2338            if (this.isTouch) this.wrapper.addClass('touch-device');
2339            this.media = new RokBox.Media();
2340        },
2341
2342        attach: function(){
2343            if (document.retrieve(this.options.data + ':attached', false)) return;
2344
2345            var touchMove = 0;
2346            var open = document.retrieve(this.options.data + ':open', function(event, element){
2347                    if (event && (event.shift || event.meta || event.rightClick)) return true;
2348                    if (event) event.preventDefault();
2349
2350                    this.open(element);
2351                }.bind(this)),
2352
2353                close = document.retrieve(this.options.data + ':close', function(event, element){
2354                    if ((!this.isOpen && !this.isOpening) || (event && event.rightClick)) return true;
2355                    if (event.target && !event.target.get('data-rokboxclose') && (event.target == this.container || this.container.contains(event.target))) return true;
2356                    if (event.target && !event.target.get('data-rokboxclose') && (
2357                        (event.target == this.header || this.header.contains(event.target)) ||
2358                        (event.target == this.footer || this.footer.contains(event.target))
2359                    )) return true;
2360
2361                    this.close();
2362                    event.stop();
2363                }.bind(this)),
2364
2365                fitscreen = document.retrieve(this.options.data + ':fitscreen', function(event, element){
2366                    if (event && event.rightClick) return true;
2367                    this.fitscreen(element);
2368                }.bind(this)),
2369
2370                unfitscreen = document.retrieve(this.options.data + ':unfitscreen', function(event, element){
2371                    if (event && event.rightClick) return true;
2372                    this.unfitscreen(element);
2373                }.bind(this)),
2374
2375                toggleFitscreen = document.retrieve(this.options.data + ':toggleFitscreen', function(event, element){
2376                    if (event && event.rightClick) return true;
2377                    this[(this.isFitting) ? 'unfitscreen' : 'fitscreen'](element);
2378                }.bind(this)),
2379
2380                navigation = document.retrieve(this.options.data + ':navigation', function(event, element){
2381                    var item;
2382                    if (event && event.rightClick) return true;
2383                    if (!element && (event.key == 'left' || event.key == 'right')){
2384                        element = document.getElement('[data-rokbox' + (event.key == 'left' ? 'previous' : 'next') + ']');
2385                    }
2386                    if (!element && (event.direction == 'left' || event.direction == 'right')){
2387                        element = document.getElement('[data-rokbox' + (event.direction == 'left' ? 'previous' : 'next') + ']');
2388                    }
2389
2390                    item = document.getElement('[href=' + element.get('data-rokboxnavigation') + '][data-rokbox-album=' + element.get('data-rokboxnavigation-album') + ']');
2391                    if (item) this.load(item);
2392                }.bind(this));
2393
2394            if (Browser.Features.Touch && !(Browser.Platform.win && Browser.chrome)){
2395                document.addEvent('touchstart:relay([data-rokbox])', function(event){
2396                    if (event.touches.length > 1) return;
2397                    var touch = event.touches[0];
2398                    touchMove = {x: touch.pageX, y: touch.pageY};
2399                });
2400                document.addEvent('touchend:relay([data-rokbox])', function(event){
2401                    if (event.changedTouches && event.changedTouches.length > 1) return;
2402                    var touch = event.changedTouches[0], newTouchMove;
2403                    newTouchMove = {x: touch.pageX, y: touch.pageY};
2404
2405                    if (newTouchMove.x == touchMove.x && newTouchMove.y == touchMove.y){
2406                        if (event.target.get('data-rokbox') == null) event.target = event.target.getParent('[data-rokbox]');
2407                        return open(event, event.target);
2408                    } else return true;
2409                });
2410                //document.addEvent('click:relay([data-rokbox])', open
2410);
2411
2412                // fix for menus - not needed for WP
2413                /*var menuTouchFix;
2414                document.getElements('.gf-menu li a').addEvent('touchstart', function(e){
2415                    if (this.getParent('.gf-menu-device-wrapper')) return;
2416                    if (!this.getParent('li').hasClass('parent')){
2417                        this.click();
2418                        e.stop();
2419                    }
2420                    if (menuTouchFix === this || this.getParent('li').hasClass('grouped') || this.getParent('li').hasClass('modules')) return this.click();
2421                    menuTouchFix = this;
2422                    return true;
2423                });
2424                document.getElements('.gf-menu li a').addEvent('touchend', function(e){
2425                    if (this.getParent('.gf-menu-device-wrapper')) return;
2426                    return false;
2427                });*/
2428
2429                document.addEvents({
2430                    'keyup:keys(esc)': close,
2431                    'touchend:relay([data-rokboxwrapper])': close,
2432                    'keydown:keys(f)': toggleFitscreen,
2433                    'touchend:relay([data-rokboxfitscreen])': fitscreen,
2434                    'touchend:relay([data-rokboxunfitscreen])': unfitscreen,
2435                    'touchend:relay([data-rokboxprevious], [data-rokboxnext])': navigation,
2436                    'keydown:keys(right)': navigation,
2437                    'keydown:keys(left)': navigation,
2438                    'swipe': navigation
2439                });
2440
2441            } else {
2442                document.addEvent('click:relay([data-rokbox])', open);
2443                document.addEvents({
2444                    'keyup:keys(esc)': close,
2445                    'click:relay([data-rokboxwrapper])': close,
2446                    'keydown:keys(f)': toggleFitscreen,
2447                    'click:relay([data-rokboxfitscreen])': fitscreen,
2448                    'click:relay([data-rokboxunfitscreen])': unfitscreen,
2449                    'click:relay([data-rokboxprevious], [data-rokboxnext])': navigation,
2450                    'keydown:keys(right)': navigation,
2451                    'keydown:keys(left)': navigation,
2452                    'swipe': navigation
2453                });
2454            }
2455
2456            document.store(this.options.data + ':attached', true);
2457            document.store('swipe:cancelVertical', true);
2458
2459            $$('[data-rokbox]').addEvent(this.isTouch ? 'touchstart' : 'click', function(e){
2460                if (e) e.preventDefault();
2461            });
2462
2463        },
2464
2465        detach: function(){
2466            if (!document.retrieve(this.options.data + ':attached', true)) return;
2467
2468            var open = document.retrieve(this.options.data + ':open'),
2469                close = document.retrieve(this.options.data + ':close'),
2470                fitscreen = document.retrieve(this.options.data + ':fitscreen'),
2471                unfitscreen = document.retrieve(this.options.data + ':unfitscreen'),
2472                navigation = document.retrieve(this.options.data + ':navigation');
2473
2474            document.removeEvents({
2475                'click:relay([data-rokbox])': open,
2476                'keyup:keys(esc)': close,
2477                'click:relay([data-rokboxwrapper])': close,
2478                'click:relay([data-rokboxfitscreen])': fitscreen,
2479                'click:relay([data-rokboxunfitscreen])': unfitscreen,
2480                'click:relay([data-rokboxprevious], [data-rokboxnext])': navigation
2481            });
2482            document.store(this.options.data + ':attached', false);
2483        },
2484
2485        open: function(element){
2486            if (this.isOpening) return this;
2487            if (this.isOpen) return this.load(element);
2488
2489            this.isOpening = true;
2490
2491            this._openAndFixJump();
2492
2493            moofx(this.wrapper).style({display: 'block'}).animate({opacity: 1}, {duration: 300});
2494            this.containerCaption.set('html', '').addClass('rokbox-hidden');
2495            this.footer.setStyle('display', 'none');
2496            moofx(this.container).style({top: '-50%', opacity: 0}).animate({top: 0, opacity: 1}, {
2497                duration: 300,
2498                callback: function(){
2499
2500                    /*['-webkit-', '-moz-', '-ms-', '-o-', ''].each(function(pfx){
2501                        moofx(document.body.getElements('> *:not([class=rokbox-wrapper])')).style(pfx + 'filter', 'blur(5px)');
2502                    });*/
2503
2504                    this.load(element);
2505                }.bind(this)
2506            });
2507        },
2508
2509        close: function(element){
2510            moofx(this.wrapper).animate({opacity: 0}, {
2511                duration: 300,
2512                callback: function(){
2513                    window.removeEvent('resize', this.bound.resize);
2514
2515                    /*['-webkit-', '-moz-', '-ms-', '-o-', ''].each(function(pfx){
2516                        moofx(document.body.getElements('> *:not([class=rokbox-wrapper])')).style(pfx + 'filter', 'none');
2517                    });*/
2518
2519                    this.wrapper.setStyle('display', 'none');
2520                    this.container.setStyles({maxWidth: null, maxHeight: null});
2521                    if (!this.isTouch) this.containerControls.setStyle('display', 'none');
2522                    this.containerContent.setStyles({maxWidth: null, maxHeight: null, width: null, height: null}).empty();
2523                    this.object = null;
2524                    this.isOpen = false;
2525                    this.isOpening = false;
2526                    document.body.setStyle('margin-right', 0).removeClass('rokbox-opened');
2527                }.bind(this)
2528            });
2529        },
2530
2531        load: function(element){
2532            if (!element) return;
2533
2534            var url = element.get('href'),
2535                href = this.media.format(url),
2536                type = this.media.getType(url),
2537                aspect = this.media.getAspect(url),
2538                object, attr, data = {}, params, size, waitLoad = true, overrideSize;
2539
2540            window.removeEvent('resize', this.bound.resize);
2541
2542            this.setNavigation(element);
2543            this.showSpinner();
2544            //this.setType(type);
2545            this.setFitting();
2546
2547            if (element.get('data-rokbox-element')) type = 'element';
2548            size = element.get('data-rokbox-size') ? element.get('data-rokbox-size').split(' ') : false;
2549
2550            data = {
2551                href: href,
2552                element: element,
2553                type: type,
2554                aspect: aspect,
2555                size: size
2556            };
2557
2558            switch(type){
2559
2560                case 'image':
2561                    object = new Image();
2562                    break;
2563
2564                case 'element':
2565                    object = new Element('div');
2566                    data.rule = element.get('data-rokbox-element');
2567                    waitLoad = false;
2568                    break;
2569
2570                case 'audio':
2571                    overrideSize = size ? {width: size[0], height: size[1]} : {width: 300, height: 30};
2572                    if (url.match(/\.mp3$/i) && Browser.firefox){
2573                        object = new Element('object', {data: url, type: 'application/x-mplayer-2', width: overrideSize.width, height: overrideSize.height + 60}).
2574                            set('html', '<param name="filename" value="'+url+'"><param name="ShowControls" value="1"><param name="AutoStart" value="true"><embed type="application/x-mplayer-2" src="'+url+'" width="'+overrideSize.width+'" height="'+(overrideSize.height+60)+'" showcontrols="true" autostart="true"></embed>').
2575                            setStyles({width: overrideSize.width, height: overrideSize.height});
2576
2577                        data.html5 = false;
2578                    } else {
2579                        var mode = url.match(/\.mp3$/i) ? 'video' : 'audio';
2580                        object = new Element(mode).set('html', 'Your browser does not support the <code><audio></code> element.');
2581                        params = this.media.getParams(url);
2582                        object.set('src', url).set('width', overrideSize.width).set('height', overrideSize.height + 60);
2583
2584                        Object.forEach(params, function(value, param){
2585                            object.set(param, value);
2586                        }, this);
2587
2588                        if (mode == 'video') object.set('type', 'audio/mpeg');
2589                        data.html5 = true;
2590                    }
2591
2592                    waitLoad = false;
2593                    break;
2594
2595                case 'video':
2596                    overrideSize = size ? {width: size[0], height: size[1]} : {width: 600, height: 400};
2597                    if (url.match(/\.swf$/i) && Browser.firefox){
2598                        object = new Element('object', {classid: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", codebase: "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0", width: overrideSize.width, height: overrideSize.height}).
2599                            set('html', '<param name="movie" value="'+url+'"><param name="quality" value="high"><embed src="'+url+'" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" width="'+overrideSize.width+'" height="'+overrideSize.height+'" type="application/x-shockwave-flash"></embed>').
2600                            setStyles({width: overrideSize.width, height: overrideSize.height});
2601
2602                        data.html5 = false;
2603                        waitLoad = false;
2604                    } else {
2605                        object = new Element('video').set('html', 'Your browser does not support the <code>video</code> element.');
2606
2607                        params = this.media.getParams(url);
2608                        if (url.match(/\.mp4$/i) && object.canPlayType('video/mp4').length) object.set('src', href);
2609                        if (url.match(/\.webm$/i) && object.canPlayType('video/webm').length) object.set('src', href);
2610                        if (url.match(/\.ogg$/i) && object.canPlayType('video/ogg').length) object.set('src', href);
2611                        if (url.match(/\.ogv$/i) && object.canPlayType('video/ogv').length) object.set('src', href);
2612                        if (size) object.setStyles(overrideSize);
2613                        else object.setStyles({width: '100%', height: 'auto'});
2614
2615                        Object.forEach(params, function(value, param){
2616                            object.set(param, value);
2617                        }, this);
2618
2619                        data.html5 = true;
2620                        waitLoad = true;
2621                    }
2622                    break;
2623
2624                case 'swf':
2625                    var w = Math.min(window.getSize().x - 100, aspect.w),
2626                        h = w * aspect.h / aspect.w;
2627
2628                    if (size){
2629                        w = size[0]; h = size[1];
2630                    }
2631
2632                    var embed = new Element('embed', {src: href, type: 'application/x-shockwave-flash', width: w, height: h});
2633                    params = this.media.getParams(url);
2634                    object = new Element('object', {
2635                        classid: 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000',
2636                        width: '100%',
2637                        height: '100%'
2638                    });
2639
2640                    object.adopt(new Element('param', {name: 'move', value: href}));
2641
2642                    Object.forEach(params, function(value, param){
2643                        new Element('param').set(param, value);
2644                        embed.set(param, value);
2645                    }, this);
2646
2647                    embed.inject(object);
2648
2649                    this.bound.resize = this._resizeObject.pass([object, data], this);
2650                    if (!isWebkit) window.addEvent('resize', this.bound.resize);
2651
2652                    waitLoad = false;
2653                    break;
2654
2655                case 'iframe': default:
2656                    var w = Math.min(window.getSize().x - 100, aspect.w),
2657                        h = w * aspect.h / aspect.w;
2658
2659                    if (size){
2660                        w = size[0]; h = size[1];
2661                    }
2662
2663                    object = new IFrame({resize: true, frameborder: 0, webkitAllowFullScreen: true, mozallowfullscreen: true, allowFullScreen: true, width: w, height: h});
2664
2665                    this.bound.resize = this._resizeObject.pass([object, data], this);
2666                    if (!isWebkit) window.addEvent('resize', this.bound.resize);
2667
2668                    if (href.match(/\.pdf$/)){
2669                        waitLoad = false;
2670                        object.set('src', href);
2671                    }
2672
2673                    break;
2674            }
2675
2676            document.id(object).inject(document.body).setStyle('display', 'none');
2677
2678            if (waitLoad){
2679                if (data.html5 && data.type == 'video'){
2680                    object.addEventListener('canplay', function(){
2681                        data.videoSize = {width: object.videoWidth, height: object.videoHeight};
2682                        this['_load' + type.capitalize()](object, data);
2683                    }.bind(this), false);
2684                    if (isiOS){
2685                        data.videoSize = {width: object.videoWidth, height: object.videoHeight};
2686                        this['_load' + type.capitalize()](object, data);
2687                        object.play();
2688                    }
2689                } else {
2690                    object.addEvent('load', this['_load' + type.capitalize()].pass([object, data], this));
2691                    object.set('src', href);
2692                }
2693
2694                if (Browser.firefox && !!url.match(/\.mp4$/i)){
2695                    // mp4 is not supported by firefox, yet
2696                    // so we are going to add a webm and ogv fallback
2697                    if (!object.canPlayType('video/mp4')){
2698                        new Element('source')
2699                                .set('src', url)
2700                                .set('type', 'video/mp4')
2701                                .inject(object, 'top');
2702                        new Element('source')
2703                                .set('src', url.replace(/\.mp4/, '.ogg'))
2704                                .set('type', 'video/ogg')
2705                                .inject(object, 'top');
2706                        new Element('source')
2707                                .set('src', url.replace(/\.mp4/, '.ogv'))
2708                                .set('type', 'video/ogv')
2709                                .inject(object, 'top');
2710                        new Element('source')
2711                                .set('src', url.replace(/\.mp4/, '.webm'))
2712                                .set('type', 'video/webm')
2713                                .inject(object, 'top')
2714                                .onerror = this._setError.pass([object, data], this);
2715                    }
2716                }
2717
2718                object.onerror = this._setError.pass([object, data], this);
2719            } else {
2720                this['_load' + type.capitalize()](object, data);
2721            }
2722        },
2723
2724        fitscreen: function(element){
2725            var dummy = (this.containerContent.getElement('img') || this.containerContent.getElement('iframe'));
2726            if (!dummy) return;
2727            var size = {
2728                    maxWidth: this.containerContent.getStyle('maxWidth'),
2729                    maxHeight: this.containerContent.getStyle('maxHeight'),
2730                    width: dummy ? dummy.getStyle('width').toInt() || 'auto' : 'auto',
2731                    height: dummy ? dummy.getStyle('height').toInt() || 'auto' : 'auto'
2732                },
2733                viewport = window.getSize();
2734
2735            if (isSafari6) moofx(dummy).style({width: 'inherit'});
2736
2737            this.container.store(this.options.data + ':fitscreen-size', {
2738                maxWidth: size.maxWidth,
2739                maxHeight: size.maxHeight,
2740                width: size.width,
2741                height: size.height,
2742                viewport: viewport
2743            });
2744
2745            moofx(this.containerContent).style({maxWidth: null, maxHeight: null});
2746            moofx(dummy).style({width: null, height: null});
2747            moofx(this.container).style({maxWidth: '100%', maxHeight: '100%'});
2748            document.getElement('[data-rokboxfitscreen]').setStyle('display', 'none');
2749            document.getElement('[data-rokboxunfitscreen]').setStyle('display', 'block');
2750
2751            (function(){
2752                if (isSafari6 || isIE8) moofx(dummy).style({width: '100%'});
2753            }.bind(this)).delay(5);
2754
2755            this.isFitting = true;
2756        },
2757
2758        unfitscreen: function(element){
2759            var size = {
2760                    maxWidth: this.container.retrieve(this.options.data + ':fitscreen-size').maxWidth,
2761                    maxHeight: this.container.retrieve(this.options.data + ':fitscreen-size').maxHeight,
2762                    width: this.container.retrieve(this.options.data + ':fitscreen-size').width,
2763                    height: this.container.retrieve(this.options.data + ':fitscreen-size').height
2764                },
2765                viewport = this.container.retrieve(this.options.data + ':fitscreen-size').viewport;
2766
2767            if (isSafari6 || isIE8) moofx(this.containerContent.getElement('img')).style({width: 'inherit'});
2768
2769            this.containerContent.setStyles({maxWidth: size.maxWidth, maxHeight: size.maxHeight});
2770            moofx(this.container).style({maxWidth: null, maxHeight: null});
2771            moofx(this.containerContent.getElement('img') || this.containerContent.getElement('iframe')).style({width: size.width, height: size.height});
2772            document.getElement('[data-rokboxunfitscreen]').setStyle('display', 'none');
2773            document.getElement('[data-rokboxfitscreen]').setStyle('display', 'block');
2774
2775            if (isSafari6 || isIE8) moofx(this.containerContent.getElement('img')).style({width: '100%'});
2776
2777            this.isFitting = false;
2778        },
2779
2780        setNavigation: function(element){
2781            var gallery = element.get('data-rokbox-album'),
2782                arrows = document.getElements('[data-rokboxprevious], [data-rokboxnext]'),
2783                prevs = document.getElements('[data-rokboxprevious]'),
2784                nexts = document.getElements('[data-rokboxnext]');
2785
2786            if (!gallery){
2787                arrows.setStyle('display', 'none');
2788                return this;
2789            }
2790
2791            var elements = document.getElements('[data-rokbox-album='+gallery+']'),
2792                index = elements.indexOf(element),
2793                previous = elements[index - 1],
2794                next = elements[index + 1];
2795
2796            if (index == -1 || elements.length == 1){
2797                arrows.setStyle('display', 'none');
2798                this.footer.setStyle('display', 'none');
2799                return this;
2800            }
2801
2802            if (typeof previous == 'undefined') previous = elements[elements.length - 1];
2803            if (typeof next == 'undefined') next = elements[0];
2804
2805            prevs.set('data-rokboxnavigation', previous.get('href')).set('data-rokboxnavigation-album', previous.get('data-rokbox-album'));
2806            nexts.set('data-rokboxnavigation', next.get('href')).set('data-rokboxnavigation-album', next.get('data-rokbox-album'));
2807            arrows.setStyle('display', 'block');
2808            if (Browser.Features.Touch) this.footer.setStyle('display', 'block');
2809
2810            return this;
2811        },
2812
2813        setType: function(type){
2814            this.container.removeClass(this.options.data + '-type-' + this.type);
2815            this.type = type;
2816            this.container.addClass(this.options.data + '-type-' + this.type);
2817        },
2818
2819        setFitting: function(){
2820            document.getElements(this.isFitting ? '[data-rokboxunfitscreen]' : '[data-rokboxfitscreen]').setStyle('display', 'none');
2821        },
2822
2823        showSpinner: function(){
2824            this.container.addClass('rokbox-loading');
2825        },
2826
2827        hideSpinner: function(){
2828            this.container.removeClass('rokbox-loading');
2829        },
2830
2831        /* Private */
2832        _build: function(){
2833            if (this.wrapper || document.getElement('[data-rokboxwrapper]')) return this;
2834
2835            var list = ['outer', 'row', 'inner', 'container'],
2836                containerList = ['loader', 'content', 'controls'],
2837                controlsList = {
2838                    x: 'close',
2839                    p: 'previous',
2840                    n: 'next',
2841                    /*f: 'fullscreen',*/
2842                    d: 'fitscreen',
2843                    w: 'unfitscreen'
2844                },
2845                Label;
2846
2847            this.wrapper = new Element('div[data-rokboxwrapper].' + this.options.data + '-wrapper').inject(document.body);
2848            list.forEach(function(mode, i){
2849                this[mode] = new Element('div[data-' + this.options.data + mode + '].' + this.options.data + '-' + mode).inject(this[list[i - 1]] || this.wrapper);
2850            }, this);
2851
2852            containerList.forEach(function(mode){
2853                this['container' + mode.capitalize()] = new Element('div[data-' + this.options.data + mode + '].' + this.options.data + '-' + mode).inject(this.container);
2854            }, this);
2855
2856
2857            // touch devices
2858            ['header', 'footer'].forEach(function(row, r){
2859                this[row] = new Element('div[data-' + this.options.data + row + '].' + this.options.data + '-' + row).inject(this.row, !r ? 'before' : 'after');
2860            }, this);
2861            // end touch devices
2862
2863            Object.forEach(controlsList, function(label, mode){
2864                Label = label.capitalize();
2865                if (mode != 'p' && mode != 'n'){
2866                    this['controls' + Label] = new Element('div[data-rokboxicon="'+mode+'"][data-' + this.options.data + label + '].' + this.options.data + '-' + label).inject(this.containerControls);
2867                } else {
2868                    this['controls' + Label] = new Element('div[data-' + this.options.data + label + '].' + this.options.data + '-' + label).inject(this.containerControls);
2869                    new Element('div[data-rokboxicon="'+mode+'"]').inject(this['controls' + Label]);
2870                }
2871
2872                if (['p', 'n'].contains(mode)) this['controls' + Label].clone().inject(this.footer);
2873                if (mode == 'x') this['controls' + Label].clone().inject(this.header);
2874
2875            }, this);
2876
2877            this.containerLoader.adopt(new Element('div.' + this.options.data + '-loader-image'));
2878            this.containerCaption = new Element('div[data-' + this.options.data + 'caption].' + this.options.data + '-caption').inject(this.container);
2879        },
2880
2881        _loadImage: function(object, data){
2882            var sizeBefore = this.containerContent.getSize(),
2883                size, computedHeight, imgOriginalSize = {};
2884
2885            this.setType(data.type);
2886
2887            if (isIE8){
2888                // soon you will die, IE8.
2889                var ie8 = object.clone().inject(document.body).setStyles({display: 'block', 'visibility': 'visible', position: 'absolute', top: '-30000px'});
2890                imgOriginalSize = {width: ie8.width, height: ie8.height}
2891                ie8.dispose();
2892            }
2893
2894            // initial cleanup
2895            moofx(object).style({opacity: 0, visibility: 'hidden', display: 'block'});
2896
2897            if (isSafari6 || isIE8) moofx(object).style({width: 'inherit'}); // safari 6 sux
2898
2899            if (data.size){
2900                moofx(object).style({width: data.size[0], height: data.size[1]});
2901            }
2902
2903            object.inject(this.containerContent.empty());
2904            if (data.type != 'element' && data.type != 'audio' && data.type != 'video') this.containerContent.adopt(new Element('div.rokbox-contentborder'));
2905
2906            moofx(this.containerContent).style({maxWidth: null, maxHeight: null});
2907            if (data.size && this.isFitting){
2908                moofx(object).style({width: null, height: null});
2909            }
2910
2911            // caption
2912            this.containerCaption.set('html', data.element.get('data-rokbox-caption') || '').removeClass('rokbox-hidden');
2913
2914            // size checks and setup
2915            size = this.containerContent.getSize();
2916            if (data.videoSize) size = {x: data.videoSize.width || size.x, y: data.videoSize.height || size.y};
2917            computedHeight = this.container.getComputedSize({styles: ['padding', 'border', 'margin']}).totalHeight;
2918            //if (data.videoSize) computedHeight += data.videoSize.height;
2919            if (!size.x) return;
2920
2921            // hide object and caption before animating
2922            moofx(object).style({display: 'none'});
2923            moofx(this.containerCaption.addClass('rokbox-hidden')).style({opacity: 0});
2924
2925            if (isSafari6 || isIE8) moofx(object).style({width: '100%'}); // safari 6 sux
2926
2927            moofx(this.containerContent).style({
2928                width: !this.isOpen ? this.containerContent.getSize().x : sizeBefore.x,
2929                height: !this.isOpen ? this.containerContent.getSize().y : sizeBefore.y
2930            });
2931
2932            // ensure the height fits on the viewport
2933            var innerSize = window.getSize(),
2934                contentSize = this.containerContent.getSize();
2935
2936            if (computedHeight >= innerSize.y){
2937                var margin = this.container.getStyle('margin-bottom').toInt(),
2938                    caption = document.getElement('[data-rokboxcaption]'),
2939                    captionSize = caption ? caption.getSize().y : 0,
2940
2941                    objectHeight = Math.round(innerSize.y * size.y / computedHeight) - captionSize - margin,
2942                    objectWidth = Math.round(size.x * objectHeight / size.y);
2943
2944                if (!this.isFitting){
2945                    size.x = objectWidth;
2946                    size.y = objectHeight;
2947                }
2948            }
2949
2950            // show / hide the fit button
2951            if (!data.error && data.type != 'element'){
2952                document.getElements(this.isFitting ? '[data-rokboxunfitscreen]' : '[data-rokboxfitscreen]').setStyle('display', object.width == size.x ? 'none' : 'block');
2953            } else {
2954                document.getElements(this.isFitting ? '[data-rokboxunfitscreen]' : '[data-rokboxfitscreen]').setStyle('display', 'none');
2955            }
2956
2957            // show caption if needed
2958            if (!data.error && data.element.get('data-rokbox-caption') && data.element.get('data-rokbox-caption').length){
2959                moofx(this.containerCaption.removeClass('rokbox-hidden')).animate({opacity: 1});
2960            }
2961
2962            //if (data.html5) moofx(object).style({width: '100%', height: '100%'});
2963
2964            // animate
2965            moofx(this.containerContent)['animate']({width: size.x, height: size.y}, {
2966                duration: 250,
2967                callback: function(){
2968                    moofx(object).style({
2969                        display: 'block',
2970                        visibility: 'visible'
2971                    });
2972
2973                    if (data.html5 && object.play) object.play();
2974
2975                    moofx(object).style({
2976                        maxWidth: (object.naturalWidth || imgOriginalSize.width || object.width || object.videoWidth || size.x) + 'px',
2977                        maxHeight: (object.naturalHeight || imgOriginalSize.height || object.height || object.videoHeight || size.y) + 'px'
2978                    });
2979
2980                    moofx(object)[!isIE8 ? 'animate' : 'style']({opacity: 1});
2981
2982                    this.containerContent.setStyles({maxWidth: size.x, maxHeight: size.y, width: null, height: null});
2983                    if (!this.isTouch) this.containerControls.setStyle('display', 'block');
2984
2985                    if (this.isFitting) this.fitscreen();
2986
2987                    this.container.store(this.options.data + ':fitscreen-size', {
2988                        maxWidth: objectWidth || size.x,
2989                        maxHeight: objectHeight || size.y
2990                    });
2991
2992                }.bind(this)
2993            });
2994
2995            this.isOpen = true;
2996            this.isOpening = false;
2997            this.object = object;
2998
2999            this.hideSpinner();
3000        },
3001
3002        _loadIframe: function(object, data){
3003            var sizeBefore = this.containerContent.getSize(),
3004                size, computedHeight;
3005
3006            object.removeEvents('load');
3007            this.setType(data.type);
3008
3009            // hide and inject in the cleaned out content container
3010            object.setStyles({visibility: 'hidden', display: 'block'});
3011            object.inject(this.containerContent.empty());
3012            if (isIE8) object.setStyle('max-width', 'inherit');
3013
3014            // max width and height are useless with iframes, unfortunately
3015            moofx(this.containerContent).style({
3016                maxWidth: null,
3017                maxHeight: null
3018            });
3019
3020            // caption
3021            this.containerCaption.set('html', data.element.get('data-rokbox-caption') || '').removeClass('rokbox-hidden');
3022
3023            // size checks and setup
3024            size = this.containerContent.getSize();
3025            if (size.x <= parseInt(object.get('width'), 10)) size.x = parseInt(object.get('width'), 10);
3026            computedHeight = this.container.getComputedSize({styles: ['padding', 'border', 'margin']}).totalHeight || this.container.getSize().y;
3027
3028            if (!size.x) return;
3029            size.y = size.y || 100;
3030
3031            // hide object and caption before animating
3032            object.setStyles({display: 'none'});
3033            moofx(this.containerCaption.addClass('rokbox-hidden')).style({opacity: 0});
3034
3035            moofx(this.containerContent).style({
3036                width: !this.isOpen ? this.containerContent.getSize().x : sizeBefore.x,
3037                height: !this.isOpen ? this.containerContent.getSize().y : sizeBefore.y
3038            });
3039
3040            // ensure the height fits on the viewport
3041            var innerSize = window.getSize(),
3042                contentSize = this.containerContent.getSize();
3043
3044            if (computedHeight >= innerSize.y){
3045                var margin = this.container.getStyle('margin-bottom').toInt(),
3046                    caption = document.getElement('[data-rokboxcaption]'),
3047                    captionSize = caption ? caption.getSize().y : 0,
3048
3049                    objectHeight = Math.round(innerSize.y * size.y / computedHeight) - captionSize - margin,
3050                    objectWidth = Math.round(size.x * objectHeight / size.y);
3051
3052                if (!this.isFitting){
3053                    size.x = objectWidth;
3054                    size.y = objectHeight;
3055                }
3056            }
3057
3058            document.getElements(this.isFitting ? '[data-rokboxunfitscreen]' : '[data-rokboxfitscreen]').setStyle('display', 'none');
3059
3060            if (data.element.get('data-rokbox-caption') && data.element.get('data-rokbox-caption').length) moofx(this.containerCaption.removeClass('rokbox-hidden')).animate({opacity: 1});
3061            moofx(this.containerContent).animate({width: size.x, height: size.y}, {
3062                duration: 250,
3063                callback: function(){
3064                    object.setStyles({
3065                        display: 'block',
3066                        visibility: 'visible',
3067                        width: size.x,
3068                        height: size.y
3069                    });
3070                    this.containerContent.setStyles({maxWidth: size.x, maxHeight: size.y, width: null, height: null});
3071                    if (!this.isTouch) this.containerControls.setStyle('display', 'block');
3072
3073                    this.container.store(this.options.data + ':fitscreen-size', {
3074                        maxWidth: objectWidth || size.x,
3075                        maxHeight: objectHeight || size.y
3076                    });
3077
3078                }.bind(this)
3079            });
3080
3081            this.isOpen = true;
3082            this.isOpening = false;
3083            this.hideSpinner();
3084        },
3085
3086        _loadSwf: function(object, data){
3087            this._loadIframe(object, data);
3088        },
3089
3090        _loadAudio: function(object, data){
3091            this[data.html5 ? '_loadImage' : '_loadIframe'](object, data);
3092        },
3093
3094        _loadVideo: function(object, data){
3095            this[data.html5 ? '_loadImage' : '_loadIframe'](object, data);
3096        },
3097
3098        _loadElement: function(object, data){
3099            var element = document.getElement(data.rule);
3100            if (!element){
3101                return this._setError(object, data);
3102                //throw Error('Element[@'+data.rule+'] not found. Unable to load RokBox.');
3103            }
3104
3105            object.adopt(element.clone(true, true).cloneEvents(element).setStyle('display', 'block').addClass('rokbox-content-element'));
3106            this._loadImage(object, data);
3107        },
3108
3109        _setError: function(object, data){
3110            var error = new Element('div#rokbox-error.rokbox-error' + data.type);
3111
3112            if (data.type == 'element') error.set('html', '<h3>Error</h3><p>The '+data.type+' <code>'+data.rule+'</code> was not found in the DOM.</p>');
3113            else if (data.type == 'video' && data.html5 && Browser.firefox && data.href.match(/\.mp4/i)){
3114                error.set('html', '<h3>Error</h3><p>An error occurred while trying to load the '+data.type+' link: <br /> <code>'+data.href+'</code> <br />Note that Firefox does not support MP4 files. Try adding a WebM or Ogg converted file at the same location of the video above (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/HTML/Supported_media_formats?redirectlocale=en-US&redirectslug=Media_formats_supported_by_the_audio_and_video_elements#WebM">More details</a>).</p>');
3115            }
3116            else error.set('html', '<h3>Error</h3><p>An error occurred while trying to load the '+data.type+' link: <br /> <code>'+data.href+'</code></p>');
3117
3118            data.error = true;
3119            this['_load' + (data.type == 'element' ? 'Image' : data.type.capitalize())](error, data);
3120        },
3121
3122        _resizeObject: function(object, data){
3123            var margin = this.container.getStyle('margin-bottom').toInt(),
3124                caption = document.getElement('[data-rokboxcaption]'),
3125                captionSize = caption ? caption.getSize().y : 0,
3126                viewport = window.getSize(),
3127                containerSize = this.containerContent.getSize(),
3128                computedHeight = this.container.getComputedSize({styles: ['padding', 'border', 'margin']}).totalHeight || this.container.getSize().y;
3129                size = {};
3130
3131            size.y = Math.round(viewport.y * containerSize.y / computedHeight) - captionSize - margin;
3132            size.x = Math.round(viewport.x * size.y / viewport.y);
3133
3134            moofx(this.containerContent).style({maxWidth: size.x, maxHeight: size.y});
3135            moofx(object).style({maxWidth: size.x, maxHeight: size.y});
3136        },
3137
3138        _openAndFixJump: function(){
3139            var previousSize = afterSize = document.body.scrollWidth, compensation = 0;
3140            document.body.addClass('rokbox-opened');
3141            afterSize = document.body.scrollWidth;
3142            compensation = afterSize - previousSize;
3143            document.body.setStyle('margin-right', compensation);
3144        }
3145
3146    });
3147
3148    window.addEvent('domready', function(){
3149        this.rokbox = new RokBox.Class();
3150    });
3151
3152})());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.