0

Well, here's my first ever question - and sadly a newbie - but if i take you through my thinking i'm hoping someone can help me extend my skills and get this layout sorted?

  • i'm using bootstrap
  • in one page i have a series of divs that work perfectly with isotope ( + infinite scroll )
  • as a user hovers over each div, i want a popover to display more info about the element
  • this i can get to work using data-container="body"

So far so good..

Next i found out the correct placement of each of the elements using:

 $('#container').isotope({
 itemSelector: '.item',
 itemPositionDataEnabled: true
 })
 // log position of each item
 .find('.item').each(function(){
 var item_position = $(this).data('isotope-item-position');
 console.log('item position is x: ' + item_position.x + ', 
 y: ' + item_position.y);});

(from http://isotope.metafizzy.co/docs/options.html#itempositiondataenabled )

So now the issue i've come up against is how to affect the placement of the popover dependent on the values the isotope log is giving me - thus if a element is placed to the far right of the viewport - then the popover displays to the left or below (and not hidden out of sight).

Appreciate any help and guidance on this - pretty much tried any answers i've found here but i can't get them to work..

(I've put together a quick (and for some reason the isotope aint working) fiddle to try to explain what i am trying to achieve here: http://jsfiddle.net/watcher/Kv8Bw/1/ )


Next attempt post @Bass help :

@bass - Appreciate the help - but i think my js knowledge is letting me down here (included some logic from another answer - [link]Changing the position of Bootstrap popovers based on the popover's X position in relation to window edge? ) have been pluggin away at this:

 $("#popover").popover({
 trigger: "hover focus"
 }); 

 var tmp = $.fn.popover.Constructor.prototype.show;
 $.fn.popover.Constructor.prototype.show = function () {

 var items = Array('top','bottom','left','right');   
 var position =  $(this).data('isotope-item-position');

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

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

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

 return "top";
 }


 tmp.call(this);

But my issue is (i think that the isotope is returning the values of ALL my items rather than the one i am hovering over - any suggestions?)

Community
  • 1
  • 1
watcher
  • 1
  • 1
  • use `var position = this.$element.data('isotope-item-position');` and replace `return "left";` with `this.options.placement = 'left'` etc. – Bass Jobsen Jul 05 '13 at 00:00

1 Answers1

1

Callback function after tooltip / popover is created with twitter bootstrap? shows how to exend the javascript. Use this to add the placement based on the calculated position before show:

var tmp = $.fn.popover.Constructor.prototype.show;
$.fn.popover.Constructor.prototype.show = function () {

  /* random placement add your calcuations based $(this).data('isotope-item-position'); on here: */  
  var items = Array('top','bottom','left','right');
  this.options.placement = items[Math.floor(Math.random()*items.length)]; 
  // from: https://stackoverflow.com/questions/5915096/get-random-item-from-array-with-jquery

  tmp.call(this);
}

see: http://bootply.com/66412

Update

In your extend show function this.$element is a reference to the element which triggered the popover. You can use this to get its position (http://api.jquery.com/position/).

 var tmp = $.fn.popover.Constructor.prototype.show;
 $.fn.popover.Constructor.prototype.show = function () {

 var position = this.$element.position();
 if(position.top<50){this.options.placement = 'bottom'}
 else if(position.top>150){this.options.placement = 'top'}
 else if(position.left<200){this.options.placement = 'right'}
 else {this.options.placement = 'left'}

 tmp.call(this);
 }

see: http://bootply.com/66412 (also updated)

https://stackoverflow.com/a/12656175/1596547 will give a better solution by calling placement as a function:

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

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

    if (position.top > 800){
        return "top";
    }

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

    //if (position.left < 485) {
    else
    {   
        return "right";
    }

}
, trigger: "click",
title: 'popover',
content: 'content of a popover'
};
$('.element').popover(options);
}

popover() is not a 'live' function. When new elements are insert to the DOM you will have to call popover again. See http://www.infinite-scroll.com/ "all options" infinite scroll has an optional callback when new content is successfully loaded in. Use this to call popover() again. See: http://bootply.com/66524 (bootply don't load the second page).

complete source:

function setpopover()
{

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

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

        if (position.top > 800){
            return "top";
        }

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

        //if (position.left < 485) {
        else
        {   
            return "right";
        }

    }
    , trigger: "click",
    title: 'popover',
    content: 'content of a popover'
    };
    $('.element').popover(options);
}   


    $(function(){

      var $container = $('#container');

      $container.isotope({
        itemSelector : '.element',
        itemPositionDataEnabled: true
      });

      $container.infinitescroll({
        navSelector  : '#page_nav',    // selector for the paged navigation 
        nextSelector : '#page_nav a',  // selector for the NEXT link (to page 2)
        itemSelector : '.element',     // selector for all items you'll retrieve
        loading: {
            finishedMsg: 'No more pages to load.',
            img: 'http://i.imgur.com/qkKy8.gif'
          }
        },
        // call Isotope as a callback
        function( newElements ) {
          $container.isotope( 'appended', $( newElements ) );
          setpopover();
        }
      );

    setpopover()



    });

NOTE: the position of your element is giving by jQuery's position (). This will give you the current position of an element relative to the offset parent. Contrast this with .offset(), which retrieves the current position relative to the document. see: http://api.jquery.com/position/. isotope-item-position will give the same position. To set the position relative to the visible windows see:

etc.

Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
  • Appreciate the help - but i think my js knowledge is letting me down here had another attempt but am getting some errors in my console.. and have tried a few things but still no joy – watcher Jul 04 '13 at 22:17