vendor: 15,920 bytes, lines 1-487
1(function(factory) { 2 if (typeof define === 'function' && define.amd) { 3 // AMD - register as an anonymous module 4 define(['jquery'], factory); 5 } else if (typeof module === 'object' && module.exports) { 6 // Node/CommonJS 7 var $ = require('jquery'); 8 factory($); 9 module.exports = $; 10 } else { 11 // Browser globals 12 factory(jQuery); 13 } 14})(function($) { 15 /** 16 * Inner implementation of the circle progress bar. 17 * The class is not exposed _yet_ but you can create an instance through jQuery method call. 18 * 19 * @param {object} config - You can customize any class member (property or method). 20 * @class 21 * @alias CircleProgress 22 */ 23 function CircleProgress(config) { 24 this.init(config); 25 } 26 27 CircleProgress.prototype = { 28 //--------------------------------------- public options --------------------------------------- 29 /** 30 * This is the only required option. It should be from `0.0` to `1.0`. 31 * @type {number} 32 * @default 0.0 33 */ 34 value: 0.0, 35 36 /** 37 * Size of the canvas in pixels. 38 * It's a square so we need only one dimension. 39 * @type {number} 40 * @default 100.0 41 */ 42 size: 100.0, 43 44 /** 45 * Initial angle for `0.0` value in radians. 46 * @type {number} 47 * @default -Math.PI 48 */ 49 startAngle: -Math.PI, 50 51 /** 52 * Width of the arc in pixels. 53 * If it's `'auto'` - the value is calculated as `[this.size]{@link CircleProgress#size} / 14`. 54 * @type {number|string} 55 * @default 'auto' 56 */ 57 thickness: 'auto', 58 59 /** 60 * Fill of the arc. You may set it to: 61 * 62 * - solid color: 63 * - `'#3aeabb'` 64 * - `{ color: '#3aeabb' }` 65 * - `{ color: 'rgba(255, 255, 255, .3)' }` 66 * - linear gradient _(left to right)_: 67 * - `{ gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 }` 68 * - `{ gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] }` 69 * - `{ gradient: [["red", .2], ["green", .3], ["blue", .8]] }` 70 * - image: 71 * - `{ image: 'http://i.imgur.com/pT0i89v.png' }` 72 * - `{ image: imageObject }` 73 * - `{ color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' }` - 74 * color displayed until the image is loaded 75 * 76 * @default {gradient: ['#3aeabb', '#fdd250']} 77 */ 78 fill: { 79 gradient: ['#3aeabb', '#fdd250'] 80 }, 81 82 /** 83 * Color of the "empty" arc. Only a color fill supported by now. 84 * @type {string} 85 * @default 'rgba(0, 0, 0, .1)' 86 */ 87 emptyFill: 'rgba(0, 0, 0, .1)', 88 89 /** 90 * jQuery Animation config. 91 * You can pass `false` to disable the animation. 92 * @see http://api.jquery.com/animate/ 93 * @type {object|boolean} 94 * @default {duration: 1200, easing: 'circleProgressEasing'} 95 */ 96 animation: { 97 duration: 0, 98 99 }, 100 101 /** 102 * Default animation starts at `0.0` and ends at specified `value`. Let's call this _direct animation_. 103 * If you want to make _reversed animation_ - set `animationStartValue: 1.0`. 104 * Also you may specify any other value from `0.0` to `1.0`. 105 * @type {number} 106 * @default 0.0 107 */ 108 animationStartValue: 0.0, 109 110 /** 111 * Reverse animation and arc draw. 112 * By default, the arc is filled from `0.0` to `value`, _clockwise_. 113 * With `reverse: true` the arc is filled from `1.0` to `value`, _counter-clockwise_. 114 * @type {boolean} 115 * @default false 116 */ 117 reverse: true, 118 119 /** 120 * Arc line cap: `'butt'`, `'round'` or `'square'` - 121 * [read more]{@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap}. 122 * @type {string} 123 * @default 'butt' 124 */ 125 lineCap: 'butt', 126 127 /** 128 * Canvas insertion mode: append or prepend it into the parent element? 129 * @type {string} 130 * @default 'prepend' 131 */ 132 insertMode: 'prepend', 133 134 //------------------------------ protected properties and methods ------------------------------ 135 /** 136 * Link to {@link CircleProgress} constructor. 137 * @protected 138 */ 139 constructor: CircleProgress, 140 141 /** 142 * Container element. Should be passed into constructor config. 143 * @protected 144 * @type {jQuery} 145 */ 146 el: null, 147 148 /** 149 * Canvas element. Automatically generated and prepended to [this.el]{@link CircleProgress#el}. 150 * @protected 151 * @type {HTMLCanvasElement} 152 */ 153 canvas: null, 154 155 /** 156 * 2D-context of [this.canvas]{@link CircleProgress#canvas}. 157 * @protected 158 * @type {CanvasRenderingContext2D} 159 */ 160 ctx: null, 161 162 /** 163 * Radius of the outer circle. Automatically calculated as `[this.size]{@link CircleProgress#size} / 2`. 164 * @protected 165 * @type {number} 166 */ 167 radius: 0.0, 168 169 /** 170 * Fill of the main arc. Automatically calculated, depending on [this.fill]{@link CircleProgress#fill} option. 171 * @protected 172 * @type {string|CanvasGradient|CanvasPattern} 173 */ 174 arcFill: null, 175 176 /** 177 * Last rendered frame value. 178 * @protected 179 * @type {number} 180 */ 181 lastFrameValue: 0.0, 182 183 /** 184 * Init/re-init the widget. 185 * 186 * Throws a jQuery event: 187 * 188 * - `circle-inited(jqEvent)` 189 * 190 * @param {object} config - You can customize any class member (property or method). 191 */ 192 init: function(config) { 193 $.extend(this, config); 194 this.radius = this.size / 2; 195 this.initWidget(); 196 this.initFill(); 197 this.draw(); 198 this.el.trigger('circle-inited'); 199 }, 200 201 /** 202 * Initialize `<canvas>`. 203 * @protected 204 */ 205 initWidget: function() { 206 if (!this.canvas) 207 this.canvas = $('<canvas>')[this.insertMode == 'prepend' ? 'prependTo' : 'appendTo'](this.el)[0]; 208 209 var canvas = this.canvas; 210 canvas.width = this.size; 211 canvas.height = this.size; 212 this.ctx = canvas.getContext('2d'); 213 214 if (window.devicePixelRatio > 1) { 215 var scaleBy = window.devicePixelRatio; 216 canvas.style.width = canvas.style.height = this.size + 'px'; 217 canvas.width = canvas.height = this.size * scaleBy; 218 this.ctx.scale(scaleBy, scaleBy); 219 } 220 }, 221 222 /** 223 * This method sets [this.arcFill]{@link CircleProgress#arcFill}. 224 * It could do this async (on image load). 225 * @protected 226 */ 227 initFill: function() { 228 var self = this, 229 fill = this.fill, 230 ctx = this.ctx, 231 size = this.size; 232 233 if (!fill) 234 throw Error("The fill is not specified!"); 235 236 if (typeof fill == 'string') 237 fill = {color: fill}; 238 239 if (fill.color) 240 this.arcFill = fill.color; 241 242 if (fill.gradient) { 243 var gr = fill.gradient; 244 245 if (gr.length == 1) { 246 this.arcFill = gr[0]; 247 } else if (gr.length > 1) { 248 var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default 249 gd = fill.gradientDirection || [ 250 size / 2 * (1 - Math.cos(ga)), // x0 251 size / 2 * (1 + Math.sin(ga)), // y0 252 size / 2 * (1 + Math.cos(ga)), // x1 253 size / 2 * (1 - Math.sin(ga)) // y1 254 ]; 255 256 var lg = ctx.createLinearGradient.apply(ctx, gd); 257 258 for (var i = 0; i < gr.length; i++) { 259 var color = gr[i], 260 pos = i / (gr.length - 1); 261 262 if ($.isArray(color)) { 263 pos = color[1]; 264 color = color[0]; 265 } 266 267 lg.addColorStop(pos, color); 268 } 269 270 this.arcFill = lg; 271 } 272 } 273 274 if (fill.image) { 275 var img; 276 277 if (fill.image instanceof Image) { 278 img = fill.image; 279 } else { 280 img = new Image(); 281 img.src = fill.image; 282 } 283 284 if (img.complete) 285 setImageFill(); 286 else 287 img.onload = setImageFill; 288 } 289 290 function setImageFill() { 291 var bg = $('<canvas>')[0]; 292 bg.width = self.size; 293 bg.height = self.size; 294 bg.getContext('2d').drawImage(img, 0, 0, size, size); 295 self.arcFill = self.ctx.createPattern(bg, 'no-repeat'); 296 self.drawFrame(self.lastFrameValue); 297 } 298 }, 299 300 /** 301 * Draw the circle. 302 * @protected 303 */ 304 draw: function() { 305 if (this.animation) 306 this.drawAnimated(this.value); 307 else 308 this.drawFrame(this.value); 309 }, 310 311 /** 312 * Draw a single animation frame. 313 * @protected 314 * @param {number} v - Frame value. 315 */ 316 drawFrame: function(v) { 317 this.lastFrameValue = v; 318 this.ctx.clearRect(0, 0, this.size, this.size); 319 this.drawEmptyArc(v); 320 this.drawArc(v); 321 }, 322 323 /** 324 * Draw the arc (part of the circle). 325 * @protected 326 * @param {number} v - Frame value. 327 */ 328 drawArc: function(v) { 329 if (v === 0) 330 return; 331 332 var ctx = this.ctx, 333 r = this.radius, 334 t = this.getThickness(), 335 a = this.startAngle; 336 337 ctx.save(); 338 ctx.beginPath(); 339 340 if (!this.reverse) { 341 ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v); 342 } else { 343 ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a); 344 } 345 346 ctx.lineWidth = t; 347 ctx.lineCap = this.lineCap; 348 ctx.strokeStyle = this.arcFill; 349 ctx.stroke(); 350 ctx.restore(); 351 }, 352 353 354 drawEmptyArc: function(v) { 355 var ctx = this.ctx, 356 r = this.radius, 357 t = this.getThickness(), 358 a = this.startAngle; 359 360 if (v < 1) { 361 ctx.save(); 362 ctx.beginPath(); 363 364 if (v <= 0) { 365 ctx.arc(r, r, r - t / 2, 0, Math.PI * 2); 366 } else { 367 if (!this.reverse) { 368 ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a); 369 } else { 370 ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v); 371 } 372 } 373 374 ctx.lineWidth = t; 375 ctx.strokeStyle = this.emptyFill; 376 ctx.stroke(); 377 ctx.restore(); 378 } 379 }, 380 381 382 drawAnimated: function(v) { 383 var self = this, 384 el = this.el, 385 canvas = $(this.canvas); 386 387 // stop previous animation before new "start" event is triggered 388 canvas.stop(true, false); 389 el.trigger('circle-animation-start'); 390 391 canvas 392 .css({animationProgress: 0}) 393 .animate({animationProgress: 1}, $.extend({}, this.animation, { 394 step: function(animationProgress) { 395 var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress; 396 self.drawFrame(stepValue); 397 el.trigger('circle-animation-progress', [animationProgress, stepValue]); 398 } 399 })) 400 .promise() 401 .always(function() { 402 // trigger on both successful & failure animation end 403 el.trigger('circle-animation-end'); 404 }); 405 }, 406 407 408 getThickness: function() { 409 return $.isNumeric(this.thickness) ? this.thickness : this.size / 14; 410 }, 411 412 413 getValue: function() { 414 return this.value; 415 }, 416 417 418 setValue: function(newValue) { 419 if (this.animation) 420 this.animationStartValue = this.lastFrameValue; 421 this.value = newValue; 422 this.draw(); 423 } 424 }; 425 426 //----------------------------------- Initiating jQuery plugin ----------------------------------- 427 $.circleProgress = { 428 // Default options (you may override them) 429 defaults: CircleProgress.prototype 430 }; 431 432 // ease-in-out-cubic 433 $.easing.circleProgressEasing = function(x) { 434 if (x < 0.5) { 435 x = 2 * x; 436 return 0.5 * x * x * x; 437 } else { 438 x = 2 - 2 * x; 439 return 1 - 0.5 * x * x * x; 440 } 441 }; 442 443 444 $.fn.circleProgress = function(configOrCommand, commandArgument) { 445 var dataName = 'circle-progress', 446 firstInstance = this.data(dataName); 447 448 if (configOrCommand == 'widget') { 449 if (!firstInstance) 450 throw Error('Calling "widget" method on not initialized instance is forbidden'); 451 return firstInstance.canvas; 452 } 453 454 if (configOrCommand == 'value') { 455 if (!firstInstance) 456 throw Error('Calling "value" method on not initialized instance is forbidden'); 457 if (typeof commandArgument == 'undefined') { 458 return firstInstance.getValue(); 459 } else { 460 var newValue = arguments[1]; 461 return this.each(function() { 462 $(this).data(dataName).setValue(newValue); 463 }); 464 } 465 } 466 467 return this.each(function() { 468 var el = $(this), 469 instance = el.data(dataName), 470 config = $.isPlainObject(configOrCommand) ? configOrCommand : {}; 471 472 if (instance) { 473 instance.init(config); 474 } else { 475 var initialConfig = $.extend({}, el.data()); 476 if (typeof initialConfig.fill == 'string') 477 initialConfig.fill = JSON.parse(initialConfig.fill); 478 if (typeof initialConfig.animation == 'string') 479 initialConfig.animation = JSON.parse(initialConfig.animation); 480 config = $.extend(initialConfig, config); 481 config.el = el; 482 instance = new CircleProgress(config); 483 el.data(dataName, instance); 484 } 485 }); 486 }; 487});
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.