Bagaimana cara meneruskan parameter ke tag Script?

96

Saya membaca tutorial widget DIY - Bagaimana menyematkan situs Anda di situs lain untuk Widget XSS oleh Dr. Nic.

Saya mencari cara untuk meneruskan parameter ke tag skrip. Misalnya, untuk membuat pekerjaan berikut:

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

Apakah ada cara untuk melakukan ini?


Dua tautan menarik:

Tomer Lichtash
sumber

Jawaban:

124

Saya minta maaf karena menjawab pertanyaan yang sangat lama tetapi setelah menghabiskan satu jam bergulat dengan solusi di atas, saya memilih hal-hal yang lebih sederhana.

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

Di dalam skrip di atas:

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

Jauh lebih mudah daripada jquery OR url parsing.

Anda mungkin memerlukan polyfil untuk doucment.currentScript dari jawaban @Yared Rodriguez untuk IE:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();
Richard Fox
sumber
6
Perhatikan bahwa currentScript tidak berfungsi di IE. Detail
Dehli
Saya menambahkan polyfill untuk IE di jawabannya. Apakah polyfill tidak berfungsi?
Richard Fox
2
polyfill tidak berfungsi lagi, document.currentScript hanya baca dan tidak dapat ditetapkan jika sudah ada. mungkin pemeriksaan yang berbeda seperti jika (! document.currentScript) {*** fungsi polyfill ***} akan bekerja lebih baik
fadomire
3
Maafkan saya David, saya selalu membuat jawaban saya umum sehingga orang lain dapat menggunakan solusi tanpa detail implementasi awal yang menambah masalah. Dalam contoh saya di atas, Anda dapat melihat src="..."Ini dimaksudkan untuk menandakan, SETIAP src, tidak masalah :)
Richard Fox
1
@RichardFox terima kasih atas jawabannya, tetapi hanya perlu berkomentar bahwa "Tidak menjawab pertanyaan asli: tidak menggunakan path / to / widget.js" mungkin adalah hal terlucu yang pernah saya baca sepanjang minggu! Tidak percaya Anda menjawab sebaik yang Anda lakukan.
Skintest
65

Lebih baik Gunakan fitur di Atribut data html5 5

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

Di dalam file skrip http://path.to/widget.js Anda bisa mendapatkan paremeter dengan cara itu:

<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
sumber
Bagaimana jika id = "myAwesomeWigretNo1" tidak selalu seperti itu tapi myAwesomeWigretNo2, atau myAwesomeWigretNo681??? Bagaimana cara memperbaikinya untuk menerima variabel nyata?
Pathros
9
Untuk apa nilainya, ada cara lain untuk mereferensikan skrip sebagai gantinya, seperti document.currentScript(hanya berfungsi untuk skrip bukan di file mereka sendiri) dan meletakkan idpada <script>tag dan kemudian menemukannya dengan itu.
Thunderforge
Dan bagaimana jika ID diubah oleh programmer lain di tim Anda yang tidak tahu bahwa Anda menggunakan id ini?
OBender
1
Jika Anda memuat skrip secara asynchronous maka menggunakan ID adalah satu-satunya pilihan yang dapat diandalkan yang saya sarankan. Terima kasih @Thunderforge ... Selain itu, programmer mana pun harus menahan diri dari refactoring kode tanpa rencana sprint yang tepat yang diulas oleh seseorang yang memiliki petunjuk tentang apa yang terjadi;)
Luca Borrione
Tentu Anda dapat menuntut Etika yang kuat dari Pengembang, tetapi itu tidak akan berhasil dalam jangka panjang ... Orang-orang melupakan banyak hal .... Dalam Desain Perangkat Lunak yang Baik Setiap Blok Harus diisolasi, mengagumkan-pixels.tumblr.com/post/101930002170 /… En.wikipedia.org/wiki/i>_(object-oriented_design) Jadi saya tidak membantah bahwa ini adalah solusi yang baik vs buruk, hanya lebih rumit untuk mempertahankan ID vs tidak memelihara :-) Apakah Anda tidak berencana untuk memuat skrip Async Saya tidak melihat alasan untuk memuat menggunakan ID
OBender
17

