Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Тэг <script> - src и код одновременно? (https://javascript.ru/forum/misc/19194-tehg-script-src-i-kod-odnovremenno.html)

klimashkin 28.07.2011 15:16

Тэг <script> - src и код одновременно?
 
Смотрю на генератор кнопки + от Google:
http://www.google.com/webmasters/+1/button/

Если выбрать какой-нибудь язык отличный от английского, то гугл генерит следующий текст:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
  {lang: 'ru'}
</script>


Что это значит, ведь по канонам это бессмысленно?

ваый 28.07.2011 15:46

ну валидацию, да, не пройдет.
но с другой стороны удобно. браузер просто проигнорирует внутреннюю вставку, в то время как скрипт plusone.js может получить нужные параметры {lang: 'ru', ...} и использовать их для своих нужд.

monolithed 28.07.2011 16:37

Цитата:

Сообщение от ваый
использовать их для своих нужд

как?

e1f 28.07.2011 16:39

Цитата:

Сообщение от monolithed (Сообщение 115854)
как?

innerHTML

ваый 28.07.2011 16:47

Цитата:

Сообщение от e1f (Сообщение 115855)
innerHTML

именно

monolithed 28.07.2011 17:23

e1f, ваый,
Очевидно, но это же полнейшая тупость, когда есть масса нормальных способов (назначить идентификатор, атрибут и пр.).
Не понимаю, для чего такие сложности ? ;)

ваый 28.07.2011 17:28

Ну это нужно у инженеров гугл спрашивать. А мне кажется, что это довольно удобный способ для задания конфигурационных параметров. А что, получить строку с параметрами {lang: 'ru'} проще простого, преобразовать в объект, еще проще. Это лучше, чем передавать параметры в атрибуте src.
monolithed, а как тебе кажется лучше было бы?

melky 28.07.2011 17:30

как получить этот innerHTML из скрипта ?прошу пример ,ваый !

мне кажется, что так.
var a = document.getElementsByTagName('script'), 
	b = a.length,
	options = {};

while( b-- ) 
	if ( ~a[i].src.indexOf("plusone.js") ) 
		options = JSON.parse (  a[i].innerHTML );

alert( options.lang ); // ru ?

ваый 28.07.2011 17:36

melky, можно изящнее.
Полагаю как-то так должно прокатить:
var scripts = document.getElementsByTagName('script');
var thisScript = scripts[scripts.length - 1];
var params = eval('(' + thisScript.innerHTML + ')');
Этот код располагается внутри самого скрипта, который загрузился. Здесь учитывается, что этот самый скрипт на момент загрузки будет самым последним из всех скриптов.

monolithed 28.07.2011 17:56

ваый,

можете не согласиться, однако:

1. наличие кода внутри дескрипторов script с атрибутом src
2. такой способ получения и обработки данных
3. предположение, что этот дескриптор будет последним в документе.

признак быдлокодерства.

Цитата:

Сообщение от ваый
а как тебе кажется лучше было бы?

1. у Google имеется JS API для подключения библиотек:
//заполнено образно
google.load("plusone", {lang : 'ru'});
gapi.plusone.render("plusone", {lang : 'ru'});

2. есть вариант с пространствами имен:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<g:plusone></g:plusone>

ваый 28.07.2011 18:06

monolithed, ну мы не обсуждаем, насколько это красивый стиль кодирования, мы говорим только о том, что это способ который по какой-то причине использует google. Кроме того, я не говорил, что они получают параметры именно таким способом, я лишь отметил, что это очень просто - получить переданные таким образом параметры.
Цитата:

Сообщение от monolithed (Сообщение 115876)
3. предположение, что этот дескриптор будет последним в документе.

:) Это не предположение. Так оно всегда и есть. Каждый из скриптов, на странице, когда он загружается является последним в момент его исполнения. Понимешь о чем, я?

B@rmaley.e><e 28.07.2011 18:19

Цитата:

Сообщение от monolithed
2. есть вариант с пространствами имен:

Оно будет кроссбраузерно и не принесёт проблем с поисковиками?

