Skip to content

Commit ffb94b1

Browse files
committed
Merge branch 'gh-pages' of github.com:bitovi/jquerypp into gh-pages
2 parents 7896b8d + 53a888a commit ffb94b1

28 files changed

+7833
-0
lines changed
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/*
2+
* jQuery++ - 1.0.0 (2012-11-20)
3+
* http://jquerypp.com
4+
* Copyright (c) 2012 Bitovi
5+
* Licensed MIT
6+
*/
7+
define(['jquery', 'jquerypp/dom/styles'], function ($) {
8+
9+
// Overwrites `jQuery.fn.animate` to use CSS 3 animations if possible
10+
var
11+
// The global animation counter
12+
animationNum = 0,
13+
// The stylesheet for our animations
14+
styleSheet = null,
15+
// The animation cache
16+
cache = [],
17+
// Stores the browser properties like transition end event name and prefix
18+
browser = null,
19+
// Store the original $.fn.animate
20+
oldanimate = $.fn.animate,
21+
22+
// Return the stylesheet, create it if it doesn't exists
23+
getStyleSheet = function () {
24+
if (!styleSheet) {
25+
var style = document.createElement('style');
26+
style.setAttribute("type", "text/css");
27+
style.setAttribute("media", "screen");
28+
29+
document.getElementsByTagName('head')[0].appendChild(style);
30+
if (!window.createPopup) {
31+
style.appendChild(document.createTextNode(''));
32+
}
33+
34+
styleSheet = style.sheet;
35+
}
36+
37+
return styleSheet;
38+
},
39+
40+
//removes an animation rule from a sheet
41+
removeAnimation = function (sheet, name) {
42+
for (var j = sheet.cssRules.length - 1; j >= 0; j--) {
43+
var rule = sheet.cssRules[j];
44+
// 7 means the keyframe rule
45+
if (rule.type === 7 && rule.name == name) {
46+
sheet.deleteRule(j)
47+
return;
48+
}
49+
}
50+
},
51+
52+
// Returns whether the animation should be passed to the original $.fn.animate.
53+
passThrough = function (props, ops) {
54+
var nonElement = !(this[0] && this[0].nodeType),
55+
isInline = !nonElement && $(this).css("display") === "inline" && $(this).css("float") === "none";
56+
57+
for (var name in props) {
58+
// jQuery does something with these values
59+
if (props[name] == 'show' || props[name] == 'hide' || props[name] == 'toggle'
60+
// Arrays for individual easing
61+
|| $.isArray(props[name])
62+
// Negative values not handled the same
63+
|| props[name] < 0
64+
// unit-less value
65+
|| name == 'zIndex' || name == 'z-index' || name == 'scrollTop' || name == 'scrollLeft') {
66+
return true;
67+
}
68+
}
69+
70+
return props.jquery === true || getBrowser() === null ||
71+
// Animating empty properties
72+
$.isEmptyObject(props) ||
73+
// We can't do custom easing
74+
(ops && ops.length == 4) || (ops && typeof ops[2] == 'string') ||
75+
// Second parameter is an object - we can only handle primitives
76+
$.isPlainObject(ops) ||
77+
// Inline and non elements
78+
isInline || nonElement;
79+
},
80+
81+
// Gets a CSS number (with px added as the default unit if the value is a number)
82+
cssValue = function (origName, value) {
83+
if (typeof value === "number" && !$.cssNumber[origName]) {
84+
return value += "px";
85+
}
86+
return value;
87+
},
88+
89+
// Feature detection borrowed by http://modernizr.com/
90+
getBrowser = function () {
91+
if (!browser) {
92+
var t, el = document.createElement('fakeelement'),
93+
transitions = {
94+
'transition': {
95+
transitionEnd: 'transitionEnd',
96+
prefix: ''
97+
},
98+
// 'OTransition': {
99+
// transitionEnd : 'oTransitionEnd',
100+
// prefix : '-o-'
101+
// },
102+
// 'MSTransition': {
103+
// transitionEnd : 'msTransitionEnd',
104+
// prefix : '-ms-'
105+
// },
106+
'MozTransition': {
107+
transitionEnd: 'animationend',
108+
prefix: '-moz-'
109+
},
110+
'WebkitTransition': {
111+
transitionEnd: 'webkitAnimationEnd',
112+
prefix: '-webkit-'
113+
}
114+
}
115+
116+
for (t in transitions) {
117+
if (el.style[t] !== undefined) {
118+
browser = transitions[t];
119+
}
120+
}
121+
}
122+
return browser;
123+
},
124+
125+
// Properties that Firefox can't animate if set to 'auto':
126+
// https://bugzilla.mozilla.org/show_bug.cgi?id=571344
127+
// Provides a converter that returns the actual value
128+
ffProps = {
129+
top: function (el) {
130+
return el.position().top;
131+
},
132+
left: function (el) {
133+
return el.position().left;
134+
},
135+
width: function (el) {
136+
return el.width();
137+
},
138+
height: function (el) {
139+
return el.height();
140+
},
141+
fontSize: function (el) {
142+
return '1em';
143+
}
144+
},
145+
146+
// Add browser specific prefix
147+
addPrefix = function (properties) {
148+
var result = {};
149+
$.each(properties, function (name, value) {
150+
result[getBrowser().prefix + name] = value;
151+
});
152+
return result;
153+
},
154+
155+
// Returns the animation name for a given style. It either uses a cached
156+
// version or adds it to the stylesheet, removing the oldest style if the
157+
// cache has reached a certain size.
158+
getAnimation = function (style) {
159+
var sheet, name, last;
160+
161+
// Look up the cached style, set it to that name and reset age if found
162+
// increment the age for any other animation
163+
$.each(cache, function (i, animation) {
164+
if (style === animation.style) {
165+
name = animation.name;
166+
animation.age = 0;
167+
} else {
168+
animation.age += 1;
169+
}
170+
});
171+
172+
if (!name) { // Add a new style
173+
sheet = getStyleSheet();
174+
name = "jquerypp_animation_" + (animationNum++);
175+
// get the last sheet and insert this rule into it
176+
sheet.insertRule("@" + getBrowser().prefix + "keyframes " + name + ' ' + style, (sheet.cssRules && sheet.cssRules.length) || 0);
177+
cache.push({
178+
name: name,
179+
style: style,
180+
age: 0
181+
});
182+
183+
// Sort the cache by age
184+
cache.sort(function (first, second) {
185+
return first.age - second.age;
186+
});
187+
188+
// Remove the last (oldest) item from the cache if it has more than 20 items
189+
if (cache.length > 20) {
190+
last = cache.pop();
191+
removeAnimation(sheet, last.name);
192+
}
193+
}
194+
195+
return name;
196+
};
197+
198+
199+
$.fn.animate = function (props, speed, easing, callback) {
200+
//default to normal animations if browser doesn't support them
201+
if (passThrough.apply(this, arguments)) {
202+
return oldanimate.apply(this, arguments);
203+
}
204+
205+
var optall = jQuery.speed(speed, easing, callback);
206+
207+
// Add everything to the animation queue
208+
this.queue(optall.queue, function (done) {
209+
var
210+
//current CSS values
211+
current,
212+
// The list of properties passed
213+
properties = [],
214+
to = "",
215+
prop, self = $(this),
216+
duration = optall.duration,
217+
//the animation keyframe name
218+
animationName,
219+
// The key used to store the animation hook
220+
dataKey,
221+
//the text for the keyframe
222+
style = "{ from {",
223+
// The animation end event handler.
224+
// Will be called both on animation end and after calling .stop()
225+
animationEnd = function (currentCSS, exec) {
226+
self.css(currentCSS);
227+
228+
self.css(addPrefix({
229+
"animation-duration": "",
230+
"animation-name": "",
231+
"animation-fill-mode": "",
232+
"animation-play-state": ""
233+
}));
234+
235+
// Call the original callback
236+
if ($.isFunction(optall.old) && exec) {
237+
// Call success, pass the DOM element as the this reference
238+
optall.old.call(self[0], true)
239+
}
240+
241+
$.removeData(self, dataKey, true);
242+
},
243+
finishAnimation = function () {
244+
// Call animationEnd using the passed properties
245+
animationEnd(props, true);
246+
done();
247+
};
248+
249+
for (prop in props) {
250+
properties.push(prop);
251+
}
252+
253+
if (getBrowser().prefix === '-moz-') {
254+
// Normalize 'auto' properties in FF
255+
$.each(properties, function (i, prop) {
256+
var converter = ffProps[$.camelCase(prop)];
257+
if (converter && self.css(prop) == 'auto') {
258+
self.css(prop, converter(self));
259+
}
260+
});
261+
}
262+
263+
// Use $.styles
264+
current = self.styles.apply(self, properties);
265+
$.each(properties, function (i, cur) {
266+
// Convert a camelcased property name
267+
var name = cur.replace(/([A-Z]|^ms)/g, "-$1").toLowerCase();
268+
style += name + " : " + cssValue(cur, current[cur]) + "; ";
269+
to += name + " : " + cssValue(cur, props[cur]) + "; ";
270+
});
271+
272+
style += "} to {" + to + " }}";
273+
274+
animationName = getAnimation(style);
275+
dataKey = animationName + '.run';
276+
277+
// Add a hook which will be called when the animation stops
278+
$._data(this, dataKey, {
279+
stop: function (gotoEnd) {
280+
// Pause the animation
281+
self.css(addPrefix({
282+
'animation-play-state': 'paused'
283+
}));
284+
// Unbind the animation end handler
285+
self.off(getBrowser().transitionEnd, finishAnimation);
286+
if (!gotoEnd) {
287+
// We were told not to finish the animation
288+
// Call animationEnd but set the CSS to the current computed style
289+
animationEnd(self.styles.apply(self, properties), false);
290+
} else {
291+
// Finish animaion
292+
animationEnd(props, true);
293+
}
294+
}
295+
});
296+
297+
// set this element to point to that animation
298+
self.css(addPrefix({
299+
"animation-duration": duration + "ms",
300+
"animation-name": animationName,
301+
"animation-fill-mode": "forwards"
302+
}));
303+
304+
// Attach the transition end event handler to run only once
305+
self.one(getBrowser().transitionEnd, finishAnimation);
306+
307+
});
308+
309+
return this;
310+
};
311+
312+
return $;
313+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* jQuery++ - 1.0.0 (2012-11-20)
3+
* http://jquerypp.com
4+
* Copyright (c) 2012 Bitovi
5+
* Licensed MIT
6+
*/
7+
define(['jquery'], function ($) {
8+
9+
// See http://ejohn.org/blog/comparing-document-position/
10+
jQuery.fn.compare = function (element) { //usually
11+
try {
12+
// Firefox 3 throws an error with XUL - we can't use compare then
13+
element = element.jquery ? element[0] : element;
14+
} catch (e) {
15+
return null;
16+
}
17+
18+
// make sure we aren't coming from XUL element
19+
if (window.HTMLElement) {
20+
var s = HTMLElement.prototype.toString.call(element)
21+
if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]' || s === '[object Window]') {
22+
return null;
23+
}
24+
}
25+
26+
if (this[0].compareDocumentPosition) {
27+
// For browsers that support it, use compareDocumentPosition
28+
// https://developer.mozilla.org/en/DOM/Node.compareDocumentPosition
29+
return this[0].compareDocumentPosition(element);
30+
}
31+
32+
// this[0] contains element
33+
if (this[0] == document && element != document) return 8;
34+
35+
var number =
36+
// this[0] contains element
37+
(this[0] !== element && this[0].contains(element) && 16) +
38+
// element contains this[0]
39+
(this[0] != element && element.contains(this[0]) && 8),
40+
docEl = document.documentElement;
41+
42+
// Use the sourceIndex
43+
if (this[0].sourceIndex) {
44+
// this[0] precedes element
45+
number += (this[0].sourceIndex < element.sourceIndex && 4)
46+
// element precedes foo[0]
47+
number += (this[0].sourceIndex > element.sourceIndex && 2)
48+
// The nodes are in different documents
49+
number += (this[0].ownerDocument !== element.ownerDocument || (this[0] != docEl && this[0].sourceIndex <= 0) || (element != docEl && element.sourceIndex <= 0)) && 1
50+
}
51+
52+
return number;
53+
}
54+
55+
return $;
56+
});

0 commit comments

Comments
 (0)