Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Применение библиотек > загрузка данных с сервера без прямого обновления


Автор: Alx 14.1.2006, 15:21
Для тех, кто не знает, теперь модно использовать сверх динамичные страницы.
То есть страницы, которые получают или отправляют данные на сервер без перезагрузки самой себя, практически незаметно для пользователя.

для этого есть три (и ещё один, но о нём позже) способа:
  • HttpRequest ( ActiveX Microsoft.XMLHTTP для MSIE или XMLHttpRequest для Firefox )
    MSIE 6.0+, Firefox 1.0+, Netscape 7+
  • Загрузка php-обработчика, как внешнего скрипта ( <script src="loader.php?param=value"></script> )
    MSIE 5.5+, Opera 7+
  • Использование невидимого iFrame ( нульфрейма )
    MSIE 5.5+, Opera 7+, Firefox 1.0+, Mozilla 0.9+, Netscape 7+
вот пример работы всех этих трёх путей:

http://alx.com.ru/stats/dataload/test.html

Код

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style>
body {overflow:auto;margin:10px;font-family:Verdana;font-size:11px;}
</style>

<script>
// загрузка данных с сервера без прямого обновления страницы
// использование ActiveX Microsoft.XMLHTTP для MSIE или XMLHttpRequest() для Firefox

var xmlDoc = null ;
  
function http_request()
{if (typeof window.ActiveXObject != 'undefined' )
{xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
xmlDoc.onreadystatechange = process ;
}
else
{xmlDoc = new XMLHttpRequest();
xmlDoc.onload = process ;
}
xmlDoc.open("GET", "HttpRequest.php?act=" + document.getElementById("param1").value, true);
xmlDoc.send(null);
}

function process()
{if (xmlDoc.readyState == 4)
{document.getElementById('res').innerHTML += xmlDoc.responseText ;
}
}
</script>

<script src="" id="dataloader"></script>
<script>
// загрузка данных с сервера без прямого обновления страницы
// загрузка в src тега <script> php-файла 

function change_src()
{var link = "change_src.php?&act=" + document.getElementById("param1").value + "&rand=" + Math.random();
var old_s = document.getElementById('dataloader');
if (old_s)
{old_s.parentNode.removeChild(old_s);            
}
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.src = link;
s.id = 'dataloader';
document.getElementsByTagName('head')[0].appendChild(s);        
}
</script>

<script>
// загрузка данных с сервера без прямого обновления страницы
// обновление невидимого iFrame ( нульфрейма )

function iframe()
{top.frames['myframe'].document.location.href = "iframe.php?&act=" + document.getElementById("param1").value
}
</script>

<script language="JavaScript" src="dk_JsHttpRequest/Js.js"></script>
<script>
// загрузка данных с сервера без прямого обновления страницы
// с использованием библиотек Subsys_JsHttpRequest ( разработчик - "dk lab" | http://dklab.ru/ )

function dk_JsHttpRequest(force)
{var query = '' + document.getElementById('param1').value;
var req = new Subsys_JsHttpRequest_Js();
req.onreadystatechange = function()
{if (req.readyState == 4)
{if (req.responseJS)
{document.getElementById('res').innerHTML += 
'md5('+(req.responseJS.q||'undefined')+') = ' + (req.responseJS.md5||'undefined') + '<br>';
}
}
}
req.caching = true;
req.open('POST', 'dk_JsHttpRequest.php?test=abc', true);
req.send({ q: query, test:303 });
}
</script>

</head>

<body>
<iframe name="myframe" id="myframe" width="0" height="0" style="visibility:hidden;"></iframe>
<b>Запрос :</b> <input type="text" id="param1" />
<br><br><br>
<input type="button" value="Subsys_JsHttpRequest" onclick="dk_JsHttpRequest(true)" /> // MSIE 5.5+, Opera 7+, Firefox 1.0+, Netscape 7+
<br><br><br>
<input type="button" value="HttpRequest" onclick="http_request()" /> // MSIE 6.0+, Firefox 1.0+, Netscape 7+
<br><br>
<input type="button" value="PHP в <script>" onclick="change_src()" /> // MSIE 5.5+, Opera 7-, Firefox 1.0+, Mozilla 0.9+, Netscape 7-,
<br><br>
<input type="button" value="iFrame" onclick="iframe()" /> // MSIE 5.5+, Opera 7+, Firefox 1.0+, Mozilla 0.9+, Netscape 7+
<br><br><br>
<div id="res" style="background:#6699cc;border:1px solid darkblue;color:white;font-family:Verdana;font-size:11px;padding:10px;width:400px;height:300px;overflow:auto;">
</div></script>
</body>
</html>


а вот соодержимое всех трех php-обработчиков:

HttpRequest.php
Код

<?
$act = $_GET['act'];
echo "md5({$act}) = ".md5($act)."<br>";
?>


change_src.php
Код

<?
$act = $_GET['act'];
echo "document.getElementById('res').innerHTML += 'md5({$act}) = ".md5($act)."<br>'";
?>


iframe.php
Код