monolithed 28.07.2011 18:23

Цитата:

Сообщение от ваый
Каждый из скриптов, на странице, когда он загружается является последним в момент его исполнения.

Этот код не отработает:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">{lang: 'ru'}</script>

<script type="text/javascript">
var scripts = document.getElementsByTagName('script');
alert(eval('(' +  scripts[scripts.length - 1].innerHTML + ')').lang);
</script>


Цитата:

Сообщение от B@rmaley.e><e
Оно будет кроссбраузерно и не принесёт проблем с поисковиками?

это альтернативное решение предложеное Google (и такой подход сейчас не редкость, - у Facebook так подключаются Like'и, при наличие смысла тянуть для этого API)

ваый 28.07.2011 18:32

Цитата:

Сообщение от monolithed (Сообщение 115886)
Этот код не отработает:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">{lang: 'ru'}</script>

<script type="text/javascript">
var scripts = document.getElementsByTagName('script');
alert(eval('(' +  scripts[scripts.length - 1].innerHTML + ')').lang);
</script>



Конечно, не отработает. Но я утверждаю, что следующий код отработает:
<script type="text/javascript" src="domain.com/script.js">
{lang: 'ru'}
</script>

Содержимое script.js:
var scripts = document.getElementsByTagName('script');
alert(eval('(' +  scripts[scripts.length - 1].innerHTML + ')').lang);

Я же о том и говорю, что сам скрипт, указанный в атрибуте src, может получить легко доступ к содержимому своего же собственного тэга script.

Пруф:
<html>
<head></head>
<body>
	<script>
	var a = 21;
	</script>
	
	<script src="test.js">
	{'lang': 'ru'}
	</script>
	
	<script>
	var b = 17;
	</script>
</body>
</html>

test.js:
var scripts = document.getElementsByTagName('script');
var thisScript = scripts[scripts.length - 1];
var params = eval('(' + thisScript.innerHTML + ')');
alert(params.lang);

Прекрасно работает.

Snipe 28.07.2011 18:44

Не проверял во всех браузерах, но:
<script type="text/javascript" src="domain.com/script.js" onclick="return {a: 'a'}"></script>
<script type="text/javascript">
	var b = document.getElementsByTagName('script')[0].onclick();
	alert(b.a);
</script>


Плюс очевиден - никакого eval.
С другой стороны, не разбирался, как onclick себя вести должен у тега script...

ваый 28.07.2011 18:55

Цитата:

Сообщение от Snipe (Сообщение 115896)
Плюс очевиден - никакого eval.

Используйте JSON.parse, если хотите.
А по-моему, вот этот как раз-таки и не вариант вовсе, что вы предложили. Потому как это то, что выше monolithed назвал быдлокодингом.

Snipe 28.07.2011 18:57

Цитата:

Сообщение от ваый (Сообщение 115898)
Используйте JSON.parse, если хотите.
А по-моему, вот этот как раз-таки и не вариант вовсе, что вы предложили. Потому как это то, что выше monolithed назвал быдлокодингом.

Ну т.е. брать строку из innerHTML у тега, у которого никакого innerHTML по логике нет - это нормально?

А использовать такой же хак с удобным onclick - это быдлокодинг? :blink:

ваый 28.07.2011 19:04

И то и другое - не очень, согласен. Но onclick все-таки ужаснее, потому что этот атрибут совсем не для этого предназначен. Тогда уже атрибут data. Я ж не спорю, что это спроный вопрос, о целесообразности такого метода с innerHTML. Я только говорю, что это можно удобно использовать.
Опять же - если так беспокоимся о семантичности, можно передавать параметры в самом URL в src, и просто разбирать, парсить URL.
<script src="domain.com/test.js?param=value"></script>

melky 28.07.2011 21:32

monolithed, это не JSON. как ты его отпарсишь?

Цитата:

Сообщение от Snipe (Сообщение 115899)
Ну т.е. брать строку из innerHTML у тега, у которого никакого innerHTML по логике нет - это нормально?

А использовать такой же хак с удобным onclick - это быдлокодинг? :blink:


да...

хм.

alert( typeof HTMLScriptElement.innerHTML ); // undefined


где это свойство?
поискал, нигде нет.

monolithed 28.07.2011 21:44

Цитата:

Сообщение от melky
это не JSON. как ты его отпарсишь?

alert(eval('(' + "{foo : 1}" + ')').foo);


на всякий:

alert(
	({
	   foo : 'text'
	}).foo.toUpperCase()
);

Octane 28.07.2011 21:50

http://ejohn.org/blog/degrading-script-tags/

Snipe 28.07.2011 21:55

А еще можно взять тег, внутрь которого написали что-то, отрезать ему src и вставить его еще раз. Тогда JS внутри выполнится.

Нет? :)

