This question already has answers here:
Passing data to a jQuery event handler
(4 answers)
Closed 1 year ago.
How can I pass modalData variable to clickOutsideModalHandler() event handler without getting any errors?
$('.modal').on('shown.bs.modal', function() {
var modalData = {
confirmText: $(this).data('confirm-text'),
cancelText: $(this).data('cancel-text'),
confirmMessage: $(this).data('confirm-message')
};
$(document).click(clickOutsideModalHandler);
});
$('.modal').on('hide.bs.modal', function() {
$(document).unbind('click', clickOutsideModalHandler);
});
function clickOutsideModalHandler() {
var obj = $(".modal-content");
if (!obj.is(event.target) && !obj.has(event.target).length) {
var formFieldset = obj.find("form").find("fieldset").attr("disabled");
if(formFieldset !== "disabled") {
yii.confirm("send form?", function(){
obj.find("form").submit();
});
}
}
}
unbind is deprecated (you should use off instead).
And using event in your clickOutsideModalHandler relies also on a deprecated feature Window.event, you should use the event passed as argument to the callback.
The on function has this signature .on( events [, selector ] [, data ], handler )
data
Type: Anything
Data to be passed to the handler in event.data when an event is triggered.
So you can set the data to be passed with the event using the data parameter:
$('.modal').on('shown.bs.modal', function() {
var modalData = {
confirmText: 'test',
cancelText: 'test',
confirmMessage: 'test',
};
$(document).on('click', modalData, clickOutsideModalHandler);
});
$('.modal').on('hide.bs.modal', function() {
$(document).off('click', clickOutsideModalHandler);
});
function clickOutsideModalHandler(event) {
// access the data using the data property of the event object
console.dir(event.data);
// rest of you code
}
// that part is just here to make the snippet functional
$('.modal').trigger('shown.bs.modal')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="modal">modal</div>
<div>some other content</div>
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 1 year ago.
I'm receiving an ajax response, and based on this adding some html content to the dom.
Problem: I want to also add a link that should have a onclick function with passing a parameter from the response.
Example:
http://jsfiddle.net/zu1ymrh8/55/
<a class="LoadFromAjax" href="#">Load Ajax</a>
<div class="appendedContainer"></div>
$(function() {
function myfunc(input) {
alert("test: " + input);
}
$(".LoadFromAjax").on("click", function() {
event.preventDefault();
$.ajax({
url: 'https://dog.ceo/api/breeds/list/all',
type : 'get',
complete : function( qXHR, textStatus ) {
var mock = "John"; //some values extracted from rsp
$('.appendedContainer').hide();
$('.appendedContainer').append(`<a href='#' onclick='myfunc(${mock})' class='mylink'>Alert me</a>`);
$('.appendedContainer').fadeIn();
}
});
});
});
Result: ReferenceError: myfunct is not defined. Why?
I suggest setting the click listener on the container element.
See example below
document.querySelector('button').addEventListener('click', load);
const container = document.querySelector('.container');
// delegating the click handler to the container
container.addEventListener('click', handleItemClick);
function load() {
Promise
.resolve(Date.now())
.then(entry => {
const child = document.createElement('a');
child.innerText = entry;
container.append(child);
})
}
function handleItemClick(ev) {
console.log(ev.target.innerText)
}
a {
display: block;
}
<button>Load</button>
<div class="container"></div>
How about something like:
$.ajax({
...,
complete : function( qXHR, textStatus ) {
var mock = "John"; //some values extracted from rsp
// create a link:
var link = $('<a>', {
href : "the-url",
class : "the-class",
});
// append to container:
$('.appendedContainer').append(link);
// set on click function:
link.click(function() {
// do something with mock:
console.log(mock);
});
...
}
});
I hope this can be understood. I’ve been working on this for about two weeks now and I’m just digging a bigger hole.
The following (fairly standard code) refills a selection option object (id=brand) from a mysql query , the parameter for which is the value of ‘brand’, called in ‘fetch.php’ when one of the previous options is selected:
$('#brand').change(function(){
$.getJSON(
'fetch.php',
'brand='+$('#brand').val(),
function(result){
$('#brand').empty();
$.each(result.result, function(){
$('#brand').append('<option>'+this['brand']+'</option>');
});
}
);
});
However, I also want to have a button on index.html that will also do the same thing except, rather than use the value of ‘brand’ as the parameter of the query, I want to use the value of a text object (id=demo) on the webpage.
My problem is how to construct the code above to call ‘fetch.php’, after the click of a button, and using the value of demo, so that the selection object ‘brand’ will be rebuilt.
The most immediate solution would be to clone the existing code and make the needed modifications to it (listen on button click, use the value of the other field).
$('#brand').change(function(){
$.getJSON(
'fetch.php',
'brand='+$('#brand').val(),
function(result){
$('#brand').empty();
$.each(result.result, function(){
$('#brand').append('<option>'+this['brand']+'</option>');
});
}
);
});
$('#button').click(function(){
$.getJSON(
'fetch.php',
'brand='+$('#demo').val(),
function(result){
$('#brand').empty();
$.each(result.result, function(){
$('#brand').append('<option>'+this['brand']+'</option>');
});
}
);
});
Instead, you could extract the common part of the two code blocks to make it reusable:
// The common part.
function fetchBrands(brand) {
$.getJSON(
'fetch.php',
'brand='+brand,
function(result){
$('#brand').empty();
$.each(result.result, function(){
$('#brand').append('<option>'+this['brand']+'</option>');
});
}
);
}
// Listen for change event on the select element.
$('#brand').change(function(){
fetchBrands($('#brand').val());
});
// Listen for click event on the button.
$('#button').click(function(){
fetchBrands($('#demo').val());
});
You can use .triggerHandler( eventType [, extraParameters ] ) and use extraParameters (they are explained in the .trigger() documentation).
They will get passed as parameters to the registered event handlers for that event.
The event object is always passed as the first parameter to an event
handler. An array of arguments can also be passed to the .trigger()
call, and these parameters will be passed along to the handler as well
following the event object. As of jQuery 1.6.2, single string or
numeric argument can be passed without being wrapped in an array.
Note the difference between the extra parameters passed here and the
eventData parameter to the .on() method. Both are mechanisms for
passing information to an event handler, but the extraParameters
argument to .trigger() allows information to be determined at the time
the event is triggered, while the eventData argument to .on() requires
the information to be already computed at the time the handler is
bound.
Modify the signature of your change event handler to:
function(ev, brand) {
// ...
}
Use the brand parameter in your change handler if it is available or the selected value of the dropdown otherwise:
brand = brand || $('#brand').val();
Then use this for the .getJSON() call:
$.getJSON(
'fetch.php',
'brand=' + encodeURIComponent(brand),
...)
You can then trigger the event handler with any brand you want (e.g. $("#demo").text()) with:
$("#brand").triggerHandler("change", $("#demo").text())
An working example (with a fake getJSON() method)
$(function() {
$('#brand').change(function(ev, brand){
brand = brand || $('#brand').val();
getJSON(brand, function(result){
$('#brand').empty()
.append("<option></option>");
$.each(result, function(){
$('#brand').append('<option>'+this['brand']+'</option>');
});
});
});
// the "reset to default values" button
$("button").on("click", function() {
$("#brand").triggerHandler("change", $("#demo").text());
});
// initially fill the drop-down (I didn't want to write the default options also in the markup...)
$("#brand").triggerHandler("change", $("#demo").text());
});
function getJSON(brand, callback) {
const fakeResponse = {
A: [ { brand: "AA" }, { brand: "AB" } ],
B: [ { brand: "BA" }, { brand: "BB" } ],
default: [ { brand: "A" }, { brand: "B" } ]
}
callback(fakeResponse[brand]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="demo">default</div>
<select id="brand"></select>
<button>Reset to "default"</button>
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
Trying to call the closeOpenNavDropdowns function within my toggleDropdownNavState function, but nothing is running and I am not getting errors. I've checked the compiled code and it's there.
EDIT: trying to call the fn like this.closeOpenNavDropdowns(); gives me Uncaught TypeError: this.closeOpenNavDropdowns is not a function
const aboutDropdownNav = {
setup() {
$('.nav__main__about-dropdown--js').click(this.toggleDropdownNavState);
// Handlers for when user clicks outside the dropdown to close
$(document).click(function(event) {
if ($('body').hasClass('about-dropdown--open') && !$(event.target).parents('.about-us-dropdown').length) {
$('body').removeClass('about-dropdown--open');
}
})
},
toggleDropdownNavState(e) {
e.stopPropagation();
e.preventDefault();
$('body').toggleClass('about-dropdown--open');
this.closeOpenNavDropdowns;
},
closeOpenNavDropdowns() {
console.log('closeOpenNavDropdowns in aboutDropdown.js');
$('body').removeClass('solutions-dropdown--open'); //close solution dropdown if its open
}
}
module.exports = aboutDropdownNav;
and the above code is called by this other file:
var aboutDropdownNav = require('./nav-about-dropdown');
module.exports = function() {
// About Dropdown Nav
aboutDropdownNav.setup();
}
The toggleDropdownNavState function is attached to an eventListener. Inside an event handler function, this is a reference to the event's current target. That's why closeOpenNavDropdowns is not a function in the object referenced by this.
There are many ways to solve that issue. One of them is to use Function.prototype.bind to force the binding between the closeOpenNavDropdowns function and your object.
const aboutDropdownNav = {
setup: function() {
$('.nav__main__about-dropdown--js').click(this.toggleDropdownNavState.bind(this));
// Handlers for when user clicks outside the dropdown to close
$(document).click(function(event) {
if ($('body').hasClass('about-dropdown--open') && !$(event.target).parents('.about-us-dropdown').length) {
$('body').removeClass('about-dropdown--open');
}
})
},
toggleDropdownNavState : function(e) {
e.stopPropagation();
e.preventDefault();
$('body').toggleClass('about-dropdown--open');
this.closeOpenNavDropdowns();
},
closeOpenNavDropdowns : function() {
console.log('closeOpenNavDropdowns in aboutDropdown.js');
$('body').removeClass('solutions-dropdown--open'); //close solution dropdown if its open
}
}
aboutDropdownNav.setup();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="nav__main__about-dropdown--js" value="Click"/>
The context, when calling this.toggleDropdownNavState is wrong, bind it to the proper context.
$('.nav__main__about-dropdown--js').click(this.toggleDropdownNavState.bind(this));
And you are missing the brackets () to call the function, you just referencing the function.
toggleDropdownNavState(e) {
e.stopPropagation();
e.preventDefault();
$('body').toggleClass('about-dropdown--open');
this.closeOpenNavDropdowns();
},
$('.btn-delete').on('click', this.confirm.bind(this));
Above, on click it runs:
p.confirm = function(e) {
if(!$(this).hasClass('danger')){
$(this).addClass('danger');
$(this).bind('mouseleave',function(){
$(this).removeClass('danger');
$(this).unbind('mouseleave');
});
}
else{
this.delete();
}
};
I'm having trouble with this. I need this to get the button but I also need this to access another method (this.delete). I've tried bind but it faisl to work.
Any ideas?
Assuming I'm understanding your question correctly, you want to be able to pass the clicked element as this to the p.confirm function. You should be able to do this by using call, or by using p.confirm as the handler:
// using call
$('.btn-delete').on('click', function (e) {
p.confirm.call(this, e);
});
// as handler
$('.btn-delete').on('click', p.confirm);
Assuming that this.delete is actually p.delete, just use call in the handler to pass the clicked element as this to the delete method:
p.confirm = function (e) {
var self = $(this); // cache lookup, "this" is the clicked element
if (!self.hasClass('danger')) {
self.addClass('danger');
self.bind('mouseleave', function () {
self.removeClass('danger');
self.unbind('mouseleave');
});
} else {
p.delete.call(this); // pass clicked element to use as "this" in p.delete
}
};
When I fire a function I want it to apply listeners just to elements I pass, particular this jQuery element.
addEventListeners(this);
function addEventListeners(el) {
$(el).mouseenter(function() {
$(this).stop(true,true).switchClass("", "HIGHLIGHT", 400, "easeInOutQuad");
});
$(el).mouseleave(function() {
$(this).stop(true,true).switchClass("HIGHLIGHT", "", 400, "easeInOutQuad");
});
}
It fires from AJAX result:
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(this);
});
How to code it good? This code is not passing variables from addEventListeners(this); to function.
in the ajax callback function "this" will be the ajax object i think and no longer an element so you need to save "this" in a variable before the ajax starts.
that = this;
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(that);
});
Judging from the context of the rest of your success handler, I assume returned is the DOM element you're attempting to bind your handlers to. Assuming this is the case:
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(data[0]);
// change this ^^^^
// pass the DOM element here, or
// change the addEventListeners function to take a jquery element
});
this in that context is not what you expect it to be. Try this:
var self = this;
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(self);
});