I have a custom popup functionality. What I want is for the browser back button to close this popup.
My ideal scenario would be to NOT show a hashtag in the URL bar.
I have tried putting window.history.pushState('forward', null, ''); in my showPopup() function and then doing the following:
$(window).on('popstate', function () {
closePopup();
});
This does work but the problem is when I manually close the popup I have to press the back button twice to navigate back to the previous page (obviously because a browser history entry was added when the popup was opened).
What is the best way of doing this? Can it be done without adding a browser history entry? Essentially what I am trying to do is replicate the behaviour of a mobile app. Press the back button in a mobile app will usually dismiss any open modals or context menus.
$('.popup-link').click(function() {
showPopup();
});
$('.popup-close').click(function() {
hidePopup();
});
function showPopup() {
$('.popup').addClass('active');
}
function hidePopup() {
$('.popup').removeClass('active');
}
.popup {
background-color: #ccc;
width: 300px;
height: 300px;
display: none;
}
.popup.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>
<div class="popup">
<button class="popup-close">x</button>
<!-- popup content here -->
</div>
It is not possible to do it without adding browser history entries since you cannot override the back button behaviour, see Intercepting call to the back button in my AJAX application: I don't want it to do anything
Sujumayas answer is a good option, you should introduce some additional variable though to avoid problems with the history when opening multiple popups (e.g. when clicking the button multiple times)
Here is some possible sample code:
let popupOpen = false;
$(".popup-link").click(function() {
showPopup();
});
$(".popup-close").click(function() {
window.history.back();
});
function showPopup() {
if (popupOpen) {
window.history.back();
}
popupOpen = true;
window.history.pushState("forward", null, "");
$(".popup").addClass("active");
}
function hidePopup() {
popupOpen = false;
$(".popup").removeClass("active");
}
$(window).on("popstate", function() {
hidePopup();
});
Additionally please note that you might have problems with Opera Mini: https://caniuse.com/#search=history
Altho I don't recommend to override regular browser history managment (back button) to use it as you please....
I think that the only thing you missed in your example is that the close button should not close the modal by itself, but instead just execute a backbutton event (which will eventually close the modal).
That simple fix and it will work as you wanted.
I am doing already something like this, and it works nicely with the browser back-button and by pushing the android back-button as well. I am also not showing a hashtag in the URL bar.
Here is the stub (I just tried to apply that to Your scenario):
function freezeHistory() {
window.history.pushState({}, window.document.title, window.location.href);
}
function goBack() {
/*
Custom history back actions: close panel, close popup, close drop-down menu
*/
var popupOpen = $(".popup.active").length > 0;
if(popupOpen) {
hidePopup();
return false;
}
window.history.back();
return true;
}
function showPopup() {
$('.popup').addClass('active');
freezeHistory();
}
function hidePopup() {
$('.popup').removeClass('active');
}
$(window).on("popstate", function(e) {
/*
Browsers tend to handle the popstate event differently on page load.
Chrome (prior to v34) and Safari always emit a popstate event on page load,
but Firefox doesn’t.
*/
goBack();
})
If this won't work for You out-of-the box, it is because IMHO You may need to clarify a little bit how do You expect to manage the page history. Feel free to add more detail to Your question if this isn't working as You'd expect now, but anyway, I strongly believe You got the idea and You are able to apply it inside the scenario of Your web-app.
Open popup and try going back and forth with the browser history buttons
$(document).ready(function () {
// manage popup state
var poped = false;
$('.popup-link').click(function () {
// prevent unwanted state changtes
if(!poped){
showPopup();
}
});
$('.popup-close').click(function () {
// prevent unwanted state changtes
if(poped){
hidePopup();
}
});
function showPopup() {
poped = true;
$('.popup').addClass('active');
// push a new state. Also note that this does not trigger onpopstate
window.history.pushState({'poped': poped}, null, '');
}
function hidePopup() {
poped = false;
// go back to previous state. Also note that this does not trigger onpopstate
history.back();
$('.popup').removeClass('active');
}
});
// triggers when browser history is changed via browser
window.onpopstate = function(event) {
// show/hide popup based on poped state
if(event.state && event.state.poped){
$('.popup').addClass('active');
} else {
$('.popup').removeClass('active');
}
};
.popup {
background-color: #ccc;
width: 300px;
height: 300px;
display: none;
}
.popup.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>
<div class="popup">
<button class="popup-close">x</button>
<!-- popup content here -->
</div>
You could add window.history.go(-2) to your popstate. That should take you back twice, which would be your original page before the modal as pushState added an entry to your history object.
Conversely, you could use history.back(2)
Use window.location.href to go 2 pages back and reload
Just run window.history.back(); when closing the popup.
$('.popup-close').click(function() {
hidePopup();
window.history.back();
});
You would have two options to implement this:
Option 1: Using the window.beforeunload event. reference
$('.popup-link').click(function() {
showPopup();
$(window).on("beforeunload", hidePopup);
});
$('.popup-close').click(hidePopup);
function hidePopup() {
$(window).off("beforeunload", hidePopup);
$('.popup').removeClass('active');
}
Demo
Option 2: Using the HTML5 History API. reference
$('.popup-link').click(function() {
showPopup();
window.history.pushState('popup-open', null, '');
$(window).on('popstate', hidePopup);
});
$('.popup-close').click(function() {
if(history.state == 'popup-open') {
window.history.back();
}
hidePopup();
});
function hidePopup() {
$(window).off('popstate', hidePopup);
$('.popup').removeClass('active');
}
Demo
Edit: sujumayas's idea is also pretty good one.
Demo
Further, I'ld recommend to register the popstate / beforeunload events only when necessary and unregister them, when you no longer need 'em in order to avoid overhead.
if anyone use bootstrap with any version you can use this
let popupOpen = false;
//show
$(".popup-link").on('click',(function() {
showPopup();
})
);
// hide
$(".popup-close").on('click',(function() {
window.history.back();
})
);
// on click back button
$(window).on("popstate", function() {
if (popupOpen) {
hidePopup();
}
});
// for bootstrap, if clicked outside the modal or close somehow
$(window).on('hidden.bs.modal', function(e) {
// Make sure is open and the same modal
if (e.target.id=='exampleModal' && popupOpen) {
popupOpen = false;
window.history.back();
}
});
function showPopup() {
// if open back
if (popupOpen) {
window.history.back();
}
popupOpen = true;
// push the browser history
window.history.pushState("forward", null, "#popup");
// you have to use the id
$("#exampleModal").modal('show');
}
function hidePopup() {
popupOpen = false
// you have to use the id to close the modal
$("#exampleModal").modal('hide');
}
Related
I'm trying to make my footer disappear when on a mobile device and only when the keyboard is open. Which I have working perfectly, however the issue is that the footer reappears before the keyboard has time to close. Which is because I'm using the event from the textbox having focus not the keyboard being open. So I thought the best way to resolve this is with a .delay() however, this isn't working at all. Anyone have any ideas here?
<script>
var isMobileView = false; //global variable
$(document).ready(function () {
function setScreenWidthFlag() {
var newWindowWidth = $(window).width();
if ( $(window).width() > 600) {
isMobileView = false;
}
else {
isMobileView = true;
}
}
$(".tbinputArea").focus(function() {
if(isMobileView)
$("#footer").hide();
});
$(".tbinputArea").focusout(function() {
if(isMobileView)
$("#footer").delay(500).show();
});
setScreenWidthFlag();
$(window).on("resize", function (e) {
setScreenWidthFlag();
});
});
</script>
$("#footer").delay(500).show(0);
Try this.
refer this explanation precisely explained the reasons for it http://www.mattlunn.me.uk/blog/2012/06/jquery-delay-not-working-for-you/
Delay is just for queue delay not any event delay so try to add some events within like fadeIn or similar.
I have a jquery-mobile popup #graphic-menu activated by an onClick event (getPosition() is in another included script, and works as expected):
HTML
Graphic menu
CSS
function showGM(pos){
$("#menu-buttons").popup("close");
$("#menu-buttons").bind({
popupafterclose: function(event, ui){
$("#graphic-menu").popup("open", {x:pos.x, y:pos.y});
}
});
}
The catch is that #gm-btn is itself part of a parent popup #menu-buttons that:
is called to appear several times
appears at different locations (it's a dragable element)
showGM(pos) uses the position of the #gm-btn when the parent popup first appears, and doesn't change for subsequent child popups when reclicked.
How can I get showGM(getPosition(this)) to correctly recalculate the position of #gm-btn when called (or, more likely, what have I screwed up in my code)?
Edit: at the moment, I'm making things work by storing the position in a variable with global scope (since there's only ever one #menu-buttons active), and passing that to #graphic-menu so it knows where to open. I think this probably isn't good programming practice, so if someone has a better suggestion I'd love to hear about it.
Based on the API (http://api.jquerymobile.com/popup/), they say:
Note: Chaining of popups not allowed: "The framework does not currently support chaining of popups so it's not possible to embed a
link from one popup to another popup. All links with a
data-rel="popup" inside a popup will not do anything at all."
A workaround to get chained popups working is the use of a timeout for
example in the popupafterclose event bound to the invoking popup. In
the following example, when the first popup is closed, the second will
be opened by a delayed call to the open method:
$( document ).on( "pageinit", function() {
$( ".popupParent" ).on({
popupafterclose: function() {
setTimeout(function() { $( ".popupChild" ).popup( "open" ) }, 100 );
}
});
});
In regards to jsFiddle, it works good for this type of testing: https://jsfiddle.net/Twisty/4gjdp4te/7/ You had not set the JQuery library, so I set it to 2.1.3, and retained your JQM 1.4.5 link.
My attempt so far has not yielded the results you want, but you can at least see what direction to take. I plan to keep working on it and will update my answer.
HTML
<div data-role="page">
<div role="main" class="ui-content">
<a id="anchor1" href="#pop-1" data-rel="popup" data-transition="pop">Basic Popup</a>
<div data-role="popup" id="pop-1" data-position-to="#anchor1">
<p>This is a basic popup.</p>
<button id="firstbutton" data-rel="popup">Button to open 2nd popup</button>
</div>
<div data-role="popup" id="pop-2">
<p>This is another basic popup.</p>
</div>
</div>
</div>
JQUERY
var buttonClick = false;
$(document).on("pageinit", function () {
$("#pop-1").on({
popupafterclose: function () {
if (buttonClick) {
console.log("Opening 2nd Popup.");
setTimeout(function () {
$("#pop-2").popup("open", {
positionTo: "#pop-1"
})
}, 100);
buttonClick = false;
} else {
console.log(buttonClick);
}
}
});
});
$(document).ready(function () {
$("#firstbutton").click(function () {
buttonClick = true;
console.log("First Button clicked");
$("#pop-1").popup("close");
});
});
EDIT
I got the code you need: https://jsfiddle.net/Twisty/4gjdp4te/8/
JQUERY
var buttonClick = false;
$(document).ready(function () {
$("#pop-1").popup({
afterclose: function(){
if (buttonClick) {
console.log("Opening 2nd Popup.");
setTimeout(function () {
$("#pop-2").popup("open", {
positionTo: "#pop-1"
})
}, 100);
buttonClick = false;
} else {
console.log(buttonClick);
}
}
});
$("#firstbutton").click(function () {
buttonClick = true;
console.log("First Button clicked");
$("#pop-1").popup("close");
});
});
My goal is to trigger a pop up function meanwhile the user is going out from my website.
So I want to show a exit popup and in the background show my pop up at the same time.
I already have found different code on internet but no one works well.
Code :
<script type="text/javascript">
function PopUp() { return 'Do you wnat to leave my site?'; }
function UnPopIt() { /* no data */ }
$(document).ready(function() {
window.onbeforeunload = PopUp;
});
</script>
Is it possible to trigger a function like a pop up in the background ?
I am trying this code but it doesn't work :
function PopUp()
{
alert ('Do you wnat to leave my site?'); triggerpopup();
}
1,not very understand your needs,but i can't add a comment right now.
2,suppose you want a selfdefined pop(not another alert),then this goes well
function PopUp() {
triggerpopup();
return 'Do you?';
}
function triggerpopup() {
console.info('called with default pop')
}
$(document).ready(function() {
window.onbeforeunload = PopUp;
});
So, a few users are experiencing their browser window minimizing when they click save on this modal window. For those users, it's consistent, but it's just a small number of users. Most people are using IE9, and everyone that has this problem is using IE9. It happens on the .dialog('close'); call, and it minimizes before it reaches the close function. Does anyone have any ideas?
$("#new-specified").dialog($.extend({}, ns.modalOptions, {
open: function () {
if (ns.disabled) {
$(this).dialog("close");
}
$(this).dialog("option", "title", app.viewModels.MissionViewModel.EditingSpecified() ? "EDIT SPECIFIED TASK" : "NEW SPECIFIED TASK");
$(this).parent().find("button:contains('Cancel')").removeClass().addClass("cancel-button");
$(this).parent().find("button:contains('SAVE')").removeClass().addClass("save-button");
app.viewModels.MissionViewModel.CurrentSpecified().TempDescription(app.functions.htmlUnescape(app.viewModels.MissionViewModel.CurrentSpecified().Description()));
if (app.viewModels.MissionViewModel.SpecifiedTasks().length === 0) {
app.viewModels.MissionViewModel.CurrentSpecified().IsMainEffort(true);
}
},
buttons: {
"Cancel": function() {
$(this).dialog("close");
},
"SAVE": function () {
var newSpecified = app.viewModels.MissionViewModel.CurrentSpecified();
newSpecified.Description(app.functions.htmlEscape(newSpecified.TempDescription()));
newSpecified.Validate();
if (newSpecified.IsInError()) {
return;
}
if (!app.viewModels.MissionViewModel.EditingSpecified()) {
app.viewModels.MissionViewModel.SpecifiedTasks.push(newSpecified);
} else {
app.viewModels.MissionViewModel.OldSpecified().CopyFrom(newSpecified);
newSpecified = app.viewModels.MissionViewModel.OldSpecified();
}
app.viewModels.MissionViewModel.CurrentSpecified(new app.models.SpecifiedTaskViewModel());
var isMainEffort = newSpecified.IsMainEffort();
var index = isMainEffort ? app.viewModels.MissionViewModel.SpecifiedTasks().indexOf(newSpecified) : -1;
app.viewModels.MissionViewModel.VerifyMainEffort(index);
ns.setupSpecifiedModal();
//VV This line below minimizes
$(this).dialog("close");
ns.setupDroppable();
}
},
close: function() {
// We don't reach here before the window minimizes
app.viewModels.MissionViewModel.CurrentSpecified(new app.models.SpecifiedTaskViewModel());
app.viewModels.MissionViewModel.EditingSpecified(false);
app.viewModels.MissionViewModel.VerifyMainEffort(-1);
ns.saveMissionToServer();
}
}));
This question might have the solution: Dynamically loading jQuery mobile causes IE to minimize
Seems like calling blur() forces the IE window to the back of the stack. If you're using jQuery Mobile, here is the related issue: https://github.com/jquery/jquery-mobile/issues/2057
If you're not using jQuery Mobile, look for calls to blur() in your code.
This was also found in jquery-UI 1.10.0: http://bugs.jqueryui.com/ticket/9420.
As first comment suggest, the cause is that blur() is called on document.body.
As a workaround you can override body.blur(), look at How do I disable body.blur() in IE8?
Part of the page I'm developing requires a $(window).resize event to be added to a div when a user clicks a button, in order to toggle between resizing it with the window and leaving it fixed at its original size:
function startResize() {
$(window).resize(function() {
$("#content").width(newWidth);
$("#content").height(newHeight);
});
}
What I can't work out is how to "turn off" this event when the button is clicked again, so that the content stops resizing.
function endResize() {
// Code to end $(window).resize function
$("#content").width(originalWidth);
$("#content").height(originalHeight);
}
Any help with this would be greatly appreciated.
function endResize() {
$(window).off("resize");
$("#content").width(originalWidth);
$("#content").height(originalHeight);
}
Note that this is extremely obtrusive and might break other code.
This is better way:
function resizer() {
$("#content").width(newWidth);
$("#content").height(newHeight);
}
function startResize() {
$(window).resize(resizer);
}
function endResize() {
$(window).off("resize", resizer);
}
function startResize() {
$(window).on("resize.mymethod",(function() {
$("#content").width(newWidth);
$("#content").height(newHeight);
}));
}
function endResize() {
$(window).off("resize.mymethod");
}
using a namespace on the query method will allow to to turn off the resize event for you method only.