![]() |
|
Модераторы: Sardar, Aliance |
![]()
|
|
| Leviafan |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Доброго времени суток =)
При создании фреймовых документов иногда приходится реализовывать обмен данными между несколькими фреймами в одном окне. Эта проблема решаема и сейчас не вызывает серьёзных трудностей... НО... я так нигде и не увидел способов решения проблемы обмена событиями между фреймами и главным окном. Поэтому предлагаю совместно найти и обсудить возможные решения. ВНИМАНИЕ! На данном этапе меня не слишком волнует кросплатформенность решения, поэтому основным браузером будет считаться IE. === Пример 1. ===
Текущий html-документ является контейнером, к которому прицеплено несколько обработчиков таких как, вызов хэлпа при нажатии F1, обработка нажатия клавиш, обработка движений мыши. Внутренний фрейм, содержимое которого может меняться, является основной частью документа и все активные действия пользователя производятся именно в нём. Загрузка новых страниц в iframe производится через метод в главном документе. !!Хотелось бы чтобы оба документа могли обрабатывать возникающее событие независимо от того, в какой части документа оно было сгенерировано. Особенности: обработку событий может производить только активный документ (который находится в фокусе). События сгенерированные внутри фрейма не попадают во внешний документ. При попытке получить объект event окна фрейма из главного окна (в целях безопасности) возвращается null. Внутренний документ может быть каким угодно, следовательно изменение исходного кода внутреннего документа следует считать невозможным. ИМХО, самым естесственным решением (не нарушая принципов DOM) было бы просачивание событий через границу iframe во внешний документ..... === Пример 2. === В главном окне содержится два фрейма. Требуется при изменении элементов одного врейма каким-то образом менять содержимое элементов второго. Например, при наведении на ссылку в первом врейме во втором выскакивает tooltip с предварительным просмотром содержимого документа по ссылке. Событий по которым будет происходить реакция второго фрейма много, причём заранее тип событий неизвестен! Т.о. нужен диспетчер событий, который будет обрабатывать события и изменять содержимое другого фрейма. Итак, начинаем обсуждение проблемы и поиск возможных решений! |
|||
|
||||
| vasac |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1060 Регистрация: 4.5.2006 Репутация: 13 Всего: 36 |
Здесь вообще проблем не вижу. На конкретное событие происходит конкретная реакция, описываемая в конкретном обработчике. Единственное отличие от "безфреймовой" структуры в том, что обработчик будет выводить тултип не в своем фрейме, а в соседнем.
Ну сами они просачиваться не будут. А ловить все события во фрейме его объектом window и передавать обработчикам в главном документе так же проблем имхо больших нет. Ну и конечно это все для документов с одного домена |
||||
|
|||||
| Leviafan |
|
||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Тогда такой вопрос, а где ты собираешься размещать обработчики?
Давай по порядку. Как именно Ты собираешься ловить события? (Ну, например, где будут находиться обработчики событий внутреннего фрейма?) Не забывай об одной "маленькой" тонкости...
И как будешь передавать обработчикам главного документа информацию о событии?.. (Свойства объекта event) И, если Тебе не трудно, напиши пример, где всё это можно наглядно показать. Вот Тебе заготовка (я постарался разнообразить виды возможных обработчиков): "Главное окно"
"Фрейм frame.html"
Это сообщение отредактировал(а) Leviafan - 23.4.2007, 19:56 |
||||||||||
|
|||||||||||
| vasac |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1060 Регистрация: 4.5.2006 Репутация: 13 Всего: 36 |
Подробно останавливаться сегодня уже влом.
Единственное: Конечно, там, где они будут вызваны. Т.е. в том фрейме в котором происходят события и на тех элементах в которых они происходят. Так же, как и обычно. Если единственное, что тебя смущает, то, что визуальная реакция будет происходить не в этом фрейме, а в соседнем, то на само распространение событий это никак не влияет. Это влияет только на код обработчика. Т.е. он будет отрисовывать окошко (или что там) не в своем фрейме, а в соседнем. Либо передавать управление нужной функции. Ну или можно попытаться сделать так:
здесь windowOtherFrame - ссылка на window другого фрейма, а f - функция-обработчик. сейчас проверить не могу, может и не сработает. Добавлено через 14 минут и 38 секунд Про просачивание. Несомненно, ничего просачиваться дальше само по себе не будет. А вот повесить из родительского окна на элемент window фрейма нужные обработчики можно. И event они будут получать на общих основаниях.
Здесь жду секунду, чтобы содержимое во фрейм подгрузилось. Несоменно в рабочем варианте лучше сделать менее грязный способ. |
||||
|
|||||
| Leviafan |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
vasac, спасибо за ответ, НО надеюсь, Ты всё-таки посмотришь мой пример...
А пока немного откомментирую последнее сообщение. В начале данной Темы я упоминал, что решение будем искать под IE. Поэтому хотелось бы, чтобы твой код соответствовал соглашению... Далее, давай всё же остановимся пока на 1-м примере, т.к. решение второго ИМХО зависит от первого. Теперь о последнем предложении...
Я так понял: Ты предлагаешь ставить обработчик на объект фрейма window. Определяешь его в главном окне. НО!! Пример НЕ работает... И даже если Ты будешь следовать такой логике то, как в таком случае будет выглядеть сам код обработчика (?), ведь он исполняется в контексте внутреннего фрейма и поэтому как минимум обращение к внешним объекта должно проходить так: window.parentWindow.xxx Решение, которое должно получиться должно быть универсальным. Важно, что главное окно и "внутренний мир" фрейма могут содержать свои обработчики... И я так понял твою идею, что... как минимум мы должны переписать все собственные обработчики, адаптируя их под работу в контексте фрейма... А идея решения Такова, что Есть отдельно код главного окна и есть код окна, которое будут загружать во фрейм. Так вот нужно сделать, так чтобы события из фрейма могли просачиваться во "внешний мир", при этом они должны нормально всплывать дальше до корня дерева HTML!! Т.е. нужно реализовать всё так, чтобы не изменять и не выворачивать наизнанку принципы DOM. |
|||
|
||||
| vasac |
|
||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1060 Регистрация: 4.5.2006 Репутация: 13 Всего: 36 |
Посмотрю, но днем.
У меня работает. Конечно, если тестируешь в IE, замени на attachEvent().
В плане контекста объекта (this) обработчик должен выполняться в контексте объекта на который установлен. И в FF в нем и исполняется. А в IE при установке attachEvent присутствует всем известный глюк - исполняется он в контексте window, в котором определен обработчик, т.е. в window главного окна. В плане же исполнительного контекста, обработчик определенный в главном окне, вне зависимости от того, куда будет передан, продолжает работать с контекстом в котором определен, поэтому window и document будут указывать на главное окно. Вызов функций и доступ к переменным, определенным в главном окне, так же происходит без перфикса window.parent.
|
||||||
|
|||||||
| Leviafan |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Спасибо за пример, Идея ясна...
Только есть одна странность: почему onclick срабатывает всего лишь раз?! И всё же хотелось бы обсудить вариант с естесственным просачиванием. Т.к. у прицепления всех внешних обработчиков на фрейм есть свои очевидные недостатки... (некоторые аргументы приведены выше) Это сообщение отредактировал(а) Leviafan - 25.4.2007, 20:52 |
|||
|
||||
| Leviafan |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Всем привет!!
Вот, после длительного перерыва решил вернуться к обсуждению данной темы. На этот раз выкладываю для обсуждения мою статью "Событийная модель и Межфреймовое взаимодействие", посвящённую проблемам, описанным выше. Это сообщение отредактировал(а) Leviafan - 30.5.2007, 19:42 |
|||
|
||||
| Zeroglif |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Прочитал половину, удивился, полезли вопросы.
Есть ли ссылка на более подробное разъяснение "приёма" от IE? Или я совершенно не понял идеи.
Обработчик стоит на элементе (iframe), объект события живёт в главном окне, зачем тогда его искать в окне фрейма?
Обработчик записан непосредственно в html элемента, отсюда появляется сложноуловимая scope chain, достаточно убрать префикс window (оставить только onload), чтобы всё заработало.
Можно, не трогая document.body.innerHTML, отражать нужную информацию в отдельно взятом элементе, просто чтобы не сбрасывался обработчик... |
||||||||
|
|||||||||
| Leviafan |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
У меня встречный вопрос: "Насколько хорошо Ты знаешь объектную модель документа (в частности у IE)"? Поясняю: для каждого из окон определена своя модель обработки событий. Фактически, фрейм - это окно в окне, следовательно его "жизнь" никак не связана с внешним документом. Как я понял, Ты считаешь, что внутренний документ при возникновнеии каких либо событий использует некий Глобальный (для всех фреймов и главного окна) объект event! НО ЭТО НЕ ТАК!! Каждое окно представлено объектом window, которое позволяет получить доступ к информации о событии в данном окне через ссылку на соответствующий объект event. Поэтому моим первым шагом была проверка: возможен ли извне доступ к информации о событиях внутреннего окна, т.е. могу ли я получить доступ к объекту event в контексте окна фрейма.
Спасибо конечно за "сложноуловимую scope chain", вот именно на такие вещи нужно в первую очередь обращать внимание!
А чё это он вдруг сбрасывается??? - Меня же интересует именно такой вопрос!! Кто мне гарантирует, что в какой-то другой ситуации обработчик снова не сбросится? ================================================================= И ещё раз спасибо за критику!! Для меня это очень важно... |
||||||
|
|||||||
| vasac |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1060 Регистрация: 4.5.2006 Репутация: 13 Всего: 36 |
Левиафан, спокойствие. Это же САМ Zeroglif
Думаю, на достаточно большое количество процентов это сможет гарантировать работа через стандартные методы DOM, а не через innerHTML при котором браузеру приходится сбрасывать часть DOM-дерева, убивать привязанные обработчики, разбирать новый код и цеплять его в нужном месте. |
||||
|
|||||
| Zeroglif |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Я считаю, что ты ошибочно видишь фрейм (окно) там где есть фрейм (элемент), ещё раз оцени, где живёт объект event в этих конкретных примерах в IE. А ты пытаешься это сразу объяснить некими спланированными действиями разработчиков браузера:
Сомневаюсь.
Должно. Но не описывается. Ты регистрируешь обработчик древним способом inline плюс к этому это ещё и весёлый onload плюс к этому это ещё и iframe со своей двойной сущностью и после этого надеешься, что будет ясная твёрдая логика. Да, это ещё и IE к тому же со своими приколами вроде frames(0).event (круглые скобки - это было от души придумано)...
Вышеописанное стечение ужасных обстоятельств. В scope chain есть body, чьё свойство onload ты и видишь, window.onload видимо вернулся в своё дефолтное состояние (null), почему так - не знаю (регистрация обработчика не-inline эту проблему должна снять). p.s. Статья построена на слабых примерах, возникающие сюрпррррызы ты списываешь на логику межфреймого взаимодействия вокруг событий. Попробуй просто исключить тонкие места, не трогая, например, innerHTML всего документа в тестах, исключив устаревшие или IE-only штучки и т.д. |
||||||||
|
|||||||||
| Leviafan |
|
||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Быть может Ты и прав, тогда поправь меня, если я ошибаюсь: frames(0) или frames[0], обращение по id - фрейм как окно, указатель this при инлайновом определении обработчика и обращение через getElementsByTagName("iframe") - фрейм как элемент.
Ну это ведь так?! Видно на примерах... Приведу ещё один, который всё же позволяет получить доступ к объекту event окна фрейма:
"Пара слов" по поводу установки обработчиков: я провожу исследование работы данной архитектуры, а, значит, установка обработчиков проверенными и стандартными путями не позволила бы мне выявить некоторые тонкие моменты...
Спасибо, я протестировал - действительно так...
Ну что ж... буду исправляться P.S. А Ты можешь предложить более изящный способ решения поставленной в статье задачи, чем в итоге получился у меня?? |
||||||||||
|
|||||||||||
| Zeroglif |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Всё так.
Да не в том дело, что где-то позволено, а где-то нет, а в том, что тут у тебя этот обработчик висит на документе фрейма, а в тех примерах (где был onload) на элементе в главном окне. Подробную не видел, общие фразы встречал.
Ты имеешь в виду:
Один и тот же обработчик вешается (руками или скриптом) на каждое окно, при наступлении события вызывается функция, допустим, из главного окна. Посмотри ещё раз, что писал здесь vasac, дело не в просачивании, а в том, что отдельное событие в отдельном фрейме можно поймать и инициировать любое нужное действие с учётом, того, что окна умеют друг с другом общаться. |
||||||
|
|||||||
| Leviafan |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Всё, понял
В моём случае такое решение неприемлемо... Поясню точной формулировкой того, что от меня требуется в реализации одного небольшого проекта: Итак, нужно реализовать многовкладочную систему просмотра документов, а именно: каждый документ загруженного сайта представлен фреймом, растянутым на всю клиентскую область окна браузера. Для переключения между открытыми вкладками использовался тот же механизм, что и комбинация alt + Tab в Windows. (Первоначально использовалось сочетание ctrl + Tab, но после появления IE 7 пришлось изменить на alt+Q) При переходе по ссылке на странице создавался новый фрейм, в который загружался требуемый документ. Получается что активной частью страницы был фрейм, а для того, чтобы все события возникали именно в контексте фрейма он должен был находиться в фокусе. Но тогда обработчики основного документа не будут получать события клавиатуры, а это необходимо, т.к. переключением вкладок, очевидно, занимается основной документ. Единственным корректным решением для данного случая является реализация свободного всплытия событий из документа фрейма за его границу. На данный момент движок сырой и есть куча недоработок, но если хотите заценить, то вам сюда: [Оболочка для Учебника по Скриптам]. Замечания: работает корректно пока только под IE, для открытия новой вкладки с номером n используйте цифры от 1 до 7, переключение между открытыми вкладками - alt+Q, в обратную сторону - alt+shift+Q; прошу заметить, что происходит та сортировка вкладок, что и при переключении приложений по alt+Tab; для закрепления панельки испльзуйте alt+ctrl, для открытия/скрытия вспомогательного меню при открытой панельке переключения вкладок либо щёлкните по активной иконке, либо нажмите alt+PgDown/PgUp; старый хелп - F1. Надеюсь что критика будет не слишком жестокой... |
||||
|
|||||
| Zeroglif |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
||||
|
||||
| Leviafan |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 19.2.2006 Где: г. Екатеринбург Репутация: нет Всего: нет |
Это заставляет писать код фрейма с учётом того, что он будет загружаться в главное окно. Разаработкой проекта занимется не один человек, загружемые страницы в общем могут иметь совершенно различное содержимое. Так что изменение кода страниц, загружаемых во фрейм не приветствуется!! А, значит, нужно адаптировать извне каждый подгружаемый фрейм, т.е. производить одни и те же действия каждый раз при создании новой вкладки. Я же действую по-другому: устанавливаю для элемента iframe компоненту поведения, расширяющую текщую модель просачивания событий. Таким образом вся логика обработки событий клавиатуры остаётся в основном документе. Сам подумай, должна ли каждая вкладка знать о сочетаниях клавиш для управления состоянием основного документа?! И... небольшое усложнение: представь себе что в документе фрейма на необходимых нам клавишах (например, на Q) установлены какие-то свои обработчики, вызов которых нежелателен при вызове панельки переключения вкладок. --> Необходима фильтрация, значит более тонкое вмешательство в логику обработчиков внутреннего документа, но без изменения его кода. Хммм... и последнее: попробуй в тестовом файлике написать обработку сочетания alt+Q - столкнёшься с неприятной особенностью (не забудь включить громкость). Это сообщение отредактировал(а) Leviafan - 8.6.2007, 22:01 |
|||
|
||||
![]()
|
| Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | JavaScript: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |