Как передать параметры в тег скрипта?


89

Я прочитал учебник по виджетам DIY - Как встроить свой сайт на другой сайт для виджетов XSS от доктора Ника.

Я ищу способ передать параметры в тег скрипта. Например, для выполнения следующей работы:

<script src="http://path/to/widget.js?param_a=1&amp;param_b=3"></script>

Есть ли способ сделать это?


Две интересные ссылки:


Ответы:


118

Прошу прощения за ответ на очень старый вопрос, но потратив час на борьбу с вышеуказанными решениями, я выбрал более простые вещи.

<script src=".." one="1" two="2"></script>

Внутри приведенного выше скрипта:

document.currentScript.getAttribute('one'); //1
document.currentScript.getAttribute('two'); //2

Намного проще, чем парсинг jquery ИЛИ url.

Вам может понадобиться полифил для doucment.currentScript из ответа @Yared Rodriguez для IE:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();

5
Обратите внимание, что currentScript не работает в IE. Подробности
Дели

Я добавил в ответ полифилл для IE. Полифилл не работает?
Ричард Фокс

2
полифилл больше не работает, document.currentScript доступен только для чтения и не может быть назначен, если он уже существует. может быть другая проверка, например if (! document.currentScript) {*** функция polyfill ***} будет работать лучше
fadomire

2
Мои извинения, Дэвид, я всегда делаю свои ответы общими, чтобы другие могли использовать решение без добавления деталей начальной реализации к проблемам. В моем примере выше вы можете видеть, src="..."что это означает, что ЛЮБОЙ источник, не имеет значения :)
Ричард Фокс

1
@RichardFox спасибо за ответ, но просто должен был прокомментировать, что «Не отвечает на исходный вопрос: не использует путь / к / widget.js» - наверное, самая смешная вещь, которую я читал за всю неделю! Не могу поверить, что вы ответили так же хорошо, как и сделали.
Skintest

63

Лучше использовать функцию в атрибутах данных html5 5

<script src="http://path.to/widget.js" data-width="200" data-height="200">
</script>

Внутри файла скрипта http://path.to/widget.js вы можете получить параметры таким образом:

<script>
function getSyncScriptParams() {
         var scripts = document.getElementsByTagName('script');
         var lastScript = scripts[scripts.length-1];
         var scriptName = lastScript;
         return {
             width : scriptName.getAttribute('data-width'),
             height : scriptName.getAttribute('data-height')
         };
 }
</script>

Что, если id = "myAwesomeWigretNo1" не всегда был таким, но myAwesomeWigretNo2, или myAwesomeWigretNo681??? Как я могу исправить это, чтобы принять реальную переменную?
Pathros

9
Как бы то ни было, есть другие способы ссылаться на сценарий вместо этого, например document.currentScript(работает только для сценариев, не находящихся в их собственном файле), поставить тег idна <script>тег, а затем найти его по нему.
Thunderforge

А что, если идентификатор был изменен каким-то другим программистом в вашей команде, который понятия не имел, что вы используете этот идентификатор?
OBender

1
Если вы загружаете скрипты асинхронно, то использование идентификатора - единственный надежный вариант, который я бы порекомендовал. Спасибо @Thunderforge ... Кроме того, любому программисту следует воздерживаться от рефакторинга кода без надлежащего плана спринта, который был рассмотрен кем-то, кто имеет представление о том, что происходит;)
Лука Боррионе

Конечно, вы можете требовать от разработчиков строгой этики, но в долгосрочной перспективе это не сработает ... Люди забывают о вещах ... В хорошем программном дизайне каждый блок должен быть изолирован, awesome-pixels.tumblr.com/post/101930002170 /… En.wikipedia.org/wiki/SOLID_(object-oriated_design) Так что я не спорю, что это хорошее и плохое решение, просто сложнее поддерживать идентификаторы, а не не поддерживать :-) Вы не планируете загрузить скрипт Async Я не вижу причин загружать с использованием ID
OBender 01

17

Понял. Что-то вроде хака, но работает неплохо:

var params = document.body.getElementsByTagName('script');
query = params[0].classList;
var param_a = query[0];
var param_b = query[1];
var param_c = query[2];

Я передаю параметры в теге скрипта как классы:

<script src="http://path.to/widget.js" class="2 5 4"></script>

Эта статья очень помогла.


1
Статья классная!
Bartek Skwira

14
Классы следует использовать для стилизации элемента, чтобы не передавать параметры.
kspacja

