Как установить данные jQuery () для тега тела iFrame и получить его изнутри iFrame?

Я застрял, пытаясь установить data() на iFrame я создаю.

Это то, что я делаю:

  // 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);
    }
  });

Когда я смотрю на свой iframe и его тег body, attr("foo") правильно установлен, и я также могу утешить его так:

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

но когда я пытаюсь утешить config используя либо data() или же data("config"), вот так:

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

это всегда возвращается undefined

Вопрос:
Почему невозможно установить jQuery data() на фрейме? Или я что-то не так делаю?

Спасибо за помощь!

2 ответа

Решение

JQuery не хранит данные с самим элементом, но в jQuery.cache,

В коде jQuery у вас есть эта часть:

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

Как вы можете видеть, для каждой загрузки jQuery создается уникальное расширение.

Расширение используется как свойство для хранения идентификатора с элементом DOM.

Когда вы храните данные с .data(key,value) в элементе jQuery выполняет следующие шаги:

  1. проверьте, есть ли id хранится с элементом в element[jQuery.expando] если нет, то это создает уникальный id,
  2. проверьте, есть ли запись с jQuery.cache[id] если нет, создайте пустой объект для хранения там данных для элемента.

Так что если вы позвоните .data(key,value) данные хранятся в окне, в котором определен используемый вами экземпляр jQuery.

Если у вас есть объект jQuery в parent и один в iframe у них есть два разных expandos из-за случайного числа. И если вы позвоните .data() от родительского объекта jQuery на элементе iframe, expando родительского используется, и данные хранятся в родительском. Если вы затем используете iframes jQuery, а затем вызвать .dataна том же элементе, что и раньше, jQuery iframe не найдет никаких данных, потому что с одной стороны он имеет другой expando а с другой стороны данные хранятся в родительском окне.

Поэтому, если вы хотите установить данные в iframe, вы должны использовать объект iframes jQuery.$('iframe')[0].contentWindow.jQuery("body").data( ... ) чтобы установить данные, то можно снова извлечь эти данные изнутри iframe, потому что тогда вы используете тот же объект jQuery для установки и чтения данных.

РЕДАКТИРОВАТЬ Одно дополнительное и важное примечание. Поскольку данные хранятся в используемом экземпляре jQuery, вы не должны использовать jQuery для хранения данных в другом контексте. JQuery имеет метод очистки, который вызывается при удалении элементов с помощью jQuery, который удаляет прослушиватели событий и удаляет данные из jQuery.cache, Но если вы используете jQuery для хранения данных для элемента, который находится в другом контексте, этот метод очистки не удастся (например, если вы загрузите другую страницу в iframe). Таким образом, данные будут освобождены только после перезагрузки родительского элемента.

Убедитесь, что ваш селектор jQuery ищет в соответствующей области, предоставив второй параметр $(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'
});

Вот скрипка, где я успешно установил данные в тело iframe, а затем получил их: http://jsbin.com/ecenij/1/edit

Другие вопросы по тегам