Javascript工具提示悬停并单击

时间:2013-08-23 20:18:43

标签: javascript jquery tooltip

我需要一些javascript工具提示的帮助。我下面的代码在悬停时工作得很好,但是我不能将函数放在外面,所以可以通过单击调用它。在函数中,只有用于计算工具提示位置及其显示方式的东西,并且可以正常工作。

非常感谢你的帮助。

var targets = $( '[rel~=tooltip]' ),
    target  = false,
    tooltip = false,
    title   = false;

targets.on( 'mouseenter', function()
{
    target  = $( this );
    tip     = target.attr( 'title' );
    tooltip = $( '<div id="tooltip"></div>' );



    if( !tip ) {
        return false;
    }

    target.removeAttr( 'title' );
    tooltip.css( 'opacity', 0 )
           .html( tip )
           .appendTo( 'body' );

    var init_tooltip = function()
    {
        containerList = $('.container').find('.listImages');

        if( containerList.width() < tooltip.outerWidth() * 1.5 )
            tooltip.css( 'max-width', containerList.width() / 2);
        else
            tooltip.css( 'max-width', 340 );

        var pos_left = target.offset().left + ( target.outerWidth() / 2 ) - ( tooltip.outerWidth() / 2 ),
            pos_top  = target.offset().top + target.outerHeight(),
            pos_right = target.offset().right + ( target.outerWidth() / 2 ) - ( tooltip.outerWidth() / 2 );

            console.log(pos_right)

        if( pos_left < containerList.offset().left )
        {
            pos_left = target.offset().left;
            tooltip.addClass( 'left' );
        }
        else {
            tooltip.removeClass( 'left' );
        }

        if( pos_left + tooltip.outerWidth() > containerList.offset().left + containerList.width() )
        {
            pos_left = target.offset().left - tooltip.outerWidth() + target.outerWidth();
            tooltip.addClass( 'right' );
        }
        else {
            tooltip.removeClass( 'right' );
        }


        if( pos_top < 0 )
        {
            var pos_top  = target.offset().top + target.outerHeight();
            tooltip.addClass( 'top' );
        }
        else {
            tooltip.removeClass( 'top' );
        }

        tooltip.css( { left: pos_left, top: pos_top } )
               .animate( { top: '+=10', opacity: 1 }, 50 );
    };

    init_tooltip();
    $( window ).resize( init_tooltip );

    var remove_tooltip = function()
    {
        tooltip.animate( { top: '-=10', opacity: 0 }, 50, function()
        {
            $( this ).remove();
        });

        target.attr( 'title', tip );
    };



    target.bind( 'mouseleave', remove_tooltip );

});

3 个答案:

答案 0 :(得分:0)

我根据您在问题中提供的内容创建了一个小提琴:http://jsfiddle.net/R26Ba/1/

但是,因为我没有完整的页面实现,所以它基于理论而不是实际可以在小提琴中使用。

基本上我所做的是创建一个Tooltip对象:

function Tooltip(el) {
    //...
}

其中包含原型方法createpositiondestroy。然后创建了基于mouseevents创建和销毁工具提示的自定义绑定:

$('[rel~=tooltip][title]').on({
    'tooltip.create': function() {
        $(this).trigger('tooltip.destroy');

        activeTooltip = new Tooltip(this);
    },
    'tooltip.destroy': function() {
        if(activeTooltip) {
            activeTooltip.destroy();
        }
    },
    'mouseenter': function() {
        $(this).trigger('tooltip.create');
    },
    'mouseleave': function() {
        $(this).trigger('tooltip.destroy');
    },
    'click': function(e) {
        e.stopPropagation();

        if(activeTooltip && activeTooltip.el == this) {
            $(this).trigger('tooltip.destroy');
        } else {
            $(this).trigger('tooltip.create');
        }
    }
});

$(document.body).on('click', function() {
    if(activeToolTip) {
        activeTooltip.destroy();
    }
});

$(window).on('resize', function() {
    if(activeTooltip) {
        activeTooltip.position();
    }
});

另外,附注:您可能会注意到我清理了很多outerWidth/Heightoffset来电。这些功能可以非常昂贵(性能明智)来调用,所以你真的想留意你必须使用它们的次数。

附注2:您可能还想为jQuery使用resizeEnd事件插件。这将限制对position方法的调用量,并将提升整体性能。

旁注3:我现在正在嘲笑自己,因为我接受了这个努力然后才意识到......你如何点击一个元素而不用导致mouseenter火灾事件?

