admin管理员组文章数量:1129437
I read the tutorial DIY widgets - How to embed your site on another site for XSS Widgets by Dr. Nic.
I'm looking for a way to pass parameters to the script tag. For example, to make the following work:
<script src="http://path/to/widget.js?param_a=1&param_b=3"></script>
Is there a way to do this?
Two interesting links:
- How to embed Javascript widget that depends on jQuery into an unknown environment (Stackoverflow discussion)
- An article on passing parameters to a script tag
I read the tutorial DIY widgets - How to embed your site on another site for XSS Widgets by Dr. Nic.
I'm looking for a way to pass parameters to the script tag. For example, to make the following work:
<script src="http://path/to/widget.js?param_a=1&param_b=3"></script>
Is there a way to do this?
Two interesting links:
- How to embed Javascript widget that depends on jQuery into an unknown environment (Stackoverflow discussion)
- An article on passing parameters to a script tag
- See also: stackoverflow.com/q/1017424/247696 – Flimm Commented Jun 30, 2015 at 15:50
15 Answers
Reset to default 198I apologise for replying to a super old question but after spending an hour wrestling with the above solutions I opted for simpler stuff.
<script src=".." one="1" two="2"></script>
Inside above script:
document.currentScript.getAttribute('one'); // 1
document.currentScript.getAttribute('two'); // 2
Much easier than jQuery or URL parsing.
You might need the polyfill for document.currentScript
from @Yared Rodriguez's answer for IE:
document.currentScript = document.currentScript || (function() {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
})();
It's better to Use feature in html5 5 data Attributes
<script src="http://path.to/widget.js" data-width="200" data-height="200">
</script>
Inside the script file http://path.to/widget.js you can get the paremeters in that way:
<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>
Another way is to use meta tags. Whatever data is supposed to be passed to your JavaScript can be assigned like this:
<meta name="yourdata" content="whatever" />
<meta name="moredata" content="more of this" />
The data can then be pulled from the meta tags like this (best done in a DOMContentLoaded event handler):
var data1 = document.getElementsByName('yourdata')[0].content;
var data2 = document.getElementsByName('moredata')[0].content;
Absolutely no hassle with jQuery or the likes, no hacks and workarounds necessary, and works with any HTML version that supports meta tags...
Got it. Kind of a hack, but it works pretty nice:
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];
I pass the params in the script tag as classes:
<script src="http://path.to/widget.js" class="2 5 4"></script>
This article helped a lot.
JQuery has a way to pass parameters from HTML to javascript:
Put this in the myhtml.html
file:
<!-- 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>
In the same directory make a subscript.js
file and put this in there:
//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);
Analyze Result:
Loading the myhtml.html page has 'foobar.mp4' print to screen. The variable called video_filename was passed from html to javascript. Javascript printed it to screen, and it appeared as embedded into the html in the parent.
jsfiddle proof that the above works:
http://jsfiddle.net/xqr77dLt/
Create an attribute that contains a list of the parameters, like so:
<script src="http://path/to/widget.js" data-params="1, 3"></script>
Then, in your JavaScript, get the parameters as an 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
If you are using jquery you might want to consider their data method.
I have used something similar to what you are trying in your response but like this:
<script src="http://path.to/widget.js" param_a = "2" param_b = "5" param_c = "4">
</script>
You could also create a function that lets you grab the GET params directly (this is what I frequently use):
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');
it is a very old thread, I know but this might help too if somebody gets here once they search for a solution.
Basically I used the document.currentScript to get the element from where my code is running and I filter using the name of the variable I am looking for. I did it extending currentScript with a method called "get", so we will be able to fetch the value inside that script by using:
document.currentScript.get('get_variable_name');
In this way we can use standard URI to retrieve the variables without adding special attributes.
This is the final code
document.currentScript.get = function(variable) {
if(variable=(new RegExp('[?&]'+encodeURIComponent(variable)+'=([^&]*)')).exec(this.src))
return decodeURIComponent(variable[1]);
};
I was forgetting about IE :) It could not be that easier... Well I did not mention that document.currentScript is a HTML5 property. It has not been included for different versions of IE (I tested until IE11, and it was not there yet). For IE compatibility, I added this portion to the code:
document.currentScript = document.currentScript || (function() {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
})();
What we are doing here is to define some alternative code for IE, which returns the current script object, which is required in the solution to extract parameters from the src property. This is not the perfect solution for IE since there are some limitations; If the script is loaded asynchronously. Newer browsers should include ".currentScript" property.
I hope it helps.
Thanks to the jQuery, a simple HTML5 compliant solution is to create an extra HTML tag, like div, to store the 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);
})
});
Live demo with the code above: http://codepen.io/anon/pen/KzzNmQ?editors=1011#0
On the live demo, one can see the data from HTML5 data-* attributes to be concatenated and printed to the log.
Source: https://api.jquery.com/data/
This is the Solution for 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');
})
I wanted solutions with as much support of old browsers as possible. Otherwise I'd say either the currentScript or the data attributes method would be most stylish.
This is the only of these methods not brought up here yet. Particularly, if for some reason you have great amounts of data, then the best option might be:
localStorage
/* On the original page, you add an inline JS Script.
* If you only have one datum you don't need JSON:
* localStorage.setItem('datum', 'Information here.');
* But for many parameters, JSON makes things easier: */
var data = {'data1': 'I got a lot of data.',
'data2': 'More of my data.',
'data3': 'Even more data.'};
localStorage.setItem('data', JSON.stringify(data));
/* External target JS Script, where your data is needed: */
var data = JSON.parse(localStorage.getItem('data'));
console.log(data['data1']);
localStorage has full modern browser support, and surprisingly good support of older browsers too, back to IE 8, Firefox 3,5 and Safari 4 [eleven years back] among others.
If you don't have a lot of data, but still want extensive browser support, maybe the best option is:
Meta tags [by Robidu]
/* HTML: */
<meta name="yourData" content="Your data is here" />
/* JS: */
var data1 = document.getElementsByName('yourData')[0].content;
The flaw of this, is that the correct place to put meta tags [up until HTML 4] is in the head tag, and you might not want this data up there. To avoid that, or putting meta tags in body, you could use a:
Hidden paragraph
/* HTML: */
<p hidden id="yourData">Your data is here</p>
/* JS: */
var yourData = document.getElementById('yourData').innerHTML;
For even more browser support, you could use a CSS class instead of the hidden attribute:
/* CSS: */
.hidden {
display: none;
}
/* HTML: */
<p class="hidden" id="yourData">Your data is here</p>
Put the values you need someplace where the other script can retrieve them, like a hidden input, and then pull those values from their container when you initialize your new script. You could even put all your params as a JSON string into one hidden field.
It's simpler if you pass arguments without names, just like function calls.
In HTML:
<script src="abc.js" data-args="a,b"></script>
Then, in JavaScript:
const args=document.currentScript.dataset.args.split(',');
Now args contains the array ['a','b']. This assumes synchronous script calling.
Parameters for <script type="module">
I had the problem to pass parameters to some JS script loaded as a module.
There are two variants, based on the ideas of @Robidy and @Fom.
In modules,
document.currentScript
is not available. Also I do not want to rely ondocument.scripts[document.scripts.length-1]
when it comes to possibly asynchronously executing modules.
@Robidy: parameters from <meta name="script.js" content>
While using <meta>
for this seems clumsy on the first sight, it starts to have some benefits:
- You can also pass (possibly sparsely filled) tabular data.
- The name can be derived from the module's name.
<meta name="module.js" content="https://cdn.skypack.dev/octokit" data-0="https://cdn.skypack.dev/[email protected]"/>
<script type="module" src="module.js"></script>
content
is placed at the first array position:meta[N][0]
in the example
data-M
gets additional tabular parameters put at theM+1
th position of the array:metas[N][M+1]
in the example
N
is theN
th meta, where0
is the first<meta>
data-X
whereX
is not a positive integer, it is ignored
I needed this, as the documented way to load Octokit failed. So I created a loader module which allows to add fallback URLs.
(example use)It does not support SRI, though.
Here is the beginning of the code of such a module.js
:
const me = import.meta.url?.split('/').pop() || 'module.js';
const metas = Array
.from(document.getElementsByName(me))
.filter(_ => _.nodeName === 'META')
.map(_ => [_.attributes.content.value].concat(Array.from(_.attributes)
.map(_ => ([_.name.split('-'), _.value]))
.filter(([name,value]) => name.length===2 && name[0] ==='data' && name[1] === `${name[1]||0}`)
.reduce((a,[[data,nr],value]) => (a[nr|0]=value, a), [])
));
I have no idea what happens if
import.meta
is not available.For the case this is no syntax error, above code uses some hardcoded value as fallback (here
'module.js'
), named after the default name of a module of course.Perhaps a better thing would be to
throw
in this case.
The variable metas
(from the example) then is an array of possibly sparsely filled arrays with the <meta>
rows' content, data-0, data-1, ..
and so on.
<meta name="module.js" content="https://cdn.skypack.dev/octokit" data-0="https://cdn.skypack.dev/[email protected]"/>
gives
[['https://cdn.skypack.dev/octokit','https://cdn.skypack.dev/[email protected]']]
and
<meta name="module.js" content="https://cdn.skypack.dev/octokit" data-2="https://cdn.skypack.dev/[email protected]"/>
gives (note the tripple comma):
[['https://cdn.skypack.dev/octokit',,,'https://cdn.skypack.dev/[email protected]']]
@Fom: JSON from hidden <div>
To parse hidden <div>
for JSON
, as suggested by @Fom, might look like:
const me = import.meta.url?.split('/').pop() || 'module.js';
const jsons = Array
.from(document.getElementsByName(me))
.filter(_ => _.nodeName === 'DIV')
.map(_ => JSON.parse(_.innerText));
This hands out an array of the JSONs found in all <div name>
elements named after the module. (You might need to wait until all DOM is loaded.)
The automatically derived name
:
If you use something like
<script type="module" src="/path/to/module.js#abc"></script>
the line
const me = import.meta.url?.split('/').pop();
sets me
to module.js#abc
, so you need to give name
like following:
<meta name="module.js#abc" content="parameter"/>
<div name="module.js#abc">{"a":"b"}</div>
<script type="module" src="/path/to/module.js#abc"></script>
Note that JS apparently allows arbitrary strings in name
.
Final note
This all works similar for normal <script>
without <script type="module">
, if you replace import.meta.url
with document?.currentScript.src
To change the code such, that it works for normal scripts, modules and WebWorkers, and create some meaningful script which can be executed as any of these, is left as an exercise for the reader.
data attributes
If you combine all the information here you arrive at a best practice answer. Note that this way everything will be a string.
<script src="index.js" data-foo="bar" data-foo-bar="1"></script>
index.js
// Can also destructure here if you prefer
const args = document.currentScript.dataset;
// args.foo is "bar", args.fooBar is "1"
URL params
Should you for some reason prefer to use URL params, here is what I got for that. It has some syntax disadvantages. Also, unfortunately everything is still a string.
<script src="index.js?foo=bar&foo-bar=1"></script>
index.js
const args = Object.fromEntries(new URL(document.currentScript.src).searchParams);
// args.foo is "bar", args.foo-bar is "1"
See Also
currentScript
本文标签: javascriptHow to pass parameters to a Script tagStack Overflow
版权声明:本文标题:javascript - How to pass parameters to a Script tag? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736746242a1950790.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论