логин: 
<< предыдущая заметкаследующая заметка >>
06 января 2010
вопрос про document.write

Сделал почти openid-авторизацию. Вышла очень красивая штука — раскрывается маленькое окошечко как для правки, в нем все вводишь, и без перезагрузки страницы (если openid — то с мгновенным возвратом на нее же) все срабатывает. Показать пока не могу, потому что не решил факин факин идеологическую проблему — что, черт возьми, делать с теми, кто уже залогинен, а теперь перелогинивается. Но эту идеологию я решу.

Проблема в другом. Выяснилось, что существует куча мелкого кода — javascript, style и т.п., который может понадобиться посетителю раз в жизни — например, если он нажал "залогиниться" и у него стали разворачиваться окна. Зачем это говно внедрять в страницу, если оно понадобится раз в жизни? Не лучше ли его получить аяксом? Чуете, куда я клоню?

Так появилась интересная идея: сделать простую javascript-процедурку, которая бы получала от сервера по яксу инструкции, скрипты, стили, открывала вспомогательные окошечки, проверяла правильность данных, получала снова по аяксу что надо, и все за собой убивала лишнее. Типа, захотелось пользователю отредактировать свои пользовательские данные — ткнул в ссылку, раскрылось внешнее окошечко, поработал, закрыл, и продолжает писать коммент. Другой пример: захотелось админу во время набора поста поискать фоточку в своем фотоальбоме и вставить ее. Ткнул в ссылку, раскрылось окошко, в нем подгрузилось все нужное... И так далее. (К слову, поглядите модельку — так мне мыслится удобная аякс-работа с фотоальбомами: http://lleo.aha.ru/blog/tree/tree.html — реально шарится по существующим на сервере директориям.)

В общем, удивительные раскрываются перспективы. И сделать-то это просто. И, главное, сел вот я и сделал с полпинка. Одна лишь проблема: ну не могу понять, как мне заставить браузер исполнить произвольный текст javascript, как если б он был на странице изначально! Поясню на примере:

Имеется текст скрипта: var scripttext = " alert('Бугагашечки!'); alert('Снова бугагашечки!'); ";
Мы даем команду: document.write('<scr'+'ipt>' + scripttext + '</scri'+'pt>');
И скрипт становится частью страницы и выполняется! Также можно добавить в код страницы новые стили и прочее.

Но это сработает только в случае, если не окончилась загрузка страницы. Если же страница уже целиком готова, а document.write() выполнился от действия пользователя (нажал ссылку), то он сбросит всю страницу. И это не бага, а документированное свойство document.write(). Как быть? Как это побороть?

Как и каким способом на javascript можно сделать так, чтобы добавился и выполнился новый javascript, имеющийся пока в виде голого текста, не сбрасывая при этом страницу? Кто подскажет?

<< предыдущая заметка следующая заметка >>
пожаловаться на эту публикацию администрации портала
Страницы, которые привлекли мое внимание за последние дни, рекомендую:
2017-11-22 В июне 1982
архив ссылок
Оставить комментарий
Windows Firefox
0
0
batc0h
Функция eval() за такое ответственна.
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Ага, спасибо!!! А можно только выполнить код? А подгрузить функции чтобы использовать в будущем - через eval никак?
Запросто. Просто запихиваете функции в объекты, а потом используете.

myfuncs.func1 = function (param) { ... };
myfuncs.func2 = function () { ... };
myfuncs.func3 = function (param1, param2) { ... };

Или более красиво:

myfuncs = {
func1 : function (param) {
...
}
,
func2 : function () {
...
}
};

Этот текст запихиваем в eval() и потом используем нужные функции, например myfuncs.func1('Бла-бла-бла');
0
0
LLeo Nokia (#3043)
Как-как, простите? Вот через точечку? В ней весь смысл, выходит? Потому что иначе у меня функции не сохранялись.
Да, именно так. Соль в том, что в eval нельзя загнать объявление глобальной функции, а определение поля/метода объекта — запросто.
0
0
Leonid Kaganov
Кажется я начинаю прозревать.

Смотрите:

<script>
var s1='f1=function(p){alert(p)};'
var s2='function f2(p){alert(p)}'
</script>

<p><input type=button onclick='eval(s1);' value='set f1'>
<input type=button onclick='f1(1);' value='f1'>

<p><input type=button onclick='eval(s2);' value='set f2'>
<input type=button onclick='f2(2);' value='f2'>

С f1 все работает. С f2 - не работает. Почему? Мне непонятна логика JS. Осталось понять, во всех ли браузерах работает f1. Если да - то это сильно упрощает дело, и моя громоздкая система по загрузке скриптов через жопу становится ненужной.
Выше написал, почему так. И так работает во всех браузерах.
0
0
Leonid Kaganov
А можно заодно еще вопрос?

Могу я средствами JS установить для DIV параметр zindex? Смысл в том, что я отныне и в будущем не хочу ограничивать движок в количестве раскрываемых окон. Мало ли, захочется одновременно писать три комментария, вызывая дополнительные панели и получая сообщения... Но хочется, чтобы каждое окошко было на экране чуть выше предыдущего.

И еще вопрос: не подскажете ли универсальную функцию для перетаскивания окошка (DIV) по экрану? Понятно, что надо обработчик мыши повесить по некой области и нажатой кнопке, но как имено это лучше сделать...
1. Да, конечно. document.getElementById('mydiv').style.zIndex = '100';

2. Вот простенький примерчик:

<style> div#dragme { position:absolute; width:300; height:300; background-color:red; cursor:move; user-select:none; -moz-user-select:none; -khtml-user-select:none; } </style>
<script>
var _moving=false, _x=0, _y=0;
function startMove(e)
{
if(!e) e = window.event; // IE fix
_moving=true;
_x = e.offsetX ? e.offsetX : e.layerX;
_y = e.offsetY ? e.offsetY : e.layerY;
}
function stopMove() { _moving=false; }
function doMove(e,d)
{
if(!e) e = window.event; // IE fix
if(_moving) { d.style.left=e.clientX-_x; d.style.top=e.clientY-_y; }
}
</script>

<div id="dragme" unselectable="on" onmousedown="startMove(event)" onmouseup="stopMove()" onmousemove="doMove(event,this)"></div>
0
0
Leonid Kaganov
Спасибо огромнейшее!!! Теперь можно грабить корованнны!

PS: Вопросик последний: а вот у меня такая магическая комбинация встроена в страницу:

// координаты мыши
var mouse_x=mouse_y=0;

document.onmousemove = function(e){ if(!e) e=window.event;
if(e.pageX || e.pageY) { mouse_x=e.pageX; mouse_y=e.pageY; }
else if (e.clientX || e.clientY) {
mouse_x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
mouse_y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
}
};

Правильно ли я понимаю, что:

1. Координаты мыши можно, не парясь, брать оттуда готовые?

2. Или кошернее не мучать мышь глобальной обработкой мыши, а всякий раз брать event по щелчку, как у вас?

3. Правильно ли мне кажется, что конструкция _e.offsetX?e.offsetX:e.layerX менее кроссбраузерна, чем та, что у меня сейчас? Ибо она менее наворочена, что странно.
0
0
Leonid Kaganov
Ой, layerX еще какой-то... "понапридумывали блять говна Сталина на них нет"(с)Арканоид
В первый вариант вкралась небольшая неточность.
Сначала надо определить саму переменную myfuncs, а потом определять её свойства:

myfuncs = {};
myfuncs.func1 = ...
0
0
Leonid Kaganov
и "myfuncs = {};" я тоже через eval() вызвать могу?
Да, конечно :)
Linux Firefox
0
0
batc0h
Через document.write не представляю как сделать. Может быть стоит держать на странице пустой блок <div id='buffer'></div>, а все необходимое подгружать в него через document.getElementById('buffer').innerHTML? А потом innerHTML = '', когда оно больше не нужно. А выполнять, да, с помощью eval("Какой-то код").
Windows Opera
1
0
batc0h
> [url=http://lleo.aha.ru/blog/2009/12/30.html#c446]Как удобней?[/url]
Так, как сделано в основном дневнике - желтым квадратиком в календаре выделяется дата текущей заметки. Как-то удобней и наглядней.
Вот примерчик:
Windows Opera
0
0
batc0h
И еще по дизайну.
не знаю, как в других браузерах, а в Опере ссылка на комментарий стоит вплотную к ссылке на все комментарии. Тоже небольшое неудобство. :)
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Честно говоря, мне вообще надоел этот дизайн шизофренических рамочек. Но на что его сменить - не знаю. С уважением смотрю, как работает Pavl0ff.
Windows
0
0
batc0h
Да - eval(scripttext)
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Ага, спасибо! А функции подгружать - отдельно надо?
Windows Firefox
0
0
batc0h
Подгружаются функции точно так же, через eval() - он любой JavaScript примет :)
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Да, но они потом не отзываются. В смысле, не "сохраняются".
Windows Firefox
0
0
batc0h
Но, удобнее чем через eval, подгружать функции из нормального файла на сервере. Вот пример из интернетов:

