I'm trying to fire a meteor event by clicking on a button inside a bootstrap popover window. However, the event is not getting fired.
Here is my code:
<button name="newLetter" class="glyphicon glyphicon-plus newLetter" type="button" data-container="body" data-toggle="popover" data-placement="right"></button>
<div id="popover-content" class="hide">
<textarea></textarea>
<button class='glyphicon glyphicon-ok btn btn-success btn-xs addNewLetter'></button>
</div>
Template.templateName.events({
'click .newLetter': function(e, t) {
$(".newLetter").popover({
html: true,
title: 'New Letter',
content: function() {
return $("#popover-content").html();
}
});
},
'click .addNewLetter': function(e, t) {
console.log('test');
}
});
Any help would be greatly appreciated.
First with your code, this doesn't show the popup on the first click. What you should do:
Template.templateName.rendered = function() {
$(".newLetter").popover({
html: true,
title: 'New Letter',
content: function() {
return $("#popover-content").html();
}
});
}
If you check with your debugger, you will see that each time you click on the .newLetter button, bootstrap take the content of #popover-content and place it in a new div with a class .popover. If you want to see how to bind an event on dynamically created elements, you should check this answer. (the solution is to use on())
Now, for what is happening, Meteor is binding a click event on .addNewLetter inside #popover-content and not on the dynamically created element .addNewLetter inside the div.popover, that's why it is not working. One workaround I found:
Template.templateName.rendered = function() {
$(document).on('click', '.addNewLetter', function() {
console.log('hey');
});
}
Related
I have the following code:
$(document).ready(function () {
EnableModal();
});
function EnableModal() {
if (isModalEnabled) { return; }
// Initialize modal dialog
// attach modal-container bootstrap attributes to links with .modal-link class.
// when a link is clicked with these attributes, bootstrap will display the href content in a modal dialog.
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
}
function DisableModal() {
$('body').off('click', '.modal-link');
}
I am attempting to turn this off under certain circumstances, so I am calling:
$('body').off('click', '.modal-link');
However, the button with the modal-link class is still allowing click events through. I see no errors in the developers console.
I have verified it is calling these correctly and that each is only being called once in my test case.
What am I doing wrong here?
I met this issue before. I wasn't sure what happened at the very beginning and wonder if it was because the selectors weren't actually the same. I checked them and found out they were the same but still couldn't remove the event handler.
I finally fixed this by giving a dummy function as event handler after I removed the original one.
function DisableModal() {
$('body').off('click', '.modal-link');
$('body').on('click', '.modal-link', () => {});
}
Feel free to use ES5 version if you don't like the lambda expression. as
$('body').on('click', '.modal-link', function(){});
Works fine here:
var isModalEnabled;
$(document).ready(function () {
EnableModal();
$(".disableModal").click(DisableModal);
});
function EnableModal() {
if (isModalEnabled) { return; }
// Initialize modal dialog
// attach modal-container bootstrap attributes to links with .modal-link class.
// when a link is clicked with these attributes, bootstrap will display the href content in a modal dialog.
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
}
function DisableModal() {
$('body').off('click', '.modal-link');
}
body { font-family: sans-serif; }
[data-target='#modal-container'] {
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click a few "Modal Link" buttons, and watch the button text turn bold. Then click the "Disable Modal" button, and click the remaining "Modal Link" buttons. The button text does <em>not</em> turn bold.</p>
<button class="modal-link">Modal Link</button>
<button class="modal-link">Modal Link</button>
<button class="modal-link">Modal Link</button>
<p><button class="disableModal">Disable Modal</button></p>
<button class="modal-link">Modal Link</button>
<button class="modal-link">Modal Link</button>
<button class="modal-link">Modal Link</button>
<p>To reset, click the "Run code snippet" button above.</p>
Without knowing the real cause of this, maybe the solution is to use namespaced events.
$('body').on('click.modal', '.modal-link', function (e) { });
and to remove it
$('body').off('.modal');
But I have a feeling it has nothing to do with this, but with the real issue is with the bootstrap modal. Maybe you need to clean up those attributes.
$('[data-toggle="modal"]').removeAttr("data-target data-toggle");
I am creating my simple jQuery plugin that can be use to attach for any action's confirmation. But facing very strange issue, It work fine for single element click, But when i am going to click for second element which also bind with my plugin it work fine but it's also fires for previous clicked element as well.
(function ($) {
$.fn.BootConfirm = function (options) {
// Establish our default settings
var settings = $.extend({
message: 'Are you sure about this ?',
complete: null
}, options);
var self = this;
var cointainer = '\
<div class="modal fade" id="confirmBoot" role="dialog" aria-labelledby="confirmDeleteLabel" aria-hidden="true">\
<div class="modal-dialog">\
<div class="modal-content">\
<div class="modal-header">\
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>\
<h4 class="modal-title">Confirm action</h4>\
</div>\
<div class="modal-body">\
<p>Are you sure about this ?</p>\
</div>\
<div class="modal-footer">\
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>\
<button type="button" class="btn btn-success btn-ok" id="confirm">Ok</button>\
</div>\
</div>\
</div>\
</div>';
return this.each(function () {
var self = this;
$(this).click(function () {
if (!$('#confirmBoot').length) {
$('body').append(cointainer);
}
if (settings.message) {
$('#confirmBoot').find('.modal-body').text($(this).attr('data-confirm'));
}
$('#confirmBoot').modal({ show: true });
if ($.isFunction(settings.complete)) {
$('#confirmBoot').find('.btn-ok').click(function () {
$.when(settings.complete.call(this, self)).done(function () {
$('#confirmBoot').modal("hide"); // Alerts "123"
});
});
}
});
});
}
}(jQuery));
This is my callback function :
function kaushik(myObject) {
ManageAcriveProducts(myObject);
};
and i am calling it by following way
$('a[data-confirm]').BootConfirm({
complete: kaushik
});
For more detail check this js fidder Jsfiddle. Can anyone one share possible solution or better way to do this. Or is there any better way to achieve this ?
The problem is that you're assigning a click on your btn-ok on every click event on a bootconfirmed object. And each click is linked to the object that has been clicked, so it ends up in your callback every time you click btn-ok.
One simple fix, though I'm not sure it's the best, is to remove the click on your btn-ok after the action is complete. Like this:
$.when(settings.complete.call(this, self)).done(function () {
$('#confirmBoot').modal("hide");
$('#confirmBoot').find('.btn-ok').off('click');
});
Working fiddle: http://jsfiddle.net/ywunutyw/
EDIT:
A little improvement on previous solution, it might need some adjustments, since I didn't look into details, but it should give you some ideas. To prevent adding click events and removing them every time user clicks on a button, you can define the click on modal window outside click behavior of each active/inactive button. And on click of active/inactive you define target that will be used in modal confirmation. Like this:
Just before calling behaviors with this.each:
$(document).on('click', '#confirmBoot .btn-ok',
function (e) {
if ($.isFunction(settings.complete)) {
console.log(self)
$.when(settings.complete.call(this, click_origin)).done(function () {
$('#confirmBoot').modal("hide");
});
}
});
Then on the click event of you active/inactive:
click_origin = e.target;
See fiddle: http://jsfiddle.net/ywunutyw/1/
I'm trying to trigger Bootstrap's Pop Over with JS.
I want to be able to change the message and title relative to the link I click.
It works if I actually click the link, but I want to achieve this via Jquery .Click event.
Here is my current JS code:
//Global Tooltip Functionality
$(function () {
$(".tool-tip").on("click",function () {
//Initializes Tooltip
$(function () {
$("#ToolTipContainer").popover();
});
var title = $(this).attr("data-tooltip-title"),
message = $(this).attr("data-tooltip-message");
$("#ToolTipContainer").attr("title", title);
$("#ToolTipContainer").attr("data-content", message);
$("#ToolTipContainer").click();
});
});
Here is my DOM element I am calling function from:
<button type="button" class="tool-tip btn btn-default" data-dismiss="modal" data-tooltip-title="Item Added" data-tooltip-message="Some Message">Continue Shopping</button>
Here is the pop-up container(css hides this, I only want to see the pop-up):
Bootstrap Documentation: Bootstrap PopOver
You can show a tooltip programatically by calling
.popover('show')
$(function () {
$(".tool-tip").on("click",function () {
//Initializes Tooltip
$(function () {
$("#ToolTipContainer").popover();
});
var title = $(this).attr("data-tooltip-title"),
message = $(this).attr("data-tooltip-message");
$("#ToolTipContainer").attr("title", title);
$("#ToolTipContainer").attr("data-content", message);
$("#ToolTipContainer").popover('show');
});
});
Try not hiding the popover container as well, it is most likely hiding your popover.
I hope someone can help.
I'm trying to hide the tooltip when another tooltip icon is clicked. It works but when I decide to click the last tooltip again it 'flashes' the tooltip.
var Hastooltip = $('.hastooltip');
HasTooltip.on('click', function(e) {
e.preventDefault();
HasTooltip.tooltip('hide');
}).tooltip({
animation: true
}).parent().delegate('.close', 'click', function() {
HasTooltip.tooltip('hide');
});
HTML
<a href="#" class="hastooltip" data-original-title="Lorem ipsum dolor sit amet, consectetur adipisicing elit.">
<h3>Info 1</h3>
</a>
<a href="#" class="hastooltip" data-original-title="Lorem ipsum dolor sit amet, consectetur adipisicing elit.">
<h3>Info 2</h3>
</a>
If it helps a following markup is added to the DOM when the user clicks on the button to display the tooltip.
<div class="tooltip"</div>
This can be handled more easily than the above answers indicate. You can do this with a single line of javascript in your show handler:
$('.tooltip').not(this).hide();
Here's a complete example. Change 'element' to match your selector.
$(element).on('show.bs.tooltip', function() {
// Only one tooltip should ever be open at a time
$('.tooltip').not(this).hide();
});
The same technique is suggested for closing popovers in this SO thread:
How can I close a Twitter Bootstrap popover with a click from anywhere (else) on the page?
You need to check if the tooltip is showing and toggle its visibility manually. This is one way of doing it.
$(function() {
var HasTooltip = $('.hastooltip');
HasTooltip.on('click', function(e) {
e.preventDefault();
var isShowing = $(this).data('isShowing');
HasTooltip.removeData('isShowing');
if (isShowing !== 'true')
{
HasTooltip.not(this).tooltip('hide');
$(this).data('isShowing', "true");
$(this).tooltip('show');
}
else
{
$(this).tooltip('hide');
}
}).tooltip({
animation: true,
trigger: 'manual'
});
});
I slightly modified the code of kiprainey
const $tooltip = $('[data-toggle="tooltip"]');
$tooltip.tooltip({
html: true,
trigger: 'click',
placement: 'bottom',
});
$tooltip.on('show.bs.tooltip', () => {
$('.tooltip').not(this).remove();
});
I use remove() instead of hide()
I went into the same problem for regular tooltips. On an iPhone, they do not go away when clicking on the body (i.e. somewhere else).
My solution is that when you click on the tooltip itself, it hides. IMHO, this should be integrated in bootstrap distribution, because it is few code with a big effect.
When you have access to bootstrap sources, add
this.tip().click($.proxy(this.hide, this))
as the last line in method Tooltip.prototype.init in file tooltip.js:
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
// Hide tooltip when clicking on it. Useful for mobile devices like iPhone where eventOut
// (see above) on $element is not triggered and you don't get rid of the tooltip anymore.
this.tip().click($.proxy(this.hide, this))
}
If you do not have the sources at hand, you can achieve the same effect with the following:
$(function()
{
// Apply tooltips
var hasTooltip = $("[data-toggle='tooltip']").tooltip();
// Loop over all elements having a tooltip now.
hasTooltip.each(function()
{
// Get the tooltip itself, i.e. the Javascript object
var $tooltip = $(this).data('bs.tooltip');
// Hide tooltip when clicking on it
$tooltip.tip().click($.proxy($tooltip.hide, $tooltip))
}
);
});
For me, that makes a good user experience on an iPhone: Click on the element to see the tooltip. Click on the tooltip that it goes away.
Re kiprainey’s answer, there is an issue in that once a tooltip has been hidden, it needs to be clicked twice to be shown again. I got around this by using tooltip('hide') instead of hide():
$(element).on('show.bs.tooltip', function() {
// Only one tooltip should ever be open at a time
$('.tooltip').not(this).tooltip('hide');
});
I was looking for a solution to this problem as well and it seems to me that $('.tooltip').not(this).hide(); will bypass any bootstrap show, shown, hide or hidden events you may have attached to the trigger element. After some thought, I've come up the following code allows for somewhat more transparent handling of attached events.
Note: tested on firefox and chrome only but should work fine in theory.
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
$(document).on('show.bs.popover', function(event) {
// could use [data-toggle="popover"] instead
// using a different selector allows to have different sets of single instance popovers.
$('[data-popover-type="singleton"]').not(event.target).each(function(key, el) {
$(el).popover('hide'); // this way everything gets propagated properly
});
});
$(document).on('click', function(event) {
// choose to close all popovers if clicking on anything but a popover element.
if (!($(event.target).data('toggle') === "popover" /* the trigger buttons */
|| $(event.target).hasClass('popover') /* the popup menu */
|| $(event.target).parents('.popover[role="tooltip"]').length /* this one is a bit fiddly but also catches child elements of the popup menu. */ )) {
$('[data-toggle="popover"]').popover('hide');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />
<button type="button" class="btn btn-danger" data-placement="bottom" data-toggle="popover" title="Popover One" data-content="Popover One Content. `focus` trigger still behaves as expected" data-trigger="focus" data-popover-type="singleton">Popover One</button>
<button type="button" class="btn btn-warning" data-placement="bottom" data-toggle="popover" title="Popover Two" data-content="Popover Two Content. for other triggers, clicking on content does not close popover" data-trigger="click" data-popover-type="singleton">Popover Two</button>
<button type="button" class="btn btn-success" data-placement="bottom" data-toggle="popover" title="Popover Three" data-content="Popover Three Content. clicking outside popover menu closes everything" data-trigger="click" data-popover-type="singleton">Popover Three</button>
fiddle example here: http://jsfiddle.net/ketwaroo/x6k1h7j4/
$('[data-toggle=tooltip],[rel=tooltip]').tooltip({
container: 'body' }).click(function () {
$('.tooltip').not(this).hide();
});
Thanks Jochen for the "Iphone" click on tooltip to close solution, exactly what I was looking for.
As for the original request (prevent multiple tooltip fonctionnality is an obvious need when you are asked to implement click tooltip instead of rollover ones), here is my take:
Just after , show: function () { add:
// HACK BEGIN
// Quick fix. Only one tooltip should be visible at all time.
// prototype level property are accessible to all instances so we use one to track last opened tooltip (ie. current this).
if ( (Tooltip.prototype.currentlyShownTooltip != null) || (Tooltip.prototype.currentlyShownTooltip != undefined) ) {
// Close previously opened tooltip.
if (Tooltip.prototype.currentlyShownTooltip != this) { // Conflict with toggle func. Re-show.
Tooltip.prototype.currentlyShownTooltip.hide();
Tooltip.prototype.currentlyShownTooltip = null
}
}
// Keep track of the currently opened tooltip.
Tooltip.prototype.currentlyShownTooltip = this
// HACK END
I will give you a good solution plus a bonus
//save the tooltip in variable (change the selector to suit your tooltip)
var $tooltips = $('a[data-toggle="tooltip"]');
//initialise the tooltip with 'click' trigger
$tooltips.tooltip({
animated: 'fade',
placement: 'top',
trigger: 'click',
delay: { "show": 100, "hide": 100 }
});
//Here is the juicy bit: when a tooltip is opened it
//it creates an 'aria-describedby' with the id of the tooltip
//opened we can leverage this to turn off all others but current
$tooltips.on('click', function () {
var toolTipId = $(this).attr('aria-describedby');
$('.tooltip').not('#'+ toolTipId).tooltip('hide');
});
//But wait theres more! if you call now we chuck in a free close on X seconds event!
$tooltips.on('shown.bs.tooltip', function (e) {
//Auto hide after 7 seconds
setTimeout(function () {
$(e.target).tooltip('hide');
}, 7000);
});
//call now! XD
I used class name to add tooltip and removed using class name. it's working.
Add Tooltip
$('.tooltips').tooltip({
animation: true
, container: 'body'
, html: true
, placement: 'auto'
, trigger: 'focus hover'
});
Hide Tooltip
$('.tooltips').tooltip('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);
}