Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/jquery.loadingSpinner/spinner.js |
— | — | @@ -0,0 +1,287 @@ |
| 2 | +(function(window, document, undefined) { |
| 3 | + |
| 4 | +/** |
| 5 | + * Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de] |
| 6 | + * Licensed under the MIT license |
| 7 | + * https://github.com/fgnass/spin.js |
| 8 | + */ |
| 9 | + |
| 10 | + var prefixes = ['webkit', 'Moz', 'ms', 'O'], /* Vendor prefixes */ |
| 11 | + animations = {}, /* Animation rules keyed by their name */ |
| 12 | + useCssAnimations; |
| 13 | + |
| 14 | + /** |
| 15 | + * Utility function to create elements. If no tag name is given, |
| 16 | + * a DIV is created. Optionally properties can be passed. |
| 17 | + */ |
| 18 | + function createEl(tag, prop) { |
| 19 | + var el = document.createElement(tag || 'div'), |
| 20 | + n; |
| 21 | + |
| 22 | + for(n in prop) { |
| 23 | + el[n] = prop[n]; |
| 24 | + } |
| 25 | + return el; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Inserts child1 before child2. If child2 is not specified, |
| 30 | + * child1 is appended. If child2 has no parentNode, child2 is |
| 31 | + * appended first. |
| 32 | + */ |
| 33 | + function ins(parent, child1, child2) { |
| 34 | + if(child2 && !child2.parentNode) ins(parent, child2); |
| 35 | + parent.insertBefore(child1, child2||null); |
| 36 | + return parent; |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * Insert a new stylesheet to hold the @keyframe or VML rules. |
| 41 | + */ |
| 42 | + //ins(document.getElementsByTagName('head')[0], createEl('style')); |
| 43 | + //var sheet = document.styleSheets[document.styleSheets.length-1]; |
| 44 | + var sheet = (function() { |
| 45 | + var style = document.createElement('style'); |
| 46 | + style['title'] = 'spinjs'; |
| 47 | + document.getElementsByTagName('head')[0].appendChild(style); |
| 48 | + if (!window.createPopup) { /* For Safari */ |
| 49 | + style.appendChild(document.createTextNode('')); |
| 50 | + } |
| 51 | + return document.styleSheets[document.styleSheets.length - 1]; |
| 52 | + })(); |
| 53 | + |
| 54 | + /** |
| 55 | + * Creates an opacity keyframe animation rule and returns its name. |
| 56 | + * Since most mobile Webkits have timing issues with animation-delay, |
| 57 | + * we create separate rules for each line/segment. |
| 58 | + */ |
| 59 | + function addAnimation(alpha, trail, i, lines) { |
| 60 | + var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-'), |
| 61 | + start = 0.01 + i/lines*100, |
| 62 | + z = Math.max(1-(1-alpha)/trail*(100-start) , alpha), |
| 63 | + prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase(), |
| 64 | + pre = prefix && '-'+prefix+'-' || ''; |
| 65 | + |
| 66 | + if (!animations[name]) { |
| 67 | + sheet.insertRule( |
| 68 | + '@' + pre + 'keyframes ' + name + '{' + |
| 69 | + '0%{opacity:'+z+'}' + |
| 70 | + start + '%{opacity:'+ alpha + '}' + |
| 71 | + (start+0.01) + '%{opacity:1}' + |
| 72 | + (start+trail)%100 + '%{opacity:'+ alpha + '}' + |
| 73 | + '100%{opacity:'+ z + '}' + |
| 74 | + '}', 0); |
| 75 | + animations[name] = 1; |
| 76 | + } |
| 77 | + return name; |
| 78 | + } |
| 79 | + |
| 80 | + /** |
| 81 | + * Tries various vendor prefixes and returns the first supported property. |
| 82 | + **/ |
| 83 | + function vendor(el, prop) { |
| 84 | + var s = el.style, |
| 85 | + pp, |
| 86 | + i; |
| 87 | + |
| 88 | + if(s[prop] !== undefined) return prop; |
| 89 | + prop = prop.charAt(0).toUpperCase() + prop.slice(1); |
| 90 | + for(i=0; i<prefixes.length; i++) { |
| 91 | + pp = prefixes[i]+prop; |
| 92 | + if(s[pp] !== undefined) return pp; |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * Sets multiple style properties at once. |
| 98 | + */ |
| 99 | + function css(el, prop) { |
| 100 | + for (var n in prop) { |
| 101 | + el.style[vendor(el, n)||n] = prop[n]; |
| 102 | + } |
| 103 | + return el; |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * Fills in default values. |
| 108 | + */ |
| 109 | + function defaults(obj, def) { |
| 110 | + for (var n in def) { |
| 111 | + if (obj[n] === undefined) obj[n] = def[n]; |
| 112 | + } |
| 113 | + return obj; |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Returns the absolute page-offset of the given element. |
| 118 | + */ |
| 119 | + function pos(el) { |
| 120 | + var o = {x:el.offsetLeft, y:el.offsetTop}; |
| 121 | + while((el = el.offsetParent)) { |
| 122 | + o.x+=el.offsetLeft; |
| 123 | + o.y+=el.offsetTop; |
| 124 | + } |
| 125 | + return o; |
| 126 | + } |
| 127 | + |
| 128 | + /** The constructor */ |
| 129 | + var Spinner = function Spinner(o) { |
| 130 | + this.opts = defaults(o || {}, { |
| 131 | + lines: 12, // The number of lines to draw |
| 132 | + length: 7, // The length of each line |
| 133 | + width: 5, // The line thickness |
| 134 | + radius: 10, // The radius of the inner circle |
| 135 | + color: '#000', // #rbg or #rrggbb |
| 136 | + speed: 1, // Rounds per second |
| 137 | + trail: 100, // Afterglow percentage |
| 138 | + opacity: 1/4 |
| 139 | + }); |
| 140 | + }, |
| 141 | + proto = Spinner.prototype = { |
| 142 | + spin: function(target) { |
| 143 | + var self = this, |
| 144 | + el = self.el = css(createEl(), {position: 'relative'}), |
| 145 | + ep, // element position |
| 146 | + tp; // target position |
| 147 | + |
| 148 | + if (target) { |
| 149 | + tp = pos(ins(target, el, target.firstChild)); |
| 150 | + ep = pos(el); |
| 151 | + css(el, { |
| 152 | + left: (target.offsetWidth >> 1) - ep.x+tp.x + 'px', |
| 153 | + top: (target.offsetHeight >> 1) - ep.y+tp.y + 'px' |
| 154 | + }); |
| 155 | + } |
| 156 | + self.lines(el, self.opts); |
| 157 | + if (!useCssAnimations) { |
| 158 | + // No CSS animation support, use setTimeout() instead |
| 159 | + var o = self.opts, |
| 160 | + i = 0, |
| 161 | + f = 20/o.speed, |
| 162 | + ostep = (1-o.opacity)/(f*o.trail / 100), |
| 163 | + astep = f/o.lines; |
| 164 | + |
| 165 | + (function anim() { |
| 166 | + i++; |
| 167 | + for (var s=o.lines; s; s--) { |
| 168 | + var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity); |
| 169 | + self.opacity(el, o.lines-s, alpha, o); |
| 170 | + } |
| 171 | + self.timeout = self.el && setTimeout(anim, 50); |
| 172 | + })(); |
| 173 | + } |
| 174 | + return self; |
| 175 | + }, |
| 176 | + stop: function() { |
| 177 | + var self = this, |
| 178 | + el = self.el; |
| 179 | + |
| 180 | + clearTimeout(self.timeout); |
| 181 | + if (el && el.parentNode) el.parentNode.removeChild(el); |
| 182 | + self.el = undefined; |
| 183 | + return self; |
| 184 | + } |
| 185 | + }; |
| 186 | + proto.lines = function(el, o) { |
| 187 | + var i = 0, |
| 188 | + seg; |
| 189 | + |
| 190 | + function fill(color, shadow) { |
| 191 | + return css(createEl(), { |
| 192 | + position: 'absolute', |
| 193 | + width: (o.length+o.width) + 'px', |
| 194 | + height: o.width + 'px', |
| 195 | + background: color, |
| 196 | + boxShadow: shadow, |
| 197 | + transformOrigin: 'left', |
| 198 | + transform: 'rotate(' + ~~(360/o.lines*i) + 'deg) translate(' + o.radius+'px' +',0)', |
| 199 | + borderRadius: (o.width>>1) + 'px' |
| 200 | + }); |
| 201 | + } |
| 202 | + for (; i < o.lines; i++) { |
| 203 | + seg = css(createEl(), { |
| 204 | + position: 'absolute', |
| 205 | + top: 1+~(o.width/2) + 'px', |
| 206 | + transform: 'translate3d(0,0,0)', |
| 207 | + opacity: o.opacity, |
| 208 | + animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite' |
| 209 | + }); |
| 210 | + if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'})); |
| 211 | + ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)'))); |
| 212 | + } |
| 213 | + return el; |
| 214 | + }; |
| 215 | + proto.opacity = function(el, i, val) { |
| 216 | + el.childNodes[i].style.opacity = val; |
| 217 | + }; |
| 218 | + |
| 219 | + ///////////////////////////////////////////////////////////////////////// |
| 220 | + // VML rendering for IE |
| 221 | + ///////////////////////////////////////////////////////////////////////// |
| 222 | + |
| 223 | + /** |
| 224 | + * Check and init VML support |
| 225 | + */ |
| 226 | + (function() { |
| 227 | + var s = css(createEl('group'), {behavior: 'url(#default#VML)'}), |
| 228 | + i; |
| 229 | + |
| 230 | + if (!vendor(s, 'transform') && s.adj) { |
| 231 | + |
| 232 | + // VML support detected. Insert CSS rules ... |
| 233 | + for (i=4; i--;) sheet.addRule(['group', 'roundrect', 'fill', 'stroke'][i], 'behavior:url(#default#VML)'); |
| 234 | + |
| 235 | + proto.lines = function(el, o) { |
| 236 | + var r = o.length+o.width, |
| 237 | + s = 2*r; |
| 238 | + |
| 239 | + function grp() { |
| 240 | + return css(createEl('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s}); |
| 241 | + } |
| 242 | + |
| 243 | + var g = grp(), |
| 244 | + margin = ~(o.length+o.radius+o.width)+'px', |
| 245 | + i; |
| 246 | + |
| 247 | + function seg(i, dx, filter) { |
| 248 | + ins(g, |
| 249 | + ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}), |
| 250 | + ins(css(createEl('roundrect', {arcsize: 1}), { |
| 251 | + width: r, |
| 252 | + height: o.width, |
| 253 | + left: o.radius, |
| 254 | + top: -o.width>>1, |
| 255 | + filter: filter |
| 256 | + }), |
| 257 | + createEl('fill', {color: o.color, opacity: o.opacity}), |
| 258 | + createEl('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change |
| 259 | + ) |
| 260 | + ) |
| 261 | + ); |
| 262 | + } |
| 263 | + |
| 264 | + if (o.shadow) { |
| 265 | + for (i = 1; i <= o.lines; i++) { |
| 266 | + seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)'); |
| 267 | + } |
| 268 | + } |
| 269 | + for (i = 1; i <= o.lines; i++) { |
| 270 | + seg(i); |
| 271 | + } |
| 272 | + return ins(css(el, { |
| 273 | + margin: margin + ' 0 0 ' + margin |
| 274 | + }), g); |
| 275 | + }; |
| 276 | + proto.opacity = function(el, i, val, o) { |
| 277 | + o = o.shadow && o.lines || 0; |
| 278 | + el.firstChild.childNodes[i+o].firstChild.firstChild.opacity = val; |
| 279 | + }; |
| 280 | + } |
| 281 | + else { |
| 282 | + useCssAnimations = vendor(s, 'animation'); |
| 283 | + } |
| 284 | + })(); |
| 285 | + |
| 286 | + window.Spinner = Spinner; |
| 287 | + |
| 288 | +})(window, document); |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/jquery.loadingSpinner/spinner.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 289 | + text/plain |