append child after the node of the script that made the call - javascript

When the call bellow is done the class creates a set of elements (a form) and then I want to append them right after the script that called it.
I have been looking at various similar questions but the best of them simply append it after the last script on the page.
It would work nicely in the head but not the body.
<script type="text/javascript">
new exampleClass();
</script>

You should have some type of unique identification to find and append elements after the script. You can use document.getElementById() if you have id, or document.getElementsByTagName("script") to get script elements and get the required script element and then use appendChild()

Ok, here is the horrible hack mentioned.
HTML
<div>Stuff</div>
<script type="text/javascript">
noop();
</script>
<div>More stuff</div>
<script type="text/javascript">
new ExampleClass();
</script>
<div>More stuff</div>
<script type="text/javascript">
noop();
</script>
<div>More stuff</div>
Javascript
function noop() {}
function appendAfter(node, newNode) {
if (node.nextSibling) {
node.parentNode.insertBefore(newNode, node.nextSibling);
} else {
node.parentNode.appendChild(newNode);
}
}
function ExampleClass() {
window.addEventListener("load", function () {
var scripts = document.getElementsByTagName("script"),
div = document.createElement("div"),
length = scripts.length,
i = 0,
script;
div.appendChild(document.createTextNode("Inserted"));
while (i < length) {
script = scripts[i];
if (script.firstChild && script.firstChild.nodeValue.indexOf("ExampleClass()") !== -1) {
appendAfter(script, div);
}
i += 1;
}
}, false);
}
On jsfiddle

Based on some of your comments and some other similar I have thought of doing something like this and it seems to work.
// Generate random string we can use as element id
var rs = Math.random().toString(36).substring(2);;
// Document write an empty div with the above string as id
document.write('<div id="' + rs + '"></div>');
// Get the element to use for append
var ip = document.getElementById(rs);
Please feel free to comment if you think it may have a fatal flaw.

Related

Load content from Div with Div Id

