JQuery function not working on element after ID has been changed - javascript

I've got a button and I want it to perform one function every odd time that it is clicked (1st, 3rd, 5th, etc) and a second function every even time that it is clicked (2nd, 4th, 6th, etc). I thought the best way to do this would be to change the id of the button and assign two JQuery functions. However, that doesn't seem to work. As you can see in this jsfiddle, when I change the id of the button, the function from the first id still gets called.
$("#search").click(function() {
alert("search clicked!");
$("#search").html("Close Search");
$("#search").attr("id", "csearch");
});
$("#csearch").click(function() {
alert("csearch clicked!");
$("#csearch").html("Search");
$("#csearch").attr("id", "csearch");
});
Why is that the case? Is it because JQuery essentially binds the function to the button when the document loads, so even though I change the id, the function is still bound?
p.s. I already found another solution to my problem, so I'm not interested in answers in that regard. Just looking to learn a little more about JQuery and Javascript.

Yes, jQuery will run through your initialization code once, when the document loads, and attach the click handlers to elements currently in the DOM. When your code runs, only the #search element exists - the $("#csearch") selector will match no elements and the click handler won't be assigned to any elements.
A jQuery object references a DOM element by reference, not by id - when you change the id of an element, a jQuery object created previously that pointed to that element will still hold a reference to the element.

If you change dynamically data in HTML you have appeal to body, because separator ('#csearch') doesnt exist after load page. Try it:
$(document).ready(function() {
$('body').on('click','#search', function() {
alert("search clicked!");
$("#search").html("Close Search");
$("#search").attr("id", "csearch");
});
$('body').on('click','#csearch', function() {
alert("csearch clicked!");
$("#csearch").html("Search");
$("#csearch").attr("id", "search");
});
})

Although you have found another way to go, a nice way to do this is to use the modulus operator (%) which can be used to return a 0 or 1.You could assign a value to the button and on the onclick - pass that value to a function where you check the returned value (ie:var number=value%2) which will give either a 0 if the number is even or a 1 if it is odd. You can then use that to direct the action of the button click - if number ==0 then do this, if it is ==1 then do that.
You then increment the count and reset the value of the button for the next click. That way you do not have to change the id of the button- you just change its behaviour. Just a thought for a method of toggling the effect of a button click :)

Look up event delegation - there's plenty of answers on SO that explain it in detail.
As for your solution - just add a data value to the button and toggle it / read it on each click. Then there's no need to change the id, so no need to change the event handler:
$("#search").click(function() {
var oddeven = $(this).data("oddeven") || 1;
if (oddeven == 1) {
alert("search clicked!");
$(this).html("Close Search");
$(this).data("oddeven", 2)
}
else {
alert("csearch clicked!");
$(this).html("Search");
$(this).data("oddeven", 1)
}
});
Updated fiddle: https://jsfiddle.net/vxn3ozzb/1/
Alternatively, you could have two buttons and toggle between them:
<button id="search" class="btn btn-default action-button shiny-bound-input" type="button">
Search
</button>
<button id="csearch" class="btn btn-default action-button shiny-bound-input" type="button" style='display:none'>
Close Search
</button>
code
$("#search").click(function() {
alert("search clicked!");
$(this).hide();
$("#csearch").show();
});
$("#csearch").click(function() {
alert("close search clicked!");
$(this).hide();
$("#search").show();
});
Fiddle: https://jsfiddle.net/vxn3ozzb/2/

You need to use event delegation, instead of binding when dealing with elements with changing selectors.
$(document).ready(function() {
$(document).on("click","#search",function() {
alert("search clicked!");
$("#search").html("Close Search");
$("#search").attr("id", "csearch");
});
$(document).on("click","#csearch",function() {
alert("csearch clicked!");
$("#csearch").html("Search");
$("#csearch").attr("id", "csearch");
});
})
Working example : https://jsfiddle.net/DinoMyte/vxn3ozzb/4/

