Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
236 views
in Technique[技术] by (71.8m points)

javascript - Twitter Bootstrap Popovers and Tooltips on Listbox Option Elements showing in the wrong place

I have setup a quick jsFiddle to demonstrate the problem.

When using either a tooltip or a popover from Bootstrap on an option element of a select list, the popover or tooltip doesn't show next to the item, but rather in the extreme upper left of the page.

The HTML I am using is:

<select size="5" id="testList">
    <option value="1" rel="popover" data-original-title="This is item 1." data-content="Lots of stuff to say" style="color: red; ">Item 1</option>
    <option value="2" rel="popover" data-original-title="This is item 2." data-content="Lots of stuff to say" style="color: green; ">Item 2</option>
    <option value="3" rel="popover" data-original-title="This is item 3." data-content="Lots of stuff to say" style="">Item 3</option>
    <option value="4" rel="popover" data-original-title="Blah" data-content="Lots of stuff to say" style="color: orange; ">Item 4</option>
</select>?

The javascript call is simple:

$(function () {
    $('#testList option[rel=popover]').popover({
        placement: 'right',
        trigger: 'hover'
    });
});  ?

What can I do to make it show up in the right place?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is expected. TB tooltip / popover calculates their position based on the associated elements offsetWidth and offsetHeight. Option does not have such properties, never has, so a popover will always end up in something relative to the farmost body left/top.

However, you can place a popover for the select itself. Bind mouseover for the select, from that show a popover to the right populated with data attributes for the option being hovered.

HTML, cleaned for rel="popover" and "data-original-title"

<select size="4" id="testList">
<option value="1" data-title="This is item 1." data-content="Lots of stuff to say 1" style="color:red;">Item 1</option>
<option value="2" data-title="This is item 2." data-content="Lots of stuff to say 2" style="color:green;">Item 2</option>
<option value="3" data-title="This is item 3." data-content="Lots of stuff to say 3" style="">Item 3</option>
<option value="4" data-title="Blah" data-content="Lots of stuff to say 4" style="color:orange;">Item 4</option>
</select>??

bind mouseover, collect option data-attribues, show popover

$("#testList").on('mouseover', function(e) {
    var $e = $(e.target); 
    if ($e.is('option')) {
        $('#testList').popover('destroy');
        $("#testList").popover({
            trigger: 'manual',
            placement: 'right',
            title: $e.attr("data-title"),
            content: $e.attr("data-content")
        }).popover('show');
    }
});

some cleanup so the popover disappears when we leave the select

$("#testList").on('mouseleave', function(e) {
    $('#testList').popover('destroy');
});

doesnt think it can be done much better for an option list :) You could struggle with template, forcing the popover to more or less follow the vertical position for each option by its index.

forked code http://jsfiddle.net/mM8sx/


Update - issues with IE and Chrome on windows.
I have seen some references to this answer, pointing out that it was not working in IE and Chrome on windows. It is due to the fact that on windows, <option> elements doesnt receive mouse events at all. Here is a "hack" of the above answer, making it "crossbrowser".

Sucesssfully tested with Chrome, FF, IE and Safari on Windows. Chrome, FF and Opera on Ubuntu. The idea is to target the correct <option> on mousemove (not mouseover) by calculating the index based on the mouseevents clientY / height of a option.

$("#testList").on('mousemove', function(e) {
    if (!isWindows) {
        var $e = $(e.target);
    } else {
        var newIndex = Math.floor(e.clientY/optionHeight);
        if (newIndex === index) return;
        index = newIndex;
        $e = $(this).find('option:eq('+index+')');
    }    
    if ($e.is('option')) {
        $('#testList').popover('destroy');
        $("#testList").popover({
            trigger: 'manual',
            placement: 'right',
            title: $e.attr("data-title"),
            content: $e.attr("data-content")
        }).popover('show');
    }
});

see fiddle for details -> http://jsfiddle.net/LfrPs/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...