jquery ignoring first click - javascript

I have this function:
NewShowHideDiv2(iconID, divID, disabled) {
var x = document.getElementById(divID);
var y = document.getElementById(iconID);
$(eval(y)).click(function() {
console.log(eval(y));
$(eval(y)).toggleClass( "clicked" );
});
$(eval(x)).slideToggle("slow", function() {
});
}
All i am trying to get it to do is toggle the "clicked" class on click. However, it ignores the first and second click, and then applies it on the third and all subsequent odd number clicks. any ideas?

Without knowing how NewShowHideDiv2 is called it's difficult to be certain but there are some likely issues.
First, by putting your click binding function inside another function, the event isn't bound to the element until NewShowHideDiv2 is run. So you'll want to pull that out and put it in something like this:
$( document ).ready(function() {
$(eval(y)).click(function() {
console.log(eval(y));
$(eval(y)).toggleClass( "clicked" );
});
});
Also, the eval approach on the JS object is likely causing issues and certainly isn't the best practice. You'll want to modify that to be:
$( document ).ready(function() {
$("#iconIDHere").click(function() {
console.log(this);
$(this).toggleClass( "clicked" );
});
function NewShowHideDiv2(divID, disabled) {
$("#" + divID).slideToggle("slow", function() {
});
}
});

Try this with vanilla JS:
var x = document.getElementById('divID');
x.addEventListener('click', function(e) {
if(e.target.classList.contains('clicked')) {
e.target.classList.remove('clicked');
} else {
e.target.classList.add('clicked');
}
});
I think JQuery is:
$('#divID').click(function() {
$('#divID').toggleClass('clicked');
});

Related

Is there a way to call jquery functions on another object after finishing the first?

I want to fade out object 1 and after fade out remove a class and add one. After that on another object the object 2 should fadein and then i assign it a class. The problem that i encountered is that if i fire my event faster than the fadein/fadeout the object stays active.
$('.menuA').on("click", function () {
$('.menuA').removeClass("blue accent-3 z-depth-2", 100);
let clicked = $(this);
$('.menuA').promise().done(function () {
clicked.addClass("blue accent-3 z-depth-2", 100);
})
animatePanes($(this).attr("con"));
})
function animatePanes(pane) {
let paneOld = $('.pane-active');
paneOld.fadeOut(250).removeClass("pane-active").addClass("pane-inactive").promise().done(function () {
$('.' + pane).fadeIn(250).removeClass("pane-inactive").addClass("pane-active");
});
};
Thats my event with the function. The problem is that if i click to fast and trigger the event on menuA the paneOld doesnt get the class pane-inactive.
I already tried to do a global variable that checks if the event is running but it didnt worked (probably because i thinked wrong).
Is there a way to disable the event listener until the event is completly finished?
Or is there a better way?
You can surely do it with a global variable - as you've already said. Maybe you just put in in the wrong place.
I'd recommend something like isAnimating=false and 'disable' the click event listener if it's value is true. This way you can reset isAnimating to false as soon as all your animations are completed.
var isAnimating = false;
$('.menuA').on("click", function() {
if (!isAnimating) {
$('.menuA').removeClass("blue accent-3 z-depth-2", 100);
let clicked = $(this);
$('.menuA').promise().done(function() {
clicked.addClass("blue accent-3 z-depth-2", 100);
})
animatePanes($(this).attr("con"));
isAnimating = true;
}
})
function animatePanes(pane) {
let paneOld = $('.pane-active');
paneOld.fadeOut(250).removeClass("pane-active").addClass("pane-inactive").promise().done(function() {
$('.' + pane).fadeIn(250).removeClass("pane-inactive").addClass("pane-active").promise().done(function() {
isAnimating = false;
});
});
}

Binding a function that is already bound to another element

I have a bunch of elements that get three different classes: neutral, markedV and markedX. When a user clicks one of these elements, the classes toggle once: neutral -> markedV -> markedX -> neutral. Every click will switch the class and execute a function.
$(document).ready(function(){
$(".neutral").click(function markV(event) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
$(this).unbind("click");
$(this).click(markX(event));
});
$(".markedV").click(function markX(event) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
$(this).unbind("click");
$(this).click(neutral(event));
});
$(".markedX").click(function neutral(event) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
$(this).unbind("click");
$(this).click(markV(event));
});
});
But obviously this doesn't work. I think I have three obstacles:
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
There's no need to constantly bind and unbind the event handler.
You should have one handler for all these options:
$(document).ready(function() {
var classes = ['neutral', 'markedV', 'markedX'],
methods = {
neutral: function (e) { alert('Good!') },
markedV: function (e) { alert('Bad!') },
markedX: function (e) { alert('Ok!') },
};
$( '.' + classes.join(',.') ).click(function (e) {
var $this = $(this);
$.each(classes, function (i, v) {
if ( $this.hasClass(v) ) {
methods[v].call(this, e);
$this.removeClass(v).addClass( classes[i + 1] || classes[0] );
return false;
}
});
});
});
Here's the fiddle: http://jsfiddle.net/m3CyX/
For such cases you need to attach the event to a higher parent and Delegate the event .
Remember that events are attached to the Elements and not to the classes.
Try this approach
$(document).ready(function () {
$(document).on('click', function (e) {
var $target = e.target;
if ($target.hasClass('markedV')) {
alert("Good!");
$target.addClass("markedV").removeClass("neutral");
} else if ($target.hasClass('markedV')) {
alert("Bad!");
$target.addClass("markedX").removeClass("markedV");
} else if ($target.hasClass('markedX')) {
alert("Ok!");
$target.addClass("neutral").removeClass("markedX");
}
});
});
OR as #Bergi Suggested
$(document).ready(function () {
$(document).on('click', 'markedV',function (e) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
});
$(document).on('click', 'markedX',function (e) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
});
$(document).on('click', 'neutral',function (e) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
});
});
Here document can be replaced with any static parent container..
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
You don't bind elements to functions, you bind handler functions to events on elements. You can't use a function before it is defined (yet you might use a function above the location in the code where it was declared - called "hoisting").
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
That is what happens implicitly when the handler is called. You only need to pass the function - do not call it! Yet your problem is that you cannot access the named function expressions from outside.
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
Yes. Use only one handler, and decide dynamically what to do in the current state. Do not steadily bind and unbind handlers. Or use event delegation.

