How can I distinguish from dynamic loaded script and normal script included using src property? For example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="static.js" type="text/javascript"></script>
<script type="text/javascript">
document.getElementsByTagName('head')[0].appendChild(document.createElement('script').src = 'dynamic.js');
</script>
</head>
<body>
<script type="text/javascript">
// I want to distinguish dynamic.js and static.js script tags
</script>
</body>
</html>
Add a specific HTML5 data-* attribute to the dynamic scripts:
var script = document.createElement("script");
script.setAttribute("data-is-dynamic", "true");
script.id = "script1";
script.src = "dynamic.js";
document.getElementsByTagName('head')[0].appendChild(script);
An option for getting the <head> element is to use document.head, although it's not supported in older browsers. Here's the MDN docs - https://developer.mozilla.org/en-US/docs/DOM/document.head
Then to distinguish later, use:
var someScript = document.getElementById("script1"); // or any script tag you want to analyze
if (someScript.getAttribute("data-is-dynamic") === "true") {
// is dynamic
} else {
// is static
}
Of course, at the same time, you can set an attribute on static script tags, like data-is-static, and then check for that in the opposite manner.
This allows you to validly set a "flag" on a script tag that you can retrieve later.
Related
Is there a way to use javascript to modify a script element?
Like for example:
HTML:
<script id="something" src="/js/file.js"></script>
Javascript:
var something = document.getElementById("something");
something.src = "/js/anotherfile.js"
Is it possible? Because I have a bit of code that works like that and it sort of doesn't work
To be specific, here's the code:
<!DOCTYPE html>
<html>
<head>
<title>MyohTheGod's Website</title>
<link rel="icon" type="image/x-icon" href="/supercorn.gif" defer>
</link>
<link id="css" href="/css/dark.css" rel="stylesheet" type="text/css">
</link>
<script src="/js/particles.js" defer></script>
<script src="/js/header.js"></script>
<script src="/js/theme.js"></script>
<script>window.alert("Welcome to the Home of MyohTheGod. You can play games, check out our web proxies, and more. Also, please do check out the About page. Press OK to continue...");</script>
</head>
<body>
-snip-
</body>
<script id="foot" src="/js/footer.js"></script>
</html>
<script>
-snip-
</script>
var css = document.getElementById("css");
var foot = document.getElementById("foot");
function toggleDLmode(m) {
-snip-
if (dlmodebool) {
css.href = "/css/dark.css"
foot.src="/js/dark-footer.js"
} else {
css.href = "/css/index.css"
foot.src="/js/footer.js"
}
}
-snip-
It is working, do you inspect it? It does changed, but maybe you're thinking, "hm why this /js/anotherfile.js is not downloaded?". Well because of the script tag is already rendered and already downloaded, so you can't do that. What you can do though add NEW script tag.
Maybe this will help How to dynamically change the script src?. This links would explain more why your code "does not work".
There certainly is. You can use document.scripts which returns an collection that you can iterate through like an array. You can change the code using the innerHTML property very much like a normal element. See here https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
Edited to add: If you've got a html page with multiple script tags, the document.script collection has each script in the order they appear. The code below will log out the source (src tag) or the actual javascript for each script element.
You can also 'write' javascript by setting the innerHTML property.
IMHO it's a bit of a solution that's looking for a problem but at least it gives you access to the number of scripts you have.
[...document.scripts].forEach(script => {
if (script.src != '') {
console.log("Script source:" + script.src);
} else {
console.log(script.innerHTML);
}
});
Okay so, I once tried this a long time ago and it never happened before.
if I do
var blocks = 0;
document.getElementById('blocks').value = blocks;
Uncaught TypeError: Cannot set property 'value' of null
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="/css/Index.css">
<script src="/js/Index.js"></script>
</head>
<body>
<input type = "text" id="blocks"/>
</body>
</html>
Try moving your script to the bottom of the body. Element does not exist at the time of execution.
<head>
<title>Home</title>
<link rel="stylesheet" href="/css/Index.css">
</head>
<body>
<input type = "text" id="blocks"/>
<script src="/js/Index.js"></script><!-- here-->
</body>
If your script is saved in its own JS file (i.e. not as a <script> tag in the HTML), you cannot access DOM elements until the document is loaded. So, wrap your code in an onload event handler:
document.onload = function() {
var blocks = 0;
document.getElementById('blocks').value = blocks;
}
Try placing the <script> tag at the end of your <body> element to ensure that the element is accessible at the time the script is called:
<!DOCTYPE html>
<head>
<title>Home</title>
<link rel="stylesheet" href="/css/Index.css">
</head>
<body>
<input type = "text" id="blocks"/>
<script src="/js/Index.js"></script>
</body>
load your script in footer section or very end of the body instead of head. Your script is executing before DOM is loaded or call the specified statements under load event.
This is failing because your script is running before the DOM is finished rendering. You should always place your DOM-manipulating script inside document.onload function, which runs after the DOM has finished loading.
Also, you should always check for NPE (NullPointerException); it's a good habit to get into:
document.onload = () => {
const element = document.getElementById('blocks');
if (element) {
element.value = 0;
} else {
// consider publishing some warning
console.error("Could not find element #blocks");
}
}
As others have suggested, the common practice to ensure your script runs after elements have loaded is to move the script tag to the bottom of the body, after the elements themselves. However, a more modern approach is to use the defer attribute on your script tag: this ensures the script won't load until your DOM has loaded, but you don't need to worry about the tag's placement in the page relative to DOM elements you'll be manipulating. It's supported by all modern browsers, even IE10+.
So simply add defer onto your existing <script> tag and everything should work :)
I'm working on a map that will allow the user to select one of two expressions of a dataset and toggle between them. Each expressions is set up in its own .js (main_heat.js for a heatmap, main.js for proportional symbols).
My issue is setting up controls in my index.html file that will and load the selected expression based on a click. The following code doesn't throw errors, but doesn't produce the result (reloading a different expression) that I am expecting:
index.html:
<div id ="expression">
<h4>Choose your expression</h4>
Heatmap |
Proportional Symbols
</div>
<!--EXTERNAL SCRIPT LINKS-->
<script type="text/javascript" src="js/main_heat.js"></script>
<script type="text/javascript" src="js/main.js"></script>
main.js:
function changeExpression(src){
var heat = document.createElement("script");
heat.src = "js/main_heat.js";
document.body.appendChild(heat);
var prop = document.createElement("script");
prop.src = "js/main.js";
document.body.appendChild(prop);
if (src === "heat"){
loadScript("main_heat.js")
} else if (src === "prop"){
loadScript("main.js");
}
};
function loadScript(src){
var el = document.createElement("script");
el.src = src;
document.body.appendChild(el);
}
Both changeExpression and loadScript are called in an initial callback function in main.js, and I'm struggling to see why the "onclick" in index.html doesn't produce a change. Does anybody see where I'm going wrong or have an insight on what might be causing this?
There are couple of ways you can achieve what you want if you need to run different scripts based on 'onClick'.
If the size of Js files does not matter best way is to add Js files with script tags in the 'index.html' file as below.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<div id ="expression">
<h4>Choose your expression</h4>
Heatmap |
Proportional Symbols
</div>
</body>
<!--EXTERNAL SCRIPT LINKS-->
<script type="text/javascript" src="js/main_heat.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</html>
In case you need to add those two scripts based on onClick, You can do it with a simple function as follows.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<div id ="expression">
<h4>Choose your expression</h4>
Heatmap |
Proportional Symbols
</div>
</body>
<script type="text/javascript">
let changeExpression = function (type) {
let elem = document.createElement("script");
if (type === 'heat') {
elem.src = "js/main_heat.js";
} else {
elem.src = "js/main.js";
}
map.off();
map.remove();
document.body.appendChild(elem);
}
</script>
</html>
Hope this helps!
Missing a semi-colon at end of line loadScript("main_heat.js")
Check the paths to your scripts because they're different (in one place you omit the directory) and therefore are likely not found
Check the console for any error like net::ERR_ABORTED 404 (Not Found)
Consider adding code to check if script is already appended because every click will append it again
This might be a dumb question but I have actually never done this and what I am trying is not working.
I have 2 files
test.html
test.js
I am linking the js as an external in test.html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="test.js"></script>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>
<body>
</body>
</html>
In my js file I have something like this
document.appendChild('<div>testing</div>')
I also tried
document.getElementsByTagName('body').appendChild('<div>testing</div>')
What I am doing wrong? I just want to learn how to generate html from an external js file for a future project I am working on.
You should generally try to run scripts that depend on the page after the document has been parsed, not before - if you put the script in <head> and run it immediately, the <body> has not been created yet. Give your script tag the defer attribute so that it only runs after the document is fully parsed:
<script defer type="text/javascript" src="test.js"></script>
appendChild accepts an element as a parameter, not a string
You need to append to the body, not the document itself (Only one element on document allowed.)
If you want to append an HTML string, assign/concatenate to the .innerHTML property
Assigning to .innerHTML will corrupt existing references to elements inside, including listeners. In order to keep listeners active, use insertAdjacentHTML instead:
document.body.appendChild(document.createElement('div'))
.textContent = 'testing1';
// Another method:
document.body.innerHTML += '<div>testing2</div>';
// Another method:
document.body.insertAdjacentHTML('beforeend', '<div>testing3</div>');
My goal is to dynamically create an iframe and write ad JavaScript into it using jQuery (e.g. Google AdSense script). My code works on Chrome, but fails intermittently in Firefox i.e. sometimes the ad script runs and renders the ad, and other times it doesn't. When it doesn't work, the script code itself shows up in the iframe.
My guess is these intermittent failures occur because the iframe is not ready by the time I write to it. I have tried various iterations of iframe_html (my name for the function which is supposed to wait for the iframe to be ready), but no luck. Any help appreciated!
PS: I have read various threads (e.g. jQuery .ready in a dynamically inserted iframe). Just letting everyone know that I've done my research on this, but I'm stuck :)
Iteration 1:
function iframe_html(html){
$('<iframe name ="myiframe" id="myiframe"/>').appendTo('#maindiv');
$('#myiframe').load(
function(){
$('#myiframe').ready( function(){
var d = $("#myiframe")[0].contentWindow.document;
d.open();
d.close();
d.write(html);
});
}
);
};
Iteration 2:
function iframe_html(html){
$('<iframe id="myiframe"/>').appendTo('#maindiv').ready(
function(){
$("#myiframe").contents().get(0).write(html);
}
);
};
Honestly, the easiest and most reliable way I have found when dealing with the load events on iframes uses the "onload" attribute in the actual iframe tag. I have never had much of a problem with setting the content once the "onload" event fires. Here is an example:
<html>
<head>
<script type='text/javascript' src='jquery-1.3.2.js'></script>
<script type='text/javascript'>
$(function() {
var $iframe = $("<iframe id='myiframe' name='myiframe' src='iframe.html' onload='iframe_load()'></iframe>");
$("body").append($iframe);
});
function iframe_load() {
var doc = $("#myiframe").contents()[0];
$(doc.body).html("hi");
}
</script>
</head>
<body></body>
</html>
The problem with this is that you have to use attribute tags and global function declarations. If you absolutely CAN'T have one of these things, I haven't had problems with this (although it doesn't look much different than your attempts, so I'm not sure):
<html>
<head>
<script type='text/javascript' src='jquery-1.3.2.js'></script>
<script type='text/javascript'>
$(function() {
var $iframe = $("<iframe id='myiframe' name='myiframe' src='iframe.html'></iframe>");
$iframe.load(iframe_load);
$("body").append($iframe);
});
function iframe_load() {
var doc = $("#myiframe").contents()[0];
$(doc.body).html("hi");
}
</script>
</head>
<body></body>
</html>
This is one of the most frustrating parts of the DOM and JavaScript - my condolences are with you. If neither of these work, then open up Firebug and tell me what the error message is.
false.html:
<html>
<head><title></title></head>
<body></body>
</html>
JS:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
function iframe_html(html)
{
var id = "myiframe_" + ((new Date()).getTime());
$('<iframe src="false.html" name ="'+id+'" id="'+id+'" />').appendTo('#maindiv');
var loadIFrame = function()
{
var elIF = window.document.frames[id];
if (elIF.window.document.readyState!="complete")
{
setTimeout(loadIFrame, 100);
return false;
}
$(elIF.window.document).find("body").html(html);
}
loadIFrame();
};
$(function(){
iframe_html("<div>hola</div>");
});
</script>
</head>
<body>
<div id="maindiv"></div>
</body>
</html>
then please see this link