How to set jQuery data() on an iFrame body tag and retrieve it from inside the iFrame?

ぐ巨炮叔叔 提交于 2019-12-11 20:33:00

问题


I'm stuck trying to set data() on an iFrame I create.

This is what I'm doing:

  // options > my configuration object
  // options.src = eg "path/foo.html"
  // options.id = uuid
  // options.parent = $(elem)
  // options.param = JSON object 

  newHTML = document.createElement("iframe");
  newHTML.setAttribute("src", options.src);
  newHTML.setAttribute("frameborder", 0);
  newHTML.setAttribute("seamless", "seamless");
  newHTML.setAttribute("data-id", options.id);

  newParentElement = options.parent.parent()[0];
  options.parent.replaceWith( newHTML ); 

  // select 
  newRootElement = newParentElement.querySelectorAll(
    '[data-id="'+options.id+'"]'
  );

  // add configuration 
  $( newRootElement[0] ).load(function () {
    var newElement = $(this);
    if (options.param) {
      newElement.contents().find("body").attr("foo","bar").data("config", options.param);
    }
  });

When I look at my iframe and it's body tag, the attr("foo") is correctly set and I can also console it like so:

  console.log(newElement.contents().find("body").attr("foo"));

but when I try to console the config using either data() or data("config"), like so:

  console.log(newElement.contents().find("body").data("config"));

it always returns undefined

Question:
Why is it not possible to set a jQuery data() on an iFrame? Or am I doing something wrong?

Thanks for helping out!


回答1:


jQuery does not store the data with the element itself but in jQuery.cache.

In jQuery code you have this part:

jQuery.expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" )

As you can see for each jQuery load a unique expando is created.

The expando is used as property to store an identifier with the DOM element.

When you store data with .data(key,value) in an element jQuery does the following steps:

  1. check if there is an id stored with the element in element[jQuery.expando] if not it creates an unique id.
  2. check if there is an entry with jQuery.cache[id] if not create an empty object for storing the data for the element there.

So if you call .data(key,value) the data is stored in the window the jQuery instance you use is defined in.

If you have a jQuery object in the parent and one in the iframe these have two different expandos because of the random number. And if you call .data() from the parents jQuery object on an element of the iframe, the expando of the parent is used and the data is stored within the parent. If you then use the iframes jQuery and then call .dataon the same element as before the iframe's jQuery would not find any data because it has on the one hand a different expando and on the other hand the data is stored in the parent window.

So if you want to set data in the iframe you should use the iframes jQuery object. $('iframe')[0].contentWindow.jQuery("body").data( ... ) to set the data, then it is possible to retrive that data from inside of the iframe again, because then you use the same jQuery object for setting and reading the data.

EDIT One additional and important note. Because the data is stored with the used jQuery instance, you should not use jQuery to store data in another context. JQuery has a cleanup methode that is called when you remove elements with jQuery which removes event listeners and removes the data from jQuery.cache. But if you use jQuery to store data for an element that is in another context this cleanup method will fail ( e.g. if you load another page in the iframe). So the data then will only be freed if you reload the parent.




回答2:


Make sure your jQuery selector is looking up in the relevant scope by providing second parameter to $(selector, scope).

$(function() {
    var scope = $('iframe')[0].contentWindow.document; // <iframe>
    $('body', scope).data('id', 'some id');            // set data on body of iframe 
    console.log($('body', scope).data('id'));          // ==> 'some id'
});

Here is a fiddle where I successfully set data to iframe's body and then retrieve it: http://jsbin.com/ecenij/1/edit



来源:https://stackoverflow.com/questions/16689280/how-to-set-jquery-data-on-an-iframe-body-tag-and-retrieve-it-from-inside-the-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!