You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

793 lines
25 KiB

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