1/*! 2 * NETEYE Activity Indicator jQuery Plugin 3 * 4 * Copyright (c) 2010 NETEYE GmbH 5 * Licensed under the MIT license 6 * 7 * Author: Felix Gnass [fgnass at neteye dot de] 8 * Version: @{VERSION} 9 */ 10 11/** 12 * Plugin that renders a customisable activity indicator (spinner) using SVG or VML. 13 */ 14(function($) { 15 16 $.fn.activity = function(opts) { 17 this.each(function() { 18 var $this = $(this); 19 var el = $this.data('activity'); 20 if (el) { 21 clearInterval(el.data('interval')); 22 el.remove(); 23 $this.removeData('activity'); 24 } 25 if (opts !== false) { 26 opts = $.extend({color: $this.css('color')}, $.fn.activity.defaults, opts); 27 28 el = render($this, opts).css('position', 'absolute').prependTo(opts.outside ? 'body' : $this); 29 var h = $this.outerHeight() - el.height(); 30 var w = $this.outerWidth() - el.width(); 31 var margin = { 32 top: opts.valign == 'top' ? opts.padding : opts.valign == 'bottom' ? h - opts.padding : Math.floor(h / 2), 33 left: opts.align == 'left' ? opts.padding : opts.align == 'right' ? w - opts.padding : Math.floor(w / 2) 34 }; 35 var offset = $this.offset(); 36 if (opts.outside) { 37 el.css({top: offset.top + 'px', left: offset.left + 'px'}); 38 } 39 else { 40 margin.top -= el.offset().top - offset.top; 41 margin.left -= el.offset().left - offset.left; 42 } 43 el.css({marginTop: margin.top + 'px', marginLeft: margin.left + 'px'}); 44 animate(el, opts.segments, Math.round(10 / opts.speed) / 10); 45 $this.data('activity', el); 46 } 47 }); 48 return this; 49 }; 50 51 $.fn.activity.defaults = { 52 segments: 12, 53 space: 3, 54 length: 7, 55 width: 4, 56 speed: 1.2, 57 align: 'center', 58 valign: 'center', 59 padding: 4 60 }; 61 62 $.fn.activity.getOpacity = function(opts, i) { 63 var steps = opts.steps || opts.segments-1; 64 var end = opts.opacity !== undefined ? opts.opacity : 1/steps; 65 return 1 - Math.min(i, steps) * (1 - end) / steps; 66 }; 67 68 /** 69 * Default rendering strategy. If neither SVG nor VML is available, a div with class-name 'busy' 70 * is inserted, that can be styled with CSS to display an animated gif as fallback. 71 */ 72 var render = function() { 73 return $('<div>').addClass('busy'); 74 }; 75 76 /** 77 * The default animation strategy does nothing as we expect an animated gif as fallback. 78 */ 79 var animate = function() { 80 }; 81 82 /** 83 * Utility function to create elements in the SVG namespace. 84 */ 85 function svg(tag, attr) { 86 var el = document.createElementNS("http://www.w3.org/2000/svg", tag || 'svg'); 87 if (attr) { 88 $.each(attr, function(k, v) { 89 el.setAttributeNS(null, k, v); 90 }); 91 } 92 return $(el); 93 } 94 95 if (document.createElementNS && document.createElementNS( "http://www.w3.org/2000/svg", "svg").createSVGRect) { 96 97 // ======================================================================================= 98 // SVG Rendering 99 // ======================================================================================= 100 101 /** 102 * Rendering strategy that creates a SVG tree. 103 */ 104 render = function(target, d) { 105 var innerRadius = d.width*2 + d.space; 106 var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1); 107 108 var el = svg().width(r*2).height(r*2); 109 110 var g = svg('g', { 111 'stroke-width': d.width, 112 'stroke-linecap': 'round', 113 stroke: d.color 114 }).appendTo(svg('g', {transform: 'translate('+ r +','+ r +')'}).appendTo(el)); 115 116 for (var i = 0; i < d.segments; i++) { 117 g.append(svg('line', { 118 x1: 0, 119 y1: innerRadius, 120 x2: 0, 121 y2: innerRadius + d.length, 122 transform: 'rotate(' + (360 / d.segments * i) + ', 0, 0)', 123 opacity: $.fn.activity.getOpacity(d, i) 124 })); 125 } 126 return $('<div>').append(el).width(2*r).height(2*r); 127 }; 128 129 // Check if Webkit CSS animations are available, as they work much better on the iPad 130 // than setTimeout() based animations. 131 132 if (document.createElement('div').style.WebkitAnimationName !== undefined) { 133 134 var animations = {}; 135 136 /** 137 * Animation strategy that uses dynamically created CSS animation rules. 138 */ 139 animate = function(el, steps, duration) { 140 if (!animations[steps]) { 141 var name = 'spin' + steps; 142 var rule = '@-webkit-keyframes '+ name +' {'; 143 for (var i=0; i < steps; i++) { 144 var p1 = Math.round(100000 / steps * i) / 1000; 145 var p2 = Math.round(100000 / steps * (i+1) - 1) / 1000; 146 var value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\n'; 147 rule += p1 + value + p2 + value; 148 } 149 rule += '100% { -webkit-transform:rotate(100deg); }\n}'; 150 151 //document.styleSheets[0].insertRule(rule); 152 animations[steps] = name; 153 } 154 el.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite'); 155 }; 156 } 157 else { 158 159 /** 160 * Animation strategy that transforms a SVG element using setInterval(). 161 */ 162 animate = function(el, steps, duration) { 163 var rotation = 0; 164 var g = el.find('g g').get(0); 165 el.data('interval', setInterval(function() { 166 g.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')'); 167 }, duration * 1000 / steps)); 168 }; 169 } 170 171 } 172 else { 173 174 // ======================================================================================= 175 // VML Rendering 176 // ======================================================================================= 177 178 var s = $('<shape>').css('behavior', 'url(#default#VML)'); 179 180 $('body').append(s); 181 182 if (s.get(0).adj) { 183 184 // VML support detected. Insert CSS rules for group, shape and stroke. 185 var sheet = document.createStyleSheet(); 186 $.each(['group', 'shape', 'stroke'], function() { 187 sheet.addRule(this, "behavior:url(#default#VML);"); 188 }); 189 190 /** 191 * Rendering strategy that creates a VML tree. 192 */ 193 render = function(target, d) { 194 195 var innerRadius = d.width*2 + d.space;
196 var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1); 197 var s = r*2; 198 var o = -Math.ceil(s/2); 199 200 var el = $('<group>', {coordsize: s + ' ' + s, coordorigin: o + ' ' + o}).css({top: o, left: o, width: s, height: s}); 201 for (var i = 0; i < d.segments; i++) { 202 el.append($('<shape>', {path: 'm ' + innerRadius + ',0 l ' + (innerRadius + d.length) + ',0'}).css({ 203 width: s, 204 height: s, 205 rotation: (360 / d.segments * i) + 'deg' 206 }).append($('<stroke>', {color: d.color, weight: d.width + 'px', endcap: 'round', opacity: $.fn.activity.getOpacity(d, i)}))); 207 } 208 return $('<group>', {coordsize: s + ' ' + s}).css({width: s, height: s, overflow: 'hidden'}).append(el); 209 }; 210 211 /** 212 * Animation strategy that modifies the VML rotation property using setInterval(). 213 */ 214 animate = function(el, steps, duration) { 215 var rotation = 0; 216 var g = el.get(0); 217 el.data('interval', setInterval(function() { 218 g.style.rotation = ++rotation % steps * (360 / steps); 219 }, duration * 1000 / steps)); 220 }; 221 } 222 $(s).remove(); 223 } 224 225})(jQuery);
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.