Pull to refresh

Comments 45

Всё круто, но ифреймы… как-то я сомневаюсь, что они прям уж так необходимы для организации виджетов. Js-api и дивы милее сердцу.
Собственно, изначально разрабатывал для того, чтобы довести до ума виджеты в Piwik — они там были сначала флешовые — было проще, потом они сделали рендеринг всех графиков без флеша и соответственно виджеты стали в iframe.

Нужно было с минимальными затратами сделать, чтобы вставленные на страницы сайта виджеты из статистики (у меня пивик используется в качестве инструмента статистики для поддоменов пользователей) выглядели нормально и автоматически ресайзились под размер.

Тратить свое время на переписывание движка виджетов в пивике в данный момент я не готов, а написать 2 небольших js-файла, которые надо просто подключить и все становится как хочется — почему нет.

Может еще кому пригодится (в piwik я уже отправил патч)
Если у вас виджет запускается через яваскрипт — то если тот сайт, с которого он запускается взломали — считайте и ваш также взломали (ну либо виджет со стрёмного ресурса взяли). Можно будет сделать любые изменения на вашей странице и, кроме того, вытянуть куки пользователя.

Если сделать window.parent у ифрэйма, который с другого домена — бравзер ругнётся.
ифреймы… как-то я сомневаюсь, что они прям уж так необходимы для организации виджетов. Js-api и дивы милее сердц

При необходимости размещать защищённые данные в виджетах на чужих доменах иного решения просто нет. Если вы разместите виджет в диве и примете с сайта виджета защищённые данные с каким угодно шифрованием, тело виджета должно содержать расшифровку, следовательно, данные будут уже не защищены от взлома и использования третьими лицами.

При размещении в фрейме вы спокойно работаете с данными и выдаёте наружу только результат, через мембрану фрейма, по postMessage. Защита, разумеется не от пользователя, а от вирусных скриптов, к которым пользователь отношения не имеет. Если его страница заражена, через фрейм скрипты не проберутся, данные виджета будут в безопасности. С дивами этого добиться невозможно.
Iframe будет жить всегда. Также, как и два бессмертных элемента верстки &nbsp; и <br />.
В xhtml нет &nbsp; там &#160;
UFO just landed and posted this here
я таких не встречал, Opera как натыкается начинает всю страницу парсить как html, a FF вовсе отказываются отображать страницу.
UFO just landed and posted this here
UFO just landed and posted this here
А лучше отказаться от &nbsp; от греха подальше :)
UFO just landed and posted this here
Лично я вместо пробела пользую распорку (прозрачный gif 1х1px или растягиваю его до нужных мне размеров).
Спасибо огромное! Как раз была проблема смены высоты фрейма в зависимости от содержимого.
Переписал код на основной странице на jQuery и добавил animate(). Пока что не видел проблем с погрешностью все ресайзится точно.
если пользоваться jQuery на дочерней странице то погрешности и не должно быть
Хм, почему-то вот это вот:

pm({
	target: window.frames[frame.id],
	type:   "register", 
	data:   {id:frame.id},
	url: frame.contentWindow.location
});


не заработало в ОгнеЛисе. Такое ощущение, что Firefox не умеет window.frames['frame_id']. Переписал так:

var target = undefined;
for (var i=0; i<window.frames.length;i++){
	if (window.frames[i].frameElement == frame){
		target = window.frames[i];
		break;		
	}
}
pm({
	target: target,
	type:   "register", 
	data:   {id:frame.id},
	url: frame.contentWindow.location
});
У меня работает — попробуйте фрейму кроме id добавить еще аттрибут name, идентичный этому id
Да, спасибо, совсем забыл про имя. Похоже Firefox ведет себя правильно, а Chrome слегка упрощает жизнь разработчику, выбирая айфреймы также и по id.
В яндексе можно найти множество решений этой проблемы, но большинство из них обладают одной проблемой: они не поддерживают возможность менять размеры окна когда содержимое iframe и родительский элемент находятся на разных доменах.

Видимо искать лучше в гугле, потому что когда мне надо было какое-то кроссдоменное решение, я нашёл это:
benalman.com/code/projects/jquery-postmessage/examples/iframe/
По сути то же самое, что и у вас (postMessage с фоллбеком на location.hash), только сделано 3 года назад :)
По сути тоже самое, но требует jQuery в дочернем и родительском документе.

Мое решение обходится без него (хотя конечно присутствие jQuery в дочернем документе упрощает дело)
Ну и еще мое решение лучше тем, что позволяет без обработки напильником расположить на странице любое количество фреймов — достаточно кажому iframe прописать id, name и зарегистрировать (FrameManager.registerFrame(this)) его.

