jquery position with collision. add class when collision detected
Asked Answered
S

3

7

I am using jquery-ui's autocomplete box with collision to display the autocomplete either above or below the input. What I would like is to add a class to the autocomplete element if a collision is detected so i can customize the css a bit if it is above vs below. This seems like it should be simple enough to do, but I can't seem to figure out any way to make it happen.

Solleret answered 8/11, 2012 at 23:29 Comment(0)
K
11

A better solution is to make use of second argument in callback. From jQueryUi documentation:

The second provides feedback about the position and dimensions of both elements, as well as calculations to their relative position. Both target and element have these properties: element, left, top, width, height. In addition, there's horizontal, vertical and important, giving you twelve potential directions like { horizontal: "center", vertical: "left", important: "horizontal" }.

As it says, there is a horizontal and a vertical attribute inside second argument, which you can use to find out whether the element is flipped or not. So you may write something like this:

$("#someId").dialog({
      position: {
      my: 'left top',
      at: 'right top',
      collision: 'flip flip',
      of: $('#' + someElementID),
      using: function (obj,info) {
          if (info.vertical != "top") {
              $(this).addClass("flipped");
          } else {
              $(this).removeClass("flipped");
          }
          if (info.horizontal != "left") {
              $(this).addClass("flipped");
          } else {
              $(this).removeClass("flipped");
          }
          $(this).css({
            left: obj.left + 'px',
            top: obj.top + 'px'
          });
      }
},
Karyoplasm answered 6/3, 2014 at 2:36 Comment(2)
I read about this in the docs, but when I tried it, I'm not getting a second argument in my using callback at all. Do you know if this is something added in a more recent version of jQuery UI? Unfortunately, we're stuck on the relatively ancient 1.8.2 right now.Tillo
I'm not sure about it, but I think I've tested it with 1.8.12 or 1.10.3 However, it doesn't seem like a thing that's introduced with a minor change of version!Karyoplasm
M
4

Rather than using the 2 solutions mentionned here, I prefer create a custom flip handler which use the default one and detect if there is a change.

Here is how I'm doing it:

$.ui.position.custom = {
    left: function(position, data) {
        var initPos = position.left;
        $.ui.position.flip.left(position, data);
        if (initPos != position.left) {
            data.elem.addClass('tooltipFlipLeft');
        } else {
            data.elem.removeClass('tooltipFlipLeft');
        }
    },
    top: function(position, data) {
        var initPos = position.top;
        $.ui.position.flip.top(position, data);
        if (initPos != position.top) {
            data.elem.addClass('tooltipFlipTop');
        } else {
            data.elem.removeClass('tooltipFlipTop');
        }
    }
};

Then I use it when using the position function:

me.position({
    of: opener,
    my: 'right bottom',
    at: 'center top',
    collision: 'custom'
});

The only relevant line here is the one with collision.

Musician answered 27/1, 2015 at 16:5 Comment(2)
This was the only working solution. Beside it seems a good approach to extend existing logic like mentioned here. USE THIS!Derzon
This answer worked perfectly for me. It's the only solution I could get working where you can tell which direction the flip occurred. Thanks!Coconut
W
2

You should use the using callback of the position

Here is a possible solution , suppose you open a dialog...

$("#someId").dialog({
position: {
    my: 'left top',
    at: 'right top',
    collision: 'flip flip',
    of: $('#' + someElementID),
    using: function (obj) {
        if (obj.left < $('#' + someElementID).offset().left) {
            $(this).addClass("flipped");
        } else {
            $(this).removeClass("flipped");
        }
        //decide if dialog is being opened flipped from buttom to top
        if ((obj.top + 50) < $('#' + someElementID).offset().top) {
            $(this).addClass("flipped_top");
        } else {
            $(this).removeClass("flipped_top");
        }
        $(this).css({
            left: obj.left + 'px',
            top: obj.top + 'px'
        });
    }
},
    ...

Instead of adding / removing class to $(this) which is the dialog itself , you can add / remove the class to some other element...

Westnorthwest answered 17/1, 2013 at 10:1 Comment(2)
What is someElement ?Derzon
any other element that you wan't to reflect the fact that the dialog is flipped (can't think of a scenario atm)Westnorthwest

© 2022 - 2024 — McMap. All rights reserved.