I have a toggle switch that when i press it adds a Javascript to the head of the page:
function yourcallback (){
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'dev/additional_script.js';
head.appendChild(script);
}
Now when i use firebug to debug it i can see all of the scripts however if i try to call a function to that script it tells me that the function i am trying to call is undefined.
So it would seem that the script is not loaded correctly.
HOWEVER if i in firebug try and call the same function it returns function()
meaning that it should be defined.
Has anyone experianced anything like this and / or know how i can fix it.
please tell me if you need more code information and il add it to my question
update
Okay so here is the thing i have two scripts:
The script that controls the switch button (when the user press it another script will be loaded)
the script that is loaded when the script button is pressed ( this is where the function is located.
In script one i am trying to call a function in script 2 after it has been loaded and this is where i am getting the error:
The way i am calling the function is just using the function name
The function i am trying to access looks like this:
var init = function() {
var i, anchors, scriptTag;
//get the uid...
scriptTag = document.getElementById("link-replacer");
if(scriptTag) {
uid = scriptTag.getAttribute("data-uid");
} else {
uid = "none";
}
urlpart = forwardUrl+"?uid="+uid+"&url=";
if(doOnLoadReplace) {
anchors = document.getElementsByTagName("a");
for(i = 0; i < anchors.length; ++i) {
fixHref(anchors[i]);
}
}
};
Try this code
var myScript = document.createElement('script');
myScript.setAttribute('type', 'text/javascript');
myScript.setAttribute('src', 'dev/additional_script.js');
var headFirst = document.getElementsByTagName('head');
headFirst[0].appendChild(myScript);
I think you're adding the script incorrectly. Try this:
var newJS = document.createElement('script');
newJS.setAttribute('type','text/javascript');
newJS.setAttribute('src', 'dev/additional_script.js');
Related
I'm making a basic editing system. For this I have an iFrame on the page, and I am wanting to inject javascript into it. I've tried a few different methods and have come to a method which works (injecting inline script), ideally I don't want to do it this way, I want to inject an external script file. The current code I have is:
function addScript(src, myscript2) {
var iFrameHead = window.frames["main_iframe"].document.getElementsByTagName("head")[0];
var myscript = document.createElement('script');
myscript.type = 'text/javascript';
myscript.src = src;
iFrameHead.appendChild(myscript);
iFrameHead.innerHTML = iFrameHead.innerHTML + myscript2;
}
addScript("js/jquery-3.1.1.js", "<scr" + "ipt>function frame_hover(e) {e.preventDefault();console.log('hover enter ', $(e.target));}function frame_drop(e) {e.preventDefault();console.log('drop ', $(e.target));}console.log('iframe loaded and script loaded');</scr" + "ipt>");
This is working, the jQuery file is working, as is the inline script that's injected.
I want it to work like this:
tion injectJS() {
function addScript(src) {
var iFrameHead = window.frames["main_iframe"].document.getElementsByTagName("head")[0];
var myscript = document.createElement('script');
myscript.type = 'text/javascript';
myscript.src = src;
iFrameHead.appendChild(myscript);
}
addScript("js/jquery-3.1.1.js");
addScript("js/frame_script.js");
}
Although when doing it this way, I get the error: Uncaught ReferenceError: frame_hover is not defined at HTMLBodyElement.ondragenter
frame_hover is called from:
$('#main_iframe').contents().find('body')
.attr('ondragenter', 'frame_hover(event)');
the content of frame_script.js is:
function frame_hover(e) {
e.preventDefault();
console.log('hover enter ', $(e.target));
}
function frame_drop(e) {
e.preventDefault();
console.log('drop ', $(e.target));
}
console.log('iframe loaded and script loaded');
What really doesn't make sense to me with this, is that jQuery works injecting it this way, that's loaded exactly the same way as the external file frame_script.js is loaded, why is it not seeing the file?!
I'm trying to reload javascript resources programmatically in Chrome and if I run that from console, then it works fine, but if I put that into the code to reload after an event was fired, then the resource doesn't change. What is the problem?
I use this reloader:
var docHeadObj = document.getElementsByTagName("head")[0];
var dynamicScript = document.createElement("script");
dynamicScript.type = "text/javascript";
dynamicScript.src = 'js/resource.js';
docHeadObj.appendChild(dynamicScript);
And here is the event handler:
obj.onclick(function(){
var docHeadObj = document.getElementsByTagName("head")[0];
var dynamicScript = document.createElement("script");
dynamicScript.type = "text/javascript";
dynamicScript.src = 'js/resource.js';
docHeadObj.appendChild(dynamicScript);
});
After both cases the new and proper <script> element is appended to the <head> and on network tab the resource is downloaded, but in case of the second one the resource is never change.
EDIT:
I'm closer to the problem. If I have this code in the resource which will be reloaded alert("aaa");
And I open the application then after performing a click event I get an alert with 3 'a' letter. Then I decrease the number of the letters to 2, reload the resource, perform a click event, then I again see 3 'a' letter. Then I decrease the number of letters to 1, save and click, then I see 2 'a' letter. So it seems to be the Chrome (and also FF) stores the last modified resource except if I reload that from console.
You should wait before the script is loaded before you use it. It can be achieved with using onload event for the dynamic script
function loadScript(url, callback) {
var docHeadObj = document.getElementsByTagName("head")[0];
var dynamicScript = document.createElement("script");
dynamicScript.type = "text/javascript";
dynamicScript.src = url;
// bind the event to the callback function
dynamicScript.onreadystatechange = callback; //for ie<9
dynamicScript.onload = callback;
// Fire the loading
docHeadObj.appendChild(dynamicScript);
}
var testJQuery = function () {
console.log($(this));
};
var obj = document.getElementById("test");
obj.onclick = function () {
loadScript("//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js", testJQuery);
};
Working example on fiddle
If you just delete the last instance of the script tag before reloading it, that should force it to reload.
function load(link, id) {
var exists = document.getElementById(id)
if(exists){
exists.parentNode.removeChild(exists);
}
var script = document.createElement('script');
script.src = link;
script.id = id;
document.body.appendChild(script);
}
obj.onclick = function(){
load('js/resource.js','dynamicScript')
}
I am trying to load one of my advertisers javascript on a click event but I am getting errors from the javascript when it loads.
var get_ad_popup = function () {
_adUnit= {settings: {siteID: 'T1446', pop: {type: 'popunder'}} };
(function () {
var s = document.createElement("script");
s.type = "text/javascript";
s.async = true;
s.src = "http://cdn.adunit.com/js/gp.min.js";
var e = document.getElementsByTagName('script')[0];
e.parentNode.insertBefore(s, e);
})();
};
Then when I call the function I get this error in the console.
TypeError: _adUnit.pop.clkPop is not a function
If I look in the head I can see that the javascript was properly loaded. I just wondering why I get this error.
Edited:
If I load the javascript outside of the function and just include it in the head then it works just fine.
The script can be seen here: http://jsfiddle.net/QXTkz/
This is provided to me by my advertiser.
Is there a way (event listener or otherwise) to detect when a particular external javascript is about to load / is loading / has finished loading?
In otherwords, does the browser fire an event when it's about to load, is loading, and/or has finished loading a particular external script?
For my purposes it's not enough to simply check to see if a known object exists or anything like that. Instead, I need something that will detect a JS file is loading/loaded regardless of the contents of the JS file.
The following example works in Chrome. It attaches an handler on the onload event of the head tag and then adds an external javascript file. When the file is loaded, the event is captured and an alert appears.
http://jsfiddle.net/francisfortier/uv9Fh/
window.onload = function() {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", "http://code.jquery.com/jquery-1.7.1.min.js");
head.addEventListener("load", function(event) {
if (event.target.nodeName === "SCRIPT")
{
alert("Script loaded: " + event.target.getAttribute("src"));
}
}, true);
head.appendChild(script);
}
Since all browsers blocks the "UI thread" when processing <script> tags, you can rely that pre-existing tags are loaded.
If you are loading a script dynamically, you can listen to the load event of the <script> tag.
function loadScript(src, callback) {
var script = document.createElement("script");
script.setAttribute("src", src);
script.addEventListener("load", callback);
document.getElementsByTagName("script")[0].insertBefore(script);
};
loadScript("http://code.jquery.com/jquery-1.7.1.min.js", function(){
alert("loading is done");
});
<script onload> will fire when a script is finished loading.
You will not be able to do something like:
<script src="/foo.js"></script>
<script src="/bar.js"></script>
<script>
function alertonload(src){
console.log(src+' is loaded');
}
scripts = document.getElementsByTagName('script');
for(var i=0; i<scripts.length; i++){
scripts[i].onload = function(){ alertonload(scripts[i].src); };
}
</script>
This is pure conjecture and speculation; I have not tried it and there's probably better ways to write it, but this will not do what you're looking to do. EDIT: The scripts are loaded as the browser sees them, not after the fact. They will be loaded before this occurs.
I wrote a script for those who wants to call a function after all external files (dynamically added) are loaded. It goes like this:
var file = [];
var loaded = [];
var head = document.getElementsByTagName('head')[0];
var fileOnLoad =
// Pass the arrays to your function
(function(file, loaded){ return function(){
loaded.push(true);
// Print the number of files loaded
document.getElementById("demo").innerHTML +=
"<br>"+loaded.length+" files loaded";
if(file.length == loaded.length){
alert("All files are loaded!");
}
}})(file, loaded);
////////////////////////////////////////////////
//// ////
//// Add the external files dynamically ////
//// ////
////////////////////////////////////////////////
file[0] = document.createElement('script');
file[0].src =
"https://maps.googleapis.com/maps/api/js?v=3.exp";
file[0].onload = fileOnLoad;
head.appendChild(file[0]);
file[1] = document.createElement('script');
file[1].src =
"http://code.jquery.com/jquery-latest.js";
file[1].onload = fileOnLoad;
head.appendChild(file[1]);
file[2] = document.createElement('script');
file[2].src =
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js";
file[2].onload = fileOnLoad;
head.appendChild(file[2]);
file[3] = document.createElement('link');
file[3].rel = "stylesheet";
file[3].href =
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css";
file[3].onload = fileOnLoad;
head.appendChild(file[3]);
file[4] = document.createElement('link');
file[4].rel = "stylesheet";
file[4].href =
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css";
file[4].onload = fileOnLoad;
head.appendChild(file[4]);
<div id="demo">0 file loaded</div>
Hope it helps!
If you can use jQuery, try $.getScript(). Docs here.
I've been having trouble trying to insert jQuery and jQuery UI into webpage headers through a Greasemonkey userscript I'm working on. Here's how I'm inserting it:
var ccst1 = document.createElement("script");
ccst1.id = "ccst1";
ccst1.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js";
ccst1.type = "text/javascript";
document.head.appendChild(ccst1);
var ccst2 = document.createElement("script");
ccst2.id = "ccst2";
ccst2.src = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js";
ccst2.type = "text/javascript";
document.head.appendChild(ccst2);
The actual insertion process works, but when I've inserted it, using jQuery on the page (e.g. in an html onclick) works, but jQuery UI immediately gives me a "$ is not defined" error AND a "jQuery is not defined" error the second it's inserted. No jQuery UI then works on the page.
I believe what you need is simply a small wait before inserting the new code that requires jQuery.
function jQueryReady() {
if (typeof unsafeWindow.$ == 'undefined') {
setTimeout(jQueryReady, 100);
} else {
loadJQueryUI(); //this is your function or code that depends on jQuery
}
}
Is jquery already defined in the page you are trying to include it into.
Have you tried
$.noConflict()
Is it inside a naked function
(function(){ alert($("#hello")); })();
I have two methods to using jQ with my userscripts. The first is to add jQ to the userscript.
function addJQuery(callback) {
var script = document.createElement("script");
script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
script.addEventListener('load', function() {
var script = document.createElement("script");
script.textContent = "(" + callback.toString() + ")();";
document.body.appendChild(script);
}, false);
document.body.appendChild(script);
}
// the guts of this userscript
function main() {
$(document).ready( function() {
// YOUR GM CODE GOES HERE
});
}
// load jQuery and execute the main function
addJQuery(main);
This works, however events can get tricky. What I like to do, if the page already is using jQ (check source) is actually create 2 files. One user.js (the GM script) that injects a into the head. This second file needs to be hosted somewhere (i use dropbox) but this is where all your bacon is located. You can write your jQ as if you are writing the code for the page and not a GM script.
eg
GM.user.js
// ==UserScript==
// #name Name (jQuery)
// #description description
// #namespace my twitter page
// #author me
// #include http://
// ==/UserScript==
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'http://dl.dropbox.com/u/example.js';
head.appendChild(script);
example.js
$(document).ready( function() {
// MY Awesome code here.
});
Whichever method you pick, good luck and have fun.
I've just found a solution to this. It actually did have to do with jQuery not being loaded properly, but none of the other solutions worked for me. Joey Geralnik suggested this, which is working properly:
var ccst1 = document.createElement("script");
ccst1.id = "ccst1";
ccst1.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js";
ccst1.type = "text/javascript";
document.body.appendChild(ccst1);
function ccst2func() {
var ccst2 = document.createElement("script");
ccst2.id = "ccst2";
ccst2.src = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js";
ccst2.type = "text/javascript";
document.body.appendChild(ccst2);
ccst2.addEventListener("load", ccst4func, true);
}
ccst1.addEventListener("load", ccst2func, true);
document.body.insertBefore(concealerPanel, document.body.firstChild);
function ccst4func() {
var ccst4 = document.createElement("script");
ccst4.id = "ccst4";
ccst4.type = "text/javascript";
ccst4.innerHTML = "$('#ccpanelmassiveconstruct').draggable({'handle': '#ccpmchandle', 'constrain': 'parent', 'distance': 20, 'cursor': 'move', 'grid': [10,10], 'scroll': true});\n$('#iframeDragger').resizable();\n$('#ccpmctabs').tabs();";
document.body.appendChild(ccst4);
}