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.

640 lines
20 KiB

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