Iterate through multiple web pages in JS with sleep in between - javascript

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 :)!

Related

Project works fine on localhost but the build gets an issue

I am working on a Preact-CLI project with a Preact-Router and it works fine on the localhost. But the production doesn't work well after the build.
I have created a one page object which gets its content dynamically from a JSON file (inside the project not external). So I've loaded the same page object 2 times for each different page.
I get the page url (using this.props.permalink) and compare it with the JSONObject.title. If they are the same I want to get the corresponding JSON content to display it on the corrrct page. Works like a charm on localhost, but not in production.
Issue:
Somehow all pages get the content of the first JSON element. First I thought it was a server issue but I was wrong. The builded files are wrong after the prerendering/build. So the prerendered html of page B contains the content of the prerendered page A.
My guess is that during the build this.props.permalink doesn't work. How should I handle this?
Additional info:
I use the prerender function but not the service worker for the build.
Thanks!
UPDATE:
I have rewritten the function. I guessed I needed to set the dynamic content through a loop, so that during the build the compiler loops through it and is able to prerender all the pages.
The iteration and setting the state works, but only the final element of the PrerenderUrls array gets stored. So now all pages gets the JSON content of the first element.
componentWillMount() {
for (var i = 0; i <= PrerenderUrls.length; i++) {
// the code you're looking for
let removeDash = new RegExp("-")
var needle = PrerenderUrls[i].title
var needle1 = needle.replace(removeDash, " ")
alert("1")
// iterate over each element in the array
if (needle1 != "Homepage") {
for (var x = 0; x < Data.length; x++) {
// look for the entry with a matching `code` value
let removeDash = new RegExp("-")
var nodash = Data[x].title.replace(removeDash, " ")
var nocaps = nodash.toLowerCase()
if (nocaps == needle1) {
alert("needle2: "+ needle1 + " nocaps: " + nocaps)
//alert("data "+ Data[x].title)
this.setState({
pageTitle: Data[x].title,
descShort: Data[x].descShort,
description: Data[x].desc,
img: Data[x].img
})
alert("state "+ this.state.pageTitle)
}
}
}
}
From your description it seems you have a standard Javascript closure problem. I noticed you use both let and var. If let is supported, use it instead of var. It will automagically solve your closure issues, because let creates variables with the block scope, instead of a function scope. Otherwise, you can try to replicate how let does it under the hood - throw the variable to the callback function. Something in the lines of:
// ...
for (var x = 0; x < Data.length; x++) {
try { throw x }
catch(iterator) {
this.setState({
pageTitle: Data[iterator].title
});
}
}
PS. It is very difficult to follow your code, when it is so specific to your functionality. You could simplify it, and focus on the troubling issue. Most of the code you provided is not relevant to your problem, but makes us going through it anyway.

Array with localStorage doesn't save or gets overwritten?

In order to summarize the problem I'll explain what the task is first.
So for the eastern event, we are going to add 3 bunny images across a website (different pages, same domain, same website). Once you've found and clicked on all 3 images it should open a new window with a specific URL.
Right now I managed to write the code which saves the clicks of the 3 pictures in an array and then opens the new window with an URL. But sadly it doesn't work once I change the page. The Array either didn't save in the browser storage or gets overwritten once I open a new page.
I'm not exactly sure what the issue is right now. I hope any of you could help me out.
I've tried to work with localStorage and sessionStorage but I don't think I used them properly. I'll provide you with my current code below.
Javascript
$(function(){
var imageStore = [];
$('.osterhasen').click(function(e){
localStorage.id = $(this).attr('id');
// returns index of the element in the array, if the element was not found returns false
var imageExists = $.inArray(localStorage.id, imageStore);
if (imageExists >= 0){
// If element exists, do nothing
e.preventDefault;
} else {
// If element doesn't exist, add element
imageStore.push(localStorage.id);
}
localStorage.setItem('imageStore', JSON.stringify(imageStore));
localStorageimageStorage = JSON.parse(localStorage.getItem('imageStore'));
console.log(localStorageimageStorage);
if (localStorageimageStorage.length == 3) {
window.open('https://www.google.ch');
}
});
});
HTML
<body>
<div class="container">
<div id="1" class="osterhasen"><img src="img/choco.png"></img></div>
<div id="2" class="osterhasen"><img src="img/geschichte.png"></img></div>
<div id="3" class="osterhasen"><img src="img/mitarbeiter.jpg"></img></div>
</div>
</body>
In the end the clicks on the images should be saved in the browser storage across the whole website and once you've found all 3 images it should open a new window with a specfic URL.
Thank you very much for your time.
Best regards
You can't assign properties to localStorage like this (it doesn't exist, and you should be using it's setItem method anyway):
localstorage.id = $(this).attr('id');
var imageExists = $.inArray(localstorage.id, imageStore);
So assign id to a variable instead:
const id = $(this).attr('id');
const imageExists = $.inArray(id, imageStore);
Working version
Yes, you're overriding the key every time. To store an array as you want, you can try the following:
$(function(){
var imageStore = [];
$('.osterhasen').click(function(e){
if(localStorage.getItem('imageStore') === null){ // check if such key exists
localStorage.setItem('imageStore', JSON.stringify([$(this).attr('id')])); // if it doesn't create an array with first item imageStore and set it to key imagestore
} else {
var currentStorage = JSON.parse((localStorage.getItem('imageStore')));
if(!currentStorage.includes($(this).attr('id')){ // if id doesn't exist add it.
currentStorage.push($(this).attr('id')); // push to new image inside of it
localStorage.setItem('imageStore', JSON.stringify(currentStorage)); // set the key to the new value
}
}
localStorageimageStorage = JSON.parse(localStorage.getItem('imageStore')); // you should have all the 3 pictures here in an array
console.log(localStorageimageStorage);
if (localStorageimageStorage.length == 3) {
window.open('https://www.google.ch');
}
});
});

Returning empty string on a input that has a value

I have a date input in my page, which I'm using Daterangepicker framework to populate it.
Here is the code of how I start my page!
$(function(){
startSelectors();
var variaveis = returnInputVars();
var rede = variaveis[0];
var codLoja = variaveis[1];
var period = variaveis[2];
console.log('1.'+rede+' 2.'+codLoja+' 3.'+period);
});
function returnInputVars(){
var rede = $("#dropdown-parceria").val();
var codLoja = $("#dropdown-loja").val();
var periodo = $("#datepicker-range").val();
return [rede, codLoja, periodo];
};
The function startSelectors() is set to start my datepicker and other fields, which is working perfectly. After it, I create a var called "variaveis" to fill
with the values of each field because I will use then later (this functions also works perfectly at other scripts of my page).
Running the page, my console returns this:
The funny thing is, if I type at the console this, the value is shown, just while starting the script is does not work!
Anybody experienced something like this?
***UPDATE
Adding this script to my start function:
console.log($("#datepicker-range"));
The value is shown, but the second console.log don't:
EDIT 1. FIDDLE (Suggested by #halleron)
To ensure things are loaded in the correct order, it is useful to apply a page sniffer code snippet that will scan the page continuously until a condition is met, or until a preset counter limit is reached (to prevent strain on browser memory). Below is an example of what I typically use that would fit your scenario.
I think because you are dealing with asynchronous loading, you can't have a global variable that holds the values in a global scope without an interval to detect when it can be used. Otherwise, it will attempt to read the variable when it is not yet ready.
You can invoke functions anywhere you like. But I would keep all of your variables contained within the page_sniffer_2017() because that is a controlled environment where you know that everything successfully loaded and you know that the variables are ready to be accessed without error.
That way, regardless of connection speed, your functions will only fire when ready and your code will flow, sequentially, in the right order.
Within the ajax success options, always add a class to the body of the document that you can search on to determine if it has finished loading.
$(document).ready(function() {
page_sniffer_2017();
});
function page_sniffer_2017() {
var counter = 0;
var imgScanner = setInterval(function() {
if ($("#datepicker-range").length > 0 && $("#datepicker-range").val().length && jQuery('body').hasClass('date-picker-successfully-generated')) {
var periodoDatepicker = $("#datepicker-range").val(); // ok
console.log(periodoDatepicker); // ok
var variaveis = returnInputVars(replaceDate(periodoDatepicker)); // ok
console.log(variaveis[0], variaveis[1], variaveis[2]);
//startNewSelectors(variaveis);
// start ajax call
generateData(variaveis[0], variaveis[1], variaveis[2]);
clearInterval(imgScanner);
} else {
//var doNothing = "";
counter++;
if (counter === 100) {
console.log(counter);
clearInterval(imgScanner);
}
}
}, 50);
}

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

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

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.

Categories