Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery offset is not giving the expected value if margin is used on body element in IE

I am trying to set the position of a contextMenu and using Jquery jquery.ui.position. For ContextMenu I am using this libaray:-

https://swisnl.github.io/jQuery-contextMenu/demo

I am trying to position a ContextMenu as follow:-

$(document).ready(function() {

    $.contextMenu({
        selector: 'td[id="tdMenu"]',
        trigger: 'left',
        position: function (opt, x, y) {

            try {

                opt.$menu.position({
                    my: 'right top',
                    at: 'right bottom',
                    of: $("#tdDiv")
                });

            } catch (e) {

            }

        },
        items: {

            "0": { name: "Hi" },
        }
    });
});

HTML is as follow:-

<table border="0" cellpadding="0" cellspacing="0" width="100%">
        <tr>
            <td id="tdDiv" style="background-color: yellow;">
                Menu Div
            </td>
        </tr>
         <tr>
            <td id="tdMenu">
                Click Here
            </td>
        </tr>
    </table>

In IE 11 once the page will load and once I click on td with id tdMenu jquery.ui.position does not calculate the offset correctly. On second click it calcultes correctly.

What I have found is inside jquery.ui.position its calculating a offset as follow:-

function getDimensions( elem ) {
    var raw = elem[0];
    return {
        width: elem.outerWidth(),
        height: elem.outerHeight(),
        offset: elem.offset() // On first click its calculating wrong value and on second it calculates correctly.
    };
}

I have also given margin to body as:-

<body style="margin: 0px;">

If I will remove this margin it calculates correctly on first click also.

I cannot remove body margin. What can be the work around for this ?

like image 972
Afnan Ahmad Avatar asked Jan 22 '19 08:01

Afnan Ahmad


1 Answers

From what you've posted, it looks like a classic case of computing an offset value before the page finished loading all styles and content, resulting in a wrong offset value at the time your contextMenu is initialized.

Replacing

$(document).ready(function() {
  // executes when DOM parser reaches </html> tag

  $.contextMenu({/* your stuff here */})
});

with

$(window).on('load', function() {
  // executes when all external resources/references (images, scripts,
  // stylesheets, iframes, etc...) have finished loading

  $.contextMenu({/* your stuff here */ })
});

is likely to solve your problem, but without a Minimal, Complete, and Verifiable example it's impossible to test and make sure it works for your case.


Note: The above solution will delay the initialization of $.contextMenu() until the page has loaded. If your page takes a long time to load all its resources and you want to have $.contextMenu initialized before that moment, a workaround is to init it on $(document).ready and update it on $(window).load:

function cMenu() {
    $.contextMenu({
      /* your stuff here */ 
    });
}
$(document).ready(cMenu);
$(window).on('load', cMenu);

In reality, chances are there is only one item in the page which influences that offset (most likely a stylesheet). If you which one it is (by elimination, disabling stuff in your page), you don't even have to wait for the rest to load, you can simply bind the re-run of your function on that elements' onload event.

like image 114
tao Avatar answered Nov 02 '22 07:11

tao