Jak przekazać parametry do tagu Script?

89

Przeczytałem samouczek dotyczący widgetów DIY - Jak osadzić swoją witrynę w innej witrynie dla widżetów XSS autorstwa Dr. Nic.

Szukam sposobu na przekazanie parametrów do tagu skryptu. Na przykład, aby wykonać następujące czynności:

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

Czy jest na to sposób?


Dwa interesujące linki:

Tomer Lichtash
źródło

Odpowiedzi:

118

Przepraszam za odpowiedź na bardzo stare pytanie, ale po spędzeniu godziny na zmaganiach z powyższymi rozwiązaniami zdecydowałem się na prostsze rzeczy.

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

Wewnątrz powyższego skryptu:

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

Znacznie łatwiejsze niż parsowanie jquery LUB adresu URL.

Możesz potrzebować pliku polyfil dla doucment.currentScript z odpowiedzi @Yared Rodriguez dla IE:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();
Richard Fox
źródło
5
Zauważ, że currentScript nie działa w IE. Szczegóły
Dehli
Dodałem w odpowiedzi polifill dla IE. Czy polyfill nie działa?
Richard Fox
2
Wypełnienie już nie działa, document.currentScript jest tylko do odczytu i nie można go przypisać, jeśli już istnieje. może inne sprawdzenie, np. czy (! document.currentScript) {*** funkcja polyfill ***} działałaby lepiej
fadomire
2
Przepraszam Davidzie, zawsze staram się, aby moje odpowiedzi były ogólne, tak aby inni mogli korzystać z rozwiązania bez dodawania do problemów szczegółów początkowej implementacji. W moim przykładzie powyżej widać, że src="..."to ma oznaczać, DOWOLNE źródło, nie ma znaczenia :)
Richard Fox,
1
@RichardFox dzięki za odpowiedź, ale muszę tylko skomentować, że „Nie odpowiada na oryginalne pytanie: nie używa ścieżki / do / widget.js” to prawdopodobnie najzabawniejsza rzecz, jaką czytałem przez cały tydzień! Nie mogę uwierzyć, że odpowiedziałeś tak ładnie, jak zrobiłeś.
Skintest
63

Lepiej jest użyć funkcji w atrybutach danych html5 5

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

W pliku skryptu http://path.to/widget.js można uzyskać parametry w następujący sposób:

<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>
OBender
źródło
A co jeśli id ​​= "myAwesomeWigretNo1" nie jest już takie, ale myAwesomeWigretNo2czy myAwesomeWigretNo681??? Jak mogę to naprawić, aby zaakceptować rzeczywistą zmienną?
Pathros
9
Jeśli chodzi o to, co jest warte, istnieją inne sposoby na odwołanie się do skryptu, takie jak document.currentScript(działa tylko dla skryptów, które nie znajdują się w ich własnym pliku) i umieszczenie znacznika idw <script>tagu, a następnie znalezienie go przez to.
Thunderforge,
A jeśli identyfikator został zmieniony przez innego programistę w Twoim zespole, który nie miał pojęcia, że ​​używasz tego identyfikatora?
OBender
1
Jeśli ładujesz skrypty asynchronicznie, użycie identyfikatora jest jedyną niezawodną opcją, którą polecam. Dzięki @Thunderforge ... Ponadto każdy programista powinien powstrzymać się od refaktoryzacji kodu bez odpowiedniego planu sprintu omówionego przez kogoś, kto ma pojęcie o tym, co się dzieje;)
Luca Borrione
Jasne, że możesz wymagać od programistów silnej etyki, ale to nie zadziała na dłuższą metę ... Ludzie zapominają o rzeczach ... W dobrym projekcie oprogramowania Każdy blok powinien być odizolowany, awesome-pixels.tumblr.com/post/101930002170 /… En.wikipedia.org/wiki/SOLID_(object-oriented_design) Więc nie twierdzę, że jest to dobre lub złe rozwiązanie, po prostu bardziej skomplikowane jest utrzymanie identyfikatorów niż ich nie utrzymywanie :-) Czy nie planujesz załaduj skrypt Async Nie widzę powodu, aby ładować za pomocą ID
OBender
17