5
@kspacja Да, и HTML должен содержать только контент без стилей, за исключением того, что мы должны точно упорядочить наши теги DIV для макетов с плавающей запятой и столбцов, потому что CSS на самом деле не может выполнять эту работу, и мы как-то согласны с этим. - Убирайся, - говорю я. Но вы можете использовать атрибуты «data-», если хотите избежать конфликта или если вы из-за этого теряете сон.
Jason C

13

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

<meta name="yourdata" content="whatever" />
<meta name="moredata" content="more of this" />

Затем данные можно извлечь из метатегов следующим образом (лучше всего это сделать в обработчике событий DOMContentLoaded):

var data1 = document.getElementsByName('yourdata')[0].content;
var data2 = document.getElementsByName('moredata')[0].content;

Абсолютно никаких проблем с jQuery или подобным, никаких хаков и обходных решений, и работает с любой версией HTML, которая поддерживает метатеги ...


Я думал, что этот метод был самым простым из всех. Это работает как шарм и дает мне именно то, что мне нужно. Отличный вопрос и фантастическое решение!
ариос 08

10

В JQuery есть способ передавать параметры из HTML в javascript:

Поместите это в myhtml.htmlфайл:

<!-- Import javascript -->
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<!-- Invoke a different javascript file called subscript.js -->
<script id="myscript" src="subscript.js" video_filename="foobar.mp4">/script>

В том же каталоге создайте subscript.jsфайл и поместите его туда:

//Use jquery to look up the tag with the id of 'myscript' above.  Get 
//the attribute called video_filename, stuff it into variable filename.
var filename = $('#myscript').attr("video_filename");

//print filename out to screen.
document.write(filename);

Результат анализа:

При загрузке страницы myhtml.html на экран выводится файл foobar.mp4. Переменная с именем video_filename была передана из html в javascript. Javascript распечатал его на экране, и он выглядел встроенным в html в родительском элементе.

jsfiddle доказательство того, что это работает:

http://jsfiddle.net/xqr77dLt/


7

Если вы используете jquery, вы можете рассмотреть их метод данных.

Я использовал что-то похожее на то, что вы пытаетесь сделать в своем ответе, но вот так:

<script src="http://path.to/widget.js" param_a = "2" param_b = "5" param_c = "4">
</script>

Вы также можете создать функцию, которая позволит вам напрямую получать параметры GET (это то, что я часто использую):

function $_GET(q,s) {
    s = s || window.location.search;
    var re = new RegExp('&'+q+'=([^&]*)','i');
    return (s=s.replace(/^\?/,'&').match(re)) ? s=s[1] : s='';
}

// Grab the GET param
var param_a = $_GET('param_a');

4

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

В основном я использовал document.currentScript, чтобы получить элемент, из которого выполняется мой код, и фильтрую, используя имя переменной, которую я ищу. Я расширил currentScript с помощью метода под названием "get", так что мы сможем получить значение внутри этого скрипта, используя:

document.currentScript.get('get_variable_name');

Таким образом, мы можем использовать стандартный URI для извлечения переменных без добавления специальных атрибутов.

Это последний код

document.currentScript.get = function(variable) {
    if(variable=(new RegExp('[?&]'+encodeURIComponent(variable)+'=([^&]*)')).exec(this.src))
    return decodeURIComponent(variable[1]);
};

Я забыл про IE :) Это не могло быть так просто ... Я не упомянул, что document.currentScript - это свойство HTML5. Он не был включен в разные версии IE (я тестировал до IE11, и его еще не было). Для совместимости с IE я добавил в код эту часть:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();

Здесь мы определяем некоторый альтернативный код для IE, который возвращает текущий объект сценария, который требуется в решении для извлечения параметров из свойства src. Это не идеальное решение для IE из-за некоторых ограничений; Если скрипт загружается асинхронно. Новые браузеры должны включать свойство ".currentScript".

Я надеюсь, что это помогает.


3

Благодаря jQuery простым решением, совместимым с HTML5, является создание дополнительного HTML-тега, такого как div, для хранения данных.

HTML :

<div id='dataDiv' data-arg1='content1' data-arg2='content2'>
  <button id='clickButton'>Click me</button>
</div>

JavaScript :

$(document).ready(function() {
    var fetchData = $("#dataDiv").data('arg1') + 
                    $("#dataDiv").data('arg2') ;

    $('#clickButton').click(function() {
      console.log(fetchData);
    })
});