Oke. Jenis retasan, tetapi berfungsi dengan cukup baik:

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

Saya meneruskan params di tag skrip sebagai kelas:

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

Artikel ini banyak membantu.

Tomer Lichtash
sumber
1
Artikelnya luar biasa!
Bartek Skwira
14
Kelas harus digunakan untuk menata elemen agar tidak melewatkan parameter.
kspacja
5
@kspacja Ya dan HTML harus berisi konten hanya tanpa gaya, kecuali kita harus secara tepat memesan tag DIV kita untuk tata letak kolom dan float karena CSS tidak dapat benar-benar melakukan pekerjaan itu, dan entah bagaimana kita setuju dengan itu. Singkirkan, kataku. Tetapi Anda dapat menggunakan atribut "data-" jika Anda ingin menghindari konflik atau Anda tipe orang yang tidak bisa tidur karenanya.
Jason C
14

Cara lain adalah dengan menggunakan tag meta. Data apa pun yang seharusnya diteruskan ke JavaScript Anda dapat ditetapkan seperti ini:

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

Data kemudian dapat ditarik dari tag meta seperti ini (paling baik dilakukan di penangan kejadian DOMContentLoaded):

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

Sama sekali tidak ada kerumitan dengan jQuery atau sejenisnya, tidak perlu peretasan dan solusi, dan berfungsi dengan versi HTML apa pun yang mendukung tag meta ...

Robidu
sumber
Saya pikir metode ini sejauh ini adalah metode termudah untuk semuanya. Ini bekerja seperti pesona dan memberi saya apa yang saya butuhkan. Pertanyaan bagus dan solusi fantastis!
arios
10

JQuery memiliki cara untuk meneruskan parameter dari HTML ke javascript:

Taruh ini di myhtml.htmlfile:

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

Di direktori yang sama buat subscript.jsfile dan taruh ini di sana:

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

Analisis Hasil:

Memuat halaman myhtml.html memiliki 'foobar.mp4' yang dicetak ke layar. Variabel bernama video_filename diteruskan dari html ke javascript. Javascript mencetaknya ke layar, dan itu muncul sebagai tertanam ke dalam html di induknya.

jsfiddle bukti bahwa yang di atas berfungsi:

http://jsfiddle.net/xqr77dLt/

Eric Leschinski
sumber
7

Jika Anda menggunakan jquery, Anda mungkin ingin mempertimbangkan metode datanya.

Saya telah menggunakan sesuatu yang mirip dengan apa yang Anda coba dalam tanggapan Anda tetapi seperti ini:

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

Anda juga dapat membuat fungsi yang memungkinkan Anda mengambil parameter GET secara langsung (inilah yang sering saya gunakan):

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.dll
sumber
4

Berkat jQuery, solusi sederhana yang sesuai dengan HTML5 adalah membuat tag HTML tambahan, seperti div, untuk menyimpan data.

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 langsung dengan kode di atas: http://codepen.io/anon/pen/KzzNmQ?editors=1011#0

Pada demo langsung, seseorang dapat melihat data dari atribut data- * HTML5 untuk digabungkan dan dicetak ke log.

Sumber: https://api.jquery.com/data/

gagallo7
sumber
1
Telah melalui beberapa solusi lain, tetapi ini adalah solusi yang paling berhasil dan juga cukup mudah untuk diterapkan. Terima kasih!
Erik Kalkoken
Ini harus menjadi solusi yang diterima, karena memungkinkan Anda untuk mereferensikan skrip berdasarkan ID dan HTML5 yang valid.
Tim S
4

Ini adalah utas yang sangat tua, saya tahu tetapi ini mungkin membantu juga jika seseorang sampai di sini begitu mereka mencari solusi.

Pada dasarnya saya menggunakan document.currentScript untuk mendapatkan elemen dari mana kode saya berjalan dan saya memfilter menggunakan nama variabel yang saya cari. Saya melakukannya dengan memperluas currentScript dengan metode yang disebut "get", jadi kita akan dapat mengambil nilai di dalam skrip itu dengan menggunakan:

document.currentScript.get('get_variable_name');