function createScript(src, charset){
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('charset', charset);
script.setAttribute('src', src);
// InsertBefore for IE.
// IE crashes on using appendChild before the head tag has been closed.
var head = document.getElementsByTagName('head').item(0);
head.insertBefore(script, head.firstChild);
}
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Ага, спасибо!
Windows Firefox
0
0
batc0h
Действительно, и определение функции через eval() и через добавление тега SCRIPT живёт до первой перезагрузки страницы. Но HTML не предоставляет нам иных средств - такой он по дизайну stateless бездушный. Впрочем если вы найдёте решение, буду только рад узнать о таком :)

Можно, конечно, извернуться - писать заглушки навроде этой (не проверял):

// index.html
if(!destroy_the_world) var destroy_the_world = function(date) {
if(файл destroy.js НЕ подгружен) { подгрузить }
destroy_the_world(date) // главное в цикл не впасть изза ошибок
}

// destroy.js
if(!destroy_the_world) var destroy_the_world = ''
destroy_the_world = function(date) {
alert(date + '!!!')
}

Но, уж не знаю, стоит ли тогда овчинка...
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
С овчинкой щас разберемся! Мне уже давно хотелось навести с ней порядок. Почти готово с овчинками.

Скажите лучше вот чего: а есть ли способ установить новые стили? В смысле, сервер по аяксу прислал какие-то данные. Как запустить скрипты - я понял и сделал. Как подстыковать новые процедуры из file.js - тоже понял. А вот как добавить дополнительные style?
0
0
Leonid Kaganov
Вообще у меня идея была изначально не грузить никаких скриптов в страницу. На фига они пользователю, если он зашел прочесть текст, прокрутит до конца и уйдет, не выполнив никакого действия? А вот если он начал какое-то действие, для которого требуются скрипты, то их подгрузить. Для начала подгрузить скрипт аякса... А дальше - через него подгружать все необходимое.
Windows Firefox
0
0
batc0h
На тот же манер что и с JS:

var headID = document.getElementsByTagName("head")[0];
var cssNode = document.createElement('link');
cssNode.type = 'text/css';
cssNode.rel = 'stylesheet';
cssNode.href = 'FireFox.css';
cssNode.media = 'screen';
headID.appendChild(cssNode);
Linux
whois*: title='{#countryname}
Чертаново{Россия'> {city:|:{#countryname}|*:Чертаново{Россия|}}
0
0
Спасибо!!! Оно так прекрасно получается, что и не описать.
функция eval("alert('bugaga')")?
document.write видимо только через innertext/innerhtml/DOM можно эмулировать.

всего комментариев: 30

<< предыдущая заметка следующая заметка >>