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, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 2311 }, 2312 2313 htmlDecode: function(){ 2314 return this.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/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.