getting the HEAD element from overlay.js firefox plugin - javascript

I have a lightwiehgt plugin to firefox which needs to inject a script into the HTML.
The code looks like this:
var head = document.getElementsByTagName("head")[0];
var newscrpt;
newscrpt = document.createElement('script');
newscrpt.type = "text/javascript" ;
newscrpt.src = "http://blabla.com/...";
newscrpt = head.appendChild(newscrpt);
The problem is that document.getElementsByTagName("head")[0] returns 'undefined', and checking document.getElementsByTagName("head").length is 0.
It currently executes on the browser document.onLoad event but I also tried calling it from window.setTimeout to make sure it is not a problem with loading synchronization, but the same happens.
Any ideas from anyone?
Thanks!

If you're using a frame or an iframe object, you should not reference the document directly but do something like:
var doc = frame.contentWindow.document;
After that you can get the head. I'm using jQuery to add some resources to it:
$(doc).find('head').append(
'<link type="text/css" rel="stylesheet" href="MyStylesheet.css" />');
Hope it helps.

Related

Unable to inject jquery in iframe

i'm having issues with injecting jQuery into an iframe. With regular javascript it works as intended, but not with jQuery.
I have appended the jQuery CDN link to the iframes <head> and if I inspect the iframe element i can see it there. I can also see the scripts in the body tag after the function has run.
When executing the jquery script i get this error.
Uncaught ReferenceError: $ is not defined
If i add these I don't get the error but nothing happens.
$iframe[0].contentWindow.$ = $;
$iframe[0].contentWindow.jQuery = $;
I've tried to add timeouts to the append function to see if it was an issue with the CDN not loading quick enough. But no difference.
If i put the HTML and jQuery outside the iframe everything works as intended so I think there is something i've done wrong or missed regarding the iframe. Anyone have an idea what I could've done wrong here?
This is the function that injects the scripts
injectScript() {
let $iframe = $('#iframe');
$iframe.ready(function () {
$iframe[0].contentWindow.$ = $;
$iframe[0].contentWindow.jQuery = $;
const jqueryScript = document.createElement("script");
jqueryScript.type = "text/javascript";
jqueryScript.src = "https://code.jquery.com/jquery-3.5.1.min.js"
$iframe.contents().find("head").append(jqueryScript);
// This code works
let vanilla = "<script>document.getElementById('vanilla').innerHTML = 'bar'<";
vanilla += "/script>";
$iframe.contents().find("body").append(vanilla);
// This code works **not**
let jQuery = "<script>$('#jquery').text('foo')<";
jQuery += "/script>";
$iframe.contents().find("body").append(jQuery);
})
}
the html in the iframe
<div id="jquery">foo</div>
<div id="vanilla">foo</div>

Place a script immediately after the opening <body> tag

