Communicate between two pages / tabs - javascript

I'm wanting a JavaScript file to control two HTML files simultaneously.
<!DOCTYPE html>
<html>
<head>
<title>tryAgainPage1</title>
<meta charset="UTF-8">
</head>
<body>
<div id="page1"></div>
<script src="tryAgain.js"></script>
</body>
</html>
That's page one. Next is page two.
<!DOCTYPE html>
<html>
<head>
<title>tryAgainPage2</title>
<meta charset="UTF-8">
</head>
<body>
<div id="page2"></div>
<script src="tryAgain.js"></script>
</body>
</html>
And here is the JavaScript:
newFunction();
function newFunction() {
document.getElementById("page1").innerHTML = "page one says hello";
document.getElementById("page2").innerHTML = "page two says goodbye";
}
Page one is working, page two isn't. I've been trying for a day to get pages talking to each other, without success. I'm not sure I understand how to implement Broadcast channel in this instance (if indeed that is appropriate.) Can anyone help?

postMessage
If you're looking for a way to make two pages or tabs communicate you can take a look at:
MDN Window.postMessage, and read this postMessage article
or MDN Broadcast_Channel_API
Using Broadcast Channel API page1 — page2
How it works:
pageX subscribes to a named Broadcast Channel object
pageY broadcasts to the same Channel name using postMessage
pageX listens to "message" events and prints the Event.data
And vice-versa.
page1.html
<h1>PAGE 1</h1>
<p><button data-broadcast="Page 1 talking!">BROADCAST</button></p>
Page 2 says: <div id="page2"></div>
<script src="comm.js"></script>
page2.html
<h1>PAGE 2</h1>
<p><button data-broadcast="Page 2! 'Allo 'Allo!">BROADCAST</button></p>
Page 1 says: <div id="page1"></div>
<script src="comm.js"></script>
comm.js
var bc = new BroadcastChannel('comm');
document.querySelector("[data-broadcast]").addEventListener("click", ev => {
bc.postMessage( ev.target.dataset.broadcast );
});
const targetEl = document.querySelectorAll("#page1, #page2");
bc.addEventListener("message", ev => {
[...targetEl].forEach( el => el.innerHTML = ev.data );
});
localStorage and the storage Event
Another simple, yet cool way, if both tabs are on the same domain is by using
Window.localStorageMDN and its Storage Event.
How it works:
pageX writes to localstorage[pageX]
pageY's window will trigger a storage event
pageY can now read localstorage[pageX] or better (to make it simpler (and pageN agnostic)) the Event.newValue sent by the storage event
And vice-versa.
For starters: DEMO: page1 — page2
page1.html
<h1>PAGE 1</h1>
<textarea data-sender="page1" placeholder="Write to page 2"></textarea>
Page 2 says: <div id="page2"></div>
<script src="comm.js"></script>
page2.html
<h1>PAGE 2</h1>
<textarea data-sender="page2" placeholder="Write to page 1"></textarea>
Page 1 says: <div id="page1"></div>
<script src="comm.js"></script>
comm.js
// RECEIVER
window.addEventListener("storage", ev => {
document.getElementById( ev.key ).innerHTML = ev.newValue;
});
// SENDER
[...document.querySelectorAll("[data-sender]")].forEach( el =>
el.addEventListener("input", ev => localStorage[el.dataset.sender] = el.value )
);
Web RTC
You could use Web RTC (Web Real-Time Communications). A technology which enables Web applications and sites to capture and optionally stream audio and/or video media, as well as to exchange arbitrary data between browsers
Your main errors:
Your script was not working on one page... actually on both, the only difference was that on page 1 broke after realizing #page2 Element could not be found - Inversely on the other page broke immediately after realizing there is no "#page1" Element (since first in order).
You should always check if al element exists using if ( someElement ) { /*found!*/ } .
And yes, you cannot make communicate two pages that way. They will only share / include the same JS file.

Both pages are throwing an error, the difference is, on the first page the error doesn't happen until after the div is changed.
Here's one possible approach.
newFunction();
function newFunction() {
var page = document.getElementById("page1") ? "1" : "2";
var msg = page == "1" ? "page one says hello" : "page two says goodbye";
document.getElementById("page"+page).innerHTML = msg;
}

