head.appendChild giving error in console but working fine - javascript

I am trying to inject a script on page load in head wherein I have to give the page name inside script.
Below is how I am implementing it in my ts file.
**var head = document.getElementsByTagName('head')[0];
var tag = document.createElement("script");
tag.type = 'text/javascript';
tag.innerHTML = "var DDO = {} DDO.pageData = {'pageName': " + pageUrl + "} ";
head.appendChild(tag);**
The script is getting injected however an error is being thrown in the console tab.
ERROR: VM3741:1 Uncaught SyntaxError: Unexpected identifier at appendChild

Try this
var head = document.getElementsByTagName('head')[0],pageUrl="somevalue";
var tag = document.createElement("script");
tag.type = 'text/javascript';
tag.textContent = "var DDO = {}; DDO.pageData = {'pageName': '" + pageUrl + "'} ";
head.appendChild(tag);
To remove previous script element
var script = head.childNodes[0]; //get previous script element
head.removeChild(script); //removing script
you have not provided single quotes for the value of the key pageName

tag.innerHTML = "var DDO = {}; DDO.pageData = {'pageName': " + pageUrl + "} ";
semicolon missing after defining the variable DDO,
and also from where are you injecting in pageUrl, make sure variable is defined.
try having script in external file and injecting in script tag with refrence to that file in case some error in script defined in inner html
document.head, document.body to attach scripts

Correct Answer:
var head = document.getElementsByTagName('head')[0];
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.id = 'adobedatalayer';
tag.textContent = 'var DDO = {}; DDO.pageData =' + JSON.stringify(pageinfo);
var script = document.getElementById('adobedatalayer');
if (script != null) {
head.removeChild(script);
}
head.appendChild(tag);

Related

How to get my desired cryptocurrencies working in this JavaScript widget?

I have a problem when trying to use a widget.
The script is as follows:
<script type="text/javascript">
baseUrl = "https://widgets.cryptocompare.com/";
var scripts = document.getElementsByTagName("script");
var embedder = scripts[ scripts.length - 1 ];
(function (){
var appName = encodeURIComponent(window.location.hostname);
if(appName==""){appName="local";}
var s = document.createElement("script");
s.type = "text/javascript";
s.async = true;
var theUrl = baseUrl+'serve/v3/coin/chart?fsym=TPAY*&tsyms=USD';
s.src = theUrl + ( theUrl.indexOf("?") >= 0 ? "&" : "?") + "app=" + appName;
embedder.parentNode.appendChild(s);
})();
</script>
When I access https://widgets.cryptocompare.com/serve/v3/coin/chart?fsym=TPAY*&tsyms=USD from my browser it displays all the data but when using the widget script it does not seem to like the fsym=TPAY&tsym=USD but because cryptocompare lists some currencies that have the same ticker they add a * to the second currency which uses the same ticker name.
Another example of this is PHORE PHR* as they have PHREAK PHR already listed. Funny enough the currencies I would like to use it TPAY* and PHR*.

How to sequentially insert scripts into the page context using <script> tags

