Другой вариант обертки Аякса. Вместо создания собственной разметки ответов и, соответственно, парсера для нее, попробуем использовать JSON с соответствующим функционалом.
Структура будет иметь следующий вид:
Значения свойств элементов оставляем почти все те же:Код:{ "element": [ { "target": "test1", "property": "innerHTML", "method": "getElementById", "overwrite": "false", "html": { "text": "text 1", "array": null }, "script": "alert('test1 alert')" }, { "target": "test2", "property": "innerHTML", "method": "getElementById", "overwrite": "false", "html": { "text": "", "array": [ {"name": "new 1", "value": 1}, {"name": "new 2", "value": 2} ] } } ], "cookie": [ {"name": "cookie 1", "value": 1} ], "script": "alert('all alert')" }
target - id цели или CSS3 селектор;
property - изменяемое свойство цели. По умолчанию - innerHTML;
method - метод выборки цели. По умолчанию - getElementById. Поддерживаются методы getElementsByTagName, getElementsByName, getElementsByClassName, querySelector и querySelectorAll;
overwrite - (true/false) указывает, перезаписывать или дополнять содержимое цели. По умолчанию true.
html.text - собственно, html код, передающийся указанному свойству указанного элемента.
html.object - а здесь пишем код для элементов, требующих js конструктор на стороне клиента. Например, элементы select или свойства style, setAttribute, classList.
script - js скрипт, отправляемый на выполнение. Исполняется сразу после изменения свойств цели, в блоке которой был указан.
bscript - на всякий случай. То же самое, только выполнится перед изменением свойств указанной цели.
Кроме того, возможно указание общих для всех элементов функций:
cookie - создаст указанную куки.
script - js скрипт, исполняющийся после изменения свойств всех элементов.
bscript - js скрипт, исполняющийся в самом начале, перед изменением свойств всех элементов.
Все элементы структуры могут быть представлены как в виде массивов, так и в виде одиночных значений.
На перловой стороне код будет выглядеть так:
1. Инициализируем кодер json
2. Добавим куда-нибудь подпрограммы - конструкторы элементов. Для простоты.Код:#!/usr/bin/perl use JSON::XS; $coder = JSON::XS->new->utf8; my $json; @{$json->{element}} = ();
3. Создаем, собственно, сами элементыКод:sub html_element { my $el; $el->{target} = ($_[0]) ? $_[0] : ''; $el->{property} = ($_[1]) ? $_[1] : 'innerHTML'; $el->{method} = ($_[2]) ? $_[2] : 'getElementById'; $el->{overwrite} = ($_[3]) ? $_[3] : 'true'; $el->{html}->{text} = ($_[4]) ? $_[4] : ''; $el->{html}->{object} = (); return $el; } sub html_select { my $el; $el->{'value'} = $_[0]; $el->{'text'} = $_[1]; if ($_[2] eq 'true') { $el->{'selected'} = true; } return $el; } sub html_attrib { my $el; $el->{'name'} = $_[0]; $el->{'value'} = $_[1]; return $el; } sub html_cookie { my $el; my %hash = @_; foreach my $key (keys %hash) { $el->{$key} = $hash{$key}; } return $el; }
4. ну и отправляем все это в браузерКод:$element = html_element('div1'); $element->{html}->{text} = $text1; $element->{script} = "alert('div1 alert')"; push @{$json->{element}}, $element; $element = html_element('div1_class'); $element->{property} = 'style'; $element->{method} = 'getElementsByClassName'; push @{$element->{html}->{object}}, html_attrib('width', '100px'); push @{$json->{element}}, $element; $element = html_element('input1'); $element->{property} = 'value'; $element->{overwrite} = false; $element->{html}->{text} = $text2; push @{$json->{element}}, $element; $element = html_element('select1'); push @{$element->{html}->{object}}, html_select(1, 'option 1'); push @{$element->{html}->{object}}, html_select(2, 'option 2', true); push @{$json->{element}}, $element; $element = html_element('select1'); $element->{property} = 'className'; $element->{html}->{text} = 'class1'; push @{$json->{element}}, $element; $element = html_element('select1'); $element->{property} = 'classList'; push @{$element->{html}->{object}}, html_attrib('add', 'newclass'); push @{$element->{html}->{object}}, html_attrib('delete', 'oldclass'); push @{$element->{html}->{object}}, html_attrib('toggle', 'class_2'); push @{$json->{element}}, $element; $element = html_element('select1'); $element->{property} = 'setAttribute'; push @{$element->{html}->{object}}, html_attrib('src', 'aaa.bbb.ru'); push @{$json->{element}}, $element; $json->{script} = "alert('all elements finish')"; @{$json->{cookie}} = (); my $ctime = time + 600; #время актуальности +- секунды push @{$json->{cookie}}, html_cookie('name' => 'sid', 'value' => $val, 'expires' => $ctime);
В браузере всю эту байду распарсит и применит должным образом такая вот функция:Код:print "Content-Type: application/json\n\n"; print $coder->encode($json);
Напоследок, надо на всякий случай отметить, что читать входящие данные в перле следует гибридным образом:Код:function SendURL(url, frm, asp) { var data = SendURLattrib.form(frm); var xmlHttp = new XMLHttpRequest(); var syn = (!asp || asp == '' || asp == 0) ? true : false; // 1 - синхронный xmlHttp.open("POST", url, syn); xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { var response = xmlHttp.responseText; if (xmlHttp.status == 200) { try {var json = JSON.parse(response)} catch { console.log('Incorrect JSON response from '+url); return; } SendURLattrib.eval(json.bscript); if (json.element) { var element = SendURLattrib.array(json.element); for (var i = 0; i < element.length; i++) { if (!element[i].target || element[i].target == '') continue; if (!element[i].method || element[i].method == '') element[i].method = 'getElementById'; var obj = document[element[i].method](element[i].target); if (obj) { SendURLattrib.eval(json.element[i].bscript); obj = SendURLattrib.array(obj); if (!element[i].property || element[i].property == '') element[i].property = 'innerHTML'; if (!element[i].overwrite || element[i].overwrite != 'false') element[i].overwrite = 'true'; if (obj.length == 0) console.log('Not found targets for ' + element[i].target); for (var j = 0; j < obj.length; j++) { if (!obj[j]) continue; if (obj[j].type == "textarea" && element[i].property == 'innerHTML') element[i].html.text = element[i].html.text.replace(/\\n/g, '\n'); if (element[i].property == 'style' || element[i].property == 'setAttribute' || element[i].property == 'classList') SendURLattrib.attrib(obj[j], element[i]); else if (obj[j].type == "select-one" && element[i].property == 'innerHTML') SendURLattrib.select(obj[j], element[i]); else if ((element[i].property == 'innerHTML' || element[i].property == 'value') && element[i].overwrite == 'false') obj[j][element[i].property] += element[i].html.text; else obj[j][element[i].property] = element[i].html.text; } SendURLattrib.eval(json.element[i].script); } else console.log('Error target for '+element[i].target); } } SendURLattrib.eval(json.script); if (json.cookie) { var cookie = SendURLattrib.array(json.cookie); for (var i = 0; i < cookie.length; i++) { if (!cookie[i].name || !cookie[i].value) continue; var ck = cookie[i].name + '=' + encodeURIComponent(cookie[i].value) + ';'; for (var pos in cookie[i]) { if (pos == 'name' || pos == 'value') continue; if (pos == 'expires') cookie[i][pos] = new Date(cookie[i][pos] * 1000).toUTCString(); ck += (' ' + pos + '=' + cookie[i][pos] + ';'); } document.cookie = ck; } } } else console.log('Error Ajax request: '+xmlHttp.status+' from '+url); } } xmlHttp.send(data); } var SendURLattrib = { array(obj) { return (obj instanceof Array) ? obj : [obj]; }, eval(obj) { if (!obj) return; var scr = this.array(obj); for (var i = 0; i < scr.length; i++) eval(scr[i]); }, form(frm) { var data = new FormData(); //data.append('refer', document.getElementById('refer').value); //добавляем к каждому запросу if (document.cookie.length > 0) { var pairs = document.cookie.split(";"); for (var i = 0; i < pairs.length; i++){ var pair = pairs[i].split("="); data.append(pair[0], decodeURIComponent(pair[1])); } } data.append('random', Math.random()); if (!frm || frm == '') return data; var arr = this.array(frm); for (var j = 0; j < arr.length; j++) { var elements = document.forms[arr[j]].querySelectorAll('input, select, textarea'); for (var i = 0; i < elements.length; i++) { if (!elements[i].name || elements[i].name == '') continue; if (["text", "hidden", "password", "textarea"].includes(elements[i].type)) { data.append(elements[i].name, elements[i].value); } if (elements[i].type == "radio" || elements[i].type == "checkbox") { if (elements[i].checked) data.append(elements[i].name, elements[i].value); } if (elements[i].type == "select-one" && elements[i].selectedIndex >= 0) { data.append(elements[i].name, elements[i].options[elements[i].selectedIndex].value); } if (elements[i].type == "file" && elements[i].files.length > 0) { if (elements[i].getAttribute('multiple') == null) { data.append(elements[i].name, elements[i].files[0]); } else { for (var e = 0; e < elements[i].files.length; e++) { data.append((elements[i].name+'_'+e), elements[i].files[e]); } } } } } return data; }, attrib(obj, elem) { var res = this.array(elem.html.object); for (var i = 0; i < res.length; i++) { if (!res[i].name || !res[i].value) continue; if (elem.property == 'style') obj.style[res[i].name] = res[i].value; if (elem.property == 'classList') obj.classList[res[i].name](res[i].value); if (elem.property == 'setAttribute') obj.setAttribute(res[i].name, res[i].value); } }, select(obj, elem) { var res = this.array(elem.html.object); if (elem.overwrite == 'true') obj.options.length = 0; for (var i = 0; i < res.length; i++) { if (!res[i].value || !res[i].text) continue; var opt = document.createElement("option"); opt.appendChild(document.createTextNode(res[i].text)); opt.setAttribute("value", res[i].value); if (res[i].selected && res[i].selected == 'true') opt.selected = true; obj.appendChild(opt); } } }
Код:use CGI ':standard'; my $buffer = $ENV{'QUERY_STRING'}; my @pairs = split(/&/, $buffer); foreach $pair(@pairs) { my ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-f0-9])/chr(hex($1))/eg; $input{$name} = $value; } for my $name (CGI::param()) { for my $value (scalar CGI::param($name)) { $input{$name} = $value; } }
-
Скрыть объявление
Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.
-
Скрыть объявлениеЕсли Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.
Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
- Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
- Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
- Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
- Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
С уважением, администрация форума Old-Games.RU
Комментарии
Сортировать комментарии по