2012-04-19 57 views
17

Có ai biết về phần mở rộng cho thành phần popover của bootstrap twitter tự động thay đổi tùy chọn vị trí để đảm bảo rằng cửa sổ bật lên hiển thị trên màn hình không?Làm thế nào bạn có thể đảm bảo cửa sổ bật lên cửa sổ bật lên twitter được hiển thị?

+0

thể trùng lặp của [Twitter vấn đề vị trí bootstrap popover] (http://stackoverflow.com/questions/8839387/twitter-bootstrap-popover-placement-issue) Không phải là bản sao chính xác, nhưng đủ gần để quan trọng. phần còn lại của vấn đề là vấn đề toán học. –

Trả lời

24

Vị trí có thể là hàm thay vì chuỗi. Một ví dụ về vị trí tự động được viết bởi mỡ và sau đó được chuyển lên phiên bản mới nhất của bootstrap bởi wleeper là một trong các vấn đề github về dự án ở đây: https://github.com/twitter/bootstrap/issues/345

Dưới đây là kết quả của việc lập CoffeeScript để JavaScript:

$("a[rel=popover]").popover({ 
    placement: function(tip, element) { 
    var $element, above, actualHeight, actualWidth, below, boundBottom, boundLeft, boundRight, boundTop, elementAbove, elementBelow, elementLeft, elementRight, isWithinBounds, left, pos, right; 
    isWithinBounds = function(elementPosition) { 
     return boundTop < elementPosition.top && boundLeft < elementPosition.left && boundRight > (elementPosition.left + actualWidth) && boundBottom > (elementPosition.top + actualHeight); 
    }; 
    $element = $(element); 
    pos = $.extend({}, $element.offset(), { 
     width: element.offsetWidth, 
     height: element.offsetHeight 
    }); 
    actualWidth = 283; 
    actualHeight = 117; 
    boundTop = $(document).scrollTop(); 
    boundLeft = $(document).scrollLeft(); 
    boundRight = boundLeft + $(window).width(); 
    boundBottom = boundTop + $(window).height(); 
    elementAbove = { 
     top: pos.top - actualHeight, 
     left: pos.left + pos.width/2 - actualWidth/2 
    }; 
    elementBelow = { 
     top: pos.top + pos.height, 
     left: pos.left + pos.width/2 - actualWidth/2 
    }; 
    elementLeft = { 
     top: pos.top + pos.height/2 - actualHeight/2, 
     left: pos.left - actualWidth 
    }; 
    elementRight = { 
     top: pos.top + pos.height/2 - actualHeight/2, 
     left: pos.left + pos.width 
    }; 
    above = isWithinBounds(elementAbove); 
    below = isWithinBounds(elementBelow); 
    left = isWithinBounds(elementLeft); 
    right = isWithinBounds(elementRight); 
    if (above) { 
     return "top"; 
    } else { 
     if (below) { 
     return "bottom"; 
     } else { 
     if (left) { 
      return "left"; 
     } else { 
      if (right) { 
      return "right"; 
      } else { 
      return "right"; 
      } 
     } 
     } 
    } 
    } 
}); 

nó đang làm việc tốt cho tôi trừ một trường hợp: nếu mục nằm ở góc trên bên phải không có chỗ tốt cho popover xuất hiện đó là một trong những lựa chọn và nó xuất hiện một phần tắt màn hình.

+4

Đây là câu trả lời hay nhưng không giải quyết được vấn đề hoàn toàn. Chiều rộng và chiều cao của chú giải công cụ được mã hóa cứng trong 'actualWidth' và' actualHeight' và không có cách nào để tự động nhận được kích thước của chú giải công cụ trước khi nó được hiển thị. –

+0

@ BjörnLindqvist Đó là một điểm tốt. Tôi đã suy nghĩ về nó trong một thời gian nhưng nó có vẻ như một vấn đề khó khăn để giải quyết bên cạnh việc điều chỉnh các giá trị để phù hợp với popup của bạn (giả sử nó là một kích thước phổ biến). Người ta có thể làm cho nó trong một khung nội tuyến ẩn hoặc làm một số hijinks khác để xác định kích thước nhưng tôi không thể nghĩ ra một cách sạch sẽ để làm điều đó. – Cymen

+0

Đây là một giải pháp tuyệt vời nếu bạn cần lật/định hướng lại cửa sổ bật lên twitter để đảm bảo nó hiển thị. –

12

Đối với những người quan tâm đến giải pháp sẽ thực hiện vị trí mặc định (sử dụng thuộc tính data-placement trên phần tử), tôi đã điều chỉnh câu trả lời tuyệt vời từ Cymen.

Tôi cũng đảm bảo rằng không có ranh giới nào được tính không cần thiết, vì vậy nó sẽ có hiệu suất cao hơn một chút.

$('[data-toggle="popover"]').each(function() { 
    var trigger = $(this); 
    trigger.popover({ 
     animation: true, 
     delay: { show: 0, hide: 0 }, 
     html: true, 
     trigger: 'hover focus', 
     placement: getPlacementFunction(trigger.attr("data-placement"), 283, 117) 
    }); 
}); 

var getPlacementFunction = function (defaultPosition, width, height) { 
    return function (tip, element) { 
     var position, top, bottom, left, right; 

     var $element = $(element); 
     var boundTop = $(document).scrollTop(); 
     var boundLeft = $(document).scrollLeft(); 
     var boundRight = boundLeft + $(window).width(); 
     var boundBottom = boundTop + $(window).height(); 

     var pos = $.extend({}, $element.offset(), { 
      width: element.offsetWidth, 
      height: element.offsetHeight 
     }); 

     var isWithinBounds = function (elPos) { 
      return boundTop < elPos.top && boundLeft < elPos.left && boundRight > (elPos.left + width) && boundBottom > (elPos.top + height); 
     }; 

     var testTop = function() { 
      if (top === false) return false; 
      top = isWithinBounds({ 
       top: pos.top - height, 
       left: pos.left + pos.width/2 - width/2 
      }); 
      return top ? "top" : false; 
     }; 

     var testBottom = function() { 
      if (bottom === false) return false; 
      bottom = isWithinBounds({ 
       top: pos.top + pos.height, 
       left: pos.left + pos.width/2 - width/2 
      }); 
      return bottom ? "bottom" : false; 
     }; 

     var testLeft = function() { 
      if (left === false) return false; 
      left = isWithinBounds({ 
       top: pos.top + pos.height/2 - height/2, 
       left: pos.left - width 
      }); 
      return left ? "left" : false; 
     }; 

     var testRight = function() { 
      if (right === false) return false; 
      right = isWithinBounds({ 
       top: pos.top + pos.height/2 - height/2, 
       left: pos.left + pos.width 
      }); 
      return right ? "right" : false; 
     }; 

     switch (defaultPosition) { 
      case "top": 
       if (position = testTop()) return position; 
      case "bottom": 
       if (position = testBottom()) return position; 
      case "left": 
       if (position = testLeft()) return position; 
      case "right": 
       if (position = testRight()) return position; 
      default: 
       if (position = testTop()) return position; 
       if (position = testBottom()) return position; 
       if (position = testLeft()) return position; 
       if (position = testRight()) return position; 
       return defaultPosition; 
     } 
    } 
}; 
+1

Điều này thật tuyệt vời và nó hoạt động khá tốt với các bản cập nhật tối thiểu. Cảm ơn bạn! – JazzyWhit

+0

hoạt động trên Bootstrap 2 hay chỉ cho 3? – isapir

+0

không thể nói, bạn phải dùng thử –

Các vấn đề liên quan