<?
$act = $_GET['act'];
echo "<script>top.document.getElementById('res').innerHTML += 'md5({$act}) = ".md5($act)."<br>';</script>";
?>


все три способа имеют свои преимущества и недостататки.

XMLHttpRequest
+ имеет самую высокую скорость выполнения
+ незаметен для пользователя (никаких прелоадеров в statusbar`е)
- поддерживается только MSIE 6.0+, Firefox и Netscape 7+
- не сработает, если в MSIE отключена обработка ActiveX
Загрузка php-обработчика, как внешнего скрипта
+ имеет хорошую скорость выполнения
+ работает в MSIE 5.5+, Opera 7, Firefox 1.0+, Mozilla 0.9+, Netscape 7
- не работает в Opera 8 и Netscape 8
- в браузерах отображается preloader
Использование невидимого iFrame
+ работает во всех браузерах
+ после запроса php файл может работать самостоятельно
- имеет низкую скорость выполнения
- загрязняет историю браузера
- в statusbar`е браузеров отображаются прелоадеры.

Что касается третьего способа, то он практически выбывает из борьбы за выживание, но у первых двух тоже свой большой недостаток - некроссбраузерность.
К счастью есть выход, а именно метод, объединяющий первые два способа и работающий на высоких скоростях во всех браузерах!
Метод этот - http://dklab.ru/lib/Subsys_JsHttpRequest, разработанный dk lab.

на странице разработчика, посвещённой данному методу, не очень хорошие примеры, много лишнего, трудно проникнуться сутью. однако сделать это стоит, если хотите использовать все возможности этого набора библиотек для обхода всех глюков и багов.
я же всё это дело упростил до нашего примера. посмотреть его можно тут - http://alx.com.ru/stats/dataload/test.html.

вот, что ещё есть в файле test.html:

Код

<script language="JavaScript" src="dk_JsHttpRequest/Js.js"></script>
<script>
// загрузка данных с сервера без прямого обновления страницы
// с использованием библиотек Subsys_JsHttpRequest ( разработчик - "dk lab" | http://dklab.ru/ )

function dk_JsHttpRequest(force)
{var query = '' + document.getElementById('param1').value;
var req = new Subsys_JsHttpRequest_Js();
req.onreadystatechange = function()
{if (req.readyState == 4)
{if (req.responseJS)
{document.getElementById('res').innerHTML += 
'md5('+(req.responseJS.q||'undefined')+') = ' + (req.responseJS.md5||'undefined') + '<br>';
// получить строку, возвращаемую обработчиком,
// можно обратившись к классу : req.responseJS.{имя параметра}
}
}
}
req.caching = true; // разрешаем кэширование
req.open('POST', 'dk_JsHttpRequest.php?test=abc', true);
req.send({ q: query, test:303 });
}
</script>


а вот содержимое php-файла, выполняющего обработку запроса:
Код

<?
require_once "dk_JsHttpRequest/config.php";
require_once "dk_JsHttpRequest/Php.php";

$JsHttpRequest =& new Subsys_JsHttpRequest_Php("windows-1251");

// $_RESULT - массив, в котором будет содержаться вся выдаваемая браузеру информация.
// можно создавать любое количество элементов и присваивать им любые строки.

$_RESULT = array(
  "q"     => $_REQUEST['q'],
  "md5"   => md5($_REQUEST['q']),
); 
?>


+ папка dk_JsHttpRequest, в которой находятся JS- и PHP-библиотеки.

скачать всю эту красоту можно тут - http://alx.com.ru/stats/dataload/dataloaders.rar

У дачи!

smile

Автор: Sardar 14.1.2006, 17:41
Цитата(Alx @ 14.1.2006, 14:21 Найти цитируемый пост)
Загрузка php-обработчика, как внешнего скрипта
...
- не работает в семействе Gecko

Не верно, работает везде кроме Оперы 8 и Netscape 8. Вернее работает, но почему то переданный параметрами в функции данные http://en.wikipedia.org/wiki/JSON убиваються и получаем NULL. Видать какая политика безопасности или баг...
Цитата(Alx @ 14.1.2006, 14:21 Найти цитируемый пост)
Использование невидимого iFrame

Добавил бы самое вредное качество - загрязнение истории, все переходы браузером "назад" престанут работать если только не спроектировать правильно скрипты... но это всё равно криво...
Цитата(Alx @ 14.1.2006, 16:18 Найти цитируемый пост)
самый лучший способ - разработка Subsys_JsHttpRequest by dk lab.

Комбинирует первый и второй способ, но выбор делает динамично, смотря что у пользователя есть. Действительно самый лучший выбор, т.к. не нужно думать о деталях, также скрипт имеет много workaround приёмов для обхода различных багов. Отсюда совет: хотите использовать динамику, JSHttpRequest от Котерова лучший ИМXО выбор.

Alx классно, дополни мои замечания и в FAQ smile

Автор: Cheba 14.1.2006, 19:33
Цитата(Alx @ 14.1.2006, 15:21 Найти цитируемый пост)
Загрузка php-обработчика, как внешнего скрипта
- не работает в семействе Gecko


Небольшой фикс:
Код
function change_src()
{
    var link = "change_src.php?&act=" + document.getElementById("param1").value + "&rand=" + Math.random();
    var old_s = document.getElementById('dinamoscript');
    if (old_s)
        old_s.parentNode.removeChild(old_s);            
    
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    s.src = link;
    s.id = 'dinamoscript';
    document.getElementsByTagName('head')[0].appendChild(s);        
}


В чем отличие... Он не подменяет src у уже существующго скрипта, а создает новую ноду script с нужным src. После добавления такой ноды Лиса будет загружать файл скрипта. Перед добавлением ноды старая нода удаляется во избежание скопления лишнего мусора.

Автор: Alx 15.1.2006, 00:27
Sardar
спасибо, обновил, ща загружу в фак!

Cheba
спасибо и + !
Добавлено @ 00:39
http://vingrad.ru/JAVASCRIPT-ART-002998

Автор: Innuendo 15.1.2006, 09:02
2 Alx
Спасибо, полезная вещь.
Вопрос:
какую структуру лучше использовать?
с iframe? пусть она медленнее, но хоть уверены что у всех будет работать (поддержка браузеров велика)

Автор: Alx 15.1.2006, 11:05
Innuendo
Цитата(Alx @ 14.1.2006, 15:21 Найти цитируемый пост)

Что касается третьего способа, то он практически выбывает из борьбы за выживание, но у первых двух тоже свой большой недостаток - некроссбраузерность.
К счастью есть выход, а именно метод, объединяющий первые два способа и работающий на высоких скоростях во всех браузерах!
Метод этот - Subsys_JsHttpRequest, разработанный dk lab.

smile


гы, а за статьи плюсы дают? smile smile

Автор: Innuendo 15.1.2006, 11:21
Цитата(Alx @ 15.1.2006, 11:05 Найти цитируемый пост)

гы, а за статьи плюсы дают?

гы, да я не жадный smile я бы конечно дал, потому что классная статья... но надо иметь 100 постов чтоб дать smile

Автор: Sardar 15.1.2006, 15:46
Цитата(Alx @ 15.1.2006, 10:05 Найти цитируемый пост)
гы, а за статьи плюсы дают?

Xотел поставить, но оценил статью... вообщем она ещё не готова, это пока просто пример, один из сотен по сети. Больше строк бы к коду, что где конкретно происходит, включая серверную сторону, этим и хотел чуть позже заняться. Попробуешь? smile

Автор: Alx 15.1.2006, 16:19
Sardar
если объяснишь лучше задачу, то могу попробывать.
ты имеешь ввиду имеено развитие решения Subsys_JsHttpRequest или идеи в целом?
я просто пока немножко не понимаю, что тут развивать? js обращается к серверу, сервер обрабатывает и возвращает данные в любом количестве, которыми оперирует js... что ещё нужно? или у тебя есть какие-то конкретные идеи?

Автор: Cheba 15.1.2006, 18:32
Было бы неплохо, если бы ты показал как обрабатывать результаты в виде XML для XMLHTTP Reques. Не даром ведь его так назвали. smile

Автор: Lixil 19.1.2006, 12:30
Я бы не стал хоронить iframe, если не ошибаюсь это единственный способ крепить файлы без перезагрузки страницы.

А вот код, который выдергивает содержимое iframe
Код

null_frame.contentWindow.document.body.innerHTML


сам долго искал, может кому пригодится.
Добавлено @ 12:31
Alx у плюс от S.A.P. как только домой вернусь smile .

Автор: Sardar 20.1.2006, 03:35
Цитата(Alx @ 15.1.2006, 15:19 Найти цитируемый пост)
ты имеешь ввиду имеено развитие решения Subsys_JsHttpRequest или идеи в целом?

Пока это просто короткий пример коих много. Xорошо бы более законченый реальный проект с законченым кодом, а не просто "мы получилли строку". Народ реально не знает что с этим делать можно, кто то JS код отдаёт, что потом на eval, кто то парсит сам и не многие знают что префикс XML не зря стоит smile Как составить не очень кривой XML словарь для своего протокола, работать с ним на клиенте.

DOM (для XML лучше XPath, это для редактирования контента) не нужно обяснять, тут главное дать затравку, ищущий найдёт необходимое.

Цитата(Lixil @ 19.1.2006, 11:30 Найти цитируемый пост)
если не ошибаюсь это единственный способ крепить файлы без перезагрузки страницы.

Заполнение формы всё равно на пользователе, просто отправка в конкретный фрейм, не важно какой.

Автор: Smak 8.12.2006, 04:39
Скажите, а как сделать чтобы этот скрипт получал данные с сервера например каждую секунду?
т.е. в данном случае данные с сервера загружаються при нажатии на button.
А если это чат. загружать новые сообщения нужно довольно часто. как это можно сделать?
я так понимаю нужна функция которая будет только загружать с сервера данные.
исполюзую Subsys_JsHttpRequest.

Автор: Alx 8.12.2006, 14:35
эээ... ну для всего есть соответствующие функции.. в данном случае можно использовать setInterval() или setTimeout(), но этого вам будет мало для написания чата...  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)