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.

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