先看bootstrap.popover.js的结构

var Popover = function ( element, options ){} //构造器
Popover.prototype = {} // 构造器的原型
$.fn.popover = function ( option ){} //jQuery原型上的自定义方法
$.fn.popover.Constructor = Popover //重写jQuery原型方法popover的构造器名
$.fn.popover.defaults = {} // 默认参数

个人感觉bootstrap.popover.js是bootstrap.tooltip.js的放大版。。源码处很多相似的地方,并且bootstrap.popover.js依赖与bootstrap.tooltip.js插件,至于怎么依赖,一会源码中我们会看到,跟bootstrap.tooltip.js一样,源码中没有提供初始化,那我们就自行初始化

<a id="a1" class="btn btn-danger"
data-content="他来自山东,是一名残疾人,因思想独立、指谪政弊而被政府迫害。地方政府和当权政要派专人看管他,
调拨专款作为对他的看管费用,他每天都活在别人的监视和囚禁中,其遭遇只能用令人发指来形容。历尽万难,他终于成功逃离了当地,
在外国使节的帮助和护送下去到了国外。他,就是孙膑。" rel="popover" href="#" data-original-title="他是谁">鼠标经过弹出提示</a>
$("#a1").popover();

执行时,加入上述代码,我们先看jQuery原型上的popover方法

/*
* jQuery原型上的自定义方法
* */
$.fn.popover = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('popover')
, options = typeof option == 'object' && option
if (!data) $this.data('popover', (data = new Popover(this, options)))//实例化构造器
if (typeof option == 'string') data[option]() //支持传入方法名参数,执行该方法。
})
}

给bootstrap.tooltip.js是一样的,初始化时,没有popover值,进入构造器

var Popover = function ( element, options ) {
this.init('popover', element, options) //实例化直接调用原型的init方法
}

注意,我们看到实例化时调用了init方法,可是popover的原型中没有直接给出init方法。

Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype,{})

可以看到,它将tooltip原型上所有方法与自己的合并了,这就是开始我们必须先引bootstrap-tooltip.js的原因,popover依赖许多tooltip原型上的很多方法。就上一次分析tooltip源码觉得蛋疼的部分代码,在本次分析中也能弄明白了。

不过在此之前,我们需要注意一个问题。大家可以大致看一下,tooltip和popover的原型上的方法,很多都是重名的,它们的原型方法一旦合并,会怎样,其实是后者覆盖前者,这是jQuery的extend方法的原理。

下面我们进入init方法

init: function ( type, element, options ) {
var eventIn
, eventOut this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.enabled = true if (this.options.trigger != 'manual') { //选择事件名
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
//绑定事件 this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))//其中有false,达到阻止冒泡的功能
this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
} this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()//没有默认参数执行
}

依照tooltip源码的分析,这里基本一致。这里调用tooltip的getOptions()方法,将默认参数与形参合并,这里参数也将tooltip里的默认参数加入进去,为标签绑定mouseenter和mouseleave事件,最后执行fixTitle方法,将被点击标签的title属性值转给data-original-title属性,最后删除title属性。

我们开始鼠标移入,进入tooltip的enter方法

/*
* 目的调用show方法
* */
, enter: function ( e ) {
/*
* 以下方法执行了jQuery原型上的tooltip方法。通过each遍历,获取data对象中的tooltip属性:即该对象的jQuery对象
* 感觉这个写法蛋疼
* */
var self = $(e.currentTarget)[this.type](this._options).data(this.type)//e.currentTarget获取当前点击对象 if (!self.options.delay || !self.options.delay.show) {
self.show()//鼠标移上去执行show方法
} else {
self.hoverState = 'in'
setTimeout(function() {
if (self.hoverState == 'in') {
self.show()
}
}, self.options.delay.show)
}
}

以上的解释是tooltip源码分析里的,我们主要过一遍代码,之前我觉得这段代码写的蛋疼,其实不是,它考虑了popover插件的复用。获取自己的jQuery对象

var self = $(e.currentTarget)[this.type](this._options).data(this.type)

不过如果说为了实现功能,完全可以写成

var self = this;

同样支持两个插件。

进入show方法。

show: function () {
var $tip
, inside
, pos
, actualWidth
, actualHeight
, placement
, tp if (this.hasContent() && this.enabled) {
$tip = this.tip()//获取提示框的jQuery对象
this.setContent()//给提示框赋值,初始化提示框的样式 if (this.options.animation) {
$tip.addClass('fade')//提示框拥有运动效果,加入fade类
} placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement//控制提示框的显示方位,默认为top inside = /in/.test(placement)//是否是in $tip
.remove()
.css({ top: 0, left: 0, display: 'block' })
.appendTo(inside ? this.$element : document.body)
/*先将提示框从文档中删除,获取其返回对象,即本身,加入样式,最后再重新插回文档中,这么写主要考虑in的情况
* 符合一种操作规范,如果添加样式,操作dom过于复杂,可以先将节点从dom中取出,经过一系列装饰后,再加入dom中,第一
* 便于浏览器渲染,二来也符合dom操作规范
* */
pos = this.getPosition(inside)//获取被点击对象的位置和本身尺寸
//获取提示框的宽度和高度
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
//我们拿top举例,在a标签上方,left方向,对着a标签居中。
switch (inside ? placement.split(' ')[1] : placement) {
case 'bottom':
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'top':
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'left':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
break
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
} $tip
.css(tp)
.addClass(placement)//配合内部的div实现小三角效果
.addClass('in')//半透明效果
}
}

这里我们需要留意几个方法,hasContent,setContent,tip方法,这些都是popover覆盖tooltip的方法,我们先从hasContent开始

hasContent: function () {
return this.getTitle() || this.getContent()//兼容tooltip插件。
}

