首页 > 代码库 > 改造一个JS插件的过程记录

改造一个JS插件的过程记录

    最近做一个合作项目,对方要求我们做一个web应用程序,然后嵌入到他们的总的wen应用中,风格要求保持一致,于是乎就发了一个html文件过来,大概列举了一下各种控件,对话框的效果。

    好了,重点说其中的一个弹出插件,其源码为:

(function($) {    $(a[data-reveal-id]).live(click, function(e) {        e.preventDefault();        var modalLocation = $(this).attr(data-reveal-id);        $(#+modalLocation).reveal($(this).data());    });    $.fn.reveal = function(options) {                        var defaults = {              animation: fade, //fade, fadeAndPop, none            animationspeed: 300, //how fast animtions are            animationopacity:0.6,// BG opacity            closeonbackgroundclick: true, //if you click background will modal close?            dismissmodalclass: close-reveal-modal, //the class of a button or element that will close an open modal        };                 var options = $.extend({}, defaults, options);             return this.each(function() {        /*--------------------------- Global Variables----------------------------*/            var modal = $(this),                topMeasure  = parseInt(modal.css(top)),                topOffset = modal.height() + topMeasure,                  locked = false,                modalBG = $(.reveal-modal-bg);/*--------------------------- Create Modal BG----------------------------*/            if(modalBG.length == 0) {                modalBG = $(<div class="reveal-modal-bg" />).insertAfter(modal);            }                        /*--------------------------- Open and add Closing Listeners----------------------------*/            //Open Modal Immediately            openModal();                        //Close Modal Listeners            var closeButton = $(. + options.dismissmodalclass).bind(click.modalEvent,closeModal)            if(options.closeonbackgroundclick) {                modalBG.css({"cursor":"pointer"})                modalBG.bind(click.modalEvent,closeModal)            }                        /*--------------------------- Open & Close Animations----------------------------*/            //Entrance Animations            function openModal() {                modalBG.unbind(click.modalEvent);                $(. + options.dismissmodalclass).unbind(click.modalEvent);                if(!locked) {                    lockModal();                    if(options.animation == "fadeAndPop") {                        modal.css({top: $(document).scrollTop()-topOffset, opacity : 0, visibility : visible});                        modalBG.fadeIn(options.animationspeed/2);                        modal.delay(options.animationspeed/2).animate({                            "top": $(document).scrollTop()+topMeasure,                            "opacity" : 1                        }, options.animationspeed,unlockModal());                                        }                    if(options.animation == "fade") {                        modal.css({opacity : 0, visibility : visible, top: $(document).scrollTop()+topMeasure});                        modalBG.fadeIn(options.animationspeed/2, function(){                               $(this).css(opacity,options.animationopacity);                        });                        modal.delay(options.animationspeed/2).animate({                            "opacity" : 1                        }, options.animationspeed,unlockModal());                                        }                     if(options.animation == "none") {                        modal.css({visibility : visible, top:$(document).scrollTop()+topMeasure});                        modalBG.css({"display":"block"});                            unlockModal()                                    }                   }            }                                //Closing Animation            function closeModal() {                if(!locked) {                    lockModal();                    if(options.animation == "fadeAndPop") {                        modalBG.delay(options.animationspeed).fadeOut(options.animationspeed);                        modal.animate({                            "top":  $(document).scrollTop()-topOffset,                            "opacity" : 0                        }, options.animationspeed/2, function() {                            modal.css({top:topMeasure, opacity : 1, visibility : hidden});                            unlockModal();                        });                                        }                          if(options.animation == "fade") {                        modalBG.delay(options.animationspeed).fadeOut(options.animationspeed);                        modal.animate({                            "opacity" : 0                        }, options.animationspeed, function() {                            modal.css({opacity : 1, visibility : hidden, top : topMeasure});                            unlockModal();                        });                                        }                          if(options.animation == "none") {                        modal.css({visibility : hidden, top : topMeasure});                        modalBG.css({display : none});                        }                               }            }            /*--------------------------- Animations Locks----------------------------*/            function unlockModal() {                 locked = false;            }            function lockModal() {                locked = true;            }                        });    }})(jQuery);        

这个插件的内容就是很简单,你写好如下的HTML,他就弹出一个提示请等待的Modal框,因为是JQuery的插件,所以调用方法其实就一句话:

$Obj.reveal()

其中,$Obj 是一个Jquery对象。这个模态框弹出之后,你点击之后就会关掉。(这个插件依赖Jqeury库,用的朋友你们懂的)

问题来了:这个拓展插件根本没提供程序关闭的方法有木有??难道只能手动点击才能关掉么?

  忍不了这破东西,要不是对方规定好了效果,我非得重新弄一个不可。看来,得挽起袖子重写一下了。嗯。

我的基本思路就是,将这个JQuery插件改写为直接用面向对象的方法调用,可以直接关闭的插件,因为这个插件用了太多闭包,看样子改写的幅度还蛮大。

首先引入甘露模型:

/* File Created: 七月 23, 2014 */function Class() {    var aDefine = arguments[arguments.length - 1]; //最后一个参数是类定义    if (!aDefine) return;    var aBase = arguments.length > 1 ? arguments[0] : object; //解析基类    function prototype_() { }; //构造prototype的临时函数,用于挂接原型链    prototype_.prototype = aBase.prototype;  //准备传递prototype    var aPrototype = new prototype_();    //建立类要用的prototype    for (var member in aDefine)  //复制类定义到当前类的prototype        if (member != "Create")    //构造函数不用复制            aPrototype[member] = aDefine[member];    //根据是否继承特殊属性和性能情况,可分别注释掉下列的语句    if (aDefine.toString != Object.prototype.toString)        aPrototype.toString = aDefine.toString;    if (aDefine.toLocaleString != Object.prototype.toLocaleString)        aPrototype.toLocaleString = aDefine.toLocaleString;    if (aDefine.valueOf != Object.prototype.valueOf)        aPrototype.valueOf = aDefine.valueOf;    if (aDefine.Create)  //若有构造函数        var aType = aDefine.Create  //类型即为该构造函数    else    //否则为默认构造函数        aType = function () {            this.base.apply(this, arguments);   //调用基类构造函数        };    aType.prototype = aPrototype;   //设置类(构造函数)的prototype    aType.Base = aBase;             //设置类型关系,便于追溯继承关系    aType.prototype.Type = aType;   //为本类对象扩展一个Type属性    return aType;   //返回构造函数作为类};//根类object定义:function object() { }    //定义小写的object根类,用于实现最基础的方法等object.prototype.isA = function (aType)   //判断对象是否属于某类型{    var self = this.Type;    while (self) {        if (self == aType) return true;        self = self.Base;    };    return false;};object.prototype.base = function ()  //调用基类构造函数{    var Base = this.Type.Base;  //获取当前对象的基类      if (!Base.Base)  //若基类已没有基类        Base.apply(this, arguments)     //则直接调用基类构造函数    else    //若基类还有基类             {        this.base = MakeBase(Base);     //先覆写this.base        Base.apply(this, arguments);    //再调用基类构造函数        delete this.base;               //删除覆写的base属性    };    function MakeBase(Type) //包装基类构造函数    {        var Base = Type.Base;        if (!Base.Base) return Base; //基类已无基类,就无需包装        return function ()   //包装为引用临时变量Base的闭包函数        {            this.base = MakeBase(Base);     //先覆写this.base            Base.apply(this, arguments);    //再调用基类构造函数        };    };};

O了,这一段如果有不明白的地方,必须得看《悟透Javascript这本书了》 我这里篇幅有限,不多介绍了。

接下来,写下自己已经改造好了的插件

/* File Created: 七月 23, 2014 */var CustomerModal = Class({    openModal: function () {        modalBG.unbind(click.modalEvent);        $(. + this.options.dismissmodalclass).unbind(click.modalEvent);        if (!locked) {            this.lockModal();            if (this.options.animation == "fadeAndPop") {                modal.css({ top: $(document).scrollTop() - topOffset, opacity: 0, visibility: visible });                modalBG.fadeIn(this.options.animationspeed / 2);                modal.delay(this.options.animationspeed / 2).animate({                    "top": $(document).scrollTop() + topMeasure,                    "opacity": 1                }, this.options.animationspeed, this.unlockModal());            }            if (this.options.animation == "fade") {                modal.css({ opacity: 0, visibility: visible, top: $(document).scrollTop() + topMeasure });                modalBG.fadeIn(this.options.animationspeed / 2, function () {                    $(this).css(opacity, 0.6);                });                modal.delay(this.options.animationspeed / 2).animate({                    "opacity": 1                }, this.options.animationspeed, this.unlockModal());            }            if (this.options.animation == "none") {                modal.css({ visibility: visible, top: $(document).scrollTop() + topMeasure });                modalBG.css({ "display": "block" });                this.unlockModal()            }        }    },    closeModal: function (CModal) {        if (!locked) {            CModal.lockModal();            if (CModal.options.animation == "fadeAndPop") {                modalBG.delay(CModal.options.animationspeed).fadeOut(CModal.options.animationspeed);                modal.animate({                    "top": $(document).scrollTop() - topOffset,                    "opacity": 0                }, CModal.options.animationspeed / 2, function () {                    modal.css({ top: topMeasure, opacity: 1, visibility: hidden });                    CModal.unlockModal();                });            }            if (CModal.options.animation == "fade") {                modalBG.delay(CModal.options.animationspeed).fadeOut(CModal.options.animationspeed);                modal.animate({                    "opacity": 0                }, CModal.options.animationspeed, function () {                    modal.css({ opacity: 1, visibility: hidden, top: topMeasure });                    CModal.unlockModal();                });            }            if (this.options.animation == "none") {                modal.css({ visibility: hidden, top: topMeasure });                modalBG.css({ display: none });            }        }    },    unlockModal: function () {        locked = false;    },    lockModal: function () {        locked = true;    },    show: function ($obj, CModal) {        this.defaults = {            animation: fade, //fade, fadeAndPop, none            animationspeed: 300, //how fast animtions are            animationopacity: 0.6, // BG opacity            closeonbackgroundclick: true, //if you click background will modal close?            dismissmodalclass: close-reveal-modal //the class of a button or element that will close an open modal        };        this.options = $.extend({}, this.defaults, this.options);        /*---------------------------        Global Variables        ----------------------------*/        modal = $obj,                topMeasure = parseInt(modal.css(top)),                topOffset = modal.height() + topMeasure,                  locked = false,                modalBG = $(.reveal-modal-bg);        /*---------------------------        Create Modal BG        ----------------------------*/        if (modalBG.length == 0) {            modalBG = $(<div class="reveal-modal-bg" />).insertAfter(modal);        }        /*---------------------------        Open and add Closing Listeners        ----------------------------*/        //Open Modal Immediately        this.openModal();        //Close Modal Listeners        var closeButton = $(. + this.options.dismissmodalclass).bind(click.modalEvent, function () { CModal.closeModal(CModal); });        if (this.options.closeonbackgroundclick) {            modalBG.css({ "cursor": "pointer" });            modalBG.bind(click.modalEvent, function () { CModal.closeModal(CModal) });        }        /*---------------------------        Open & Close Animations        ----------------------------*/        //Entrance Animations        //Closing Animation        /*---------------------------        Animations Locks        ----------------------------*/    }});

调用就很简单了:

m_CustomerModal = new CustomerModal();  m_CustomerModal.show($("#watingmodal"),m_CustomerModal);

这个是一个div框而已了,代码如下:

   <div id="watingmodal" class="wating_modal spopup">        请等待......</div>

关闭的时候如此调用:

 m_CustomerModal.closeModal(m_CustomerModal);

虽然看起来有那么些别扭,但是Javascript的this关键字是比较特殊的,如果用call其实也是可以的,条条大路通罗马。

当然,别忘了样式:

.spopup{ top:200px;}.big-link { display:block; margin-top:100px; text-align:center; font-size:16px;}.reveal-modal-bg { position:fixed; height:100%; width:100%; background:#000; z-index:100; display:none; top:0; left:0; zoom:1; filter:alpha(opacity=70); opacity:0.7;}.reveal-modal { visibility:hidden; position: absolute; left:50%; margin-left:-300px; background:#EDEDED; z-index:101; border:#ACAEB4 solid 1px; border-radius:5px; behavior:url(js/PIE.htc);}.reveal-modal .close-reveal-modal { position:absolute; top:6px; right:12px; color:#aaa; cursor:pointer;} .reveal-modal .popuptitle{ height:28px; background:url(../images/dot03.gif) 12px 7px no-repeat; padding-left:35px;}.reveal-modal .popuptitle span{ position:relative; top:6px; line-height:20px; color:#E70000; letter-spacing:1px; font-weight:bold;}.reveal-modal .popupcontent{ background:#FFF; border:#C0C0C0 solid 1px; margin:0 4px 3px 4px;}.reveal-modal .popupcontent .popupbut{ width:100%; height:40px; border-top:#C0C0C0 solid 1px; background:#F4F4F4; text-align:right;}.reveal-modal .popupcontent .popupbut h1{ margin:9px 20px 0 0;}.reveal-modal .popupcontent .popupbut h1 input{ margin-left:4px;}.popupbutton{ height:22px; background:url(../images/graybutbg.png) repeat-x; border:#ABADB3 solid 1px; line-height:22px; text-align:center; padding:0 10px; cursor:pointer; color:#333;}.popupbutton_on{ height:22px; line-height:22px; text-align:center; padding:0 10px; cursor:pointer;}.wating_modal { visibility:hidden; position: absolute; left:50%; top:300px; margin-left:-200px; z-index:101; color:#FFF; font-weight:bold; font-size:14px; letter-spacing:1px;}

好吧。。我是不是专业美工,但是扣代码大家都会的吧,模版都给你了的说。。。改造完毕。