Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   innerHTML и скрипты (https://javascript.ru/forum/events/60377-innerhtml-i-skripty.html)

alavrova_78 25.12.2015 12:08

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 = "Ошибка при отправке формы";
                }
             });
        }

В ответе присутствуют скрипты, но не работают. Как заставить их выполняться?

Dilettante_Pro 28.12.2015 12:22

Дело в том, что у вас при получении ответа в выбранный вами элемент HTML вписывается текст через свойство innerHTML. При этом вписанные элементы HTML работают, а вписанные скрипты - нет. Они при такой загрузке не обрабатываются, а грузятся, как простой текст, и могут еще и вызывать ошибки.
Для нормальной активизации динамически подгружаемого скрипта нужно создавать объект document.createElement ('script'); и задавать все прочие его свойства.

ruslan_mart 28.12.2015 14:04

response = response.replace(/<script(?:.*?)>([\s\S]*?)<\/script>/gi, function(m, script) {
    eval(script);
    return '';
});

Dilettante_Pro 28.12.2015 16:51

Цитата:

Сообщение от Ruslan_xDD (Сообщение 401715)
response = response.replace(/<script(?:.*?)>([\s\S]*?)<\/script>/gi, function(m, script) {
    eval(script);
    return '';
});

Работоспособность такого варианта зависит от загружаемого скрипта.
Если там простая строчка/несколько строчек для исполнения сразу после загрузки - то все ОК, а если, например, определение функции - то функция останется неопределенной.
Жалко, что alavrova_78 молчит - ее вопрос слишком в общей форме...

ruslan_mart 28.12.2015 17:08

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 '';
});


:)

Dilettante_Pro 28.12.2015 17:34

Цитата:

Сообщение от Ruslan_xDD (Сообщение 401745)
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);
});


:)

Количество вариантов растет... а топикстартер молчит...

CHER84 06.01.2016 01:17

Сам сейчас столкнулся с данной проблемой, поэтому понимаю топикстартера, так как для сбора данных формы использую абсолютно такую же конструкцию как у топикстартера.
Если своими словами описывать проблему:
На сайте есть динамически подгруженное окно
$("#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, а вот теперь никуда не деться.

laimas 06.01.2016 01:47

В методе .load() можно задать не только адресата принимающего данные сервера, отправляемые данные, но и callback функцию, которая будет выполнена после запроса. Если требуется выполнение сценариев после запроса, то они в общем то могут уже быть заданы, а ответ сервера только определяет что из них запустить. Что-то не видно тут проблемы, или я не понимаю сути.

CHER84 06.01.2016 01:54

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?

laimas 06.01.2016 02:11

Цитата:

Сообщение от CHER84
о помимо простого html там еще куски JS кода...

Зачем? Определить необходимые сценарии и подключать их сразу можно или это по каким либо причинам не желательно?
Если клиент сам знает, что необходимо выполнить, то вообще просто, если же определяется условиями от сервера, то ведь и он может передавать то, что необходимо запустить. Но в данном случае лучше работать с 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>


Работает?

CHER84 06.01.2016 02:20

<?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>

я пару недописанных символов добавил, да, код работает. Спасибо, сейчас буду размышлять над ним.
И вообще большое спасибо за оперативный ответ, я не ожидал такого оперативного отклика.
А код должен сгенерироваться именно на динамической странице, поэтому не имею возможности заранее написать его в статической.

laimas 06.01.2016 02:27

Цитата:

Сообщение от CHER84
А код должен сгенерироваться именно на динамической странице

Все может быть, но ведь есть такое понятие как аргументы, а что еще надо... Если json-ответ содержит ключ exe, то вложенный его массив описывает функции с их аргументами, которые нужно выполнить на клиенте. А на клиенте объект exe = {name1:function() {...}, name2:function(arguments){...}}

Если подумать, то многое сводится к универсальности, а значит можно иметь "скелет готовый". Хотя все может быть, может и нужна необходимость гонять скрипты между сервером и клиентом, трудно сказать не видя и не зная всего.

CHER84 06.01.2016 02:30

Я не считаю себя особо опытным в этом деле, поэтому думаю, что Вы правы. Возможно через какое-то время я к этому и приду, а пока стараюсь писать код на уровне своего понимания =)

laimas 06.01.2016 02:37

Цитата:

Сообщение от CHER84
я пару недописанных символов добавил

Каких, фигурные скобки условия? Они не нужны в данном случае.

CHER84 06.01.2016 02:41

