Thay đổi vị trí của cửa sổ bật lên Bootstrap dựa trên vị trí X của cửa sổ bật lên liên quan đến cạnh cửa sổ?


83

Tôi đã tìm kiếm khắp nơi trên Internet và trong khi tôi tìm thấy bài đăng stackoverflow này rất sâu sắc Có thể thay đổi vị trí của các cửa sổ bật lên Bootstrap dựa trên chiều rộng màn hình không? , nó vẫn không trả lời câu hỏi của tôi, có thể là do tôi không hiểu vị trí / điểm bù.

Đây là những gì tôi đang cố gắng làm. Tôi muốn vị trí Cửa sổ bật lên của Bản đồ khởi động Twitter là RIGHT trừ khi cửa sổ bật lên của điểm phát sóng sẽ được định vị bên ngoài khung nhìn, khi đó tôi muốn nó được định vị TRÁI. Tôi đang tạo một ứng dụng web trên iPad có các điểm phát sóng, khi bạn nhấn vào một điểm phát sóng, thông tin sẽ xuất hiện nhưng tôi không muốn nó xuất hiện bên ngoài chế độ xem khi cuộn ngang bị khóa.

Tôi nghĩ nó sẽ diễn ra như thế này:

$('.infopoint').popover({
        trigger:'hover',
        animation: false,
        placement: wheretoplace 
    });
    function wheretoplace(){
        var myLeft = $(this).offset.left;

        if (myLeft<500) return 'left';
        return 'right';
    }

Suy nghĩ? Cảm ơn!

Câu trả lời:


177

Tôi chỉ nhận thấy rằng tùy chọn vị trí có thể là một chuỗi hoặc một hàm trả về một chuỗi thực hiện phép tính mỗi khi bạn nhấp vào liên kết có thể bật qua.

Điều này giúp bạn dễ dàng sao chép những gì bạn đã làm mà không có hàm $ .each ban đầu :

var options = {
    placement: function (context, source) {
        var position = $(source).position();

        if (position.left > 515) {
            return "left";
        }

        if (position.left < 515) {
            return "right";
        }

        if (position.top < 110){
            return "bottom";
        }

        return "top";
    }
    , trigger: "click"
};
$(".infopoint").popover(options);

1
Đây là cách tốt nhất vì autokhông phải lúc nào cũng hoạt động hoàn hảo tùy thuộc vào bố cục trang và nội dung bạn đưa vào cửa sổ bật lên.
Bron Davies

Cám ơn vì cái này. Có ổn không nếu chúng tôi sử dụng nó mà không cần bạn?
D.Tate

6
@ D.Tate Tôi tin rằng mọi thứ trên stackoverflow đều có thể sử dụng được mà không cần bất kỳ sự phân bổ nào. Phát điên với nó;)
bchhun

3
Logic của việc lựa chọn là gì left 515&top 110
Murali Murugesan

1
@MuraliMurugesan không có logic nào cả; Tôi chỉ sử dụng những con số được cung cấp trong câu hỏi. Bạn có thể sử dụng bất cứ thứ gì bạn muốn.
bchhun

35

Đối với Bootstrap 3, có

placement: 'auto right'

cái nào dễ hơn. Theo mặc định, nó sẽ ở bên phải, nhưng nếu phần tử nằm ở phía bên phải của màn hình, cửa sổ bật lên sẽ ở bên trái. Nên nó phải là:

$('.infopoint').popover({
   trigger:'hover',
   animation: false,
   placement: 'auto right'
});

2
Tôi đã có kinh nghiệm lẫn lộn với điều này cho đến nay. Tôi chưa xem xét nguồn Bootstrap, nhưng có vẻ như nó chỉ tính đến vị trí của phần tử chứ không phải vị trí hiện có của cửa sổ bật lên. Vì vậy, các phần tử nằm trên cạnh hoặc ngoài rìa cửa sổ tối đa sẽ có cửa sổ bật lên ở cạnh, nhưng các phần tử nằm ngay trên cạnh (ví dụ) sẽ có cửa sổ bật lên dưới màn hình đầu tiên.
Daved

1
Không, nó không phải là câu trả lời được chấp nhận. Tùy chọn "vị trí" không tính đến các cạnh cửa sổ , chỉ tính đến ranh giới vùng chứa / phần tử mẹ. Vì vậy, nếu bạn có ví dụ: 'tự động đầu trang', nó sẽ vẫn hiển thị ở đầu cửa sổ khi bạn cuộn xuống.
rzb

31

Dựa trên tài liệu, bạn có thể sử dụng autokết hợp với vị trí ưu tiên, ví dụ:auto left