I am having troubles loading all the scripts that I am inserting into the page context with <script> tags from a content_script script, because they are required to be executed in the correct loading order, as some depend on others. In an actual HTML file I guess there is a queue to load the files, but with inserting <script> tags it seems like if one script delays a little time, the next one starts loading and then is immediately executed notwithstanding it had to wait for its dependency library that is still loading.
Below is the network output with the error caused because of x-tag-core.min.js is loaded before primeui-all.min.js and eventPage.js which uses jquery-ui.min.js, is loaded before it:
// manifest.js
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/jquery-3.1.1.min.js",
"js/main.js"
]
}
]
// main.js
var s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-3.1.1.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-ui.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeui-all.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/x-tag-core.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeelements.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/eventPage.js');
$(document.head).append(s);
Duplicating your problem in a snippet
The following snippet duplicates your problem by sequentially inserting <script> elements. I am using network resources, because there is no method of storing such scripts on Stack Overflow. Given that you only supplied version information for jQuery, I have had to guess at appropriate versions for the other libraries which you are using.
In order to stay close to the code which you are using in your Chrome extension, chrome.extension.getURL() is faked. In these snippets, that function returns a functional network URL for the libraries which you are using. Obviously, in your Chrome extension, you will want to continue to use the library files which you ave included with your extension.
In addition, the code for eventPage.js is faked by having some code that reports if jQuery exists, if $(document).puidialog is a function, and/or if xtag is defined. The errors you are seeing are that $([something]).puidialog was not a function and xtag was not defined. This fakeEventPageJS code accurately shows if the scripts have been properly loaded.
In this duplication of your problem, an error is also produced from the various libraries as the subsequent libraries can not find prior libraries.
var s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-3.1.1.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-ui.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeui-all.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/x-tag-core.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeelements.min.js');
document.head.appendChild(s);
s = document.createElement('script');
//s.src = chrome.extension.getURL('js/eventPage.js');
//Fake js/eventPage.js with an actual script.
s.textContent = fakeEventPageJS;
document.head.appendChild(s);
<!-- The JavaScript code included in this HTML section is used to fake the chrome API
and part of faking the existence of a js/eventPage.js file by inserting code. -->
<!-- Using HTML <script> tags to test that loading it via these works prior to testing
using JavaScript inserts. If you want to verify that the code works when the
scripts are included in the original HTML, you can uncomment the <script>
tags here. -->
<!-- jquery-3.1.1.min.js -->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script><!-- -->
<!-- jquery-ui.min.js -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script><!-- -->
<!-- primeui-all.min.js -->
<link rel="stylesheet" href="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.css">
<!-- <script src="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js"></script><!-- -->
<!-- x-tag-core.min.js -->
<!-- <script src="https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js"></script>
<!-- primeelements.min.js -->
<!-- <script src="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js"></script> <!-- -->
<script>
//Fake chrome.extension.getURL
var netScriptLoations = {
'js/jquery-3.1.1.min.js':'https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js',
'js/jquery-ui.min.js':'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js',
'js/primeui-all.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js',
'js/x-tag-core.min.js':'https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js',
'js/primeelements.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js'
}
if(typeof chrome !== 'object'){
var chrome = {};
}
if(typeof chrome.extension !== 'object'){
chrome.extension = {};
}
if(typeof chrome.extension.getURL !== 'function'){
chrome.extension.getURL = function(script){
//console.log(netScriptLoations[script]);
return netScriptLoations[script];
};
}
var fakeEventPageJS =
'var testResult = "Scripts did NOT load correctly. "'
+ ' + "$(document).puidialog is NOT a function.";'
+ 'var passedChecks=0;'
+ 'if(typeof $ === "function"){'
+ ' var puidialogNot = " NOT";'
+ ' if(typeof $(document).puidialog === "function") {'
+ ' puidialogNot = "";'
+ ' }'
+ ' console.log("$(document).puidialog is" + puidialogNot + " a function");'
+ '} else {'
+ ' console.log("No jQuery");'
+ '}'
+ 'var xtagNot = " NOT";'
+ 'if(typeof xtag !== "undefined") {'
+ ' xtagNot = "";'
+ '}'
+ 'console.log("xtag is" + xtagNot + " defined.");'
+ 'if(puidialogNot + xtagNot === "") {'
+ ' testResult = "Scripts loaded CORRECTLY. "'
+ '}'
+ 'console.log(testResult);';
</script>
Insert each <script> in the onload event handler of the prior script
It is clear that the inserted <script> elements are executed asynchronously. In order to force them to be executed synchronously, we need to insert the next script after the prior one has completed execution. This can be done by utilizing the load event for each script.
The following code loads each subsequent script in the load event handler of the prior script.
The function createScriptElement creates an individual <script> element. This function can be somewhat simplified in your code due to not needing to fake the eventPage.js script.
The function createScriptSequence creates a sequence of <script> elements which each inserts the next script in its onload listener. This uses script.addEventListerner('load',...) in order to be immune to the script being loaded changing the script.onload property/attribute.
var scriptsToInsert = [
'js/jquery-3.1.1.min.js',
'js/jquery-ui.min.js',
'js/primeui-all.min.js',
'js/x-tag-core.min.js',
'js/primeelements.min.js',
'js/eventPage.js'
]
function createScriptElement(script){
let scriptEl = document.createElement('script');
let scriptElSource = chrome.extension.getURL(script);
if(scriptElSource){
scriptEl.src = scriptElSource;
} else {
//Only need this `else` because we are faking having js/eventPage.js by using
// some code to indicate if $(document).puidialog is a function.
scriptEl.textContent = fakeEventPageJS;
}
return scriptEl;
}
function createScriptSequence(scriptArray){
var scriptEls = [];
//Create all the script elements
scriptArray.forEach((script,index)=>{
//console.log(script);
scriptEls.push(createScriptElement(script));
if(index>0){
//Add an onload listener for each script (except the last) which loads
// the next one in the sequence.
scriptEls[index - 1].addEventListener('load',function oneTime(){
//Probably don't need to remove this, but better to clean things up.
scriptEls[index - 1].removeEventListener('load',oneTime,false);
document.head.appendChild(scriptEls[index]);
},false);
}
});
//Return the first script in the sequence
return scriptEls[0];
}
document.head.appendChild(createScriptSequence(scriptsToInsert));
<!-- The JavaScript code included in this HTML section is used to fake the chrome API
and part of faking the existence of a js/eventPage.js file by inserting code. -->
<!-- jquery-ui.min.js -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<!-- primeui-all.min.js -->
<link rel="stylesheet" href="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.css">
<script>
//Fake chrome.extension.getURL
var netScriptLoations = {
'js/jquery-3.1.1.min.js':'https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js',
'js/jquery-ui.min.js':'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js',
'js/primeui-all.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js',
'js/x-tag-core.min.js':'https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js',
'js/primeelements.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js'
}
if(typeof chrome !== 'object'){
var chrome = {};
}
if(typeof chrome.extension !== 'object'){
chrome.extension = {};
}
if(typeof chrome.extension.getURL !== 'function'){
chrome.extension.getURL = function(script){
//console.log(netScriptLoations[script]);
return netScriptLoations[script];
};
}
var fakeEventPageJS =
'var testResult = "Scripts did NOT load correctly. "'
+ ' + "$(document).puidialog is NOT a function.";'
+ 'var passedChecks=0;'
+ 'if(typeof $ === "function"){'
+ ' var puidialogNot = " NOT";'
+ ' if(typeof $(document).puidialog === "function") {'
+ ' puidialogNot = "";'
+ ' }'
+ ' console.log("$(document).puidialog is" + puidialogNot + " a function");'
+ '} else {'
+ ' console.log("No jQuery");'
+ '}'
+ 'var xtagNot = " NOT";'
+ 'if(typeof xtag !== "undefined") {'
+ ' xtagNot = "";'
+ '}'
+ 'console.log("xtag is" + xtagNot + " defined.");'
+ 'if(puidialogNot + xtagNot === "") {'
+ ' testResult = "Scripts loaded CORRECTLY. "'
+ '}'
+ 'console.log(testResult);';
</script>

