插件的创建机制
默认情况下,boostrap.js文件被页面加载执行完成后,boostrap会自动根据html元素的data-toggle属性和相关class创建插件对象。有时候,我们不希望boostrap插件的行为影响到整个页面,希望可以精准地在一个 指定的html元素上创建插件。要想达到这个目的,需要两个步骤:
1. 关闭插件的默认行为。
2. 在指定的html元素重新创插件。
 
第一步只需要很简单的一行代码就可以达到目的:
$(document).off(".data-api");
这行代码是关闭.data-api名字空间下的所有事件处理器,而boostrap所有插件的事件类型都是在.data-api名字空间下的,所以,这样就可以让所有插件失效。
 
第二步就比较麻烦,需要搞清楚bootstrap默认是怎样创建插件的。下面以collapse插件为例看看插件的创建过程:
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
 
return $(target)
}
 
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
 
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
 
var old = $.fn.collapse
 
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
 
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
 
if (!$this.attr('data-target')) e.preventDefault()
 
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
 
Plugin.call($target, option)
})
通过上面的一段代码,可以得到4个重要的结论:
1. Plugin函数表名,bootstrap插件实际上是一个jquery插件。
2. document元素所有子元素中,带有属性data-toggle="collapse"的元素上注册了click事件.
3. 带有data-toggle="collapse"属性的元素只是触发器(trigger), data-target指向的元素才是collapse插件创建的目标元素。
4. trigger第一次执行click事件处理器时才会创建collapse插件。
有了这4个结论,就很容易想到,只需把click.bs.collapse.data-api事件注册到指定的知道的元素上即可随意控制collapse插件的影响范围,即:把document替换成你想要的element。
 
collapse插件是一个很典型的bootstrap插件,在boostrap中,绝大多数插件都和它类似,通过在document上注册事件作为插创建的入口。因此可以说,boostrap插件的手动创建过程,就是在指定的元素上重新注册事件。
 
下面来具体看一下每一个插件的创建和和关闭。
 
Modal
默认情况下,在带有data-toggle="modal"的元素上注册click.bs.modal.data-api的处理函数,当触发这个元素的click事件后,会在data-target或href属性指向的元素上创建Modal插件。对真正的modal来说,这个元素只是一个trigger, model之后的行为和它再无关系。modal创建可以忽略这个trigger, $(elem).modal("show")即可在指定的元素上创建,$(elem).modal("hide")关闭。
 
Dropdown
创建:
$(elem).dropdown();
if(!$(document).data("dropdown_inited")){
$(document).data("dropdown_inited", true);
$(document).dropdown();
}
droapdown方法会把Dropdown的toggle方法注册到elem的click事件上,toggle方法实现了dropdwon的所有行为。只是这样还不行,因为这个插件还有一个行为:点击其他任何地方都会导致原来已经弹出的dropdwon收起,所以还要在document创建一个用于处理全局点击事件的drapdown。不要担心这个全局的dropdown会造成不良影响,它的唯一作用是收起已经打开的dropdown。
关闭:
$(elem).off("click.bs.dropdown");
 
