2012-10-29 12 views
5

Tôi đã thiết lập nhanh chóng jsFiddle để chứng minh sự cố.Twitter Bootstrap Popovers và chú giải công cụ trên Listbox Các yếu tố tùy chọn hiển thị ở vị trí sai

Khi sử dụng chú giải công cụ hoặc cửa sổ bật lên từ Bootstrap trên phần tử tùy chọn của danh sách chọn, cửa sổ bật lên hoặc chú giải công cụ không hiển thị bên cạnh mục đó, mà là ở phía trên cùng bên trái của trang.

HTML Tôi đang sử dụng là:

<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>​ 

Cuộc gọi javascript là đơn giản:

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

Tôi có thể làm gì để làm cho nó xuất hiện ở đúng nơi?

+0

Điều thú vị là jsFiddle được liên kết dường như đang hoạt động ngay bây giờ. Có lẽ một phiên bản mới hơn đã sửa lỗi này? – SteveShaffer

Trả lời

15

Dự kiến. TB tooltip/popover tính toán vị trí của chúng dựa trên các yếu tố liên quan offsetWidthoffsetHeight. Tùy chọn không có các thuộc tính như vậy, không bao giờ có, do đó, một popover sẽ luôn luôn kết thúc trong một cái gì đó liên quan đến farmost body trái/trên cùng.

Tuy nhiên, bạn có thể đặt cửa sổ bật lên cho chính mình là select. Bind mouseover để chọn, từ đó hiển thị cửa sổ bật lên ở bên phải được điền các thuộc tính dữ liệu cho số option được di chuột.

HTML, làm sạch cho rel="popover""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, thu thập tùy chọn dữ liệu 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'); 
    } 
}); 

một số ngẫu nhiên nên popover biến mất khi chúng tôi rời khỏi chọn

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

không nghĩ rằng nó có thể được thực hiện nhiều đặt cược ter cho danh sách tùy chọn :) Bạn có thể đấu tranh với template, buộc cửa sổ bật lên ít nhiều theo vị trí dọc cho từng tùy chọn theo chỉ mục của nó.

chia hai đang http://jsfiddle.net/mM8sx/


Cập nhật - vấn đề với IE và Chrome trên cửa sổ.
Tôi đã thấy một số tham chiếu đến câu trả lời này, chỉ ra rằng nó không hoạt động trong IE và Chrome trên các cửa sổ. Đó là do thực tế là trên cửa sổ, <option> yếu tố không nhận được sự kiện chuột nào cả. Đây là một "hack" của câu trả lời ở trên, làm cho nó "crossbrowser".

Thử nghiệm thành công với Chrome, FF, IE và Safari trên Windows. Chrome, FF và Opera trên Ubuntu. Ý tưởng là nhắm mục tiêu chính xác <option> trên mousemove (không di chuột qua) bằng cách tính chỉ mục dựa trên các mức độ ảnh clientY/chiều cao của tùy chọn.

$("#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'); 
    } 
}); 

thấy fiddle để biết chi tiết ->http://jsfiddle.net/LfrPs/

+0

Fiddle của bạn hoạt động như dự định, nhưng tôi đã có một câu hỏi tiếp theo. Điều gì sẽ xảy ra nếu tôi không muốn đặt rõ ràng kích thước của lựa chọn? Làm thế nào sau đó tôi vẫn có thể nhận được cửa sổ bật lên với một phần tử chọn thả xuống? – Sam

+1

@Sam, rất thích giải quyết vấn đề này - tiếc là sự kiện 'mouseover' cho' tùy chọn' không được kích hoạt khi 'kích thước' không được đặt. Nó hoạt động trong FireFox, nhưng không phải trong Chrome hoặc Opera (đã thử nghiệm IE), vì vậy bạn không thể xác định cửa sổ nào cần được hiển thị. – davidkonrad

+0

Ý tưởng tuyệt vời, nhưng phiên bản 'mousemove' không hoạt động đáng tin cậy ngay bây giờ trong Firefox và các phiên bản khác không hoạt động với phiên bản 3.x của Bootstrap, trong thử nghiệm của tôi. :( –

2

Cố gắng rất khó để áp dụng cùng một hộp popover đến một hộp thả xuống mà không may mắn:

  1. Dường như không có sự kiện cháy ở tất cả các yếu tố tùy chọn trong một thả xuống chọn.
  2. Mục tiêu e.target của sự kiện di chuột trên phần tử 'chọn' sẽ luôn là chính yếu tố chọn! Không có cách nào bạn có thể nhận được một tham chiếu đến thẻ 'tùy chọn' đang được di chuột.
  3. Tôi cũng đã thử gói văn bản trong phần tử 'tùy chọn' thành phần tử 'span' và cố gắng thêm trình xử lý sự kiện 'di chuột' hoặc 'di chuột' vào phần tử 'span' đó. Điều này không hoạt động.

Khi thay đổi thả xuống danh sách, (sau đó thêm thuộc tính size = "xx"), các yếu tố tùy chọn sau đó có thể hoạt động như yếu tố thông thường. Tôi nghi ngờ trong một hộp thả xuống, tất cả các tùy chọn được gói bởi trình duyệt vào một lớp riêng biệt. Không được phép tương tác với các phần tử bên trong của một phần tử được chọn. Xin vui lòng cho tôi biết nếu tôi sai.