Dengan cara ini kita bisa menggunakan URI standar untuk mengambil variabel tanpa menambahkan atribut khusus.

Ini adalah kode terakhir

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

Saya lupa tentang IE :) Tidak bisa semudah itu ... Saya tidak menyebutkan bahwa document.currentScript adalah properti HTML5. Ini belum disertakan untuk versi IE yang berbeda (saya uji sampai IE11, dan itu belum ada). Untuk kompatibilitas IE, saya menambahkan bagian ini ke kode:

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

Apa yang kita lakukan di sini adalah mendefinisikan beberapa kode alternatif untuk IE, yang mengembalikan objek skrip saat ini, yang diperlukan dalam solusi untuk mengekstrak parameter dari properti src. Ini bukan solusi sempurna untuk IE karena ada beberapa batasan; Jika skrip dimuat secara asinkron. Browser yang lebih baru harus menyertakan properti ".currentScript".

Saya harap ini membantu.

Yared Rodriguez
sumber
4

Buat atribut yang berisi daftar parameter, seperti:

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

Kemudian, di JavaScript Anda, dapatkan parameter sebagai array:

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
Mistik
sumber
Apa kerugian dari pendekatan ini?
Tronathan
@Tronathan tidak ada kerugian nyata untuk pendekatan ini dan ada polyfill yang disertakan untuk dukungan browser yang lebih baik. Satu-satunya downside yang saya lihat di sini adalah tidak dapat menyertakan koma dalam parameter, yang biasanya tidak menjadi masalah, dan Anda dapat mengimbanginya dengan mengubah pembatas menjadi karakter yang tidak Anda rencanakan untuk digunakan.
Mistik
2

Letakkan nilai yang Anda butuhkan di suatu tempat di mana skrip lain dapat mengambilnya, seperti masukan tersembunyi, lalu tarik nilai tersebut dari penampungnya saat Anda menginisialisasi skrip baru Anda. Anda bahkan dapat menempatkan semua parameter Anda sebagai string JSON ke dalam satu bidang tersembunyi.

bwest
sumber
Terimakasih telah menjawab. Parameter sebenarnya dimasukkan oleh pengguna (yang menyematkan tag skrip ini dalam kode mereka). Lalu bagaimana?
Tomer Lichtash
Satu-satunya hal yang dapat saya pikirkan jika Anda tidak memiliki kendali atas kedua skrip klien / server adalah dengan mengambil input pengguna dan menggunakannya untuk menghasilkan file .js tertentu dengan input mereka tertanam di dalamnya, dan itu dengan asumsi Anda memegang kendali mengumpulkan dan memproses masukan mereka.
bwest
Tidak menjawab pertanyaan asli: di mana meletakkan argumen ketika tidak ada formulir untuk menampung bidang Tersembunyi?
David Spector
2

Saya menginginkan solusi dengan dukungan browser lama sebanyak mungkin. Kalau tidak, saya akan mengatakan metode currentScript atau data atribut akan paling bergaya.

Ini adalah satu-satunya metode yang belum dibahas di sini. Terutama, jika karena alasan tertentu Anda memiliki banyak data, maka opsi terbaik mungkin adalah:

penyimpanan lokal

/* 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 memiliki dukungan penuh peramban modern, dan secara mengejutkan juga mendukung peramban lama yang baik, antara lain IE 8, Firefox 3,5 dan Safari 4 [sebelas tahun yang lalu].

Jika Anda tidak memiliki banyak data, tetapi masih menginginkan dukungan browser yang ekstensif, mungkin opsi terbaik adalah:

Tag meta [oleh Robidu]

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

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

Kekurangannya, adalah tempat yang tepat untuk meletakkan tag meta [hingga HTML 4] di tag head, dan Anda mungkin tidak ingin data ini ada di sana. Untuk menghindarinya, atau meletakkan tag meta di badan, Anda dapat menggunakan:

Paragraf tersembunyi

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

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

Untuk lebih banyak lagi dukungan browser, Anda dapat menggunakan kelas CSS sebagai ganti atribut tersembunyi:

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

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

Ini adalah Solusi untuk 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
sumber