How to find if a javascript is already loaded or not? - javascript

I am developing a chrome extension to ajaxify every non ajax website like wikipedia. etc. It works fine but it fail to load the js files. So, I have written a script to load js files thats are required for the page by getting src attribute from tag. But the problem is when i am loading another page of that website every scripts are loaded again. So it is useless to make it with a purpose to reduce bandwidth.
So, I want to know whether there is any way to match the script array of the new with its previous page. and to identify which scripts are new and load only them.
var array1 = [];
for (var i = 0; i < jsn; i++) {
var jssrc = document.getElementsByTagName("script")[i].src;
array1.push(jssrc);
}
var array2 = [how to find out array script source of the new page]
Array.prototype.diff = function(array2) {
var ret = [];
for(i in this) {
if(array2.indexOf( this[i] ) > -1){
ret.push( this[i] );
}
}
return ret;
};
ajaxpagefetcher.load("ajax-script", "", true, array1.diff(array2);)
How to find script src array of the new page that is to be loaded..
one more question, with out reloading the page if i delete the body tag through remove() function, are the scripts that already loaded also removed?
Thanks
I am waiting with eager for your replay....

At the end of the JS file:
window.iAmLoadedOnThisWindow = true;
And in the loader part:
if(! window.iAmLoadedOnThisWindow) {
// append the script with some dom method
}
If the JS file is a library, test the library : if(jQuery), if(_), etc.

Related

Adding dynamically third party javascript widgets to the web app

I am working on a React js project where I should dynamically add third party scripts (widgets) to the web app.
Widgets include any kind of third party platforms: Twitter, Instagram, Youplay, Youtube etc.
The current code that I have looks like this:
appendThirdPartyScript(externalScript) {
// Create an element outside the document to parse the string with
const head = document.createElement("head");
// Parse the string
head.innerHTML = externalScript;
// Copy those nodes to the real `head`, duplicating script elements so
// they get processed
let node = head.firstChild;
while (node) {
const next = node.nextSibling;
if (node.tagName === "SCRIPT") {
// Just appending this element wouldn't run it, we have to make a fresh copy
const newNode = document.createElement("script");
if (node.src) {
newNode.src = node.src;
}
while (node.firstChild) {
// Note we have to clone these nodes
newNode.appendChild(node.firstChild.cloneNode(true));
node.removeChild(node.firstChild);
}
node = newNode;
}
document.head.appendChild(node);
node = next;
}
}
So basically the scripts urls comes from the backend/api and that is a list of scripts smth like ['http://twitter-widget.js', 'http://instagram-widget.js']
So since I have an array of scripts as string I use a for loop to go thru each of element and call appendThirdPartyScript('somescript')
data.externalScripts.map(script => {
this.appendThirdPartyScript("" + script);
});
This solution worked for almost all cases until I came to this case:
['http://embed.tt.se/v10/tt-widget.js', 'new tt.TTWidget({WhereToAddWidget: 'tt-quiz-XMuxmuWHc',type: 'quiz',ID: 'xxx',clientID: 'xxx',});']
So basically the error I get is:
tt is not a function
I am assuming that the first script hasn't completed loading (in this case http://embed.tt.se/v10/tt-widget.js) and the next one is trying to call something that does not exists.
When I try to hard code http://embed.tt.se/v10/tt-widget.js within head tag in index.html directly than it works!
So this approach of dynamically adding third party widgets is not reliable. Anyone can let me know if my current code needs to be changed or any suggestion would be pretty much appreciated!
This seems to work but probably not best solution:
const delayTime = 500;
externalScriptArray.forEach((script, index) => {
setTimeout(() => {
this.appendNewTagElementToDom(script);
}, delayTime*index);
});

Folder level script referencing document level script

I have the following javascript code that works at the document level in Adobe Acrobat 10 when the document is opened (enveloped in this.addScript):
var nNumFields = this.numFields;
var cFieldName;
var oField;
for(i = 0; i < nNumFields; i++)
{
cFieldName = this.getNthFieldName(i);
oField = this.getField(cFieldName);
oField.textFont = \"PTSans\";
}
I want to avoid going through multiple documents and adding this script to all of them. Is there a way to adapt this code to the folder level so it works for all acrobat opened documents?? If so what would it be?
Or is there a way to add this script for a list of documents quickly (programmatically) instead of manually?? (manually as in by opening the document, inserting the script into the debugger, running it, then saving the document, then repeating for every document)

Iterate through multiple web pages in JS with sleep in between