I believe, changing the ID of an element would not be an appropriate idea for this particular scenario. Instead, it's better to use data attributes to accomplish this. For example, Instead of changing the ID, you could change the data attribute value to track it and then you can apply your logic accordingly. This way in future, if you want to add additional behaviour to the button (odd, even and somethingElse), you don't need to write an additional event handler, just need to add one more condition to the same event handler. Going forward, if the behaviours of the button are increasing, you can separate the logic out and put it into one function by passing the behaviour value to it, that way your event handler will be much cleaner and manageable.
Please suggest if anyone has a better solution.
$(document).ready(function() {
$("#search").on("click", function() {
var action = $(this).data("action");
if(action === "odd") {
$(this).data("action", "even");
alert("odd");
}
else if (action === "even") {
$(this).data("action", "odd");
alert("even");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<button id="search" data-action="odd" class="btn btn-default action-button shiny- bound-input" type="button">
Search
</button>
</div>

Related

Cannot get button's onclick attribute to invoke JS function

I have a simple form that, in jsfiddle I've simplified even further:
https://jsfiddle.net/mvw1nt5L/
Basically I have a table with just a header row. Above it I have an "Add" button which each time it gets clicked is supposed to add a row to the table.
my button element is ...
<button id="addMeeting" type="button" onclick="addMeeting();" > Add A Meeting </button>
and the associated JS function is simply
function addMeeting() {
alert("add button clicked");
return false;
}
Real, real simple! But it doesn't work.
the JS code is contained directly in the html document as a script tag.
What am I doing wrong?
TIA for any help!
Gus
It is a conflict between an element ID on your form and the function name. Or maybe not so much a conflict as a scoping issue. I've honestly never encountered this before until I tried to solve your problem. Very strange. Here's a more detailed explanation:
Why JS function name conflicts with element ID?
it seems it's a loading and scope issue. If you place a script tag before the html it will work just fine:
<script>
function addMeeting() {
alert("add button clicked");
return false;
}
</script>
<button id="addMeeting" type="button" onclick="addMeeting()"> Add A Meeting </button>
alternatively you can also explicit use the window object:
window.addMeeting = function() {
alert("add button clicked");
return false;
}
and:
<button id="addMeeting5" type="button" onclick="window.addMeeting();"> Add A Meeting </button>

How to change image when two buttons are clicked?

I want to make jQuery script where I will have 10 buttons all with different colors and after user clicks on two different buttons, combination of the clicked buttons colors will be made and switch the image frame with already prepared images based on color combinations.
My question is how to put conditions for two buttons(or links) clicked.
switch me
<img src="http://placehold.it/333/fe3/img/picture2.jpg" id="bg" />
$(function() {
$('.menulink').click(function(e){
e.preventDefault();
$("#bg").attr('src',"http://placehold.it/333/3ef/img/picture1.jpg");
});
});
I want to achieve something like this but I want image to change when two buttons (or links) are clicked.
http://jsfiddle.net/maniator/Sevdm/
provided you wanted to make sure the buttons were unique when clicked, you'll want a way of tracking which have been seen. I'm using a JS Object like a Set here for compat with older browsers.
var clickCount = 0;//count the clicks
var clickTracker = {};//track which id's were clicked
var clickThreshold = 2;//the number of clicks we want before executing the if block
function clickHandler(){//callback function for the event
if(clickTracker[this.id] === undefined){//we haven't seen this id yet
clickCount++;//increment the number of buttons clicked
clickTracker[this.id] = 1;//flag for tracking the click
if(clickCount >= clickThreshold){//we saw at least clickThreshold clicks
console.log(clickCount + 'unique clicks happened!');
//your work here
}
}
}
$('.cls').click(clickHandler);//bind events
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='btn1' class='cls'>1</button>
<button id='btn2' class='cls'>2</button>
<button id='btn3' class='cls'>3</button>
<button id='btn4' class='cls'>4</button>
<button id='btn5' class='cls'>5</button>
You can use event delegation to track clicks on .menulink elements. using e.delegateTarget we can have the parent container hold a variable that determines if a .menulink element has been clicked previously, and if it has, we can have it change the background.
To do this I switched the click method to an on method. The on methods parameters are:
$(element).on(event, delegated selector, function)
JQuery .on documentation
Delegation simply means that instead of checking if each button has been clicked by placing an event on the button, we place an event on the container of the buttons and ask if the element that caused the event matches our delegated selector. If it does the provided function is fired. To access the parent of the delegated element within the code we can use the passed back event object, or in this case e.delegateTarget
JQuery delegateTarget documentation
Since everything in JavaScript is an Object, we can assign new properties and methods to anything that is not explicitly part of the Browser's most base architecture. This absolutely includes the body of a page.
In the code below, I place a new property clicked on the body of the page. This is added on click of the first .menulink element, and is checked upon each subsequent click.
Because of this we can know if it is a second click by determining if body.clicked is true. If it is we tell the script to change the background image.
$(function() {
$('body').on("click", ".menulink", function(e){
if(e.delegateTarget.clicked) $("#bg").attr('src',"http://placehold.it/333/3ef/img/picture1.jpg");
else e.delegateTarget.clicked = true;
e.preventDefault();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
switch me
switch me
<img src="http://placehold.it/333/fe3/img/picture2.jpg" id="bg" />
This is what I was looking for
<script>
$(document).ready(function() {
var chosenColors = [];
$(".colors button").click(function() {
chosenColors.push($(this).text())
check();
});
function check() {
if (chosenColors.length === 2) {
$(".pretty-picture").attr("src", chosenColors.sort().join("-") + ".png")
chosenColors = [];
}
}
});
</script>
<body>
<div class=colors>
<button type="button">red</button>
<button type="button">yellow</button>
<button type="button">blue</button>
</div>
<img class="pretty-picture">
</body>

How to disable the click on an icon after one click?

After clicking on the icon with ids (#prevleft and #nextright) , an ajax function is called. During the time ajax function loads a new table, I want to disable the icon click.
HTML Code:
hrHTML='<tr><th colspan="5"><i class="icon icon-chevron-left icon-2x lr"
style="float:left;" title="Previous Five Weeks"
id="prevleft"></i>' +"Weekly Utilization"+'<i class="icon icon-chevron-right
icon-2x lr" style="float:right;" title="Next Five Weeks" id="nextright"
></i></th>
</tr>';
The table row is appended dynamically as shown above. Want to disable #prevleft and #nextright after one click.
The following line doesn't work:
$('#prevleft').prop("disabled", true);
I am new to coding, so all help is appreciated.
Just check with the version of the jquery your using, I hope that your using jquery 1.5 or below
For jQuery 1.6+
Use can use .prop() function:
$('#prevleft').prop("disabled", true);
$("#nextright").prop("disabled", true);
For jQuery 1.5 and below
You need to use .attr() and disable the icon
$("#prevleft").attr('disabled','disabled');
$("#nextright").attr('disabled','disabled');
and for re enable the icon (remove attribute entirely):
$("#nextright").removeAttr('disabled');
$("#prevleft").removeAttr('disabled');
Assuming you have an event handler on a icon, in any version of jQuery you can use the following property to check if your icon is enabled or not
if (this.disabled){
// your logic here
}
Bind simple a click event when clicked on prevleft and prevright id icon.
$("body").on("click","#prevleft ,#prevright",function(){
var _this = $(this);
$(this).prop("disabled","true");
// ajax call code right here
// on ajax success function right this line
success: function(resp){
_this.prop("disabled","false");
}});
})
You have attached an event listener to one or more elements that do not yet exist in document. You can use event delegation, or jQuery() function to attach event to element when created.
Pass html string to jQuery(), use .find() to get "#prevleft", #nextright selectors, attach click event using .one(), append jQuery() object to document
$(elementWherehrHTMLIsAppended)
.append(
$(hrHTML)
.find("#prevleft, #nextright")
.one("click", function() {
$(this).prop("disabled", true)
}).end()
);
You can add a class to the element and check for the class when the user clicks.
For example:
$('#prevleft').click(function(){
if($(this).hasClass('clicked')){
// do nothing or return false
}else{
// ajax call
// on a successful call you can add the class using:
$('#prevleft').addClass('clicked');
}
});
Let me know if this is what you were asking for. This also gives you the ability to add an alert or do something if the button was already clicked.
Hope this helped!
Try my code, this event only called when icon hasn't class 'clicked', in the first call we will add 'clicked' class to prevent this event from this time.
$('#prevleft:not(.clicked), #nextright:not(.clicked)').on('click', function(){
$(this).addClass('clicked');
});
Hope this can help you!

Clicking on a button that has onClick already on

I know this sounds silly, but I need to create a function that finds a button that has onClick attached to it. And then clicks it.
So like:
<div onclick="coolFunction()" class="coolClass">
<p>Click Me!</p>
</div>
I tried searching for it by doing something like this:
$('.coolClass').attr('onClick') == 'coolFunction()'
Which did actually find it, the problem is I don't understand how can I click on it because it's in an if method.
Your selector would be something more like $('[onclick="coolFunction()"]').
So to do what you describe, you could do this
$('[onclick="coolFunction()"]').trigger('click');
Although, unless coolFunction() cares about being explicitly by this DOM element, you could just call coolFunction(), without having it piggy-back on your click handler.
Update: With an argument
// Note selector is less specific, but still targeted
$('[onclick^="coolFunction"]').trigger('click');
With, this, you can trigger the click handler, and coolFunction(var) in your HTML would work as expected.
if ( $('.coolClass').attr('onClick') == 'coolFunction()' )
{
$('.coolClass').click();
}
$('.coolClass').each(function() {
$this = $(this);
if ($this.attr('onClick') == 'coolFunction()') {
$this.trigger('click')
}
});
This will select all elements with .coolClass, check if the onClick attribute matches the coolFunction call and trigger the click event on that element.
As couzzi said, you can first verify if all the elements of the class coolClass have the attribut coolFunction and when it's the case you can just apply what you want to do on them.
$('.coolClass').each(function() {
$this = $(this);
if ($this.attr('onClick') == 'coolFunction()') {
$this.trigger('click')
}

javascript, 2 different function on a unique button, with 2 events

I want to build a JS script, to add 2 onClick events in 1 single button. This 2 events must works separately:
ex.
first click on button: event A
second click on the same button: event B
that's my code:
html button: press it once to how a div, press it again to show another div
<button id="add-form" class="add"><a class="btn" href="#"><i class="fa fa-plus-circle fa-2x"></i></a></button>-->
...
...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
the 2 div are hidden at start
$("#div2").hide();
$("#div3").hide()
that's the function to(try) show the 2 divs, once at time
$("#add-form").click(function(){
$("#viaggio2").fadeIn();
}$("#add-form").click(function(){
("#viaggio3").fadeIn();
});
});
</script>
PS. Sorry for my bad english, and ty everyone who try to help me! :)
you can do this simply in jQuery
$( "#target" ).toggle(function() {
alert( "calling function 1" );
}, function() {
alert( "calling function 2" );
});
Docs
If more than two handlers are provided, .toggle() will cycle among all of them. For example, if there are three handlers, then the first handler will be called on the first click, the fourth click, the seventh click, and so on.
Note
This method signature was deprecated in jQuery 1.8 and removed in
jQuery 1.9. jQuery also provides an animation method named .toggle()
that toggles the visibility of elements. Whether the animation or the
event method is fired depends on the set of arguments passed.
But to your requirement it can be done easily with toggleClass
$("#add-form").click(function(){
$(this).toggleClass("add-form add-form2")
$("#viaggio2").fadeIn();})
$("#add-form2").click(function(){
$(this).toggleClass("add-form add-form2")
$("#viaggio3").fadeIn();})
You can attach one event but with counter for ex:
var condition = 0;
document.querySelector('.my-button').addEventListener('click', function() {
if(condition === 0) { /* logic 1 */
else if (condition === 1) { /* logic 2 */}
condition++;
});
The jQuery .toggle() method has some elegance to it, but it does come with some extra functionality you may not be expecting. Be sure to read the documentation before implementing.
A more vanilla approach would be something like this:
// keep track of button clicks
var buttonClickCount = 0;
document.getElementById('myButton').addEventListener('click', function(){
// increment the button click count
++buttonClickCount;
// on the first click, eventA
if(buttonClickCount===1){
eventA();
}
// on the second click, eventB
if(buttonClickCount===2){
eventB();
}
});
function eventA(){
console.log('Event A');
}
function eventB(){
console.log('Event B');
}

Categories