How do you hide a bootstrap popover if the parent element, that triggered this popover, is removed from the dom?
If a user clicks a button on my page, some content will be loaded into a div via ajax. On the next click on a different button, another ajax call will replace the content in this same div.
The content loaded into this div contains elements that act as Bootstrap Popover triggers, like this one:
<a class="infolink" data-toggle="popover" data-title="some title" data-placement="bottom" data-trigger="hover click" ></a>
The popovers get initialized after every successful ajax call:
$(document).ajaxSuccess(function(){
var init = function() {
$('[data-toggle="popover"]').each(function(index) {
initPopover(this); //This is where the popover gets initialized
});
}
window.setTimeout(init,100); // set timeout to prevent function from being executed before content is replaced
});
The problem after a ajax call is, if a popup was visible, it stays visible even after the parent element has been removed. This is not an uncommon issue with popovers or dialogs according to google results, but the solutions I've come across so far did not seem very clean to me.
Two solutions, just to name some:
Hide every popover once an ajax finishes with success. This is not an option, because the content of my popovers is loaded dynamically via ajax once they get opened.
Have an array store all trigger elements. Once a Ajax success event occurs, loop through that array and check if that element is still there.
//Pseudocode
var popoverTriggers = [];
$('[data-toggle="popover"]').each(function(index) {
popoverTriggers.push(this);
}
Doesn't seem very clean to me either.
Does anyone know of a better way to do this?
I added a
$('.popover').remove();
To the event that should trigger the removal of the popover. This worked great for me.
Related
I have an xpage (viewed via web browser) which has many <xe:dialog...> controls on it, resulting in bootstrap modal dialogue boxes.
I want to run some client-side script when any dialogue is closed.
So I tried ..
$('.modal').on('hide.bs.modal', function() { ...}
However this didn't work, I suspect because when the xpage is loaded there aren't actually any elements with class 'modal', until one is opened. Then a partial refresh injects the relevant HTML.
So I tried running that line above in the event when the modal opens (in the xpages onShow event), but that didn't fire either. I guess the event might be 'when the modal opens but before it's displayed' meaning the elements aren't ont he screen then either.
So I also tried (hack, hack) a setTimeout of 2 seconds to allow the modal to show first, but still no luck.
So .. question is ..
Using xpages bootstrap modals, via the standard xe:dialog control, how can I attach a client-side javascript event whcih will run when the modal is closed / hidden ?
You can use Event Delegation to bind the listener to a parent element of the (non-existing) modals and trigger a function when a click happens on elements matching the .modal selector in that parent element:
$(document).on("hide.bs.modal", ".modal", function () {...});
I do something similar to this, where a button selection on one modal, closes said modal, and then depending on the button that was clicked, opens the next modal. Instead of doing that, could you not run your script in the same way?
var
currentModal = $(this);
//click next
currentModal.find('.btn-close').click(function(){
currentModal.modal('hide');
OTHER STUFF?
EDIT - My full code:
<script type="text/javascript">
$("div[id^='myModal1']").each(function(){
var
currentModal = $(this);
//click next
currentModal.find('.btn-next').click(function(){
currentModal.modal('hide');
currentModal.closest("div[id^='myModal']").nextAll("div[id^='myModal3']").first().modal('show');
});
//click prev
currentModal.find('.btn-prev').click(function(){
currentModal.modal('hide');
currentModal.closest("div[id^='myModal']").nextAll("div[id^='myModal2']").first().modal('show');
});
});
$(window).on('load',function(){
$('#myModal1').modal('show');
});
</script>
I have a div inside my html with the id pageContent. When users click various buttons, it will load the appropriate content. When a user clicks the javaQuestions button it loads, javaQuestions.html into the div just fine. However, inside, the javaQuestions.html, I have a collapsible list, and I can't figure out a way to "bind" the li collapse/uncollapse without having the user to click TWICE. Right now what I have is:
$("#pageContent").on('click', 'li', function (){
$('.collapsible').collapsible();
});
So I guess what happens is, first the user clicks on the button, and it loads content. Then, the user clicks on any li, and it enables the "collapsible()" function, but does not uncollapse/collapse the content. Only when the user clicks a second time does it works fine. I tried adding the line $('.collapsible').collapsible(); into the event that loads the javaQuestions.html content, but it doesn't do anything. Kind of at a roadblock, any ideas?
EDIT: Here is the code that loads the content:
$("#pageContent").on('click', '#javaQuestions', function (e) {
fadeIn("#pageContent", "../java-questions/javaQuestions.html", 50);
fadeIn("#commentsContent", "../comments/comment-section.html", 500);
});
I also really want to know how this will function once I figure it out. But as you can see, the above function loads the javaquestions.html, and I can't seem to find a way to ALSO bind 'li' to be collapsible in one swoop.
Have you tried using jQuery bind method? You can bind your handler to, say, body and then you don't have to care about loading and attaching a handler after it.
Update: may be this will help:
$(document).ready(function() {
$("body").on('click', '#pageContent li', function (){
$('.collapsible').collapsible();
});
});
Use this DOCUMENT because it is dynamically loaded
$(document).on("click","li #pageContent",function(){
$('.collapsible').collapsible();
});
I have the following code:
$( "#check-button" ).on( "click", function() {
$("#button_cart").click();
$('.checkout-button').click();
});
I have this jQuery click event. What I want to do is, on clicking the check-button, the first line inside the function is updating the cart (which reloads the page) and then the second line inside the function is the checkout button, which takes me to the next (checkout) page.
But here only the first event is firing. Is this because the page is reloaded on "button-cart" clicking? How do I solve it?
That's correct. The second click actually could be working but in some kind of limbo between the click and the load and you wont see it.
The solution is to "handle" the reload event, I put it between "" because this event can't be handled ( as far as I know) but you can make some hacks.
First, why is reloading the page? Are you adding new content?
In this case just call the click in the content added with a load handler like $(document).ready();
Here is how i did it: Using localstorage.
Just saved the value of someVariable on check-button click ( along with button-cart click) and on page reload i checked if the value is set. If it is set, i unset it and clicked the next button.
Here is the link
This was really great help from SO. Thank u SO
I've recently started using Twitter's new Bootstrap 2.0.1 and its Javascript popovers.
I want to write a script so that no more than one popover can be displayed at one time. In other words, when a new popover is generated for whatever reason (e.g. the client clicks or hovers over a new element with a popover), all of the PREVIOUSLY displayed popovers are hidden first.
Here's the function that initially sets up all of the popovers for my webpage:
$(function (){
$("[rel=popover]").popover({placement:'left', trigger:'click', html:true});
});
What I need, I think, is to write a function that hides all popovers. I would call that function BEFORE displaying every popover, to ensure that only one popover is displayed at a time. The function might look like this, I imagine:
function hidePopovers(){
$(function (){
$("[rel=popover]").popover('hide');
});
}
But my problem is figuring out WHERE (or HOW) to call this hidePopovers function. I want to call it when a popover is triggered, but before the popover is displayed. Help?
Oh, and just to clear up any confusion, the new Bootstrap now has a 'click' trigger that allows you to display popovers upon clicking. More details about it can be found here.
Thank you so much!
Considering what you have presented as the problem to solve, I think that it would be much more efficient to simply store a reference to the last popover open, rather than execute the hide() method on every single popover element you might select on the page. As far as I understand it, you only want a single popover to be open in the first place, so there should only ever be at most a single one to hide.
The following would do the trick:
var $visiblePopover;
$('body').on('click', '[rel="popover"]', function() {
var $this = $(this);
// check if the one clicked is now shown
if ($this.data('popover').tip().hasClass('in')) {
// if another was showing, hide it
$visiblePopover && $visiblePopover.popover('hide');
// then store reference to current popover
$visiblePopover = $this;
} else { // if it was hidden, then nothing must be showing
$visiblePopover = '';
}
});
JSFiddle
Technically, you could potentially change the selector where the delegate handler is attached (in the example code 'body' is used) to a more specific element of the page, allowing you to attach the only-one-visible-at-a-time behavior to only a subset of the popovers on the page.
For instance, if you had a specific form where the popovers would appear too close together, but other popups on the page wouldn't collide/overlap, you could select just the form (e.g., '#some_form_id'), and only the popups in the form would have the behavior.
JSFiddle
Note: In this latter example, I also optimized the code a bit by changing the stored reference to only use the actual Popover object, rather than the jQuery-ized DOM element it is attached to.
Haven't tested this but something like this might work:
Set the trigger to manual.
Listen for click events and on click, call hidePopovers(), and then show the clicked popover.
$(function (){
function hidePopovers(){
$(function (){
$("[rel=popover]").popover('hide');
});
}
$("[rel=popover]").popover({placement:'left', trigger:'manual', html:true});
$("[rel=popover]").click(function() { hidePopovers(); $(this).popover('show');});
});
I have a SharePoint web part page with a list view that is grouped and defaulted to "collapsed" (much like a basic toggle). SharePoint generates its own JavaScript to handle the initial click action, which then expands the page area and dynamically writes new content to that area. The problem is that jQuery cannot access the new content immediately following the click (it needs to finish loading). My thoughts are to add a 2nd jQuery click function to the toggle link and somehow wait for the new content to be added before anything else happens, but I'm not sure how to determine when the dynamic content finishes loading...
//bind a 2nd additional onclick handler via jquery to these items
$('td.ms-gb').children('a').click(function()
{
//give the clicked item a border for visual identification
$(this).css("border","1px solid cyan");
//delay this function until the sharepoint onclick handler finishes loading new content
$('TD.ms-vb-icon').children('a').each(function(index)
{
//give each item a border for visual identification
$(this).css("border","1px solid red");
//perform more jquery on each item
}
);
}
);
A common technique to address this kind of issues is to use
setTimeout(function, timeoutInMs)
and try to find new content in function, if fail restart a timeout until you find the content
Here's a jsFiddle to illustrate:
http://jsfiddle.net/Dhww2/
The only thing I can think of is to set another click handler that registers with $.ajaxSuccess() http://api.jquery.com/ajaxSuccess/ and responds after the first AJAX request (after the click) finishes
It's hackish, but if the code that is fetching the dynamic content doesn't have a callback, there aren't many options.
What are you going to do with loaded contnent? Just style and catch another clicks?
In such case use stylesheets for custom styling and jQuery's live function to catch (click) events of further loaded elements.
Update for comment
$('TD.ms-vb-icon a').live('click', function(ev) {
$(this).attr('name','value');
}
May not work if your click tracking code registers earlier. If so try with mouseover event.