x-yuri 29.07.2011 17:24

Цитата:

Сообщение от monolithed
1. наличие кода внутри дескрипторов script с атрибутом src
2. такой способ получения и обработки данных
3. предположение, что этот дескриптор будет последним в документе.

признак быдлокодерства.

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

Цитата:

Сообщение от Snipe
Не проверял во всех браузерах, но:
<script type="text/javascript" src="domain.com/script.js" onclick="return {a: 'a'}"></script>
<script type="text/javascript">
var b = document.getElementsByTagName('script')[0].onclick();
alert(b.a);
</script>
Плюс очевиден - никакого eval.

а чем так плох eval в данном случае?

кстати, передачу через onclick вообще для чего придумали?

Snipe 29.07.2011 17:48

Цитата:

Сообщение от x-yuri (Сообщение 116130)
кстати, передачу через onclick вообще для чего придумали?

Всмысле?

ваый 29.07.2011 18:01

Цитата:

Сообщение от Snipe
Сообщение от x-yuri
кстати, передачу через onclick вообще для чего придумали?
Всмысле?

Я так понимаю, что тут пытались выдумать что угодно, но только не использовать innerHTML.
Я же для себя лично отметил, что использование innerHTML для передачи внешних параметров в загружаемый скрипт - достаточно прикольный и удобный способ.
Я уже выше писал, что альтернативой могут быть параметры в URL в src, но по сравнению с innerHTML этот способ sucks. Про атрибуты типа onclick вообще молчу.

x-yuri 29.07.2011 20:22

Цитата:

Сообщение от Snipe
Всмысле?

это был вопрос про передачу информации через onclick вообще. Например, по сравнению с передачей через кастомные атрибуты, onclick валиден (правда для меня это на данный момент не важно). Но с появлением data-* это стало не актуально. Или может быть еще какие-то причины есть...

Цитата:

Сообщение от ваый
Я же для себя лично отметил, что использование innerHTML для передачи внешних параметров в загружаемый скрипт - достаточно прикольный и удобный способ.
Я уже выше писал, что альтернативой могут быть параметры в URL в src, но по сравнению с innerHTML этот способ sucks. Про атрибуты типа onclick вообще молчу.

значительной разницы между передачей через innerHTML и src нету, пока информации мало. Использование onclick ни чем не хуже innerHTML. А если учесть, что innerHTML не обязательно один в один совпадает с содержимым элемента, этот вариант может потребовать доработки, либо может перестать работать при некоторых входных данных. Так что подумай, может стоит заворачивать содержимое в textarea, а то мало ли чего... ;)

ваый 29.07.2011 21:17

Мне кажется, что мы говорим о разных вещах. Как мне может помочь textarea в данном случае?
Цитата:

Сообщение от x-yuri
innerHTML не обязательно один в один совпадает с содержимым элемента

Это да, но думаю, что для передачи параметров как JSON строки, это можно предусмотреть.

monolithed 29.07.2011 21:20

x-yuri,
Цитата:

Сообщение от x-yuri
1. наличие кода внутри дескрипторов script с атрибутом src

когда-то читал, что код может отработать некорректно (вроде бы в книге Д. Гудмана, но точно не помню). Не знаю на сколько эта информация устарела, но для меня это стало табу, да и не было никогда необходимости.
Цитата:

Сообщение от x-yuri
такой способ получения и обработки данных