I have some code working but want to make an adaptation but can't get it to work. I have the following:
<script type="text/javascript">
// <![CDATA[
var textBlocks = new Array('Apple', 'Banana', 'Orange');
function changeText(elemid) {
var ind = document.getElementById(elemid).selectedIndex;
document.getElementById("display").innerHTML=textBlocks[ind];
}
// ]]>
</script>
But only want to change 'Apple', 'Banana', 'Orange' into something to load the content from a specific DIV's with DIV ID's: content A, content B and content C.
Thanks, Eddy
Assuming I understood what you need try this:
var textDivsId = new Array('contentA', 'contentB', 'contentC');
function changeText(elemid) {
var ind = document.getElementById(elemid).value;
document.getElementById("display").innerHTML = document.getElementById(ind).innerHTML;
}
where contentA, contentB and contentC are ID's of DIVs you want to load. Here is some working example on JSFiddle.
This is not an elegant solution, have you considered using visibility=visible property and CSS class swapping dynamically?
I'm not entirely sure what you mean by
into something to load the content from a specific DIV's with DIV ID's: content A, content B and content C
but if you mean you have 3 divs:
<div id='A'>Apple</div>
<div id='B'>Banana</div>
<div id='C'>Orange</div>
then you can create an array within javascript of their contents with:
var textBlocks = [document.getElementById('A').innerHTML, document.getElementById('B').innerHTML, document.getElementById('C').innerHTML];
however, this will only work if it runs in this order (i.e. your divs have to be inserted into your document before you run this javascript to build textBlocks. For this reason you might want to consider using jQuery to detect when your HTML elements are ready:
<script src='https://code.jquery.com/jquery-latest.min.js' type='text/javascript'></script>
<script type="text/javascript">
// <![CDATA[
var textBlocks = [];
function changeText(elemid) {
var ind = document.getElementById(elemid).selectedIndex;
document.getElementById("display").innerHTML=textBlocks[ind];
}
$(document).ready(function() {
textBlocks = [document.getElementById('A').innerHTML, document.getElementById('B').innerHTML, document.getElementById('C').innerHTML];
// ... do your other stuff here, like call changeText(..)
});
// ]]>
</script>
<div id='A'>Apple</div>
<div id='B'>Banana</div>
<div id='C'>Orange</div>

Run JavaScript inside <script src="..."></script> Tags?

I've a JavaScript file that processes tab switches. Here is the source:
var tCount = 0;
function SwitchToTab(id) {
if (id < 0 || id > tCount) { id = 0; }
for (var i = 0; i < tCount; i++) { document.getElementById("tab" + i).className = ""; }
document.getElementById("tab" + id).className = "active";
for (var i = 0; i < tCount; i++) { document.getElementById("area" + i).style.display = "none"; }
document.getElementById("area" + id).style.display = "";
}
function InitializeTabs(initialTabId, tabsCount) {
tCount = tabsCount;
SwitchToTab(initialTabId);
}
I'm trying to make it as short as possible like this:
<script src="Resources/Tabs.js">InitializeTabs(0, 4);</script>
It doesn't works but it works if I separate them like this:
<script src="Resources/Tabs.js"></script>
<script>InitializeTabs(0, 4);</script>
So, is there any way to run JavaScript inside <script src="..."></script> tags? What I am missing?
No, this is not possible. The html spec dictates that a <script> tag does one or the other.
<script>Tag Html Spec, emphasis mine.
The script may be defined within the contents of the SCRIPT element or in an external file. If the src attribute is not set, user agents must interpret the contents of the element as the script. If the src has a URI value, user agents must ignore the element's contents and retrieve the script via the URI.
You are suppose to do it the second way. in <script src="Resources/Tabs.js">InitializeTabs(0, 4);</script> you are referencing an external javascript file, your inline code should go into a second script block.
You can either use src, or put JavaScript inside the tag.
But not both at once. There's no downside to using two tags anyway (apart from larger file size).
When you include <script src="Resources/Tabs.js"></script>, you are mentioning that you want to use the Javascript which is included inside the Tabs.js file so that the compiler knows where to look for InitializeTabs function, when it is trying to execute the function.
Now if you want to include some Javascript inline, that is inside the HTML, hen you use the <script>... JAVASCRIPT HERE .... </script>
You need to do it like this
<script src="Resources/Tabs.js"></script>
<script>InitializeTabs(0, 4);</script>
You can't put javascript inside of <script src="... tags, but you could run a JavaScript file which parses the HTML, looking for <script src tags, which converts it into two tags.
For example,
<script src="Resources/Tabs.js">InitializeTabs(0, 4);</script>
would have to be converted into
<script src="Resources/Tabs.js"></script>
<script>InitializeTabs(0, 4);</script>
Here's the code I tried:
var tags = document.querySelectorAll("script[src]");
[].forEach.call(tags, function(elem){
var text = elem.innerText;
var src = elem.src;
var parent = elem.parentNode;
parent.removeChild(elem);
var newTag = document.createElement('script');
newTag.setAttribute('src', src);
parent.appendChild(newTag);
var newTag = document.createElement('script');
var t = document.createTextNode(text);
newTag.appendChild(t);
parent.appendChild(newTag);
});
in a JSFiddle

Javascript add new class in body tag

If OS is MAC I set a variable & then on condition I want to add new class in body tag.
Here is my code
<script type="text/javascript" language="javascript">
var mac=0;
if(navigator.userAgent.indexOf('Mac') > 0){
mac=1;
}else{
mac=0;
}
if(1==mac){
//document.body.className+='mac-os';
//document.getElementsByTagName('body')[0].className+='mac-os';
$('body').addClass('mac-os');
}else{
//document.body.className+='win-os';
//document.getElementsByTagName('body').className+='win-os';
//$('body').addClass('mac-os');
//$("body.className").addClass('win-os');
//document.body.className += " " + 'win-os';
$("body").addClass('win-os');
}
</script>
I have tried all but fail.
It's likely that the body element simply doesn't exist at the point your current code is being executed.
Ensure that your code is not executed until the DOM is ready, by putting it inside a ready handler:
$(document).ready(function() {
// your code
...
});
It would also work if you put it inside the <body> element, typically at the end of the page.
If your script is in head your should wait until the body to be loaded, Change your code to:
$(document).ready(function(){
var mac=0;
if(navigator.userAgent.indexOf('Mac') > 0){
mac=1;
}else{
mac=0;
}
if(1==mac){
//document.body.className+='mac-os';
//document.getElementsByTagName('body')[0].className+='mac-os';
$('body').addClass('mac-os');
}else{
//document.body.className+='win-os';
//document.getElementsByTagName('body').className+='win-os';
//$('body').addClass('mac-os');
//$("body.className").addClass('win-os');
//document.body.className += " " + 'win-os';
$("body").addClass('win-os');
}
});
Or put your script into body tag:
<body>
<!-- your script -->
<!-- others -->
</body>
The html elements don't exist until after the page loads, but your js is executing before the <body> tag is even read by the browser. Your script tags come before the <body> tag, so the browser executes the js code first. If you need to delay execution of your js code until after the page loads(as is the case with most js code)--and you don't want to use jquery--then you can do this:
<script type="text/javascript">
window.onload = function() {
//js code here
}
</script>
That function will not execute until the onload event occurs, which is after the page loads. The problem with the onload event is that all the images must load completely before the event fires, and that can take a long time, which will delay rendering any styles set by the js, or allowing buttons to fire onclick handlers set by the js.
As an alternative, you can put your script tags just before the closing body tag:
...
<script type="text/javascript">
//js code here
</script>
</body>
In that case, all the html on the page will have been parsed by the browser when the javascript tags are encountered, and as a result all the html elements will exist. <img> tags that are parsed will exist, but the browser doesn't wait for them to load--the browser continues on and parses the rest of the html while the images are loading. Even the body element exists even though its closing tag hasn't been seen yet.
Better still is to link to a js file, so that your js code isn't cluttering up the html:
<script type="text/javascript" src="myjs.js"></script>
</body>
Also, if you have this:
<body class="bgcolor">
...and your js code does this:
document.getElementsByTagName('body')[0].className += 'mac-os';
...then you will get his:
<body class="bgcolormac-os">
...which is not what you want. You need to add a space in there:
.... += ' mac-os';
...so that you get:
<body class="bgcolor mac-os">
A comment on your code style: you need to add more spaces, for instance:
if (1 == mac) {
document.getElementsByTagName('body')[0].className += 'mac-os';
}
else {
document.getElementsByTagName('body')[0].className += 'win-os';
}
Also, don't use 'cuddled' else clauses--they are really ugly. Consider using the style in the example where the else starts on a new line. Code clarity is what you are aiming for--not the fewest number of bytes. You might also consider indenting just 2 spaces--js statements can get pretty long, so conserving space there can be helpful.
And to avoid having to re-type those long document.get.... statements and make your code easier to read, you can do thing things like this:
var mybody = document.getElementsByTagName('body')[0];
if (1 == mac) {
mybody.className += ' mac-os';
}
else {
mybody.className += ' win-os';
}
Your code works, maybe you forgot to wrap your code with
$(function () {
//your code
});
?
$(function () {
var mac = 0;
if (navigator.userAgent.indexOf('Mac') > 0) {
mac = 1;
} else {
mac = 0;
}
if (1 == mac) {
//document.body.className+='mac-os';
//document.getElementsByTagName('body')[0].className+='mac-os';
$('body').addClass('mac-os');
} else {
//document.body.className+='win-os';
//document.getElementsByTagName('body').className+='win-os';
//$('body').addClass('mac-os');
//$("body.className").addClass('win-os');
//document.body.className += " " + 'win-os';
$("body").addClass('win-os');
}
});
Just put your jquery codes in $(document).ready(...) block to be sured that they execute in correct time...:
$(document).ready(function() {
// jquery codes...
$(document.body).addClass('your-class');
// ...
});

How to run and display processing code (currently in part of the document.body) in an html canvas?

NOTE: I know I can import .pde files but I need to run code on screen so I will not be using this.
My three following attempts failed. I do not know which one was closer to achieving and I do not prefer one as long as it produces desired result. Appreciate the help by helping me get any of the attempts working/suggesting a new one.
1ST ATTEMPT) - use getText function written below but then some text that is not code can be found in the resulting jscode variable and thus the processing instance does not work.
function getText(n) {
var s = [];
function getStrings(n, s) {
var m;
if (n.nodeType == 3) { // TEXT_NODE
s.push(n.data);
}
else if (n.nodeType == 1) { // ELEMENT_NODE
for (m = n.firstChild; null != m; m = m.nextSibling) {
getStrings(m, s);
}
}
}
getStrings(n, s);
var result = s.join(" ");
return result;
}
var processingCode = getText(document.body)
processingCode.replace(/<[^>]+>¦&[^;]+;/g,'').replace(/ {2,}/g,' ');
var jsCode = Processing.compile(processingCode).sourceCode;
alert(jsCode);
var canvas = document.getElementById("mysketch");
var processingInstance = new Processing(canvas, jsCode);
....
<span class="sketch">
<canvas id="mysketch"></canvas>
</span>
2ND ATTEMPT) Same as above but added a tag with id="all_processing_code" but couldn't figure out how to get the text within anyway. This did not work:
var processingCode = getText(document.getElementbyId(all_processing_code));
3RD ATTEMPT) Removed getText and tried to use JQuery text() to isolate the code. Was having trouble mixing JS and Jquery though. Tried different stuff and none worked. What would be appropriate way to mix it in? What script type should I use? This was confusing.
<script type="text/jquery">
var processingCode = $('#all_processing_code').text();
//processingCode.replace(/<[^>]+>¦&[^;]+;/g,'').replace(/ {2,}/g,' ');
var jsCode = $.Processing.compile(processingCode).sourceCode;
alert(jsCode);
var canvas = $(#'mysketch');
var processingInstance = new $.Processing($('canvas'), $('jsCode'));
}
</script>
First, check if your processing code is wrapped by an html element (like a div or something else) with an id. If it isn't, please do it!
For exemple:
<div id="mycode">
void setup() {
background(0);
}
</div>
After this, check if you have the getProcessingSketchId() function declared in your code. Processing IDE in JavaScript mode already exports html files with that function. If there isn't, please declare it inside your <head>:
<script type="text/javascript">
// convenience function to get the id attribute of generated sketch html element
function getProcessingSketchId () { return 'yourcanvasid'; }
</script>
You can include JQuery from google api including this line in your html before you use JQuery:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
// convenience function to get the id attribute of generated sketch html element
function getProcessingSketchId () { return 'yourcanvasid'; }
</script>
Assuming that you want to run your processing code when the page just has loaded, just append this code after the getProcessingSketchId() declaration.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
// convenience function to get the id attribute of generated sketch html element
function getProcessingSketchId () { return 'yourcanvasid'; }
$(document).ready(function() {
new Processing(getProcessingSketchId(), $('#mycode').html());
});
</script>
You can create this code inside any other <script type="text/javascript">.
At the end, you will have something like this:
<html>
<head>
<!-- Your title, meta tags, stylesheet and all other stuff here -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
// convenience function to get the id attribute of generated sketch html element
function getProcessingSketchId () { return 'yourcanvasid'; }
$(document).ready(function() {
new Processing(getProcessingSketchId(), $('#mycode').html());
});
</script>
</head>
<body>
<div id="mycode">
void setup() {
background(0);
}
</div>
</body>
</html>