Related

Chrome: How to detect history navigation (back button having been pressed)

I know, this question looks quite the same as those asked and reasked regularly, as for example here:
How to force reloading a page when using browser back button?
I need to know if the user has...
. navigated to current page, or reloaded current page (in both cases the page has been normally loaded, I need no further specific action)
. or has arrived on current page using history back or forward button (in these cases, the page is not loaded, just anyhow taken out of browser-cache, and I need to take further actions -the simplest being just reloading the page, window.location.reload(); or equivalent).
I tried the solutions exposed here: https://stackoverflow.com/a/43043658/3872061 and here: https://stackoverflow.com/a/56851042/3872061 as well as in several other places, within Stackoverflow or not.
It works well for Firefox (105.0.1), for Edge (105.0.1343.50), but I can't get it to work with Chrome (105.0.5195.127).
Here the simplest test I could imagine.
page1.html :
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(window).on("pageshow", function(e){
$("#type").text(window.performance.getEntriesByType("navigation")[0].type);
let historyTraversal = event.persisted
|| ( typeof window.performance != "undefined" && window.performance.getEntriesByType("navigation")[0].type === "back_forward" );
if ( historyTraversal ) { // Handle page restore.
$("#backOrNot").text('User just came back using the history "back" button');
//window.location.reload(); // this is actually the targetted action: reload page
}
else {
$("#backOrNot").text('User loaded the page');
}
});
</script>
</head>
<body>
<p id="backOrNot"></p>
<p>( window.performance.getEntriesByType("navigation")[0].type = <span id="type"></span> )</p>
<p>Just a link from where you can click the history back button</p>
</body>
</html>
page2.html :
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<p>
From here, try to:<br>
1. Navigate to page1.html<br>
2. Go back to page1.html using the history back-button
</p>
</body>
</html>
With both FF and Edge, when you come back to page1 using the history, the "back_forward" information is available.
With Chrome, you just get the status ("navigate" or "reload") which the page had on the initial load,as if you had never navigated away then returned using the back button.
What have I missed? What am I doing wrong here?
Your page will automatically reload, if you send off page headers to not allow caching of that itemsList.php page. My test code -- see answer here -- should help you understand the concept. I am still trying to find a better way to solve that problem differently. In my case, I am firing off a "page-is-now-loading-spinner" that is not resetting itself to hidden, if the back button (go back one page) is presses.

Why can't I receive messages from another website using the window.postMessage method?

I run an HTML file using WebStorm 2022.1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Window.postMessage</title>
</head>
<body>
<script>
let time = 0;
setInterval
(
function ()
{
window.top.postMessage("Source01", "*");
console.log(`Time: ${++time}`);
},
2000,
time
)
</script>
</body>
</html>
And it's at the address : http://localhost:63342/XXX .Then I open any website, let's say https://stackoverflow.com/ .In the console, I write the following code
window.addEventListener("message", function (event)
{
console.log(event);
})
I observed that no messages were sent. Did I forget something?
window.top.postMessage sends the message to the document in the current window, at the top of any stack of frames. Let's call this Page A.
If the URL for Page A appears in the browser's address bar, it will send a message to itself.
If the URL in the address bar is Page B and it includes an iframe which loads Page A, then it will send the message through the frames to Page B. (Stackoverflow doesn't have <iframe src="http://localhost:63342/XXX"></iframe> so this isn't the case for you).
If you load Page C in a new window, then Page A won't send a message to it, because is in a window.
If you navigate from Page A to Page D in the same window, then Page A won't send a message to Page D because navigating away from Page A will stop the JS program.

How to clear browsing history using JavaScript?

