zepto插件 countdown 倒計時插件 從jquery 改爲 zepto

插件特點:支持zepto庫  支持時間戳格式 支持年月日時分秒格式html

countdown 由jquery依賴庫改爲zeptonode

zepto的event機制與jquery不一樣,因此更換以後代碼不能正常運行jquery

這裏對event機制作下探討web

事件是用來描述網頁中某一特定有趣時刻的,衆所周知事件一般是在由用戶和瀏覽器進行交互時觸發,其實否則,經過Javascript能夠在任什麼時候間觸發特定的事件,而且這些事件與瀏覽器建立的事件是相同的。這就意味着會有適當的事件冒泡,而且瀏覽器會執行分配的事件處理程序。這種能力在測試web應用程序的時候,是很是有用的,在DOM 3級規範中提供了方法來模擬特定的事件,IE9 chrome FF Opera 和 Safari都支持這樣的方式,在IE8及之前的辦法的IE瀏覽器有他本身的方式來模擬事件chrome

a)Dom 事件模擬
  能夠經過document上的createEvent()方法,在任什麼時候候建立事件對象,此方法只接受一個參數,既要建立事件對象的事件字符串,在DOM2 級規範上全部的字符串都是複數形式,在DOM 3級事件上全部的字符串都採用單數形式,全部的字符串以下:
  UIEvents:通用的UI 事件,鼠標事件鍵盤事件都是繼承自UI事件,在DOM 3 級上使用的是 UIEvent。
  MouseEvents:通用的鼠標事件,在DOM 3 級上使用的是 MouseEvent。
  MutationEvents:通用的突變事件,在DOM 3 級上使用的是 MutationEvent。
  HTMLEvents:通用的HTML事件,在DOM3級上尚未等效的。
注意,ie9是惟一支持DOM3級鍵盤事件的瀏覽器,但其餘瀏覽器也提供了其餘可用的方法來模擬鍵盤事件。
一旦建立了一個事件對象,就要初始化這個事件的相關信息,每一種類型的事件都有特定的方法來初始化,在建立完事件對象以後,經過dispatchEvent()方法來將事件應用到特定的dom節點上,以便其支持該事件。這個dispatchEvent()事件,支持一個參數,就是你建立的event對象。express

對於HTML事件,直接上代碼。
  var event = document.createEvent(「HTMLEvents」);
  event.initEvent(「focus」, true, false);
  target.dispatchEvent(event);瀏覽器

 

插件源碼地址:app