How to force a script reload and re-execute?

I have a page that is loading a script from a third party (news feed). The src url for the script is assigned dynamically on load up (per third party code).
<div id="div1287">
<!-- dynamically-generated elements will go here. -->
</div>
<script id="script0348710783" type="javascript/text">
</script>
<script type="javascript/text">
document.getElementById('script0348710783').src='http://oneBigHairyURL';
</script>
The script loaded from http://oneBigHairyURL then creates and loads elements with the various stuff from the news feed, with pretty formatting, etc. into div1287 (the Id "div1287" is passed in http://oneBigHairyURL so the script knows where to load the content).
The only problem is, it only loads it once. I'd like it to reload (and thus display new content) every n seconds.
So, I thought I'd try this:
<div id="div1287">
<!-- dynamically-generated elements will go here. -->
</div>
<script id="script0348710783" type="javascript/text">
</script>
<script type="javascript/text">
loadItUp=function() {
alert('loading...');
var divElement = document.getElementById('div1287');
var scrElement = document.getElementById('script0348710783');
divElement.innerHTML='';
scrElement.innerHTML='';
scrElement.src='';
scrElement.src='http://oneBigHairyURL';
setTimeout(loadItUp, 10000);
};
loadItUp();
</script>
I get the alert, the div clears, but no dynamically-generated HTML is reloaded to it.
Any idea what I'm doing wrong?
How about adding a new script tag to <head> with the script to (re)load? Something like below:
<script>
function load_js()
{
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.src= 'source_file.js';
head.appendChild(script);
}
load_js();
</script>
The main point is inserting a new script tag -- you can remove the old one without consequence. You may need to add a timestamp to the query string if you have caching issues.
Here's a method which is similar to Kelly's but will remove any pre-existing script with the same source, and uses jQuery.
<script>
function reload_js(src) {
$('script[src="' + src + '"]').remove();
$('<script>').attr('src', src).appendTo('head');
}
reload_js('source_file.js');
</script>
Note that the 'type' attribute is no longer needed for scripts as of HTML5. (http://www.w3.org/html/wg/drafts/html/master/scripting-1.html#the-script-element)
Creating a new script tag and copying the contents of the existing script tag, and then adding it, works well.
var scriptTag = document.createElement('script');
scriptTag.innerText = "document.body.innerHTML += 'Here again ---<BR>';";
var head = document.getElementsByTagName('head')[0];
head.appendChild(scriptTag);
setInterval(function() {
head.removeChild(scriptTag);
var newScriptTag = document.createElement('script');
newScriptTag.innerText = scriptTag.innerText;
head.appendChild(newScriptTag);
scriptTag = newScriptTag;
}, 1000);
This won't work if you expect the script to change every time, which I believe is your case. You should follow Kelly's suggestion, just remove the old script tag (just to keep the DOM slim, it won't affect the outcome) and reinsert a new script tag with the same src, plus a cachebuster.
Small tweak to Luke's answer,
function reloadJs(src) {
src = $('script[src$="' + src + '"]').attr("src");
$('script[src$="' + src + '"]').remove();
$('<script/>').attr('src', src).appendTo('head');
}
and call it like,
reloadJs("myFile.js");
This will not have any path related issues.
Use this function to find all script elements containing some word and refresh them.
function forceReloadJS(srcUrlContains) {
$.each($('script:empty[src*="' + srcUrlContains + '"]'), function(index, el) {
var oldSrc = $(el).attr('src');
var t = +new Date();
var newSrc = oldSrc + '?' + t;
console.log(oldSrc, ' to ', newSrc);
$(el).remove();
$('<script/>').attr('src', newSrc).appendTo('head');
});
}
forceReloadJS('/libs/');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
I know that is to late, but I want to share my answer.
What I did it's save de script's tags in a HTML file,
locking up the scripts on my Index file in a div with an id, something like this.
<div id="ScriptsReload"><script src="js/script.js"></script></div>
and when I wanted to refresh I just used.
$("#ScriptsReload").load("html_with_scripts_tags.html", "", function(
response,
status,
request
) {
});

Categories

Resources