Requirement: When clicking on a button that pushes a #info route to show a full screen overlay component, closing the modal or pressing back should dismiss the overlay rather than go to the previous page.
e.g. on page 1, go to page 2. On page 2, press button to show overlay. Press back or closing overlay should dismiss overlay and remain on page 2.
The problem: When going back to page 2 I still have forward history to go to the overlay route.
I've searched for ways and couldn't find a solution to delete forward history.
My code is as such: If overlay is shown:
this.props.router.push(this.props.router.getCurrentLocation().pathname + '#info')
Then I have a code to goBack when overylay is closed or when pressing back button:
onBackButtonEvent () {
if (this.props.renderOverlay) {
this.setState({
overlayRoutePushed: false
})
this.props.closeOverlay()
}
}
closeOverylayAndBack () {
this.setState({
overlayRoutePushed: false
})
this.props.closeOverlay()
this.props.router.goBack()
}
componentDidMount () {
window.onpopstate = this.onBackButtonEvent
}
In order to detect back button with window.onpopstate I have to push a route. I tried to replaceRoute with #info when overlay shown and just close overlay when pressing back but I can't prevent default of route.goBack().
Any ideas?
I wasn't able to find a way to prevent forward or remove forward history so my final resort was to remove using hash and just show the overlay when i hit forward and hide when I hit back:
this.props.router.push({
pathname: this.props.router.getCurrentLocation().pathname,
state: {overlay: true}
})
This is to remove the #, and if I don't change state push will actually be using replace() which won't let me handle onPopState.
Then I check to see if state is changed when I pop back and forth:
componentWillReceiveProps (nextProps) {
if (nextProps.router.location.state) {
if (nextProps.router.location.state.overlay) {
this.showOverylay()
}
}
}
Related
I am showing user a modal that takes over the entire screen if user is accessing the website on phone. A user tends to instinctively click the back button on their phone to go back to the previous screen instead of using the close button provided on the modal.
Is there a way to intercept the function that is triggered when a user clicks the back button? I want to close the modal when user clicks the back button on their phone, instead of having them redirect to the previous page.
Use the History API. An example on how to acomplish this is:
//listen for state changes
window.onpopstate = (event) =>
{
if (!event.state.modalOpened)
{
closeModal()
}
}
//change the actual page state so it contains the modalOpened property
window.history.replaceState({modalOpened: false})
function openModal(content)
{
//push new state, put the modal information in the state object, this will push a new state, when the user presses the back button, the browser will just trigger the onpopstate event, instead of going to the previous page
window.history.replaceState({modalOpened: true})
//this is any code you use to open your modal, for example
ReactDOM.render(<Modal>{content}</Modal>, document.getElementById("modal-container")
}
class based component
There are many ways to aproach this, this is one of them, everything you need to make something that fits with your app is in the History API DOCS.
//listen for state changes
window.onpopstate = (event) =>
{
if (!event.state.modalOpened)
{
updateModal(false, null)
}
}
function openModal()
{
//push new state, put the modal information in the state object, this will push a new state, when the user presses the back button, the browser will just trigger the onpopstate event, instead of going to the previous page
window.history.replaceState({modalOpened: true})
updateModal(false, <div>Modal content!</div>)
}
function updateModal(open, content)
{
ReactDOM.render(<Modal open={open} content={content} />, document.getElementById("modal-container")
}
//change the actual page state so it contains the modalOpened property
window.history.replaceState({modalOpened: false})
class Modal extends React.Component {
constructor(props) {
super(props);
}
render() {
//check the history to determine if we have to open or close the modal
return <div className={"modal " + (props.open)? "show" : ""}><div className="modal-content">{props.content}</div><button onClick={() => window.history.back()}>OK</button></div>;
}
}
I can't give you a snippet because my code is too big, but basically I have, let's say htmlpage1 and htmlpage2. When on htmlpage1, I click on an element, and get redirected to htmlpage2, on htmlpage2, when I click the 'back' button on the browser, I go back to the previous htmlpage1 page, but now what I want is when I click forward button, not to be able to go back again to the htmlpage2. How do I make this happen?
I tried adding this:
if(performance.navigation.type == 2 || performance.navigation.type == 0) { location.replace("htmlpage1")
}
inside htmlpage1 in order to sort of replace the current page with the same page, and my thinking was that, that would prevent the 'forward' button from going back to 'htmlpage2', but it's not working. It keeps going there.
I also added this:
window.onbeforeunload = function() {
location.replace("htmlpage1")
}
on the htmlpage2 JS file. My thinking was, when you click 'back' button, this onbeforeunload should be triggered, and the page should be replaced with the htmlpage1, thus removing it from the doc history, but again, it's not working.
Why is it not working, and how do I make it work?
Without clicking/touching on anywhere inside page when click browser back button, navigation should be disable.
Below implementation only work when click inside page.
history.pushState(null, null, window.location.href);
history.back();
window.onpopstate = () =>{ // not getting activate without clicking inside page
console.warn('DISABLE BROWSER NAVIGATION');
history.forward();
}
one of the best way is to open your application in a popup without controls but again depending upon your requirement this may not be applicable. Hope this helps. Something like below
function openPopup(){
var pathname = (window.location.pathname);
window.open(pathname+'openpagePopup.html','','width=800,height=450,toolbar=no, menubar=no,scrollbars=no,resizable=no,dependent,screenx=80,screeny=80,left=80,top=20,scrollbars=no');
return false;
}
The otherways are not trustworthy like you can show user an alert, but can not disable the back button, as per my knowledge. If you do the below make sure you check browser compatibility.
window.onbeforeunload = function() {
return "Write something here";
};
Update : I found there is a way to handle the page history. Incase that works, I have never tried, here is a link
JS - window.history - Delete a state
I have a single page website. If click one of the navbar tabs, lets say 'contact us' the site will scroll down to the contact section. The problem is, if I refresh the site now it will automatically scroll down to the contact section each time. I want the site to scroll to the top of the page every time I refresh. The reason this is happening is because the address bar is changed to ...index.html#contact-area.
I tried the code below but the site gets caught in an infinite refresh loop.
<script>
window.location.replace("index.html");
</script>
I also tried the following but it doesn't work. It starts to scroll up then stops.
<script>
window.onbeforeunload = function () {
window.scrollTo(0, 0);
}
</script>
One option is to attach an event listener to the anchor instead, and instead of changing the page hash, call scrollIntoView on the #contact-area:
anchor.addEventListener('e', (e) => {
e.preventDefault(); // don't change page hash (unless JS disabled...)
document.querySelector('#contact-area').scrollIntoView();
});
Configured our app to support Add to home screen option, to ask for permission we added one button, onclick the prompt will ask to add the icon in home screen. If the user keep clicking close, then it wont ask further, so the button becomes non-functional.
If the user already added icon, i didn't get any method to find it.
There isn't any method best known to me to capture whether the app icon has been added to home screen or not. Simple reason for that could be absence of any valid existing use case. However, what you can capture is the action taken by the user. When the A2HS banner is shown, you can tap into the beforeinstallprompt event to determine the choice made by the user when presented with the banner.
The code below shows this in action:
window.addEventListener('beforeinstallprompt', function(event) {
event.userChoice.then(function(result) {
if(result.outcome == 'dismissed') {
// User dismissed
}
else {
// User accepted
}
});
});
UPDATE:
While going through the official doc for A2HS, found a way to determine if the app was successfully added to the users home screen after they accepted the prompt, you can listen for the appinstalled event. Code:
window.addEventListener('appinstalled', (evt) => {
app.logEvent('a2hs', 'installed');
});
appinstalled does not work
window.addEventListener('appinstalled', (evt) => {
app.logEvent('a2hs', 'installed');
});