I was checking some simple solutions for showing multiple web pages for some dashboard and currently fighting with simple HTML page with javascript inside to achieve what I want to see there.
var urls = new Array();
urls[0] = "https://stackoverflow.com/"
urls[1] = "https://www.google.com"
var arrayLength = urls.length;
for (var i = 0; i < arrayLength; i++) {
window.location.assign(urls[i]);
sleep(3000);
}
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds) {
break;
}
}
}
Currently this page opens only first page (after some time) and looks like it doesn't do iteration trough other pages. Maybe you could help me to make it work? I want to rotate those pages forever on screen (will add some infinite while loop after making this part working).
Currently this page opens only first page (after some time) and looks
like it doesn't do iteration trough other pages.
Once you change your window.location, and go to the first url from the array, you are losing all of your JS code (as it is not present in just opened url any more).
You can do this by installing a chrome plugin (which will not lose your JS after window.location change).
The plugin will run the added JS at DOMContentLoaded (no need to attach any event listener).
I needed also to do this, check things on the page, store some information and move on to the next page. I know, this can be done with Python and other stuff but by doing this it can be done on the FE side also.
I used the localStorage to store my information.
I pasted this into the browser console to prepare all the stuff and clean the localStorage:
// clear the localStorage
localStorage.clear();
// set an array that will keep all our pages to iterate into the localStorage
localStorage.setItem(
"pages",
JSON.stringify([
"https://my-page-1.html",
"https://my-page-2.html",
"https://my-page-3.html",
"https://my-page-4.html",
])
);
// set an array that will keep our findings
localStorage.setItem("resultArray", JSON.stringify([]));
// move to the first page of the iteration
window.location.href = "https://my-page-1.html";
After doing this, I opened the plugin interface and added the following code:
(function check() {
// array saved into the localStorage that contains all the pages to iterate
const pagesArray = JSON.parse(localStorage.getItem("pages"));
// array to store your stuff
const resultArray = JSON.parse(localStorage.getItem("resultArray"));
// whatever you want to check on that page
const myFancyCondition = true;
if (myFancyCondition) {
// push any data to the array so that you can check it later
resultArray.push({
page: pagesArray[0],
message: "I found what I was looking for!",
});
}
//remove the current page from the array
pagesArray.shift();
//reset the array value after the first page was already checked
localStorage.setItem("pages", JSON.stringify(pagesArray));
//store the array data
localStorage.setItem("resultArray", JSON.stringify(resultArray));
// quit if the iteration is over and there are no more pages to check
if(!pagesArray.length) return;
//go to the next page
window.location.href = pagesArray[0];
})();
Then, to check the results you just need to read the data from the localStorage like:
JSON.parse(localStorage.getItem('resultArray'))
I hope this helps :)!

Can I fetch a title of an external page in my domain using JavaScript?

I have several pages (all reside in the same directory as master page) that are loaded into the parent via iFrame. I would like to fetch each one of the child pages titles and load them into an array. Is that possible?
Best I could do so far is to pass the tile from a child page when the page is loaded into an iFrame, but I need to preload all the titles from the start in order to populate the table of contents as shown below:
Parent code:
var pages = new Array("page1.html", "page2.html", "page3.html");
var maxPages = pages.length;
function pageTitle(title){ //called from inside a child HTML
document.getElementById("titleText").innerHTML = title;
};
child code:
window.onload = function passTitle(){
var title = $(document).find("title").text();
parent.pageTitle(title);
};
You want to use window.frames - this is a list of frame objects (not an array - important to know for the second solution)
Then, the simplest way is this
var pageTitles = [];
for (i = 0; i < window.frames.length; i++) {
if( !!window.frames[i].document) { // only frames in same domain
pageTitles.push(window.frames[i].document.title);
}
}
Or, little more advanced, but in my opinion the nicer way
var pageTitles = [].filter.call(window.frames, function(frame) {
return !!frame.document; // return only frames in same domain
}).map(function(frame) {
return frame.document.title;
});
actually you could use just window without the .frames - at least in firefox, because window.frames === window - however, I'd recommend using window.frames for clarity in code

Javascript giving a TypeError variable is undefined for code (photo gallery) run on server. Same code works locally

i'm putting together a personal website as a portfolio and i'm having trouble getting a photo gallery to work. I found a free Javascript gallery (http://ettrics.com/lab/demo/material-photo-gallery/) that I decided to implement. When putting the page together locally, the javascript runs no problem, however when I upload the page to the site (which already has plenty of other javascript running) I get the following error when scrolling on the page, or when trying to 'fullscreen' one of the images by clicking on it:
TypeError: this._fullImgs is undefined
I tried to isolate the issue and found that a line of code was executing differently on the server, than locally, the excerpt is below:
Gallery.prototype._loadFullImgsDone = function() {
var imgLoad = imagesLoaded(this._fullBox);
imgLoad.on('done', function(instance) {
var imgArr = instance.images;
this._fullImgs = [];
this._fullImgDimensions = [];
this._fullImgsTransforms = [];
for (var i = 0, ii = imgArr.length; i < ii; i++) {
var rect = imgArr[i].img.getBoundingClientRect();
this._fullImgs.push(imgArr[i].img);
this._positionFullImgs.call(this, imgArr[i].img, i);
this._fullImgDimensions.push(rect);
}
this._fullImgsLoaded = true;
}.bind(this));
};
I have found that the images are being found from their source location, however
imgLoad.on('done', function(instance) {
...
executes differently. The site is located at http://http://samueller.tech/photo-best.html id anybody would like to see for themselves the error I am getting.
Thanks in advance, i'm at a complete loss of how to fix this.
I'm seeing (on that site) the resizeHandler is getting called before the images are loaded
Gallery.prototype._handleScroll = debounce(function() {
this._resetFullImg.call(this);
}, 25);
Gallery.prototype._handleResize = function() {
this._resetFullImg.call(this);
};
Then this._resetFullImg fails because there are no images loaded yet which is why this._fullImgs is empty. The code seems to have another variable called _fullImgsLoaded and probably the _resetFullImg method should do nothing if images haven't been loaded.
You could try adding that like this:
// in material-photo-gallery.js line 1379
Gallery.prototype._resetFullImg = function() {
if (!this._fullImagesLoaded) {
return
}
this._fullImgsTransforms = [];
for (var i = 0, ii = this._fullImgs.length; i < ii; i++) {
...
I don't know how this will affect the reset of the gallery code, but it might work. It makes some sense that on your production system, the page load time (with extra JS and stuff) is such that these events might get called before things are ready which is something you don't see locally.
good luck.

Categories