Created
February 7, 2014 16:18
-
-
Save jpdery/8866053 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
--- | |
provides: moofx | |
version: 3.2.0 | |
description: A CSS3-enabled javascript animation library | |
homepage: http://moofx.it | |
author: Valerio Proietti <@kamicane> (http://mad4milk.net) | |
license: MIT (http://mootools.net/license.txt) | |
includes: cubic-bezier by Arian Stolwijk (https://github.com/arian/cubic-bezier) | |
... | |
*/ | |
(function(modules) { | |
var cache = {}, require = function(id) { | |
var module = cache[id]; | |
if (!module) { | |
module = cache[id] = {}; | |
var exports = module.exports = {}; | |
modules[id].call(exports, require, module, exports, window); | |
} | |
return module.exports; | |
}; | |
window["moofx"] = require("0"); | |
})({ | |
"0": function(require, module, exports, global) { | |
/* .- 3 | |
.-.-..-..-.-|-._. | |
' ' '`-'`-' ' ' ' | |
*/ | |
"use strict"; | |
// color and timer | |
var color = require("1"), frame = require("2"); | |
// if we're in a browser we need ./browser, otherwise ./fx | |
var moofx = typeof document !== "undefined" ? require("4") : require("18"); | |
moofx.requestFrame = function(callback) { | |
frame.request(callback); | |
return this; | |
}; | |
moofx.cancelFrame = function(callback) { | |
frame.cancel(callback); | |
return this; | |
}; | |
moofx.color = color; | |
// and export moofx | |
module.exports = moofx; | |
}, | |
"1": function(require, module, exports, global) { | |
/* | |
color | |
*/ | |
"use strict"; | |
var colors = { | |
maroon: "#800000", | |
red: "#ff0000", | |
orange: "#ffA500", | |
yellow: "#ffff00", | |
olive: "#808000", | |
purple: "#800080", | |
fuchsia: "#ff00ff", | |
white: "#ffffff", | |
lime: "#00ff00", | |
green: "#008000", | |
navy: "#000080", | |
blue: "#0000ff", | |
aqua: "#00ffff", | |
teal: "#008080", | |
black: "#000000", | |
silver: "#c0c0c0", | |
gray: "#808080", | |
transparent: "#0000" | |
}; | |
var RGBtoRGB = function(r, g, b, a) { | |
if (a == null || a === "") a = 1; | |
r = parseFloat(r); | |
g = parseFloat(g); | |
b = parseFloat(b); | |
a = parseFloat(a); | |
if (!(r <= 255 && r >= 0 && g <= 255 && g >= 0 && b <= 255 && b >= 0 && a <= 1 && a >= 0)) return null; | |
return [ Math.round(r), Math.round(g), Math.round(b), a ]; | |
}; | |
var HEXtoRGB = function(hex) { | |
if (hex.length === 3) hex += "f"; | |
if (hex.length === 4) { | |
var h0 = hex.charAt(0), h1 = hex.charAt(1), h2 = hex.charAt(2), h3 = hex.charAt(3); | |
hex = h0 + h0 + h1 + h1 + h2 + h2 + h3 + h3; | |
} | |
if (hex.length === 6) hex += "ff"; | |
var rgb = []; | |
for (var i = 0, l = hex.length; i < l; i += 2) rgb.push(parseInt(hex.substr(i, 2), 16) / (i === 6 ? 255 : 1)); | |
return rgb; | |
}; | |
// HSL to RGB conversion from: | |
// http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript | |
// thank you! | |
var HUEtoRGB = function(p, q, t) { | |
if (t < 0) t += 1; | |
if (t > 1) t -= 1; | |
if (t < 1 / 6) return p + (q - p) * 6 * t; | |
if (t < 1 / 2) return q; | |
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; | |
return p; | |
}; | |
var HSLtoRGB = function(h, s, l, a) { | |
var r, b, g; | |
if (a == null || a === "") a = 1; | |
h = parseFloat(h) / 360; | |
s = parseFloat(s) / 100; | |
l = parseFloat(l) / 100; | |
a = parseFloat(a) / 1; | |
if (h > 1 || h < 0 || s > 1 || s < 0 || l > 1 || l < 0 || a > 1 || a < 0) return null; | |
if (s === 0) { | |
r = b = g = l; | |
} else { | |
var q = l < .5 ? l * (1 + s) : l + s - l * s; | |
var p = 2 * l - q; | |
r = HUEtoRGB(p, q, h + 1 / 3); | |
g = HUEtoRGB(p, q, h); | |
b = HUEtoRGB(p, q, h - 1 / 3); | |
} | |
return [ r * 255, g * 255, b * 255, a ]; | |
}; | |
var keys = []; | |
for (var c in colors) keys.push(c); | |
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("|") + ")"; | |
var xhex = RegExp(shex, "i"), xrgb = RegExp(srgb + slist, "i"), xhsl = RegExp(shsl + slist, "i"); | |
var color = function(input, array) { | |
if (input == null) return null; | |
input = (input + "").replace(/\s+/, ""); | |
var match = colors[input]; | |
if (match) { | |
return color(match, array); | |
} else if (match = input.match(xhex)) { | |
input = HEXtoRGB(match[1]); | |
} else if (match = input.match(xrgb)) { | |
input = match.slice(1); | |
} else if (match = input.match(xhsl)) { | |
input = HSLtoRGB.apply(null, match.slice(1)); | |
} else return null; | |
if (!(input && (input = RGBtoRGB.apply(null, input)))) return null; | |
if (array) return input; | |
if (input[3] === 1) input.splice(3, 1); | |
return "rgb" + (input.length === 4 ? "a" : "") + "(" + input + ")"; | |
}; | |
color.x = RegExp([ skeys, shex, srgb + slist, shsl + slist ].join("|"), "gi"); | |
module.exports = color; | |
}, | |
"2": function(require, module, exports, global) { | |
/* | |
requestFrame / cancelFrame | |
*/ | |
"use strict"; | |
var indexOf = require("3"); | |
var requestFrame = global.requestAnimationFrame || global.webkitRequestAnimationFrame || global.mozRequestAnimationFrame || global.oRequestAnimationFrame || global.msRequestAnimationFrame || function(callback) { | |
return setTimeout(function() { | |
callback(); | |
}, 1e3 / 60); | |
}; | |
var callbacks = []; | |
var iterator = function(time) { | |
var split = callbacks.splice(0, callbacks.length); | |
for (var i = 0, l = split.length; i < l; i++) split[i](time || (time = +new Date())); | |
}; | |
var cancel = function(callback) { | |
var io = indexOf(callbacks, callback); | |
if (io > -1) callbacks.splice(io, 1); | |
}; | |
var request = function(callback) { | |
var i = callbacks.push(callback); | |
if (i === 1) requestFrame(iterator); | |
return function() { | |
cancel(callback); | |
}; | |
}; | |
exports.request = request; | |
exports.cancel = cancel; | |
}, | |
"3": function(require, module, exports, global) { | |
/** | |
* Array.indexOf | |
*/ | |
function indexOf(arr, item, fromIndex) { | |
fromIndex = fromIndex || 0; | |
if (arr == null) { | |
return -1; | |
} | |
var len = arr.length, i = fromIndex < 0 ? len + fromIndex : fromIndex; | |
while (i < len) { | |
// we iterate over sparse items since there is no way to make it | |
// work properly on IE 7-8. see #64 | |
if (arr[i] === item) { | |
return i; | |
} | |
i++; | |
} | |
return -1; | |
} | |
module.exports = indexOf; | |
}, | |
"4": function(require, module, exports, global) { | |
/* | |
MooFx | |
*/ | |
"use strict"; | |
// requires | |
var color = require("1"), frame = require("2"); | |
var cancelFrame = frame.cancel, requestFrame = frame.request; | |
var prime = require("5"); | |
var camelCase = require("d"), trim = require("j"), properCase = require("n"), hyphenateString = require("o"); | |
var map = require("r"), forEach = require("11"), indexOf = require("3"); | |
var elements = require("12"); | |
var fx = require("18"); | |
// util | |
var clean = function(str) { | |
return trim(str).replace(/\s+/g, " "); | |
}; | |
var matchString = function(s, r) { | |
return String.prototype.match.call(s, r); | |
}; | |
var hyphenated = {}; | |
var hyphenate = function(self) { | |
return hyphenated[self] || (hyphenated[self] = hyphenateString(self)); | |
}; | |
var round = function(n) { | |
return Math.round(n * 1e3) / 1e3; | |
}; | |
// compute > node > property | |
var compute = global.getComputedStyle ? function(node) { | |
var cts = getComputedStyle(node, null); | |
return function(property) { | |
return cts ? cts.getPropertyValue(hyphenate(property)) : ""; | |
}; | |
} : /*(css3)?*/ function(node) { | |
var cts = node.currentStyle; | |
return function(property) { | |
return cts ? cts[camelCase(property)] : ""; | |
}; | |
}; | |
/*:null*/ | |
// pixel ratio retriever | |
var test = document.createElement("div"); | |
var cssText = "border:none;margin:none;padding:none;visibility:hidden;position:absolute;height:0;"; | |
// returns the amount of pixels that takes to make one of the unit | |
var pixelRatio = function(element, u) { | |
var parent = element.parentNode, ratio = 1; | |
if (parent) { | |
test.style.cssText = cssText + ("width:100" + u + ";"); | |
parent.appendChild(test); | |
ratio = test.offsetWidth / 100; | |
parent.removeChild(test); | |
} | |
return ratio; | |
}; | |
// mirror 4 values | |
var mirror4 = function(values) { | |
var length = values.length; | |
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]); | |
return values; | |
}; | |
// regular expressions strings | |
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"; | |
// regular expressions | |
var rgLength = RegExp(sLength, "g"), rLengthNum = RegExp(sLengthNum), rgLengthNum = RegExp(sLengthNum, "g"), rBorderStyle = RegExp(sBorderStyle); | |
// normalize > css | |
var parseString = function(value) { | |
return value == null ? "" : value + ""; | |
}; | |
var parseOpacity = function(value, normalize) { | |
if (value == null || value === "") return normalize ? "1" : ""; | |
return isFinite(value = +value) ? value < 0 ? "0" : value + "" : "1"; | |
}; | |
try { | |
test.style.color = "rgba(0,0,0,0.5)"; | |
} catch (e) {} | |
var rgba = /^rgba/.test(test.style.color); | |
var parseColor = function(value, normalize) { | |
var black = "rgba(0,0,0,1)", c; | |
if (!value || !(c = color(value, true))) return normalize ? black : ""; | |
if (normalize) return "rgba(" + c + ")"; | |
var alpha = c[3]; | |
if (alpha === 0) return "transparent"; | |
return !rgba || alpha === 1 ? "rgb(" + c.slice(0, 3) + ")" : "rgba(" + c + ")"; | |
}; | |
var parseLength = function(value, normalize) { | |
if (value == null || value === "") return normalize ? "0px" : ""; | |
var match = matchString(value, rLengthNum); | |
return match ? match[1] + (match[2] || "px") : value; | |
}; | |
var parseBorderStyle = function(value, normalize) { | |
if (value == null || value === "") return normalize ? "none" : ""; | |
var match = value.match(rBorderStyle); | |
return match ? value : normalize ? "none" : ""; | |
}; | |
var parseBorder = function(value, normalize) { | |
var normalized = "0px none rgba(0,0,0,1)"; | |
if (value == null || value === "") return normalize ? normalized : ""; | |
if (value === 0 || value === "none") return normalize ? normalized : value + ""; | |
var c; | |
value = value.replace(color.x, function(match) { | |
c = match; | |
return ""; | |
}); | |
var s = value.match(rBorderStyle), l = value.match(rgLengthNum); | |
return clean([ parseLength(l ? l[0] : "", normalize), parseBorderStyle(s ? s[0] : "", normalize), parseColor(c, normalize) ].join(" ")); | |
}; | |
var parseShort4 = function(value, normalize) { | |
if (value == null || value === "") return normalize ? "0px 0px 0px 0px" : ""; | |
return clean(mirror4(map(clean(value).split(" "), function(v) { | |
return parseLength(v, normalize); | |
})).join(" ")); | |
}; | |
var parseShadow = function(value, normalize, len) { | |
var transparent = "rgba(0,0,0,0)", normalized = len === 3 ? transparent + " 0px 0px 0px" : transparent + " 0px 0px 0px 0px"; | |
if (value == null || value === "") return normalize ? normalized : ""; | |
if (value === "none") return normalize ? normalized : value; | |
var colors = [], value = clean(value).replace(color.x, function(match) { | |
colors.push(match); | |
return ""; | |
}); | |
return map(value.split(","), function(shadow, i) { | |
var c = parseColor(colors[i], normalize), inset = /inset/.test(shadow), lengths = shadow.match(rgLengthNum) || [ "0px" ]; | |
lengths = map(lengths, function(m) { | |
return parseLength(m, normalize); | |
}); | |
while (lengths.length < len) lengths.push("0px"); | |
var ret = inset ? [ "inset", c ] : [ c ]; | |
return ret.concat(lengths).join(" "); | |
}).join(", "); | |
}; | |
var parse = function(value, normalize) { | |
if (value == null || value === "") return ""; | |
// cant normalize "" || null | |
return value.replace(color.x, function(match) { | |
return parseColor(match, normalize); | |
}).replace(rgLength, function(match) { | |
return parseLength(match, normalize); | |
}); | |
}; | |
// get && set | |
var getters = {}, setters = {}, parsers = {}, aliases = {}; | |
var getter = function(key) { | |
return getters[key] || (getters[key] = function() { | |
var alias = aliases[key] || key, parser = parsers[key] || parse; | |
return function() { | |
return parser(compute(this)(alias), true); | |
}; | |
}()); | |
}; | |
var setter = function(key) { | |
return setters[key] || (setters[key] = function() { | |
var alias = aliases[key] || key, parser = parsers[key] || parse; | |
return function(value) { | |
this.style[alias] = parser(value, false); | |
}; | |
}()); | |
}; | |
// parsers | |
var trbl = [ "Top", "Right", "Bottom", "Left" ], tlbl = [ "TopLeft", "TopRight", "BottomRight", "BottomLeft" ]; | |
forEach(trbl, function(d) { | |
var bd = "border" + d; | |
forEach([ "margin" + d, "padding" + d, bd + "Width", d.toLowerCase() ], function(n) { | |
parsers[n] = parseLength; | |
}); | |
parsers[bd + "Color"] = parseColor; | |
parsers[bd + "Style"] = parseBorderStyle; | |
// borderDIR | |
parsers[bd] = parseBorder; | |
getters[bd] = function() { | |
return [ getter(bd + "Width").call(this), getter(bd + "Style").call(this), getter(bd + "Color").call(this) ].join(" "); | |
}; | |
}); | |
forEach(tlbl, function(d) { | |
parsers["border" + d + "Radius"] = parseLength; | |
}); | |
parsers.color = parsers.backgroundColor = parseColor; | |
parsers.width = parsers.height = parsers.minWidth = parsers.minHeight = parsers.maxWidth = parsers.maxHeight = parsers.fontSize = parsers.backgroundSize = parseLength; | |
// margin + padding | |
forEach([ "margin", "padding" ], function(name) { | |
parsers[name] = parseShort4; | |
getters[name] = function() { | |
return map(trbl, function(d) { | |
return getter(name + d).call(this); | |
}, this).join(" "); | |
}; | |
}); | |
// borders | |
// borderDIRWidth, borderDIRStyle, borderDIRColor | |
parsers.borderWidth = parseShort4; | |
parsers.borderStyle = function(value, normalize) { | |
if (value == null || value === "") return normalize ? mirror4([ "none" ]).join(" ") : ""; | |
value = clean(value).split(" "); | |
return clean(mirror4(map(value, function(v) { | |
parseBorderStyle(v, normalize); | |
})).join(" ")); | |
}; | |
parsers.borderColor = function(value, normalize) { | |
if (!value || !(value = matchString(value, color.x))) return normalize ? mirror4([ "rgba(0,0,0,1)" ]).join(" ") : ""; | |
return clean(mirror4(map(value, function(v) { | |
return parseColor(v, normalize); | |
})).join(" ")); | |
}; | |
forEach([ "Width", "Style", "Color" ], function(name) { | |
getters["border" + name] = function() { | |
return map(trbl, function(d) { | |
return getter("border" + d + name).call(this); | |
}, this).join(" "); | |
}; | |
}); | |
// borderRadius | |
parsers.borderRadius = parseShort4; | |
getters.borderRadius = function() { | |
return map(tlbl, function(d) { | |
return getter("border" + d + "Radius").call(this); | |
}, this).join(" "); | |
}; | |
// border | |
parsers.border = parseBorder; | |
getters.border = function() { | |
var pvalue; | |
for (var i = 0; i < trbl.length; i++) { | |
var value = getter("border" + trbl[i]).call(this); | |
if (pvalue && value !== pvalue) return null; | |
pvalue = value; | |
} | |
return pvalue; | |
}; | |
// zIndex | |
parsers.zIndex = parseString; | |
// opacity | |
parsers.opacity = parseOpacity; | |
/*(css3)?*/ | |
var filterName = test.style.MsFilter != null && "MsFilter" || test.style.filter != null && "filter"; | |
if (filterName && test.style.opacity == null) { | |
var matchOp = /alpha\(opacity=([\d.]+)\)/i; | |
setters.opacity = function(value) { | |
value = (value = parseOpacity(value)) === "1" ? "" : "alpha(opacity=" + Math.round(value * 100) + ")"; | |
var filter = compute(this)(filterName); | |
return this.style[filterName] = matchOp.test(filter) ? filter.replace(matchOp, value) : filter + " " + value; | |
}; | |
getters.opacity = function() { | |
var match = compute(this)(filterName).match(matchOp); | |
return (!match ? 1 : match[1] / 100) + ""; | |
}; | |
} | |
/*:*/ | |
var parseBoxShadow = parsers.boxShadow = function(value, normalize) { | |
return parseShadow(value, normalize, 4); | |
}; | |
var parseTextShadow = parsers.textShadow = function(value, normalize) { | |
return parseShadow(value, normalize, 3); | |
}; | |
// Aliases | |
forEach([ "Webkit", "Moz", "ms", "O", null ], function(prefix) { | |
forEach([ "transition", "transform", "transformOrigin", "transformStyle", "perspective", "perspectiveOrigin", "backfaceVisibility" ], function(style) { | |
var cc = prefix ? prefix + properCase(style) : style; | |
if (prefix === "ms") hyphenated[cc] = "-ms-" + hyphenate(style); | |
if (test.style[cc] != null) aliases[style] = cc; | |
}); | |
}); | |
var transitionName = aliases.transition, transformName = aliases.transform; | |
// manually disable css3 transitions in Opera, because they do not work properly. | |
if (transitionName === "OTransition") transitionName = null; | |
// this takes care of matrix decomposition on browsers that support only 2d transforms but no CSS3 transitions. | |
// basically, IE9 (and Opera as well, since we disabled CSS3 transitions manually) | |
var parseTransform2d, Transform2d; | |
/*(css3)?*/ | |
if (!transitionName && transformName) (function() { | |
var unmatrix = require("1a"); | |
var v = "\\s*([-\\d\\w.]+)\\s*"; | |
var rMatrix = RegExp("matrix\\(" + [ v, v, v, v, v, v ] + "\\)"); | |
var decomposeMatrix = function(matrix) { | |
var d = unmatrix.apply(null, matrix.match(rMatrix).slice(1)) || [ [ 0, 0 ], 0, 0, [ 0, 0 ] ]; | |
return [ "translate(" + map(d[0], function(v) { | |
return round(v) + "px"; | |
}) + ")", "rotate(" + round(d[1] * 180 / Math.PI) + "deg)", "skewX(" + round(d[2] * 180 / Math.PI) + "deg)", "scale(" + map(d[3], round) + ")" ].join(" "); | |
}; | |
var def0px = function(value) { | |
return value || "0px"; | |
}, def1 = function(value) { | |
return value || "1"; | |
}, def0deg = function(value) { | |
return value || "0deg"; | |
}; | |
var transforms = { | |
translate: function(value) { | |
if (!value) value = "0px,0px"; | |
var values = value.split(","); | |
if (!values[1]) values[1] = "0px"; | |
return map(values, clean) + ""; | |
}, | |
translateX: def0px, | |
translateY: def0px, | |
scale: function(value) { | |
if (!value) value = "1,1"; | |
var values = value.split(","); | |
if (!values[1]) values[1] = values[0]; | |
return map(values, clean) + ""; | |
}, | |
scaleX: def1, | |
scaleY: def1, | |
rotate: def0deg, | |
skewX: def0deg, | |
skewY: def0deg | |
}; | |
Transform2d = prime({ | |
constructor: function(transform) { | |
var names = this.names = []; | |
var values = this.values = []; | |
transform.replace(/(\w+)\(([-.\d\s\w,]+)\)/g, function(match, name, value) { | |
names.push(name); | |
values.push(value); | |
}); | |
}, | |
identity: function() { | |
var functions = []; | |
forEach(this.names, function(name) { | |
var fn = transforms[name]; | |
if (fn) functions.push(name + "(" + fn() + ")"); | |
}); | |
return functions.join(" "); | |
}, | |
sameType: function(transformObject) { | |
return this.names.toString() === transformObject.names.toString(); | |
}, | |
// this is, basically, cheating. | |
// retrieving the matrix value from the dom, rather than calculating it | |
decompose: function() { | |
var transform = this.toString(); | |
test.style.cssText = cssText + hyphenate(transformName) + ":" + transform + ";"; | |
document.body.appendChild(test); | |
var m = compute(test)(transformName); | |
if (!m || m === "none") m = "matrix(1, 0, 0, 1, 0, 0)"; | |
document.body.removeChild(test); | |
return decomposeMatrix(m); | |
} | |
}); | |
Transform2d.prototype.toString = function(clean) { | |
var values = this.values, functions = []; | |
forEach(this.names, function(name, i) { | |
var fn = transforms[name]; | |
if (!fn) return; | |
var value = fn(values[i]); | |
if (!clean || value !== fn()) functions.push(name + "(" + value + ")"); | |
}); | |
return functions.length ? functions.join(" ") : "none"; | |
}; | |
Transform2d.union = function(from, to) { | |
if (from === to) return; | |
// nothing to do | |
var fromMap, toMap; | |
if (from === "none") { | |
toMap = new Transform2d(to); | |
to = toMap.toString(); | |
from = toMap.identity(); | |
fromMap = new Transform2d(from); | |
} else if (to === "none") { | |
fromMap = new Transform2d(from); | |
from = fromMap.toString(); | |
to = fromMap.identity(); | |
toMap = new Transform2d(to); | |
} else { | |
fromMap = new Transform2d(from); | |
from = fromMap.toString(); | |
toMap = new Transform2d(to); | |
to = toMap.toString(); | |
} | |
if (from === to) return; | |
// nothing to do | |
if (!fromMap.sameType(toMap)) { | |
from = fromMap.decompose(); | |
to = toMap.decompose(); | |
} | |
if (from === to) return; | |
// nothing to do | |
return [ from, to ]; | |
}; | |
// this parser makes sure it never gets "matrix" | |
parseTransform2d = parsers.transform = function(transform) { | |
if (!transform || transform === "none") return "none"; | |
return new Transform2d(rMatrix.test(transform) ? decomposeMatrix(transform) : transform).toString(true); | |
}; | |
// this getter makes sure we read from the dom only the first time | |
// this way we save the actual transform and not "matrix" | |
// setting matrix() will use parseTransform2d as well, thus setting the decomposed matrix | |
getters.transform = function() { | |
var s = this.style; | |
return s[transformName] || (s[transformName] = parseTransform2d(compute(this)(transformName))); | |
}; | |
})(); | |
/*:*/ | |
// tries to match from and to values | |
var prepare = function(node, property, to) { | |
var parser = parsers[property] || parse, from = getter(property).call(node), // "normalized" by the getter | |
to = parser(to, true); | |
// normalize parsed property | |
if (from === to) return; | |
if (parser === parseLength || parser === parseBorder || parser === parseShort4) { | |
var toAll = to.match(rgLength), i = 0; | |
// this should always match something | |
if (toAll) from = from.replace(rgLength, function(fromFull, fromValue, fromUnit) { | |
var toFull = toAll[i++], toMatched = toFull.match(rLengthNum), toUnit = toMatched[2]; | |
if (fromUnit !== toUnit) { | |
var fromPixels = fromUnit === "px" ? fromValue : pixelRatio(node, fromUnit) * fromValue; | |
return round(fromPixels / pixelRatio(node, toUnit)) + toUnit; | |
} | |
return fromFull; | |
}); | |
if (i > 0) setter(property).call(node, from); | |
} else if (parser === parseTransform2d) { | |
// IE9/Opera | |
return Transform2d.union(from, to); | |
} | |
/*:*/ | |
return from !== to ? [ from, to ] : null; | |
}; | |
// BrowserAnimation | |
var BrowserAnimation = prime({ | |
inherits: fx, | |
constructor: function BrowserAnimation(node, property) { | |
var _getter = getter(property), _setter = setter(property); | |
this.get = function() { | |
return _getter.call(node); | |
}; | |
this.set = function(value) { | |
return _setter.call(node, value); | |
}; | |
BrowserAnimation.parent.constructor.call(this, this.set); | |
this.node = node; | |
this.property = property; | |
} | |
}); | |
var JSAnimation; | |
/*(css3)?*/ | |
JSAnimation = prime({ | |
inherits: BrowserAnimation, | |
constructor: function JSAnimation() { | |
return JSAnimation.parent.constructor.apply(this, arguments); | |
}, | |
start: function(to) { | |
this.stop(); | |
if (this.duration === 0) { | |
this.cancel(to); | |
return this; | |
} | |
var fromTo = prepare(this.node, this.property, to); | |
if (!fromTo) { | |
this.cancel(to); | |
return this; | |
} | |
JSAnimation.parent.start.apply(this, fromTo); | |
if (!this.cancelStep) return this; | |
// the animation would have started but we need additional checks | |
var parser = parsers[this.property] || parse; | |
// complex interpolations JSAnimation can't handle | |
// even CSS3 animation gracefully fail with some of those edge cases | |
// other "simple" properties, such as `border` can have different templates | |
// because of string properties like "solid" and "dashed" | |
if ((parser === parseBoxShadow || parser === parseTextShadow || parser === parse) && this.templateFrom !== this.templateTo) { | |
this.cancelStep(); | |
delete this.cancelStep; | |
this.cancel(to); | |
} | |
return this; | |
}, | |
parseEquation: function(equation) { | |
if (typeof equation === "string") return JSAnimation.parent.parseEquation.call(this, equation); | |
} | |
}); | |
/*:*/ | |
// CSSAnimation | |
var remove3 = function(value, a, b, c) { | |
var index = indexOf(a, value); | |
if (index !== -1) { | |
a.splice(index, 1); | |
b.splice(index, 1); | |
c.splice(index, 1); | |
} | |
}; | |
var CSSAnimation = prime({ | |
inherits: BrowserAnimation, | |
constructor: function CSSAnimation(node, property) { | |
CSSAnimation.parent.constructor.call(this, node, property); | |
this.hproperty = hyphenate(aliases[property] || property); | |
var self = this; | |
this.bSetTransitionCSS = function(time) { | |
self.setTransitionCSS(time); | |
}; | |
this.bSetStyleCSS = function(time) { | |
self.setStyleCSS(time); | |
}; | |
this.bComplete = function() { | |
self.complete(); | |
}; | |
}, | |
start: function(to) { | |
this.stop(); | |
if (this.duration === 0) { | |
this.cancel(to); | |
return this; | |
} | |
var fromTo = prepare(this.node, this.property, to); | |
if (!fromTo) { | |
this.cancel(to); | |
return this; | |
} | |
this.to = fromTo[1]; | |
// setting transition styles immediately will make good browsers behave weirdly | |
// because DOM changes are always deferred, so we requestFrame | |
this.cancelSetTransitionCSS = requestFrame(this.bSetTransitionCSS); | |
return this; | |
}, | |
setTransitionCSS: function(time) { | |
delete this.cancelSetTransitionCSS; | |
this.resetCSS(true); | |
// firefox flickers if we set css for transition as well as styles at the same time | |
// so, other than deferring transition styles we defer actual styles as well on a requestFrame | |
this.cancelSetStyleCSS = requestFrame(this.bSetStyleCSS); | |
}, | |
setStyleCSS: function(time) { | |
delete this.cancelSetStyleCSS; | |
var duration = this.duration; | |
// we use setTimeout instead of transitionEnd because some browsers (looking at you foxy) | |
// incorrectly set event.propertyName, so we cannot check which animation we are canceling | |
this.cancelComplete = setTimeout(this.bComplete, duration); | |
this.endTime = time + duration; | |
this.set(this.to); | |
}, | |
complete: function() { | |
delete this.cancelComplete; | |
this.resetCSS(); | |
this.callback(this.endTime); | |
}, | |
stop: function(hard) { | |
if (this.cancelExit) { | |
this.cancelExit(); | |
delete this.cancelExit; | |
} else if (this.cancelSetTransitionCSS) { | |
// if cancelSetTransitionCSS is set, means nothing is set yet | |
this.cancelSetTransitionCSS(); | |
//so we cancel and we're good | |
delete this.cancelSetTransitionCSS; | |
} else if (this.cancelSetStyleCSS) { | |
// if cancelSetStyleCSS is set, means transition css has been set, but no actual styles. | |
this.cancelSetStyleCSS(); | |
delete this.cancelSetStyleCSS; | |
// if its a hard stop (and not another start on top of the current animation) | |
// we need to reset the transition CSS | |
if (hard) this.resetCSS(); | |
} else if (this.cancelComplete) { | |
// if cancelComplete is set, means style and transition css have been set, not yet completed. | |
clearTimeout(this.cancelComplete); | |
delete this.cancelComplete; | |
// if its a hard stop (and not another start on top of the current animation) | |
// we need to reset the transition CSS set the current animation styles | |
if (hard) { | |
this.resetCSS(); | |
this.set(this.get()); | |
} | |
} | |
return this; | |
}, | |
resetCSS: function(inclusive) { | |
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); | |
remove3("all", properties, durations, equations); | |
remove3(this.hproperty, properties, durations, equations); | |
if (inclusive) { | |
properties.push(this.hproperty); | |
durations.push(this.duration + "ms"); | |
equations.push("cubic-bezier(" + this.equation + ")"); | |
} | |
var nodeStyle = this.node.style; | |
nodeStyle[transitionName + "Property"] = properties; | |
nodeStyle[transitionName + "Duration"] = durations; | |
nodeStyle[transitionName + "TimingFunction"] = equations; | |
}, | |
parseEquation: function(equation) { | |
if (typeof equation === "string") return CSSAnimation.parent.parseEquation.call(this, equation, true); | |
} | |
}); | |
// elements methods | |
var BaseAnimation = JSAnimation; | |
var moofx = function(x, y) { | |
return typeof x === "function" ? fx(x) : elements(x, y); | |
}; | |
elements.implement({ | |
// {properties}, options or | |
// property, value options | |
animate: function(A, B, C) { | |
var styles = A, options = B; | |
if (typeof A === "string") { | |
styles = {}; | |
styles[A] = B; | |
options = C; | |
} | |
if (options == null) options = {}; | |
var type = typeof options; | |
options = type === "function" ? { | |
callback: options | |
} : type === "string" || type === "number" ? { | |
duration: options | |
} : options; | |
var callback = options.callback || function() {}, completed = 0, length = 0; | |
options.callback = function(t) { | |
if (++completed === length) callback(t); | |
}; | |
for (var property in styles) { | |
var value = styles[property], property = camelCase(property); | |
this.forEach(function(node) { | |
length++; | |
var self = elements(node), anims = self._animations || (self._animations = {}); | |
var anim = anims[property] || (anims[property] = new BaseAnimation(node, property)); | |
anim.setOptions(options).start(value); | |
}); | |
} | |
return this; | |
}, | |
// {properties} or | |
// property, value | |
style: function(A, B) { | |
var styles = A; | |
if (typeof A === "string") { | |
styles = {}; | |
styles[A] = B; | |
} | |
for (var property in styles) { | |
var value = styles[property], set = setter(property = camelCase(property)); | |
this.forEach(function(node) { | |
var self = elements(node), anims = self._animations, anim; | |
if (anims && (anim = anims[property])) anim.stop(true); | |
set.call(node, value); | |
}); | |
} | |
return this; | |
}, | |
compute: function(property) { | |
property = camelCase(property); | |
var node = this[0]; | |
// return default matrix for transform, instead of parsed (for consistency) | |
if (property === "transform" && parseTransform2d) return compute(node)(transformName); | |
var value = getter(property).call(node); | |
// unit conversion to `px` | |
return value != null ? value.replace(rgLength, function(match, value, unit) { | |
return unit === "px" ? match : pixelRatio(node, unit) * value + "px"; | |
}) : ""; | |
} | |
}); | |
moofx.parse = function(property, value, normalize) { | |
return (parsers[camelCase(property)] || parse)(value, normalize); | |
}; | |
module.exports = moofx; | |
}, | |
"5": function(require, module, exports, global) { | |
/* | |
prime | |
- prototypal inheritance | |
*/ | |
"use strict"; | |
var hasOwn = require("6"), forIn = require("7"), mixIn = require("8"), filter = require("a"), create = require("b"), type = require("c"); | |
var defineProperty = Object.defineProperty, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | |
try { | |
defineProperty({}, "~", {}); | |
getOwnPropertyDescriptor({}, "~"); | |
} catch (e) { | |
defineProperty = null; | |
getOwnPropertyDescriptor = null; | |
} | |
var define = function(value, key, from) { | |
defineProperty(this, key, getOwnPropertyDescriptor(from, key) || { | |
writable: true, | |
enumerable: true, | |
configurable: true, | |
value: value | |
}); | |
}; | |
var copy = function(value, key) { | |
this[key] = value; | |
}; | |
var implement = function(proto) { | |
forIn(proto, defineProperty ? define : copy, this.prototype); | |
return this; | |
}; | |
var verbs = /^constructor|inherits|mixin$/; | |
var prime = function(proto) { | |
if (type(proto) === "function") proto = { | |
constructor: proto | |
}; | |
var superprime = proto.inherits; | |
// if our nice proto object has no own constructor property | |
// then we proceed using a ghosting constructor that all it does is | |
// call the parent's constructor if it has a superprime, else an empty constructor | |
// proto.constructor becomes the effective constructor | |
var constructor = hasOwn(proto, "constructor") ? proto.constructor : superprime ? function() { | |
return superprime.apply(this, arguments); | |
} : function() {}; | |
if (superprime) { | |
mixIn(constructor, superprime); | |
var superproto = superprime.prototype; | |
// inherit from superprime | |
var cproto = constructor.prototype = create(superproto); | |
// setting constructor.parent to superprime.prototype | |
// because it's the shortest possible absolute reference | |
constructor.parent = superproto; | |
cproto.constructor = constructor; | |
} | |
if (!constructor.implement) constructor.implement = implement; | |
var mixins = proto.mixin; | |
if (mixins) { | |
if (type(mixins) !== "array") mixins = [ mixins ]; | |
for (var i = 0; i < mixins.length; i++) constructor.implement(create(mixins[i].prototype)); | |
} | |
// implement proto and return constructor | |
return constructor.implement(filter(proto, function(value, key) { | |
return !key.match(verbs); | |
})); | |
}; | |
module.exports = prime; | |
}, | |
"6": function(require, module, exports, global) { | |
/* | |
object:hasOwn | |
*/ | |
"use strict"; | |
var hasOwnProperty = Object.hasOwnProperty; | |
var hasOwn = function(self, key) { | |
return hasOwnProperty.call(self, key); | |
}; | |
module.exports = hasOwn; | |
}, | |
"7": function(require, module, exports, global) { | |
/* | |
object:forIn | |
*/ | |
"use strict"; | |
var has = require("6"); | |
var forIn = function(self, method, context) { | |
for (var key in self) if (method.call(context, self[key], key, self) === false) break; | |
return self; | |
}; | |
if (!{ | |
valueOf: 0 | |
}.propertyIsEnumerable("valueOf")) { | |
// fix for stupid IE enumeration bug | |
var buggy = "constructor,toString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString".split(","); | |
var proto = Object.prototype; | |
forIn = function(self, method, context) { | |
for (var key in self) if (method.call(context, self[key], key, self) === false) return self; | |
for (var i = 0; key = buggy[i]; i++) { | |
var value = self[key]; | |
if ((value !== proto[key] || has(self, key)) && method.call(context, value, key, self) === false) break; | |
} | |
return self; | |
}; | |
} | |
module.exports = forIn; | |
}, | |
"8": function(require, module, exports, global) { | |
/* | |
object:mixIn | |
*/ | |
"use strict"; | |
var forOwn = require("9"); | |
var copy = function(value, key) { | |
this[key] = value; | |
}; | |
var mixIn = function(self) { | |
for (var i = 1, l = arguments.length; i < l; i++) forOwn(arguments[i], copy, self); | |
return self; | |
}; | |
module.exports = mixIn; | |
}, | |
"9": function(require, module, exports, global) { | |
/* | |
object:forOwn | |
*/ | |
"use strict"; | |
var forIn = require("7"), hasOwn = require("6"); | |
var forOwn = function(self, method, context) { | |
forIn(self, function(value, key) { | |
if (hasOwn(self, key)) return method.call(context, value, key, self); | |
}); | |
return self; | |
}; | |
module.exports = forOwn; | |
}, | |
a: function(require, module, exports, global) { | |
/* | |
object:filter | |
*/ | |
"use strict"; | |
var forIn = require("7"); | |
var filter = function(self, method, context) { | |
var results = {}; | |
forIn(self, function(value, key) { | |
if (method.call(context, value, key, self)) results[key] = value; | |
}); | |
return results; | |
}; | |
module.exports = filter; | |
}, | |
b: function(require, module, exports, global) { | |
/* | |
object:create | |
*/ | |
"use strict"; | |
var create = function(self) { | |
var constructor = function() {}; | |
constructor.prototype = self; | |
return new constructor(); | |
}; | |
module.exports = create; | |
}, | |
c: function(require, module, exports, global) { | |
/* | |
type | |
*/ | |
"use strict"; | |
var toString = Object.prototype.toString, types = /number|object|array|string|function|date|regexp|boolean/; | |
var type = function(object) { | |
if (object == null) return "null"; | |
var string = toString.call(object).slice(8, -1).toLowerCase(); | |
if (string === "number" && isNaN(object)) return "null"; | |
if (types.test(string)) return string; | |
return "object"; | |
}; | |
module.exports = type; | |
}, | |
d: function(require, module, exports, global) { | |
var toString = require("e"); | |
var replaceAccents = require("f"); | |
var removeNonWord = require("g"); | |
var upperCase = require("h"); | |
var lowerCase = require("i"); | |
/** | |
* Convert string to camelCase text. | |
*/ | |
function camelCase(str) { | |
str = toString(str); | |
str = replaceAccents(str); | |
str = removeNonWord(str).replace(/[\-_]/g, " ").replace(/\s[a-z]/g, upperCase).replace(/\s+/g, "").replace(/^[A-Z]/g, lowerCase); | |
//convert first char to lowercase | |
return str; | |
} | |
module.exports = camelCase; | |
}, | |
e: function(require, module, exports, global) { | |
/** | |
* Typecast a value to a String, using an empty string value for null or | |
* undefined. | |
*/ | |
function toString(val) { | |
return val == null ? "" : val.toString(); | |
} | |
module.exports = toString; | |
}, | |
f: function(require, module, exports, global) { | |
var toString = require("e"); | |
/** | |
* Replaces all accented chars with regular ones | |
*/ | |
function replaceAccents(str) { | |
str = toString(str); | |
// verifies if the String has accents and replace them | |
if (str.search(/[\xC0-\xFF]/g) > -1) { | |
str = str.replace(/[\xC0-\xC5]/g, "A").replace(/[\xC6]/g, "AE").replace(/[\xC7]/g, "C").replace(/[\xC8-\xCB]/g, "E").replace(/[\xCC-\xCF]/g, "I").replace(/[\xD0]/g, "D").replace(/[\xD1]/g, "N").replace(/[\xD2-\xD6\xD8]/g, "O").replace(/[\xD9-\xDC]/g, "U").replace(/[\xDD]/g, "Y").replace(/[\xDE]/g, "P").replace(/[\xE0-\xE5]/g, "a").replace(/[\xE6]/g, "ae").replace(/[\xE7]/g, "c").replace(/[\xE8-\xEB]/g, "e").replace(/[\xEC-\xEF]/g, "i").replace(/[\xF1]/g, "n").replace(/[\xF2-\xF6\xF8]/g, "o").replace(/[\xF9-\xFC]/g, "u").replace(/[\xFE]/g, "p").replace(/[\xFD\xFF]/g, "y"); | |
} | |
return str; | |
} | |
module.exports = replaceAccents; | |
}, | |
g: function(require, module, exports, global) { | |
var toString = require("e"); | |
/** | |
* Remove non-word chars. | |
*/ | |
function removeNonWord(str) { | |
str = toString(str); | |
return str.replace(/[^0-9a-zA-Z\xC0-\xFF \-_]/g, ""); | |
} | |
module.exports = removeNonWord; | |
}, | |
h: function(require, module, exports, global) { | |
var toString = require("e"); | |
/** | |
* "Safer" String.toUpperCase() | |
*/ | |
function upperCase(str) { | |
str = toString(str); | |
return str.toUpperCase(); | |
} | |
module.exports = upperCase; | |
}, | |
i: function(require, module, exports, global) { | |
var toString = require("e"); | |
/** | |
* "Safer" String.toLowerCase() | |
*/ | |
function lowerCase(str) { | |
str = toString(str); | |
return str.toLowerCase(); | |
} | |
module.exports = lowerCase; | |
}, | |
j: function(require, module, exports, global) { | |
var toString = require("e"); | |
var WHITE_SPACES = require("k"); | |
var ltrim = require("l"); | |
var rtrim = require("m"); | |
/** | |
* Remove white-spaces from beginning and end of string. | |
*/ | |
function trim(str, chars) { | |
str = toString(str); | |
chars = chars || WHITE_SPACES; | |
return ltrim(rtrim(str, chars), chars); | |
} | |
module.exports = trim; | |
}, | |
k: function(require, module, exports, global) { | |
/** | |
* Contains all Unicode white-spaces. Taken from | |
* http://en.wikipedia.org/wiki/Whitespace_character. | |
*/ | |
module.exports = [ " ", "\n", "\r", " ", "\f", "", " ", " ", "", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\u2028", "\u2029", " ", " ", " " ]; | |
}, | |
l: function(require, module, exports, global) { | |
var toString = require("e"); | |
var WHITE_SPACES = require("k"); | |
/** | |
* Remove chars from beginning of string. | |
*/ | |
function ltrim(str, chars) { | |
str = toString(str); | |
chars = chars || WHITE_SPACES; | |
var start = 0, len = str.length, charLen = chars.length, found = true, i, c; | |
while (found && start < len) { | |
found = false; | |
i = -1; | |
c = str.charAt(start); | |
while (++i < charLen) { | |
if (c === chars[i]) { | |
found = true; | |
start++; | |
break; | |
} | |
} | |
} | |
return start >= len ? "" : str.substr(start, len); | |
} | |
module.exports = ltrim; | |
}, | |
m: function(require, module, exports, global) { | |
var toString = require("e"); | |
var WHITE_SPACES = require("k"); | |
/** | |
* Remove chars from end of string. | |
*/ | |
function rtrim(str, chars) { | |
str = toString(str); | |
chars = chars || WHITE_SPACES; | |
var end = str.length - 1, charLen = chars.length, found = true, i, c; | |
while (found && end >= 0) { | |
found = false; | |
i = -1; | |
c = str.charAt(end); | |
while (++i < charLen) { | |
if (c === chars[i]) { | |
found = true; | |
end--; | |
break; | |
} | |
} | |
} | |
return end >= 0 ? str.substring(0, end + 1) : ""; | |
} | |
module.exports = rtrim; | |
}, | |
n: function(require, module, exports, global) { | |
var toString = require("e"); | |
var lowerCase = require("i"); | |
var upperCase = require("h"); | |
/** | |
* UPPERCASE first char of each word. | |
*/ | |
function properCase(str) { | |
str = toString(str); | |
return lowerCase(str).replace(/^\w|\s\w/g, upperCase); | |
} | |
module.exports = properCase; | |
}, | |
o: function(require, module, exports, global) { | |
var toString = require("e"); | |
var slugify = require("p"); | |
var unCamelCase = require("q"); | |
/** | |
* Replaces spaces with hyphens, split camelCase text, remove non-word chars, remove accents and convert to lower case. | |
*/ | |
function hyphenate(str) { | |
str = toString(str); | |
str = unCamelCase(str); | |
return slugify(str, "-"); | |
} | |
module.exports = hyphenate; | |
}, | |
p: function(require, module, exports, global) { | |
var toString = require("e"); | |
var replaceAccents = require("f"); | |
var removeNonWord = require("g"); | |
var trim = require("j"); | |
/** | |
* Convert to lower case, remove accents, remove non-word chars and | |
* replace spaces with the specified delimeter. | |
* Does not split camelCase text. | |
*/ | |
function slugify(str, delimeter) { | |
str = toString(str); | |
if (delimeter == null) { | |
delimeter = "-"; | |
} | |
str = replaceAccents(str); | |
str = removeNonWord(str); | |
str = trim(str).replace(/ +/g, delimeter).toLowerCase(); | |
return str; | |
} | |
module.exports = slugify; | |
}, | |
q: function(require, module, exports, global) { | |
var toString = require("e"); | |
var CAMEL_CASE_BORDER = /([a-z\xE0-\xFF])([A-Z\xC0\xDF])/g; | |
/** | |
* Add space between camelCase text. | |
*/ | |
function unCamelCase(str, delimiter) { | |
if (delimiter == null) { | |
delimiter = " "; | |
} | |
function join(str, c1, c2) { | |
return c1 + delimiter + c2; | |
} | |
str = toString(str); | |
str = str.replace(CAMEL_CASE_BORDER, join); | |
str = str.toLowerCase(); | |
//add space between camelCase text | |
return str; | |
} | |
module.exports = unCamelCase; | |
}, | |
r: function(require, module, exports, global) { | |
var makeIterator = require("s"); | |
/** | |
* Array map | |
*/ | |
function map(arr, callback, thisObj) { | |
callback = makeIterator(callback, thisObj); | |
var results = []; | |
if (arr == null) { | |
return results; | |
} | |
var i = -1, len = arr.length; | |
while (++i < len) { | |
results[i] = callback(arr[i], i, arr); | |
} | |
return results; | |
} | |
module.exports = map; | |
}, | |
s: function(require, module, exports, global) { | |
var prop = require("t"); | |
var deepMatches = require("u"); | |
/** | |
* Converts argument into a valid iterator. | |
* Used internally on most array/object/collection methods that receives a | |
* callback/iterator providing a shortcut syntax. | |
*/ | |
function makeIterator(src, thisObj) { | |
switch (typeof src) { | |
case "function": | |
// function is the first to improve perf (most common case) | |
return typeof thisObj !== "undefined" ? function(val, i, arr) { | |
return src.call(thisObj, val, i, arr); | |
} : src; | |
case "object": | |
// typeof null == "object" | |
return src != null ? function(val) { | |
return deepMatches(val, src); | |
} : src; | |
case "string": | |
case "number": | |
return prop(src); | |
default: | |
return src; | |
} | |
} | |
module.exports = makeIterator; | |
}, | |
t: function(require, module, exports, global) { | |
/** | |
* Returns a function that gets a property of the passed object | |
*/ | |
function prop(name) { | |
return function(obj) { | |
return obj[name]; | |
}; | |
} | |
module.exports = prop; | |
}, | |
u: function(require, module, exports, global) { | |
var forOwn = require("v"); | |
var isArray = require("y"); | |
function containsMatch(array, pattern) { | |
var i = -1, length = array.length; | |
while (++i < length) { | |
if (deepMatches(array[i], pattern)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function matchArray(target, pattern) { | |
var i = -1, patternLength = pattern.length; | |
while (++i < patternLength) { | |
if (!containsMatch(target, pattern[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function matchObject(target, pattern) { | |
var result = true; | |
forOwn(pattern, function(val, key) { | |
if (!deepMatches(target[key], val)) { | |
// Return false to break out of forOwn early | |
return result = false; | |
} | |
}); | |
return result; | |
} | |
/** | |
* Recursively check if the objects match. | |
*/ | |
function deepMatches(target, pattern) { | |
if (target && typeof target === "object") { | |
if (isArray(target) && isArray(pattern)) { | |
return matchArray(target, pattern); | |
} else { | |
return matchObject(target, pattern); | |
} | |
} else { | |
return target === pattern; | |
} | |
} | |
module.exports = deepMatches; | |
}, | |
v: function(require, module, exports, global) { | |
var hasOwn = require("w"); | |
var forIn = require("x"); | |
/** | |
* Similar to Array/forEach but works over object properties and fixes Don't | |
* Enum bug on IE. | |
* based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation | |
*/ | |
function forOwn(obj, fn, thisObj) { | |
forIn(obj, function(val, key) { | |
if (hasOwn(obj, key)) { | |
return fn.call(thisObj, obj[key], key, obj); | |
} | |
}); | |
} | |
module.exports = forOwn; | |
}, | |
w: function(require, module, exports, global) { | |
/** | |
* Safer Object.hasOwnProperty | |
*/ | |
function hasOwn(obj, prop) { | |
return Object.prototype.hasOwnProperty.call(obj, prop); | |
} | |
module.exports = hasOwn; | |
}, | |
x: function(require, module, exports, global) { | |
var _hasDontEnumBug, _dontEnums; | |
function checkDontEnum() { | |
_dontEnums = [ "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor" ]; | |
_hasDontEnumBug = true; | |
for (var key in { | |
toString: null | |
}) { | |
_hasDontEnumBug = false; | |
} | |
} | |
/** | |
* Similar to Array/forEach but works over object properties and fixes Don't | |
* Enum bug on IE. | |
* based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation | |
*/ | |
function forIn(obj, fn, thisObj) { | |
var key, i = 0; | |
// no need to check if argument is a real object that way we can use | |
// it for arrays, functions, date, etc. | |
//post-pone check till needed | |
if (_hasDontEnumBug == null) checkDontEnum(); | |
for (key in obj) { | |
if (exec(fn, obj, key, thisObj) === false) { | |
break; | |
} | |
} | |
if (_hasDontEnumBug) { | |
while (key = _dontEnums[i++]) { | |
// since we aren't using hasOwn check we need to make sure the | |
// property was overwritten | |
if (obj[key] !== Object.prototype[key]) { | |
if (exec(fn, obj, key, thisObj) === false) { | |
break; | |
} | |
} | |
} | |
} | |
} | |
function exec(fn, obj, key, thisObj) { | |
return fn.call(thisObj, obj[key], key, obj); | |
} | |
module.exports = forIn; | |
}, | |
y: function(require, module, exports, global) { | |
var isKind = require("z"); | |
/** | |
*/ | |
var isArray = Array.isArray || function(val) { | |
return isKind(val, "Array"); | |
}; | |
module.exports = isArray; | |
}, | |
z: function(require, module, exports, global) { | |
var kindOf = require("10"); | |
/** | |
* Check if value is from a specific "kind". | |
*/ | |
function isKind(val, kind) { | |
return kindOf(val) === kind; | |
} | |
module.exports = isKind; | |
}, | |
"10": function(require, module, exports, global) { | |
var _rKind = /^\[object (.*)\]$/, _toString = Object.prototype.toString, UNDEF; | |
/** | |
* Gets the "kind" of value. (e.g. "String", "Number", etc) | |
*/ | |
function kindOf(val) { | |
if (val === null) { | |
return "Null"; | |
} else if (val === UNDEF) { | |
return "Undefined"; | |
} else { | |
return _rKind.exec(_toString.call(val))[1]; | |
} | |
} | |
module.exports = kindOf; | |
}, | |
"11": function(require, module, exports, global) { | |
/** | |
* Array forEach | |
*/ | |
function forEach(arr, callback, thisObj) { | |
if (arr == null) { | |
return; | |
} | |
var i = -1, len = arr.length; | |
while (++i < len) { | |
// we iterate over sparse items since there is no way to make it | |
// work properly on IE 7-8. see #64 | |
if (callback.call(thisObj, arr[i], i, arr) === false) { | |
break; | |
} | |
} | |
} | |
module.exports = forEach; | |
}, | |
"12": function(require, module, exports, global) { | |
/* | |
elements | |
*/ | |
"use strict"; | |
var prime = require("5"), forEach = require("13"), map = require("14"), filter = require("15"), every = require("16"), some = require("17"); | |
// uniqueID | |
var uniqueIndex = 0; | |
var uniqueID = function(n) { | |
return n === global ? "global" : n.uniqueNumber || (n.uniqueNumber = "n:" + (uniqueIndex++).toString(36)); | |
}; | |
var instances = {}; | |
// elements prime | |
var $ = prime({ | |
constructor: function $(n, context) { | |
if (n == null) return this && this.constructor === $ ? new elements() : null; | |
var self = n; | |
if (n.constructor !== elements) { | |
self = new elements(); | |
var uid; | |
if (typeof n === "string") { | |
if (!self.search) return null; | |
self[self.length++] = context || document; | |
return self.search(n); | |
} | |
if (n.nodeType || n === global) { | |
self[self.length++] = n; | |
} else if (n.length) { | |
// this could be an array, or any object with a length attribute, | |
// including another instance of elements from another interface. | |
var uniques = {}; | |
for (var i = 0, l = n.length; i < l; i++) { | |
// perform elements flattening | |
var nodes = $(n[i], context); | |
if (nodes && nodes.length) for (var j = 0, k = nodes.length; j < k; j++) { | |
var node = nodes[j]; | |
uid = uniqueID(node); | |
if (!uniques[uid]) { | |
self[self.length++] = node; | |
uniques[uid] = true; | |
} | |
} | |
} | |
} | |
} | |
if (!self.length) return null; | |
// when length is 1 always use the same elements instance | |
if (self.length === 1) { | |
uid = uniqueID(self[0]); | |
return instances[uid] || (instances[uid] = self); | |
} | |
return self; | |
} | |
}); | |
var elements = prime({ | |
inherits: $, | |
constructor: function elements() { | |
this.length = 0; | |
}, | |
unlink: function() { | |
return this.map(function(node, i) { | |
delete instances[uniqueID(node)]; | |
return node; | |
}); | |
}, | |
// straight es5 prototypes (or emulated methods) | |
forEach: function(method, context) { | |
return forEach(this, method, context); | |
}, | |
map: function(method, context) { | |
return map(this, method, context); | |
}, | |
filter: function(method, context) { | |
return filter(this, method, context); | |
}, | |
every: function(method, context) { | |
return every(this, method, context); | |
}, | |
some: function(method, context) { | |
return some(this, method, context); | |
} | |
}); | |
module.exports = $; | |
}, | |
"13": function(require, module, exports, global) { | |
/* | |
array:forEach | |
*/ | |
"use strict"; | |
var forEach = function(self, method, context) { | |
for (var i = 0, l = self.length >>> 0; i < l; i++) { | |
if (method.call(context, self[i], i, self) === false) break; | |
} | |
return self; | |
}; | |
module.exports = forEach; | |
}, | |
"14": function(require, module, exports, global) { | |
/* | |
array:map | |
*/ | |
"use strict"; | |
var map = function(self, method, context) { | |
var length = self.length >>> 0, results = Array(length); | |
for (var i = 0, l = length; i < l; i++) { | |
results[i] = method.call(context, self[i], i, self); | |
} | |
return results; | |
}; | |
module.exports = map; | |
}, | |
"15": function(require, module, exports, global) { | |
/* | |
array:filter | |
*/ | |
"use strict"; | |
var filter = function(self, method, context) { | |
var results = []; | |
for (var i = 0, l = self.length >>> 0; i < l; i++) { | |
var value = self[i]; | |
if (method.call(context, value, i, self)) results.push(value); | |
} | |
return results; | |
}; | |
module.exports = filter; | |
}, | |
"16": function(require, module, exports, global) { | |
/* | |
array:every | |
*/ | |
"use strict"; | |
var every = function(self, method, context) { | |
for (var i = 0, l = self.length >>> 0; i < l; i++) { | |
if (!method.call(context, self[i], i, self)) return false; | |
} | |
return true; | |
}; | |
module.exports = every; | |
}, | |
"17": function(require, module, exports, global) { | |
/* | |
array:some | |
*/ | |
"use strict"; | |
var some = function(self, method, context) { | |
for (var i = 0, l = self.length >>> 0; i < l; i++) { | |
if (method.call(context, self[i], i, self)) return true; | |
} | |
return false; | |
}; | |
module.exports = some; | |
}, | |
"18": function(require, module, exports, global) { | |
/* | |
fx | |
*/ | |
"use strict"; | |
var prime = require("5"), requestFrame = require("2").request, bezier = require("19"); | |
var map = require("r"); | |
var sDuration = "([\\d.]+)(s|ms)?", sCubicBezier = "cubic-bezier\\(([-.\\d]+),([-.\\d]+),([-.\\d]+),([-.\\d]+)\\)"; | |
var rDuration = RegExp(sDuration), rCubicBezier = RegExp(sCubicBezier), rgCubicBezier = RegExp(sCubicBezier, "g"); | |
// equations collection | |
var equations = { | |
"default": "cubic-bezier(0.25, 0.1, 0.25, 1.0)", | |
linear: "cubic-bezier(0, 0, 1, 1)", | |
"ease-in": "cubic-bezier(0.42, 0, 1.0, 1.0)", | |
"ease-out": "cubic-bezier(0, 0, 0.58, 1.0)", | |
"ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1.0)" | |
}; | |
equations.ease = equations["default"]; | |
var compute = function(from, to, delta) { | |
return (to - from) * delta + from; | |
}; | |
var divide = function(string) { | |
var numbers = []; | |
var template = (string + "").replace(/[-.\d]+/g, function(number) { | |
numbers.push(+number); | |
return "@"; | |
}); | |
return [ numbers, template ]; | |
}; | |
var Fx = prime({ | |
constructor: function Fx(render, options) { | |
// set options | |
this.setOptions(options); | |
// renderer | |
this.render = render || function() {}; | |
// bound functions | |
var self = this; | |
this.bStep = function(t) { | |
return self.step(t); | |
}; | |
this.bExit = function(time) { | |
self.exit(time); | |
}; | |
}, | |
setOptions: function(options) { | |
if (options == null) options = {}; | |
if (!(this.duration = this.parseDuration(options.duration || "500ms"))) throw new Error("invalid duration"); | |
if (!(this.equation = this.parseEquation(options.equation || "default"))) throw new Error("invalid equation"); | |
this.callback = options.callback || function() {}; | |
return this; | |
}, | |
parseDuration: function(duration) { | |
if (duration = (duration + "").match(rDuration)) { | |
var time = +duration[1], unit = duration[2] || "ms"; | |
if (unit === "s") return time * 1e3; | |
if (unit === "ms") return time; | |
} | |
}, | |
parseEquation: function(equation, array) { | |
var type = typeof equation; | |
if (type === "function") { | |
// function | |
return equation; | |
} else if (type === "string") { | |
// cubic-bezier string | |
equation = equations[equation] || equation; | |
var match = equation.replace(/\s+/g, "").match(rCubicBezier); | |
if (match) { | |
equation = map(match.slice(1), function(v) { | |
return +v; | |
}); | |
if (array) return equation; | |
if (equation.toString() === "0,0,1,1") return function(x) { | |
return x; | |
}; | |
type = "object"; | |
} | |
} | |
if (type === "object") { | |
// array | |
return bezier(equation[0], equation[1], equation[2], equation[3], 1e3 / 60 / this.duration / 4); | |
} | |
}, | |
cancel: function(to) { | |
this.to = to; | |
this.cancelExit = requestFrame(this.bExit); | |
}, | |
exit: function(time) { | |
this.render(this.to); | |
delete this.cancelExit; | |
this.callback(time); | |
}, | |
start: function(from, to) { | |
this.stop(); | |
if (this.duration === 0) { | |
this.cancel(to); | |
return this; | |
} | |
this.isArray = false; | |
this.isNumber = false; | |
var fromType = typeof from, toType = typeof to; | |
if (fromType === "object" && toType === "object") { | |
this.isArray = true; | |
} else if (fromType === "number" && toType === "number") { | |
this.isNumber = true; | |
} | |
var from_ = divide(from), to_ = divide(to); | |
this.from = from_[0]; | |
this.to = to_[0]; | |
this.templateFrom = from_[1]; | |
this.templateTo = to_[1]; | |
if (this.from.length !== this.to.length || this.from.toString() === this.to.toString()) { | |
this.cancel(to); | |
return this; | |
} | |
delete this.time; | |
this.length = this.from.length; | |
this.cancelStep = requestFrame(this.bStep); | |
return this; | |
}, | |
stop: function() { | |
if (this.cancelExit) { | |
this.cancelExit(); | |
delete this.cancelExit; | |
} else if (this.cancelStep) { | |
this.cancelStep(); | |
delete this.cancelStep; | |
} | |
return this; | |
}, | |
step: function(now) { | |
this.time || (this.time = now); | |
var factor = (now - this.time) / this.duration; | |
if (factor > 1) factor = 1; | |
var delta = this.equation(factor), from = this.from, to = this.to, tpl = this.templateTo; | |
for (var i = 0, l = this.length; i < l; i++) { | |
var f = from[i], t = to[i]; | |
tpl = tpl.replace("@", t !== f ? compute(f, t, delta) : t); | |
} | |
this.render(this.isArray ? tpl.split(",") : this.isNumber ? +tpl : tpl, factor); | |
if (factor !== 1) { | |
this.cancelStep = requestFrame(this.bStep); | |
} else { | |
delete this.cancelStep; | |
this.callback(now); | |
} | |
} | |
}); | |
var fx = function(render) { | |
var ffx = new Fx(render); | |
return { | |
start: function(from, to, options) { | |
var type = typeof options; | |
ffx.setOptions(type === "function" ? { | |
callback: options | |
} : type === "string" || type === "number" ? { | |
duration: options | |
} : options).start(from, to); | |
return this; | |
}, | |
stop: function() { | |
ffx.stop(); | |
return this; | |
} | |
}; | |
}; | |
fx.prototype = Fx.prototype; | |
module.exports = fx; | |
}, | |
"19": function(require, module, exports, global) { | |
module.exports = function(x1, y1, x2, y2, epsilon) { | |
var curveX = function(t) { | |
var v = 1 - t; | |
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t; | |
}; | |
var curveY = function(t) { | |
var v = 1 - t; | |
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t; | |
}; | |
var derivativeCurveX = function(t) { | |
var v = 1 - t; | |
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2; | |
}; | |
return function(t) { | |
var x = t, t0, t1, t2, x2, d2, i; | |
// First try a few iterations of Newton's method -- normally very fast. | |
for (t2 = x, i = 0; i < 8; i++) { | |
x2 = curveX(t2) - x; | |
if (Math.abs(x2) < epsilon) return curveY(t2); | |
d2 = derivativeCurveX(t2); | |
if (Math.abs(d2) < 1e-6) break; | |
t2 = t2 - x2 / d2; | |
} | |
t0 = 0, t1 = 1, t2 = x; | |
if (t2 < t0) return curveY(t0); | |
if (t2 > t1) return curveY(t1); | |
// Fallback to the bisection method for reliability. | |
while (t0 < t1) { | |
x2 = curveX(t2); | |
if (Math.abs(x2 - x) < epsilon) return curveY(t2); | |
if (x > x2) t0 = t2; else t1 = t2; | |
t2 = (t1 - t0) * .5 + t0; | |
} | |
// Failure | |
return curveY(t2); | |
}; | |
}; | |
}, | |
"1a": function(require, module, exports, global) { | |
/* | |
Unmatrix 2d | |
- a crude implementation of the slightly bugged pseudo code in http://www.w3.org/TR/css3-2d-transforms/#matrix-decomposition | |
*/ | |
"use strict"; | |
// returns the length of the passed vector | |
var length = function(a) { | |
return Math.sqrt(a[0] * a[0] + a[1] * a[1]); | |
}; | |
// normalizes the length of the passed point to 1 | |
var normalize = function(a) { | |
var l = length(a); | |
return l ? [ a[0] / l, a[1] / l ] : [ 0, 0 ]; | |
}; | |
// returns the dot product of the passed points | |
var dot = function(a, b) { | |
return a[0] * b[0] + a[1] * b[1]; | |
}; | |
// returns the principal value of the arc tangent of | |
// y/x, using the signs of both arguments to determine | |
// the quadrant of the return value | |
var atan2 = Math.atan2; | |
var combine = function(a, b, ascl, bscl) { | |
return [ ascl * a[0] + bscl * b[0], ascl * a[1] + bscl * b[1] ]; | |
}; | |
module.exports = function(a, b, c, d, tx, ty) { | |
// Make sure the matrix is invertible | |
if (a * d - b * c === 0) return false; | |
// Take care of translation | |
var translate = [ tx, ty ]; | |
// Put the components into a 2x2 matrix | |
var m = [ [ a, b ], [ c, d ] ]; | |
// Compute X scale factor and normalize first row. | |
var scale = [ length(m[0]) ]; | |
m[0] = normalize(m[0]); | |
// Compute shear factor and make 2nd row orthogonal to 1st. | |
var skew = dot(m[0], m[1]); | |
m[1] = combine(m[1], m[0], 1, -skew); | |
// Now, compute Y scale and normalize 2nd row. | |
scale[1] = length(m[1]); | |
// m[1] = normalize(m[1]) // | |
skew /= scale[1]; | |
// Now, get the rotation out | |
var rotate = atan2(m[0][1], m[0][0]); | |
return [ translate, rotate, skew, scale ]; | |
}; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment