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

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.

Related

Set script tag from API call in header of index.html

I'm trying to implement dynatrace in my react app, and this works fine if I just add the required script tag manually in my index.html header.
However I want to make use of dynatraces api which returns the whole script tag element (so I can use for different environments).
How can I add the script tag to my index.html after calling the api? Creating a script element from code won't work because the response of the api call is a script tag itself (which is returned as string).
I tried creating a div element and adding the script as innerHtml, then append it to the document. But scripts don't get executed in innerHtml text.
const wrapperDiv = document.createElement("div");
wrapperDiv.innerHTML = "<script>alert('simple test')</script>";
document.head.appendChild(wrapperDiv.firstElementChild);
Can this be done?
I found a roundabout way of doing this:
const wrapperDiv = document.createElement("div");
const scriptElement = document.createElement("script");
wrapperDiv.innerHTML = "<script src=... type=...></script>";
for(let i = 0; i < wrapperDiv.firstElementChild.attributes.length; i++){
const attr = wrapperDiv.firstElementChild.attributes[i];
scriptElement.setAttribute(attr.name, attr.value);
}
document.head.appendChild(scriptElement);
in this example of the script i'm only using a src but this can be done with the value as well. If there is any better way for doing this pls let me know
This can be achieved without use of eval() :
const source = "alert('simple test')";
const wrapperScript = document.createElement("script");
wrapperScript.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
document.head.appendChild(wrapperScript);
In the code above you basically create Blob, containing your script, in order to create Object URL (representation of File or Blob object in browser memory).
This solution is based on idea that dynamically added <script> is evaluated by browser in case it has src property.
Update:
Since endpoint returns you <script> tag with some useful attributes, the best solution would be to clone attributes (including src) - your current approach is pretty good.
I found a roundabout way of doing this:
const wrapperDiv = document.createElement("div");
const scriptElement = document.createElement("script");
wrapperDiv.innerHTML = "<script src=... type=...></script>";
for(let i = 0; i < wrapperDiv.firstElementChild.attributes.length; i++){
const attr = wrapperDiv.firstElementChild.attributes[i];
scriptElement.setAttribute(attr.name, attr.value);
}
document.head.appendChild(scriptElement);
in this example of the script i'm only using a src but this can be done with the value as well

Need to load Javascript lib's and support files dynamically by another javascript file

My task: If I include a single javascript file (vlib.js) it should automatically include all supporting JS lib in to landing document.
What I did: I have a string array which contains all list of JS file paths to append. I have a function declared in Vlib.js as a global function. It appends all the files correctly, but the problem is I'm getting some errors!
The appending starts with some library files like angular.min,... jquery.min.. bootstrap.. and my custom JS files. Even though I append them in the correct order I'm getting errors like angular not defined and others errors which shouldn't have come if it is loaded in correct order. My team mate says even if put it in correct order it might finish load randomly like angular related files loading before angular.min. So is there any way I can load a script and then move on to appending to other js only when the first one is loaded? I have to do this using native JS.
im using this code
function populateJsDynamicX() {
for (var index = 0; index < jsSet.length; index++) {
source = jsSet[index];
if (jsSet[index].includes('.js')) {
console.log(source);
var scriptTag = document.createElement('script'), // create a script tag
firstScriptTag = document.getElementById('viewerHandle'); // find the first script tag in the document
scriptTag.src = source; // set the source of the script to your script
scriptTag.type = "text/javascript";
//firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag); // append the script to the DOM
document.head.appendChild(scriptTag);
(document, 'script');
} else {
console.log(source);
var scriptTag = document.createElement('link'), // create a script tag
firstScriptTag = document.getElementById('viewerHandle'); // find the first script tag in the document
scriptTag.href = source; // set the source of the script to your script
scriptTag.type = "text/css";
scriptTag.rel = "stylesheet";
//firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag); // append the script to the DOM
document.head.appendChild(scriptTag);
(document, 'script');
}
}
console.log(jsSet.length);
}
Some other guys said $.getScript will get the job done, but I want to do this by native JS, can u guys tell me where I'm wrong?
I get error like this:

How to execute a JS Script stored in a string on Html code stored in a string

I don't even know if what I'm asking is possible or not, I'm fairly new to web development.
Here is what I'd like to achieve:
I need to execute a JS script on a web page. The script returns some keywords related to that page.
I get the JS script from a remote server and I store it in a string.
The only thing I know about the web page is its url, so I get the content of the page with jQuery.
Here is what I tried (I know it looks stupid, but it illustrates what I'm trying to achieve):
// Let's say I want to execute that script on www.google.com's page
$.get("www.google.com", null, function(data) {
let myScript = localStorage.getItem('my_script')
// What I tried so far (it doesn't work, of course)
var temp = document.createElement('div')
temp.innerHTML = data
var resultsOfMyScript = temp.firstChild.eval(myScript) // not a function
})
Do you have any idea on how I could do that?
Try this:
const script = document.createElement('script')
script.type = 'text/javascript'
script.charset = 'utf-8'
script.text = "console.log('this is my script')"
document.body.appendChild(script)
Substitute .text for the string you mentioned.

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.
})();

Reference JS file in JS file

I have a Js function that I would like to:
Reference another js file
Pull a function out.
I would like to do this JS side and not reference on the actual page as I need this process to happen dynamically.
var h = document.getElementsByTagName('head')[0],
s = document.createElement('script');
s.type = 'text/javascript';
s.onload = function () { document.getElementById('hello').innerText = h.innerText; };
s.src = 'http://html5shiv.googlecode.com/svn/trunk/html5.js';
h.appendChild(s);
see: http://jsbin.com/uhoger
If you're working with the browser, jQuery has an helper function for it, $.getScript.
The only option I can think of is to dynamically insert a new script tag into the page targeting your desired script from your initial javascript. Just have your initial script insert the new <script> tag on load, or upon request and then test for availability.

Categories

Resources