Как установить данные 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 выполняет следующие шаги:
- проверьте, есть ли
id
хранится с элементом вelement[jQuery.expando]
если нет, то это создает уникальныйid
, - проверьте, есть ли запись с
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