я привел выше несколько альтернативных решений. К тому же, годами все ставят Google Analytics-счетчики, где вполне приемлимый подход обработки данных. Меня в этом вопросе возмущает, то почему они не выбрали один из уже существующих подходов (не считая решения с пространствами имен). В любом случае распарсивать так код, на мой взгляд, полное извращенство.
Цитата:

Сообщение от x-yuri
предположение, что этот дескриптор будет последним в документе.

Нет возможности проверить это утверждение, ну тут я просто сомневаюсь, что это везде корректно отработает.

Скажем, так я высказал личное мнение, не более

B@rmaley.e><e 29.07.2011 21:31

Цитата:

Сообщение от Snipe
Не проверял во всех браузерах, но:

Выглядит сомнительно. Эвент-хандлеры, в общем-то, не рассчитаны на возвращение значений.

ваый 29.07.2011 21:42

Цитата:

Сообщение от monolithed
Сообщение от x-yuri
предположение, что этот дескриптор будет последним в документе.
Нет возможности проверить это утверждение, ну тут я просто сомневаюсь, что это везде корректно отработает.

А тут и проверять нечего. 100% кросбраузерно. Он не может быть не последним.

monolithed 29.07.2011 21:48

Цитата:

Сообщение от ваый
А тут и проверять нечего. 100% кросбраузерно. Он не может быть не последним.

У элементов тоже ну не может не быть прототипов, но вот IE10- доказывает обратное...
В общем, все может быть, но я бы так делать делать не стал.

ваый 29.07.2011 21:52

Ну тот факт, что этот вариант использует google, уже внушает доверие, разве нет? К тому же такой метод уже лет десять как используют, опять же по причине простоты и кроссбраузерности. Вот, кстати, нарыл доказательство, кто не верит http://feather.elektrum.org/book/src.html

x-yuri 30.07.2011 00:29

Цитата:

Сообщение от ваый
Мне кажется, что мы говорим о разных вещах. Как мне может помочь textarea в данном случае?

Цитата:

Why <textarea>?
The <textarea> element has the nice property of not radically messing up the formatting of its innerHTML.
- This stability of <textarea>'s innerHTML is important because JST syntax allows you to place control flow tags (like if/elseif/for) in all sorts of odd places, such as even -inside- HTML tags. For example:
<option value="${country.name}" {if country.name == currCountry}selected{/if}>
- Just as with many server-side template languages, the JST syntax is not true HTML/XHTML/XML. Hence, the beauty of using <textarea> elements to hold our JST templates.
http://code.google.com/p/trimpath/wi...criptTemplates
другие шаблонизаторы тоже бывает textarea используют

Цитата:

Сообщение от ваый
Это да, но думаю, что для передачи параметров как JSON строки, это можно предусмотреть.

зависит от параметров, для {lang: 'ru'} скорее всего и предусматривать ничего не надо

Цитата:

Сообщение от monolithed
когда-то читал, что код может отработать некорректно (вроде бы в книге Д. Гудмана, но точно не помню). Не знаю на сколько эта информация устарела, но для меня это стало табу, да и не было никогда необходимости.

да, это аргумент, но не табу

Цитата:

Сообщение от monolithed
Меня в этом вопросе возмущает, то почему они не выбрали один из уже существующих подходов (не считая решения с пространствами имен).

ну там же много людей, может и причины какие-то были

Цитата:

Сообщение от monolithed
В любом случае распарсивать так код, на мой взгляд, полное извращенство.

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

Цитата:

Сообщение от B@rmaley.e><e
Выглядит сомнительно. Эвент-хандлеры, в общем-то, не рассчитаны на возвращение значений.

и тем не менее, довольно известная практика

Цитата:

Сообщение от monolithed
У элементов тоже ну не может не быть прототипов, но вот IE10- доказывает обратное...

а можно подробнее про ie 10?

Цитата:

Сообщение от ваый
Ну тот факт, что этот вариант использует google, уже внушает доверие, разве нет?

ну есть немного

Цитата:

