Як передати параметри тегу Script?


89

Я прочитав підручник віджетів "Зроби сам" - Як вставити свій сайт на інший сайт для віджетів XSS від доктора Ніка.

Я шукаю спосіб передачі параметрів тегу сценарію. Наприклад, зробити наступну роботу:

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

Чи є спосіб зробити це?


Два цікаві посилання:


Дивіться також: stackoverflow.com/q/1017424/247696
Флімм

Відповіді:


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
polyfill більше не працює, document.currentScript лише для читання і не може бути призначений, якщо він уже існує. можливо інша перевірка, наприклад, якщо (! document.currentScript) {*** функція
поліфілу

2
Мої вибачення, Девід, я завжди роблю свої відповіді загальними, щоб інші могли використовувати рішення без первинних деталей реалізації, що додають проблеми. У наведеному вище прикладі ви можете бачити, що src="..."це означає, що будь-який 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??? Як я можу це виправити, щоб прийняти реальну змінну?
Патрос

9
Для чого це коштує, є й інші способи , щоб посилатися на скрипт , а не, наприклад, document.currentScript(працює тільки для скриптів , а не в їх власному файлі) і покласти idна <script>тег , а потім знайти його цим.
Thunderforge

А що, якби ідентифікатор змінив інший програміст у вашій команді, який не мав уявлення про те, що ви використовуєте цей ідентифікатор?
OBПід час

1
Якщо ви завантажуєте сценарії асинхронно, тоді використання ідентифікатора - єдиний надійний варіант, який я б рекомендував. Дякую @Thunderforge ... Крім того, будь-який програміст повинен утриматись від рефакторингу коду без належного спринтерського плану, який переглядає той, хто має уявлення про те, що відбувається;)
Лука Борріоне

Звичайно, ви можете вимагати від розробників суворої етики, але це не працюватиме в довгостроковій перспективі ... Люди забувають речі .... У гарному дизайні програмного забезпечення кожен блок повинен бути ізольованим, awesome-pixels.tumblr.com/post/101930002170 /… En.wikipedia.org/wiki/SOLID_(object-oriented_design) Тож я не сперечаюся, що це хороше проти погане рішення, воно просто складніше підтримувати ідентифікатори проти не підтримувати :-) Чи не плануєте ви завантажити скрипт Async Я не бачу причини для завантаження за допомогою ID
OBдо

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, яка підтримує мета-теги ...


Я думав, що цей метод був на сьогоднішній день найпростішим із усіх. Це працює як шарм і дає мені саме те, що мені потрібно. Чудове питання та фантастичне рішення!
arios

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 в одне приховане поле.


Дякую за відповідь. Параметри фактично вводяться користувачами (які вбудовують цей тег сценарію у свій код). Що потім?
Томер Ліхташ

Єдине, про що я можу подумати, якщо у вас немає контролю над обома сценаріями клієнт / сервер, це взяти введення даних користувачів і використовувати його для створення певного файлу .js із вбудованим вхідним сигналом, і це за умови, що ви контролюєте збору та обробки їх даних.
захід захід

Не відповідає на оригінальне запитання: куди подіти аргументи, коли немає форми для прихованого поля?
Девід Спектор,

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 [одинадцять років тому], серед інших.

Якщо у вас недостатньо даних, але ви все ще хочете розширити підтримку браузера, можливо, найкращим варіантом є:

Метатеги [від Робіду]

/* 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 замість прихованого атрибута:

/* 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.