Tab
创建
function clickHandler(e) {
e.preventDefault()
let Plugin = $(this).tab;
Plugin.call($(this), 'show')
}
$(elem)
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
关闭
$(elem)
.off('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
.off('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
 
Tooltip, Popover
创建
$(elem).tooltip();
$(elem).popover();
关闭
默认情况下会在elem上注册mouseenter, mouseleave或focusin, focusout或click事件,关闭是需要注销这几个事件。这些事件的注册行为取决于options的trigger属性,默认值是"hover focus"
function off(plugin){
let triggers = plugin.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
let trigger = triggers[i]
 
if (trigger == 'click') {
plugin.$element.off('click.' + plugin.type)
} else if (trigger != 'manual') {
let eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
let eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
 
plugin.$element.off(eventIn + '.' + plugin.type)
plugin.$element.off(eventOut + '.' + plugin.type)
  }
}
plugin.$element.data("bs"+plugin.type, null);
}
let plugin =$(elem).data('bs.tooltip')
if(plugin) off(plugin);
plugin = $(elem).data('bs.popover');
if(plugin off(plugin);
 
Popover是从Tooltip继承而来,它们的行为处理方式是一样的。
 
Alert
创建
$(elem).alert();
关闭
$(elem).off("click", [data-dismiss="alert"]);
 
Button
创建
$(elem).button();
关闭
button插件不需关闭,bootstrap没有在它在元素上注册事件处理,造成干扰。
 
Collapse
创建:
collapse默认在trigger上注册click事件处理器函数,这个函数先从trigger的data-taget或href上得到创建collapse的目标元素,然后在这个目标元素上创建collapse
function getTargetFromTrigger($trigger){
let href
let target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
 
return $(target)
}
function clickHandler(e){
let $this = $(this)
 
if (!$this.attr('data-target')) e.preventDefault()
 
let $target = getTargetFromTrigger($this)
let data = $target.data('bs.collapse')
let option = data ? 'toggle' : $this.data()
 
let Plugin = elem.collapse;
Plugin.call($target, option)
}
$(elem).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', clickHandler);
 
关闭
$(elem).off(".collapse.data-api", '[data-toggle="collapse"]', clickHandler);
 
let triggers = $(elem).find('[data-toggle="collapse"]');
triggers.foreach(function(){
let $this = $(this)
let $target = getTargetFromTrigger($this)
$target.data('bs.collapse', null);
});
 
Carousel
创建
trigger的点击事件处理函数
function clickHandler(e){
let href
let $this = $(this)
let $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
if (!$target.hasClass('carousel')) return
let options = $.extend({}, $target.data(), $this.data())
let slideIndex = $this.attr('data-slide-to')
if (slideIndex) options.interval = false
 
let Plugin = $this.carousel;
Plugin.call($target, options)
 
if (slideIndex) {
$target.data('bs.carousel').to(slideIndex)
}
e.preventDefault()
}
添加事件处理函数
$(elem)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
;
关闭:
销毁trigger关联的元素上的carousel
function destroy(triggers){
triggers.foreach(function(){
let href
let $this = $(this)
let $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, ''));
if (!$target.hasClass('carousel')) return
$target.foreach(function(){
let $item = $(this);
$item.data('bs.carousel', null);
});
});
}
关闭事件处理
$(elem)
.off('click.bs.carousel.data-api', '[data-slide]', clickHandler)
.off('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
;
销毁所有trigger关联元素上的carousel
let triggers = elem.find("[data-slide]");
destroy(triggers);
triggers = elem.find("[data-slide-to]");
destroy(triggers);

bootstrap 通过js代码创建和关闭插件的更多相关文章

  1. 如何将Js代码封装成Jquery插件

    很多相同的Jquery代码会在很多页面使用,每次都复制粘贴太麻烦了,不如封装成一个Jquery插件就方便了,至于影响网页的速度不,我就没有测试了哈. 代码如下 这是一个自定闪烁打印文字的Jquery特 ...

  2. Atom编辑器折腾记_(15)JS代码片段补全(插件:javascript-snippets)

    题外话 这款插件就比較重量级了-.用熟悉了写原生JS的效率要提升非常多--并且,不仅支持JS还包括了nodejs snippet javascript-snippets 插件作者: zenorocha ...

  3. MyEclipse安装JS代码提示(Spket插件)

    近期需要大量使用JS来开发,但是MyEclipse2014自带的JS编辑器没有代码提示的功能,开发效率有点低,所以安装了一个Spket的插件,过程非常简单,SVN插件的安装比这个更简单. Spket插 ...

  4. bootstrap插件学习-bootstrap.modal.js

    bootstrap插件学习-bootstrap.modal.js 先从bootstrap.modal.js的结构看起. function($){ var Modal = function(){} // ...

  5. Bootstrap transition.js 插件详解

    Bootstrap 自带的 JavaScript 插件的动画效果几乎都是使用 CSS 过渡实现的,而其中的 transition.js 就是为了判断当前使用的浏览器是否支持 CSS 过渡.下面先来简单 ...

  6. bootstrap插件学习-bootstrap.carousel.js

    先看bootstrap.carousel.js的结构 var Carousel = function (element, options){} //构造器 Carousel.prototype = { ...

  7. Bootstrap transition.js 插件

    Bootstrap transition.js 插件详解   Bootstrap 自带的 JavaScript 插件的动画效果几乎都是使用 CSS 过渡实现的,而其中的 transition.js 就 ...

  8. bootstrap插件学习-bootstrap.dropdown.js

    bootstrap插件学习-bootstrap.dropdown.js 先看bootstrap.dropdown.js的结构 var toggle = '[data-toggle="drop ...

  9. 《玩转Bootstrap(JS插件篇)》笔记

    导入JavaScript插件 不论是单独导入还一次性导入之前必须先导入jQuery库. 一次性导入 <script src="js/bootstrap.min.js"> ...

随机推荐

  1. ASP.NET Web API 异常处理 HttpResponseException 以及Angularjs获取异常信息并提示

    一.HttpResponseException 如果一个Web API控制器抛出一个未捕捉异常,默认地,大多数异常都会被转化成一个带有状态码“500 – 内部服务器错误”的HTTP响应.HttpRes ...

  2. linux命令 find的应用

    1.列出当前目录及子目录下所有文件和文件夹 2.在 /home目录下查找以 “.txt”结尾的文件名 3.在当前目录下查找所有以“.txt”结尾的文件 4基于目录深度搜索(向下最大深度限制为3) 5. ...

  3. AlexNet详解2

    此处以caffe官方提供的AlexNet为例. 目录: 1.背景 2.框架介绍 3.步骤详细说明 5.参考文献 背景: AlexNet是在2012年被发表的一个金典之作,并在当年取得了ImageNet ...

  4. Opencv4.0:遍历Mat图像空间、读取摄像头

    GitHub https://github.com/gongluck/Opencv3.4-study.git #include "opencv2/opencv.hpp" using ...

  5. 绿色版Mysql自动建立my.ini和命令行启动并动态指定datadir路径

    1.先去下载绿色版的Mysql(https://cdn.mysql.com//archives/mysql-5.7/mysql-5.7.20-winx64.zip) 2.解压缩到任意目录(如D:\My ...

  6. 重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下

    1.先看下整体效果 2.前端代码 <UserControl x:Class="iPIS.UI.Base.Tree.ImageTreeControl" xmlns=" ...

  7. 使用C#写MVC框架(一:核心原理)

    目录: 一.MVC原理解析 二.HttpHandler 1.HttpHandler,IHttpHandler,MvcHandler的说明 2.IHttpHandler解析 3.MvcHandler解析 ...

  8. 【react】关于react框架使用的一些细节要点的思考

    ( _(:3 」∠)_给园友们提个建议,无论是API文档还是书籍,一定要多看几遍!特别是隔一段时间后,会有意想不到的收获的)   这篇文章主要是写关于学习react中的一些自己的思考:   1.set ...

  9. Android---------------Handler的学习

    public LocalVPNService() { mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mBackgro ...

  10. Select count(*)、Count(1)、Count(0)的区别和执行效率比较

    记得很早以前就有人跟我说过,在使用count的时候要用count(1)而不要用count(*),因为使用count(*)的时候会对所有的列进行扫描,相比而言count(1)不用扫描所有列,所以coun ...