Rozumiem. Coś w rodzaju włamania, ale działa całkiem nieźle:

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];

Parametry w tagu script przekazuję jako klasy:

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

Ten artykuł bardzo pomógł.

Tomer Lichtash
źródło
1
Artykuł jest niesamowity!
Bartek Skwira
14
Klasy powinny być używane do stylizacji elementu, aby nie przekazywał parametrów.
kspacja
5
@kspacja Tak, a HTML powinien zawierać tylko treść bez stylów, z wyjątkiem tego, że musimy dokładnie uporządkować nasze tagi DIV dla układów pływających i kolumnowych, ponieważ CSS nie może w rzeczywistości wykonać tego zadania i jakoś nam to nie przeszkadza. Odwal się, mówię. Ale możesz użyć atrybutów „data-”, jeśli chcesz uniknąć konfliktu lub jeśli jesteś typem, który nie może się z tym pogodzić.
Jason C
13

Innym sposobem jest użycie metatagów. Wszelkie dane, które mają zostać przesłane do twojego JavaScript, można przypisać w następujący sposób:

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

Dane można następnie pobrać z metatagów w ten sposób (najlepiej zrobić to w module obsługi zdarzeń DOMContentLoaded):

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

Absolutnie bez kłopotów z jQuery lub podobnymi rozwiązaniami, bez hacków i obejść koniecznych i działa z każdą wersją HTML obsługującą metatagi ...

Robidu
źródło
Myślałem, że ta metoda jest zdecydowanie najłatwiejsza ze wszystkich. Działa jak urok i daje mi dokładnie to, czego potrzebuję. Świetne pytanie i fantastyczne rozwiązanie!
arios
10

JQuery ma sposób na przekazywanie parametrów z HTML do javascript:

Umieść to w myhtml.htmlpliku:

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

W tym samym katalogu utwórz subscript.jsplik i umieść go tam:

//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);

Wynik analizy:

Ładowanie strony myhtml.html ma wydruk „foobar.mp4” na ekranie. Zmienna o nazwie video_filename została przekazana z html do javascript. JavaScript wydrukował go na ekranie i pojawił się jako osadzony w html w rodzicu.

jsfiddle dowód, że powyższe działa:

http://jsfiddle.net/xqr77dLt/

Eric Leschinski
źródło
7

Jeśli używasz jquery, możesz rozważyć ich metodę danych.

Użyłem czegoś podobnego do tego, co próbujesz w swojej odpowiedzi, ale w ten sposób:

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

Możesz także utworzyć funkcję, która pozwoli ci bezpośrednio pobrać parametry GET (z tego często korzystam):

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');
rg88
źródło
4

to jest bardzo stary wątek, wiem, ale to też może pomóc, jeśli ktoś przyjdzie tutaj, gdy będzie szukać rozwiązania.

Zasadniczo użyłem document.currentScript, aby pobrać element, z którego działa mój kod, i filtruję, używając nazwy zmiennej, której szukam. Zrobiłem to rozszerzając currentScript za pomocą metody o nazwie "get", więc będziemy mogli pobrać wartość z tego skryptu za pomocą:

document.currentScript.get('get_variable_name');

W ten sposób możemy użyć standardowego URI do pobrania zmiennych bez dodawania specjalnych atrybutów.

To jest ostateczny kod

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

Zapomniałem o IE :) Nie mogło być tak prościej ... Cóż, nie wspomniałem, że document.currentScript jest właściwością HTML5. Nie został dołączony do różnych wersji IE (testowałem do IE11 i jeszcze go nie było). Ze względu na kompatybilność z IE dodałem do kodu następującą część:

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

To, co tutaj robimy, to zdefiniowanie alternatywnego kodu dla IE, który zwraca bieżący obiekt skryptu, który jest wymagany w rozwiązaniu do wyodrębnienia parametrów z właściwości src. Nie jest to idealne rozwiązanie dla IE, ponieważ istnieją pewne ograniczenia; Jeśli skrypt jest ładowany asynchronicznie. Nowsze przeglądarki powinny zawierać właściwość „.currentScript”.

Mam nadzieję, że to pomoże.

