PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.3
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.3
5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / assets / javascripts / vendor / circles.js
latepoint / lib / assets / javascripts / vendor Last commit date
intl-tel-input 1 year ago chart.min.js 1 year ago circles.js 1 year ago daterangepicker.min.js 1 year ago dragula.min.js 1 year ago jquery.inputmask.min.js 1 year ago jquery.json-viewer.js 1 year ago medium-editor.min.js 1 year ago moment-with-locales.min.js 1 year ago pickr.min.js 1 year ago sprintf.min.js 1 year ago
circles.js
317 lines
1 // circles
2 // copyright Artan Sinani
3 // https://github.com/lugolabs/circles
4 (function(root, factory) {
5 if(typeof exports === 'object') {
6 module.exports = factory();
7 }
8 else if(typeof define === 'function' && define.amd) {
9 define([], factory);
10 }
11 else {
12 root.Circles = factory();
13 }
14
15
16 }(this, function() {
17
18 "use strict";
19
20 var requestAnimFrame = window.requestAnimationFrame ||
21 window.webkitRequestAnimationFrame ||
22 window.mozRequestAnimationFrame ||
23 window.oRequestAnimationFrame ||
24 window.msRequestAnimationFrame ||
25 function (callback) {
26 setTimeout(callback, 1000 / 60);
27 },
28
29 Circles = function(options) {
30 var elId = options.id;
31 this._el = document.getElementById(elId);
32
33 if (this._el === null) return;
34
35 this._radius = options.radius || 10;
36 this._duration = options.duration === undefined ? 500 : options.duration;
37
38 this._value = 0.0000001;
39 this._maxValue = options.maxValue || 100;
40
41 this._text = options.text === undefined ? function(value){return this.htmlifyNumber(value);} : options.text;
42 this._strokeWidth = options.width || 10;
43 this._colors = options.colors || ['#EEE', '#F00'];
44 this._svg = null;
45 this._movingPath = null;
46 this._wrapContainer = null;
47 this._textContainer = null;
48
49 this._wrpClass = options.wrpClass || 'circles-wrp';
50 this._textClass = options.textClass || 'circles-text';
51
52 this._valClass = options.valueStrokeClass || 'circles-valueStroke';
53 this._maxValClass = options.maxValueStrokeClass || 'circles-maxValueStroke';
54
55 this._styleWrapper = options.styleWrapper === false ? false : true;
56 this._styleText = options.styleText === false ? false : true;
57
58 var endAngleRad = Math.PI / 180 * 270;
59 this._start = -Math.PI / 180 * 90;
60 this._startPrecise = this._precise(this._start);
61 this._circ = endAngleRad - this._start;
62
63 this._generate().update(options.value || 0);
64 };
65
66 Circles.prototype = {
67 VERSION: '0.0.6',
68
69 _generate: function() {
70
71 this._svgSize = this._radius * 2;
72 this._radiusAdjusted = this._radius - (this._strokeWidth / 2);
73
74 this._generateSvg()._generateText()._generateWrapper();
75
76 this._el.innerHTML = '';
77 this._el.appendChild(this._wrapContainer);
78
79 return this;
80 },
81
82 _setPercentage: function(percentage) {
83 this._movingPath.setAttribute('d', this._calculatePath(percentage, true));
84 this._textContainer.innerHTML = this._getText(this.getValueFromPercent(percentage));
85 },
86
87 _generateWrapper: function() {
88 this._wrapContainer = document.createElement('div');
89 this._wrapContainer.className = this._wrpClass;
90
91 if (this._styleWrapper) {
92 this._wrapContainer.style.position = 'relative';
93 this._wrapContainer.style.display = 'inline-block';
94 }
95
96 this._wrapContainer.appendChild(this._svg);
97 this._wrapContainer.appendChild(this._textContainer);
98
99 return this;
100 },
101
102 _generateText: function() {
103
104 this._textContainer = document.createElement('div');
105 this._textContainer.className = this._textClass;
106
107 if (this._styleText) {
108 var style = {
109 position: 'absolute',
110 top: 0,
111 left: 0,
112 textAlign: 'center',
113 width: '100%',
114 fontSize: (this._radius * .7) + 'px',
115 height: this._svgSize + 'px',
116 lineHeight: this._svgSize + 'px'
117 };
118
119 for(var prop in style) {
120 this._textContainer.style[prop] = style[prop];
121 }
122 }
123
124 this._textContainer.innerHTML = this._getText(0);
125 return this;
126 },
127
128 _getText: function(value) {
129 if (!this._text) return '';
130
131 if (value === undefined) value = this._value;
132
133 value = parseFloat(value.toFixed(2));
134
135 return typeof this._text === 'function' ? this._text.call(this, value) : this._text;
136 },
137
138 _generateSvg: function() {
139
140 this._svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
141 this._svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
142 this._svg.setAttribute('width', this._svgSize);
143 this._svg.setAttribute('height', this._svgSize);
144
145 this._generatePath(100, false, this._colors[0], this._maxValClass)._generatePath(1, true, this._colors[1], this._valClass);
146
147 this._movingPath = this._svg.getElementsByTagName('path')[1];
148
149 return this;
150 },
151
152 _generatePath: function(percentage, open, color, pathClass) {
153 var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
154 path.setAttribute('fill', 'transparent');
155 path.setAttribute('stroke', color);
156 path.setAttribute('stroke-width', this._strokeWidth);
157 path.setAttribute('d', this._calculatePath(percentage, open));
158 path.setAttribute('class', pathClass);
159
160 this._svg.appendChild(path);
161
162 return this;
163 },
164
165 _calculatePath: function(percentage, open) {
166 var end = this._start + ((percentage / 100) * this._circ),
167 endPrecise = this._precise(end);
168 return this._arc(endPrecise, open);
169 },
170
171 _arc: function(end, open) {
172 var endAdjusted = end - 0.001,
173 longArc = end - this._startPrecise < Math.PI ? 0 : 1;
174
175 return [
176 'M',
177 this._radius + this._radiusAdjusted * Math.cos(this._startPrecise),
178 this._radius + this._radiusAdjusted * Math.sin(this._startPrecise),
179 'A', // arcTo
180 this._radiusAdjusted, // x radius
181 this._radiusAdjusted, // y radius
182 0, // slanting
183 longArc, // long or short arc
184 1, // clockwise
185 this._radius + this._radiusAdjusted * Math.cos(endAdjusted),
186 this._radius + this._radiusAdjusted * Math.sin(endAdjusted),
187 open ? '' : 'Z' // close
188 ].join(' ');
189 },
190
191 _precise: function(value) {
192 return Math.round(value * 1000) / 1000;
193 },
194
195 /*== Public methods ==*/
196
197 htmlifyNumber: function(number, integerPartClass, decimalPartClass) {
198
199 integerPartClass = integerPartClass || 'circles-integer';
200 decimalPartClass = decimalPartClass || 'circles-decimals';
201
202 var parts = (number + '').split('.'),
203 html = '<span class="' + integerPartClass + '">' + parts[0]+'</span>';
204
205 if (parts.length > 1) {
206 html += '.<span class="' + decimalPartClass + '">' + parts[1].substring(0, 2) + '</span>';
207 }
208 return html;
209 },
210
211 updateRadius: function(radius) {
212 this._radius = radius;
213
214 return this._generate().update(true);
215 },
216
217 updateWidth: function(width) {
218 this._strokeWidth = width;
219
220 return this._generate().update(true);
221 },
222
223 updateColors: function(colors) {
224 this._colors = colors;
225
226 var paths = this._svg.getElementsByTagName('path');
227
228 paths[0].setAttribute('stroke', colors[0]);
229 paths[1].setAttribute('stroke', colors[1]);
230
231 return this;
232 },
233
234 getPercent: function() {
235 return (this._value * 100) / this._maxValue;
236 },
237
238 getValueFromPercent: function(percentage) {
239 return (this._maxValue * percentage) / 100;
240 },
241
242 getValue: function()
243 {
244 return this._value;
245 },
246
247 getMaxValue: function()
248 {
249 return this._maxValue;
250 },
251
252 update: function(value, duration) {
253 if (value === true) {//Force update with current value
254 this._setPercentage(this.getPercent());
255 return this;
256 }
257
258 if (this._value == value || isNaN(value)) return this;
259 if (duration === undefined) duration = this._duration;
260
261 var self = this,
262 oldPercentage = self.getPercent(),
263 delta = 1,
264 newPercentage, isGreater, steps, stepDuration;
265
266 this._value = Math.min(this._maxValue, Math.max(0, value));
267
268 if (!duration) {//No duration, we can't skip the animation
269 this._setPercentage(this.getPercent());
270 return this;
271 }
272
273 newPercentage = self.getPercent();
274 isGreater = newPercentage > oldPercentage;
275
276 delta += newPercentage % 1; //If new percentage is not an integer, we add the decimal part to the delta
277 steps = Math.floor(Math.abs(newPercentage - oldPercentage) / delta);
278 stepDuration = duration / steps;
279
280
281 (function animate(lastFrame) {
282 if (isGreater)
283 oldPercentage += delta;
284 else
285 oldPercentage -= delta;
286
287 if ((isGreater && oldPercentage >= newPercentage) || (!isGreater && oldPercentage <= newPercentage))
288 {
289 requestAnimFrame(function(){ self._setPercentage(newPercentage); });
290 return;
291 }
292
293 requestAnimFrame(function() { self._setPercentage(oldPercentage); });
294
295 var now = Date.now(),
296 deltaTime = now - lastFrame;
297
298 if (deltaTime >= stepDuration) {
299 animate(now);
300 } else {
301 setTimeout(function() {
302 animate(Date.now());
303 }, stepDuration - deltaTime);
304 }
305
306 })(Date.now());
307
308 return this;
309 }
310 };
311
312 Circles.create = function(options) {
313 return new Circles(options);
314 };
315
316 return Circles;
317 }));