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();
},
Related
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>
In the course of development of JS, faced with such a situation. My code:
Object.prototype.show = function () {
$('span[data-search]').on('click', function (evt) {
var data_search = $(this).data('search');
$('body').on('shown.bs.modal', '.modal', function () {
$(this).find('button.synConfirm').on('click', function(){
console.log(data_search); // Not see variable
});
});
}):
});
Ie if you click on the span opens a modal window (Bootstrap 3). Then when you click on the button in the modal window, I should have access to the variable data-search announced in the beginning of the method, but I do not have access to it ...
Question: Why? After I identified her to call console.log (), .. How do I get it?
I'm getting the following error that is saying my e.preventDefault(); ---> "e." undefined is not a function when clicking <button class='url_qry_add' onclick='url_qry_add(this);'>. The function itself is defined before the end of my </body> and I have only invoked jQuery once.
The function structure is as follows:
var url_qry_add = function ( e ) {
e.preventDefault();
...
};
It used to be:
$( "ul.url_qry" ).on( "click", "li .url_qry_add", function ( e ) {
e.preventDefault();
...
});
But subsequent buttons added dynamically afterwards were not being picked up.
So I've been trying to figure out how to go about it and decided I should try converting the problem function to a named "invokable" function and putting the call in manually with the onclick='..' into the buttons that exist before and after dynamic creation.
Like I say, the error must be in the way I've created the function or the way I'm calling it. The error can't be to do with the order of files and I have not accidentally nested the function within another function or a document.ready.
What am I doing wrong?
<button class='url_qry_add' onclick='url_qry_add(event);'>
var url_qry_add = function (e) {
console.log(typeof e.preventDefault); // function
};
Update:
I'll try clarify how it works "internally", when we add attributes to function url_qry_add "inside" it looks like this:
document.querySelector('.url_qry_add').addEventListener('click', function (event) {
(function (event) {
url_qry_add(event, this, $(this));
}).call(event.target, event);
});
var url_qry_add = function (event, element, $jElement) {
console.log(event);
console.log(element);
console.log($jElement);
};
Hence, we have variable "event" (event object, where we have method preventDefault and so on), and "this" (current element). I hope that this explanation will help you understand where we get variable "event".
$('.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
}
};
I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});