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.

674 lines
21 KiB

10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 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
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
  1. /*
  2. * # Semantic - Progress
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  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. module
  44. ;
  45. module = {
  46. initialize: function() {
  47. module.debug('Initializing progress', settings);
  48. module.read.metadata();
  49. module.set.initials();
  50. module.instantiate();
  51. },
  52. instantiate: function() {
  53. module.verbose('Storing instance of progress', module);
  54. instance = module;
  55. $module
  56. .data(moduleNamespace, module)
  57. ;
  58. },
  59. destroy: function() {
  60. module.verbose('Destroying previous progress for', $module);
  61. module.remove.state();
  62. $module.removeData(moduleNamespace);
  63. instance = undefined;
  64. },
  65. reset: function() {
  66. module.set.percent(0);
  67. },
  68. complete: function() {
  69. if(module.percent === undefined || module.percent < 100) {
  70. module.set.percent(100);
  71. }
  72. },
  73. read: {
  74. metadata: function() {
  75. if( $module.data(metadata.percent) ) {
  76. module.verbose('Current percent value set from metadata');
  77. module.percent = $module.data(metadata.percent);
  78. }
  79. if( $module.data(metadata.total) ) {
  80. module.verbose('Total value set from metadata');
  81. module.total = $module.data(metadata.total);
  82. }
  83. if( $module.data(metadata.value) ) {
  84. module.verbose('Current value set from metadata');
  85. module.value = $module.data(metadata.value);
  86. }
  87. },
  88. currentValue: function() {
  89. return (module.value !== undefined)
  90. ? module.value
  91. : false
  92. ;
  93. }
  94. },
  95. increment: function(incrementValue) {
  96. var
  97. total = module.total || false,
  98. edgeValue,
  99. startValue,
  100. newValue
  101. ;
  102. if(total) {
  103. startValue = module.value || 0;
  104. incrementValue = incrementValue || 1;
  105. newValue = startValue + incrementValue;
  106. edgeValue = module.total;
  107. module.debug('Incrementing value by', incrementValue, startValue, edgeValue);
  108. if(newValue > edgeValue ) {
  109. module.debug('Value cannot increment above total', edgeValue);
  110. newValue = edgeValue;
  111. }
  112. module.set.progress(newValue);
  113. }
  114. else {
  115. startValue = module.percent || 0;
  116. incrementValue = incrementValue || module.get.randomValue();
  117. newValue = startValue + incrementValue;
  118. edgeValue = 100;
  119. module.debug('Incrementing percentage by', incrementValue, startValue);
  120. if(newValue > edgeValue ) {
  121. module.debug('Value cannot increment above 100 percent');
  122. newValue = edgeValue;
  123. }
  124. module.set.progress(newValue);
  125. }
  126. },
  127. decrement: function(decrementValue) {
  128. var
  129. total = module.total || false,
  130. edgeValue = 0,
  131. startValue,
  132. newValue
  133. ;
  134. if(total) {
  135. startValue = module.value || 0;
  136. decrementValue = decrementValue || 1;
  137. newValue = startValue - decrementValue;
  138. module.debug('Decrementing value by', decrementValue, startValue);
  139. }
  140. else {
  141. startValue = module.percent || 0;
  142. decrementValue = decrementValue || module.get.randomValue();
  143. newValue = startValue - decrementValue;
  144. module.debug('Decrementing percentage by', decrementValue, startValue);
  145. }
  146. if(newValue < edgeValue) {
  147. module.debug('Value cannot decrement below 0');
  148. newValue = 0;
  149. }
  150. module.set.progress(newValue);
  151. },
  152. get: {
  153. text: function(templateText) {
  154. var
  155. value = module.value || 0,
  156. total = module.total || 0,
  157. percent = module.percent || 0
  158. ;
  159. templateText = templateText || '';
  160. templateText = templateText
  161. .replace('{value}', value)
  162. .replace('{total}', total)
  163. .replace('{percent}', percent)
  164. ;
  165. module.debug('Adding variables to progress bar text', templateText);
  166. return templateText;
  167. },
  168. randomValue: function() {
  169. module.debug('Generating random increment percentage');
  170. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  171. },
  172. percent: function() {
  173. return module.percent || 0;
  174. },
  175. value: function() {
  176. return module.value || false;
  177. },
  178. total: function() {
  179. return module.total || false;
  180. }
  181. },
  182. is: {
  183. success: function() {
  184. return $module.hasClass(className.success);
  185. },
  186. warning: function() {
  187. return $module.hasClass(className.warning);
  188. },
  189. error: function() {
  190. return $module.hasClass(className.error);
  191. }
  192. },
  193. remove: {
  194. state: function() {
  195. module.verbose('Removing stored state');
  196. delete module.total;
  197. delete module.percent;
  198. delete module.value;
  199. },
  200. active: function() {
  201. module.verbose('Removing active state');
  202. $module.removeClass(className.active);
  203. },
  204. success: function() {
  205. module.verbose('Removing success state');
  206. $module.removeClass(className.success);
  207. },
  208. warning: function() {
  209. module.verbose('Removing warning state');
  210. $module.removeClass(className.warning);
  211. },
  212. error: function() {
  213. module.verbose('Removing error state');
  214. $module.removeClass(className.error);
  215. }
  216. },
  217. set: {
  218. barWidth: function(value) {
  219. if(value > 100) {
  220. module.error(error.tooHigh, value);
  221. }
  222. else if (value < 0) {
  223. module.error(error.tooLow, value);
  224. }
  225. else {
  226. $bar
  227. .css('width', value + '%')
  228. ;
  229. }
  230. },
  231. initials: function() {
  232. if(settings.total !== false) {
  233. module.verbose('Current total set in settings', settings.total);
  234. module.total = settings.total;
  235. }
  236. if(settings.value !== false) {
  237. module.verbose('Current value set in settings', settings.value);
  238. module.value = settings.value;
  239. }
  240. if(settings.percent !== false) {
  241. module.verbose('Current percent set in settings', settings.percent);
  242. module.percent = settings.percent;
  243. }
  244. if(module.percent !== undefined) {
  245. module.set.percent(module.percent);
  246. }
  247. else if(module.value !== undefined) {
  248. module.set.progress(module.value);
  249. }
  250. },
  251. percent: function(percent) {
  252. percent = (typeof percent == 'string')
  253. ? +(percent.replace('%', ''))
  254. : percent
  255. ;
  256. if(percent > 0 && percent < 1) {
  257. module.verbose('Module percentage passed as decimal, converting');
  258. percent = percent * 100;
  259. }
  260. // round percentage
  261. if(settings.precision === 0) {
  262. percent = Math.round(percent);
  263. }
  264. else {
  265. percent = Math.round(percent * (10 * settings.precision) / (10 * settings.precision) );
  266. }
  267. module.percent = percent;
  268. if(module.total) {
  269. module.value = Math.round( (percent / 100) * module.total);
  270. }
  271. if(settings.limitValues) {
  272. module.value = (module.value > 100)
  273. ? 100
  274. : (module.value < 0)
  275. ? 0
  276. : module.value
  277. ;
  278. }
  279. module.set.barWidth(percent);
  280. module.set.barLabel();
  281. if(percent === 100) {
  282. if(settings.autoSuccess && !(module.is.warning() || module.is.error())) {
  283. module.set.success();
  284. module.debug('Automatically triggering success at 100%');
  285. }
  286. else {
  287. module.remove.active();
  288. }
  289. }
  290. else if(percent > 0) {
  291. module.set.active();
  292. }
  293. $.proxy(settings.onChange, element)(percent, module.value, module.total);
  294. },
  295. label: function(text) {
  296. text = text || '';
  297. if(text) {
  298. text = module.get.text(text);
  299. module.debug('Setting label to text', text);
  300. $label.text(text);
  301. }
  302. },
  303. barLabel: function(text) {
  304. if(text !== undefined) {
  305. $progress.text( module.get.text(text) );
  306. }
  307. else if(settings.label == 'ratio' && module.total) {
  308. module.debug('Adding ratio to bar label');
  309. $progress.text( module.get.text(settings.text.ratio) );
  310. }
  311. else if(settings.label == 'percent') {
  312. module.debug('Adding percentage to bar label');
  313. $progress.text( module.get.text(settings.text.percent) );
  314. }
  315. },
  316. active: function(text) {
  317. text = text || settings.text.active;
  318. module.debug('Setting active state');
  319. if(settings.showActivity) {
  320. $module.addClass(className.active);
  321. }
  322. module.remove.warning();
  323. module.remove.error();
  324. module.remove.success();
  325. if(text) {
  326. module.set.label(text);
  327. }
  328. $.proxy(settings.onActive, element)(module.value, module.total);
  329. },
  330. success : function(text) {
  331. text = text || settings.text.success;
  332. module.debug('Setting success state');
  333. $module.addClass(className.success);
  334. module.remove.active();
  335. module.remove.warning();
  336. module.remove.error();
  337. module.complete();
  338. if(text) {
  339. module.set.label(text);
  340. }
  341. $.proxy(settings.onSuccess, element)(module.total);
  342. },
  343. warning : function(text) {
  344. text = text || settings.text.warning;
  345. module.debug('Setting warning state');
  346. $module.addClass(className.warning);
  347. module.remove.active();
  348. module.remove.success();
  349. module.remove.error();
  350. module.complete();
  351. if(text) {
  352. module.set.label(text);
  353. }
  354. $.proxy(settings.onWarning, element)(module.value, module.total);
  355. },
  356. error : function(text) {
  357. text = text || settings.text.error;
  358. module.debug('Setting error state');
  359. $module.addClass(className.error);
  360. module.remove.active();
  361. module.remove.success();
  362. module.remove.warning();
  363. module.complete();
  364. if(text) {
  365. module.set.label(text);
  366. }
  367. $.proxy(settings.onError, element)(module.value, module.total);
  368. },
  369. total: function(totalValue) {
  370. module.total = totalValue;
  371. },
  372. progress: function(value) {
  373. var
  374. numericValue = (typeof value === 'string')
  375. ? (value.replace(/[^\d.]/g, '') !== '')
  376. ? +(value.replace(/[^\d.]/g, ''))
  377. : false
  378. : value,
  379. percentComplete
  380. ;
  381. if(numericValue === false) {
  382. module.error(error.nonNumeric, value);
  383. }
  384. if(module.total) {
  385. module.value = numericValue;
  386. percentComplete = (numericValue / module.total) * 100;
  387. module.debug('Calculating percent complete from total', percentComplete);
  388. module.set.percent( percentComplete );
  389. }
  390. else {
  391. percentComplete = numericValue;
  392. module.debug('Setting value to exact percentage value', percentComplete);
  393. module.set.percent( percentComplete );
  394. }
  395. }
  396. },
  397. setting: function(name, value) {
  398. module.debug('Changing setting', name, value);
  399. if( $.isPlainObject(name) ) {
  400. $.extend(true, settings, name);
  401. }
  402. else if(value !== undefined) {
  403. settings[name] = value;
  404. }
  405. else {
  406. return settings[name];
  407. }
  408. },
  409. internal: function(name, value) {
  410. if( $.isPlainObject(name) ) {
  411. $.extend(true, module, name);
  412. }
  413. else if(value !== undefined) {
  414. module[name] = value;
  415. }
  416. else {
  417. return module[name];
  418. }
  419. },
  420. debug: function() {
  421. if(settings.debug) {
  422. if(settings.performance) {
  423. module.performance.log(arguments);
  424. }
  425. else {
  426. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  427. module.debug.apply(console, arguments);
  428. }
  429. }
  430. },
  431. verbose: function() {
  432. if(settings.verbose && settings.debug) {
  433. if(settings.performance) {
  434. module.performance.log(arguments);
  435. }
  436. else {
  437. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  438. module.verbose.apply(console, arguments);
  439. }
  440. }
  441. },
  442. error: function() {
  443. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  444. module.error.apply(console, arguments);
  445. },
  446. performance: {
  447. log: function(message) {
  448. var
  449. currentTime,
  450. executionTime,
  451. previousTime
  452. ;
  453. if(settings.performance) {
  454. currentTime = new Date().getTime();
  455. previousTime = time || currentTime;
  456. executionTime = currentTime - previousTime;
  457. time = currentTime;
  458. performance.push({
  459. 'Name' : message[0],
  460. 'Arguments' : [].slice.call(message, 1) || '',
  461. 'Element' : element,
  462. 'Execution Time' : executionTime
  463. });
  464. }
  465. clearTimeout(module.performance.timer);
  466. module.performance.timer = setTimeout(module.performance.display, 100);
  467. },
  468. display: function() {
  469. var
  470. title = settings.name + ':',
  471. totalTime = 0
  472. ;
  473. time = false;
  474. clearTimeout(module.performance.timer);
  475. $.each(performance, function(index, data) {
  476. totalTime += data['Execution Time'];
  477. });
  478. title += ' ' + totalTime + 'ms';
  479. if(moduleSelector) {
  480. title += ' \'' + moduleSelector + '\'';
  481. }
  482. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  483. console.groupCollapsed(title);
  484. if(console.table) {
  485. console.table(performance);
  486. }
  487. else {
  488. $.each(performance, function(index, data) {
  489. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  490. });
  491. }
  492. console.groupEnd();
  493. }
  494. performance = [];
  495. }
  496. },
  497. invoke: function(query, passedArguments, context) {
  498. var
  499. object = instance,
  500. maxDepth,
  501. found,
  502. response
  503. ;
  504. passedArguments = passedArguments || queryArguments;
  505. context = element || context;
  506. if(typeof query == 'string' && object !== undefined) {
  507. query = query.split(/[\. ]/);
  508. maxDepth = query.length - 1;
  509. $.each(query, function(depth, value) {
  510. var camelCaseValue = (depth != maxDepth)
  511. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  512. : query
  513. ;
  514. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  515. object = object[camelCaseValue];
  516. }
  517. else if( object[camelCaseValue] !== undefined ) {
  518. found = object[camelCaseValue];
  519. return false;
  520. }
  521. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  522. object = object[value];
  523. }
  524. else if( object[value] !== undefined ) {
  525. found = object[value];
  526. return false;
  527. }
  528. else {
  529. module.error(error.method, query);
  530. return false;
  531. }
  532. });
  533. }
  534. if ( $.isFunction( found ) ) {
  535. response = found.apply(context, passedArguments);
  536. }
  537. else if(found !== undefined) {
  538. response = found;
  539. }
  540. if($.isArray(returnedValue)) {
  541. returnedValue.push(response);
  542. }
  543. else if(returnedValue !== undefined) {
  544. returnedValue = [returnedValue, response];
  545. }
  546. else if(response !== undefined) {
  547. returnedValue = response;
  548. }
  549. return found;
  550. }
  551. };
  552. if(methodInvoked) {
  553. if(instance === undefined) {
  554. module.initialize();
  555. }
  556. module.invoke(query);
  557. }
  558. else {
  559. if(instance !== undefined) {
  560. module.destroy();
  561. }
  562. module.initialize();
  563. }
  564. })
  565. ;
  566. return (returnedValue !== undefined)
  567. ? returnedValue
  568. : this
  569. ;
  570. };
  571. $.fn.progress.settings = {
  572. name : 'Progress',
  573. namespace : 'progress',
  574. debug : false,
  575. verbose : true,
  576. performance : true,
  577. random : {
  578. min : 2,
  579. max : 5
  580. },
  581. autoSuccess : true,
  582. showActivity : true,
  583. limitValues : true,
  584. label : 'percent',
  585. precision : 1,
  586. percent : false,
  587. total : false,
  588. value : false,
  589. onChange : function(percent, value, total){},
  590. onSuccess : function(total){},
  591. onActive : function(value, total){},
  592. onError : function(value, total){},
  593. onWarning : function(value, total){},
  594. error : {
  595. method : 'The method you called is not defined.',
  596. nonNumeric : 'Progress value is non numeric',
  597. tooHigh : 'Value specified is above 100%',
  598. tooLow : 'Value specified is below 0%'
  599. },
  600. regExp: {
  601. variable: /\{\$*[A-z0-9]+\}/g
  602. },
  603. metadata: {
  604. percent : 'percent',
  605. total : 'total',
  606. value : 'value'
  607. },
  608. selector : {
  609. bar : '> .bar',
  610. label : '> .label',
  611. progress : '.bar > .progress'
  612. },
  613. text : {
  614. active : false,
  615. error : false,
  616. success : false,
  617. warning : false,
  618. percent : '{percent}%',
  619. ratio : '{value} of {total}'
  620. },
  621. className : {
  622. active : 'active',
  623. error : 'error',
  624. success : 'success',
  625. warning : 'warning'
  626. }
  627. };
  628. })( jQuery, window , document );