Живая демонстрация с кодом выше: http://codepen.io/anon/pen/KzzNmQ?editors=1011#0

В живой демонстрации можно увидеть, как данные из атрибутов HTML5 data- * должны быть объединены и напечатаны в журнале.

Источник: https://api.jquery.com/data/


1
Перебирал некоторые другие решения, но это было то, что сработало лучше всего, а также довольно просто реализовать. Благодарность!
Эрик Калкокен

Это должно быть приемлемое решение, поскольку оно позволяет ссылаться на скрипт по идентификатору и является допустимым HTML5.
Tim S

2

Поместите нужные вам значения в место, где другой сценарий может их получить, например, скрытый ввод, а затем вытащите эти значения из своего контейнера при инициализации нового сценария. Вы даже можете поместить все свои параметры в виде строки JSON в одно скрытое поле.


Спасибо за ответы. Параметры фактически вводятся пользователями (которые встраивают этот тег скрипта в свой код). Что тогда?
Tomer Lichtash

Единственное, что я могу придумать, если у вас нет контроля над обоими клиентскими / серверными сценариями, - это взять вводимые пользователем данные и использовать его для создания определенного файла .js с их вводом, встроенным в него, и это при условии, что вы контролируете сбора и обработки их ввода.
bwest

Не отвечает на исходный вопрос: куда поместить аргументы, когда нет формы для хранения скрытого поля?
Дэвид Спектор

2

Создайте атрибут, содержащий список параметров, например:

<script src="http://path/to/widget.js" data-params="1, 3"></script>

Затем в вашем JavaScript получите параметры в виде массива:

var script = document.currentScript || 
/*Polyfill*/ Array.prototype.slice.call(document.getElementsByTagName('script')).pop();

var params = (script.getAttribute('data-params') || '').split(/, */);

params[0]; // -> 1
params[1]; // -> 3

Каковы недостатки этого подхода?
Тронатан

@Tronathan, у этого подхода нет реальных недостатков, и для лучшей поддержки браузера включен полифилл. Единственный недостаток, который я вижу здесь, - это невозможность включать запятые в параметры, что обычно не является проблемой, и вы можете компенсировать это, изменив разделитель на символ, который вы не планируете использовать.
Мистический

2

Мне нужны были решения с максимальной поддержкой старых браузеров. В противном случае я бы сказал, что наиболее стильным будет либо метод currentScript, либо метод атрибутов данных .

Это единственный из этих методов, который здесь еще не обсуждался. В частности, если по какой-то причине у вас большой объем данных, лучшим вариантом может быть:

localStorage

/* On the original page, you add an inline JS Script: */
<script>
   localStorage.setItem('data-1', 'I got a lot of data.');
   localStorage.setItem('data-2', 'More of my data.');
   localStorage.setItem('data-3', 'Even more data.');
</script>

/* External target JS Script, where your data is needed: */
var data1 = localStorage.getItem('data-1');
var data2 = localStorage.getItem('data-2');
var data3 = localStorage.getItem('data-3');

localStorage имеет полную поддержку современных браузеров, а также удивительно хорошую поддержку старых браузеров, в том числе IE 8, Firefox 3,5 и Safari 4 [одиннадцать лет назад].

Если у вас не так много данных, но вы по-прежнему хотите расширенную поддержку браузера, возможно, лучшим вариантом будет:

Мета-теги [от Robidu]

/* HTML: */
<meta name="yourData" content="Your data is here" />

/* JS: */
var data1 = document.getElementsByName('yourData')[0].content;

Недостатком этого является то, что правильное место для размещения метатегов [до HTML 4] находится в теге заголовка, и вы можете не захотеть, чтобы эти данные были там. Чтобы избежать этого или поместить метатеги в тело, вы можете использовать:

Скрытый абзац

/* HTML: */
<p hidden id="yourData">Your data is here</p>

/* JS: */
var yourData = document.getElementById('yourData').innerHTML;

Для еще большей поддержки браузера вы можете использовать класс CSS вместо атрибута hidden:

/* CSS: */
.hidden {
   display: none;
}

/* HTML: */
<p class="hidden" id="yourData">Your data is here</p>

2

Это решение для jQuery 3.4

<script src="./js/util.js" data-m="myParam"></script>
$(document).ready(function () {
    var m = $('script[data-m][data-m!=null]').attr('data-m');
})
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.