I am doing a simple project, let us take high secure website. I have 5 different JSP pages. If I started from first JSP page, it is redirecting to second JSP page and so on. In the meanwhile, it should not store those pages in my browser history.
How to clear those browsing history using JavaScript?
Can you try using document.location.replace() it is used to clear the last entry in the history and replace it with the address of a new url. replace() removes the URL of the current document from the document history, meaning that it is not possible to use the "back" button to navigate back to the original document.
<script type="text/javascript">
function Navigate(){
window.location.replace('your link');
return false;
}
</script>
HTML:
<button onclick="Navigate()">Replace document</button>
As MDN Window.history() describes :
For top-level pages you can see the list of pages in the session history, accessible via the History object, in the browser's dropdowns next to the back and forward buttons.
For security reasons the History object doesn't allow the non-privileged code to access the URLs of other pages in the session history, but it does allow it to navigate the session history.
There is no way to clear the session history or to disable the back/forward navigation from unprivileged code. The closest available solution is the location.replace() method, which replaces the current item of the session history with the provided URL.
So there is no Javascript method to clear the session history, instead, if you want to block navigating back to a certain page, you can use the location.replace() method, and pass the page link as parameter, which will not push the page to the browser's session history list. For example, there are three pages:
a.html:
<!doctype html>
<html>
<head>
<title>a.html page</title>
<meta charset="utf-8">
</head>
<body>
<p>This is <code style="color:red">a.html</code> page ! Go to b.html page !</p>
</body>
</html>
b.html:
<!doctype html>
<html>
<head>
<title>b.html page</title>
<meta charset="utf-8">
</head>
<body>
<p>This is <code style="color:red">b.html</code> page ! Go to <a id="jumper" href="c.html">c.html</a> page !</p>
<script type="text/javascript">
var jumper = document.getElementById("jumper");
jumper.onclick = function(event) {
var e = event || window.event ;
if(e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = true ;
}
location.replace(this.href);
jumper = null;
}
</script>
</body>
c.html:
<!doctype html>
<html>
<head>
<title>c.html page</title>
<meta charset="utf-8">
</head>
<body>
<p>This is <code style="color:red">c.html</code> page</p>
</body>
</html>
With href link, we can navigate from a.html to b.html to c.html. In b.html, we use the location.replace(c.html) method to navigate from b.html to c.html. Finally, we go to c.html*, and if we click the back button in the browser, we will jump to **a.html.
So this is it! Hope it helps.
It's not possible to clear user history without plugins. And also it's not an issue at developer's perspective, it's the burden of the user to clear his history.
For information refer to How to clear browsers (IE, Firefox, Opera, Chrome) history using JavaScript or Java except from browser itself?
No,that would be a security issue.
However, it's possible to clear the history in JavaScript within a Google chrome extension. chrome.history.deleteAll().
Use
window.location.replace('pageName.html');
similar behavior as an HTTP redirect
Read How to redirect to another webpage in JavaScript/jQuery?
to disable back function of the back button:
window.addEventListener('popstate', function (event) {
history.pushState(null, document.title, location.href);
});
Ok. This is an ancient history, but may be my solution could be useful for you or another developers.
If I don't want an user press back key in a page (lets say page B called from an page A) and go back to last page (page A), I do next steps:
First, on page A, instead call next page using window.location.href or window.location.replace, I make a call using two commands: window.open and window.close example on page A:
<a href="#"
onclick="window.open('B.htm','B','height=768,width=1024,top=0,left=0,menubar=0,
toolbar=0,location=0,directories=0,scrollbars=1,status=0');
window.open('','_parent','');
window.close();">
Page B</a>;
All modifiers on window open are just to make up the resulting page. This will open a new window (popWindow) without posibilities of use the back key, and will close the caller page (Page A)
Second: On page B you can use the same proccess if you want this page do the same thing.
Well. This needs the user accept you can open popup windows, but in a controlled system, as if you are programming pages for your work or client, this is easily recommended for the users. Just accept the site as trusted.
You cannot clear the browser history. It belongs to the user, not the developer. Also have a look at the MDN documentation.
Update: The link you were posting all over does not actually clear your browser history. It just prevents using the back button.

Access a variable of iframe from parent

