Running Javascript in new window.open - javascript

I'm running this function to open a new window.
function htmlNewWindow(id) {
var html = $(id).html();
var newWindow = window.open('');
newWindow.document.body.innerHTML = '<html><head><title>Hi</title> <script src="js/myScript.js"></script> </head>' + html;
}
This successfully creates a new window with the HTML in it. I have a bunch of HTML tags which when clicked run a function called Foo1. I've tried printing the entire function of Foo1 to the new HTML document, and tried putting Foo1 inside myScript.js. I see both Foo1 inside a script tag in the new window, and but neither are loaded since they are just written to the new page as HTML.

Scripts added with .innerHTML aren't executed. You need to create a script node and append it to the window's DOM.
$("#button").click(newWindow);
function newWindow(id) {
var html = $(id).html();
var win = window.open('');
win.document.head.innerHTML = '<title>Hi</title></head>';
win.document.body.innerHTML = '<body>' + html + '</body>';
var script = document.createElement('script');
script.src = 'js/myScript.js';
win.document.head.appendChild(script);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Click me</button>
This doesn't run in Stack Snippet's sandbox, here's a working jsfiddle.

Try this:
var newWindow = window.open('');
newWindow.document.createElement('script');
script.src = 'js/myScript.js';
newWindow.document.head.appendChild(script);

Just in case someone has this to be done in a link. Do the following:
Link
This opens a new window with that URL, it set the focus to that windows, and as soon as the 'load' event is triggered, it executes the code in the function. It only works with a page in the same domain.
Hope this helps ⬆✌.
Cheers 👍

Here's how you create, and then append a script file within a new window:
var fileref = document.createElement('script');
//creates script in current document
fileref.setAttribute("type", "text/javascript")
//set it to JS by "type"
fileref.setAttribute("src", filename)
//set your "src=yourFile_href_Here.js"
//Then create your newWindow as you did above, but slightly updated
//Create your function which will consume the "fileref" argument
function htmlNewWindow(fileref) {
var newWindow = window.open('');
newWindow.document.getElementsByTagName("head")[0].appendChild(fileref);
}; //right now the function is made but you still have to execute it
//Execute your function, and pass it the variable "fileref" that you set above.
htmlNewWindow(fileref);
//Within this edit you will append the head element
//with your newly created script(or any other parameterized argument)
/* Replace your filename to pass any other script */
NOTE - Opening a page residing on a different domain, if not specifically allowed, will reject instances of this due to CORS(https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
It's not a safe practice to be sending your scripts into other people's pages or allowing them in your own if your domain hasn't sent them. Also, depending on your server/technology stack you may need to configure your *-origin settings within your backend stack. See here: (https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)

Related

How to close window without triggering 'window.onunload'?

I have an external program that opens an .hta file which contains some JavaScript:
function getLUTKey(key) {
// Write txt file to user's file system
var fso, fh;
fso = new ActiveXObject("Scripting.FileSystemObject");
fh = fso.CreateTextFile("PartID.txt", true);
fh.Write(key);
fh.close();
self.close();
}
The idea is that the window contains a number of links for different parts which, when clicked, will write their respective "Part ID" to a file using the above js function. The previously-mentioned external program then waits in the background for this file to be created, then uses the file's contents.
However, in order to prevent the user from exiting without selecting a part -
therefore never creating a file and leaving the external program to loop until a timeout triggers - I've added the following code:
window.onunload = function(){ getLUTKey('cancel') };
This creates another problem. When getLUTKey() is run with a valid ID, and it closes the window, the window.unload the code runs immediately after, overwriting whatever the ID in the file was with "cancel". My question is this:
Is there a way to close a window in javascript without triggering window.unload?
I guess it's way easier for you to manage the state of your app. For example you can simply remove the handler of window closing after you're done with the function.
function getLUTKey(key){
// Write txt file to user's file system
var fso, fh;
fso = new ActiveXObject('Scripting.FileSystemObject');
fh = fso.CreateTextFile('PartID.txt', true);
fh.Write(key);
fh.close();
window.onunload = null;
self.close();
}

Set Script Source from the same file instead of a different one?

I create an iframe in a file and insert a <script> tag as its content. The Script src is loaded from a different file called test.js. Here is how it is done:
var scriptElement = document.querySelector("#your-widget");
var iframe = document.createElement("iframe");
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
var script = document.createElement("script");
iframe.contentWindow.document.appendChild(script);
script.src = "http://www.example.com/test.js";
Instead of loading the content of the script from http://www.example.com/test.js I want to take it from the same file where the above code is. This would like this:
var scriptElement = document.querySelector("#your-widget");
var iframe = document.createElement("iframe");
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
var script = document.createElement("script");
iframe.contentWindow.document.appendChild(script);
script.src = // ????
// the following JavaScript code should be placed inside the script
function mywidget() {
// some code
return true;
}
mywidget.succeeded = mywidget();
How can I set the Script Source from the same file instead of a different one?
If you literally just want to place that exact snippet in a script tag, you can just do so using .innerText.
script.innerText = 'function mywidget() { ...';
Then it will execute as is when it's inserted into the DOM. If you want to dynamically find and inject that code, read on.
There are exactly two ways to load a script on a page.
Add a <script> with the src attribute pointing to a file.
Create a <script> tag then set the contents to whatever you want to execute.
var script = document.createElement('script');
script.innerText = 'console.log("Hello, World!")';
document.body.appendChild(script);
If you want to extract part of a script and use those contents then the best you can do is load the contents via ajax and inject it using method 2.
Assuming you have jQuery (for easy AJAX work):
$.ajax({
url: 'path/to/script.js',
dataType: 'text', // make sure it doesn't get eval'd
success: function(contentsOfScript) {
// Refer to method 2
}
});
Now you can go about extracting the contents of that snippet in one of two ways:
Know exactly which line it begins on.
var lines = contentsOfScript.split('\n');
var snippet = lines.slice(lineNumber + 1); // adjust for 0 indexing
Generate a regular expression to identify where your code begins. This is rather tricky and very error prone if your snippet isn't easily distinguished from other code.
var snippet = contentsOfScript.match(/function mywidget.+/)[0];
Neither of these methods will work if you perform any minification on your code.

Passing a variable before injecting a content script

I am working on a Chrome Extension that works mainly within a pop-up.
I would like the user to enter some text (a string) into an input field in the pop-up, and this string will serve as a "variable" in a script I would like to inject and run on a specific page.
I have tried achieving this by making a content script that will execute the script, using the following well documented way:
var s = document.createElement('script');
s.src = chrome.runtime.getURL('pageSearch.js');
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
Basically, I would like to pass the user's input all the way to the code in pageScript.js before executing the script on the page.
What would be the best way to approach this? I will not be getting any information back to the extension.
Thanks.
To pass a variable from the popup to the dynamically inserted content script, see Pass a parameter to a content script injected using chrome.tabs.executeScript().
After getting a variable in the content script, there are plenty of ways to get the variable to the script in the page.
E.g. by setting attributes on the script tag, and accessing this <script> tag using document.currentScript. Note: document.currentScript only refers to the script tag right after inserting the tag in the document. If you want to refer to the original script tag later (e.g. within a timer or an event handler), you have to save a reference to the script tag in a local variable.
Content script:
var s = document.createElement('script');
s.dataset.variable = 'some string variable';
s.dataset.not_a_string = JSON.stringify({some: 'object'});
s.src = chrome.runtime.getURL('pageSearch.js');
s.onload = function() {
this.remove();
};
(document.head||document.documentElement).appendChild(s);
pageSearch.js:
(function() {
var variable = document.currentScript.dataset.variable;
var not_a_string = JSON.parse(document.currentScript.dataset.not_a_string);
// TODO: Use variable or not_a_string.
})();

Javascript update function via change src script file

My javascript file with function:
scr.js:
function myf(){
alert('aaa');
}
myf();
After load page, I see dialog box with 'aaa'. This is right.
The next, I change script source to:
function myf(){
alert('bbb'); ///////////
}
myf();
and src file by add to him timestamp (for update file):
$('script[src^="./scr.js"]').attr('src','./scr.js?='+new Date().getTime());
The problems:
after update file, the myf() function doesn't run.
after run myf() function from browser console I see dialog with 'aaa' not with 'bbb'
when I remove script tag with src scr.js, I can call again my function
Where is problem and what do for update scritpt?
As far as I know, changing a script src attribute, doesn't force the browser to download the script; you need to create a new script tag and append it to the DOM.
Because the browser didn't downloaded and executed the new script.
When your script was first run by the browser it created a global function, which has been attached to the global object; that's why you can still call it, even though you've dinamically removed the script.
UPDATE (Possible solution):
Create a script element dinamically using something like this:
function createScript(src) {
var s = document.createElement("script");
s.src = src;
return s;
}
Update the DOM:
var oldScript = document.querySelector("script[src^='s.js']");
var newScript = createScript("s.js?t=" + (new Date()).getTime());
document.body.replaceChild(newScript, oldScript);
(you can translate that into jQuery if you want)

Add content to a new open window

I don't know how to solve this issue, I've trying reading many post but no one answer to it.
I need to open a new window with a page already coded (inside the same domain) and add some content.
The problem is that if I use OpenWindow.write() the page is not loaded yet or it overrides everything and only the code added through write appears.
var OpenWindow = window.open('mypage.html','_blank','width=335,height=330,resizable=1');
OpenWindow.document.write(output);
output is the code I need to append.
I need it to work at least on Firefox, IE and GC.
It is not a problem if I need to use JQuery.
When You want to open new tab/window (depends on Your browser configuration defaults):
output = 'Hello, World!';
window.open().document.write(output);
When output is an Object and You want get JSON, for example (also can generate any type of document, even image encoded in Base64)
output = ({a:1,b:'2'});
window.open('data:application/json;' + (window.btoa?'base64,'+btoa(JSON.stringify(output)):JSON.stringify(output)));
Update
Google Chrome (60.0.3112.90) block this code:
Not allowed to navigate top frame to data URL: data:application/json;base64,eyJhIjoxLCJiIjoiMiJ9
When You want to append some data to existing page
output = '<h1>Hello, World!</h1>';
window.open('output.html').document.body.innerHTML += output;
output = 'Hello, World!';
window.open('about:blank').document.body.innerText += output;
in parent.html:
<script type="text/javascript">
$(document).ready(function () {
var output = "data";
var OpenWindow = window.open("child.html", "mywin", '');
OpenWindow.dataFromParent = output; // dataFromParent is a variable in child.html
OpenWindow.init();
});
</script>
in child.html:
<script type="text/javascript">
var dataFromParent;
function init() {
document.write(dataFromParent);
}
</script>
Here is what you can try
Write a function say init() inside mypage.html that do the html thing ( append or what ever)
instead of OpenWindow.document.write(output); call OpenWindow.init() when the dom is ready
So the parent window will have
OpenWindow.onload = function(){
OpenWindow.init('test');
}
and in the child
function init(txt){
$('#test').text(txt);
}
When you call document.write after a page has loaded it will eliminate all content and replace it with the parameter you provide. Instead use DOM methods to add content, for example:
var OpenWindow = window.open('mypage.html','_blank','width=335,height=330,resizable=1');
var text = document.createTextNode('hi');
OpenWindow.document.body.appendChild(text);
If you want to use jQuery you get some better APIs to deal with. For example:
var OpenWindow = window.open('mypage.html','_blank','width=335,height=330,resizable=1');
$(OpenWindow.document.body).append('<p>hi</p>');
If you need the code to run after the new window's DOM is ready try:
var OpenWindow = window.open('mypage.html','_blank','width=335,height=330,resizable=1');
$(OpenWindow.document.body).ready(function() {
$(OpenWindow.document.body).append('<p>hi</p>');
});
If you want to open a page or window with sending data POST or GET method you can use a code like this:
$.ajax({
type: "get", // or post method, your choice
url: yourFileForInclude.php, // any url in same origin
data: data, // data if you need send some data to page
success: function(msg){
console.log(msg); // for checking
window.open('about:blank').document.body.innerHTML = msg;
}
});
it is even more simple!
Just put the code below in between the <head> </head> of your code and all of your links will open in a new window:
<base target="_blank">

Categories

Resources