Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Задачки на сообразительность (https://javascript.ru/forum/misc/9351-zadachki-na-soobrazitelnost.html)

Kolyaj 12.05.2010 11:16

Задачки на сообразительность
 
Ситуация: ваш скрипт работает в чужой страничке, на которой определены функции addEventListener/attachEvent
<html>
<head>
<script type="text/javascript">
    function addEventListener() {

    }

    function attachEvent() {

    }
</script>
</head>
</html>
Разумеется, они становятся свойствами объекта window.
Задача: повесить обработчик события resize на window.
Скажу сразу, window.onresize не подходит, ибо сильно вторгается в окружение страницы.


Вторая задача более общая. На враждебной странице может быть переопределена любая глобальная функция (encodeURIComponent, например), или метод у какого-нибудь прототипа ([].slice, например).
Задача: "добыть" оригиналы этих функций для использования их в своём скрипте.


Если кто знает решения, или быстро придумал заведомо работающие решения, просьба подождать хотя бы до вечера, пусть другие подумают :)


UPD: В первой задаче не будем учитывать attachEvent.

Gvozd 12.05.2010 11:30

[SPOILER]
буквально вчера-позавчера в одной из тем фигурировал код по этой теме
[/SPOILER]

Kolyaj 12.05.2010 11:33

Gvozd,
мне вот это сообщение напомнило _http://javascript.ru/forum/54878-post42.html . (Форум ссылку ломает)

Gvozd 12.05.2010 11:36

ну а мне другую тему, но указывать не буду, ибо дикий спойлер
хотя, там еще подумать все равно надо, в чистом виде еще не пригодно
чуть попозже напрягу мозги

Octane 12.05.2010 13:00

Либо это просто, либо я чего-то не знаю и можно сделать еще проще :)

Kolyaj 12.05.2010 13:08

Первая очень просто, вторая чуть похитрее. Но просто, это когда знаешь ответ.

Octane 12.05.2010 13:17

Хм… у меня на обе задачи одинаковый ответ:
ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJpZnJhbWUiKSkuY29udGVudFdpbmRvdy5hZGRFdmVudExpc3RlbmVy

Kolyaj 12.05.2010 13:26

Octane,
на первый вопрос это уж слишком грубое решение. А на второй самое то, но не в таком виде конечно.

Skipp 12.05.2010 13:33

window.close()
Подойдёт к обеим задачам!

Kolyaj 12.05.2010 13:35

Skipp,
если уж на то пошло, окно не закроется :)

Riim 12.05.2010 13:38

Нужно просто вспомнить что js - ООП язык, и все легко решается.

Skipp 12.05.2010 13:39

Ну тогда brain.destroy() уж точно подойдёт!

Kolyaj 12.05.2010 13:42

Skipp,
вопрос не о профессиональных качествах того, кто создал такое окружение, а о том, как с таким окружением жить.

Octane 12.05.2010 13:43

Тогда не знаю, что делать с attachEvent для window в IE.

Kolyaj 12.05.2010 13:46

Кстати, живой пример первой задачи: _http://www.kingsland.ru/

MeFCorvi 12.05.2010 13:49

Хм, со второй задачей всё понятно. Для addEventListener тоже есть рабочий вариант, но attachEvent в IE вызвать пока не получилось)

Kolyaj 12.05.2010 13:56

Упс, а attachEvent-то я и не проверял. Вобщем для красоты решения в первой задаче лучше оставить только addEventListener.

Хотя если кто найдёт красивое решение для attachEvent, с удовольствием посмотрим.

Riim 12.05.2010 13:59

Что-то вторая задачка так же как первая решаться не хочет :( .

Riim 12.05.2010 14:19

Вторую тоже решил :) .

Kolyaj 14.05.2010 11:57

Что-то забыл про тему. Итак мои варианты.

1. С addEventListener всё просто, вытаскиваем его у любого элемента и вызываем в контексте window
document.createElement('div').addEventListener.call(window, 'resize', fn, false);