;
(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['Zepto'], factory);
    } else {
        factory(Zepto);
    }
})(function($) {

    var PRECISION = 1000; // 0.1 seconds, used to update the DOM
    var instances = [],
        matchers = [];
    // Miliseconds
    // matchers.push(/^[0-9]*$/.source);
        matchers.push(/^[0-9]*$/.source);
    // Month/Day/Year [hours:minutes:seconds
    // matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
       matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
    // Year/Day/Month [hours:minutes:seconds
    // matchers.push(/[0-9]{4}(\/[0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
       matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
    // Cast the matchers to a regular expression object
    matchers.push(/^[0-9]*$/.source);
    matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
    matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
    matchers = new RegExp(matchers.join("|"));
    // Parse a Date formatted has String to a native object
    function parseDateString(dateString) {
        // Pass through when a native object is sent 
        if (dateString instanceof Date) {
            return dateString;
        }
        // Caste string to date object
        if (String(dateString).match(matchers)) {
            // If looks like a milisecond value cast to number before 
            // final casting (Thanks to @msigley)
            if (String(dateString).match(/^[0-9]*$/)) {
                dateString = Number(dateString);
            }
            if (String(dateString).match(/\-/)) {
                dateString = String(dateString).replace(/\-/g, "/");
            }
            // return new Date(dateString);
            return new Date(dateString);
        } else {
            throw new Error("Couldn't cast `" + dateString + "` to a date object.");
        }
    }

    var DIRECTIVE_KEY_MAP = {
        'Y': 'years',
        'm': 'months',
        'w': 'weeks',
        'd': 'days',
        'D': 'totalDays',
        'H': 'hours',
        'M': 'minutes',
        'S': 'seconds'
    };

    // Time string formatter 
    function strftime(offsetObject) {
        // console.log(offsetObject)
        return function(format) {
            // console.log(format)
            var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
            if (directives) {
                for (var i = 0, len = directives.length; i < len; ++i) {
                    var directive = directives[i]
                        .match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/),
                        regexp = new RegExp(directive[0]),
                        modifier = directive[1] || '',
                        plural = directive[3] || '',
                        value = null;
                    // Get the key
                    directive = directive[2];
                    // Swap shot-versions directives
                    if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
                        value = DIRECTIVE_KEY_MAP[directive];
                        value = Number(offsetObject[value]);
                    }
                    if (value !== null) {
                        // Pluralize
                        if (modifier === '!') {
                            value = pluralize(plural, value);
                        }
                        // Add zero-padding
                        if (modifier === '') {
                            if (value < 10) {
                                value = '0' + value.toString();
                            }
                        }
                        // Replace the directive
                        format = format.replace(regexp, value.toString());
                    }
                }
            }
            format = format.replace(/%%/, '%');
            return format;
        };
    }
    // Pluralize
    function pluralize(format, count) {
        var plural = 's',
            singular = '';
        if (format) {
            format = format.replace(/(:|;|\s)/gi, '').split(/\,/);
            if (format.length === 1) {
                plural = format[0];
            } else {
                singular = format[0];
                plural = format[1];
            }
        }
        if (Math.abs(count) === 1) {
            return singular;
        } else {
            return plural;
        }
    }

    function fireEvent(el, type, extra) {
        var ev = document.createEvent("HTMLEvents");
        // console.log(type);
        ev.initEvent(type, true, true)
        for (var key in extra) {
            ev[key] = extra[key]
            console.log(extra[key])
        }
        el.dispatchEvent(ev);
        // console.log(el);
    }
    $.fn.On = function(name, cb) {
            if ($ == Zepto) {
                this.get(0).addEventListener(name, cb);
            } else {
                this.$el.on(name, callback);
            }
        }
        // The Final Countdown
    var Countdown = function(el, finalDate, callback) {
        this.el = el;
        this.$el = $(el);
        this.interval = null;
        this.offset = {};
        // Set the final date
        this.setFinalDate(finalDate);
        // Register this instance
        this.instanceNumber = instances.length;
        instances.push(this);
        // Save the reference
        this.$el.data('countdown-instance', this.instanceNumber);
        // Register the callbacks when supplied
        if (callback) {
            this.$el.On('update.countdown', callback);
            this.$el.On('stoped.countdown', callback);
            this.$el.On('finish.countdown', callback);
        }
        this.start();
    };
    Countdown.prototype.start = function() {

        if (this.interval !== null) {
            throw new Error("Countdown is already running!");
        }
        var self = this;
        this.update();
        this.interval = setInterval(function() {
            self.update.call(self);
        }, PRECISION);

    };
    Countdown.prototype.stop = function() {
        clearInterval(this.interval);
        this.interval = null;
        this.dispatchEvent('stoped');
    };
    Countdown.prototype.pause = function() {
        this.stop.call(this);
    };
    Countdown.prototype.resume = function() {
        this.start.call(this);
    };
    Countdown.prototype.remove = function() {
        this.stop();
        delete instances[this.instanceNumber];
    };
    Countdown.prototype.setFinalDate = function(value) {
        this.finalDate = parseDateString(value); // Cast the given date
    };
    Countdown.prototype.update = function() {
        // Stop if dom is not in the html (Thanks to @dleavitt)
        if (this.$el.closest('html').length === 0) {
            this.remove();
            return;
        }
        // Calculate the remaining time
        this.totalSecsLeft = this.finalDate.valueOf() -
            new Date().valueOf(); // In miliseconds
        this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1000);
        this.totalSecsLeft = this.totalSecsLeft < 0 ?
            0 : this.totalSecsLeft;
        // Calculate the offsets
        this.offset = {
            seconds: this.totalSecsLeft % 60,
            minutes: Math.floor(this.totalSecsLeft / 60) % 60,
            hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
            days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
            totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
            weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
            months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30),
            years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365)
        };
        // Dispatch an event
        if (this.totalSecsLeft === 0) {
            this.stop();
            this.dispatchEvent('finish');
        } else {
            this.dispatchEvent('update');
        }

    };
    Countdown.prototype.dispatchEvent = function(eventName) {
        var event = {}; //$.Event(eventName + '.countdown');
        event.finalDate = this.finalDate;
        event.offset = $.extend({}, this.offset);
        event.strftime = strftime(this.offset);
        if ($ == Zepto) {
            // console.log(eventName)
            fireEvent(this.$el.get(0), eventName + '.countdown', event);
        } else {
            this.$el.trigger(event);
        }
        // console.log(this)
        // console.log(event);
    };
    // Register the jQuery selector actions
    $.fn.countdown = function() {

        var argumentsArray = Array.prototype.slice.call(arguments, 0);
        // console.log(argumentsArray[1])
        return this.each(function() {

            var instanceNumber = $(this).data('countdown-instance');
            // console.log(instanceNumber+'agd')
            // Verify if we already have a countdown for this node ...
            if (instanceNumber) {

                var instance = instances[instanceNumber],
                    method = argumentsArray[0];

                // If method exists in the prototype execute
                if (Countdown.prototype.hasOwnProperty(method)) {
                    instance[method].apply(instance,
                        argumentsArray.slice(1));
                    // If method look like a date try to set a new final date
                } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
                    instance.setFinalDate.call(instance,
                        method);
                } else {
                    $.error('Method %s does not exist on jQuery.countdown'.replace(/\%s/gi, method));
                }
            } else {
                // ... if not we create an instance
                new Countdown(this, argumentsArray[0], argumentsArray[1]);

            }
        });
    };
});
View Code

參考文檔 http://www.cnblogs.com/MrBackKom/archive/2012/06/26/2564501.htmldom

相關文章
相關標籤/搜索