http://getbootstrap.com/javascript/#popovers : "Khi" tự động "được chỉ định, nó sẽ tự động định hướng lại cửa sổ bật lên. Ví dụ: nếu vị trí là" tự động bên trái ", chú giải công cụ sẽ hiển thị bên trái khi có thể, ngược lại nó sẽ hiển thị bên phải. "

Tôi đã cố gắng làm điều tương tự và sau đó nhận ra rằng chức năng này đã tồn tại.


2
auto trái cho thanh cuộn ngang
Jitendra Vyas

3
Bạn cũng có thể chỉ định a viewportnếu bạn không muốn nó được tính toán dựa trên cha của các phần tử.
allicarn

5

Vì vậy, tôi đã tìm ra một cách để làm điều này một cách hiệu quả. Đối với dự án cụ thể của mình, tôi đang xây dựng một trang web dành cho iPad để tôi biết chính xác giá trị pixel X / Y sẽ là bao nhiêu để đạt đến mép màn hình. Giá trị thisX và thisY của bạn sẽ khác nhau.

Vì dù sao thì các cửa sổ bật lên cũng đang được đặt theo kiểu nội tuyến, tôi chỉ cần lấy các giá trị bên trái và trên cùng cho mỗi liên kết để quyết định hướng cửa sổ bật lên. Điều này được thực hiện bằng cách thêm các giá trị dữ liệu html5 mà .popover () sử dụng khi thực thi.

if ($('.infopoint').length>0){
    $('.infopoint').each(function(){
        var thisX = $(this).css('left').replace('px','');
        var thisY = $(this).css('top').replace('px','');
        if (thisX > 515)
            $(this).attr('data-placement','left');
        if (thisX < 515)
            $(this).attr('data-placement','right');
        if (thisY > 480)
            $(this).attr('data-placement','top');
        if (thisY < 110)
            $(this).attr('data-placement','bottom');
    });
    $('.infopoint').popover({
        trigger:'hover',
        animation: false,
        html: true
    });
}

Mọi nhận xét / cải tiến đều được hoan nghênh nhưng điều này sẽ hoàn thành công việc nếu bạn sẵn sàng đưa các giá trị vào theo cách thủ công.


2

Câu trả lời của bchhun đã giúp tôi đi đúng hướng, nhưng tôi muốn kiểm tra không gian thực tế có sẵn giữa nguồn và cạnh khung nhìn. Tôi cũng muốn tôn trọng thuộc tính vị trí dữ liệu như một tùy chọn với các dự phòng thích hợp nếu không có đủ không gian. Theo cách đó, "phải" sẽ luôn đi đúng trừ khi không có đủ không gian để cửa sổ bật lên hiển thị ở phía bên phải, chẳng hạn. Đây là cách tôi xử lý nó. Nó hoạt động đối với tôi, nhưng nó cảm thấy hơi cồng kềnh. Nếu bất kỳ ai có bất kỳ ý tưởng nào cho một giải pháp gọn gàng hơn, ngắn gọn hơn, tôi rất muốn xem nó.

var options = {
  placement: function (context, source) {
    var $win, $source, winWidth, popoverWidth, popoverHeight, offset, toRight, toLeft, placement, scrollTop;

    $win = $(window);
    $source = $(source);
    placement = $source.attr('data-placement');
    popoverWidth = 400;
    popoverHeight = 110;
    offset = $source.offset();

    // Check for horizontal positioning and try to use it.
    if (placement.match(/^right|left$/)) {
      winWidth = $win.width();
      toRight = winWidth - offset.left - source.offsetWidth;
      toLeft = offset.left;

      if (placement === 'left') {
        if (toLeft > popoverWidth) {
          return 'left';
        }
        else if (toRight > popoverWidth) {
          return 'right';
        }
      }
      else {
        if (toRight > popoverWidth) {
          return 'right';
        }
        else if (toLeft > popoverWidth) {
          return 'left';
        }
      }
    }

    // Handle vertical positioning.
    scrollTop = $win.scrollTop();
    if (placement === 'bottom') {
      if (($win.height() + scrollTop) - (offset.top + source.offsetHeight) > popoverHeight) {
        return 'bottom';
      }
      return 'top';
    }
    else {
      if (offset.top - scrollTop > popoverHeight) {
        return 'top';
      }
      return 'bottom';
    }
  },
  trigger: 'click'
};
$('.infopoint').popover(options);

1

Bạn cũng có thể thử cái này,

==> Nhận vị trí đích / nguồn trong chế độ xem
==> Kiểm tra xem khoảng trống từ dưới cùng có nhỏ hơn chiều cao chú giải công cụ của bạn hay không
==> Nếu không gian từ dưới cùng nhỏ hơn chiều cao chú giải công cụ của bạn, thì chỉ cần cuộn trang lên

