innerHTML и скрипты
Всем привет!
Есть код: function AjaxFormRequest(result_id,form_id,url) { jQuery.ajax({ url: url, type: "POST", dataType: "html", data: jQuery("#"+form_id).serialize(), success: function(response) { document.getElementById(result_id).innerHTML = response; }, error: function(response) { document.getElementById(result_id).innerHTML = "Ошибка при отправке формы"; } }); } В ответе присутствуют скрипты, но не работают. Как заставить их выполняться? |
Дело в том, что у вас при получении ответа в выбранный вами элемент HTML вписывается текст через свойство innerHTML. При этом вписанные элементы HTML работают, а вписанные скрипты - нет. Они при такой загрузке не обрабатываются, а грузятся, как простой текст, и могут еще и вызывать ошибки.
Для нормальной активизации динамически подгружаемого скрипта нужно создавать объект document.createElement ('script'); и задавать все прочие его свойства. |
response = response.replace(/<script(?:.*?)>([\s\S]*?)<\/script>/gi, function(m, script) { eval(script); return ''; }); |
Цитата:
Если там простая строчка/несколько строчек для исполнения сразу после загрузки - то все ОК, а если, например, определение функции - то функция останется неопределенной. Жалко, что alavrova_78 молчит - ее вопрос слишком в общей форме... |
response = response.replace(/<script(?:.*?)>([\s\S]*?)<\/script>/gi, function(m, code) { var script = document.createElement('script'); script.type = 'text/javascript'; script.appendChild(document.createTextNode(code)); document.head.appendChild(script); return ''; }); :) |
Цитата:
|
Сам сейчас столкнулся с данной проблемой, поэтому понимаю топикстартера, так как для сбора данных формы использую абсолютно такую же конструкцию как у топикстартера.
Если своими словами описывать проблему: На сайте есть динамически подгруженное окно $("#modal_form").load("/ajax/registration.php"); в файле регистрации куча различных полей для ввода информации, включая ползунок слайдер, для работоспособности которого подтянута библиотека UI. Плюс в зависимости от выбранного select (тип пользователя) всё окошко обновляется и для каждого типа пользователя отдается свой набор полей формы. Происходит это тоже посредством load /* перезагрузка при выборе определенного select */ $('#sel_who').change( function(){ var myOption = $("#sel_who").val(); $("#modal_form").load( "/ajax/registration.php", { whoareyou: myOption // передаем переменную, заданную в option }); }); Эта перезагрузка идет уже из самого динамически подгруженного файла, то есть на данном этапе JS воспринимается как код. Далее после заполнения формы пользователь жмет на кнопку отправки формы и должен перейти ко второму шагу (загрузка изображений, которые привяжутся к вновь созданному пользователю), но прежде нужно проверить корректность отправленных данных. Их я проверяю средствами php в том же registration.php и при возникновении ошибки пытаюсь той же конструкцией load отправить пользователя на страницу формы и расставить все правильные переменные по своим полям, чтобы пользователю не пришлось все заново набирать $("#modal_form").load( "/ajax/registration.php", { whoareyou: '.$whoareyou.', step: 0, name1: '.$name1.', name2: '.$name2.', name3: '.$name3.', year: '.$year.', month: '.$month.', day: '.$day.', country: '.$country.', city: '.$city.', art_direction: '.$art_direction.', age_restrictions: '.$age_restrictions.', mincost: '.$mincost.', maxcost: '.$maxcost.', education: '.$education.', events: '.$events.', public: '.$public.', email: '.$email.', pass_err_code: '.$pass_err_code.', comeback: 1 }); как раз отрабатывает конструкция, указанная у топикстартера и из-за innerHTML весь JS код превращается в простой текст из-за того, что этот кусочек кода динамически собирается в .php я не могу вынести его в отдельный файл, для отдельного файла, как я понял, существует getscript. для полноты картины ниже приведу код подключаемых библиотек и скриптов, в динамически подгруженном файле <!-- Скрипты добавляем, чтобы работал ползунок --> <script type="text/javascript" src="js/jquery-1.6.1.min.js"></script> <script type="text/javascript" src="/js/jquery.ui-slider.js"></script> <script type="text/javascript" src="/js/jquery.main.js"></script> <!-- КОНЕЦ Скрипты добавляем, чтобы работал ползунок --> <script> $(document).ready(function() { // вся мaгия пoсле зaгрузки стрaницы $("#modal_form").load( "/ajax/registration.php", { whoareyou: '.$whoareyou.', step: 0, name1: '.$name1.', name2: '.$name2.', name3: '.$name3.', year: '.$year.', month: '.$month.', day: '.$day.', country: '.$country.', city: '.$city.', art_direction: '.$art_direction.', age_restrictions: '.$age_restrictions.', mincost: '.$mincost.', maxcost: '.$maxcost.', education: '.$education.', events: '.$events.', public: '.$public.', email: '.$email.', pass_err_code: '.$pass_err_code.', comeback: 1 }); /* перезагрузка при выборе определенного select */ $('#sel_who').change( function(){ // лoвим клик пo крестику или пoдлoжке var myOption = $("#sel_who").val(); $("#modal_form").load( "/ajax/registration.php", { whoareyou: myOption // передаем переменную, заданную в option }); }); /* Зaкрытие мoдaльнoгo oкнa */ $('#modal_close, #overlay').click( function(){ // лoвим клик пo крестику или пoдлoжке $('#modal_form') .animate({opacity: 0, top: '45%'}, 200, // плaвнo меняем прoзрaчнoсть нa 0 и oднoвременнo двигaем oкнo вверх function(){ // пoсле aнимaции $(this).css('display', 'none'); // делaем ему display: none; $('#overlay').fadeOut(400); // скрывaем пoдлoжку } ); }); }); </script> Извините, если сумбурно описал проблему, первый раз на форуме вопрос задаю. Хочется уже для себя определиться, как сделать текст кодом, потому что проблема вылезает уже не в первый раз, раньше обходил ее так, чтобы после отправки формы уже не требовались скрипты JS, а вот теперь никуда не деться. |
В методе .load() можно задать не только адресата принимающего данные сервера, отправляемые данные, но и callback функцию, которая будет выполнена после запроса. Если требуется выполнение сценариев после запроса, то они в общем то могут уже быть заданы, а ответ сервера только определяет что из них запустить. Что-то не видно тут проблемы, или я не понимаю сути.
|
function AjaxFormRequest(result_id,form_id,url) { jQuery.ajax({ url: url, //Адрес подгружаемой страницы type: "POST", //Тип запроса dataType: "html", //Тип данных data: jQuery("#"+form_id).serialize(), success: function(response) { //Если все нормально alert(response); document.getElementById(result_id).innerHTML = response; /*$("#modal_form").load("/ajax/registration.php");*/ }, error: function(response) { //Если ошибка document.getElementById(result_id).innerHTML = "Ошибка при отправке формы"; } }); }; Вот с помощью этой конструкции я отправляю данный формы на обработку в файл registration.php document.getElementById(result_id).innerHTML = response; Вот эта строка показывает результат отработавшего registration.php, но помимо простого html там еще куски JS кода, но они не выполняются, поскольку из-за innerHTML воспринимаются как текст. В документации на этот случай предлагают использовать eval или globalEval(code) document.getElementById(result_id).innerHTML = eval(response); такая конструкция не возвращает мне ничего, хотя алертом, который на строчку выше, я получаю вменяемый код ожидаемой страницы. Возможно я неправильно использую eval? |
Цитата:
Если клиент сам знает, что необходимо выполнить, то вообще просто, если же определяется условиями от сервера, то ведь и он может передавать то, что необходимо запустить. Но в данном случае лучше работать с json-форматом, в котором каждый ключ определяет действия: данные, сообщения, запуск сценария и т.п.. Ну если надо подключение скриптов присланных сервером, то в среде JQ с этим проблем нет, выполните пример: <?php if($_POST) exit('<span>Text</span><script>$(function(){alert(1)});</script>'); ?> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script> $(function() { $('button').click(function() { $.post(location, {a:1}, function(d) { $('#as').html(d) }) }) }); </script> </head> <body> <div id="as"></div> <button>GO</button> </body> <html> Работает? |
<?php if($_POST) {exit('<span>Text</span><script> $(function() { alert(1) }); </script>'); } ?> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script> $(function() { $('button').click(function() { $.post(location, {a:1}, function(d) { $('#as').html(d) }) }) }); </script> </head> <body> <div id="as"></div> <button>GO</button> </body> <html> я пару недописанных символов добавил, да, код работает. Спасибо, сейчас буду размышлять над ним. И вообще большое спасибо за оперативный ответ, я не ожидал такого оперативного отклика. А код должен сгенерироваться именно на динамической странице, поэтому не имею возможности заранее написать его в статической. |
Цитата:
Если подумать, то многое сводится к универсальности, а значит можно иметь "скелет готовый". Хотя все может быть, может и нужна необходимость гонять скрипты между сервером и клиентом, трудно сказать не видя и не зная всего. |
Я не считаю себя особо опытным в этом деле, поэтому думаю, что Вы правы. Возможно через какое-то время я к этому и приду, а пока стараюсь писать код на уровне своего понимания =)
|
Цитата:
|
да, открывающую фигурную скобку {
и закрывающий ?> я в notepad++ работаю он код подсвечивает, а без этих символов каша получалась, да и вообще если есть закрывающая скобка - должна быть и открывающая, а если где-то мы сказали, что с этой строчки пойдет php код, то должны сказать, где этот код закончится. |
Я исправил, просто вы взяли код до исправления. Если условие или тело цикла это одна операция, то фигурные скобки не нужны, это уже роскошь. )
|
Позвольте еще вопрос
$.ajax({ url: 'example.html', type: 'GET', success: function(data) { var dom = $(data); dom.filter('script').each(function(){ $.globalEval(this.text || this.textContent || this.innerHTML || ''); }); $('#mydiv').html(dom.find('#something').html()); } }); Вот нашел такой кусок кода, внешне фактически то, что использую и я. Не могу понять смысла строчки $('#mydiv').html(dom.find('#something').html()); то есть мы загружаем в блок с id="myDiv" методом html кусок обработанного текста в переменной dom. А вот что дальше? зачем мы ищем в dom #something ? И правильно ли я понимаю, что в строках dom.filter('script').each(function(){ $.globalEval(this.text || this.textContent || this.innerHTML || ''); }); происходит преобразование текста в код, вернее куски текста, представляющие из себя код начинают восприниматься кодом, а не текстом? |
Цитата:
var dom = $(data); это уже объект (jq), а dom.find('#something').html() находит в этом объекте объект с id=something получая его html, ну и вставляет в mydiv. Цитата:
|
CHER84,
$.ajax({ url: 'example.html', type: 'GET', success: function(data) { //пришла строка var dom = $(data); //превратили строку в html dom.filter('script').each(function(){ //нашли содержимое всех сриптов в этом html $.globalEval(this.text || this.textContent || this.innerHTML || '');//запустили все скрипты, которые нашли при помощи плагина }); $('#mydiv').html(dom.find('#something').html()); // весь html нам не нужен, а нужен только элемент something, его отыскали и вывели на экран } }); |
Спасибо за пояснения, кажется я нащупал решение своей проблемы.
Выложу здесь код, там минимум изменений получится с первоначальным вариантом, так что должно быть полезным. Суть сводится к слкдующему: document.getElementById(result_id).innerHTML = response; myFunction(); запускаем именованную функцию, а уже внутрь этой функции засовываем то, что нам нужно, то есть в моем подгружаемом файлике образовалась еще такая конструкция: function myFunction(){ $(document).ready(function() { alert ("hi"); /* Зaкрытие мoдaльнoгo oкнa, тут делaем тo же сaмoе нo в oбрaтнoм пoрядке */ $('#modal_close, #overlay').click( function(){ // лoвим клик пo крестику или пoдлoжке $('#modal_form') .animate({opacity: 0, top: '45%'}, 200, // плaвнo меняем прoзрaчнoсть нa 0 и oднoвременнo двигaем oкнo вверх function(){ // пoсле aнимaции $(this).css('display', 'none'); // делaем ему display: none; $('#overlay').fadeOut(400); // скрывaем пoдлoжку } ); }); }); } и алерт и код закрывания окошка по нажатию на крестик заработали, а вот перезагрузка методом load пока сопротивляется, буду дожимать =) По сути принципиальный вопрос: как заставить код JS быть именно кодом, а не текстом, разрешился, так что надеюсь поможет кому-то еще =) решение нашел здесь Извиняюсь, если запрещены ссылки на сторонние ресурсы, там англоверсия, не каждый будет читать, собственно и я не читал - пробежался по коду просто. |
function myFunction(){ - это объявленная функция
$(document).ready(function() - это событие Где вы такое нашли, да еще по указанной ссылке? |
Все-таки есть некоторое неудобство в том решении, которое я выше описывал.
Решил сделать по-другому. Кнопкой сабмит вызываем функцию: function formSubmit(result_id,form_id,url){ //var dataVar = jQuery("#"+form_id).serializeArray(); var dataVar = $("#"+form_id).serialize(); // var1=1&var2=0&... var dataVar = dataVar.replace(/&/g,","); // var1=1,var2=0, ... var dataVar = dataVar.replace(/=/g,":"); // var1:1,var2:0, ... $("#modal_form").load( "/ajax/registration.php", { dataVar }); } не работает... пробую задать параметры вручную function formSubmit(result_id,form_id,url){ //var dataVar = jQuery("#"+form_id).serializeArray(); var dataVar = $("#"+form_id).serialize(); // var1=var1&var2=var2&... var dataVar = dataVar.replace(/&/g,","); // var1=var1,var2=var2, ... var dataVar = dataVar.replace(/=/g,":"); // var1:var1,var2:var2, ... $("#modal_form").load( "/ajax/registration.php", { var1: 1,var2:0 }); } этот вариант работает Я понимаю, что проблема в типе передаваемых данных, но не могу найти решения, пишут, что для load можно передавать строку, но на практике не проходит такой вариант. Еще нашел, что нужно использовать var dataVar = $("#"+form_id).serializeArray(); Но как из массива объектов сделать приемлемую форму для передачи данных - тоже не могу разобраться. |
Цитата:
|
Цитата:
|
Я имею ввиду такой тип данных, который бы корректно воспринялся.
например, когда я пишу код вот так: $("#modal_form").load( $("#modal_form").load( "/ajax/registration.php", { var1: 1, var2: 0 }); то данные успешно передаются и я могу с ними работать Но когда я делаю var dataVar = 'var1:1,var2:0'; $("#modal_form").load( "/ajax/registration.php", { dataVar }); то данные не передаются. Соответственно я предполагаю, что проблема в типе передаваемых данных http://jquery-docs.ru/Ajax/load/#source здесь сказано " данные (необязательно) Map,Строка Пары ключ/значение, которые будут отосланы на сервер. Начиная с jQuery 1.3 может также передаваться строка данных. При указании строки, запрос будет типа GET, для всего остального — типа POST. " http://jquery-docs.ru/Types/ тут я не смог найти что такое мар, строка В моем представлении строк два представленных выше куска кода должны одинаково отрабатывать, но видимо я чего-то не понимаю. Это я пока не касаюсь serializeArray, потому что возвращаемое им для меня еще более непонятно и как это привести к более наглядной форме я пока не понял, просто массив, переданный как данные var dataVar = jQuery("#"+form_id).serializeArray(); $("#modal_form").load( "/ajax/registration.php", { dataVar }); тоже не дает никакого результата, всмысле данные теряются, но тут не так обидно, они изначально [object Object] и требуется какая-то обработка, для приведения их к виду var1:1,var2:0 ... |
var dataVar = $("#"+form_id).serializeArray(); alert(dataVar); $("#modal_form").load( "/ajax/registration.php",dataVar ); Вот так без фигурных скобок работает и передает данные. Спасибо за оказанную помощь, Вы мне очень помогли, по сути в теме уже два варианта решения проблемы и второй мне больше нравится, так как в нем мы никуда не уходим от метода load, который без дополнительных танцев с бубном воспринимает JS как код. У меня голова уже пухнет, поэтому отложу увлекательное ковыряние на завтра =) |
Цитата:
Но это не ответ на вопрос "о какой форме речь". Вообще не понятно - зачем возвращать на страницу формы регистрации при ошибках, если ошибки нужно проверять в сеансе регистрации, а значит и так находимся в форме? Скорее нужен переход на страницу завершения регистрации при успехе. В вашем случае нужен диалог, а его удобнее вести посредством JSON формата, и лучше не .load() использовать, а .ajax() метод. Это будет более гибкое решение, да и не зная всего уверен, что многое можно иметь готовым на клиенте, не гоняя в данных сценариев. |
Часовой пояс GMT +3, время: 11:43. |