改造一个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;}

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

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

时间: 2024-10-31 16:48:14

改造一个JS插件的过程记录的相关文章

去年方百度首页播放器写的一个js代码,先记录一下,不支持火狐了,改天用autio改改

播放器内核使用的是 object 或embed 刚刚测试了下,最新的火狐不支持了,IE 360还能用,改天换成audio来做吧 这里先记录下来 支持下一曲,暂停,开始 使用方法很简单: 该代码很简单,使用js实现,使用方法很简单 1.引入css:<link href="css/StyleSheet.css" rel="stylesheet" type="text/css" />2.引入js:<script src="j

一个问题完整解决过程记录

有时候一些东西不经意听见了,并不当回事,回头就忘了.人总是这么健忘! 学习hebernate的时候,看到一句话,对于需 要映射到数据库中的实体类需要满足几个要求,其中有一个是说对于重写了equals重写后要重写hashcode.相信这是一句老生常谈的话了,大家都不 陌生.当时我也一扫而过.后来看到一个短片说怎样验证一个cookie有效性也提到了hash算法.于是就想验证一下之前的两个重写. 当时随手就写了一段代码(没有用快捷键),如下: 1 public class hash { 2 publi

jquery.validate.js插件的使用方法

近期做项目.须要用到 jQuery.validate.js插件,于是记录一下工作中的一些经验,以便日后学习. [样例例如以下] 1.前台页面 <form id="form1" method="post"> username:<input type="text" id="UserName" name="UserName" /><!--<span id="name_

js插件设置innerHTML时,在IE8下报错“未知运行时错误”

问题描述: 网站中使用了一个js插件,设置innerHTML时,在IE8下报错“未知运行时错误”: <div id=”divContainer”> <a name=”link”> -->报错处 第三方插件内容… </a> </div> 原因: 所设置的innerHTML的对象是一个<a>,是由于<a>的对象包容性的比较低,当浏览器运行这段脚本时,校验出了运行时错误. 解决方法: 将<a>标签替换为<div>

jquery.validate.js插件的用法

最近做项目,需要用到 jQuery.validate.js插件,于是记录一下工作中的一些经验,以便日后学习. [例子如下] 1.前台页面 <form id="form1" method="post"> 用户名:<input type="text" id="UserName" name="UserName" /><!--<span id="name_error&q

swiper的使用方法,以及各种JS插件的使用通用技巧

任何一个JS插件,都可以看做是一个组件. 组件包含三种东西:HTML布局,CSS样式表,JS代码. 组件使用的时候:要也是要注意三个东西 一.html布局. 通过HTML结构分析,来快速的了解,插件的html布局. 1.HTML一般只有两种结构,父子结构,兄弟结构. 2.分析层数,分析出最精简的结构,看看层数,父子结构,就看成是2层 二.css样式表 这个一般不需要分析. 三.JS使用 第三方组件,比如swiper,都是使用对象作为参数进行配置. 对象是对象,参数是参数.对象本质,参数是用途.

关于最近在做的一个js全屏轮播插件

最近去面试了,对方要求我在一个星期内用原生的js代码写一个全屏轮播的插件,第一想法就是跟照片轮播很相似,只是照片轮播是有定义一个宽高度大小已经确定了的容器用来存储所有照片,然后将照片全部左浮动,利用margin-left的值不断变化,来改变显示哪张照片,当达到最后一张的时候,将第一张照片appendChild到最后一张照片的后面,如果有左右移动的话,当到达第一张照片时,还要继续左移动的话,就将最后一张照片利用insertBefore,将最后一张照片放在第一张照片的前面,这两个方法都只是改变子元素

如何定义一个高逼格的原生JS插件

转自:https://www.jianshu.com/p/205a4033010a 如何定义一个高逼格的原生JS插件 作为一个前端er,如果不会写一个小插件,都不好意思说自己是混前端界的.写还不能依赖jquery之类的工具库,否则装得不够高端.那么,如何才能装起来让自己看起来逼格更高呢?当然是利用js纯原生的写法啦.以前一直说,掌握了js原生,就基本上可以解决前端的所有脚本交互工作了,这话大体上是有些浮夸了.不过,也从侧面说明了原生js在前端中占着多么重要的一面.好了.废话不多说.咱们就来看一下

openWRT自学---自己编译的第一个 backfire10.03 版本的过程记录(转)

基于 backfire10.03(从http://downloads.openwrt.org/backfire/10.03/ 中下砸的源码包backfire_10.03_source.tar.bz2:后来确认不应该从这里下载:而是应该从svn下载),编译用于H618B的版本 -- BRCM53xx:过程记录如下: 1.sdk自带的luci版本是0.9.0,结果编译luci出错: /home/hadoop/openwrt/backfire_10.03/build_dir/target-mipsel