/********************************** * jCounter Script v0.1.4 (beta) * Author: Catalin Berta * Official page and documentation: http://devingredients.com/jcounter * Licensed under the MIT license **********************************/ ;(function($,document,window,undefined) { //once upon a time... $.fn.jCounter = function(options,callback) { var jCounterDirection = 'down'; // points out whether it should count down or up | handled via customRange setting var customRangeDownCount; //if true, it will tell countdown_proc() it's a down count and not an up count var days,hours,minutes,seconds; var endCounter = false; //stops jCounter if true var eventDate; //time target (holds a number of seconds) var pausedTime; //stores the time (in seconds) when pausing var thisEl = this; //custom 'this' selector var thisLength = this.length; //number of multiple elements per selector var pluralLabels = new Array('DAYS','HOURS','MINUTES','SECONDS'); //plural labels - used for localization var singularLabels = new Array('DAY','HOUR','MINUTE','SECOND'); //singular labels - used for localization this.options = options; //stores jCounter's options parameter to verify against specified methods this.version = '0.1.4'; //default settings var settings = { animation: null, callback: null, customDuration: null, customRange: null, date: null, debugLog: false, serverDateSource: 'dateandtime.php', //path to dateandtime.php file (i.e. http://my-domain.com/dateandtime.php) format: 'dd:hh:mm:ss', timezone: 'Europe/London', twoDigits: 'on' }; //merge the settings with the options values if (typeof options === 'object') { $.extend(settings,options); thisEl.data("userOptions", settings); //push the settings to applied elements (they're used by methods) } if(thisEl.data('userOptions').debugLog == true && window['console'] !== undefined ) { var consoleLog = true; //shows debug messages via console.log() if true } //METHODS var jC_methods = { //initialize init : function() { thisEl.each(function(i,el) { initCounter(el); }); }, //pause method: $.jCounter('pause') pause : function() { if(consoleLog) { console.log("(jC) Activity: Counter paused."); } endCounter = true; return thisEl.each(function(i,el) { clearInterval($(el).data("jC_interval")); }); }, //stop method: $.jCounter('stop') stop : function() { if(consoleLog) { console.log("(jC) Activity: Counter stopped."); } endCounter = true; return thisEl.each(function(i,el) { clearInterval($(el).data("jC_interval")); $(el).removeData("jC_pausedTime"); resetHTMLCounter(el); }); }, //reset method: $.jCounter('reset') reset : function() { if(consoleLog) { console.log("(jC) Activity: Counter reset."); } return thisEl.each(function(i,el) { clearInterval($(el).data("jC_interval")); resetHTMLCounter(el); initCounter(el); }); }, //start method: $.jCounter('start') start : function() { if(consoleLog) { console.log("(jC) Activity: Counter started."); } return thisEl.each(function(i,el) { pausedTime = $(el).data("jC_pausedTime"); endCounter = false; clearInterval($(el).data("jC_interval")); initCounter(el); }); } } //checks whether customDuration is used if(thisEl.data("userOptions").customDuration) { if(!isNaN(thisEl.data("userOptions").customDuration)) { var customDuration = true; } else { var customDuration = false; if(consoleLog) { console.log("(jC) Error: The customDuration value is not a number! NOTE: 'customDuration' accepts a number of seconds."); } } } //checks whether customRange is used if(thisEl.data("userOptions").customRange) { var customRangeValues = thisEl.data("userOptions").customRange.split(":"); var rangeVal0 = parseInt(customRangeValues[0]); var rangeVal1 = parseInt(customRangeValues[1]); if(!isNaN(rangeVal0) && !isNaN(rangeVal1)) { var customRange = true; if(rangeVal0 > rangeVal1) { var customRangeDownCount = true; } else { var customRangeDownCount = false; jCounterDirection = 'up'; } } else { var customRange = false; if(consoleLog) { console.log("(jC) Error: The customRange value is not a valid range! Example: customRange: '0:30' or '30:0'"); } } } //checks whether animation is set to slide if(thisEl.data("userOptions").animation == 'slide') { thisEl.data("jCanimation","slide"); } //FUNCTIONS //jCounter initializer function initCounter(el) { if(customDuration) { if (pausedTime) { if (!isNaN(pausedTime)) { eventDate = Math.round(pausedTime); } } else { eventDate = Math.round($(el).data("userOptions").customDuration); } currentTime = 0; countdown_proc(currentTime,el); $(el).data("jC_interval", setInterval(function(){ if(endCounter == false) { currentTime = parseInt(currentTime) + 1; countdown_proc(currentTime,el) } },1000)); } else if(customRange) { eventDate = Math.round(customRangeValues[1]); if (pausedTime) { if (!isNaN(pausedTime)) { var currentTime = eventDate - pausedTime; } } else { var currentTime = Math.round(customRangeValues[0]); } countdown_proc(currentTime,el); $(el).data("jC_interval", setInterval(function(){ if(endCounter == false) { var ifRangeDownCount = (customRangeDownCount) ? currentTime = parseInt(currentTime) - 1 : currentTime = parseInt(currentTime) + 1; countdown_proc(currentTime,el); } },1000)); } else { eventDate = Date.parse($(el).data("userOptions").date) / 1000; dateSource = thisEl.data("userOptions").serverDateSource + '?timezone=' + thisEl.data("userOptions").timezone + '&callback=?'; $.ajax({ url: dateSource, dataType : 'json', data : {}, success : function(data, textStatus){ var currentDate = Date.parse(data.currentDate) / 1000; startCounter(currentDate,el); }, error : function(){ if(consoleLog) { console.log("(jC) Error: Couldn't find dateandtime.php from serverDateSource: " + thisEl.data('userOptions').serverDateSource + "\n(jC) - Make sure the path is correct! \n(jC) - Now using the client-side time (not recommended).") } var currentDate = Math.floor($.now() / 1000); startCounter(currentDate,el); } }); } } function startCounter(currentDate,el) { countdown_proc(currentDate,el); if (eventDate > currentDate) { $(el).data("jC_interval", setInterval(function(){ if(endCounter == false) { currentDate = parseInt(currentDate) + 1; countdown_proc(currentDate,el) } },1000)); } else { resetHTMLCounter(el) } } //jCslider - adds the slide effect layer //Note: this requires a jCounter slide-ready theme! (i.e. iOS dark or iOS light) function jCslider(el,unitClass,timeUnit,eventDate,duration) { $(el).find(unitClass + " u").each(function(i,el) { var twoDigits = (thisEl.data("userOptions").twoDigits == 'on') ? '0' : ''; var newIndex = (jCounterDirection == 'up') ? newIndex = -i : newIndex = i; currNo = parseInt(timeUnit,10) + (newIndex); if (String(parseInt(timeUnit,10)).length >= 2) { $(el).text(parseInt(timeUnit,10) + (newIndex)) } else if(String(parseInt(timeUnit,10)).length == 1 && currNo == 10) { $(el).text(parseInt(timeUnit,10) + (newIndex)) } else { $(el).text(twoDigits + (parseInt(timeUnit,10) + (newIndex))); } }) $(el).find(unitClass).animate({ top: '0.15em' },200, function() { $(el).find(unitClass + " u:eq(1)").remove(); $(el).find(unitClass).prepend(''); $(el).find(unitClass).css({'top':'-1.24em'}) }); } //resets jCounter's HTML values to 0 or 00, based on the twoDigits setting function resetHTMLCounter(el) { if(thisEl.data("userOptions").twoDigits == 'on') { $(el).find(".days,.hours,.minutes,.seconds").text('00'); } else if(thisEl.data("userOptions").twoDigits == 'off') { $(el).find(".days,.hours,.minutes,.seconds").text('0'); } if(thisEl.data("jCanimation") == 'slide') { $(el).find(".daysSlider u,.hoursSlider u,.minutesSlider u,.secondsSlider u").text('00'); } } //main jCounter processor function countdown_proc(duration,el) { //check if the counter needs to count down or up if(customRangeDownCount) { if(eventDate >= duration) { clearInterval($(el).data("jC_interval")); if(thisEl.data("userOptions").callback) { thisEl.data("userOptions").callback.call(this); } } } else { if(eventDate <= duration) { clearInterval($(el).data("jC_interval")); if(thisEl.data("userOptions").callback) { thisEl.data("userOptions").callback.call(this); } } } //if customRange is used, update the seconds variable var seconds = (customRange) ? duration : eventDate - duration; var thisInstanceFormat = thisEl.data("userOptions").format; //calculate seconds into days,hours,minutes,seconds //if dd (days) is specified in the format setting (i.e. format: 'dd:hh:mm:ss') if(thisInstanceFormat.indexOf('dd') != -1) { var days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed } //if hh (hours) is specified if(thisInstanceFormat.indexOf('hh') != -1) { var hours = Math.floor(seconds / (60 * 60)); seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed } //if mm (minutes) is specified if(thisInstanceFormat.indexOf('mm') != -1) { var minutes = Math.floor(seconds / 60); seconds -= minutes * 60; //update the seconds variable with no. of minutes removed } //if ss (seconds) is specified if(thisInstanceFormat.indexOf('ss') == -1) { seconds -= seconds; //if ss is unspecified in format, update the seconds variable to 0; } //conditional Ss //updates the plural and singular labels accordingly if (days == 1) { $(el).find(".textDays").text(singularLabels[0]); } else { $(el).find(".textDays").text(pluralLabels[0]); } if (hours == 1) { $(el).find(".textHours").text(singularLabels[1]); } else { $(el).find(".textHours").text(pluralLabels[1]); } if (minutes == 1) { $(el).find(".textMinutes").text(singularLabels[2]); } else { $(el).find(".textMinutes").text(pluralLabels[2]); } if (seconds == 1) { $(el).find(".textSeconds").text(singularLabels[3]); } else { $(el).find(".textSeconds").text(pluralLabels[3]); } //twoDigits ON setting //if the twoDigits setting is set to ON, jCounter will always diplay a minimum number of 2 digits if(thisEl.data("userOptions").twoDigits == 'on') { days = (String(days).length >= 2) ? days : "0" + days; hours = (String(hours).length >= 2) ? hours : "0" + hours; minutes = (String(minutes).length >= 2) ? minutes : "0" + minutes; seconds = (String(seconds).length >= 2) ? seconds : "0" + seconds; } //updates the jCounter's html values if(!isNaN(eventDate)) { $(el).find(".days").text(days); $(el).find(".hours").text(hours); $(el).find(".minutes").text(minutes); $(el).find(".seconds").text(seconds); if(thisEl.data("jCanimation") == 'slide') { $(el).find(".daysSlider u:eq(1)").text(days); $(el).find(".hoursSlider u:eq(1)").text(hours); $(el).find(".minutesSlider u:eq(1)").text(minutes); $(el).find(".secondsSlider u:eq(1)").text(seconds); jCslider(el,'.secondsSlider',seconds,eventDate,duration); if(parseInt(seconds,10) == 59) { jCslider(el,'.minutesSlider',minutes,eventDate,duration) if(parseInt(minutes,10) == 59) { jCslider(el,'.hoursSlider',hours,eventDate,duration) if(parseInt(hours,10) == 23) { jCslider(el,'.daysSlider',days,eventDate,duration) } } } } } else { if(consoleLog) { console.log("(jC) Error: Invalid date! Here's an example: 01 January 1970 12:00:00"); } clearInterval($(el).data("jC_interval")); } //stores the remaining time when pausing jCounter $(el).data("jC_pausedTime", eventDate-duration); } //method calling logic if ( jC_methods[this.options] ) { return jC_methods[ this.options ].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof this.options === 'object' || ! this.options ) { return jC_methods.init.apply( this, arguments ); } else { console.log('(jC) Error: Method >>> ' + this.options + ' <<< does not exist.' ); } } //the end; }) (jQuery,document,window);