2. С глобальными функциями идеей многие тоже прониклись. Создаём iframe и берём оттуда. Идея проста, реализация сложней.

Во-первых, я уже как-то писал, IE не создает js-контекст на странице, если там нет ни одного скрипта. Т.о. в iframe нужно написать хотябы <body onload=""></body>

Во-вторых, во всех браузерах все эти операции с iframe'ом синхронны, а в Опере, как всегда, всё наоборот, там нужно ждать onload (при этом не во всех браузерах он срабатывает).

В-третьих, после уничтожения iframe (зачем нам его держать в DOM'е?) IE через некоторое время убивает добытые функции. Мне помогло после добытия функций
setTimeout(function() {}, 3600 * 24 * 1000);



Оба эти подхода, кстати, не академические, и вполне себе работают в боевых условиях.

Gvozd 14.05.2010 12:15

Цитата:

Сообщение от Kolyaj
Мне помогло после добытия функций setTimeout(function() {}, 3600 * 24 * 1000);

не совсем понял
это вызывается из контекста убиваемого фрейма?
и в чем смысл?

Kolyaj 14.05.2010 12:30

Нет, там, где функции достаются.
encodeURIComponent = iframe.contentWindow.encodeURIComponent;
Array_push = iframe.contentWindow.Array.prototype.push;

document.documentElement.removeChild(iframe);
setTimeout(function() {}, 3600 * 24 * 1000);


Тут как вариант, я думаю, было бы вынести переменную iframe выше в области видимости, чтобы её GC не собрал. Но мне лучше так, чем лишнюю переменную вытаскивать.

Riim 14.05.2010 17:21

Цитата:

Сообщение от Kolyaj
С addEventListener всё просто, вытаскиваем его у любого элемента и вызываем в контексте window

первое что я попробовал, но у меня как не работало так и не работает:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
	<title>blank</title>
	<script type="text/javascript">

function addEventListener() {}

document.createElement('div').addEventListener.call(window, 'resize', function() {
	alert('OK!');
}, false);

	</script>
</head>
<body>
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
</body>
</html>

e1f 14.05.2010 17:27

Riim, так где именно не работает? У меня в FF и в Опере работает, и Ваш код, и через window.constructor.prototype.addEventListener.call

Riim 14.05.2010 17:41

Цитата:

Сообщение от e1f
У меня в FF и в Опере работает

верю, но у меня ни в FF ни в Chrome не работает, хотя должно. Тот код что выше это ctrl+a => ctrl+c => ctrl+v , т. е. вообще без изменений.

Цитата:

Сообщение от e1f
window.constructor.prototype.addEventListener.call

я так же сделал :) .

со второй задачкой долго пытался что-то такое выдумать: (new window.constructor()).encodeURIComponent , но никак :( .

e1f 14.05.2010 17:46

Riim, хм. Я просто скопипастил код из поста #23, открыл в Лисе, Опере - работает. В Сафари/Хроме -- нет.

Riim 14.05.2010 17:47

Может от кодировки зависит, у меня utf-8.

upd: менял на win-1251, тоже не пашет, копировал со своего поста, опять нет.

e1f 14.05.2010 17:51

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
    <title>blank</title>
    <script type="text/javascript">
    function addEventListener() {
        // nop
    }

    function init() {
        window.constructor.prototype.addEventListener.call(window, 'resize', function() {
            alert('OK!');
        }, false);
    }
    </script>
</head>
<body onload="init()">
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
<br /><br /><br /><br />
</body>
</html>


Так работает в Хроме, не работает в Сафари (что с онлодом, что без -- одинаково)

Riim 14.05.2010 17:53

Блин, ниче я туплю, onresize, а я br-ов нафигачил и колесико мотаю :) .
Я просто 1-й раз с onscroll делал.

e1f 14.05.2010 18:33

Riim, ы :) Бывает. Но все же проблема в Сафари осталась -- онресайз не срабатывает...


Часовой пояс GMT +3, время: 08:20.