/src/flipclock/js/libs/flipclock.js

https://github.com/lukaserat/FlipClock · JavaScript · 1394 lines · 596 code · 303 blank · 495 comment · 82 complexity · 875362d45ea6b4f9bed96f274586a6b1 MD5 · raw file

  1. /*jshint smarttabs:true */
  2. var FlipClock;
  3. /**
  4. * FlipClock.js
  5. *
  6. * @author Justin Kimbrell
  7. * @copyright 2013 - Objective HTML, LLC
  8. * @licesnse http://www.opensource.org/licenses/mit-license.php
  9. */
  10. (function($) {
  11. "use strict";
  12. /**
  13. * FlipFlock Helper
  14. *
  15. * @param object A jQuery object or CSS select
  16. * @param int An integer used to start the clock (no. seconds)
  17. * @param object An object of properties to override the default
  18. */
  19. FlipClock = function(obj, digit, options) {
  20. return new FlipClock.Factory(obj, digit, options);
  21. };
  22. /**
  23. * The global FlipClock.Lang object
  24. */
  25. FlipClock.Lang = {};
  26. /**
  27. * The Base FlipClock class is used to extend all other FlipFlock
  28. * classes. It handles the callbacks and the basic setters/getters
  29. *
  30. * @param object An object of the default properties
  31. * @param object An object of properties to override the default
  32. */
  33. FlipClock.Base = Base.extend({
  34. /**
  35. * Build Date
  36. */
  37. buildDate: '2013-11-07',
  38. /**
  39. * Version
  40. */
  41. version: '0.3.1',
  42. /**
  43. * Sets the default options
  44. *
  45. * @param object The default options
  46. * @param object The override options
  47. */
  48. constructor: function(_default, options) {
  49. if(typeof _default !== "object") {
  50. _default = {};
  51. }
  52. if(typeof options !== "object") {
  53. options = {};
  54. }
  55. this.setOptions($.extend(true, {}, _default, options));
  56. },
  57. /**
  58. * Delegates the callback to the defined method
  59. *
  60. * @param object The default options
  61. * @param object The override options
  62. */
  63. callback: function(method) {
  64. if(typeof method === "function") {
  65. var args = [];
  66. for(var x = 1; x <= arguments.length; x++) {
  67. if(arguments[x]) {
  68. args.push(arguments[x]);
  69. }
  70. }
  71. method.apply(this, args);
  72. }
  73. },
  74. /**
  75. * Log a string into the console if it exists
  76. *
  77. * @param string The name of the option
  78. * @return mixed
  79. */
  80. log: function(str) {
  81. if(window.console && console.log) {
  82. console.log(str);
  83. }
  84. },
  85. /**
  86. * Get an single option value. Returns false if option does not exist
  87. *
  88. * @param string The name of the option
  89. * @return mixed
  90. */
  91. getOption: function(index) {
  92. if(this[index]) {
  93. return this[index];
  94. }
  95. return false;
  96. },
  97. /**
  98. * Get all options
  99. *
  100. * @return bool
  101. */
  102. getOptions: function() {
  103. return this;
  104. },
  105. /**
  106. * Set a single option value
  107. *
  108. * @param string The name of the option
  109. * @param mixed The value of the option
  110. */
  111. setOption: function(index, value) {
  112. this[index] = value;
  113. },
  114. /**
  115. * Set a multiple options by passing a JSON object
  116. *
  117. * @param object The object with the options
  118. * @param mixed The value of the option
  119. */
  120. setOptions: function(options) {
  121. for(var key in options) {
  122. if(typeof options[key] !== "undefined") {
  123. this.setOption(key, options[key]);
  124. }
  125. }
  126. }
  127. });
  128. /**
  129. * The FlipClock Factory class is used to build the clock and manage
  130. * all the public methods.
  131. *
  132. * @param object A jQuery object or CSS selector used to fetch
  133. the wrapping DOM nodes
  134. * @param mixed This is the digit used to set the clock. If an
  135. object is passed, 0 will be used.
  136. * @param object An object of properties to override the default
  137. */
  138. FlipClock.Factory = FlipClock.Base.extend({
  139. /**
  140. * Auto start the clock on page load (True|False)
  141. */
  142. autoStart: true,
  143. /**
  144. * The callback methods
  145. */
  146. callbacks: {
  147. destroy: false,
  148. create: false,
  149. init: false,
  150. interval: false,
  151. start: false,
  152. stop: false,
  153. reset: false
  154. },
  155. /**
  156. * The CSS classes
  157. */
  158. classes: {
  159. active: 'flip-clock-active',
  160. before: 'flip-clock-before',
  161. divider: 'flip-clock-divider',
  162. dot: 'flip-clock-dot',
  163. label: 'flip-clock-label',
  164. flip: 'flip',
  165. play: 'play',
  166. wrapper: 'flip-clock-wrapper'
  167. },
  168. /**
  169. * The name of the clock face class in use
  170. */
  171. clockFace: 'HourlyCounter',
  172. /**
  173. * The name of the default clock face class to use if the defined
  174. * clockFace variable is not a valid FlipClock.Face object
  175. */
  176. defaultClockFace: 'HourlyCounter',
  177. /**
  178. * The default language
  179. */
  180. defaultLanguage: 'english',
  181. /**
  182. * The language being used to display labels (string)
  183. */
  184. language: 'english',
  185. /**
  186. * The language object after it has been loaded
  187. */
  188. lang: false,
  189. /**
  190. * The FlipClock.Face object
  191. */
  192. face: true,
  193. /**
  194. * Is the clock running? (True|False)
  195. */
  196. running: false,
  197. /**
  198. * The FlipClock.Time object
  199. */
  200. time: false,
  201. /**
  202. * The FlipClock.Timer object
  203. */
  204. timer: false,
  205. /**
  206. * An array of FlipClock.List objects
  207. */
  208. lists: [],
  209. /**
  210. * The wrapping jQuery object
  211. */
  212. $wrapper: false,
  213. /**
  214. * Constructor
  215. *
  216. * @param object The wrapping jQuery object
  217. * @param object Number of seconds used to start the clock
  218. * @param object An object override options
  219. */
  220. constructor: function(obj, digit, options) {
  221. this.lists = [];
  222. this.running = false;
  223. this.base(options);
  224. this.$wrapper = $(obj).addClass(this.classes.wrapper);
  225. this.time = new FlipClock.Time(this, digit ? Math.round(digit) : 0);
  226. this.timer = new FlipClock.Timer(this, options);
  227. this.lang = this.loadLanguage(this.language);
  228. this.face = this.loadClockFace(this.clockFace, options);
  229. if(this.autoStart) {
  230. this.start();
  231. }
  232. },
  233. /**
  234. * Load the FlipClock.Face object
  235. *
  236. * @param object The name of the FlickClock.Face class
  237. * @param object An object override options
  238. */
  239. loadClockFace: function(name, options) {
  240. var face, suffix = 'Face';
  241. name = name.ucfirst()+suffix;
  242. if(FlipClock[name]) {
  243. face = new FlipClock[name](this, options);
  244. }
  245. else {
  246. face = new FlipClock[this.defaultClockFace+suffix](this, options);
  247. }
  248. face.build();
  249. return face;
  250. },
  251. /**
  252. * Load the FlipClock.Lang object
  253. *
  254. * @param object The name of the language to load
  255. */
  256. loadLanguage: function(name) {
  257. var lang;
  258. if(FlipClock.Lang[name.ucfirst()]) {
  259. lang = FlipClock.Lang[name.ucfirst()];
  260. }
  261. else if(FlipClock.Lang[name]) {
  262. lang = FlipClock.Lang[name];
  263. }
  264. else {
  265. lang = FlipClock.Lang[this.defaultLanguage];
  266. }
  267. return lang;
  268. },
  269. /**
  270. * Localize strings into various languages
  271. *
  272. * @param string The index of the localized string
  273. * @param object Optionally pass a lang object
  274. */
  275. localize: function(index, obj) {
  276. var lang = this.lang;
  277. if(!index) {
  278. return null;
  279. }
  280. var lindex = index.toLowerCase();
  281. if(typeof obj == "object") {
  282. lang = obj;
  283. }
  284. if(lang && lang[lindex]) {
  285. return lang[lindex];
  286. }
  287. return index;
  288. },
  289. /**
  290. * Starts the clock
  291. */
  292. start: function(callback) {
  293. var t = this;
  294. if(!t.running && (!t.countdown || t.countdown && t.time.time > 0)) {
  295. t.face.start(t.time);
  296. t.timer.start(function() {
  297. t.flip();
  298. if(typeof callback === "function") {
  299. callback();
  300. }
  301. });
  302. }
  303. else {
  304. t.log('Trying to start timer when countdown already at 0');
  305. }
  306. },
  307. /**
  308. * Stops the clock
  309. */
  310. stop: function(callback) {
  311. this.face.stop();
  312. this.timer.stop(callback);
  313. for(var x in this.lists) {
  314. this.lists[x].stop();
  315. }
  316. },
  317. /**
  318. * Reset the clock
  319. */
  320. reset: function(callback) {
  321. this.timer.reset(callback);
  322. this.face.reset();
  323. },
  324. /**
  325. * Sets the clock time
  326. */
  327. setTime: function(time) {
  328. this.time.time = time;
  329. this.face.setTime(time);
  330. },
  331. /**
  332. * Get the clock time
  333. *
  334. * @return object Returns a FlipClock.Time object
  335. */
  336. getTime: function(time) {
  337. return this.time;
  338. },
  339. /**
  340. * Changes the increment of time to up or down (add/sub)
  341. */
  342. setCountdown: function(value) {
  343. var running = this.running;
  344. this.countdown = value ? true : false;
  345. if(running) {
  346. this.stop();
  347. this.start();
  348. }
  349. },
  350. /**
  351. * Flip the digits on the clock
  352. *
  353. * @param array An array of digits
  354. */
  355. flip: function() {
  356. this.face.flip();
  357. }
  358. });
  359. /**
  360. * The FlipClock Face class is the base class in which to extend
  361. * all other FlockClock.Face classes.
  362. *
  363. * @param object The parent FlipClock.Factory object
  364. * @param object An object of properties to override the default
  365. */
  366. FlipClock.Face = FlipClock.Base.extend({
  367. /**
  368. * An array of jQuery objects used for the dividers (the colons)
  369. */
  370. dividers: [],
  371. /**
  372. * An array of FlipClock.List objects
  373. */
  374. factory: false,
  375. /**
  376. * An array of FlipClock.List objects
  377. */
  378. lists: [],
  379. /**
  380. * Constructor
  381. *
  382. * @param object The parent FlipClock.Factory object
  383. * @param object An object of properties to override the default
  384. */
  385. constructor: function(factory, options) {
  386. this.base(options);
  387. this.factory = factory;
  388. this.dividers = [];
  389. },
  390. /**
  391. * Build the clock face
  392. */
  393. build: function() {},
  394. /**
  395. * Creates a jQuery object used for the digit divider
  396. *
  397. * @param mixed The divider label text
  398. * @param mixed Set true to exclude the dots in the divider.
  399. * If not set, is false.
  400. */
  401. createDivider: function(label, css, excludeDots) {
  402. if(typeof css == "boolean" || !css) {
  403. excludeDots = css;
  404. css = label;
  405. }
  406. var dots = [
  407. '<span class="'+this.factory.classes.dot+' top"></span>',
  408. '<span class="'+this.factory.classes.dot+' bottom"></span>'
  409. ].join('');
  410. if(excludeDots) {
  411. dots = '';
  412. }
  413. label = this.factory.localize(label);
  414. var html = [
  415. '<span class="'+this.factory.classes.divider+' '+(css ? css : '').toLowerCase()+'">',
  416. '<span class="'+this.factory.classes.label+'">'+(label ? label : '')+'</span>',
  417. dots,
  418. '</span>'
  419. ];
  420. return $(html.join(''));
  421. },
  422. /**
  423. * Creates a FlipClock.List object and appends it to the DOM
  424. *
  425. * @param mixed The digit to select in the list
  426. * @param object An object to override the default properties
  427. */
  428. createList: function(digit, options) {
  429. if(typeof digit === "object") {
  430. options = digit;
  431. digit = 0;
  432. }
  433. var obj = new FlipClock.List(this.factory, digit, options);
  434. //this.factory.$wrapper.append(obj.$obj);
  435. return obj;
  436. },
  437. /**
  438. * Triggers when the clock is reset
  439. */
  440. reset: function() {},
  441. /**
  442. * Sets the clock time
  443. */
  444. setTime: function(time) {
  445. this.flip(time);
  446. },
  447. /**
  448. * Sets the clock time
  449. */
  450. addDigit: function(digit) {
  451. var obj = this.createList(digit, {
  452. classes: {
  453. active: this.factory.classes.active,
  454. before: this.factory.classes.before,
  455. flip: this.factory.classes.flip
  456. }
  457. });
  458. obj.$obj.insertBefore(this.factory.lists[0].$obj);
  459. this.factory.lists.unshift(obj);
  460. },
  461. /**
  462. * Triggers when the clock is started
  463. */
  464. start: function() {},
  465. /**
  466. * Triggers when the time on the clock stops
  467. */
  468. stop: function() {},
  469. /**
  470. * Triggers when the numbers on the clock flip
  471. */
  472. flip: function(time, doNotAddPlayClass) {
  473. var t = this;
  474. if(!doNotAddPlayClass) {
  475. if(!t.factory.countdown) {
  476. t.factory.time.time++;
  477. }
  478. else {
  479. if(t.factory.time.time <= 0) {
  480. t.factory.stop();
  481. }
  482. t.factory.time.time--;
  483. }
  484. }
  485. var offset = t.factory.lists.length - time.length;
  486. if(offset < 0) {
  487. offset = 0;
  488. }
  489. var totalNew = 0;
  490. var reFlip = false;
  491. $.each(time, function(i, digit) {
  492. i += offset;
  493. var list = t.factory.lists[i];
  494. if(list) {
  495. var currentDigit = list.digit;
  496. list.select(digit);
  497. if(digit != currentDigit && !doNotAddPlayClass) {
  498. list.play();
  499. }
  500. }
  501. else {
  502. t.addDigit(digit);
  503. reFlip = true;
  504. }
  505. });
  506. for(var x = 0; x < time.length; x++) {
  507. if(x >= offset && t.factory.lists[x].digit != time[x]) {
  508. t.factory.lists[x].select(time[x]);
  509. }
  510. }
  511. }
  512. });
  513. /**
  514. * The FlipClock List class is used to build the list used to create
  515. * the card flip effect. This object fascilates selecting the correct
  516. * node by passing a specific digit.
  517. *
  518. * @param object A FlipClock.Factory object
  519. * @param mixed This is the digit used to set the clock. If an
  520. * object is passed, 0 will be used.
  521. * @param object An object of properties to override the default
  522. */
  523. FlipClock.List = FlipClock.Base.extend({
  524. /**
  525. * The digit (0-9)
  526. */
  527. digit: 0,
  528. /**
  529. * The CSS classes
  530. */
  531. classes: {
  532. active: 'flip-clock-active',
  533. before: 'flip-clock-before',
  534. flip: 'flip'
  535. },
  536. /**
  537. * The parent FlipClock.Factory object
  538. */
  539. factory: false,
  540. /**
  541. * The wrapping jQuery object
  542. */
  543. $obj: false,
  544. /**
  545. * The items in the list
  546. */
  547. items: [],
  548. /**
  549. * Constructor
  550. *
  551. * @param object A FlipClock.Factory object
  552. * @param int An integer use to select the correct digit
  553. * @param object An object to override the default properties
  554. */
  555. constructor: function(factory, digit, options) {
  556. this.factory = factory;
  557. this.digit = digit;
  558. this.$obj = this.createList();
  559. if(digit > 0) {
  560. this.select(digit);
  561. }
  562. this.factory.$wrapper.append(this.$obj);
  563. },
  564. /**
  565. * Select the digit in the list
  566. *
  567. * @param int A digit 0-9
  568. */
  569. select: function(digit) {
  570. if(typeof digit === "undefined") {
  571. digit = this.digit;
  572. }
  573. else {
  574. this.digit = digit;
  575. }
  576. var target = this.$obj.find('[data-digit="'+digit+'"]');
  577. var active = this.$obj.find('.'+this.classes.active).removeClass(this.classes.active);
  578. var before = this.$obj.find('.'+this.classes.before).removeClass(this.classes.before);
  579. if(!this.factory.countdown) {
  580. if(target.is(':first-child')) {
  581. this.$obj.find(':last-child').addClass(this.classes.before);
  582. }
  583. else {
  584. target.prev().addClass(this.classes.before);
  585. }
  586. }
  587. else {
  588. if(target.is(':last-child')) {
  589. this.$obj.find(':first-child').addClass(this.classes.before);
  590. }
  591. else {
  592. target.next().addClass(this.classes.before);
  593. }
  594. }
  595. target.addClass(this.classes.active);
  596. },
  597. /**
  598. * Adds the play class to the DOM object
  599. */
  600. play: function() {
  601. this.$obj.addClass(this.factory.classes.play);
  602. },
  603. /**
  604. * Removes the play class to the DOM object
  605. */
  606. stop: function() {
  607. var t = this;
  608. setTimeout(function() {
  609. t.$obj.removeClass(t.factory.classes.play);
  610. }, this.factory.timer.interval);
  611. },
  612. /**
  613. * Create the list of digits and appends it to the DOM object
  614. */
  615. createList: function() {
  616. var html = $('<ul class="'+this.classes.flip+' '+(this.factory.running ? this.factory.classes.play : '')+'" />');
  617. for(var x = 0; x < 10; x++) {
  618. var item = $([
  619. '<li data-digit="'+x+'">',
  620. '<a href="#">',
  621. '<div class="up">',
  622. '<div class="shadow"></div>',
  623. '<div class="inn">'+x+'</div>',
  624. '</div>',
  625. '<div class="down">',
  626. '<div class="shadow"></div>',
  627. '<div class="inn">'+x+'</div>',
  628. '</div>',
  629. '</a>',
  630. '</li>'].join(''));
  631. this.items.push(item);
  632. html.append(item);
  633. }
  634. return html;
  635. }
  636. });
  637. /**
  638. * The FlipClock Time class is used to manage all the time
  639. * calculations.
  640. *
  641. * @param object A FlipClock.Factory object
  642. * @param mixed This is the digit used to set the clock. If an
  643. * object is passed, 0 will be used.
  644. * @param object An object of properties to override the default
  645. */
  646. FlipClock.Time = FlipClock.Base.extend({
  647. /**
  648. * The time (in seconds)
  649. */
  650. minimumDigits: 0,
  651. /**
  652. * The time (in seconds)
  653. */
  654. time: 0,
  655. /**
  656. * The parent FlipClock.Factory object
  657. */
  658. factory: false,
  659. /**
  660. * Constructor
  661. *
  662. * @param object A FlipClock.Factory object
  663. * @param int An integer use to select the correct digit
  664. * @param object An object to override the default properties
  665. */
  666. constructor: function(factory, time, options) {
  667. this.base(options);
  668. this.factory = factory;
  669. if(time) {
  670. this.time = time;
  671. }
  672. },
  673. /**
  674. * Convert a string or integer to an array of digits
  675. *
  676. * @param mixed String or Integer of digits
  677. * @return array An array of digits
  678. */
  679. convertDigitsToArray: function(str) {
  680. var data = [];
  681. str = str.toString();
  682. for(var x = 0;x < str.length; x++) {
  683. if(str[x].match(/^\d*$/g)) {
  684. data.push(str[x]);
  685. }
  686. }
  687. return data;
  688. },
  689. /**
  690. * Get a specific digit from the time integer
  691. *
  692. * @param int The specific digit to select from the time
  693. * @return mixed Returns FALSE if no digit is found, otherwise
  694. * the method returns the defined digit
  695. */
  696. digit: function(i) {
  697. var timeStr = this.toString();
  698. var length = timeStr.length;
  699. if(timeStr[length - i]) {
  700. return timeStr[length - i];
  701. }
  702. return false;
  703. },
  704. /**
  705. * Formats any array of digits into a valid array of digits
  706. *
  707. * @param mixed An array of digits
  708. * @return array An array of digits
  709. */
  710. digitize: function(obj) {
  711. var data = [];
  712. $.each(obj, function(i, value) {
  713. value = value.toString();
  714. if(value.length == 1) {
  715. value = '0'+value;
  716. }
  717. for(var x = 0; x < value.length; x++) {
  718. data.push(value.charAt(x));
  719. }
  720. });
  721. if(data.length > this.minimumDigits) {
  722. this.minimumDigits = data.length;
  723. }
  724. if(this.minimumDigits > data.length) {
  725. data.unshift('0');
  726. }
  727. return data;
  728. },
  729. /**
  730. * Gets a daily breakdown
  731. *
  732. * @return object Returns a digitized object
  733. */
  734. getDayCounter: function(includeSeconds) {
  735. var digits = [
  736. this.getDays(),
  737. this.getHours(true),
  738. this.getMinutes(true)
  739. ];
  740. if(includeSeconds) {
  741. digits.push(this.getSeconds(true));
  742. }
  743. return this.digitize(digits);
  744. },
  745. /**
  746. * Gets number of days
  747. *
  748. * @param bool Should perform a modulus? If not sent, then no.
  749. * @return int Retuns a floored integer
  750. */
  751. getDays: function(mod) {
  752. var days = this.time / 60 / 60 / 24;
  753. if(mod) {
  754. days = days % 7;
  755. }
  756. return Math.floor(days);
  757. },
  758. /**
  759. * Gets an hourly breakdown
  760. *
  761. * @return object Returns a digitized object
  762. */
  763. getHourCounter: function() {
  764. var obj = this.digitize([
  765. this.getHours(),
  766. this.getMinutes(true),
  767. this.getSeconds(true)
  768. ]);
  769. return obj;
  770. },
  771. /**
  772. * Gets an hourly breakdown
  773. *
  774. * @return object Returns a digitized object
  775. */
  776. getHourly: function() {
  777. return this.getHourCounter();
  778. },
  779. /**
  780. * Gets number of hours
  781. *
  782. * @param bool Should perform a modulus? If not sent, then no.
  783. * @return int Retuns a floored integer
  784. */
  785. getHours: function(mod) {
  786. var hours = this.time / 60 / 60;
  787. if(mod) {
  788. hours = hours % 24;
  789. }
  790. return Math.floor(hours);
  791. },
  792. /**
  793. * Gets the twenty-four hour time
  794. *
  795. * @return object returns a digitized object
  796. */
  797. getMilitaryTime: function() {
  798. var date = new Date();
  799. var obj = this.digitize([
  800. date.getHours(),
  801. date.getMinutes(),
  802. date.getSeconds()
  803. ]);
  804. return obj;
  805. },
  806. /**
  807. * Gets number of minutes
  808. *
  809. * @param bool Should perform a modulus? If not sent, then no.
  810. * @return int Retuns a floored integer
  811. */
  812. getMinutes: function(mod) {
  813. var minutes = this.time / 60;
  814. if(mod) {
  815. minutes = minutes % 60;
  816. }
  817. return Math.floor(minutes);
  818. },
  819. /**
  820. * Gets a minute breakdown
  821. */
  822. getMinuteCounter: function() {
  823. var obj = this.digitize([
  824. this.getMinutes(),
  825. this.getSeconds(true)
  826. ]);
  827. return obj;
  828. },
  829. /**
  830. * Gets number of seconds
  831. *
  832. * @param bool Should perform a modulus? If not sent, then no.
  833. * @return int Retuns a ceiled integer
  834. */
  835. getSeconds: function(mod) {
  836. var seconds = this.time;
  837. if(mod) {
  838. if(seconds == 60) {
  839. seconds = 0;
  840. }
  841. else {
  842. seconds = seconds % 60;
  843. }
  844. }
  845. return Math.ceil(seconds);
  846. },
  847. /**
  848. * Gets the current twelve hour time
  849. *
  850. * @return object Returns a digitized object
  851. */
  852. getTime: function() {
  853. var date = new Date();
  854. var hours = date.getHours();
  855. var merid = hours > 12 ? 'PM' : 'AM';
  856. var obj = this.digitize([
  857. hours > 12 ? hours - 12 : (hours === 0 ? 12 : hours),
  858. date.getMinutes(),
  859. date.getSeconds()
  860. ]);
  861. return obj;
  862. },
  863. /**
  864. * Gets number of weeks
  865. *
  866. * @param bool Should perform a modulus? If not sent, then no.
  867. * @return int Retuns a floored integer
  868. */
  869. getWeeks: function() {
  870. var weeks = this.time / 60 / 60 / 24 / 7;
  871. if(mod) {
  872. weeks = weeks % 52;
  873. }
  874. return Math.floor(weeks);
  875. },
  876. /**
  877. * Removes a specific number of leading zeros from the array.
  878. * This method prevents you from removing too many digits, even
  879. * if you try.
  880. *
  881. * @param int Total number of digits to remove
  882. * @return array An array of digits
  883. */
  884. removeLeadingZeros: function(totalDigits, digits) {
  885. var total = 0;
  886. var newArray = [];
  887. $.each(digits, function(i, digit) {
  888. if(i < totalDigits) {
  889. total += parseInt(digits[i], 10);
  890. }
  891. else {
  892. newArray.push(digits[i]);
  893. }
  894. });
  895. if(total === 0) {
  896. return newArray;
  897. }
  898. return digits;
  899. },
  900. /**
  901. * Converts the object to a human readable string
  902. */
  903. toString: function() {
  904. return this.time.toString();
  905. }
  906. /*
  907. getYears: function() {
  908. return Math.floor(this.time / 60 / 60 / 24 / 7 / 52);
  909. },
  910. getDecades: function() {
  911. return Math.floor(this.getWeeks() / 10);
  912. }*/
  913. });
  914. /**
  915. * The FlipClock.Timer object managers the JS timers
  916. *
  917. * @param object The parent FlipClock.Factory object
  918. * @param object Override the default options
  919. */
  920. FlipClock.Timer = FlipClock.Base.extend({
  921. /**
  922. * Callbacks
  923. */
  924. callbacks: {
  925. destroy: false,
  926. create: false,
  927. init: false,
  928. interval: false,
  929. start: false,
  930. stop: false,
  931. reset: false
  932. },
  933. /**
  934. * FlipClock timer count (how many intervals have passed)
  935. */
  936. count: 0,
  937. /**
  938. * The parent FlipClock.Factory object
  939. */
  940. factory: false,
  941. /**
  942. * Timer interval (1 second by default)
  943. */
  944. interval: 1000,
  945. /**
  946. * Constructor
  947. *
  948. * @return void
  949. */
  950. constructor: function(factory, options) {
  951. this.base(options);
  952. this.factory = factory;
  953. this.callback(this.callbacks.init);
  954. this.callback(this.callbacks.create);
  955. },
  956. /**
  957. * This method gets the elapsed the time as an interger
  958. *
  959. * @return void
  960. */
  961. getElapsed: function() {
  962. return this.count * this.interval;
  963. },
  964. /**
  965. * This method gets the elapsed the time as a Date object
  966. *
  967. * @return void
  968. */
  969. getElapsedTime: function() {
  970. return new Date(this.time + this.getElapsed());
  971. },
  972. /**
  973. * This method is resets the timer
  974. *
  975. * @param callback This method resets the timer back to 0
  976. * @return void
  977. */
  978. reset: function(callback) {
  979. clearInterval(this.timer);
  980. this.count = 0;
  981. this._setInterval(callback);
  982. this.callback(this.callbacks.reset);
  983. },
  984. /**
  985. * This method is starts the timer
  986. *
  987. * @param callback A function that is called once the timer is destroyed
  988. * @return void
  989. */
  990. start: function(callback) {
  991. this.factory.running = true;
  992. this._createTimer(callback);
  993. this.callback(this.callbacks.start);
  994. },
  995. /**
  996. * This method is stops the timer
  997. *
  998. * @param callback A function that is called once the timer is destroyed
  999. * @return void
  1000. */
  1001. stop: function(callback) {
  1002. this.factory.running = false;
  1003. this._clearInterval(callback);
  1004. this.callback(this.callbacks.stop);
  1005. this.callback(callback);
  1006. },
  1007. /**
  1008. * Clear the timer interval
  1009. *
  1010. * @return void
  1011. */
  1012. _clearInterval: function() {
  1013. clearInterval(this.timer);
  1014. },
  1015. /**
  1016. * Create the timer object
  1017. *
  1018. * @param callback A function that is called once the timer is created
  1019. * @return void
  1020. */
  1021. _createTimer: function(callback) {
  1022. this._setInterval(callback);
  1023. },
  1024. /**
  1025. * Destroy the timer object
  1026. *
  1027. * @param callback A function that is called once the timer is destroyed
  1028. * @return void
  1029. */
  1030. _destroyTimer: function(callback) {
  1031. this._clearInterval();
  1032. this.timer = false;
  1033. this.callback(callback);
  1034. this.callback(this.callbacks.destroy);
  1035. },
  1036. /**
  1037. * This method is called each time the timer interval is ran
  1038. *
  1039. * @param callback A function that is called once the timer is destroyed
  1040. * @return void
  1041. */
  1042. _interval: function(callback) {
  1043. this.callback(this.callbacks.interval);
  1044. this.callback(callback);
  1045. this.count++;
  1046. },
  1047. /**
  1048. * This sets the timer interval
  1049. *
  1050. * @param callback A function that is called once the timer is destroyed
  1051. * @return void
  1052. */
  1053. _setInterval: function(callback) {
  1054. var t = this;
  1055. t.timer = setInterval(function() {
  1056. t._interval(callback);
  1057. }, this.interval);
  1058. }
  1059. });
  1060. /**
  1061. * Capitalize the first letter in a string
  1062. *
  1063. * @return string
  1064. */
  1065. String.prototype.ucfirst = function() {
  1066. return this.substr(0, 1).toUpperCase() + this.substr(1);
  1067. };
  1068. /**
  1069. * jQuery helper method
  1070. *
  1071. * @param int An integer used to start the clock (no. seconds)
  1072. * @param object An object of properties to override the default
  1073. */
  1074. $.fn.FlipClock = function(digit, options) {
  1075. if(typeof digit == "object") {
  1076. options = digit;
  1077. digit = 0;
  1078. }
  1079. return new FlipClock($(this), digit, options);
  1080. };
  1081. /**
  1082. * jQuery helper method
  1083. *
  1084. * @param int An integer used to start the clock (no. seconds)
  1085. * @param object An object of properties to override the default
  1086. */
  1087. $.fn.flipClock = function(digit, options) {
  1088. return $.fn.FlipClock(digit, options);
  1089. };
  1090. }(jQuery));