I have two buttons on modal, on first I need to save changes and close modal, on second I need to close modal and reset changes - same thing when person closes modal by clicking anywhere. The problem is I don't know how to check whether save button was clicked.
Here is html:
<div class="modal fade" id="modalNumber" tabindex="-1" role="dialog" aria-labelledby="modalNumberLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
blablabla
<div class="modal-footer">
<button data-dismiss="modal" class="btn-u btn-u-default" type="button">{{ 'backButton'|trans }}</button>
<button type="submit" class="btn-u saveChanges">{{ 'confirmChangesButton'|trans }}</button>
</div>
</div>
</div>
</div>
and here is JS code:
$('.saveChanges').on('click', function () {
// doing something here
// ....
// and closing modal in the end
$(this).closest('.modal.fade').modal('hide');;
});
$('.modal.fade').each(function(index, object) {
$(object).on('hidden.bs.modal', function (e) {
console.log(e.target);
// here is part of irrelevant code - what's important is that I use index and I need to know if saveButton was clicked
mainContainer.resetGroup(index);
});
});
e.target always returns div class="modal fade" element, not the button
What's important - I don't want to call mainContainer.resetGroup(index); when save button was clicked.
When you attach a function to your save-btn you don't need to know which button was clicked. In my example are two functions, similar to your example. The first function is called when the save-btn is clicked. In this function you can fetch the data, which you have to save and save it (e.g. via ajax).
The second method is called every time when the modal is closed. But when the save-btn was pressed, the first function was invoked before, and therefore you don't need to check any more which button was pressed...
You just need to replace the alert(data) function with your 'save procedure'. I hope that I didn't misunderstood your question...
$(document).ready(function(){
$('.save-btn').on('click', function(evt){
evt.preventDefault();
var $btn = $(this);
var $modal = $btn.closest('.modal');
var data = $modal.find('form').serializeArray();
// save data
alert(data);
// close modal
$modal.modal('hide');
});
$('#myModal').on('hidden.bs.modal', function(evt) {
alert('modal was hidden -- clear input fields');
$('#myModal').find('input').val('');
});
});
Check out this fiddle: https://jsfiddle.net/216q3jgk/4/
EDIT:
In the case that you would know which button was pressed, I would suggest to add a data-attribute to your modal, when the save-btn is pressed.
To add the data attribute call this in the first function before the modal is closed:
$modal.data('savePressed', true);
The data-attribute can be checked in the hidden.bs.modal function with the following code:
var $modal = $(evt.target);
if (!$modal.data('savePressed')) {
// save button was NOT pressed
alert('save not pressed');
}
You can find a full example in this fiddle: http://jsfiddle.net/216q3jgk/5/
Related
I have an <a> tag that toggles the show/hide of a Bootstrap Modal.
Where emailFoo modal looks like
<div class="modal fade" id="emailFoo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-footer">
<button id="sendEmail">OK</button>
</div>
</div>
</div>
</div>
I want to obtain the data of FOO upon the clicked event of an #email button inside the #emailFoo
How can I get the value of the foo from the button that opened the modal in the #sendEmail click event?
$( "#sendEmail" ).click(function() {
//Get foo here from Parent modal that button is inside
//$('#emailFoo').dataset['foo']
});
As a workaround I can obtain foo from when the modal is first opened. I was thinking I can then set this value somewhere else so that the button click can get it.
I.e.
$('#emailFoo').on('show.bs.modal', function () {
//This works! How can I do the same thing from the `sendEmail` click event above?
const callerFromAnchorTag = $(e.relatedTarget);
const foo = callerFromAnchorTag [0].dataset['foo'];
});
it seems you want to get the foo value in this way:
$( "#sendEmail" ).click(function() {
const btn = $(this);
const modal_id = btn.parents('.modal').attr('id');
let toggler = $('body').find('[data-target="#' + modal_id +'"]');
console.log(toggler.attr('data-foo'));
});
UPDATE:
new part:
so we have several toggler in a page, you want to detect witch toggler is the caller of modal?
A fancy way to achieve this (by js objects):
class Modal {
constructor(selector) {
this.$modal = $(selector);
this.modal_id = this.$modal.attr('id');
this.$toggler = null;
this.init();
this.events();
}
init() {
const obj = this;
}
events() {
const obj = this;
$('[data-toggle="modal"]').on('click', function () {
const $a_toggler = $(this);
if ($a_toggler.attr('data-target') === '#' + obj.modal_id)
obj.$toggler = $(this);
});
}
get_toggler() {
return this.$toggler;
}
}
usage:
making new modal object (at first of your code):
const my_modal = new Modal($('#emailFoo'));
returning toggler jquery object (wherever you want to get it):
console.log(my_modal.get_toggler());
another simple way:
make a hidden input inside your modal like this:
<div class="modal fade" id="emailFoo">
<input type="hidden" class="js-toggler__input" value="" hidden>
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-footer">
<button id="sendEmail">OK</button>
</div>
</div>
</div>
</div>
after clicking on togglers, save its id or some attribute like data-toggler="__toggler-number__" (I used data attribute):
$('[data-toggle="modal"]').on('click', function () {
const toggler = $(this);
const toggler_identifier = toggler.attr('data-toggler');
let modal_id = toggler.attr('data-target');
$(modal_id).find('.js-toggler__input').val(toggler_identifier);
});
so you can get the toggler by jQuery:
let toggler_identifier = $("#sendEmail").parents('.modal').find('.js-toggler__input').val();
console.log($('[data-toggler="' + toggler_identifier + '"]'))
be care about:
data-toggler attributes should be unique
some points:
better to use classes over data-attributes to select DOM, data-attributes should use to store little data.
Answer by Ali works, but you can try this too:
Add a hidden field in the modal: <input type="hidden" id="hidden-value">
On clicking the modal toggle, set the value of this hidden-value:
$('#open-modal').on('click', function(event) {
$('#hidden-value').val($(this).data('foo'));
});
On clicking the OK button, get the value (just logging here):
$( "#sendEmail" ).on('click', function() {
console.log($('#hidden-value').val());
});
This is an answer more on the way of 'set the value somewhere, then get it on click'.
You can try this instead assign foo to button data-attr
$('#emailFoo').on('show.bs.modal', function () {
const callerFromAnchorTag = $(e.relatedTarget);
const foo = callerFromAnchorTag [0].dataset['foo'];
$('#sendEmail').attr('data-foo', foo);
});
then
$('#sendEmail').click(function(){
const foo = $(this).data('foo');
});
I have a drawer menu that expands on btn click, what I am trying to achieve is closing the menu when a user clicks on the sidenav-body class which covers the whole body.
Here is the base html and js
<div class="offcanvas-body sidenav-body">
<main id="main-content" role="main">
<div class="container-fluid short-section-row">
<div class="row">
<div class="side-nav-btn navbar-btn js-side-nav-btn" aria-expanded="false" aria-label="Open Side Navigation" aria-controls="SecondaryMenu">Explore This Section <span class="svg-sprite -hamburger"><svg role="img" aria-label="[object Object]"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#hamburger"></use></svg></span></div>
<nav class="side-nav col-sm-2" role="Secondary navigation" aria-label="Side Navigation" aria-hidden="true" id="SecondaryMenu">
<div class="side-nav__control-bar">
<button class="navbar-btn js-side-nav-btn btn btn-primary pull-right" aria-expanded="false" aria-label="Close Side Navigation" aria-controls="SecondaryMenu" tabindex="-1"><span class="svg-sprite -close"><svg role="img" aria-label="close secondary nav"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#close"></use></svg></span> Menu</button>
</div>
// some ul and li items
</nav>
</div>
</div>
</main>
</div>
How I defined classes
this.$body = $(el);
this.$sideNavBody = $('.sidenav-body');
this.$sideNav = $('.side-nav');
this.$controls = $('.side-nav button');
this.$sideNavBtn = $('.js-side-nav-btn');
I have a toggle function on btn click
sideNavBodyToggleEvent(){
// if the nav is open, run close event
if(this.$body.hasClass('side-is-open')) {
this.sideNavBodyCloseEvent();
} else {
this.sideNavBodyOpenEvent();
}
}
And those conditional functions are defined like so
sideNavBodyCloseEvent () {
this.$body.removeClass('side-is-open');
// always clear the 'opened state' of any open menus
this.$sideNavSection.removeClass('side-is-open');
$(this.$controls).attr('tabindex', '-1');
$(this.$sideNav).attr('aria-hidden', 'true');
$(this.$sideNavBtn).attr('aria-expanded', 'false');
$(this.$sideNavSectionToggle).removeClass('side-is-open');
// unbind the pushed body click event
this.$sideNavBody.off();
}
sideNavBodyOpenEvent() {
this.$body.addClass('side-is-open');
$(this.$sideNav).attr('aria-hidden', 'false');
$(this.$controls).removeAttr('tabindex');
$(this.$sideNavBtn).attr('aria-expanded', 'true');
// bind an event on the div containing the pushed body
// original code left by prev dev was this.$sideNavBody.offClick.bind(this) and doesnt work as I think its trying to run both functions at once (the menu doesnt even open);
//below I am just trying to test if the click event even makes it to this.$.sideNavBody which is the .sidenav-body class and the section I want users to be able to click to close
$(this.$sideNavBody).click(function(e){
console.log(e);
});
}
The open function works and the drawer menu slides out but my attempt at closing it was as follows
$(this.$sideNavBody).click(function(e){
$(this.sideNavBodyCloseEvent());
console.log(e);
});
Which returns this error Uncaught TypeError: this.sideNavBodyCloseEvent is not a function everytime the .sidenav-body / $sideNavBody is clicked
How can I pass is this sideNavBodyCloseEvent() function on that element click?
When adding the bit of code to close the menu when click on the .sidenav body the menu closes when it encounters this code from jquery
if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; }; }
I have never seen or had this problem before any suggestions?
Does this work?
$(this.$sideNavBody).click(function(e){
$(this.sideNavBodyCloseEvent());
console.log(e);
}.bind(this));
The inner function has its own this object, which doesn't have the sideNavBodyCloseEvent method. To use the this object of the outer function in the inner function, use bind.
Normally, you have an initialisation function that binds the necessary event handlers:
init () {
this.$sideNavBtn.click(this.sideNavBodyOpenEvent.bind(this));
this.$sideNavBody.click(this.sideNavBodyCloseEvent.bind(this));
}
How about doing this a different way.
I think I've made a mistake somewhere in there with the elements, but passing this element as a parameter is the main change.
$body = $(el);
$sideNavBody = $('.sidenav-body');
$sideNav = $('.side-nav');
$controls = $('.side-nav button');
$sideNavBtn = $('.js-side-nav-btn');
$sideNavBody.click(function(e){
sideNavBodyCloseEvent($(this))
console.log(e);
});
sideNavBodyCloseEvent (element) {
element.$body.removeClass('side-is-open');
// always clear the 'opened state' of any open menus
element.$sideNavSection.removeClass('side-is-open');
$controls.attr('tabindex', '-1');
$sideNav.attr('aria-hidden', 'true');
$sideNavBtn.attr('aria-expanded', 'false');
$sideNavSectionToggle.removeClass('side-is-open');
// unbind the pushed body click event
$sideNavBody.off();
}
I have this modal :
<div class="modal fade" id="column-settings-modal" tabindex="-1" role="basic" aria-hidden="false">
And this checkbox in the modal :
<input type="checkbox" id="partcountry-cb" value="Ülke"/> Ülke <br />
I have a function to load modal. And I want to check this checkbox while modal is opening. My function is below :
function load_column_filters(surveyId,toShow) {
var $modal = $('#column-settings-modal');
$modal.modal();
$("#partcountry-cb").attr("checked", true);
}
However, the last statement does not work. (I have tried .prop,but it did not work.) Is this problem about modal itself or am I missing something?
Are you using bootstrap modal? If yes, try check out this event doc for modal. Try modified it content when it completely open by triggering shown callback like so :
function load_column_filters(surveyId,toShow) {
var $modal = $('#column-settings-modal');
$modal.modal();
}
$('#column-settings-modal').on('shown.bs.modal', function() {
$("#partcountry-cb").prop("checked", true);
});
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 have the following element
<button type="button" class='launch' data-toggle="modal" data-target="#myModal">Launch modal</button>
<button type="button" class='boom' data-toggle="modal" data-target="#myModal"> Boom </button>
and I have an event listener:
$('#myModal').on('show', function () {
// how do I check if button has class launch or boom?
})
how do I check if button has class launch or boom inside the function?
or in other words the question is how do I get the button that triggers this action inside this function.
use the jQuery .hasClass method to check whether the class exsists.
$('#element').hasClass('launch'); // returns true or false;
try the code below. Please add the .myModalbtn class to both buttons
$('.myModalbtn').on('hidden', function () {
$(this).hasClass('launch')) // if the it has launch class -> returns true else false;
});
You can add a separate class for each button like .modalBtn for example and do:
$('.modalBtn').click(function() {
if ($(this).hasClass('launch')) showModal($('.launch'));
else if ($(this).hasClass('boom')) showModal($('.boom'));
});
function showModal( $btn ) {
//insert code to show modal (you can find it in the bootstrap javascript docs. Now you have $btn object to use.
}