﻿/* 
* jCountdown 1.3.1 jQuery Plugin
* Copyright 2011 Tom Ellis http://www.webmuse.co.uk
* MIT Licensed (license.txt)
*/
(function ($j) {

    $j.fn.countdown = function (method /*, options*/) {

        var defaults = {
            date: new Date(),
            updateTime: 1E3,
            htmlTemplate: "<div style=\"float: left; margin-right: 12px; width: 51px; font-size: 40px; font-family: Impact;  text-align: center;\">%{h}</div><div style=\"float: left; margin-right: 12px; width: 51px; font-size: 40px; font-family: Impact; text-align: center; \">%{m}</div><div style=\"float: left; width: 51px; font-size: 40px; font-family: Impact; text-align: left; padding-left: 3px; \">%{s}</div>",
            minus: false,
            onChange: null,
            onComplete: null,
            onResume: null,
            onPause: null,
            leadingZero: false,
            offset: null,
            hoursOnly: false, //New in 1.3.1
            direction: "down"
        },
		slice = [].slice,
		floor = Math.floor,
		msPerHr = 36E5,
		msPerDay = 864E5,
		rDate = /(%\{d\}|%\{h\}|%\{m\}|%\{s\})/g,
		rDays = /%\{d\}/,
		rHrs = /%\{h\}/,
		rMins = /%\{m\}/,
		rSecs = /%\{s\}/,
		getTZDate = function (offset) {
		    //Returns a new date based on an offset (set in options as "offset")
		    //Useful when you want to match a server time, not a local PC time
		    var hrs = offset || 0,
				curHrs = 0,
				tmpDate = new Date(),
				dateMS;

		    hrs *= msPerHr;
		    curHrs = tmpDate.getTime() - ((-tmpDate.getTimezoneOffset() / 60) * msPerHr);
		    dateMS = tmpDate.setTime(curHrs + hrs);
		    tmpDate = null;
		    return new Date(dateMS);
		},
		timerFunc = function () {
		    //Function runs at set interval updating countdown
		    var $this = this,
				template,
				now,
				date,
				timeLeft,
				eDaysLeft,
				daysLeft,
				eHrsLeft,
				hrsLeft,
				minsLeft,
				eMinsleft,
				secLeft,
				time = "",
				settings = $this.data("jcdData");

		    if (!settings) {
		        return false;
		    }

		    template = settings.htmlTemplate;

		    now = (settings.offset === null) ? new Date() : getTZDate(settings.offset);
		    date = new Date(settings.date);

		    timeLeft = (settings.direction === "down") ? date.getTime() - now.getTime() :
				now.getTime() - date.getTime();
		    eDaysLeft = timeLeft / msPerDay;
		    daysLeft = floor(eDaysLeft);
		    eHrsLeft = (eDaysLeft - daysLeft) * 24;
		    hrsLeft = floor(eHrsLeft);
		    minsLeft = floor((eHrsLeft - hrsLeft) * 60);
		    eMinsleft = (eHrsLeft - hrsLeft) * 60;
		    secLeft = floor((eMinsleft - minsLeft) * 60);

		    if (settings.hoursOnly) {
		        hrsLeft += daysLeft * 24;
		        daysLeft = 0;
		    }

		    if (settings.leadingZero) {
		        if (daysLeft < 10 && !settings.hoursOnly) {
		            daysLeft = "0" + daysLeft;
		        }
		        if (hrsLeft < 10) {
		            hrsLeft = "0" + hrsLeft;
		        }
		        if (minsLeft < 10) {
		            minsLeft = "0" + minsLeft;
		        }
		        if (secLeft < 10) {
		            secLeft = "0" + secLeft;
		        }
		    }

		    if (settings.direction === "down" && (now <= date || settings.minus)) {
		        time = template.replace(rDays, daysLeft)
							   .replace(rHrs, hrsLeft)
							   .replace(rMins, minsLeft)
							   .replace(rSecs, secLeft);
		    } else if (settings.direction === "up" && (date <= now || settings.minus)) {
		        time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		    } else {
		        time = template.replace(rDate, "00");
		        settings.hasCompleted = true;
		    }

		    $this.html(time).trigger("change.jcdevt", [settings]);

		    if (settings.hasCompleted) {
		        $this.trigger("complete.jcdevt");
		        clearInterval(settings.timer);
		    }
		},
		methods = {
		    init: function (options) {

		        var opts = $j.extend({}, defaults, options),
					template;

		        template = opts.htmlTemplate;

		        return this.each(function () {
		            var $this = $j(this),
						settings = {},
						now = (opts.offset === null) ? new Date() : getTZDate(opts.offset),
						date = new Date(opts.date),
						timeLeft = (opts.direction === "down") ? date.getTime() - now.getTime() :
							now.getTime() - date.getTime(),
						eDaysLeft = timeLeft / msPerDay,
						daysLeft = floor(eDaysLeft),
						eHrsLeft = (eDaysLeft - daysLeft) * 24, //Gets remainder and * 24
						hrsLeft = floor(eHrsLeft),
						minsLeft = floor((eHrsLeft - hrsLeft) * 60),
						eMinsleft = (eHrsLeft - hrsLeft) * 60, //Gets remainder and * 60
						secLeft = floor((eMinsleft - minsLeft) * 60),
						time = "",
						func;

		            if (opts.hoursOnly) {
		                hrsLeft += daysLeft * 24;
		                daysLeft = 0;
		            }
		            //If this element already has a countdown timer, just change the settings
		            if ($this.data("jcdData")) {
		                $this.countdown("changeSettings", options);
		                return true;
		            }

		            //Add event handlers where set
		            if (opts.onChange) {
		                $this.bind("change.jcdevt", opts.onChange);
		            }

		            if (opts.onComplete) {
		                $this.bind("complete.jcdevt", opts.onComplete);
		            }

		            if (opts.onPause) {
		                $this.bind("pause.jcdevt", opts.onPause);
		            }

		            if (opts.onResume) {
		                $this.bind("resume.jcdevt", opts.onResume);
		            }

		            if (opts.leadingZero) {

		                if (daysLeft < 10 && !opts.hoursOnly) {
		                    daysLeft = "0" + daysLeft;
		                }

		                if (hrsLeft < 10) {
		                    hrsLeft = "0" + hrsLeft;
		                }

		                if (minsLeft < 10) {
		                    minsLeft = "0" + minsLeft;
		                }

		                if (secLeft < 10) {
		                    secLeft = "0" + secLeft;
		                }
		            }

		            settings = {
		                originalContent: $this.html(),
		                date: opts.date,
		                hoursOnly: opts.hoursOnly,
		                leadingZero: opts.leadingZero,
		                updateTime: opts.updateTime,
		                direction: opts.direction,
		                template: opts.htmlTemplate,
		                htmlTemplate: opts.htmlTemplate,
		                minus: opts.minus,
		                offset: opts.offset,
		                onChange: opts.onChange,
		                onComplete: opts.onComplete,
		                onResume: opts.onResume,
		                onPause: opts.onPause,
		                hasCompleted: false,
		                timer: 0
		            };

		            //Set initial time
		            if (opts.direction === "down" && (now <= date || opts.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else if (opts.direction === "up" && (date <= now || opts.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else {
		                time = template.replace(rDate, "00");
		                settings.hasCompleted = true;
		            }

		            //If a countdown has completed before its even started we don"t
		            //need to set an interval
		            if (!settings.hasCompleted) {
		                func = $j.proxy(timerFunc, $this);
		                settings.timer = setInterval(func, settings.updateTime);
		            }

		            $this.data("jcdData", settings).html(time);

		            //Store settings so they can be accessed later
		            if (settings.hasCompleted) {
		                $this.trigger("complete.jcdevt");
		                clearInterval(settings.timer);
		            }

		        });

		    },
		    changeSettings: function (options) {

		        //Like resume but with resetting/changing options
		        return this.each(function () {
		            var $this = $j(this),
						settings,
						template,
						now,
						date,
						timeLeft,
						eDaysLeft,
						daysLeft,
						eHrsLeft,
						hrsLeft,
						minsLeft,
						eMinsleft,
						secLeft,
						time = "",
						func;

		            if (!$this.data("jcdData")) {
		                return true;
		            }

		            settings = $j.extend({}, $this.data("jcdData"), options);
		            template = settings.htmlTemplate;

		            now = (settings.offset === null) ? new Date() : getTZDate(settings.offset);
		            date = new Date(settings.date);
		            timeLeft = (settings.direction === "down") ? date.getTime() - now.getTime() :
						now.getTime() - date.getTime();
		            eDaysLeft = timeLeft / msPerDay;
		            daysLeft = floor(eDaysLeft);
		            eHrsLeft = (eDaysLeft - daysLeft) * 24; //Gets remainder and * 24
		            hrsLeft = floor(eHrsLeft);
		            minsLeft = floor((eHrsLeft - hrsLeft) * 60);
		            eMinsleft = (eHrsLeft - hrsLeft) * 60; //Gets remainder and * 60
		            secLeft = floor((eMinsleft - minsLeft) * 60);

		            if (settings.hoursOnly) {
		                hrsLeft += daysLeft * 24;
		                daysLeft = 0;
		            }

		            //Remove all bound events as they will be set later
		            $this.unbind(".jcdevt");
		            //Clear the timer, as it might not be needed
		            clearInterval(settings.timer);

		            if (settings.onChange) {
		                $this.bind("change.jcdevt", settings.onChange);
		            }

		            if (settings.onComplete) {
		                $this.bind("complete.jcdevt", settings.onComplete);
		            }

		            if (settings.onPause) {
		                $this.bind("pause.jcdevt", settings.onPause);
		            }

		            if (settings.onResume) {
		                $this.bind("resume.jcdevt", settings.onResume);
		            }

		            if (settings.direction === "down" && (now <= date || settings.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else if (settings.direction === "up" && (date <= now || settings.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else {
		                time = template.replace(rDate, "00");
		                settings.hasCompleted = true;
		            }

		            func = $j.proxy(timerFunc, $this);

		            settings.timer = setInterval(func, settings.updateTime);

		            $this.data("jcdData", settings);
		            func(); //Needs to run straight away when changing settings
		            if (settings.hasCompleted) {
		                $this.trigger("complete.jcdevt");
		                clearInterval(settings.timer);
		            }
		        });
		    },
		    resume: function () {
		        //Resumes a countdown timer
		        return this.each(function () {
		            var $this = $j(this),
						settings,
						template,
						func,
						now,
						date,
						timeLeft,
						eDaysLeft,
						daysLeft,
						eHrsLeft,
						hrsLeft,
						minsLeft,
						eMinsleft,
						secLeft,
						time = "";

		            settings = $this.data("jcdData");

		            if (!settings) {
		                return true;
		            }

		            func = $j.proxy(timerFunc, $this);

		            template = settings.htmlTemplate;
		            now = (settings.offset === null) ? new Date() : getTZDate(settings.offset);
		            date = new Date(settings.date);
		            timeLeft = (settings.direction === "down") ? date.getTime() - now.getTime() :
						now.getTime() - date.getTime();
		            eDaysLeft = timeLeft / msPerDay;
		            daysLeft = floor(eDaysLeft);
		            eHrsLeft = (eDaysLeft - daysLeft) * 24;
		            hrsLeft = floor(eHrsLeft);
		            minsLeft = floor((eHrsLeft - hrsLeft) * 60);
		            eMinsleft = (eHrsLeft - hrsLeft) * 60;
		            secLeft = floor((eMinsleft - minsLeft) * 60);

		            if (settings.hoursOnly) {
		                hrsLeft += daysLeft * 24;
		                daysLeft = 0;
		            }

		            if (settings.direction === "down" && (now <= date || settings.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else if (settings.direction === "up" && (date <= now || settings.minus)) {
		                time = template.replace(rDays, daysLeft).replace(rHrs, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
		            } else {
		                time = template.replace(rDate, "00");
		                settings.hasCompleted = true;
		            }

		            settings.timer = setInterval(func, settings.updateTime);

		            $this.data("jcdData", settings).trigger("resume.jcdevt").html(time).trigger("change.jcdevt");

		            if (settings.hasCompleted) {
		                $this.trigger("complete.jcdevt");
		                clearInterval(settings.timer);
		            }
		        });
		    },
		    pause: function () {
		        //Pause a countdown timer			
		        return this.each(function () {
		            var $this = $j(this),
						settings = $this.data("jcdData");

		            if (!settings) {
		                return true;
		            }
		            //Clear interval (Will be started on resume)
		            clearInterval(settings.timer);
		            //Trigger pause event handler
		            $this.trigger("pause.jcdevt");

		        });
		    },
		    complete: function () {
		        return this.each(function () {
		            var $this = $j(this),
						settings = $this.data("jcdData");

		            if (!settings) {
		                return true;
		            }
		            //Clear timer
		            clearInterval(settings.timer);
		            settings.hasCompleted = true;
		            //Update setting, trigger complete event handler, then unbind all events
		            //We don"t delete the settings in case they need to be checked later on
		            $this.data("jcdData", settings).trigger("complete.jcdevt").unbind(".jcdevt");
		        });
		    },
		    destroy: function () {
		        return this.each(function () {
		            var $this = $j(this),
						settings;

		            settings = $this.data("jcdData");

		            if (!settings) {
		                return true;
		            }
		            //Clear timer
		            clearInterval(settings.timer);
		            //Unbind all events, remove data and put DOM Element back to its original state (HMTL wise)
		            $this.unbind(".jcdevt").removeData("jcdData").html(settings.originalContent);
		        });
		    },
		    getSettings: function (name) {
		        var $this = $j(this),
					settings;

		        settings = $this.data("jcdData");

		        if (!settings) {
		            return undefined;
		        }
		        //If an individual setting is required
		        if (name) {
		            //If it exists, return it
		            if (settings.hasOwnProperty(name)) {
		                return settings[name];
		            }
		            return undefined;
		        }
		        //Return all settings
		        return settings;
		    }
		};

        if (methods[method]) {
            return methods[method].apply(this, slice.call(arguments, 1));
        } else if (typeof method === "object" || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $j.error("Method " + method + " does not exist in the jCountdown Plugin");
        }
    };

})(jQuery);


$j(document).ready(function () {

    $j("#time").countdown({
        date: "december 22, 2011", //Counting TO a date
        onComplete: function (event) {

            $j(this).html("Slut");
        },
        leadingZero: true,
        direction: "up"
    });

    $j("#time_hms").countdown({
        date: "november 24, 2011",
        offset: 1,
        onComplete: function (event) {

            $j(this).html("<div style=\"float: left; margin-right: 40px; font-size: 40px;\">S</div><div style=\"float: left; margin-right: 40px; font-size: 40px;\">L</div><div style=\"float: left; margin-right: 40px; font-size: 40px;\">U</div><div style=\"float: left;font-size: 40px;\">T</div>");
        },
        onPause: function (event, timer) {

            $j(this).html("Pause");
        },
        onResume: function (event) {

            $j(this).html("Resumed");
        },
        leadingZero: true
    });
});
