|
|
|
| Просьба подсказать стратегию реализации моих хотелок.
Есть код который по таймеру отправляет AJAX запрос на сервер по фокусу на textarea:
// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();
// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject()
{
// will store the reference to the XMLHttpRequest object
var xmlHttp;
// if running Internet Explorer
if(window.ActiveXObject)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
xmlHttp = false;
}
}
// if running Mozilla or other browsers
else
{
try
{
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
xmlHttp = false;
}
}
// return the created object or display an error message
if (!xmlHttp)
alert("Error creating the XMLHttpRequest object.");
else
return xmlHttp;
}
// создаем асинхронный HTTP запрос с использованием XMLHttpRequest объекта
function process()
{
var st;
// proceed only if the xmlHttp object isn't busy
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
// retrieve the name typed by the user on the form
name = encodeURIComponent(document.getElementById("myName").value);
// execute the quickstart.php page from the server
xmlHttp.open("POST", "quickstart.php", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// define the method to handle server responses
xmlHttp.onreadystatechange = handleServerResponse;
// make the server request
xmlHttp.send("name=" + name);
}
else
// if the connection is busy, try again after one second
st = setTimeout('process()', 1000);
}
// executed automatically when a message is received from the server
function handleServerResponse()
{
// move forward only if the transaction has completed
if (xmlHttp.readyState == 4)
{
// status of 200 indicates the transaction completed successfully
if (xmlHttp.status == 200)
{
// extract the XML retrieved from the server
xmlResponse = xmlHttp.responseXML;
// obtain the document element (the root element) of the XML structure
xmlDocumentElement = xmlResponse.documentElement;
// get the text message, which is in the first child of
// the the document element
helloMessage = xmlDocumentElement.firstChild.data;
// update the client display using the data received from the server
document.getElementById("divMessage").innerHTML =
'<i>' + helloMessage + '</i>';
// restart sequence
st = setTimeout('process()', 1000);
}
// a HTTP status different than 200 signals an error
else
{
alert("There was a problem accessing the server: " + xmlHttp.statusText);
}
}
}
function stop()
{
clearTimeout(st);
}
<textarea id="myName" name="joke" onfocus='process()' onblur='stop()'></textarea>
|
с горем пополам, переделал с GET на POST и добавил остановку таймера при снятии фокуса с textarea
Но иногда остановка не происходит, приходится перегружать страницу.
Время от времени хостер меня блокирует, я так понимаю из-за большого количества запросов
http://valick.besaba.com/
Что я хочу реализовать:
1) Изменение размера textarea по вертикали в зависимости от контента, например при вставке копипастом, а так же при загрузке страницы с сервера, для редактирования.
2) Увеличение периода обращения AJAX к серверу с течением времени и полной остановкой либо через определенный промежуток времени (20 секунд) либо по количеству итераций с обращениями например 10. И сброс при изменении содержимого (onchange).
3) Запретить обращение к серверу при количестве символов менее 10
Вобщем хотелось бы чтобы мне помогли разбить задачи на более мелкие задания, с которыми я попробую справится сам. Начну с пункта номер 3.
___
еще раз всех с новым годом!!! | |
|
|
|
|
|
|
|
для: Valick
(03.01.2014 в 23:53)
| | Сделал так
var textValue = document.getElementById("myName").value;
// proceed only if the xmlHttp object isn't busy
if ((xmlHttp.readyState == 4 || xmlHttp.readyState == 0) && textValue.length > 10)
|
но теперь проблема, если бэкспейсить с 10 символов до нуля, то содержимое дива divMessage не затирается, то само по себе логично
тут надо подумать, как и по какому событию его очищать.
Сделал вот так:
function process()
{
var st;
var textValue = document.getElementById("myName").value;
if (textValue.length < 10)
{
document.getElementById("divMessage").innerHTML='';
}
else
{
// proceed only if the xmlHttp object isn't busy
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
// retrieve the name typed by the user on the form
name = encodeURIComponent(textValue);
// execute the quickstart.php page from the server
xmlHttp.open("POST", "quickstart.php", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// define the method to handle server responses
xmlHttp.onreadystatechange = handleServerResponse;
// make the server request
xmlHttp.send("name=" + name);
}
}
// if the connection is busy, try again after one second
st = setTimeout('process()', 1000);
}
|
но сам от этого не в восторге и кажется появилось притормаживание при скроле страницы, да и при снятии фокуса с textarea отправка запросов не останавливается. | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 00:24)
| | к сожалению, сейчас нет времени разбираться, но первое, что бросается в глаза: переменая st должна быть объявлена в глобальной области видимости (у вас же в локальной, это не верно), вместо setTimeout в данном случае правильнее использовать setInterval, первый аргумент для setInterval/setTimeout тоже не совсем верный | |
|
|
|
|
|
|
|
для: psychomc
(04.01.2014 в 01:41)
| | ок, спасибо
в голбальной это рядышком с var xmlHttp ? | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 01:46)
| | да, сейчас в функции stop она не видна просто. и обязательно обратите внимание на setInterval | |
|
|
|
|
|
|
|
для: psychomc
(04.01.2014 в 01:49)
| | однако она каким-то образом работала
подправил вот так, стало гораздо удобнее
function process()
{
var textValue = document.getElementById("myName").value;
if (textValue.length < 10)
{
document.getElementById("divMessage").innerHTML='';
st = setTimeout('process()', 1000);
}
else
{
// proceed only if the xmlHttp object isn't busy
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
// retrieve the name typed by the user on the form
name = encodeURIComponent(textValue);
// execute the quickstart.php page from the server
xmlHttp.open("POST", "quickstart.php", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// define the method to handle server responses
xmlHttp.onreadystatechange = handleServerResponse;
// make the server request
xmlHttp.send("name=" + name);
}
else
// if the connection is busy, try again after one second
st = setTimeout('process()', 1000);
}
}
|
буду читать про setInterval
___
хм, setInterval выполняется многократно и его нет смысла использовать в теле той функции которую он вызывает, т.е. нужна другая функция, которая будет вызывать process(), я правильно понимаю? | |
|
|
| |
|
|
|
|
для: confirm
(04.01.2014 в 09:03)
| | спасибо, я прочитал, но "воз и ныне там" :) | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 10:28)
| | Я не извозчик, а ссылка объясняет в чем может быть причина обвала сервера, тем более при таком малом временном интервале. | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 10:58)
| | Ну до обвала там далеко, меня просто блокировали на время, из другого места все доступно, и ftp всегда доступен.
И опять же, такое случалось когда не отрабатывала очистка таймера. Вот почему это случается, я пока понять не могу. | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 12:07)
| |
var n = 10;
tmr = setTimeout(function itr() {
!n ? clearTimeout(tmr) : setTimeout(itr, 1000);
n--;
console.log(n);
}, 1000);
|
| |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 12:28)
| | спасибо, в процессе разбора вашей функции методом проб и ошибок решил откакзаться от ранне намеченной стратегии и вот что получилось:
var textValue = '';
var txtLenOld = 0;
var txtLenNew = 0;
var seIn;
var seTi;
function checkTextArea()
{
textValue = document.getElementById("myName").value;
txtLenNew = textValue.length;
if (txtLenNew != txtLenOld)
{
process();
clearTimeout(seIn);
seTi = setTimeout(function(){checkTextArea()}, 1000);
}
txtLenOld = txtLenNew;
console.log('опрос textarea');
clearTimeout(seTi);
seIn = setTimeout(function(){checkTextArea()}, 1000);
}
function stopTimer()
{
clearTimeout(seTi);
clearTimeout(seIn);
}
|
но мне не нравится использование глобальных переменных
и еще как лучше передавать getElementById("myName") параметром в функцию, чтобы использовать например два и более textarea | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 17:15)
| | var seIn;
var seTi;
и
seTi = setTimeout()
seIn = setTimeout()
это зачем?
seTi = setTimeout() это и есть объявление глобальной переменной, зачем ее "дублировать"?
Вы не можете очистить таймер без ссылки на его идентификатор, так что нравится, не нравится, это эмоции. Вот только к чему такой баян писать не понятно - два таймера на одну функцию, да еще отдельная функция для их очистки. | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 17:39)
| | Вот только к чему такой баян писать не понятно
ну наверно к тому что я не знаю JS и пытаюсь его вымучить
я могу себе позволить не знать JS я не программист, для меня это всего лишь хобби, мне это просто интересно, вот только свободного времени очень мало
кстати может выглядит и ужасно не спорю, да не то что не спорю, а знаю, что ужасно, но пока хоть так, а главное работает так как я хочу
Вы не можете очистить таймер без ссылки на его идентификатор, так что нравится, не нравится, это эмоции.
эмоций никаких нет, я про другие переменные в частности txtLenOld
_____
кстати ваш предыдущий пример, не проще ли использовать цикл for для итераций? | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 17:45)
| | Передавайте параметры, если не нравится, но учтите, если читали внимательно, то должны усвоить, что вызовы по Timeout выполняются в глобальном контексте.
Что касается баяна, то это к тому, что запускаются два таймера (!) для запуска одной и той же (!) функции, через один и тот же интервал. А если забыть о JS и считать, что выполняется серверная задача с задержкой с проверкой условия, вы подобное бы написали?
Мой предыдущий пример не о циклах, а о том, что JS, это не интерпретатор РНР. Какие задачи вы прописали JS, те и будут выполнятся, сразу, асинхронно, и если вы не следите за объектом, или вам кажется, что следите, то так и может происходить - изменяете значение в одном месте, а пытаетесь контролировать в другом, и либо повезет, либо нет. Вторая причина, это "хромая" логика, а третья, это не понимание процессов таймаутов вами заданных.
А в примере - есть переменная, есть процесс ее изменяющий, и этот же процесс отслеживает эти изменения, прекращая сам процесс при достижении условия. | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 18:16)
| | Полностью согласен и хромая логика и непонимание процессов, и чесное пионерское пытался убрать один таймер, но итерации останавливались. Но не думайте что я довольный и счасливый от моего говнокода сел на попу ровнои плюю в потолок, я буду продвигаться далее и надеюсь со временем придет понимание процессов. Это не первая моя попытка осилить JS :) | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 19:27)
| | Да если бы только процессы. Вот вы говорите, что не нравится через глобальные переменные. Ну что сказать, вкусы действительно разные, но при этом совсем не понятно для чего вы их создаете?
Я не знаю чего вы пытаетесь сделать, но если судить по коду, то вы "скачете" вокруг одного и того же объекта - текстовой области, ее значения, втискивая его в новое, старое, а еще и изначальное. А нужно ли? Может быть надо всего лишь обрабатывать события клавиатуры и таким образом определяя изменилось ли значение? А уж после этого запускать опрос. Да и "изменилось", это понятие далеко неоднозначное, и что надо на самом деле...
Но если запрос по изменению значения текстового поля, то каким боком нужен таймер, да еще и целых два? Уж если ставить таймер, то для того, чтобы ограничить запросы. А если так, то зачем старое/новое значение, если можно определить "частицу меры", по которой производить опрос, а это можно определить простым делением по модулю текущего значения, и не переменной, которая вам не нравится, а значения самого объекта, по которому щелкает клава?
Два таймера нужны тогда, когда один делает постоянный опрос, задавая интервал или проверяя условие, а второй непосредственно выполняет серию запросов. Например, плюс/минус 10 секунд от каждого часа опрашивать сервер через 1 секунду. | |
|
|
|
|
2.5 Кб |
|
|
для: confirm
(04.01.2014 в 19:49)
| | Вот вы говорите, что не нравится через глобальные переменные. Ну что сказать, вкусы действительно разные, но при этом совсем не понятно для чего вы их создаете?
как только научусь делать без них сделаю без них, если это будет оптимальнее
Но если запрос по изменению значения текстового поля, то каким боком нужен таймер, да еще и целых два?
как только научусь делать без таймера, сделаю без него если это оптимальнее
__
я просто взял пример из книги (файлы прикрепил) и делаю то на что хватает мозга, ну и тему собственно создал в расчете на то что дадут пинка в нужном направлении вектора. | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 21:37)
| | А чему учится то, как делать не от JS конкретно зависит и насколько вы его знаете.
Если необходимо любое изменение контролировать, то нет смысла в этих трех переменных, и надо опрашивать всегда, а это значит таймер не нужен. Но так можно и завалить сервер, а значит надо действовать порциями. Но почему обязательно таймер для этого, ведь за время ожидания ввод может породить приличные изменения, так почему просто не взять за ориентир порцию этих изменений?
Если N, это количество введенных символов за время Т, как средняя скорость ввода, то почему просто не проверять значение на кратность этой величине? Если уж так необходимо еще более экономить запросы, то плюс хранить текущее значение в одной единственной переменной, сравнивая еще и с ней. Проверять надо - если не пусто, если кратно порции (и если надо, то и больше предыдущего значения), и обрабатывать потерю фокуса. Если откинуть частности в сторону и принять за ввод только с клавиатуры, то таймер лишний.
Другое дело что есть частности, или есть некие условия определяющие сам сценарий, тогда все может быть и гораздо сложнее. Но вот по вашему не понять к чему это все нужно. | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 22:14)
| | А чему учится то, как делать не от JS конкретно зависит и насколько вы его знаете.
вот тут я как раз в корне не согласен и с этим готов поспорить
например в РНР если я вижу несколько решений задачи, я выбираю оптимальное (ну естественно по своему уровню знаний), так как хорошо знаю язык и его возможности.
Я вам еще раз говорю, я не знаю как взять из textarea строку без таймера, потому, что не знаю возможностей JS, я взял пример из книги и переделал его под себя - это и есть процесс обучения. Теперь я знаю как это можно сделать одним из множества, пусть даже не эффективным способом, теперь буду искать и учить другие варианты.
__
вот к примеру ребенок учится ходить, а я подойду и скажу, зачем ты ходишь, да еще так криво и падаешь, веть гораздо эффективнее бегать, да еще и с элементами паркура, чтобы срезать дорогу... | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 22:33)
| | >я не знаю как взять из textarea строку без таймера, потому, что не знаю возможностей JS
Вот вы получаете строку текстовой области:
var textValue = document.getElementById("myName").value;
Разве для этого нужен таймер? А еще у объектов есть события, возникающие при различных ситуациях, и можно обработав событие отпускания клавиши у текстовой области получить длину ее значения onkeyup="len=this.value.length", где len предопределенная переменная.
Я не говорил, что изучать не надо, я сказал, что задачу определяет не язык, а тот кто ставит задачу, то есть вы. Если вам надо погладить брюки, вы же не будете изучать инструкцию утюга, вы первым делом определитесь, что вам нужен именно утюг, а не топор, а инструкция, так это по надобности. Не вижу разницы между постановкой задачи по глажке брюк и опроса сервера - определитесь что должно выполняться, значит и появятся идеи ее решения, а нет... Ведь брюки вполне можно погладить и топором, разве не так? ) | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 23:07)
| | вы первым делом определитесь, что вам нужен именно утюг, а не топор
только в том случае если я буду знать о существовании утюга, а если нет то поглажу и топором, пойму что это неудобно и буду искать другие варианты, а вот на сколько скоро я узнаю о существовании утюга это уже зависит от многих факторов, в том числе и от удачи.
А еще у объектов есть события
да и я знаю onfocus (топор) и onblur (лопата), и на момент написания скрипта я не занл про утюг (onkeyup), потому что за основу взял срипт из учебника, почему там нет утюга я не знаю
сейчас попробую погладить с помощью утюга :) | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 23:29)
| | Ну это вы уже ответвляете в дискуссию мною утрированное.
Что вообще такое язык программирования? Да их можно спокойно выбросить и посадить компьютеры опять на хлеб с водою - перфокарты, и все будет работать без проблем, понятно, что затраты будут велики, но ведь суть то не в этом. Работали раньше на перфокартах, и что, человек ставя задачу размышлял "дырочками перфокарт"? Конечно же нет, он ставил конкретные задачи, мыслил конкретными, а не виртуальными свойственными только компьютеру образами, и мысля находил пути ее решения, и только потом протыкал дырочки иголочкой, и только на этом этапе действовал не абы как, а как железяка требовала.
Языки появились вообще во многом благодаря областям к компьютерам прямого отношения не имеющим. Языки, это просто средство общения с машиной, и которое обладает своим набором инструментов. А думаете же вы не функциями и методами. Задача опроса сервера по длине значения, которую вы описываете, тоже самое, что писать письмо на деревню дедушке, задавшись вопросом при каком условии его отправлять. Если найти выгодное решение, понять как лучше и чем это условие контролировать, то переложить эти "человеческие" действия на язык машины, так это просто взять список машинных инструкций и согласно их описаниям произвести подмену.
Если же думать языковыми категориями и ожидать, что получится нужное, ну так это только при большом опыте и полном знании предмета, но даже и в этом случае вполне может получится - думаете, что в руках утюг, а окажется, что нет. Не свойственно это человеку. ) | |
|
|
|
|
|
|
|
для: confirm
(04.01.2014 в 23:56)
| | погладил утюгом, но возникла проблемка, при копипасте мышкой естественно onkeyup не происходит
нашёл молоток (oninput), оказывается мне надо было не гладить а гвозди забивать
но оно поддерживается всеми браузерами, кроме IE<9, а в IE9 оно поддерживается частично
пока остановился на таком варианте:
// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();
// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject()
{
// will store the reference to the XMLHttpRequest object
var xmlHttp;
// if running Internet Explorer
if(window.ActiveXObject)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
xmlHttp = false;
}
}
// if running Mozilla or other browsers
else
{
try
{
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
xmlHttp = false;
}
}
// return the created object or display an error message
if (!xmlHttp)
alert("Error creating the XMLHttpRequest object.");
else
return xmlHttp;
}
// создаем асинхронный HTTP запрос с использованием XMLHttpRequest объекта
function process(textAreaId, divName)
{
var textAreaId, divName;
var textValue = document.getElementById(textAreaId).value;
if(textValue.length < 10)
{
document.getElementById(divName).innerHTML ='';
return;
}
// proceed only if the xmlHttp object isn't busy
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
// retrieve the name typed by the user on the form
name = encodeURIComponent(textValue);
// execute the quickstart.php page from the server
xmlHttp.open("POST", "quickstart.php", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// define the method to handle server responses
xmlHttp.onreadystatechange = function(){handleServerResponse(divName);};
// make the server request
xmlHttp.send("name=" + name);
}
else
// if the connection is busy, try again after one second
setTimeout(function(){process();}, 1000);
}
// executed automatically when a message is received from the server
function handleServerResponse(divName)
{
var divName;
// move forward only if the transaction has completed
if (xmlHttp.readyState == 4)
{
// status of 200 indicates the transaction completed successfully
if (xmlHttp.status == 200)
{
// extract the XML retrieved from the server
xmlResponse = xmlHttp.responseXML;
// obtain the document element (the root element) of the XML structure
xmlDocumentElement = xmlResponse.documentElement;
// get the text message, which is in the first child of
// the the document element
helloMessage = xmlDocumentElement.firstChild.data;
// update the client display using the data received from the server
document.getElementById(divName).innerHTML =
'<i>' + helloMessage + '</i>';
}
// a HTTP status different than 200 signals an error
else
{
alert("There was a problem accessing the server: " + xmlHttp.statusText);
}
}
}
|
<textarea id="myName" oninput="process('myName','divMessage')"></textarea>
|
| |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 17:15)
| | >но мне не нравится использование глобальных переменных
попробуйте описать вашу задачу в виде объекта | |
|
|
|
|
|
|
|
для: psychomc
(04.01.2014 в 17:43)
| | рано еще :) | |
|
|
|
|
|
|
|
для: Valick
(04.01.2014 в 17:51)
| | да нет, там всё просто. только с синтаксисом разобраться | |
|
|
|
|