github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/src/definitions/modules/progress.js (about) 1 /*! 2 * # Semantic UI - Progress 3 * http://github.com/semantic-org/semantic-ui/ 4 * 5 * 6 * Copyright 2014 Contributors 7 * Released under the MIT license 8 * http://opensource.org/licenses/MIT 9 * 10 */ 11 12 ;(function ( $, window, document, undefined ) { 13 14 "use strict"; 15 16 $.fn.progress = function(parameters) { 17 var 18 $allModules = $(this), 19 20 moduleSelector = $allModules.selector || '', 21 22 time = new Date().getTime(), 23 performance = [], 24 25 query = arguments[0], 26 methodInvoked = (typeof query == 'string'), 27 queryArguments = [].slice.call(arguments, 1), 28 29 returnedValue 30 ; 31 32 $allModules 33 .each(function() { 34 var 35 settings = ( $.isPlainObject(parameters) ) 36 ? $.extend(true, {}, $.fn.progress.settings, parameters) 37 : $.extend({}, $.fn.progress.settings), 38 39 className = settings.className, 40 metadata = settings.metadata, 41 namespace = settings.namespace, 42 selector = settings.selector, 43 error = settings.error, 44 45 eventNamespace = '.' + namespace, 46 moduleNamespace = 'module-' + namespace, 47 48 $module = $(this), 49 $bar = $(this).find(selector.bar), 50 $progress = $(this).find(selector.progress), 51 $label = $(this).find(selector.label), 52 53 element = this, 54 instance = $module.data(moduleNamespace), 55 56 animating = false, 57 transitionEnd, 58 module 59 ; 60 61 module = { 62 63 initialize: function() { 64 module.debug('Initializing progress bar', settings); 65 66 transitionEnd = module.get.transitionEnd(); 67 68 module.read.metadata(); 69 module.set.duration(); 70 module.set.initials(); 71 module.instantiate(); 72 }, 73 74 instantiate: function() { 75 module.verbose('Storing instance of progress', module); 76 instance = module; 77 $module 78 .data(moduleNamespace, module) 79 ; 80 }, 81 destroy: function() { 82 module.verbose('Destroying previous progress for', $module); 83 clearInterval(instance.interval); 84 module.remove.state(); 85 $module.removeData(moduleNamespace); 86 instance = undefined; 87 }, 88 89 reset: function() { 90 module.set.percent(0); 91 }, 92 93 complete: function() { 94 if(module.percent === undefined || module.percent < 100) { 95 module.set.percent(100); 96 } 97 }, 98 99 read: { 100 metadata: function() { 101 if( $module.data(metadata.percent) ) { 102 module.verbose('Current percent value set from metadata'); 103 module.percent = $module.data(metadata.percent); 104 } 105 if( $module.data(metadata.total) ) { 106 module.verbose('Total value set from metadata'); 107 module.total = $module.data(metadata.total); 108 } 109 if( $module.data(metadata.value) ) { 110 module.verbose('Current value set from metadata'); 111 module.value = $module.data(metadata.value); 112 } 113 }, 114 currentValue: function() { 115 return (module.value !== undefined) 116 ? module.value 117 : false 118 ; 119 } 120 }, 121 122 increment: function(incrementValue) { 123 var 124 total = module.total || false, 125 edgeValue, 126 startValue, 127 newValue 128 ; 129 if(total) { 130 startValue = module.value || 0; 131 incrementValue = incrementValue || 1; 132 newValue = startValue + incrementValue; 133 edgeValue = module.total; 134 module.debug('Incrementing value by', incrementValue, startValue, edgeValue); 135 if(newValue > edgeValue ) { 136 module.debug('Value cannot increment above total', edgeValue); 137 newValue = edgeValue; 138 } 139 module.set.progress(newValue); 140 } 141 else { 142 startValue = module.percent || 0; 143 incrementValue = incrementValue || module.get.randomValue(); 144 newValue = startValue + incrementValue; 145 edgeValue = 100; 146 module.debug('Incrementing percentage by', incrementValue, startValue); 147 if(newValue > edgeValue ) { 148 module.debug('Value cannot increment above 100 percent'); 149 newValue = edgeValue; 150 } 151 module.set.progress(newValue); 152 } 153 }, 154 decrement: function(decrementValue) { 155 var 156 total = module.total || false, 157 edgeValue = 0, 158 startValue, 159 newValue 160 ; 161 if(total) { 162 startValue = module.value || 0; 163 decrementValue = decrementValue || 1; 164 newValue = startValue - decrementValue; 165 module.debug('Decrementing value by', decrementValue, startValue); 166 } 167 else { 168 startValue = module.percent || 0; 169 decrementValue = decrementValue || module.get.randomValue(); 170 newValue = startValue - decrementValue; 171 module.debug('Decrementing percentage by', decrementValue, startValue); 172 } 173 174 if(newValue < edgeValue) { 175 module.debug('Value cannot decrement below 0'); 176 newValue = 0; 177 } 178 module.set.progress(newValue); 179 }, 180 181 get: { 182 text: function(templateText) { 183 var 184 value = module.value || 0, 185 total = module.total || 0, 186 percent = (module.is.visible() && animating) 187 ? module.get.displayPercent() 188 : module.percent || 0, 189 left = (module.total > 0) 190 ? (total - value) 191 : (100 - percent) 192 ; 193 templateText = templateText || ''; 194 templateText = templateText 195 .replace('{value}', value) 196 .replace('{total}', total) 197 .replace('{left}', left) 198 .replace('{percent}', percent) 199 ; 200 module.debug('Adding variables to progress bar text', templateText); 201 return templateText; 202 }, 203 randomValue: function() { 204 module.debug('Generating random increment percentage'); 205 return Math.floor((Math.random() * settings.random.max) + settings.random.min); 206 }, 207 208 transitionEnd: function() { 209 var 210 element = document.createElement('element'), 211 transitions = { 212 'transition' :'transitionend', 213 'OTransition' :'oTransitionEnd', 214 'MozTransition' :'transitionend', 215 'WebkitTransition' :'webkitTransitionEnd' 216 }, 217 transition 218 ; 219 for(transition in transitions){ 220 if( element.style[transition] !== undefined ){ 221 return transitions[transition]; 222 } 223 } 224 }, 225 226 // gets current displayed percentage (if animating values this is the intermediary value) 227 displayPercent: function() { 228 var 229 barWidth = $bar.width(), 230 totalWidth = $module.width(), 231 minDisplay = parseInt($bar.css('min-width'), 10), 232 displayPercent = (barWidth > minDisplay) 233 ? (barWidth / totalWidth * 100) 234 : module.percent 235 ; 236 if(settings.precision === 0) { 237 return Math.round(displayPercent); 238 } 239 return Math.round(displayPercent * (10 * settings.precision) / (10 * settings.precision) ); 240 }, 241 242 percent: function() { 243 return module.percent || 0; 244 }, 245 value: function() { 246 return module.value || false; 247 }, 248 total: function() { 249 return module.total || false; 250 } 251 }, 252 253 is: { 254 success: function() { 255 return $module.hasClass(className.success); 256 }, 257 warning: function() { 258 return $module.hasClass(className.warning); 259 }, 260 error: function() { 261 return $module.hasClass(className.error); 262 }, 263 active: function() { 264 return $module.hasClass(className.active); 265 }, 266 visible: function() { 267 return $module.is(':visible'); 268 } 269 }, 270 271 remove: { 272 state: function() { 273 module.verbose('Removing stored state'); 274 delete module.total; 275 delete module.percent; 276 delete module.value; 277 }, 278 active: function() { 279 module.verbose('Removing active state'); 280 $module.removeClass(className.active); 281 }, 282 success: function() { 283 module.verbose('Removing success state'); 284 $module.removeClass(className.success); 285 }, 286 warning: function() { 287 module.verbose('Removing warning state'); 288 $module.removeClass(className.warning); 289 }, 290 error: function() { 291 module.verbose('Removing error state'); 292 $module.removeClass(className.error); 293 } 294 }, 295 296 set: { 297 barWidth: function(value) { 298 if(value > 100) { 299 module.error(error.tooHigh, value); 300 } 301 else if (value < 0) { 302 module.error(error.tooLow, value); 303 } 304 else { 305 $bar 306 .css('width', value + '%') 307 ; 308 $module 309 .attr('data-percent', parseInt(value, 10)) 310 ; 311 } 312 }, 313 duration: function(duration) { 314 duration = duration || settings.duration; 315 duration = (typeof duration == 'number') 316 ? duration + 'ms' 317 : duration 318 ; 319 module.verbose('Setting progress bar transition duration', duration); 320 $bar 321 .css({ 322 '-webkit-transition-duration': duration, 323 '-moz-transition-duration': duration, 324 '-ms-transition-duration': duration, 325 '-o-transition-duration': duration, 326 'transition-duration': duration 327 }) 328 ; 329 }, 330 initials: function() { 331 if(settings.total !== false) { 332 module.verbose('Current total set in settings', settings.total); 333 module.total = settings.total; 334 } 335 if(settings.value !== false) { 336 module.verbose('Current value set in settings', settings.value); 337 module.value = settings.value; 338 } 339 if(settings.percent !== false) { 340 module.verbose('Current percent set in settings', settings.percent); 341 module.percent = settings.percent; 342 } 343 if(module.percent !== undefined) { 344 module.set.percent(module.percent); 345 } 346 else if(module.value !== undefined) { 347 module.set.progress(module.value); 348 } 349 }, 350 percent: function(percent) { 351 percent = (typeof percent == 'string') 352 ? +(percent.replace('%', '')) 353 : percent 354 ; 355 if(percent > 0 && percent < 1) { 356 module.verbose('Module percentage passed as decimal, converting'); 357 percent = percent * 100; 358 } 359 // round percentage 360 if(settings.precision === 0) { 361 percent = Math.round(percent); 362 } 363 else { 364 percent = Math.round(percent * (10 * settings.precision) / (10 * settings.precision) ); 365 } 366 module.percent = percent; 367 if(module.total) { 368 module.value = Math.round( (percent / 100) * module.total); 369 } 370 else if(settings.limitValues) { 371 module.value = (module.value > 100) 372 ? 100 373 : (module.value < 0) 374 ? 0 375 : module.value 376 ; 377 } 378 module.set.barWidth(percent); 379 if( module.is.visible() ) { 380 module.set.labelInterval(); 381 } 382 module.set.labels(); 383 settings.onChange.call(element, percent, module.value, module.total); 384 }, 385 labelInterval: function() { 386 var 387 animationCallback = function() { 388 module.verbose('Bar finished animating, removing continuous label updates'); 389 clearInterval(module.interval); 390 animating = false; 391 module.set.labels(); 392 } 393 ; 394 clearInterval(module.interval); 395 $bar.one(transitionEnd + eventNamespace, animationCallback); 396 module.timer = setTimeout(animationCallback, settings.duration + 100); 397 animating = true; 398 module.interval = setInterval(module.set.labels, settings.framerate); 399 }, 400 labels: function() { 401 module.verbose('Setting both bar progress and outer label text'); 402 module.set.barLabel(); 403 module.set.state(); 404 }, 405 label: function(text) { 406 text = text || ''; 407 if(text) { 408 text = module.get.text(text); 409 module.debug('Setting label to text', text); 410 $label.text(text); 411 } 412 }, 413 state: function(percent) { 414 percent = (percent !== undefined) 415 ? percent 416 : module.percent 417 ; 418 if(percent === 100) { 419 if(settings.autoSuccess && !(module.is.warning() || module.is.error())) { 420 module.set.success(); 421 module.debug('Automatically triggering success at 100%'); 422 } 423 else { 424 module.verbose('Reached 100% removing active state'); 425 module.remove.active(); 426 } 427 } 428 else if(percent > 0) { 429 module.verbose('Adjusting active progress bar label', percent); 430 module.set.active(); 431 } 432 else { 433 module.remove.active(); 434 module.set.label(settings.text.active); 435 } 436 }, 437 barLabel: function(text) { 438 if(text !== undefined) { 439 $progress.text( module.get.text(text) ); 440 } 441 else if(settings.label == 'ratio' && module.total) { 442 module.debug('Adding ratio to bar label'); 443 $progress.text( module.get.text(settings.text.ratio) ); 444 } 445 else if(settings.label == 'percent') { 446 module.debug('Adding percentage to bar label'); 447 $progress.text( module.get.text(settings.text.percent) ); 448 } 449 }, 450 active: function(text) { 451 text = text || settings.text.active; 452 module.debug('Setting active state'); 453 if(settings.showActivity && !module.is.active() ) { 454 $module.addClass(className.active); 455 } 456 module.remove.warning(); 457 module.remove.error(); 458 module.remove.success(); 459 if(text) { 460 module.set.label(text); 461 } 462 settings.onActive.call(element, module.value, module.total); 463 }, 464 success : function(text) { 465 text = text || settings.text.success; 466 module.debug('Setting success state'); 467 $module.addClass(className.success); 468 module.remove.active(); 469 module.remove.warning(); 470 module.remove.error(); 471 module.complete(); 472 if(text) { 473 module.set.label(text); 474 } 475 settings.onSuccess.call(element, module.total); 476 }, 477 warning : function(text) { 478 text = text || settings.text.warning; 479 module.debug('Setting warning state'); 480 $module.addClass(className.warning); 481 module.remove.active(); 482 module.remove.success(); 483 module.remove.error(); 484 module.complete(); 485 if(text) { 486 module.set.label(text); 487 } 488 settings.onWarning.call(element, module.value, module.total); 489 }, 490 error : function(text) { 491 text = text || settings.text.error; 492 module.debug('Setting error state'); 493 $module.addClass(className.error); 494 module.remove.active(); 495 module.remove.success(); 496 module.remove.warning(); 497 module.complete(); 498 if(text) { 499 module.set.label(text); 500 } 501 settings.onError.call(element, module.value, module.total); 502 }, 503 total: function(totalValue) { 504 module.total = totalValue; 505 }, 506 progress: function(value) { 507 var 508 numericValue = (typeof value === 'string') 509 ? (value.replace(/[^\d.]/g, '') !== '') 510 ? +(value.replace(/[^\d.]/g, '')) 511 : false 512 : value, 513 percentComplete 514 ; 515 if(numericValue === false) { 516 module.error(error.nonNumeric, value); 517 } 518 if(module.total) { 519 module.value = numericValue; 520 percentComplete = (numericValue / module.total) * 100; 521 module.debug('Calculating percent complete from total', percentComplete); 522 module.set.percent( percentComplete ); 523 } 524 else { 525 percentComplete = numericValue; 526 module.debug('Setting value to exact percentage value', percentComplete); 527 module.set.percent( percentComplete ); 528 } 529 } 530 }, 531 532 setting: function(name, value) { 533 module.debug('Changing setting', name, value); 534 if( $.isPlainObject(name) ) { 535 $.extend(true, settings, name); 536 } 537 else if(value !== undefined) { 538 settings[name] = value; 539 } 540 else { 541 return settings[name]; 542 } 543 }, 544 internal: function(name, value) { 545 if( $.isPlainObject(name) ) { 546 $.extend(true, module, name); 547 } 548 else if(value !== undefined) { 549 module[name] = value; 550 } 551 else { 552 return module[name]; 553 } 554 }, 555 debug: function() { 556 if(settings.debug) { 557 if(settings.performance) { 558 module.performance.log(arguments); 559 } 560 else { 561 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 562 module.debug.apply(console, arguments); 563 } 564 } 565 }, 566 verbose: function() { 567 if(settings.verbose && settings.debug) { 568 if(settings.performance) { 569 module.performance.log(arguments); 570 } 571 else { 572 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 573 module.verbose.apply(console, arguments); 574 } 575 } 576 }, 577 error: function() { 578 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 579 module.error.apply(console, arguments); 580 }, 581 performance: { 582 log: function(message) { 583 var 584 currentTime, 585 executionTime, 586 previousTime 587 ; 588 if(settings.performance) { 589 currentTime = new Date().getTime(); 590 previousTime = time || currentTime; 591 executionTime = currentTime - previousTime; 592 time = currentTime; 593 performance.push({ 594 'Name' : message[0], 595 'Arguments' : [].slice.call(message, 1) || '', 596 'Element' : element, 597 'Execution Time' : executionTime 598 }); 599 } 600 clearTimeout(module.performance.timer); 601 module.performance.timer = setTimeout(module.performance.display, 100); 602 }, 603 display: function() { 604 var 605 title = settings.name + ':', 606 totalTime = 0 607 ; 608 time = false; 609 clearTimeout(module.performance.timer); 610 $.each(performance, function(index, data) { 611 totalTime += data['Execution Time']; 612 }); 613 title += ' ' + totalTime + 'ms'; 614 if(moduleSelector) { 615 title += ' \'' + moduleSelector + '\''; 616 } 617 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 618 console.groupCollapsed(title); 619 if(console.table) { 620 console.table(performance); 621 } 622 else { 623 $.each(performance, function(index, data) { 624 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 625 }); 626 } 627 console.groupEnd(); 628 } 629 performance = []; 630 } 631 }, 632 invoke: function(query, passedArguments, context) { 633 var 634 object = instance, 635 maxDepth, 636 found, 637 response 638 ; 639 passedArguments = passedArguments || queryArguments; 640 context = element || context; 641 if(typeof query == 'string' && object !== undefined) { 642 query = query.split(/[\. ]/); 643 maxDepth = query.length - 1; 644 $.each(query, function(depth, value) { 645 var camelCaseValue = (depth != maxDepth) 646 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 647 : query 648 ; 649 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 650 object = object[camelCaseValue]; 651 } 652 else if( object[camelCaseValue] !== undefined ) { 653 found = object[camelCaseValue]; 654 return false; 655 } 656 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 657 object = object[value]; 658 } 659 else if( object[value] !== undefined ) { 660 found = object[value]; 661 return false; 662 } 663 else { 664 module.error(error.method, query); 665 return false; 666 } 667 }); 668 } 669 if ( $.isFunction( found ) ) { 670 response = found.apply(context, passedArguments); 671 } 672 else if(found !== undefined) { 673 response = found; 674 } 675 if($.isArray(returnedValue)) { 676 returnedValue.push(response); 677 } 678 else if(returnedValue !== undefined) { 679 returnedValue = [returnedValue, response]; 680 } 681 else if(response !== undefined) { 682 returnedValue = response; 683 } 684 return found; 685 } 686 }; 687 688 if(methodInvoked) { 689 if(instance === undefined) { 690 module.initialize(); 691 } 692 module.invoke(query); 693 } 694 else { 695 if(instance !== undefined) { 696 instance.invoke('destroy'); 697 } 698 module.initialize(); 699 } 700 }) 701 ; 702 703 return (returnedValue !== undefined) 704 ? returnedValue 705 : this 706 ; 707 }; 708 709 $.fn.progress.settings = { 710 711 name : 'Progress', 712 namespace : 'progress', 713 714 debug : false, 715 verbose : true, 716 performance : true, 717 718 random : { 719 min : 2, 720 max : 5 721 }, 722 723 duration : 300, 724 725 autoSuccess : true, 726 showActivity : true, 727 limitValues : true, 728 729 label : 'percent', 730 precision : 1, 731 framerate : (1000 / 30), /// 30 fps 732 733 percent : false, 734 total : false, 735 value : false, 736 737 onChange : function(percent, value, total){}, 738 onSuccess : function(total){}, 739 onActive : function(value, total){}, 740 onError : function(value, total){}, 741 onWarning : function(value, total){}, 742 743 error : { 744 method : 'The method you called is not defined.', 745 nonNumeric : 'Progress value is non numeric', 746 tooHigh : 'Value specified is above 100%', 747 tooLow : 'Value specified is below 0%' 748 }, 749 750 regExp: { 751 variable: /\{\$*[A-z0-9]+\}/g 752 }, 753 754 metadata: { 755 percent : 'percent', 756 total : 'total', 757 value : 'value' 758 }, 759 760 selector : { 761 bar : '> .bar', 762 label : '> .label', 763 progress : '.bar > .progress' 764 }, 765 766 text : { 767 active : false, 768 error : false, 769 success : false, 770 warning : false, 771 percent : '{percent}%', 772 ratio : '{value} of {total}' 773 }, 774 775 className : { 776 active : 'active', 777 error : 'error', 778 success : 'success', 779 warning : 'warning' 780 } 781 782 }; 783 784 785 })( jQuery, window , document );