placement: function(context, source){
  //get target/source position in viewport
  var bounds = $(source)[0].getBoundingClientRect();
      winHeight = $(window).height();

  //check wheather space from bottom is less that your tooltip height
  var rBottom = winHeight - bounds.bottom;

  //Consider 180 == your Tooltip height
  //if space from bottom is less that your tooltip height, this will scrolls page up
  //We are keeping tooltip position is fixed(at bottom)

  if (rBottom < 180){
    $('html, body').animate({ scrollTop: $(document).scrollTop()+180 }, 'slow');
  }

  return "bottom";
}

0

Bạn có thể sử dụng tính năng tự động trong vị trí dữ liệu như data-position = "auto left". Nó sẽ tự động điều chỉnh theo kích thước màn hình của bạn và vị trí mặc định sẽ được để lại.


0

Ngoài câu trả lời tuyệt vời của bchhun, nếu bạn muốn định vị absoulte, bạn có thể làm điều này

var options = {
    placement: function (context, source) {
         setTimeout(function () {
               $(context).css('top',(source.getBoundingClientRect().top+ 500) + 'px')
         },0)
         return "top";
    },
    trigger: "click"
};
$(".infopoint").popover(options);

0

Tôi đã giải quyết vấn đề của mình trong AngularJS như sau:

var configPopOver = {
        animation: 500,
        container: 'body',
        placement: function (context, source) {
                    var elBounding = source.getBoundingClientRect();
                    var pageWidth = angular.element('body')[0].clientWidth
                    var pageHeith = angular.element('body')[0].clientHeith

                    if (elBounding.left > (pageWidth*0.34) && elBounding.width < (pageWidth*0.67)) {
                        return "left";
                    }

                    if (elBounding.left < (pageWidth*0.34) && elBounding.width < (pageWidth*0.67)) {
                        return "right";
                    }

                    if (elBounding.top < 110){
                        return "bottom";
                    }

                    return "top";
                },
        html: true
    };

Chức năng này làm cho vị trí của cửa sổ popover nổi Bootstrap đến vị trí tốt nhất, dựa trên vị trí của phần tử.


0
$scope.popoverPostion = function(event){
    $scope.pos = '';

       if(event.x <= 207 && event.x >= 140){
           $scope.pos = 'top';
           event.x = '';
       }
       else if(event.x < 140){
           $scope.pos = 'top-left';
           event.x = '';
       }
       else if(event.x > 207){
           $scope.pos = 'top-right';
           event.x = '';
       }

};

-2

Bạn cũng có thể thử cái này nếu bạn cần nó ở hầu hết các vị trí trong trang.

Bạn có thể cấu hình nó một cách chung chung rồi chỉ cần sử dụng nó.

Bằng cách này, bạn cũng có thể sử dụng phần tử HTML và bất cứ thứ gì bạn muốn :)

$(document).ready(function()
                  {
  var options =
      {
        placement: function (context, source)
        {
          var position = $(source).position();
          var content_width = 515;  //Can be found from a JS function for more dynamic output
          var content_height = 110;  //Can be found from a JS function for more dynamic output

          if (position.left > content_width)
          {
            return "left";
          }

          if (position.left < content_width)
          {
            return "right";
          }

          if (position.top < content_height)
          {
            return "bottom";
          }

          return "top";
        }
        , trigger: "hover"
        , animation: "true"
        , html:"true"
      };
  $('[data-toggle="popover"]').popover(options);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>


<div class="container">
	<h3>Popover Example</h3>
	<a id="try_ppover" href="#" data-toggle="popover" title="Popover HTML Header" data-content="<div class='jumbotron'>Some HTML content inside the popover</div>">Toggle popover</a>
</div>

Thêm vào


Để thiết lập thêm các tùy chọn, bạn có thể vào đây .

Thậm chí nhiều hơn có thể được tìm thấy ở đây .

Cập nhật


Nếu bạn muốn cửa sổ bật lên sau khi nhấp, bạn có thể thay đổi tùy chọn JS để trigger: "click"thích điều này-

        return ..;
    }
    ......
    , trigger: "click"
    ......
};

Bạn cũng có thể tùy chỉnh nó trong quảng cáo HTML data-trigger="click"như thế này-

<a id="try_ppover" href="#" data-toggle="popover" data-trigger="click" title="Popover Header" data-content="<div class='jumbotron'>Some content inside the popover</div>">Toggle popover</a>

Tôi nghĩ rằng nó sẽ là mã định hướng hơn và có thể tái sử dụng nhiều hơn và hữu ích hơn cho tất cả :).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.