1

I'm simply trying to get the top, left, etc position of an element when in the admin backend...

function my_backend_assets() {
    wp_enqueue_script(
        'my-editor-js',
        plugins_url( '/src/editor.js', dirname( __FILE__ ) ),
        array( 'jquery' ),
        filemtime( plugin_dir_path( __FILE__ ) . '/src/editor.js' )
    );
}
add_action( 'admin_enqueue_scripts', 'my_backend_assets', 99999 );

And my js

$( document ).load(function() {

  var $test = $(".my-div").offset();

  console.log( $test.top );

});

I get Uncaught TypeError: Cannot read property 'left' of undefined

Element my-div exists. I can log it it fine. The script loads in the backend. Jquery works... I don't understand why I can't get the offest() of elements.

More details:

I'm loading my custom js in the Wordpress edit page (when eidting a page)

I'm trying to get the offset of any UI element within the editor page. For example the editor text area. It is not returning anything. Only with a timeout function it works.

I am using the latest Wordpress which has the Gutenberg editor.

CyberJunkie
  • 21,596
  • 59
  • 148
  • 215
  • Try adding the last parameter on the wp_enqueue_script to `TRUE`. `wp_enqueue_script( 'my-editor-js', plugins_url( '/src/editor.js', dirname( __FILE__ ) ), array( 'jquery' ), filemtime( plugin_dir_path( __FILE__ ) . '/src/editor.js' ), TRUE );` – disinfor Dec 28 '18 at 19:23

3 Answers3

2

Cannot read property 'left' of undefined necessarily means that $(".my-div").offset() is returning undefined.

Probably, the $(".my-div") is not matching an element when it's being executed...

Now, the why part of that is what it hinges on! You say that you can log it fine. I'm assuming that means that you're able to open up the developer tools in your browser and get results from putting that same code into the console.

A possible troubleshooting tactic:

Wrap a setTimeout() around the callback function inside $(document).load, and run it 5s after. This is a hacky workaround that could help you understand wether or not the .my-div element is being added to the DOM sometime after the ready

That being the case, look into how/where your .my-div element is being added and hook your JS execution to an event triggered by that process instead of $(document).load

Anyway - the troubleshooting code:

$(document).load(function() {
  setTimeout(function() {
    var $test = $(".my-div").offset();
    console.log($test.top);
    if ($(".my-div").length > 0) {
      console.log('.my-div was able to be located in the DOM, 5s after `$(document).load`');
    }
  }, 5000);
});
Cameron Hurd
  • 4,836
  • 1
  • 22
  • 31
  • Hello Cameron. Thank you for the answer! With the timeout function it seems to work. The elements seem to appear after the page loads. I tried an on click event on an element in the wordpress editor with a simple console message to test and nothing happened. I tried `.click(function() {` and `.on('click', function () {` The test however works on front end pages. – CyberJunkie Dec 29 '18 at 07:59
  • Could you perhaps amend your question with more data about what admin page this is all on? And how, exactly, the `.my-div` is being added to the DOM? (a 3rd party plugin, custom code, etc.) – Cameron Hurd Dec 29 '18 at 16:45
  • Ok I added more details at the end of my question. – CyberJunkie Dec 29 '18 at 17:15
  • 1
    This is the closest answer to correct, although I would possibly suggest using a "no-conflict safe" document ready / load: `(function( $ ) { $(document).load(function() { // More code using $ as alias to jQuery }); })(jQuery);` – random_user_name Dec 31 '18 at 23:49
2

You are most probably firing the script BEFORE the page has completely loaded, hence jQuery can not find the element in the time of script execution.

Tl:DR; There are few items that I would do differently and I use them as a rule of thumb in wp .

  • Specify jQuery instead of $. ( known issue in wp )
  • Enqueue the scripts at the footer ( hooking wp_footer() action )
  • wrap jQuery firing with jQuery(document).ready(function ($) { ... });

A bit longer explanation :

1- In wp it is better to use the jQuery keyword.

This is because wp works in compatibility mode or noConflict(); by default.

You can find more info in this question, this or many others. Although not your error - still a good practice.

2- the wp_enqueue_script() has the following syntax :

wp_enqueue_script( string $handle, string $src = '', array $deps = array(), string|bool|null $ver = false, bool $in_footer = false)

and as you can see at the last parameter, $in_footer = false the default is loading scripts at the header and not footer.

It is a good practice for debugging to make sure your script is loading last...

3- The third has to do with WHEN your code fires ( and also handles the first to some degree ) .

see this question

The Difference between $(document).ready() and $(window).load() functions is that the code included inside $(window).load() will run once the entire page(images, iframes, stylesheets,etc) are loaded whereas the document ready event fires before all images,iframes etc. are loaded, but after the whole DOM itself is ready

You can find a lot of info about it here on stackoverflow

As far as your code goes :

 wp_enqueue_script( 'my-editor-js', 
    plugins_url( '/src/editor.js', dirname( __FILE__ ) ), 
    array( 'jquery' ), 
    filemtime( plugin_dir_path( __FILE__ ) . '/src/editor.js' ), 
    ,'1.3',TRUE );

where '1.3' can be any version or FALSE as default and

   jQuery(document).ready(function ($) {

      var $test = jQuery(".my-div").offset();

      console.log( $test.top );

    });

would surprise me if didn't work ...

Obmerk Kronen
  • 15,619
  • 16
  • 66
  • 105
1

The first issue is that there is nothing matching you jQuery selector. Moreover, I would highly recommend you to write your JS not with $ but with jQuery like so :

jQuery( document ).load(function() {
    var $test = jQuery(".my-div").offset();
});

Depending if you load in header or footer : https://digwp.com/2011/09/using-instead-of-jquery-in-wordpress/

Maxime Culea
  • 109
  • 7