Недавно взялся разработать новую версию своего парсера лого в сервера SHOUTcast Прасер написан на PHP, при этом активно использует JavaScript (на простом уровне).
Я вообще в JavaScript новичок честно говоря. И меня это непонятное явление тронуло до глубины души, практически шокировав.
Профессионалы, подскажите в чём прикол) Или в чём моя ошибка, если я туплю
Чтобы не быть голословным, вот код селектора, написанного на JavaScript (это аналог переключателя страничек в любом поисковике, например в Яндексе, однако аналог скорее всего только лишь по внешнему виду и предназначению, реализовано-то в поисковиках это дело наверняка совсем по-другому
)
PHP-код самого парсера приводить не буду, ибо огромный и сложный. Если потом понадобится, опубликую в отдельном посте. Итак, код нижнего фрейма:
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Shoutcast log parser</title>
<style type="text/css">
<!--
.style10 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: small;}
a:link {
color: #0000CC;
}
a:visited {
color: #0000CC;
}
a.current {
color: #EC7600;
}
-->
</style>
</head>
<body>
<script language="JavaScript" type="text/javascript">
function changePage(ref) {
obj = document.frm
obj.action = ref
obj.submit.click()
}
function init() {
}
function check() {
return (frm.filename.value != '')
}
function addData(str) {
if (main_part == '') main_part = document.frm.innerHTML
document.frm.innerHTML = str + main_part
//document.getElementById('tracker').innerHTML = str
}
var main_part = ''
function printPageList(pages, group, cur_page) {
flag = true;
var buf = ''
var from = parent.topframe.getFrom()
var to = parent.topframe.getTo()
var grouping = document.getElementById('grouping').checked ? 'true' : 'false';
buf += '<table border="0"><tr>'
if (cur_page == 10) {
cur_page = 0
}
if (group > 0) {
buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=0\'); return false"><<</a> </td>'
buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + ((group - 1) * 10) + '\'); return false"><</a> </td>'
}
for (i = group * 10 + 1; i <= (group + 1) * 10; i++) {
if (i > pages) {
break;
}
style = ''
if (i % 10 == cur_page) {
style = ' class="current"'
}
buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + (i-1) + '\'); return false"' + style + '>' + i + '</a> </td>'
}
if (pages>10) {
if (i <= pages) {
if ((group + 1) * 10 + 1 <= pages) {
buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + ((group + 1) * 10) + '\'); return false">></a> </td>'
}
buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + (pages - 1) + '\'); return false">>></a></td>'
}
buf += '<td> всего ' + pages + '</td>';
}
buf += '</tr></table><br>'
addData(buf)
}
</script>
<!--<span id="tracker" class="style10"></span>-->
<form action="parser.php" name="frm" id="frm" target="topframe" method="post" enctype="multipart/form-data" class="style10">
<p><input type="checkbox" name="grouping" id="grouping">Группировать смежные сеансы</p>
<input type="file" name="filename" size="38"><br><br>
<input type="submit" name="submit" value="Анализ"><br>
</form>
</body>
</html>
Собственно, дело вот в чём. Во второй версии скрипта при загрузке нового блока PHP-скрипт в верхнем фрейме с помощью JS по событию onload перенаправлял селектор в нижнем фрейме по новому URL, передавая в адресной строке новые параметры, которые использовались селектором для обновления раскладки. Но вот я решил что это не есть хорошо (например, у меня при этом значение поля с именем анализируемого файла очищалось, и почему-то через JS с помощью функции из родительского фрейма не восстанавливалось), и в третьей версии решил сделать механизм, который позволит обновить нужную часть нижнего фрейма без перезагрузки. Для этого я убрал из селектора парсинг URL и вместо этого добавил в функцию вывода раскладки три аргумента.
Сперва я попробовал работать напрямую с document.frm.innerHTML, где frm - имя формы, но, как выяснилось, почему-то данные, добавленные посредством модификации innerHTML из сценария, не читаются, будто их и нет. Поэтому удалить старую раскладку таким способом не получалось. Полностью очистить innerHTML я не мог, потому что там содержался ряд других контролов и надписей. Недолго думая, я нашёл вариант, который уже применял когда-то в другой онлайн-системе с интернет-радио: завести глобальную переменную и хранить в ней исходное состояние innerHTML. Да, наверное это ужасно плохой стиль, но я ничего лучше не придумал. Оно заработало.
Но тут я подумал: а почему мне надо обязательно пихать таблицу с номерами внутрь формы, ведь можно сделать ей отдельный контейнер! И очищать его перед обновлением. Сказано - сделано. Я сделал всё как описано выше, и тут начинается фантастика.
В вышеописанном коде есть оба варианта решения - через глобальную переменную и через отдельный контейнер (второй сейчас закомментирован). Парадокс в том, что второй, более человеческий способ тормозит как не знаю что. Я специально проводил отсчёт времени переключения между страницами данных. В случае помещения трекера в отдельный див, между нажатием на ссылку и осуществлением загрузки верхнего скрипта, который после её завершения вызывал JS функцию селектора, я успевал досчитать до девяти (!). То есть около 9 секунд. В случае же хранения HTML разметки формы в глобальной переменной, при всей нелепости подхода, я едва успевал сосчитать до двух (1,5-2 секунды!)
Я до сих пор слегка в ауте. PHP-код один и тот же, остальное не менялось, единственное существенное отличие которое я вижу - в первом случае использован метод document.getElementById() (при чём документ мягко говоря не очень большой, пара инпутов, форма, див и обчёлся), во втором же случае происходит обращение упрощённым способом к самой форме: document.frm
Я конечно слышал, что ссылки на формы хранятся браузером как-то особо, для упрощённого вызова. Но getElementById() используется повсюду!.. Ну не верю я чтобы он у всех так тормозил. Он что, ТАК долго обходит дерево?
Какие тогда возможны альтернативы?
Или я где-то жёстко затупил... Прошу помочь разобраться!