script of iframe
<script type="text/javascript" >
var a=5;
</script>
script of parent window
<script type="text/javascript" >
function close()
{
var check=document.getElementById("iframeid").contentDocument.a;
alert(check)
}
</script>
I want to access the variable which is defined inside the iframe from parent. But the above code doesn't work properly can anyone give an idea to implement this.
Using contentWindow instead of contentDocument works for me:
var check = document.getElementById("iframeid").contentWindow.a;
Also, ensure that the domains match and that you are using a webserver to test (I got a protocol warning when testing from the file system).
UPDATE: You're almost definitely better to use the postMessage API.
One method that has always worked reliably for me is for the iFrame to give its parent a reference to its own window when it first loads. The parent can then access all the variables through that reference. This does require that the parent is loaded before the iFrame, but for me that is usually the case.
So in the parent
var iFrameWin;
Then in the iFrame at some point after it has loaded and settled down
parent.iFrameWin = window; //parent now has a ref to the iframe's window
Then, in the parent when it wants a global var contents from the iFrame
alert(iFrameWin.ivar); // shows value if the global 'ivar' in the iFrame
script of iframe:
var a = 5;
window.parent.postMessage(['varA', a], '*'); // put this in some sort of function, ready, or whatever - you can call it multiple times if you need to as the code in the parent is an eventListener
script of parent window:
var b;
// you might want to write these into if statements to make sure that e.data[0] is varA if you have multiple messages coming across
if (typeof window.addEventListener != 'undefined') {
window.addEventListener('message', function(e) {
b = e.data[1];
}, false);
} else if (typeof window.attachEvent != 'undefined') { // this part is for IE8
window.attachEvent('onmessage', function(e) {
b = e.data; // you'll probably have to play around with this part as I can't remember exactly how it comes across in IE8 -- i think it will involve slice() iirc
});
}
Most of my knowledge on this topic comes from Ben Vinegar's talk on Seamless iFrames
This is a cross-domain "okay" method to deal wit this stuff. I'm sure there are some security holes, just as with anything on the web.
See if this works for you:
i created this parent.html page and put an iframe in it with a text input which will show the value passed from iframe window:
<html>
<head>
<title>IFrame Example</title>
<script language="javascript">
function hello(string){
var name=string
document.getElementById('myAnchor').value=name;
}
</script>
</head>
<body>
<iframe namne="iframe" id="iframe_id" src="inputForm.html" height="150" >
</iframe>
Name: <input type="text" id="myAnchor" >
</body>
</html>
and this iframe content page:
<html>
<head>
<title>IFrame Child Example</title>
</head>
<body>
<form name="frm2" >
<h1><font color="#000099">Input Form</font></h1>
<p>Name : </p><input type="text" name="resp" id="input" value=""/>
<input type="button" onclick="parent.hello(this.form.resp.value);" value="Submit" />
</form>
</body>
</html>
clicking the button i get the value in my parent window.
Play with it if you get something with this one.
document.getElementById('ID_OF_IFRAME').document.getElementById('f1')
Note that cross-domain restrictions will still apply.
This is how SharePoint do it when passing argument values from the parent window to the iframe. It's simple, but it works.
<html>
<body>
<iframe id="iframe1"></iframe>
<script type="text/javascript">
var ifr = window.document.getElementById("iframe1");
ifr.dialogArgs = "Hello from the other side.";
ifr.src = "iframeContent.html"
</script>
</body>
</html>
Inside iframeContent.html:
<html>
<body>
<input type="button" value="Click Me!" onclick="alert(window.frameElement.dialogArgs);" />
</body>
</html>
The other way around (accessing ifr.dialogArgs from the parent window after having its value modified by the iframe document) also works.

Store domain in local storage and call it in href

I allow the user to store a domain in local storage (e.g. http://192.168.1.104). My method of pulling the domain out of local storage is like this:
<script type="text/javascript">
domain = localStorage['domain'];
function DOMAIN(dive) {
window.location=domain+dive;
}
</script>
and I can open it like this:
CLICK HERE
or
CLICK HERE
but I can't seem to get it to allow opening in a new tab (chrome v13). It's driving me nuts, any suggestions?
Try this:
CLICK HERE
Lets see if this works for you:
CLICK HERE
Okay, I figured it out, but it's a little hacky and restless. Make a dummy html document, say /html/home.html for instance. Call the js-function inside the dummy doc:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Ripping Status</title>
<script type="text/javascript">
domain = localStorage['domain'] || '';
function init() {
window.location=domain+'/';
document.getElementById( 'box' );
};
</script>
</head>
<body onload="init();">
<div id="box"></div>
</body>
</html>
where 'domain' is stored as, say, http://192.168.1.101. Now, call /html/home.html inside the main html document via
CLICK HERE
and it allows right click > open new tab, window, etc as you would expect.

Categories