答案 1 :(得分:0)

如果要重用init_tooltip函数,可以在mouseenter事件之外声明它,并传递两个参数:target和tooltip。

init_tooltip函数定义如下:

var init_tooltip = function(target, tooltip)

然后在您的mouseenter事件中,您将拥有:

init_tooltip(target, tooltip);
$( window ).resize( function () { init_tooltip(target, tooltip); } );

这样,您也可以将它用于click事件处理程序,如下所示:

targets.on('click', function () {
    tooltip = $( '<div id="tooltip"></div>' );
    init_tooltip($(this), tooltip);
});

您可能需要在点击事件中重现您的逻辑,以确定它是否应显示或隐藏工具提示。

答案 2 :(得分:0)

这就是我现在可以做的事情,但是点击和鼠标移动再次出现问题。我改进了代码,但这并不完美。

$( "body" ).append( '<div id="tooltip"></div>' );

var activeTooltip = null,
    $tooltip = $('#tooltip'),
    $containerList = $('#content .listImages');

function Tooltip(el) {
    this.el = el;
    this.$el = $(el);
    this.text = this.$el.attr('data-content');

    this.create();
}

$.extend(Tooltip.prototype, {
    'create': function () {
        this.$el.removeAttr('data-content');

        $tooltip.css({
            'opacity': 0
        }).text(this.text);

        this.position();
    },
        'position': function () {
        var conWidth = $containerList.width(),
            conOffset = $containerList.offset(),
            toolWidth = $tooltip.outerWidth();

        if (conWidth < $tooltip.outerWidth() * 1.5) {
            $tooltip.css('max-width', conWidth / 2);
        } else {
            $tooltip.css('max-width', 340);
        }

        var elOffset = this.$el.offset(),
            elWidth = this.$el.outerWidth(),
            elHeight = this.$el.outerHeight(),
            pos_left = elOffset.left + (elWidth / 2) - (toolWidth / 2),
            pos_top = elOffset.top + elHeight;

        if (this.$el.offset().left + (elWidth / 2) - ($tooltip.outerWidth() / 2) < conOffset.left) {
            pos_left = this.$el.offset().left;

            $tooltip.addClass('left');
        } else {
            $tooltip.removeClass('left');
        }

        if (elOffset.left + (this.$el.outerWidth() / 2) - ($tooltip.outerWidth() / 2) + $tooltip.outerWidth() > $containerList.offset().left + $containerList.width()) {
            pos_left = this.$el.offset().left - $tooltip.outerWidth() + this.$el.outerWidth();
            $tooltip.addClass('right');
        } else {
            $tooltip.removeClass('right');
        }

        if (elOffset.top + this.$el.outerHeight() < 0) {
            pos_top = elOffset.top + this.$el.outerHeight();

            $tooltip.addClass('top');
        } else {
            $tooltip.removeClass('top');
        }

        $tooltip.css({
            'left': pos_left,
            'top': pos_top
        })
            .animate({
            'top': '+=10',
            'opacity': 1
        }, 50);
    },
        'destroy': function () {
        $tooltip.animate({
            'top': '-=10',
            'opacity': 0
        }, 50);

        this.$el.attr('data-content', this.text);

        activeTooltip = null;
    }
});

var savelastTooltip, activeSaveTooltip = false;

$('[rel~=tooltip][data-content]').on({
    'tooltip.create': function () {
        $(this).trigger('tooltip.destroy');
        activeTooltip = new Tooltip(this);
    },
    'tooltip.destroy': function () {
        if (activeTooltip) {
            activeTooltip.destroy();
        }
    },
    'mouseenter': function () {
        $(this).trigger('tooltip.create');
    },
    'mouseleave': function () {
        $(this).trigger('tooltip.destroy');
        if(true === activeSaveTooltip)
        { 
            activeTooltip = new Tooltip(savelastTooltip);
        }
    },
    'click': function (e) {
       e.stopPropagation();
       activeSaveTooltip = true;
       savelastTooltip = this;

        if (activeTooltip && activeTooltip.el != this) {
            $(this).trigger('tooltip.destroy');
        } else if(activeTooltip && activeTooltip.el == this) {
            $(this).off('mouseleave');
        } else {
            $(this).trigger('tooltip.create');
        }
    }
});

$(window).on('resize', function () {
    if (activeTooltip) {
        activeTooltip.position();
    }
});