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

后端 未结 2 1000
轮回少年
轮回少年 2020-12-15 13:31

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

相关标签:
2条回答
  • 2020-12-15 13:34

    Tried very hard to apply the same popover box to a drop-down box without luck :

    1. It looks like there's no event fires at all for option elements within a drop down select.
    2. The e.target of the hover event on a 'select' element will always be the select element itself ! There's no way you can get a reference to the 'option' tag that is being hovered.
    3. I've also tried wrapping the text in a 'option' element into a 'span' element and try to add a 'hover' or 'mouseover' event listener to that 'span' element. This does not work either.

    When change the drop down into a list, (i.e. adding size="xx" attribute ), option elements can then work as normal elements. I suspect in a drop down boxes, all options are wrapped by the browser into a separated layer. No interaction with the inner elements of a select element is allowed. Please tell me if I am wrong.

    0 讨论(0)
  • 2020-12-15 13:52

    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/

    0 讨论(0)
提交回复
热议问题