I'm creating a new window using the following:
var windowX = window.open('page.html', 'newWindow', 'width=600,height=600');
The new window is just a blank html page that contains javascript which constructs a new object, I then use that object with some more javascript that I inject after the page has loaded.
My solution works in chrome and firefox but does not appear to work in IE11. The alert does not show, nor does the following code.
windowX.onload = function() {
//I've added the alert just to see if the onload is firing...
windowX.alert('hello!');
var script = document.createElement('script');
script.type = 'text/javascript';
script.language = 'JavaScript';
script.src = '/scripts/newScript.js';
windowX.document.head.appendChild(script);
};
I've attempted to use jQuery $(windowX).ready(...) & $(windowX).load(...) which still works in chrome but with no success in IE11.
I figured out the problem is that IE11 runs window.open() as a synchronous task, preventing any further javascript from running until the window has opened and loaded, so the onload event that is declared afterwards is never fired because the new window has already 'loaded'.
To get around this I check if the users browser is IE11 and fire the load event using jquery:
if (!!window.MSInputMethodContext && !!document.documentMode) {
$(windowX).trigger('load');
}
It is ok - you cannot work with properties of unfinished object ("Unable to set property 'onload' of undefined or null reference"), but this code works in IE11 (do not need to load empty page):
var windowX = window.open('');
windowX.alert('hello!');
var script = windowX.document.createElement('script');
script.type = 'text/javascript';
script.language = 'JavaScript';
script.src = '/scripts/newScript.js';
windowX.document.head.appendChild(script);
But you are right those 2 browsers have them visible during loading (for example window.name does not exist in IE, but exist in these 2).
Related
Dynamically appended script never loads:
const nodeTemplate = document.importNode(template.content, true)
const script = nodeTemplate.firstElementChild
script.removeAttribute('async')
script.setAttribute('defer', 'defer')
document.body.appendChild(nodeTemplate)
Any idea why? Is there a way to force it to load?
I've looked around at diverse solutions here and elsewhere and none seem to work as of now.
It works fine if it happens at page load.
I think you need to check whether it's loaded or not, if not, better to remove completely that script from the DOM, and then create new script tag.
And then try something like this, it's common pattern to inject script widgets:
// 1. remove your old script
// 2. create new
(function(){
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = false;
s.defer = true;
s.src = "https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js";
document.getElementsByTagName('head')[0].appendChild(s);
})();
With IE7 and IE8, I discovered one could avoid memory leaks in a "single page app" that was doing frequent JSONP calls by adding a script element to the head and simply changing the src attribute. Each time the src attribute was changed, it would immediately load and run the script. This is no longer working in IE9 or IE10. Using JQuery's .ajax() or manually where the previous script node is removed from the head, and a new one added (which works fine in FF and Chrome) causes memory to leak in IE.
Here is the basic code I use to submit the JSONP - Jquery and other libraries seem to leak memory, I'm wondering if I can avoid it at all with ie9 and ie10...
// Some statics used by JSONP calls (below)... uuid is used to prevent getting stale cached results, it forces a new "get" every time by changing the url
Testing123.uuid = 0;
Testing123.head = document.getElementsByTagName('head')[0];
//-----------------------------------------------------
// mainurl is the url we are going to, callbackFuncName is the callback function, parameters must be a string with zero or more parameters already encoded
// formatted as "&parm1=value1&parm2=value2" as it is being tacked onto a GET url...
Testing123.debugJSONP = false; // set to true to see stuff in console
Testing123.initiateJSONP = function (mainurl, callbackFuncName, parameters) {
var url = mainurl + "?callback=" + callbackFuncName + "&uuid=" + (Testing123.uuid++);
var script;
url += parameters; // add optional parameters.
// Now, let's make the JSONP call happen. One way for IE 8 and below, another way for FF, Chrome, etc.
if (Testing123.isIE) {
// ***** NOTE *****
// This tests for ALL ie versions, but ie9 and ie10 will only display one interation...
// If you add && Testing123.browserVersionNumber < 9.0 to the if above, then the iterations will work, but
// memory usage will go up dramatically if run for a while...
// ***** NOTE ******
// For IE, we create the script node just once, and then set its src attribute to run again...
// ***** This seems now to fail in ie9 and ie10
var addToDOM = 0;
script = document.getElementById('JSONP');
if (!script) {
if (Testing123.debugJSONP) Testing123.logToOutput("initiateJSONP with IE: creating script element with id JSONP");
script = document.createElement('script');
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
addToDOM = 1;
}
if (Testing123.debugJSONP) Testing123.logToOutput("initiateJSONP with IE: setting script element's src to " + url);
script.setAttribute("src", url);
//script.src = url;
if (addToDOM) // Only do this the first time we create it...
{
if (Testing123.debugJSONP) Testing123.logToOutput("initiateJSONP with IE: appending script element with id JSONP to head");
Testing123.head.appendChild(script);
}
} else {
//First lets clean up the DOM from the last call, if there was one...
var tmp;
while (tmp = document.getElementById('JSONP')) {
if (Testing123.debugJSONP) Testing123.logToOutput("initiateJSONP non IE: found a JSONP element by id... asking parent to remove it and deleting its properties.");
tmp.parentNode.removeChild(tmp);
// not working in IE 7/8/9
for (var prop in tmp) {
//if (Testing123.debugJSONP) Testing123.logToOutput("initiateJSONP non IE: deleting prop: [" + prop + "] from the element found.");
delete tmp[prop];
}
tmp = null;
}
Does anyone have a solution to this issue? Here is a jsfiddle with a little test application and all the code:
http://jsfiddle.net/bbct/9RqZ6/
Thanks in advance for any advice / insight.
I am trying to include a form from one page on one domain to another page on another domain. Here is my code which I put after my block form.
function IncludeSrc(src) {
var s= document.createElement("script");
s.src = src;
s.async = true;
document.getElementsByTagName("head")[0].appendChild(s);
}
var onLoadFunc = window.onload;
window.onload=function(){
if (typeof(onLoadFunc)=='function') onLoadFunc();
IncludeSrc('MYADRESS');
};
There is no error in any browser but the form does not load. In Firefox console I found the error too much recursion. The address of the script is valid, I checked it. What am I doing wrong?
That's because you're calling onLoadFunc within itself. Regardless of why you'd want to do this, there's no base case for the recursion, so it never bottoms out...
I want to use Ctrl+Enter to submit the Google+ reply but it does not work when I send a 'Click' event to the submit button. This is a chrome plugin for plus.google.com.
document.onkeydown=function(e){
if(e.ctrlKey&&e.keyCode==13){
div_id=document.activeElement.id;
div_id=div_id.substr(0,3);
editorid=div_id.substr(0,2)+String.fromCharCode(div_id.charCodeAt(2)-1);
postbuttonid=editorid+'.post';
console.log(postbuttonid);
postbutton=document.getElementById(postbuttonid);
evt=document.createEvent("MouseEvents");
evt.initEvent("click", true, true);
postbutton.dispatchEvent(evt);
}
}
I suggest you use jQuery:
jQuery("#:2s.post").click();
The above code should work assuming that, as one of your comments describes, the button you want to click has the id ":2s.post".
I hope that works for you. If you're unable to include jQuery directly, you could try something like:
/*--- Create a proper unsafeWindow object on browsers where it doesn't exist
(Chrome, mainly).
Chrome now defines unsafeWindow, but does not give it the same access to
a page's javascript that a properly unsafe, unsafeWindow has.
This code remedies that.
*/
if (typeof unsafeWindow === "undefined") {
unsafeWindow = ( function () {
var dummyElem = document.createElement('p');
dummyElem.setAttribute ('onclick', 'return window;');
return dummyElem.onclick ();
} ) ();
if(typeof unsafeWindow === "undefined") {
unsafeWindow = window;
}
}
// END PROPER unsafeWindow
var script = unsafeWindow.document.createElement("SCRIPT");
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js';
script.type = 'text/javascript';
unsafeWindow.document.getElementsByTagName("head")[0].appendChild(script);
script.addEventListener('load', function(){
jQ = unsafeWindow['jQuery'];
$ = jQ.noConflict(true); // keep jQuery local so you don't accidentally override/overwrite any variables
requiresjQuery($);
}, false);
In which case, your code would actually look more like:
function requiresjQuery($) { // put any code in here that requires jQuery; I actually recommend putting all of your code in here.
$("#:2s.post").click();
}
try document.forms.yourForm.submit();
I need to dynamically load several JavaScript file assets in a very specific order after a page has loaded. I'm trying to use onload, but this seems to fire before the asset has fully loaded. How should I adjust the below script to fire a proper callback to load the next script?
Note: Only needs to work in the latest Chrome, Firefox, Safari, and IE9.
function loadAssets() {
// Setup script
var scriptJS = document.createElement('script');
scriptJS.type = 'text/javascript';
scriptJS.src = objectUrl;
scriptJS.onload = loadAssetsNext();
// Begin insertion
var headerJS = document.getElementsByTagName('HEAD');
headerJS[0].appendChild(scriptJS);
},
function loadAssetsNext() {
// Increment object counter
objectsCount++;
// Test to see if you should call another item
if ((objectsCount) < objects.length) {
// Setup script
var scriptJS = document.createElement('script');
scriptJS.type = 'text/javascript';
scriptJS.src = nextObjectUrl;
// Declare callback to fire after script has fully loaded
scriptJS.onload = loadAssetsNext();
// Begin insertion
var headerJS = document.getElementsByTagName('HEAD');
headerJS[0].appendChild(scriptJS);
}
}
What I need is something like scriptJS.fullyLoaded = doStuff. Have no clue where to go from here though.
PS: jQuery is not an option or another library. You should be able to do this by slightly modifying the above script.
The reason your onload event is firing immediately is that you are calling it, not assigning it.
scriptJS.onload = loadAssetsNext();
This just assigns the returned value from the call to loadAssetsNext to the property onload of the scriptJS object. What you are intending to do is:
scriptJS.onload = loadAssetsNext;
That sets the onload handler to be the loadAssests function. This should take care of your issues.
I think the problem is that your scriptJS.onload = loadAssetsNext(); is placed before headerJS[0].appendChild(scriptJS);
That means that your scripts would load and get appended to the page like this:
load script 1
load script 2
load script 3
...
append script 3
append script 2
append script 1
So I think you should just reorder your script a little bit.