I would like to place a Google tag manager script and according to Google Tag documentation, the script should be placed immediately after the opening tag.
Since we cannot change the source code, we have to append the script using the following code snippet.
<script type="text/javascript">
(function () {
var url = "path/to/js/file";
var gtm = document.createElement('script');
gtm.type = 'text/javascript';
gtm.async = true;
gtm.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + url;
var s = document.getElementsByTagName('body')[0];
s.parentNode.insertBefore(gtm, s);
})();
</script>
It is almost the same as Google analytics script snippet. Now the script is appended right before the body tag. I am not sure if using jQuery method insertAfter is the proper way to do it or if there is a better way!
I appreciate your kind help.
Actually your code inserts script between the head and body tags. Use this instead:
var s = document.body.firstChild;
s.parentNode.insertBefore(gtm, s);
You can use Node.insertBefore for this:
var body = document.getElementsByTagName("body")[0];
body.insertBefore(gtm, body.firstChild);
This works even if body tag has no firstChild.
This Q is not relevant anymore (DEC 2021), since GTM change the Setup and install of Tag Manager:
On the "new" setup you should:
Place the <script> code snippet in the <head> of your web page's HTML output, preferably as close to the opening <head> tag as
possible, but below any dataLayer declarations.
**Additionally - Place the <noscript> code snippet immediately after the tag in your HTML output.
https://support.google.com/tagmanager/answer/6103696
About <noscript> no meaning to add <noscript> by any Javascript code (noscript works only in browsers when JavaScript is off).
let html = '<p>Your HTML code here</p>';
document.body.insertAdjacentHTML('afterbegin', html);
The insertAdjacentHTML method allows you to insert an HTML string at a specified position relative to an element. In this case, we use 'afterbegin' to insert the HTML just after the opening tag.
I think you can try this out - appendChild
document.getElementsByTagName("body")[0].appendChild(gtm);
Try this:
var script = 'The script content here'; // Add your JS as a string,
var url = 'path/to/js/file'; // Or link to the file.
var scriptNode = document.createElement('script'); // Create a script Element
scriptnode.setAttribute('type', "text/javascript"); // Set the Element's `type` attribute.
// Either:
scriptNode.appendChild(document.createTextNode(script)); // Add the text to the script Element.
// Or:
scriptNode.setAttribute('src', url); // Link to the script
// Place the script Element before the first child of the body.
document.body.insertBefore(scriptNode , document.body.firstChild);
So, basically, use insertBefore
If you are utilizing jQuery, you may be able to use .prepend().
(function () {
var url = "path/to/js/file";
var gtm = document.createElement('script');
gtm.type = 'text/javascript';
gtm.async = true;
gtm.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + url;
$('body').prepend(gtm);
})();
Can you have an element in your body tag as first element, and append the script just before it. Use yourFirstElementIdfromBodyTag.before(here is your appended code goes) ..
For Example
<body>
<your first element> like <input type="hidden" id="hidA" />
//rest code goes here
</body>
Now as suggested use $('#hidA').before('the script code') . I am sure it will append the script just after <body>.

Detect whether external script has loaded

