本来这个系列主题已经结束了,突然想到还有个功能要做,就是“模态”,即把学校选择器做成一个类似模态的对话框。这样就可以应付这样的使用场景:在一个学生列表的页面中,可以修改任意学生的所在学校,也可以添加其他学校的学生。
模态对话框
经常看到“模态”这个词,特地百度了一下它的定义:
模态对话框(Modal Dialogue Box,又叫做模式对话框),是指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应。如单击【确定】或【取消】按钮等将该对话框关闭。
再看看Bootstrap v2提供的模态对话框
可以看到其实没什么,就是页面背景加一块遮罩(mask),然后添加一个对话框的关闭按钮,告诉用户一定要先对该对话框进行操作。
添加模态
首先从SchoolBox的对外接口出发,原来我们构造SchoolBox对象时会传入一个appendTo
参数,意思是把这个对象追到到哪个元素中去。现在我们不用传appendTo
了,就可以表示这是个模态框,不需要追加到哪个具体元素。
1.我们要做的就是在SchoolBox对外的show
和hide
方法做相应的改变。
1 | show: function(){ |
这里注意,当用户不传入appendTo
时,构造函数中会给它个默认值就是body
,即上面代码中的$(this.opts.appendTo)
就是$('body')
。
2.在初始化时添加模态框的窗口栏和关闭按钮。
1 | var $popupCloseCopy = $('<div class="school-box-popup-close"><a href="javascript:void(0)" title="关闭">X</a></div>'); |
3.为模态框和遮罩添加相应的样式。
1 | .school-box-mask{ |
4.【patch】在真正的构造函数中添加appendTo
的默认值,并添加this.opts.popup
。在prototype的init
中如果是popup
,先隐藏school-box-wrapper
,因为它直接append到body最后。
对象共享
到这里我们已经实现了模态的SchoolBox,但是还有个问题,因为SchoolBox的构造开销不小,我们不希望在页面中每个有“学校”的地方都为之创建一个SchoolBox对象,我们希望同一个页面中能共用同一个SchoolBox对象。
因为我们之前已经使用了观察者模式,页面中的元素去监听自定义事件,然而“学校选定”这件事只触发一个事件。因此如果页面中有多个元素都监听着schoolChosen
事件,那么当由一个元素打开的学校选择器操作完成后,所有监听着该事件的其他元素都会做出相应的改变。即在一个学生列表的页面中,我改变一个学生的学校,其他学生的学校也会跟着改变。
因此要实现共用一个对象,我们得在每次使用它时,清空它的监听者列表,并重新赋予它该次使用时唯一的回调函数。这样就可以实现操作一个学生的学校,只响应一个元素。
1 | SchoolBox.prototype.unbind = function(type){ |
完整应用
多个需要使用学校的元素
1 | <div id="formResult"> |
共用一个SchoolBox对象,为页面元素绑定事件。
1 | $('.choose-school').click(function(){ |