Но все равно спасибо за ссылку.
Я делал реализацию на postMessage + хак с window.opener в старых ослах (как реализовано в Open Social). Соответственно, никаких таймаутов, хешей, 1 скрипт на все страницы.
К сожалению, не знаком с Open Social. Поделитесь информацией с хаком window.opener?

Таймаут нужен для отслеживания изменения высоты документа внутри фрейма, насколько мне известно, по-другому это никак не отследишь — onresize срабатывает при изменении размеров окна, а не документа.
Хак заключается в том, что осел позволяет менять свойство opener объекта window у созданного фрейма:
iframe.contentWindow.opener = {
  postMessage: function (data, domain){};
};


Соответственно, из фрейма делаем уже кроссбраузерный вызов:
window.opener.postMessage('data', '*');


Причем, как советует гугл, объект для opener лучше создавать через vbscript из-за соображений безопасности (каких конкретно не помню):
function onMessage(evt, domain) {}; // Обработчик postMessage, в осле evt == evt.data

window._onMessage = onMessage;
window.execScript(
  'Private onMessage\n' +

  'Class PostMsg\n' +
    'Public Sub postMessage(data, domain)\n' +
      'Call onMessage(data, domain)\n' +
    'End Sub\n' +
  'End Class\n' +

  'Set onMessage = window._onMessage\n' +
  'Set window._onMessage = New PostMsg', 'vbscript');


Ну а window._onMessage присваивается как opener в созданные фреймы.
Аналогичное решение на юзерскрипте делалось в HabrAjax для кнопки Google Plus для передачи количества «лайков» наружу. Кто заинтересуется, может скрипт там посмотреть, он без сторонних библиотек типа postMessage.js, всё на виду. А вообще, планирую на этой неделе написать статью (уже написана) по этой же теме с проекцией на юзерскрипты, потому что из-за них в Хроме есть баг передачи данных через фрейм, который там обойдён.
#site1
document.domain = 'com'

#site2
document.domain = 'com'

Таким скриптом вы можете очень хорошо положить #site1, особенно если он вам не принадлежит. Вот сделали такую глупость, а потом вебмастер #site1 не может понять, почему в IE он создаёт frame, пытается к нему достучаться и получает Security Exception.
по какой причине не может достучаться? Все может.
и можно делать domain='com' только при выполнении условия каких либо
это только IE касается чтоли? меня ie вообще никоим образом не интересует.
IE пользуется значительная часть интернет обывателей. Так что когда речь идёт о массовых и кроссбраузерных решениях, то что конкретно вас ie не интересует, никого больше не интересует.
я не говорил о кроссбраузерных решениях, у меня сейчас есть своя четкая задача под один только хром поэтому я и сказал что мне не важен ие. хотя я и забыл что топик о решении в целом.
Не замеряли быстродействие такого метода? Сколько времени занимает один сеанс запрос-ответ между айфреймами? Например, у Facebook JS SDK есть проблема, что фенкция запроса параметров из iFrame занимает от 500мс и до бесконечности (FB.Canvas.getInfo), что очень замедляет работу приложения.
UFO just landed and posted this here
Один из самых интересных моментов в этой задаче — общение между доменами, вы скинули на отдельную библиотеку, остальное достаточно просто, и задачу эту не раз уже решали в любом сервисе, который так или иначе держит у себя внешние приложения. См, например метод gadgets.window.adjustHeight в opensocial вообще и в apache shindig в частности. Интереснее было бы, если бы вы предложили архитектуру для предоставления API фреймам внутри сайта для общения с контейнером.
Так postMessage это фактически и есть простая обертка (API), позволяющая общаться фреймам внутри сайта с контейнером, а также окнам браузера между собой.

Задачу решать-то решали, но вот найти решение в открытом доступе было достаточно сложно (например, если я никогда не пользовался opensocial — откуда мне знать, что я там смогу найти ответ на мой вопрос?)
Теперь решение есть, и судя по количеству добавлений в избранное — оно достаточно востребованное.
Как вообще изменить высоту этого iframe на iPad?
В нём он всегда растягивается по высоте содержимого и никак иначе =(
Как я понял, проблема в том, что мобильный webkit (на ios, android и т.д.) не имеет нормальной возможности скроллить что-то внутри элемента с фиксированной шириной/высотой, поэтому там все растягивается.

Тем не менее, есть решение:
iScroll
Классный метод взаимодействия между iframe-ми. Спасибо за статью и пример. Очень помогло.
postmessage.freebaseapps.com

Выдаёт 404. Обновите ссылочку в статье?.. :)
Sign up to leave a comment.

Articles