I'm using Infinite Ajax Scroll for pagination on my blog. When there are no more posts left to load, I want to hide the trigger (the buttons) parent container (currently, it just has opacity: 0, but this leaves unwanted whitespace).
In the console, I can see that IAS leaves a message saying "No more pages left to load", so I know there is a method in place to check if more posts exist. But, having applied two methods, I cannot get it to work.
Method 1: Using last:function()
Method 2: Checking if the trigger has opacity: 0, then hiding parent container if so
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/#webcreate/infinite-ajax-scroll#3.0.0-beta.6/dist/infinite-ajax-scroll.min.js"></script>
<div class="container pagination-hide">
<div class="row">
<div class="col-12">
<div class="pagination">
<a class="loadmore">Load more</a>
</div>
</div>
</div>
</div>
<script>
$(function() {
var ias = new InfiniteAjaxScroll('.insertPosts', {
item: '.insertCard',
pagination: '.blog-pagination',
next: '.next-posts-link',
trigger: '.loadmore',
loadOnScroll: false,
last:function(){
$(".pagination-hide").addClass("d-none");
}
});
// $('.loadmore').click(function(){
// if ( $(this).css('opacity') == '0' ) {
// console.log("true");
// $(this).parent(".pagination-hide").addClass("d-none");
// }
// });
});
</script>
Have also tried the following, as per IAS docs, however, this just adds the d-none class to pagination-hide on page load, rather than adding the class (as it should) if there are no more posts to load.
trigger: {
element: '.loadmore',
// this function is called when the button has to be hidden
hide: function(element) {
$(element).closest(".pagination-hide").addClass("d-none");
element.style.opacity = '0'; // default behaviour
}
},
Seems like you would also need to add a show() method that un-does the changes in hide(), in order to get the correct behavior:
trigger: {
element: '.loadmore',
// this function is called when the button has to be hidden
hide: function(element) {
$(element).closest(".pagination-hide").addClass("d-none");
element.style.opacity = '0'; // default behaviour
},
show: function(element) {
$(element).closest(".pagination-hide").removeClass("d-none");
element.style.opacity = '1';
}
},
Sorry, but you went on a bad road. You shoud show button <a class="loadmore">Load more</a> if you have some other conten unstead of hiding unnecessary. It's wrong in root. You are calling unnecessary operations in the DOM render. You better rewrite your code.
AFAICT you were on the right track with your first attempt - the last event seems like exaclty the right way to do what you need. But the docs also show that you need to bind event handlers with .on(), not pass them as options, which is what you tried.
For example, something like this:
var ias = new InfiniteAjaxScroll('.insertPosts', {
// ... your options
// last:function(){} // <-- won't work, not the way to bind event handlers
});
// What we want to happen when we've hit the last page
function noMorePages() {
$(".pagination-hide").addClass("d-none");
}
// Handle the "last" event with our function
ias.on('last', noMorePages);
There is a similar example in the docs.
You simply need to provide show and hide functions for the trigger ref. The library calls the functions automatically on last event.
Demo website https://zyf5k.csb.app/
Codesandbox https://codesandbox.io/s/zen-volhard-zyf5k?file=/index.js
Code for ready reference:
window.ias = new InfiniteAjaxScroll(".container", {
item: ".item",
next: nextHandler,
trigger: {
element: ".loadmore",
show: function (element) {
element.parentElement.style.display = "block";
},
hide: function (element) {
//hide desired element`
element.parentElement.style.display = "none";
}
}
});
Note: Didn't realize #Kevin had already answered this. Posting the answer for extra info.
Can we get popovers to be dismissable in the same way as modals, ie. make them close when user clicks somewhere outside of them?
Unfortunately I can't just use real modal instead of popover, because modal means position:fixed and that would be no popover anymore. :(
Update: A slightly more robust solution: http://jsfiddle.net/mattdlockyer/C5GBU/72/
For buttons containing text only:
$('body').on('click', function (e) {
//did not click a popover toggle or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
For buttons containing icons use (this code has a bug in Bootstrap 3.3.6, see the fix below in this answer)
$('body').on('click', function (e) {
//did not click a popover toggle, or icon in popover toggle, or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('[data-toggle="popover"]').length === 0
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
For JS Generated Popovers Use '[data-original-title]' in place of '[data-toggle="popover"]'
Caveat: The solution above allows multiple popovers to be open at once.
One popover at a time please:
Update: Bootstrap 3.0.x, see code or fiddle http://jsfiddle.net/mattdlockyer/C5GBU/2/
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
This handles closing of popovers already open and not clicked on or their links have not been clicked.
Update: Bootstrap 3.3.6, see fiddle
Fixes issue where after closing, takes 2 clicks to re-open
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
(($(this).popover('hide').data('bs.popover')||{}).inState||{}).click = false // fix for BS 3.3.6
}
});
});
Update: Using the conditional of the previous improvement, this solution was achieved. Fix the problem of double click and ghost popover:
$(document).on("shown.bs.popover",'[data-toggle="popover"]', function(){
$(this).attr('someattr','1');
});
$(document).on("hidden.bs.popover",'[data-toggle="popover"]', function(){
$(this).attr('someattr','0');
});
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
if($(this).attr('someattr')=="1"){
$(this).popover("toggle");
}
}
});
});
$('html').on('mouseup', function(e) {
if(!$(e.target).closest('.popover').length) {
$('.popover').each(function(){
$(this.previousSibling).popover('hide');
});
}
});
This closes all popovers if you click anywhere except on a popover
UPDATE for Bootstrap 4.1
$("html").on("mouseup", function (e) {
var l = $(e.target);
if (l[0].className.indexOf("popover") == -1) {
$(".popover").each(function () {
$(this).popover("hide");
});
}
});
Most simple, most fail safe version, works with any bootstrap version.
Demo:
http://jsfiddle.net/guya/24mmM/
Demo 2: Not dismissing when clicking inside the popover content
http://jsfiddle.net/guya/fjZja/
Demo 3: Multiple popovers:
http://jsfiddle.net/guya/6YCjW/
Simply calling this line will dismiss all popovers:
$('[data-original-title]').popover('hide');
Dismiss all popovers when clicking outside with this code:
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined') {
$('[data-original-title]').popover('hide');
}
});
The snippet above attach a click event on the body.
When the user click on a popover, it'll behave as normal.
When the user click on something that is not a popover it'll close all popovers.
It'll also work with popovers that are initiated with Javascript, as opposed to some other examples that will not work. (see the demo)
If you don't want to dismiss when clicking inside the popover content, use this code (see link to 2nd demo):
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
$('[data-original-title]').popover('hide');
}
});
With bootstrap 2.3.2 you can set the trigger to 'focus' and it just works:
$('#el').popover({trigger:'focus'});
None of supposed high-voted solutions worked for me correctly.
Each leads to a bug when after opening and closing (by clicking on other elements) the popover for the first time, it doesn't open again, until you make two clicks on the triggering link instead of one.
So i modified it slightly:
$(document).on('click', function (e) {
var
$popover,
$target = $(e.target);
//do nothing if there was a click on popover content
if ($target.hasClass('popover') || $target.closest('.popover').length) {
return;
}
$('[data-toggle="popover"]').each(function () {
$popover = $(this);
if (!$popover.is(e.target) &&
$popover.has(e.target).length === 0 &&
$('.popover').has(e.target).length === 0)
{
$popover.popover('hide');
} else {
//fixes issue described above
$popover.popover('toggle');
}
});
})
This is basically not very complex, but there is some checking to do to avoid glitches.
Demo (jsfiddle)
var $poped = $('someselector');
// Trigger for the popover
$poped.each(function() {
var $this = $(this);
$this.on('hover',function() {
var popover = $this.data('popover');
var shown = popover && popover.tip().is(':visible');
if(shown) return; // Avoids flashing
$this.popover('show');
});
});
// Trigger for the hiding
$('html').on('click.popover.data-api',function() {
$poped.popover('hide');
});
I made a jsfiddle to show you how to do it:
http://jsfiddle.net/3yHTH/
The idea is to show the popover when you click the button and to hide the popover when you click outside the button.
HTML
<a id="button" href="#" class="btn btn-danger">Click for popover</a>
JS
$('#button').popover({
trigger: 'manual',
position: 'bottom',
title: 'Example',
content: 'Popover example for SO'
}).click(function(evt) {
evt.stopPropagation();
$(this).popover('show');
});
$('html').click(function() {
$('#button').popover('hide');
});
simply add this attribute with the element
data-trigger="focus"
Just add this attribute to html element to close popover in next click.
data-trigger="focus"
reference from https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click
According to http://getbootstrap.com/javascript/#popovers,
<button type="button" class="popover-dismiss" data-toggle="popover" title="Dismissible popover" data-content="Popover Content">Dismissible popover</button>
Use the focus trigger to dismiss popovers on the next click that the user makes.
$('.popover-dismiss').popover({
trigger: 'focus'
})
Bootstrap 5 UPDATE:
$(document).on('click', function (e) {
var
$popover,
$target = $(e.target);
//do nothing if there was a click on popover content
if ($target.hasClass('popover') || $target.closest('.popover').length) {
return;
}
$('[data-bs-toggle="popover"]').each(function () {
$popover = $(this);
if (!$popover.is(e.target) &&
$popover.has(e.target).length === 0 &&
$('.popover').has(e.target).length === 0)
{
$popover.popover('hide');
}
});
})
This has been asked before here. The same answer I gave then still applies:
I had a similar need, and found this great little extension of the Twitter Bootstrap Popover by Lee Carmichael, called BootstrapX - clickover. He also has some usage examples here. Basically it will change the popover into an interactive component which will close when you click elsewhere on the page, or on a close button within the popover. This will also allow multiple popovers open at once and a bunch of other nice features.
This is late to the party... but I thought I'd share it.
I love the popover but it has so little built-in functionality. I wrote a bootstrap extension .bubble() that is everything I'd like popover to be. Four ways to dismiss. Click outside, toggle on the link, click the X, and hit escape.
It positions automatically so it never goes off the page.
https://github.com/Itumac/bootstrap-bubble
This is not a gratuitous self promo...I've grabbed other people's code so many times in my life, I wanted to offer my own efforts. Give it a whirl and see if it works for you.
Modified accepted solution. What I've experienced was that after some popovers were hidden, they would have to be clicked twice to show up again. Here's what I did to ensure that popover('hide') wasn't being called on already hidden popovers.
$('body').on('click', function (e) {
$('[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
var popoverElement = $(this).data('bs.popover').tip();
var popoverWasVisible = popoverElement.is(':visible');
if (popoverWasVisible) {
$(this).popover('hide');
$(this).click(); // double clicking required to reshow the popover if it was open, so perform one click now
}
}
});
});
This solution works fine :
$("body") .on('click' ,'[data-toggle="popover"]', function(e) {
e.stopPropagation();
});
$("body") .on('click' ,'.popover' , function(e) {
e.stopPropagation();
});
$("body") .on('click' , function(e) {
$('[data-toggle="popover"]').popover('hide');
});
For anyone looking for a solution that works with Bootstrap 5 and no jQuery, even when the popovers are dynamically generated (ie manually triggered):
document.querySelector('body').addEventListener('click', function(e) {
var in_popover = e.target.closest(".popover");
if (!in_popover) {
var popovers = document.querySelectorAll('.popover.show');
if (popovers[0]) {
var triggler_selector = `[aria-describedby=${popovers[0].id}]`;
if (!e.target.closest(triggler_selector)) {
let the_trigger = document.querySelector(triggler_selector);
if (the_trigger) {
bootstrap.Popover.getInstance(the_trigger).hide();
}
}
}
}
});
jQuery("#menu").click(function(){ return false; });
jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); });
You can also use event bubbling to remove the popup from the DOM. It is a bit dirty, but works fine.
$('body').on('click touchstart', '.popover-close', function(e) {
return $(this).parents('.popover').remove();
});
In your html add the .popover-close class to the content inside the popover that should close the popover.
It seems the 'hide' method does not work if you create the popover with selector delegation, instead 'destroy' must be used.
I made it work like that:
$('body').popover({
selector: '[data-toggle="popover"]'
});
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('destroy');
}
});
});
JSfiddle here
We found out we had an issue with the solution from #mattdlockyer (thanks for the solution!). When using the selector property for the popover constructor like this...
$(document.body').popover({selector: '[data-toggle=popover]'});
...the proposed solution for BS3 won't work. Instead it creates a second popover instance local to its $(this). Here is our solution to prevent that:
$(document.body).on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
var bsPopover = $(this).data('bs.popover'); // Here's where the magic happens
if (bsPopover) bsPopover.hide();
}
});
});
As mentioned the $(this).popover('hide'); will create a second instance due to the delegated listener. The solution provided only hides popovers which are already instanciated.
I hope I could save you guys some time.
Bootstrap natively supports this:
JS Bin Demo
Specific markup required for dismiss-on-next-click
For proper cross-browser and cross-platform behavior, you must use the <a> tag, not the <button> tag, and you also must include the role="button" and tabindex attributes.
this solution gets rid of the pesky 2nd click when showing the popover for the second time
tested with with Bootstrap v3.3.7
$('body').on('click', function (e) {
$('.popover').each(function () {
var popover = $(this).data('bs.popover');
if (!popover.$element.is(e.target)) {
popover.inState.click = false;
popover.hide();
}
});
});
I've tried many of the previous answers, really nothing works for me but this solution did:
https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click
They recommend to use anchor tag not button and take care of role="button" + data-trigger="focus" + tabindex="0" attributes.
Ex:
<a tabindex="0" class="btn btn-lg btn-danger" role="button" data-toggle="popover"
data-trigger="focus" title="Dismissible popover" data-content="amazing content">
Dismissible popover</a>
I came up with this:
My scenario included more popovers on the same page, and hiding them just made them invisible and because of that, clicking on items behind the popover was not possible.
The idea is to mark the specific popover-link as 'active' and then you can simply 'toggle' the active popover. Doing so will close the popover completely
$('.popover-link').popover({ html : true, container: 'body' })
$('.popover-link').popover().on 'shown.bs.popover', ->
$(this).addClass('toggled')
$('.popover-link').popover().on 'hidden.bs.popover', ->
$(this).removeClass('toggled')
$("body").on "click", (e) ->
$openedPopoverLink = $(".popover-link.toggled")
if $openedPopoverLink.has(e.target).length == 0
$openedPopoverLink.popover "toggle"
$openedPopoverLink.removeClass "toggled"
I just remove other active popovers before the new popover is shown (bootstrap 3):
$(".my-popover").popover();
$(".my-popover").on('show.bs.popover',function () {
$('.popover.in').remove();
});
The answer from #guya works, unless you have something like a datepicker or timepicker in the popover. To fix that, this is what I have done.
if (typeof $(e.target).data('original-title') === 'undefined' &&
!$(e.target).parents().is('.popover.in')) {
var x = $(this).parents().context;
if(!$(x).hasClass("datepicker") && !$(x).hasClass("ui-timepicker-wrapper")){
$('[data-original-title]').popover('hide');
}
}
tested with 3.3.6 and second click is ok
$('[data-toggle="popover"]').popover()
.click(function () {
$(this).popover('toggle');
});;
$(document).on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
demo: http://jsfiddle.net/nessajtr/yxpM5/1/
var clickOver = clickOver || {};
clickOver.uniqueId = $.now();
clickOver.ClickOver = function (selector, options) {
var self = this;
//default values
var isVisible, clickedAway = false;
var callbackMethod = options.content;
var uniqueDiv = document.createElement("div");
var divId = uniqueDiv.id = ++clickOver.uniqueId;
uniqueDiv.innerHTML = options.loadingContent();
options.trigger = 'manual';
options.animation = false;
options.content = uniqueDiv;
self.onClose = function () {
$("#" + divId).html(options.loadingContent());
$(selector).popover('hide')
isVisible = clickedAway = false;
};
self.onCallback = function (result) {
$("#" + divId).html(result);
};
$(selector).popover(options);
//events
$(selector).bind("click", function (e) {
$(selector).filter(function (f) {
return $(selector)[f] != e.target;
}).popover('hide');
$(selector).popover("show");
callbackMethod(self.onCallback);
isVisible = !(clickedAway = false);
});
$(document).bind("click", function (e) {
if (isVisible && clickedAway && $(e.target).parents(".popover").length == 0) {
self.onClose();
isVisible = clickedAway = false;
} else clickedAway = true;
});
}
this is my solution for it.
This approach ensures that you can close a popover by clicking anywhere on the page. If you click on another clickable entity, it hides all other popovers. The animation:false is required else you will get a jquery .remove error in your console.
$('.clickable').popover({
trigger: 'manual',
animation: false
}).click (evt) ->
$('.clickable').popover('hide')
evt.stopPropagation()
$(this).popover('show')
$('html').on 'click', (evt) ->
$('.clickable').popover('hide')
Ok this is my first attempt at actually answering something on stackoverflow so here goes nothing :P
It appears that it isn't quite clear that this functionality actually works out of the box on the latest bootstrap (well, if you're willing to compromise where the user can click. I'm not sure if you have to put 'click hover' per-se but on an iPad, click works as a toggle.
The end result is, on a desktop you can hover or click (most users will hover). On a touch device, touching the element will bring it up, and touching it again will take it down. Of course, this is a slight compromise from your original requirement but at least your code is now cleaner :)
$(".my-popover").popover({
trigger: 'click hover'
});
I'm trying to hide the Bootstrap Popover when the user clicks anywhere outside the popover. (I'm really not sure why the creators of Bootstrap decided not to provide this functionality.)
I found the following code on the web but I really don't understand it.
// Hide popover on click anywhere on the document except itself
$(document).click(function(e) {
// Check for click on the popup itself
$('.popover').click(function() {
return false; // Do nothing
});
// Clicking on document other than popup then hide the popup
$('.pop').popover('hide');
});
The main thing I find confusing is the line $('.popover').click(function() { return false; });. Doesn't this line add an event handler for the click event? How does that prevent the call to popover('hide') that follows from hiding the popover?
And has anyone seen a better technique?
Note: I know variations of this question has been asked here before, but the answers to those questions involve code more complex than the code above. So my question is really about the code above
I made http://jsfiddle.net/BcczZ/2/, which hopefully answers your question
Example HTML
<div class="well>
<a class="btn" data-toggle="popover" data-content="content.">Popover</a>
<a class="btn btn-danger bad">Bad button</a>
</div>
JS
var $popover = $('[data-toggle=popover]').popover();
//first event handler for bad button
$('.bad').click(function () {
alert("clicked");
});
$(document).on("click", function (e) {
var $target = $(e.target),
var isPopover = $target.is('[data-toggle=popover]'),
inPopover = $target.closest('.popover').length > 0
//Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT
$('.bad').click(function () {
console.log('clicked');
return false;
});
//hide only if clicked on button or inside popover
if (!isPopover && !inPopover) $popover.popover('hide');
});
As I mentioned in my comment, event handlers don't get overwritten, they just stack. Since there is already an event handler on the .bad button, it will be fired, along with any other event handler
Open your console in the jsfiddle, press 5 times somewhere on the page (not the popover button) and then click bad button you should see clicked printed the same amount of times you pressed
Hope it helps
P.S:
If you think about it, you already saw this happening, especially in jQuery.
Think of all the $(document).ready(...) that exist in a page using multiple jquery plugins. That line just registers an event handler on the document's ready event
I just did a more event based solution.
var $toggle = $('.your-popover-button');
$toggle.popover();
var hidePopover = function() {
$toggle.popover('hide');
};
$toggle.on('shown', function () {
var $popover = $toggle.next();
$popover.on('mousedown', function(e) {
e.stopPropagation();
});
$toggle.on('mousedown', function(e) {
e.stopPropagation();
});
$(document).on('mousedown',hidePopover);
});
$toggle.on('hidden', function () {
$(document).off('mousedown', hidePopover);
});
short answer
insert this to bootstrap min.js
when popout onblur will hide popover
when popout more than one, older popover will be hide
$count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;});
None of the above solutions worked 100% for me because I had to click twice on another, or the same, popover to open it again. I have written the solution from scratch to be simple and effective.
$('[data-toggle="popover"]').popover({
html:true,
trigger: "manual",
animation: false
});
$(document).on('click','body',function(e){
$('[data-toggle="popover"]').each(function () {
$(this).popover('hide');
});
if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target).popover('show');
}
else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target.parentElement).popover('show');
}
});
My solution, works 100%, for Bootstrap v3
$('html').on('click', function(e) {
if(typeof $(e.target).data('original-title') !== 'undefined'){
$('[data-original-title]').not(e.target).popover('hide');
}
if($(e.target).parents().is('[data-original-title]')){
$('[data-original-title]').not($(e.target).closest('[data-original-title]')).popover('hide');
}
if (typeof $(e.target).data('original-title') == 'undefined' &&
!$(e.target).parents().is('.popover.in') && !$(e.target).parents().is('[data-original-title]')) {
$('[data-original-title]').popover('hide');
}
});
I want to have a modal dialog to appear with some content and buttons inside it. The dialog should be bound to some observable property or not, the dialog also must have close buttons, one inside its body, another on the top right corner. My main aim is to close this modal form with these buttons, but "Cancel" button inside dialog's body doesn't work as expected.
1) First approach:
In this example dialog is created with static dialog, on "Open dialog" button click it shows up, it gets closed if clicked on top right X link, but it doesn't close on "Close" button click, however I set my observable to null. I was pretty much sure about this approach, as it was described in this brilliant explanation.
Excerpt from my code:
HTML:
<button data-bind="click: openDialog">Open dialog</button>
<div data-bind="with: dialogOpener">
<div data-bind="dialog: { data: $data, options: { close: Close } }">
<button data-bind="click: Save">Save</button>
<button data-bind="click: Close">Cancel</button>
</div>
</div>
JS:
self.dialogOpener = ko.observable();
self.openDialog = function () {
var data = {
Save: function() {
alert('Saved');
},
Close: function() {
alert('Closed');
self.dialogOpener(null);
}
}
self.dialogOpener(data);
}
Fully working example:
http://jsfiddle.net/cQLbX/
2) Second approach shows how my dialog html is dynamically created and it has the contents and the same results as in the first example.
Excerpt from my code:
HTML:
<button data-bind="click: openDialog">Open dialog</button>
JS:
self.dialogOpener = ko.observable();
self.openDialog = function () {
var element = "";
element += '<div data-bind="with: $data">';
element += '<div data-bind="dialog: { data: $data, options: { close: Close } }">';
element += '<button data-bind="click: Save">Save</button>';
element += '<button data-bind="click: Close">Cancel</button>';
element += '</div>';
element += '</div>';
var data = {
Save: function() {
alert('Saved');
},
Close: function() {
alert('Closed');
self.dialogOpener(null);
}
}
self.dialogOpener(data);
ko.applyBindings(data, $(element)[0]);
}
Fully working example:
http://jsfiddle.net/6T3Ra/
My question is:
On both examples "Cancel" button inside body doesn't work, the dialog doesn't close, what am I doing wrong and how to solve this?
Thanks a lot!
made a bunch of changes to your fiddle, maybe not how you want to do it, but the cancel and x buttons both do the same thing now
http://jsfiddle.net/cQLbX/3/
<div data-bind="dialog: dialogOpener, dialogOptions: { autoOpen: false, close: Close, buttons: { 'Save': Save, 'Cancel': Close } }">
<div data-bind='with: dialogContent'>
<div data-bind="text: Test"></div>
</div>
</div>
i usually structure my dialogs like this, and i've had success with them.
I don't know if you use any plugins and what not, but looking at your js fiddle example no2 with the help of a great thing called debugger is that you aren't explicitly telling the element to hide. A solution to this could be the following:
//If you look at E, E would be the ViewModel and X would be the jQuery Event Click
Close: function(e, x) {
//from the event we have currentTarget which is the button that was pressed.
//parentElement would be the first element, and the next parentElement was
//the modal in your demo. When we call hide() it hides the modal from
//which the button was pressed.
$(x.currentTarget.parentElement.parentElement).hide();
//left these as is from your example
alert('Closed');
self.dialogOpener(null);
}