jQuery refactored function

I like to keep my code as DRY as possible and would like to know if the following is possible.
I'll need to reuse the code below many times with the only difference being what I do in the following function.
.on("click", "a", function(e) {})
I could just duplicate the addToBooking function, give it a different name, make the slight change in the click handler but that feels wasteful and repetitive.
Can I perhaps pass a code block to the addToBooking function?
Or maybe there's another cool, efficient way I'm not aware of.
The full code block
var addToBooking = function(that, event) {
var left, top;
event.stopPropagation();
//Turn off all calendar tracking
$(".track").off();
//Get proper sticky positioning (Checks to make sure it wont display off screen)
left = getPosition(".add_to_booking", "left");
top = getPosition(".add_to_booking", "top");
//Position sticky, display and listen for click event to see what to do next
$(".add_to_booking").css({top: top, left: left})
.fadeIn('fast')
.on("click", function(e) { e.stopPropagation(); })
.on("click", "a", function(e) {
if($(this).text() === "YES") {
//Close dialog
closeTT();
//Open new add to booking box
addBooking(that, event);
} else {
closeTT();
}
});
}
Pass in the function and assign it
var addToBooking = function(that, event, custFnc) {
...
...
.on("click", "a", custFnc );
}
Fiddle
To pass parameters, you need to use call()
jQuery( function(){
function hey(evt, test){
var text = jQuery(this).text();
alert(text + ":" + test);
}
function addClick( custFnc ){
var test=99;
jQuery("#foo").on("click",
function(e){
custFnc.call(this, e,test);
}
);
}
addClick(hey);
});
​
Fiddle

How to write onshow event using JavaScript/jQuery?

I have an anchor tag on my page, I want an event attached to it, which will fire when the display of this element change.
How can I write this event, and catch whenever the display of this element changes?
This is my way of doing on onShow, as a jQuery plugin. It may or may not perform exactly what you are doing, however.
(function($){
$.fn.extend({
onShow: function(callback, unbind){
return this.each(function(){
var _this = this;
var bindopt = (unbind==undefined)?true:unbind;
if($.isFunction(callback)){
if($(_this).is(':hidden')){
var checkVis = function(){
if($(_this).is(':visible')){
callback.call(_this);
if(bindopt){
$('body').unbind('click keyup keydown', checkVis);
}
}
}
$('body').bind('click keyup keydown', checkVis);
}
else{
callback.call(_this);
}
}
});
}
});
})(jQuery);
You can call this inside the $(document).ready() function and use a callback to fire when the element is shown, as so.
$(document).ready(function(){
$('#myelement').onShow(function(){
alert('this element is now shown');
});
});
It works by binding a click, keyup, and keydown event to the body to check if the element is shown, because these events are most likely to cause an element to be shown and are very frequently performed by the user. This may not be extremely elegant but gets the job done. Also, once the element is shown, these events are unbinded from the body as to not keep firing and slowing down performance.
You can't get an onshow event directly in JavaScript. Do remember that the following methods are non-standard.
IN IE you can use
onpropertychange event
Fires after the property of an element
changes
and for Mozilla
you can use
watch
Watches for a property to be assigned
a value and runs a function when that
occurs.
You could also override jQuery's default show method:
var orgShow = $.fn.show;
$.fn.show = function()
{
$(this).trigger( 'myOnShowEvent' );
orgShow.apply( this, arguments );
return this;
}
Now just bind your code to the event:
$('#foo').bind( "myOnShowEvent", function()
{
console.log( "SHOWN!" )
});
The code from this link worked for me: http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
$('#foo').on('show', function() {
console.log('#foo is now visible');
});
$('#foo').on('hide', function() {
console.log('#foo is hidden');
});
However the callback function gets called first and then the element is shown/hidden. So if you have some operation related to the same selector and it needs to be done after being shown or hidden, the temporary fix is to add a timeout for few milliseconds.

empty div not getting recognised in javascript

i am creating an empty div in the javascript DOM. but when i call some function on it, for example,
var hover = document.createElement("div");
hover.className = "hover";
overlay.appendChild(hover);
hover.onClick = alert("hi");
the onClick function isn't working. Instead it displays an alert as soon as it reaches the div creation part of the script. What am i doing wrong?
Try addEventHandler & attachEvent to attach event to an element :
if (hover.addEventListener)
{
// addEventHandler Sample :
hover.addEventListener('click',function () {
alert("hi");
},false);
}
else if (hover.attachEvent)
{
// attachEvent sample :
hover.attachEvent('onclick',function () {
alert("hi");
});
}
else
{
hover.onclick = function () { alert("hi"); };
}
You need to put the onclick in a function, something like this:
hover.onclick = function() {
alert('hi!');
}
The property name is "onclick" not "onClick". JavaScript is case sensitive.
It also takes a function. The return value of alert(someString) is not a function.

Categories