JavaScript练习五之仿bootstrap之Tooltip

来源:互联网 发布:sql server有mac版吗 编辑:程序博客网 时间:2024/05/22 07:59

前言
bootstrap是目前比较主流的前端开发框架(简称BS),里面有很多很实用的JS小组件,非常有学习及参考价值。本次参考的是tooltip组件,该组件是BS中用处较广的组件之一,相比传统的title,能为用户提供更好的交互。

感悟
1、看似简单的tooltip功能,其源码确并不简单,即便是在bs的所有组件当中,该组件的代码量也是非常多的。第一天主要是查看其代码结构,理解其编程思路,并搭出了一个基础框架,已可以实现了主体功能。第二天完善细节,提供更多配置

2、第一天搭框架时,该组件里的很多代码第一时间看的时候,并没有理解其中作用,并按照自己的理解,将很多代码进行删减,原先400行代码按照我个人理解砍到了只剩150行。在第三天在搭建Popover组件时,发现其代码大部分都是继承于tooltip,于是我再按照自己的理解对tooltip进行了调整以便于继承。此时回首tooltip源码,发现我的扩增思路和其原代码实现思路不谋而合,很多之前不明所以的参数或者方法一瞬间理解了。所以,在查阅其他人源代码的时候,不能过于相信其代码,在遇上理解困难时,不妨先按照自己的思路去实现一下,发现阻碍之后再回过头或许会更好理解。

Code List

//@charset "utf-8" /** * @function : 仿bootstrap的Tooltip组件(练习) * @author   : yinggaozhen * @create   : 2016-01-14 * @version  : 0.0.1 * @example  :  * HTML :       <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="right" title="gaozhen'Js Test">Tooltip on right</button> * JavaScript :       $(function () {        $('[data-toggle="tooltip"]').tooltip()    }) */ +function($) {    var ext = 'tooltip';    var TOOLTIP_DEFAULTOPTIONS = {        animation : true,        placement : 'top',        templete  : '<di v class="tooltip" role="tooltip"><d iv class="tooltip-arrow"></di v><di v class="tooltip-inner"></di v></di v>',        trggier   : 'hover focus click',        delay     : 0    };    var Tooltip = function(element, options) {        this.type    = null;        options = options || {};        this.init('tooltip', element, options);    };    Tooltip.prototype.init = function(type, element, options) {        var me = this;        me.type    = type;        me.$el     = $(element);        me.options = me.getOptions(options);        me.inState = {click : false, hover : false, focus : false};        var trggierEvts = me.options.trggier.split(' ');        for (var idx in trggierEvts) {            var trggierEvt = trggierEvts[idx];            if (trggierEvt == 'click') {                me.$el.on('click.' + me.type, me.enter, $.proxy(this.toggle, this));            } else if (trggierEvt != 'manual') {                var evtIn  = trggierEvt == 'hover' ? 'mouseenter' : 'focusin',                    evtOut = trggierEvt == 'hover' ? 'mouseleave' : 'focusout';                me.$el.on(evtIn  + '.' + me.type, me.enter, $.proxy(this.enter, this));                me.$el.on(evtOut + '.' + me.type, me.leave, $.proxy(this.leave, this));            }        }    };    Tooltip.prototype.getOptions = function(options) {        return options = $.extend({}, this.getDefaultOptions(), this.$el.data(), options);    };    Tooltip.prototype.getDefaultOptions = function() {        return TOOLTIP_DEFAULTOPTIONS;    };    Tooltip.prototype.inTrueState  = function() {        for (var key in this.inState) {            if (this.inState[key]) return true;        }        return false;    };    Tooltip.prototype.enter = function(obj) {        var me = obj instanceof this.constructor ? this : $(obj.currentTarget).data('gz.' + this.type);        me.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true;        if (me.getGUID()) return;        clearTimeout(me.delayTimer);        if (!me.options.delay) {            return me.show();        }        if (typeof me.options.delay == 'number' && me.options.delay > 0) {            me.delayTimer = setTimeout(function() {                me.show();            }, me.options.delay);        }    };    Tooltip.prototype.leave = function(obj) {        var me = obj instanceof this.constructor ? this : $(obj.currentTarget).data('gz.' + this.type);        me.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false;        if (me.inTrueState()) return;        clearTimeout(me.delayTimer);        if (!me.options.delay) {            return me.remove();        }        if (typeof me.options.delay == 'number' && me.options.delay > 0) {            me.delayTimer = setTimeout(function() {                me.remove();            }, me.options.delay);        }    };    Tooltip.prototype.toggle = function(e) {        return this[this.inTrueState() ? 'leave' : 'enter'](this);    }    Tooltip.prototype.show = function() {        this.tip();        this.setGUID();        var actualTop  = this.$el.offset().top,            actualLeft = this.$el.offset().left;        this.$tip.find('.tooltip-inner').html(this.getTitle());        this.$tip.addClass(this.options.placement);        this.$el.after(this.$tip);        var elOffset = this.getCalculatedOffset(this.options.placement, actualLeft, actualTop);        this.$tip.attr('tpid', this.getGUID())                 .addClass('fade in')                 .css('left', elOffset.left).css('top', elOffset.top);    };    Tooltip.prototype.remove = function() {        $(this.$tip).remove();        if (this.$tip) this.$tip = undefined;        this.setGUID(false);        return this;    };    Tooltip.prototype.tip = function() {        var me = this;        if (!me.getGUID()) {            me.$tip = $(me.options.templete);            if (me.$tip.length != 1) {                throw new Error('模版顶层元素只能有一个');            }        }        return me.$tip;    };    Tooltip.prototype.getTitle = function() {        return !this.$el.attr('title') ? this.$el.data().originalTitle || '' : this.$el.attr('title');    }    Tooltip.prototype.setContent = function() {    }    Tooltip.prototype.getContent = function() {        return this.options.html ?  this.options.html : this.$el.data().content;    }    Tooltip.prototype.getCalculatedOffset = function(placement, actualLeft, actualTop) {        return placement == 'top'    ? {top : actualTop - this.$tip[0].offsetHeight, left : actualLeft + (this.$el[0].offsetWidth / 2) - (this.$tip[0].offsetWidth / 2)} :               placement == 'left'   ? {top : actualTop - this.$tip[0].offsetHeight / 2 + this.$el[0].offsetHeight / 2, left : actualLeft - this.$tip[0].offsetWidth} :               placement == 'bottom' ? {top : actualTop + this.$el[0].offsetHeight, left : actualLeft + (this.$el[0].offsetWidth / 2) - (this.$tip[0].offsetWidth / 2)} :                                       {top : actualTop - this.$tip[0].offsetHeight / 2 + this.$el[0].offsetHeight / 2, left : actualLeft + this.$el[0].offsetWidth};    };    Tooltip.prototype.getGUID = function() {        return this.$el.data(this.type + 'guid');    };    Tooltip.prototype.setGUID = function(guid) {        guid === false ? this.$el.data(this.type + 'guid', null) : this.$el.data(this.type + 'guid', this.type + parseInt(Math.random() * 100000000)) ;    };    function Plugin(option) {        return this.each(function() {            var $el  = $(this),                data = $el.data('gz.tooltip');            if (!data) $el.data('gz.tooltip', new Tooltip($(this), option));            return $el.data('gz.tooltip');        })    }    $.fn[ext] = Plugin;    $.fn[ext].Constructor = Tooltip; } (jQuery)
0 0
原创粉丝点击