// JavaScript Document // AJAX -функции if(typeof(String.prototype.trim) != "function"){ String.prototype.trim = function () { var str = this; return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); } } // Кроссбраузерное создание объекта запроса // В зависимости от браузера, код для создания объекта может быть разный. // Кроссбраузерная функция создания XMLHttpRequest: function getXmlHttp(){ var xmlhttp; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest!='undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } //********** // служебная функция для записи рез-тов тестировния в объект // вызывается по событию .onreadystatechange в ходе проверки... function write_status(in_obj,in_status){ var old_status = in_obj.status_connection; in_obj.status_connection = in_status; // если есть in_obj.onchange_status (метод, который вызывается при изменениии состояния подключения), // и прошло изменение состояния подключения - вызываем этот метод. if( (in_obj.status_connection != old_status) && (in_obj.onchange_status != false)) in_obj.onchange_status(); } // end function write_status //********** // функция, для AJAX вызова, - собственно само тестирование наличия положительного ответа от сервера // (на сервере вызывается файл "/test_connection.php") // сама функция используется как метод для объекта, показывающего наличие/отсутствие соединения function Pred_testing_connect(){ var curr_status = false; var now = new Date(); // временный объект - дата // Так как IE не дает подцепить к объекту-запросчику нужные свойства/методы, // создаем временный объект "НАД" запросчиком var tmp_aj = {}; tmp_aj.aj_req = getXmlHttp(); // временный объект-запросчик tmp_aj.status2 = false; // адрес подключения+"случайный" параметр, чтобы не кешировались ответы // document.domain - используется для однозначного указания адреса, т.к. выявлен глюк - если не указывать // а испльзовать только '/test_connection.php?rand_time_var='+ now.getTime()' , результаты одинаковые для // локального и удаленного серверов (!) даже если локальный работает, а сетевой нет.. (Fireworks...) tmp_aj.URL = 'http://'+document.domain +'/test_connection.php?rand_time_var='+ now.getTime(); tmp_aj.connect_prop = this; // this - объект, методом которого является данная служебная функция Pred_testing_connect // собственно проверка.. tmp_aj.aj_req.open('GET', tmp_aj.URL, true); // задать адрес подключения (true - асинхронный) tmp_aj.aj_req.onreadystatechange = function() { // onreadystatechange активируется при получении ответа сервера if (tmp_aj.aj_req.readyState == 4) { // если запрос закончил выполняться if(tmp_aj.aj_req.status == 200) { // если статус 200 (ОК) - ставим флажок, что есть соединение tmp_aj.status2 = true; write_status(tmp_aj.connect_prop,tmp_aj.status2); } else { write_status(tmp_aj.connect_prop,tmp_aj.status2); } } } // end this.aj_req.onreadystatechange = function ... // объект запроса подготовлен: указан адрес и создана функция onreadystatechange // для обработки ответа сервера tmp_aj.aj_req.send(null); // отослать запрос } // end function Pred_testing_connect() //********** // Конструктор для создания объекта тестирования подключения function create_test_conn_obj(test_interval){ if(!test_interval) var test_interval = 3700; // интервал (в мсек) через который тестируется соединение //alert(test_interval); this.status_connection = false; // первоначальный предполагаемый статус соединения //!!! чтобы можно было назначить метод, который вызывается в случае измения status_connection // [... - вызов (активация) происходит в функции write_status] this.onchange_status = false; this.testing_connect = Pred_testing_connect; var self_testing = this; this.testing_TimerID = setInterval(function() { self_testing.testing_connect() },test_interval); } // end function create_test_conn_obj(test_interval) //===================================================== //===================================================== if(typeof(getPosition) != "function"){ // определение позиции верхнего левого угла элемента на странице function getPosition(e){ var left = 0; var top = 0; while (e.offsetParent){ left += e.offsetLeft; top += e.offsetTop; e = e.offsetParent; } left += e.offsetLeft; top += e.offsetTop; return {x:left, y:top}; } } if(typeof(getElementPosition) != "function"){ // координаты элемента // на выходе - объект со свойствами left, top, width, height, несущими координаты элемента function getElementPosition(elemId) { var elem = document.getElementById(elemId); var w = elem.offsetWidth; var h = elem.offsetHeight; var l = 0; var t = 0; if(navigator.appName != "Opera" ){ while (elem) { l += elem.offsetLeft; t += elem.offsetTop; elem = elem.offsetParent; } } else { l = elem.offsetLeft; t = elem.offsetTop; } return {"left":l, "top":t, "width": w, "height":h}; } // end function getElementPosition(elemId) } //********************************************************************* if( (typeof(mouseCoords) != "function") && ( typeof(getMouseOffset) != "function" )){ //=============== // определение координат мышки () function mouseCoords(ev){ if(ev.pageX || ev.pageY){ return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop }; } // относительная позиция координат (относительно объекта target) function getMouseOffset(target, ev){ ev = ev || window.event; var docPos = getPosition(target); var mousePos = mouseCoords(ev); return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y}; } //********************************************************************* } //*********************************************************** //*********************************************************** //** Блок функций, связанных с формированием списка // добавление узла (P) для обеспечения выбора значений function add_p_node(in_obj, in_val, target_input){ var p_node = document.createElement("P"); p_node.innerHTML = in_val; /* прописываем события */ p_node.onmouseover = function(){this.className="p_list_active";}; p_node.onmouseout = function(){this.className="p_list_deactive";}; // событие передачи значения элемента в текстовое поле (задано ссылкой на объект текстового поля) p_node.target_input = target_input; // ссылку на объект передаем как свойство созданного объекта P p_node.onclick = function(event){send_value(this,this.target_input,event); return false;}; // прописываем в документе in_obj.appendChild(p_node); } // end function add_p_node // --------------------------------------------------- // передача значения из списка выбора в текстовое поле function send_value(from_obj,target_obj,ev){ ev = ev || window.event; target_obj.focus(); target_obj.value = from_obj.innerHTML; // Перехватываем событие, чтобы не всплывало далее // Вариант Internet Explorer: ev.cancelBubble = true // Вариант стандарта W3C: if (ev.stopPropagation) { ev.stopPropagation(); } } // end function send_value // позиционирование divMessage function place_divMessage(in_input_obj){ var el_input = in_input_obj; el_input.koords = getElementPosition(el_input.id); var el_divMessage = document.getElementById('divMessage'); el_divMessage.style.left = el_input.koords.left + 'px'; el_divMessage.style.top = el_input.koords.top + el_input.koords.height + 'px'; el_divMessage.style.width = el_input.koords.width + 20 + 'px'; } // end function place_divMessage // --------------------------------------------------- // инициирование (позиционирование и заполнение) divMessage по отношению к полю target_input // источник данных values_arr function init_div_select(target_input,values_arr){ // добавляем к документу отлавливаетель клика ВНЕ divMessage, // чтобы "закрывать" divMessage addHandler(document, 'click', onclick_outside); var el_divMessage = document.getElementById('divMessage'); el_divMessage.style.visibility = "hidden"; el_divMessage.style.display = "block"; // добавляем "список значений" for(var i=0; i< values_arr.length; i++ ){ add_p_node(el_divMessage, values_arr[i], target_input); } // добавляем значение "Закрыть" var p_node = document.createElement("P"); p_node.className = "p_list_close"; p_node.innerHTML = "Закрыть"; p_node.style.cursor = "pointer"; // прописываем в документе el_divMessage.appendChild(p_node); // пристыковываем divMessage к элементу target_input place_divMessage(target_input); el_divMessage.style.visibility = "visible"; // блок установки свойства divMessage.activated = true // свойство устанавливается с задержкой, чтобы избежать возможных // конфликтов между текущими событиями 'click' и включением в работу // "отлавливаетеля" клика для закрытия divMessage (при клике вне div-а, при открытом divMessage) el_divMessage.f_activated = function(){this.activated = true;}; el_divMessage.link_input = target_input; // включаем ссылку на целевое поле ввода, как метод divMessage var tmp_func = el_divMessage; setTimeout(function() { tmp_func.f_activated() },50); } // end function init_div_select // --------------------------------------------------- // очистка и скрытие списка выбора divMessage function clear_div_select(){ var el_divMessage = document.getElementById('divMessage'); el_divMessage.innerHTML = ""; // очищаем el_divMessage.activated = false; el_divMessage.link_input = null; el_divMessage.style.display = "none"; removeHandler(document, 'click', onclick_outside); } // end function clear_div_select // --------------------------------------------------- // определение клика вне списка выбора... function onclick_outside(event){ var el_divMessage = document.getElementById('divMessage'); // если список не активирован, возвращаемся if(el_divMessage.activated != true) return true; // определяем где (относительно el_divMessage) произошел клик // целевой объект клика var t = event.target || event.srcElement // если клик произошел в целевом поле, ничего не делаем if(t == el_divMessage.link_input) return true; // убираем список выбора clear_div_select(); return true; // на случай неполадок.. alert("document.onclick !!!!!! (function onclick_outside)"); return true; } // end function onclick_outside // --------------------------------------------------- //*********************************************************** //*********************************************************** //** Блок функций, связанных с полем ввода function key_manage(in_txt_obj,in_event){ var ev = in_event || window.event; var arr_key = ev.keyCode var el_divMessage = document.getElementById('divMessage'); var status_div = (typeof el_divMessage.activated == 'undefined' ? false : el_divMessage.activated); switch(arr_key){ case 27: // нажата клавиша Esc // убираем divMessage (если он активен) var el_divMessage = document.getElementById('divMessage'); var status_div = (typeof el_divMessage.activated == 'undefined' ? false : el_divMessage.activated); if(status_div) clear_div_select(); // специально для предотвращения дальнейшего убирания значения данных поля in_txt_obj В IE in_txt_obj.esc_flag = true; in_txt_obj.esc_val = in_txt_obj.value; in_txt_obj.focus(); return false; case 8: // нажата клавиша Backspace case 9: // нажата клавиша Tab if(status_div) clear_div_select(); return true; case 13: // нажата клавиша Enter if(status_div){ // определяем (по className="p_list_active" ) выделенный элемент var p_arr = el_divMessage.getElementsByTagName("P"); for(var i=0; i < p_arr.length; i++){ if(p_arr[i].className == "p_list_active"){ send_value(p_arr[i],in_txt_obj,ev); clear_div_select(); } } } return true; case 40: // нажата клавиша стрелка вниз if(status_div){ var p_founded = false; var p_arr = el_divMessage.getElementsByTagName("P"); for(var i=0; i < p_arr.length; i++){ if(p_arr[i].className == "p_list_active"){ p_founded = true; break; } } // end for(var i=0; i < p_arr.length; i++) if(p_founded){ if(typeof p_arr[i+1] == 'undefined' ) return true; if(p_arr[i+1].className == "p_list_close" ) return true; p_arr[i].className="p_list_deactive"; p_arr[i+1].className="p_list_active"; } else { p_arr[0].className="p_list_active"; } } else { // status_div - неактивен... // открываем подсказки, если нажата кнопка вниз.. var val = in_txt_obj.value.trim(); if(val.length > 0){ prepare_divMessage_local(in_txt_obj,val); } } // end if(status_div) break; case 38: // нажата клавиша стрелка вверх if(status_div){ var p_founded = false; var p_arr = el_divMessage.getElementsByTagName("P"); for(var i=0; i < p_arr.length; i++){ if(p_arr[i].className == "p_list_active"){ p_founded = true; break; } } // end for(var i=0; i < p_arr.length; i++) if(p_founded){ if((i-1) < 0) return true; if(typeof p_arr[i-1] == 'undefined' ) return true; p_arr[i].className="p_list_deactive"; p_arr[i-1].className="p_list_active"; } else { clear_div_select(); } } // end if(status_div) break; } // end switch(arr_key) return true; } // end function key_manage // --------------------------------------------------- // первичное? формирование списка function first_analiz(in_txt_obj,in_event){ var ev = in_event || window.event; var key = (typeof ev.charCode == 'undefined' ? ev.keyCode : ev.charCode); // "отменяем" ESC if(key == 27) { if( (typeof in_txt_obj.esc_flag != 'undefined') && in_txt_obj.esc_flag) { in_txt_obj.focus(); // на случай если браузер при Esc очищает поле, // восстанавливаем его значение in_txt_obj.esc_flag = false; in_txt_obj.value = in_txt_obj.esc_val; } return false; } // пропускаем управляющие клавиши if (ev.ctrlKey || ev.altKey || (key < 41 && key != 32)) return true; var val = in_txt_obj.value; var keyChar = String.fromCharCode(key); //alert(keyChar); val = val + keyChar; // добавляем вводимый символ к тому, что имеется в поле (при обработке события он еще в поле не пропечатан) if(val.trim().length > 0){ var el_divMessage = document.getElementById('divMessage'); var status_div = (typeof el_divMessage.activated == 'undefined' ? false : el_divMessage.activated); if(status_div) clear_div_select(); prepare_divMessage_local(in_txt_obj,val); } } // end function first_analiz // --------------------------------------------------- // подготовка данных на основе локального списка function prepare_divMessage_local(in_txt_obj,val){ var limit = 14; // ограничение на количество элементов списка var legend = in_txt_obj.id; var val = val || ""; var reg_space = new RegExp('\s','g'); val = val.replace(reg_space,""); //var reg_val = new RegExp('^'+ val +'.*','gi'); // делаем регулярку на основе введенного значения var reg_val = new RegExp('^'+ val,'i'); // делаем регулярку на основе введенного значения //alert(val); // нет такого предварительного списка.... if(typeof row_str_obj[legend] == 'undefined') return false; var tmp_arr = row_str_obj[legend].split(";"); var count_list_arr = new Array; var count = 0; for(var i=0; i limit) break; } } // нет совпадений if(count == 0) return false; // есть список... init_div_select(in_txt_obj,count_list_arr); } // end function prepare_divMessage_local // ---------------------------------------------------