1

我需要一些关于 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 );

});
4

3 回答 3

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); } );

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

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

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

于 2013-08-23T21:23:52.023 回答
0

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

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

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

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

其中有原型方法createpositiondestroy。然后创建自定义绑定,根据鼠标事件创建和销毁工具提示:

$('[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/Heightandoffset调用。这些函数调用起来可能非常昂贵(性能方面),所以你真的要留意你必须使用它们的次数。

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

旁注 3:我现在在嘲笑自己,因为我进行了这项工作,然后才意识到……您如何在触发mouseenter事件的情况下单击元素?

于 2013-08-23T21:20:32.490 回答
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();
    }
});
于 2013-08-24T20:43:16.607 回答