前者是tooltip的getTitle方法,主要是获取data-original-title属性的值,并返回,后者是popover自己的方法,我们看一下

getContent: function () {
var content
, $e = this.$element
, o = this.options content = $e.attr('data-content')
|| (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) content = content.toString().replace(/(^\s*|\s*$)/, "") return content
}

跟getTitle类似,取出标签中data-content属性的值,如果前者返回空,则执行后一个方法,这样将两种插件很好的连在一起。

获取弹出框模版

/*获取弹出框对象*/
, tip: function() {
if (!this.$tip) {
this.$tip = $(this.options.template)
}
return this.$tip
}

向弹出框中添加内容

/*
* 给弹出框设置内容
* */
, setContent: function () {
var $tip = this.tip()
, title = this.getTitle()
, content = this.getContent() $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
$tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content) $tip.removeClass('fade top bottom left right in')
}

这里$.type()方法是判断对象的类型的。最后初始化弹出框的样式。

根据popover的默认参数中,弹出框显示在右侧。当鼠标移出时,进入leave方法。

leave: function ( e ) {
/*
* 与enter中一样
* */
var self = $(e.currentTarget)[this.type](this._options).data(this.type) if (!self.options.delay || !self.options.delay.hide) {
self.hide()
} else {
self.hoverState = 'out'
setTimeout(function() {
if (self.hoverState == 'out') {
self.hide()
}
}, self.options.delay.hide)
}
}

调用hide方法

hide: function () {
var that = this
, $tip = this.tip() $tip.removeClass('in')
/*
* 定义了提示框消失的特效,要显示这个特效,需要引入其他js,这先不讨论
* */
function removeWithAnimation() {
var timeout = setTimeout(function () {
$tip.off($.support.transition.end).remove()
}, 500) $tip.one($.support.transition.end, function () {
clearTimeout(timeout)
$tip.remove()
})
}

纵观整个popover插件,它几乎和tooltip一样。它没有提供像tooltip一样更多操作API,不过我们都可以自己实现。

很多时候这两个插件我们可以一起使用,用的时候,注意a标签上的属性就行了data-content是popover插件的,而data-original-title是tooltip插件的。

内容不多,时间刚好,以上是我的一点读码体会,如有错误,请指出,大家共通学习。

bootstrap插件学习-bootstrap.popover.js的更多相关文章

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

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

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

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

  3. bootstrap插件学习-bootstrap.alert.js

    我们先看bootstrap.alert.js的结构 var dismiss = '[data-dismiss="alert"]' //自定义属性 Alert = function ...

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

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

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

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

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

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

  7. bootstrap插件学习-bootstrap.button.js

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

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

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

  9. bootstrap插件学习-bootstrap.scrollspy.js

    先看bootstrap.dropdown.js的结构 function ScrollSpy(){} //构造函数 ScrollSpy.prototype = {} //构造器的原型 $.fn.scro ...

随机推荐

  1. js高仿QQ消息列表左滑功能

    该组件,主要功能类似于QQ消息列表左滑出现删除.标为已读等按钮的功能:现在的版本用的是纯javaScript编写:后续会跟进 angularJs 开发的类似组件以及jquery的; 下面,就让我们来认 ...

  2. springJDBC学习笔记和实例

    前言:相对于Mybatis(ibatis),个人感觉springJDBC更灵活,主要实现类JdbcTemplate:它替我们完成了资源的创建以及释放工作,从而简化了我们对JDBC的使用.它还可以帮助我 ...

  3. oprofile

    一.原理 在关注事件发生一定次数时,进行一次采样,记录下需要的信息(比如指令寄存器或栈寄存器信息). 二.参数 项 说明 eventname   要关注的事件名称,常用的事件名称及功能如下:   CP ...

  4. 了解 JavaScript (6)– 广告条(Banner)

    在 Web 上冲浪时,常常会见到定期在图像之间切换的广告条.我们可以用 JavaScript 来实现,重复循环显示它们. 创建循环的广告条 RotatingBanner.html 页面中在循环的广告条 ...

  5. 专访高磊:安卓APK安全加固的引领者

    高磊,爱加密CEO,安卓巴士版主之一,曾编写河南省某地市交通信息化规划十二五规划,以及参与省厅级资源共享平台设计等.之前的工作经理积累了丰富的设计规划经验,此外还具有J2EE和 Android开发经验 ...

  6. WIN7只能上QQ打不开网页,使用CMD输入netsh winsock reset

    此类问题可以用腾讯电脑管家电脑诊所一键修复,请点击上方的[立即修复]即可. 附:手动修复步骤(来源:腾讯电脑管家电脑诊所,自动修复请点击上方的[立即修复])方案一:手动设置DNS(说明:如果您使用DN ...

  7. [aaronyang]WPF4.5 - AyTabControlBase样式分享,绝对好看

    样式代码如下: 对于博客园将文章移除首页的做法:我就迁移了.文章已经迁移:http://www.ayjs.net/post/75.html 由于例子比较简单,你只要指定Style即可,难点,透明区域的 ...

  8. .NET错误The 'targetFramework' attribute in the <compilation> element of the Web.config file is used only to target version 4.0 and later of the .NET Framework

    错误描述: The 'targetFramework' attribute in the <compilation> element of the Web.config file is u ...

  9. Activemq消息类型

    Activemq消息类型JMS规范中的消息类型包括TextMessage.MapMessage.ObjectMessage.BytesMessage.和StreamMessage等五种.ActiveM ...

  10. Chapter 5. Graph Theory:: Fundamentals:: Intermediate

    10457 - Magic Car 题意一开始看起来有点费解,其实最后就是要起点到终点的路径上最大边与最小边之差越小越好.这样我们可以先将边排个序,然后枚举路径上的最小边,之后依次将比它大的边按升序的 ...