Different UI script to execute depending on URL

I have my UI's split up in 2 javascript files. If the URL is of certain patter lets say /test1 then I want script1 to execute or in other words, I want script1 to be added as <include> so the UI renders according to script1 else I want script2 to be added for /test2.
There is no button that triggers these URLs. Its when the page loads -detect URL and load script accordingly.
How can I achieve this?
you can dynamically insert javascript file.
<script type="application/javascript">
function loadJS(file) {
// DOM: Create the script element
var jsElm = document.createElement("script");
// set the type attribute
jsElm.type = "application/javascript";
// make the script element load file
jsElm.src = file;
// finally insert the element to the body element in order to load the script
document.body.appendChild(jsElm);
}
if(type === "test1")
loadJS('file1.js')
else
loadJS('file2.js');
</script>
using jquery and javascript:
$(document).ready(function(){
var url=location.href//get the page url
var scriptUrl
if(url.indexOf('something')>0){//check for specific string in url
scriptUrl='/script1.js'
}
else{
scriptUrl='/script2.js'
}
var script = document.createElement( 'script' );//create script element
script.type = 'text/javascript';
script.src = scriptUrl;
$("head").append( script );//append newly created script element to head
})
Query String Examples:
?page=test1
?page=test2
Following code will check the value of page and then load the appropriate Script:
$(document).ready(function () {
var page = $.getUrlVar("page");
var scriptToRun = null;
switch (page) {
case "test1":
scriptToRun = "script1.js";
break;
case "test2":
scriptToRun = "script2.js";
break;
}
// Create Script Tag
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptToRun;
$("head").append(script);
});
Be sure to add the following Extension before your $(document).ready code:
$.extend({
getUrlVars: function(){
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
},
getUrlVar: function(name){
return $.getUrlVars()[name];
}
});
(This jQuery Extension is not my Code).