да, открывающую фигурную скобку {
и закрывающий ?>
я в notepad++ работаю он код подсвечивает, а без этих символов каша получалась, да и вообще если есть закрывающая скобка - должна быть и открывающая, а если где-то мы сказали, что с этой строчки пойдет php код, то должны сказать, где этот код закончится.

laimas 06.01.2016 02:44

Я исправил, просто вы взяли код до исправления. Если условие или тело цикла это одна операция, то фигурные скобки не нужны, это уже роскошь. )

CHER84 06.01.2016 02:56

Позвольте еще вопрос
$.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 || '');
        });

происходит преобразование текста в код, вернее куски текста, представляющие из себя код начинают восприниматься кодом, а не текстом?

laimas 06.01.2016 03:07

Цитата:

Сообщение от CHER84
Не могу понять смысла строчки
$('#mydiv').html(dom.find('#something').html());

То что прислал сервер (data), это просто строка, а после

var dom = $(data);

это уже объект (jq), а dom.find('#something').html() находит в этом объекте объект с id=something получая его html, ну и вставляет в mydiv.

Цитата:

Сообщение от CHER84
происходит преобразование текста в код

Да, а $.globalEval() отличается от javascript-метода eval() в глобальной области выполнения.

рони 06.01.2016 03:10

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, его отыскали и вывели на экран

    }
});

CHER84 06.01.2016 03:16

Спасибо за пояснения, кажется я нащупал решение своей проблемы.
Выложу здесь код, там минимум изменений получится с первоначальным вариантом, так что должно быть полезным.
Суть сводится к слкдующему:
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 быть именно кодом, а не текстом, разрешился, так что надеюсь поможет кому-то еще =)

решение нашел здесь
Извиняюсь, если запрещены ссылки на сторонние ресурсы, там англоверсия, не каждый будет читать, собственно и я не читал - пробежался по коду просто.

laimas 06.01.2016 03:32

function myFunction(){ - это объявленная функция
$(document).ready(function() - это событие

Где вы такое нашли, да еще по указанной ссылке?

CHER84 06.01.2016 04:24

Все-таки есть некоторое неудобство в том решении, которое я выше описывал.
Решил сделать по-другому.
Кнопкой сабмит вызываем функцию:
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();

Но как из массива объектов сделать приемлемую форму для передачи данных - тоже не могу разобраться.

CHER84 06.01.2016 04:25

Цитата:

Сообщение от laimas (Сообщение 402753)
function myFunction(){ - это объявленная функция
$(document).ready(function() - это событие

Где вы такое нашли, да еще по указанной ссылке?

это уже я наворотил, поэтому и не нравится мне такой подход =)

laimas 06.01.2016 04:43

Цитата:

Сообщение от CHER84
Но как из массива объектов сделать приемлемую форму для передачи данных

Не понял о какой форме речь, $("#"+form_id).serializeArray() это данные формы в виде объекта для передачи серверу, а что значит создать приемлемую форму?

CHER84 06.01.2016 04:58

Я имею ввиду такой тип данных, который бы корректно воспринялся.
например, когда я пишу код вот так:
$("#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 ...

CHER84 06.01.2016 05:15

var dataVar = $("#"+form_id).serializeArray();
		
		alert(dataVar);
		$("#modal_form").load(
		"/ajax/registration.php",dataVar
		);


Вот так без фигурных скобок работает и передает данные.
Спасибо за оказанную помощь, Вы мне очень помогли, по сути в теме уже два варианта решения проблемы и второй мне больше нравится, так как в нем мы никуда не уходим от метода load, который без дополнительных танцев с бубном воспринимает JS как код.
У меня голова уже пухнет, поэтому отложу увлекательное ковыряние на завтра =)

laimas 06.01.2016 05:26

Цитата:

Сообщение от CHER84
Вот так без фигурных скобок работает и передает данные.

Ну так зачем же они, если var dataVar = $("#"+form_id).serializeArray(); и есть объект?

Но это не ответ на вопрос "о какой форме речь". Вообще не понятно - зачем возвращать на страницу формы регистрации при ошибках, если ошибки нужно проверять в сеансе регистрации, а значит и так находимся в форме? Скорее нужен переход на страницу завершения регистрации при успехе. В вашем случае нужен диалог, а его удобнее вести посредством JSON формата, и лучше не .load() использовать, а .ajax() метод. Это будет более гибкое решение, да и не зная всего уверен, что многое можно иметь готовым на клиенте, не гоняя в данных сценариев.


Часовой пояс GMT +3, время: 16:02.