I have the following code that shows an ajax content for each element for my page.
function details_in_popup(link, div_id){
$.ajax({
url: link,
success: function(response){
$('#'+div_id).empty().html(response);
}
});
return '<div id="'+ div_id +'">Loading...</div>';
}
$(function () {
$('[data-toggle="popover"]').popover({
"html": true,
"title": '<span class="text-info"><strong>Quick View</strong></span>' +
'<button type="button" id="close" class="close" >×</button>',
"content": function () {
var div_id = $(this).data('id');
return details_in_popup($(this).data('url'), div_id);
}
}).on('shown.bs.popover', function (e) {
var popover = jQuery(this);
$('body').on('click', '.close', function (e) {
//popover.popover('hide');
$(".popover").remove();
$(this).data('id').remove();
});
});
});
And in the html i have :
<button data-url="<%= my_url %>" href="#" type="button" class="" data-container="body" data-toggle="popover" data-id="<%= product.slug %>" style="">Popover</button>
This code does the trick and shows the popover with the correct content, in the sense that the first time the popover opens. I have the normal behavour
But starting from the second time, i have 2 popovers one on top of the other, One with loading message, and the other with the content. Also the button of the loading popover is the one that can close both popovers.
First time popover:
Second time popover:
Do you have any idea on how could i get ride of the second loading popover and bind the close button the the popover that have the content ?
Thank you very much and i hope that i was clear in my explanation
I tried your html code. I think you need to add data content as well. data-content="your text here". Rest seems to be fine. And for close functionality just add data-trigger = "focus". click here http://www.bootply.com/ZkPQGSAkbq
If you need a close button here is an example. This might help you figure out. [][1]
[1]: http://jsfiddle.net/erik1337/fvE22/
I want to close pop up on click of back button for mobile. I implemented this using onhashchange:
window.onhashchange = function (event) {
};
In this case, if pop up is opened multiple times then on click of back button, it opens and closes the modal pop up. But, I want modal pop up to close on first back and navigate to prev page on next back.
I also tried using onbeforeunload, but it will show another alert to leave or stay on the page.
$(window).bind('beforeunload', function(e) {
return false;
});
What is the best way to close the pop up on back button and redirect to prev page on next back?
if (window.history && window.history.pushState) {
$('#myModal').on('show.bs.modal', function (e) {
window.history.pushState('forward', null, './#modal');
});
$(window).on('popstate', function () {
$('#myModal').modal('hide');
});
}
bootply.com was down when I was testing my answer. See the inline script and comments at the bottom of the code below. The rest is just Twitter Bootstrap boilerplate so that I could easily test it locally.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>modal.html</title>
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<p>If you press the back button now, you should return to whatever page you were on before this page.</p>
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">Show me the modal!</button>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
<p>If you press the web browser's back button OR the modal's close buttons, the modal will close and the hash will return to "modal.html#modalClosed".</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
// Immutable hash state identifiers.
var closedModalHashStateId = "#modalClosed";
var openModalHashStateId = "#modalOpen";
/* Updating the hash state creates a new entry
* in the web browser's history. The latest entry in the web browser's
* history is "modal.html#modalClosed". */
window.location.hash = closedModalHashStateId;
/* The latest entry in the web browser's history is now "modal.html#modalOpen".
* The entry before this is "modal.html#modalClosed". */
$('#myModal').on('show.bs.modal', function(e) {
window.location.hash = openModalHashStateId;
});
/* When the user closes the modal using the Twitter Bootstrap UI,
* we just return to the previous entry in the web
* browser's history, which is "modal.html#modalClosed". This is the same thing
* that happens when the user clicks the web browser's back button. */
$('#myModal').on('hide.bs.modal', function(e) {
window.history.back();
});
</script>
</body>
</html>
This is my solution for bootstrap modals. It adds support closing with back button to all bootstrap modals. You can adapt it for your non-bootstrap popups.
//Modal Closer With Back Button Support (Uses EventDelegation, so it works for ajax loaded content too.)
(function() {
var activeOpenedModalId = null;
var isHidingModalByPopState = false;
$(document).on('show.bs.modal', '.modal', function() {
activeOpenedModalId = $(this).attr('id');
window.location.hash = activeOpenedModalId;
}).on('hide.bs.modal', '.modal', function() {
if(!isHidingModalByPopState) {
window.history.back();
}
isHidingModalByPopState = false;
activeOpenedModalId = null;
});
$(window).on('popstate', function() {
if(activeOpenedModalId && window.location.hash !== '#'+activeOpenedModalId) {
isHidingModalByPopState = true;
$("#" + activeOpenedModalId).modal('hide');
}
});
})();
I write this code for my own website
and tested too many times with different devices and browsers
Chromium 71 , Chrome 67 , FireFox 65 , Android 4.1 , Android 4.2 , Android 7.1
window.onload=function(){
State=0;
$(".modal").on("show.bs.modal",function(){
path=window.location.pathname+window.location.search;
history.pushState("hide",null,path);
history.pushState("show",null,path);
State="show";
})
.on("hidden.bs.modal",function(){
if(!!State)
history.go(State=="hide"?-1:-2);
});
setTimeout(function(){// fix old webkit bug
window.onpopstate=function(e){
State=e.state;
if(e.state=="hide"){
$(".modal").modal("hide");
}
};
},999);
$("#myModal").modal("show");
};
dont use $(document).ready instead of window.onload
This could be done easily using Apache Cordova but not sure if you are using it to show your page in webview.
function onBackKeyDown(e) {
e.preventDefault();
}
document.addEventListener("backbutton", onBackKeyDown, false);
http://cordova.apache.org/docs/en/2.4.0/cordova_events_events.md.html#backbutton
according to http://www.mylearning.in/2015/06/close-modal-pop-up-on-back-button.html
$('#myModal').on('show.bs.modal', function(e) {
window.location.hash = "modal";
});
$(window).on('hashchange', function (event) {
if(window.location.hash != "#modal") {
$('#myModal').modal('hide');
}
});
By clicking back, automatically $('.modal').hide() function get activated.
So no need to hide modal. We can see grey shaded background after back button.You can use either of these line of code to close modal pop up.
$('.modal' ).modal( 'hide' ).data( 'bs.modal', null ); [work on bootstrap 3]
Or
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
Inspect the page when modal is active you can see these classes.
Do correct me if this method is wrong or other simple way exist.
Just add this code to script:
//update url to current url + #modal-open. example: https://your-url.test/home#modal-open
$('body').on('shown.bs.modal', '.modal', function () {
location.hash = '#modal-open'
})
//remove #modal-open from current url, so the url back to: https://yoururl.test/home
$('body').on('hidden.bs.modal', '.modal', function () {
location.hash = ''
})
//when user press back button
$(window).on('hashchange', function (e) {
if(location.hash == ''){
$('.modal').modal('hide')
}
})
and the above code works perfectly even though the modal is opened and closed several times.
*note:
jQuery 3.^
Bootstrap 4.^
My Solution in Angular
// push history state when a dialog is opened
dialogRef.afterOpened.subscribe((ref: MatDialogRef<any, any>) => {
window.history.pushState(ref.id, '');
// pop from history if dialog has not been closed with back button, and gurrent state is still ref.id
ref.afterClosed().subscribe(() => {
if (history.state === ref.id) {
window.history.go(-1);
}
});
});
Issue : When a modal is open and the user clicks browser's back button, the page navigates (backwards or forward) but the modal remains open.
Solution :
In Javascript :
$(window).on('popstate', function() {
$('.modal').click();
});
In Angular :
ngAfterViewInit() {
$(window).on('popstate', function() {
$('.modal').click();
});}
I don't like hash. And this code without hash in url
onModalMounted() => {
if (isMobile) {
history.pushState('modalShow', "", path); // add history point
window.onpopstate = (e) => {
e.stopPropagation()
e.preventDefault()
closeModalFn() // your func close modal
history.replaceState('', "", path);
window.onpopstate = () => {} // stop event listener window.onpopstate
}
} else {
window.onpopstate = (e) => {
e.stopPropagation()
e.preventDefault()
closeModalFn() // your func close modal
window.onpopstate = () => {} // stop event listener window.onpopstate
}
}
}
I'll did it like this :
// 2.0 and above
#Override
public void onBackPressed(evt) {
evt.preventDefault();
closeTab();
}
// Before 2.0
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
evt.preventDefault();
closeTab();
return true;
}
return super.onKeyDown(keyCode, event);
}
--> These are handlers btw, need addEventListener =)
I've done it by memory, i'll check it later when i find it in my 'code mess' folder
I have bootstrap modal window which opens on button click. Everything works fine except one thing : when i click on outmodal space - modal window become closed but i can open it again on button click. If i close modal on button close - it works well.
Update: when i close modal using 'Esc' keyboard - behaviour is the same as for outmodal click.
HTML
<button data-bind="click: function () { $root.showLogModal(); }" title="Show Logs" class="btn btn-large btn-info">Show Logs</button>
<div data-bind="bootstrapLogModal: logModal" tabindex="-1" role="dialog"></div>
Custom Template
<script id="showLogModal" type="text/html">
<div class="modal-header">
<button type="button" class="close" data-bind="click: close" aria-hidden="true">×</button>
<h3>Logs</h3>
</div>
<div class="modal-body">
<div class="alert alert-info">
Some Content
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-bind="click: close">Close</button>
</div>
JS
function ViewModel() {
var self = this;
self.logModal = {
show: ko.observable(false),
onClose: function () {
},
onAction: function () {
}
};
self.showLogModal = function () {
self.logModal.show(true);
};
}
$(function () {
var viewModel = new ViewModel();
ko.bindingHandlers.bootstrapLogModal = {
init: function (element, valueAccessor, allBindingsAccessor, data, bindingContext) {
var props = valueAccessor(),
vm = bindingContext.createChildContext(data);
ko.utils.extend(vm, props);
vm.close = function () {
vm.show(false);
vm.onClose();
};
vm.action = function () {
vm.onAction();
};
ko.utils.toggleDomNodeCssClass(element, "modal hide fade large", true);
ko.renderTemplate("showLogModal", vm, null, element);
var showHide = ko.computed(function () {
$(element).modal(vm.show() ? 'show' : 'hide');
});
return {
controlsDescendantBindings: true
};
}
};
ko.applyBindings(viewModel);
});
http://jsfiddle.net/tLT6d/ here is Live example.
It's expected behavior, if you want to prevent the modal closing when outside area is click, provide backdrop attribute as 'static'.
Includes a modal-backdrop element. Alternatively, specify static for a backdrop which doesn't close the modal on click.
update
I don't know why you rewrite the bootstrap modal into knockout, but to make you code works without closing the modal when outside area is clicked.
just add this line of code in your binding handler
ko.renderTemplate("showLogModal", vm, null, element);
// adds new code
$(element).modal({ backdrop: 'static', show: false });
var showHide = ko.computed(function () {
$(element).modal(vm.show() ? 'show' : 'hide');
});
update 2
To fix your initial code to perform proper closing, when outside area is clicked, attach hidden event handler and call the related close method.
// adds new code
$(element).on("hidden.bs.modal", function(){
vm.close();
});
var showHide = ko.computed(function () {
$(element).modal(vm.show() ? 'show' : 'hide');
});
I am creating a Bootstrap 2.3.1 modal as follows:
myModal = $('<div/>', {
'class': 'modal hide',
'id': id + '-addModal',
'tabindex': -1, // needed for escape to work...
'role': 'dialog',
'data-backdrop': 'static'
}).append(content);
// insert Modal into DOM...
$(jqElement).after(myModal);
// focus on first input when it pops up...
myModal.on('shown', function () {
myModal.find('select:first').focus();
});
// in response to button click...
myModal.modal('show');
On rare occasions, the backdrop shows, but no modal is displayed. Has anyone encountered a similar problem and a workaround? I am aware IE8 does not like animated modals (use of fade class) and this doesn't appear to be the same issue as we don't use fade. The issue appears in FF, Chrome and IE, but like the Spanish Inquisition, never when I'm expecting it.
The failure appears to be within the modal('show') execution. It seems that the modal exists but is not unhidden. I believe this should be achieved by adding the in class to the modal. The show and shown events do occur however. From looking at the bootstrap code, the fact that the shown event occurs means that the event is not prevented from default behaviour.
Note This is a question similar to one I posted earlier, but I have added some more information concerning how it fails.
Please also note that I cannot update to Bootstrap 3. I am responsible for making small changes to an already released product and a change of basic libraries is a non-starter.
I've modified the code and appended to the body instead of the unknown jqElement specified in your example. I've also added some example place holder content. See the following JS Fiddle for a working example http://jsfiddle.net/kYVtf/5/
var id = 'test',
content = '<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h3 id="myModalLabel">Modal header</h3></div><div class="modal-body"><p><select><option>TEST</option></select></p></div> <div class="modal-footer"> <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button> </div>';
var myModal = $('<div/>', {
'class': 'modal hide fade',
'id': id + '-addModal',
'tabindex': -1, // needed for escape to work...
'role': 'dialog',
'data-backdrop': 'static'
}).html(content);
// insert Modal into DOM...
$('body').append(myModal);
// focus on first input when it pops up...
myModal.on('shown', function () {
myModal.find('select:first').focus();
});
I found the following issues helped:
a) The 'shown' action of the modal checks for a display:block attribute and forces it to be set.
b) the close button (which needed to do validation) was set to a click event - changing this to a delegated event made it work reliably
c) both the cancel buttons were mapped to the modal-dismiss action.
myModal.on('show', function (event) {
self._debug("show modal");
// show add form - should be a modal
myModal.find('form')[0].reset();
myModal.find('.alerts').empty();
self._debug('show end');
return true;
});
myModal.on('shown', function () {
var $el = $('#myModal');
if ($el.css('display') == 'none') {
self._debug(" WARNING! modal css error");
}
self._debug("fix for bootstrap error");
$el.css('display', 'block');
myModal.find('select:first').focus();
self._debug('Shown modal');
return true;
});
myModal.on('hide', function () {
self._debug('Hide modal');
return true;
});
myModal.on('hidden', function () {
var $el = $('#myModal');
$el.css('display', 'none');
self._debug('Hidden modal');
return true;
});
This behaviour started happening for me after I added the following to prevent unhandled modal closure.
$('.modal').modal({
backdrop: 'static',
keyboard: false
});
I fixed it by adding show: false to the modal options and making sure there was no hide class in <div class="modal fade"
I am using jquery-ui tabs and dialog functionality.
Each tab has a button on the page which opens a dialog. This works for one of the tabs. However if I go the second tab, the button does not work there. When I come back to the first tab, the dialog does show up but the problem is I notice as I make switches back and forth to the first tab, it keeps on inserting new div's while the old div's have display:none set on them.
I am doing this using JSP. This is how the reusable jsp looks like:
<script>
$(function() {
var formData = null;
$.ajax({
url : "addFormGenerator.html",
success : function(data) {
formData = data;
$("#addFormDialog").html(data);
$("#addFormDialog").dialog({
autoOpen : false,
height : 300,
width : 350,
modal : true,
buttons : {
"Add" : function() {
$(this).dialog("close");
},
Cancel : function() {
$(this).dialog("close");
}
},
close : function() {
}
});
}
});
$("#addButton").button().click(function() {
$("#addFormDialog").html(formData);
$("#addFormDialog").dialog("open");
});
});
</script>
<button id="addButton">Click here to Add New</button>
<div id="addFormDialog" title="Add New"></div>
This jsp fragment is included in other jsp pages as well.
I was assuming as I switch between tabs the old button will be garbage collected.
Can you help me understand the problem and fix it?
You need not render the following part from your jsp's response
<div class="addFormDialog" title="Add New"></div>
$("#addButton").button().click(function() {
$("#addFormDialog").html(formData);
$("#addFormDialog").dialog("open");
});
Just have the following, ideally with class names and not duplicate id's
<button class="addButton">Click here to Add New</button>
UPDATE:
I still don't think you need unique id's -
<div id="tabs-container">
<!-- tabs here -- >
<-- let's say this is tab#1 -->
<button class="addButton">Click here to Add New</button>
<div class="addFormDialog" title="Add New"></div>
<!-- tab1 -->
</div>
$('#tabs-container').on('click' , '.addButton', function(){
var dialogContent = $(this).siblings('.addFormDialog');
//now call .dialog({..}); or whatever you need
});
This way you're binding just one click handler that listens to any click that bubbles up from a .addButton and then searches for its sibling .addFormDialog. (I hope I'm not sounding too confusing)