-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathprogressive.js
More file actions
130 lines (116 loc) · 4.1 KB
/
progressive.js
File metadata and controls
130 lines (116 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*****************************************
Progressive.js v0.1 - Brought to you by James Allardice (@james_allardice) and Keith Clark (@keithclarkcouk), freely distributable under the terms of the MIT license.
******************************************/
/*jslint browser: true, plusplus: true */
var Progressive = (function () {
"use strict";
var styleElem = document.createElement("style"),
animationSupport = false,
animationString,
keyframePrefix = "",
domPrefixes = ["Webkit", "Moz", "O", "ms", "Khtml"],
numPrefixes = domPrefixes.length,
prefix,
enhance,
i;
// Polyfill `getElementsByClassName`, which is used by the fallback method
document.getElementsByClassName = document.getElementsByClassName || function (className) {
var classElements = [],
els,
elsLen,
pattern = new RegExp("(^|\\s)" + className + "(\\s|$)"),
i,
j;
els = document.getElementsByTagName("*");
elsLen = els.length;
for (i = 0, j = 0; i < elsLen; i++) {
if (pattern.test(els[i].className)) {
classElements[j] = els[i];
j++;
}
}
return classElements;
};
// Feature/vendor prefix detection for CSS animations
if (styleElem.style.animationName) {
animationSupport = true;
} else {
for (i = 0; i < numPrefixes; i++) {
if (styleElem.style[domPrefixes[i] + "AnimationName"] !== undefined) {
prefix = domPrefixes[i];
animationString = prefix + "Animation";
keyframePrefix = "-" + prefix.toLowerCase() + "-";
animationSupport = true;
break;
}
}
}
// The main `enhance` method to register callbacks that will be executed when certain DOM elements are inserted
enhance = function (enhancements) {
var ruleText,
styleRules = {},
enhancement,
onNodeInserted,
// The fallback function is executed on window load. It will handle any elements not handled by the animation callbacks
fallback = function () {
var enhancement,
elems,
numElems,
i;
for (enhancement in enhancements) {
if (enhancements.hasOwnProperty(enhancement)) {
elems = document.getElementsByClassName(enhancements[enhancement].className);
numElems = elems.length;
if (!enhancements[enhancement].count || enhancements[enhancement].count < numElems) {
for (i = 0; i < numElems; i++) {
enhancements[enhancement].callback.call(elems[i]);
}
}
}
}
};
ruleText = "";
// This is used as a callback to the CSS animation events. It's used to fire the supplied enhancements, in the context of each element
onNodeInserted = function (e) {
var enhancement = enhancements[e.animationName];
if (enhancement) {
enhancement.count = ++enhancement.count || 1;
enhancement.callback.call(e.target);
}
};
if (animationSupport) {
// Build up a set of CSS rules to run animations on newly inserted elements
for (enhancement in enhancements) {
if (enhancements.hasOwnProperty(enhancement)) {
ruleText += "." + enhancements[enhancement].className + "{";
ruleText += keyframePrefix + "animation:" + enhancement + " 0.001s;";
ruleText += "}";
ruleText += "@" + keyframePrefix + "keyframes " + enhancement + "{from{clip:rect(1px,auto,auto,auto);}to{clip:rect(0px,auto,auto,auto);}}";
}
}
styleRules = document.createTextNode(ruleText);
styleElem.type = "text/css";
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = styleRules.nodeValue;
} else {
styleElem.appendChild(styleRules);
}
document.getElementsByTagName("script")[0].parentNode.appendChild(styleElem);
// Register cross-browser CSS animation event handlers
document.addEventListener("animationstart", onNodeInserted, false);
document.addEventListener("oanimationstart", onNodeInserted, false);
document.addEventListener("MSAnimationStart", onNodeInserted, false);
document.addEventListener("webkitAnimationStart", onNodeInserted, false);
}
// Register fallback event handlers
if (window.addEventListener) {
window.addEventListener("load", fallback);
} else if (window.attachEvent) {
window.attachEvent("onload", fallback);
}
};
// Expose public methods
return {
enhance: enhance
};
}());