Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 14.08.2011, 08:36
Профессор
Отправить личное сообщение для popov654 Посмотреть профиль Найти все сообщения от popov654
 
Регистрация: 22.09.2010
Сообщений: 217

Это ШОК для чайника!
Недавно взялся разработать новую версию своего парсера лого в сервера 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">&lt;&lt;</a>&nbsp;</td>'
          buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + ((group - 1) * 10) + '\'); return false">&lt;</a>&nbsp;</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>&nbsp;</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">&gt;</a>&nbsp;</td>'
             }
             buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + (pages - 1) + '\'); return false">&gt;&gt;</a></td>'
          }
          buf += '<td>&nbsp;&nbsp;&nbsp;всего ' + 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() используется повсюду!.. Ну не верю я чтобы он у всех так тормозил. Он что, ТАК долго обходит дерево? Какие тогда возможны альтернативы?

Или я где-то жёстко затупил... Прошу помочь разобраться!

Последний раз редактировалось popov654, 14.08.2011 в 08:44.
Ответить с цитированием
  #2 (permalink)  
Старый 14.08.2011, 12:27
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

1. Много кода.
2. Много букв.
3.
Цитата:
Во второй версии скрипта при загрузке нового блока PHP-скрипт в верхнем фрейме с помощью JS по событию onload перенаправлял селектор в нижнем фрейме по новому URL, передавая в адресной строке новые параметры, которые использовались селектором для обновления раскладки.
Какая связь php-скрипта и JS'а, если первый только генерирует разметку, кто такие селекторы и как они перенаправляются, кто такие раскладки - не понятно.
Это отбивает любое желание разобраться и помочь.

Я не могу утверждать, что я понял всё из вышенаписанного, но раз там промелькнуло упоминание фрейма, возможно, задержка вызвана загрузкой документа, всех его элементов и построением соответствующего дерева. Если не нужно ждать загрузки элементов, а хватит только дерева, отлавливайте не onload, а domReady (google -> domready). Если нужен только код страницы, используйте XHR (страница при этом должна быть на том же домене).
Ответить с цитированием
  #3 (permalink)  
Старый 14.08.2011, 22:38
Профессор
Отправить личное сообщение для popov654 Посмотреть профиль Найти все сообщения от popov654
 
Регистрация: 22.09.2010
Сообщений: 217

Я прошу прощения
Но я тоже ровно ничего не понял.

Давайте я переформулирую вопрос корректнее, а Вы уточните, что Вы имели в виду) ОК?

"Селектор" - я немного некорректно употребил это слово. Пускай будет "трекер". Селектором я его назвал от слова "select" - он выбирает, какая часть файла будет анализировться, или, говоря на языке конечного пользователя, какую страничку обработанных данных покажет ему скрипт.

Насчёт onload - опять же ни в чём не уверен, но не думаю что дело именно в этом. Ведь событие и в первом и во втором случае вешается на onload. Более того, я вообще не уверен что проблема в JS (хотя ручаюсь, что PHP код абсолютно идентичен в обоих случаях). Понимаете, просто такое ощущение, что "висит" именно PHP. Причём во всех браузерах. И только в случае отдельного контейнера. Ну как такое возможно?

В принципе, есть у меня предположение... Только что сообразил. Возможно, проблема как раз-таки в том, что в случае с отдельным контейнером поле с файлом не очищается. Хоть я и сделал в PHP логику, чтобы при наличии загруженного файла на сервере и установленной куке в клиенте повторной загрузки не происходило, возможно, данные каким-то образом всё же утекают и передаются на сервер снова через форму. То есть такая огромная задержка вызвана тупо повторной загрузкой 5-мегабайтного файла. Но PHP судя по отладочной печати его не сохраняет. Может ли быть так, что данне передаются "вхолостую"? То есть послали, но не приняли?..

И если это так, то как с этим бороться? Каждый раз грузить весь огромный лог - Боже упаси, а очищать поле не хочется, т.к. для пользователя это единственный источник информации о том, какой лог он анализирует. Сделать отдельный "дисплей" с именем файла? Увы, у меня места на него нет, да и пустое поле загрузки смотрится не очень красиво...
Можно ли как-то обойти эту проблему через JS? Например, запретить загрузку на сервер части формы? Можно конечно вообще форму не сабмитить, я не спорю, а только пренаправлять верхний фрейм с PHP-скриптом. Это так, но что делать, если юзер-таки захочет загрузить новый лог? Надо вообще разделить процесс загрузки файла с логом и процесс переключения страниц. Но как это сделать органично? Тут ведь в чём была прелесть - нажал "Анализ" - и тут же получил результат, так как скрипт в конце стадии подготовки сам устанавливал текущую страницу в ноль и шёл работать дальше. Для пользователя всё было совершенно прозрачно. Кроме того, в ближайшие 10 минут пользователь мог нажать "Анализ" вообще не выбирая файл. Скрипт сам соображал, что файл уже загружен и брал его с сервера. Если сейчас эти процессы разделять - может выйти неудобно с точки зрения юзабилити

Последний раз редактировалось popov654, 14.08.2011 в 23:00.
Ответить с цитированием
  #4 (permalink)  
Старый 19.08.2011, 00:37
Профессор
Отправить личное сообщение для popov654 Посмотреть профиль Найти все сообщения от popov654
 
Регистрация: 22.09.2010
Сообщений: 217

В итоге оставил первый вариант чтобы не мачиться)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Решение проблемы кодировок для AJAX и PHP без iconv (cp1251 в AJAX) Serge Ageyev AJAX и COMET 10 24.04.2013 20:48
Новая система управления сайтом Scripto CMS deepslam Ваши сайты и скрипты 38 31.01.2011 14:55
Как (эффективно) изучать JavaScript? JSTalker Общие вопросы Javascript 33 23.12.2010 03:13
Узнать CSS правило для элемента vinet Events/DOM/Window 4 10.12.2010 08:12
загрузка джаваскрипта file by file с номером ревизии(последней) в урле для файла sergdev Ваши сайты и скрипты 7 13.04.2010 10:52