Getting twitter shares count, response giving weird output

//this function is the callback, it needs to be a global variable
window.readResponse = function (response){
document.getElementsByTagName('SPAN')[0].innerHTML = response;
}
(function(){
//note the "readResponse" at the end
$URL = "http://www.google.com/"
var src = 'http://cdn.api.twitter.com/1/urls/count.json?url=' + $URL + '&callback=readResponse',
script = document.createElement('SCRIPT');
script.src = src;
document.body.appendChild(script);
})();
That above is my codes to get the shares count. But when I do the request, the response I am getting is
function (){ //note the "readResponse" at the end $URL = "http://www.google.com/" var src = 'http://cdn.api.twitter.com/1/urls/count.json?url=' + $URL + '&callback=readResponse', script = document.createElement('SCRIPT'); script.src = src; document.body.appendChild(script); }
Where as I am expecting the response.count is the actual share count.
I setup a demo here http://jsfiddle.net/zs1dgs45/5/
Any help would be appreciated
Twitter have stopped supporting the share count API. Sorry.

JSDOM - Hardcore way - Add external script and use it

I'm starting to use JSDOM and I have this working properly:
jsdom.env(
'<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom\'s Homepage</a></p>',
["http://127.0.0.1:8080/js/test.js"],
function (errors, window) {
//console.log("contents of a.the-link:", window.$("a.the-link").text());
console.log(errors);
console.log(window.myVar);
console.log(window.test);
});
Test.js script is very simple:
console.log("testing testing testing");
window.myVar = "myVar Content";
var test = "test content";
The content of myVar and test is displayed when I execute the script.
But the problem is when I start to do it on the hardcore way (hardcore as the documentation say):
I do the follow:
var jsdom = require("jsdom").jsdom;
var document = jsdom("<html><head></head><body>hello world</body></html>");
var window = document.parentWindow;
var script = document.createElement("SCRIPT");
script.src = "http://127.0.0.1:8080/js/test.js";
var head= window.document.getElementsByTagName('head')[0];
head.appendChild(script);
var window = document.parentWindow;
console.log("myVar Content: " + window.myVar);
In this case, window.myVar is undefined.
What am I missing?
Thanks.
I found how to do it:
var jsdom = require("jsdom").jsdom;
var document = jsdom("<html><head></head><body>hello world</body></html>");
var window = document.parentWindow;
var script = document.createElement("script");
script.type = "text/javascript";
var fs = require("fs");
var requireJSFile = fs.readFileSync("test.js","utf8");
script.innerHTML = requireJSFile;
var head= window.document.getElementsByTagName('head')[0];
head.appendChild(script);
var window = document.parentWindow;
console.log(document.innerHTML);
console.log("myVar Content: " + window.myVar);
I will add a function in the var and I will see if I can use it as: window.myVar(param1, param2, param3).
I'm pretty sure it will work.

Categories

Resources