Сообщение от ваый
К тому же такой метод уже лет десять как используют, опять же по причине простоты и кроссбраузерности. Вот, кстати, нарыл доказательство, кто не верит http://feather.elektrum.org/book/src.html

откуда такие выводы? Ну можно предположить, что статья написана году в 2005-ом. Но почему ты решил, что это распространенная практика? Да и доказывать ты как-то косвенно пытаешься. Давай попробуем напрямую:
<!doctype html>
<html>
<body>
    <script src="1.js"></script>
    <script src="2.js"></script>
    <script src="3.js"></script>
    <script>
        d([a, b, document.body.innerHTML]);

        function d(s){
            document.body.appendChild(
                document.createTextNode(s)
            );
            document.body.appendChild(
                document.createElement('br')
            );
        }
    </script>
</body>
</html>


1.js:
var a = 1;


2.js:
var scripts = document.getElementsByTagName('script');
var script = scripts[scripts.length-1];
script.parentNode.insertBefore(document.createTextNode('test'), script);


3.js:
var b = 2;


не нашел браузера, в котором это не работает. Почему это плохой тест (почему такой метод доступа к тегу скрипт может не работать) и как его можно улучшить?

p.s. вообще, я в последнее время подумал, что слишком сильно себя ограничиваю. Надо больше экспериментировать.

ваый 30.07.2011 00:50

Цитата:

Сообщение от x-yuri
Да и доказывать ты как-то косвенно пытаешься.

Ну я тоже выше экспериментальное доказательство приводил.

Цитата:

Сообщение от x-yuri
Но почему ты решил, что это распространенная практика?

Я и не говорил, что очень распространенная. Напротив, она очень даже не распространенная, но некоторые о ней знают, Джон Резиг, например :)

monolithed 30.07.2011 01:00

Цитата:

Сообщение от x-yuri
а можно подробнее про ie 10?

в IE9 final + обновления (без них нет) имплементровали полную поддержку Node , HTMLDocument.prototype и Element.prototype. Ну и в IE10 совсем все гладко))

x-yuri 30.07.2011 01:16

а что значит полная? У меня следующий код работает и в ie 8:
Element.prototype.testMethod = function() {
    alert("test");
}
document.body.testMethod();

или это не полная поддержка?

monolithed 30.07.2011 01:28

Цитата:

Сообщение от x-yuri
а что значит полная?

объект Node отсутсвует в IE8, а Element.prototype появилось вроде как не с первого билда (также как Selectors API Level 2)

Kolyaj 30.07.2011 11:56

У нас в вебвизоре предлагался вот такой код для вставки на сайты
<script type="text/javascript">
    document.write('<script\u0020type="text/javascript"\u0020id=":visorCode"><\u002fscript>');
    var __visorInit=new Function('','if(typeof(__visor)!="undefined")__visor.init(100);');
    var __visorConnect=new Function('','document.getElementById(":visorCode").src="//c1.web-visor.com/c.js"');
    if(Object.prototype.toString.call(window.opera)=='[object\u0020Opera]')
    document.addEventListener('DOMContentLoaded',__visorConnect,false);
    else __visorConnect();
</script>


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

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

tenshi 30.07.2011 14:11

Kolyaj, ну расскажи нам об этих предпосылках.

фича с исполнением скриптов по мере загрузки страницы не работает в гекко в режиме xhtml. там сначала строится дерево, а только потом исполняются скрипты. соответствнено и document.write не работает.

пространства имён вполне кроссбраузерны. если опять же не пользоваться xhtml парсором.

Snipe 01.08.2011 12:13

Цитата:

Сообщение от x-yuri (Сообщение 116181)
это был вопрос про передачу информации через onclick вообще. Например, по сравнению с передачей через кастомные атрибуты, onclick валиден (правда для меня это на данный момент не важно). Но с появлением data-* это стало не актуально. Или может быть еще какие-то причины есть...

Придумал не я.
Используется, потому что удобно (не надо ничего парсить, можно не просто передавать данные, а выполнять функции), кроссбраузерно и не лезет в innerHTML (актуально для элементов верстки, к которым надо подключить JS).


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