Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
thewickedkarma
GitHub Repository: thewickedkarma/blackeye-im
Path: blob/master/sites/icloud/activity-indicator.js
777 views
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
document.styleSheets[0].insertRule(rule);
151
animations[steps] = name;
152
}
153
el.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite');
154
};
155
}
156
else {
157
158
/**
159
* Animation strategy that transforms a SVG element using setInterval().
160
*/
161
animate = function(el, steps, duration) {
162
var rotation = 0;
163
var g = el.find('g g').get(0);
164
el.data('interval', setInterval(function() {
165
g.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')');
166
}, duration * 1000 / steps));
167
};
168
}
169
170
}
171
else {
172
173
// =======================================================================================
174
// VML Rendering
175
// =======================================================================================
176
177
var s = $('<shape>').css('behavior', 'url(#default#VML)');
178
179
$('body').append(s);
180
181
if (s.get(0).adj) {
182
183
// VML support detected. Insert CSS rules for group, shape and stroke.
184
var sheet = document.createStyleSheet();
185
$.each(['group', 'shape', 'stroke'], function() {
186
sheet.addRule(this, "behavior:url(#default#VML);");
187
});
188
189
/**
190
* Rendering strategy that creates a VML tree.
191
*/
192
render = function(target, d) {
193
194
var innerRadius = d.width*2 + d.space;
195
var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);
196
var s = r*2;
197
var o = -Math.ceil(s/2);
198
199
var el = $('<group>', {coordsize: s + ' ' + s, coordorigin: o + ' ' + o}).css({top: o, left: o, width: s, height: s});
200
for (var i = 0; i < d.segments; i++) {
201
el.append($('<shape>', {path: 'm ' + innerRadius + ',0 l ' + (innerRadius + d.length) + ',0'}).css({
202
width: s,
203
height: s,
204
rotation: (360 / d.segments * i) + 'deg'
205
}).append($('<stroke>', {color: d.color, weight: d.width + 'px', endcap: 'round', opacity: $.fn.activity.getOpacity(d, i)})));
206
}
207
return $('<group>', {coordsize: s + ' ' + s}).css({width: s, height: s, overflow: 'hidden'}).append(el);
208
};
209
210
/**
211
* Animation strategy that modifies the VML rotation property using setInterval().
212
*/
213
animate = function(el, steps, duration) {
214
var rotation = 0;
215
var g = el.get(0);
216
el.data('interval', setInterval(function() {
217
g.style.rotation = ++rotation % steps * (360 / steps);
218
}, duration * 1000 / steps));
219
};
220
}
221
$(s).remove();
222
}
223
224
})(jQuery);
225