Using JavaScript, is there a way to detect whether or not an external script (from a third-party vendor) has completely loaded?
The script in question is used to pull in and embed the markup for a list of jobs and, unfortunately, doesn't make use of any variables or functions. It uses document.write to output all of the content that gets embedded in my page.
Ideally, I'd like to display some kind of loading message while I'm waiting for the external script to load, and if it fails to load, display a "We're sorry, check back later..." message.
I'm using jQuery on the site, but this external script is called before I make the jQuery call.
Here's what the document.write stuff from the external script looks like:
document.write('<div class="jt_job_list">');
document.write("
<div class=\"jt_job jt_row2\">
<div class=\"jt_job_position\">
Position Title
</div>
<div class=\"jt_job_location\">City, State</div>
<div class=\"jt_job_company\">Job Company Name</div>
</div>
");
Attach an function to the load event:
<script type="text/javascript" src="whatever.js" onload ="SomeFunction()" />
As far as your loading... problem goes, try displaying a div for loading and then just display:none-ing it in your onload function. Make sure to handle cases where your script fails to load too, though.
Script tags block downloads, so as long as the content dependent on your script is below where your script it loaded, you should be fine. This is true even if the script is in-line in the body of your page.
This website has a great example of how this works.
This obviously does not work if you're loading the scripts asynchronously.
Scripts without async or defer attributes are fetched and executed immediately, before the browser continues to parse the page.
Source: MDN
You could put a script block after it on the page:
<script src="external_script.js"></script>
<script type="text/javascript">
ExternalScriptHasLoaded();
</script>
Thanks for the assistance above, especially ngmiceli for the Steve Souders link!
I decided to take what's probably a "lazy" approach, and also forego the "loading" message:
$(document).ready(function(){
if ($('.jt_job_list').length === 0){
$('#job-board').html("<p>We're sorry, but the Job Board isn't currently available. Please try again in a few minutes.</p>");
};
});
Pretty simple, but I'm looking to see if an element with the .jt_job_list class is in the dom. If it isn't, I display an error message.
This worked for me: it does however, rely on the newer querySelector interface which most modern browsers support. But if you're using really old browsers, you can use getElement... and run a for loop.
function loadJS(file, callback, error, type) {
var _file = file ;
var loaded = document.querySelector('script[src="'+file+'"]') ;
if (loaded) {
loaded.onload = callback ;
loaded.onreadystatechange = callback;
return
}
var script = document.createElement("script");
script.type = (typeof type ==="string" ? type : "application/javascript") ;
script.src = file;
script.async = false ;
script.defer = false ;
script.onload = callback ;
if (error) {
script.onerror = error ;
}
else {
script.onerror = function(e) {
console.error("Script File '" + _file + "' not found :-(");
};
}
script.onreadystatechange = callback;
document.body.appendChild(script);
}
You could give what ever your looking for an ID
and check whether not the ID has been loaded using document.getElementById("ID");
Is that what your looking for not sure I fully understand?

Use JS variable to set the src attribute for <script> tag

I want to use a javascript variable as a 'src' attribute for another tag on the same jsp.
<script>
var link = mylink // the link is generated based on some code
</script>
I want to create this new element as shown below.
<script src="mylink">
</script>
On searching various forums, I have tried using the following options but they don't seem to work. I want this thing to work on all major browsers.
Put this code in the first element.
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/somelink";
document.body.appendChild(script);
Use document write method in the first element.
document.write("<script type='text/javascript' src="+ google.com + "><\/script>");
Tried to set a JSTL Variable in the first element and use it.
<c:set var="URL" value="mylink"/>
None of these ways were successful. Any suggestions on what is going wrong?
Though CDATA works fine, using document.createElement is also a great choice.. Especially if you intend to append some value to a URL, say for cache busting..
<script type="text/javascript">
var JSLink = "/Folder/sub_folder/version.js?version=" + Math.random();
var JSElement = document.createElement('script');
JSElement.src = JSLink;
JSElement.onload = OnceLoaded;
document.getElementsByTagName('head')[0].appendChild(JSElement);
function OnceLoaded() {
// Once loaded.. load other JS or CSS or call objects of version.js
}
</script>
Code well.. :)
I use something similar to choice two. There is a slight mistake in your code because "google.com" needs to be surrounded by quotes.
To improve compatibility, you might want to write it as:
document.write("<script type='text/javascript' src='"+ x + "'><\/scr" + "ipt>");
In this situation, x would be the file to be included. You can define it as:
var x = "http://google.com/script.js";
OR
var x = "path/to/script.js";
Are you able to use jQuery? If so you could use getScript():
http://api.jquery.com/jQuery.getScript/
$.getScript(mylink, function() {
// do something using the JS that was loaded.
});
Try:
(function(d){
var file = 'yourJS.js';
var ref = d.getElementsByTagName('script')[0];
var js = d.createElement('script');
js.src = file;
ref.parentNode.insertBefore(js, ref);
}(document));
What this does:
Find the first script element on your page
Creates a new script element with your supplied source.
Then inserts that new element before the first existing script element.
<xsl:variable name="Path" select="/root/folder/"></xsl:variable> <!-- Global path variable. -->
<xsl:variable name="myScriptPath" select="concat($Path, 'myScript.js')"></xsl:variable> <!-- Relative script path variable. -->
<script src="{$myScriptPath}"/> <!-- Attach script. -->

Using appendChild with IE in Javascript

I am having trouble with this code in IE (with Chrome it seems to work fine):
<html>
<body>
<script type="text/javascript">
var scriptContent = "var whatever=1";
var _js = document.createElement('script');
_js.setAttribute('type', 'text/javascript');
textNode = document.createTextNode(scriptContent);
_js.appendChild(textNode);
document.getElementsByTagName('body')[0].appendChild(_js);
</script>
</body>
</html>
The error I get in Internet Explorer (IE9) is: "unexpected call to a method or access to a property" on statement "_js.appendChild(textNode)".
Is there any way to work around this problem?
As you can see here appendChild() in IE is not applied to <script>-elements.
(Seems as if IE9 supports it, but it depends on the browser-mode)
There was an correct answer before by Nivas, unfortunately it has been deleted.
In IE use
_js.text = scriptContent;
Your script is being executed before the DOM is ready, so getting the <body> tag is a race condition. I actually get the same error in Chrome 15 and Firefox 8.
You can see the code works when called after the page is loaded, for example in a function
HTML
append
JavaScript
function append() {
var scriptContent = "var whatever=1";
var _js = document.createElement('script');
_js.setAttribute('type', 'text/javascript');
textNode = document.createTextNode(scriptContent);
_js.appendChild(textNode);
document.getElementsByTagName('body')[0].appendChild(_js);
return false;
}

Categories

Resources