Yared Rodriguez
źródło
3

Dzięki jQuery prostym rozwiązaniem zgodnym z HTML5 jest utworzenie dodatkowego tagu HTML, takiego jak div, do przechowywania danych.

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

Demo na żywo z powyższym kodem: http://codepen.io/anon/pen/KzzNmQ?editors=1011#0

W wersji demonstracyjnej na żywo można zobaczyć dane z atrybutów HTML5 data- *, które mają zostać połączone i wydrukowane w dzienniku.

Źródło: https://api.jquery.com/data/

gagallo7
źródło
1
Przeszedłem przez niektóre inne rozwiązania, ale to było to, które działało najlepiej, a także jest dość proste do wdrożenia. dzięki!
Erik Kalkoken
Powinno to być akceptowane rozwiązanie, ponieważ umożliwia odwoływanie się do skryptu za pomocą identyfikatora i jest poprawnym HTML5.
Tim S
2

Umieść potrzebne wartości w miejscu, gdzie inny skrypt może je pobrać, na przykład ukryte dane wejściowe, a następnie pobierz te wartości z ich kontenera podczas inicjowania nowego skryptu. Możesz nawet umieścić wszystkie parametry jako ciąg JSON w jednym ukrytym polu.

bwest
źródło
Dzięki za odpowiedź. Parametry są w rzeczywistości wprowadzane przez użytkowników (którzy osadzają ten tag skryptu w swoim kodzie). Co wtedy?
Tomer Lichtash
Jedyną rzeczą, o której mogę pomyśleć, jeśli nie masz kontroli nad obydwoma skryptami klienta / serwera, jest pobranie danych wejściowych użytkownika i użycie ich do wygenerowania określonego pliku .js z osadzonymi w nim danymi wejściowymi, a to przy założeniu, że masz kontrolę gromadzenia i przetwarzania ich danych wejściowych.
bwest
Nie odpowiada na oryginalne pytanie: gdzie umieścić argumenty, gdy nie ma formularza do przechowywania ukrytego pola?
David Spector
2

Utwórz atrybut zawierający listę parametrów, na przykład:

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

Następnie w swoim JavaScript pobierz parametry jako tablicę:

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
Mistyczne
źródło
Jakie są wady tego podejścia?
Tronathan
@Tronathan nie ma żadnych wad tego podejścia i jest dołączony polyfill dla lepszej obsługi przeglądarki. Jedynym minusem, jaki tutaj widzę, jest brak możliwości umieszczania przecinków w parametrach, co zwykle nie stanowi problemu, i możesz to zrekompensować, zmieniając separator na znak, którego nie planujesz używać.
Mistyczne
2

Chciałem rozwiązań, które w jak największym stopniu obsługują starsze przeglądarki. W przeciwnym razie powiedziałbym, że albo currentScript, albo metoda atrybutów danych byłaby najbardziej stylowa.

To jedyna z tych metod, których jeszcze tu nie wspomniano. W szczególności, jeśli z jakiegoś powodu masz duże ilości danych, najlepszą opcją może być:

Lokalny magazyn

/* 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 ma pełną obsługę nowoczesnych przeglądarek i zaskakująco dobre wsparcie dla starszych przeglądarek, między innymi do IE 8, Firefox 3,5 i Safari 4 [jedenaście lat temu].

Jeśli nie masz dużej ilości danych, ale nadal potrzebujesz rozbudowanej obsługi przeglądarki, być może najlepszą opcją jest:

Metatagi [autorstwa Robidu]

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

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

Wadą tego jest to, że prawidłowe miejsce do umieszczania metatagów [do HTML 4] znajduje się w tagu head i możesz nie chcieć tam umieszczać tych danych. Aby tego uniknąć lub umieścić metatagi w treści, możesz użyć:

Ukryty akapit

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

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

Aby uzyskać jeszcze lepszą obsługę przeglądarek, możesz użyć klasy CSS zamiast atrybutu hidden:

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

/* HTML: */
<p class="hidden" id="yourData">Your data is here</p>
Fom
źródło
2

To jest rozwiązanie dla 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');
})
Greil Omatics
źródło