I'm attempting to do a project in which I need to change attributes on a button. I have no code for you, but I still need help. Is there any way I can change a button that's already there so that the onclick attribute runs a different function from before? Thanks in advance.
I feel like all the answers so far miss the main point. Since you don't have any code examples, I'm guessing you'll find it hard to extrapolate out what everyone is saying.
So, one button, which when clicked, changes to another method, and when clicked again, changes back. I'm using the onclick attribute for simplicity, but as others have shown, using JavaScript .onclick or addEventListener is a better choice.
function function1(e) {
// Show where we're at
alert("function1 is running");
// Get which button was clicked from the event that is passed in, and set its onclick event
e.currentTarget.setAttribute("onclick", "function2(event)");
}
function function2(e) {
// Show where we're at
alert("function2 is running");
// Get which button was clicked from the event that is passed in, and set its onclick event
e.currentTarget.setAttribute("onclick", "function1(event)");
}
<button onclick="function1(event)">Click Me!</button>
You can of course change what function1 and function2 do, and add more changes (e.g. function 3 and 4), add logic for when to change, and so on.
use .onclick = function_name;
Demo :
document.getElementById('myButton').onclick = fun2;
function fun1() {
alert('I am from Function 1');
}
function fun2() {
alert('I am from Function 2');
}
<button id='myButton' onclick='fun1()'>Click me</button>
Yes, you can. There's only one thing to keep in mind:
An event on which you want the change to happen
Once you have identified that event, just bind it with JQuery's .attr() function to change any attribute.
Read more: http://api.jquery.com/attr/
Javascript Events: https://developer.mozilla.org/en-US/docs/Web/API/Event
Use jQuery like:
$("mybtn").click(function(){
$("#mybtn").attr({
"onclick" : "anotherFunction()",
});
});
Yes, it's possible. Check this fiddle: https://jsfiddle.net/gerardofurtado/ga3k7ssp/1/
I set a variable to 0 and this function for button 1:
bt1.onclick = function(){
i++;
myPar.innerHTML = i;
};
It increases the variable and displays the number.
But, clicking on button 2, it changes button 1 function:
bt1.onclick = function(){
i--;
myPar.innerHTML = i;
};
Now button 1 decreases the variable.
This other fiddle is similar, but using radio buttons, to show that you can set the original function of button 1 back: https://jsfiddle.net/gerardofurtado/8gbLq355/1/
Related
I have a multistep form, with 4 frameset. Each one must come in when I press the "Next" button (of course)
My ES6 modular code cointains something like this:
class FormController {
// 1. describe and initiate object
constructor() {
this.nextBtn = $(".next");
this.next_fs;
....
this.events();
}
// EVENTS LISTENER
events(){
this.nextBtn.on("click", this.nextClicked.bind(this));
// other listeners
}
nextClicked() {
this.next_fs = $(this)
.parent()
.next(); // this is the next fieldset
// some actions...
}
// rest of the code
}
My problem is the following:
I need to bind "this" inside nextClicked function to be able tu use all variables and methods like this.next_fs, this.saveData(), etc...
But I also need to know which button has been clicked, and I cannot know that because this is no more "this button", and I cannot pass a variable (let's call it 'e') to trace the e.target.
What's the matter with my code? I know that's something stupid that I'm not seeing.
Thanks!
But I also need to know which button has been clicked, and I cannot know that because "this" is no more "this button", and I cannot pass a variable (let's call it 'e') to trace the e.target
The browser's event triggering code passes that. You just need to read it.
nextClicked(e) {
"...and I cannot pass a variable (let's call it 'e') to trace the e.target"
Actually, you don't need to pass it as variable, because even if you don't pass the e you can get it in nextClicked because browsers do it by default, so it will come as parameter if you declare the function as nextClicked(e){...} and keep the bind as you have.
Or, you can pass parameters after this, such as ...bind(this, this.nextBtn), then the first parameter on nextCliked will be the button.
See below these two possibilities I mentioned:
$(".buttons").on("click", this.nextClicked.bind(this))
function nextClicked(e){
//here your context is the same as when you binded the function, but you have the event
let target = e.target;
console.log(target.id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-1" class="buttons">click me 1</button>
<button id="btn-2" class="buttons">click me 2</button>
let nextButton = $("#btn-1")[0];
$(".buttons").on("click", this.nextClicked.bind(this, nextButton))
function nextClicked(nextBtn, e) {
//here your context is the same as when you binded the function,
//but you have the button AND the event
console.log("NextButton Id: " + nextBtn.id);
console.log("Clicked button Id: " + e.target.id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-1" class="buttons">next</button>
<button id="btn-2" class="buttons">previous</button>
You are doing
this.next_fs = $(this)
But, earlier you set this to an instance of FormController
this.nextBtn.on("click", this.nextClicked.bind(this));
so what you are doing is
this.next_fs = $( (FormController)this);
You are expecting jQuery to work with a class instance, instead of the event object.
I strongly discourage you from using $(this) ever in a event handling context. this can change it's meaning as you have shown in your sample by the code breaking.
Always use event.target or event.currentTarget. I prefer currentTarget as it points to the element on which the event was bound, and not a deeper lying element within that element.
so your code should be
nextClicked(e) {
this.next_fs = $(e.currentTarget)
.parent()
.next(); // this is the next fieldset
// some actions...
}
I have a button that when pressed besides doing something it changes its own id so when pressed again it does something different as if it is a different button. The problem is that after changing the id for the first time the prev button click function throws an error because the id doesn't exist anymore.
$("#button1").click(function() {
//do something
document.getElementById("#button1").id = "button2";
});
$("#button2").click(function() {
//do something different
document.getElementById("#button2").id = "button1";
});
You can accomplish this by using jQuery on, but like mentioned in comments, this might be a sign you need to change your approach. However, if you must do it this way, here is a solution using jQuery's 'on'.
http://jsfiddle.net/WetNoodles/ab5yn7eL/
$('#outerContainer').on('click', '#button1', function () {
alert('button 1 clicked!');
$(this).attr('id', 'button2');
});
$('#outerContainer').on('click', '#button2', function () {
alert('button 2 clicked!');
$(this).attr('id', 'button1');
});
Some additional notes - If you take smerny's approach, you will still need to use the 'on' function in order to bind events to changing attributes unless you have the onclick attribute set directly on the html tag. Kristian's approach would let you use the click functions like you are currently using.
I have following page:
<body>
foo
</body>
</html>
<script type="text/javascript">
function func(k){
alert(k);
$('#key').click(function() {func(++k)});
}
</script>
My expectations of this code execution following:
I click on link and see 0, then click one more time and see 1, then click one more time and see 2....then 3....4...5....6
But actual result:
I click on link and see 0,
I click on link and see 0 and then 1 twice,
I click on link one more time and see 0 2 2 2 2 and 1.
Please help to understand what does happen and and how to rewrite it?
Update
Key of the question is invocation of old function with new argument on onclick action!
you can set a global variable and increase in each function call
var globalCounter = 0;
$('#key').click(function() {
alert(globalCounter);
globalCounter++;
});
you dont need
onclick="func(0)"
in html tag because you already set click event handler with
$('#key').click(function(){});
You can simply modify your function as follows:
function func() {
if (!window.count)
window.count = 0;
alert(count++);
}
foo
Side notes:
You should add the <script> block inside your <html> document, preferably just before closing <body>
You are missing quotes around the id attribute
I rewrote function like this:
function func(k){
alert(k);
$("#key").removeAttr('onclick');
$("#key").unbind('click')
$('#key').click(function() {func(++k)});
}
and I see expected result
Currently, the inline click handler is setting k to 0 and adding a new jQuery click listener on every click. Each jQuery handler will increase the value of k on every click, and this creates a mess you can see in the alerted values.
At first, remove the inline onclick from #key. You can do it without breaking anything, just set it to null within $(document).ready():
$('#key').prop('onclick', null);
Then for the click counter, create a variable and a new click handler:
var clickCounter = 0;
$('#key').click(function () {
clickCounter += 1;
});
A live demo at jsFiddle.
You are adding a new func on each click. That is why you are seeing the new number many times, as well as the old ones.
Add these lines to remove previous handlers:
$("a").prop("onclick", null); //remove default "onclick" handler - otherwise the 0 will always continue coming
$("#key").off("click"); //remove old jQuery assigned handlers
Then send ++k to new handler.
I've got a table with different columns identified with different classes.
I've also a checkbox binded to every column.
I created a function which is called on the click of any checkbox. In this function I hide/show the column which is linked to this.
It doesn't have any javascript error, and the code is the following:
$(document).ready(function(){
$('ul input').click(function(){
//alert('yooo');
if ($(this).is(':checked')) {
//alert('checked');
$("td."+replaceAll(" ","_",$(this).val())).show();
$("th."+replaceAll(" ","_",$(this).val())).show();
//alert($("td").length);
}
else{
//alert('unselected');
$("td."+replaceAll(" ","_",$(this).val())).hide();
$("th."+replaceAll(" ","_",$(this).val())).hide();
}
});
});
However, after every click, the action has a lag (after many clicks it becomes tooooooo slow, many seconds).
I tried also with .css instead of hide-show, but it doesn't make any change.
I understood that the problem was linked only to checkbox, not on callback or on jquery function. I solved the problem simply by working with radio input, adding a "true" and a "false" radio input for every checkbox that was in the page.
Instead of running the jQuery selector on every click like below:
$("td."+replaceAll(" ","_",$(this).val()))
You could set up some sort of caching like:
var cache = {} //<-- declare this outside your click handler
//add the code below inside your click handler
className = replaceAll(" ","_",$(this).val())
if(!cache[className])
cache[className ] = $("td."+className + ", th."+className); //select all the elements once and store in the cache object
$el = cache[className];
if ($(this).is(':checked'))
$el.show();
else
$el.hide();
Unless I am mistaken. jQuery and CSS handle the :checked selector very differently. In CSS when I use :checked, styles are applied appropriately as I click around, but in jQuery it only seems to recognize what was originally in the DOM on page-load. Am I missing something?
Here is my Fiddle
In jQuery:
$('input:checked').click(function () {
$('input:checked').css('background','#FF0000');
$('input:checked+label').css('background','#ff0000');
});
In CSS:
input:checked+label {font-weight:bold;color:#5EAF1E}
UPDATE:
I should clarify that what I am looking to do is trigger behavior if a user clicks an already selected radio button.
Try setting up the handler this way:
$('body').on('click', 'input:checked', function() {
// ...
});
The way you have it, you're finding all the elements that are checked when that code runs. The above uses event bubbling so that the test is made when each "click" happens.
Inside your handler, you're updating the style for all checked elements, even though any particular click will only change one. That's not a huge deal if the number of checkboxes isn't too big.
edit — some further thought, and a helpful followup question, makes me realize that inside an event handler for a radio button "click" event, the button will always be ":checked". The value of the "checked" property is updated by the browser before the event is dispatched. (That'll be reversed if the default action of the event is prevented.)
I think it'll be necessary to add a class or use .data() to keep track of a shadow for the "checked" property. When a button is clicked, you'd see if your own flag is set; if so, that means the button was set before being clicked. If not, you set the flag. You'll also want to clear the flag of all like-named radio buttons.
You bound the event only to the inputs that were initially checked. Remove :checked from the first selector and it works as intended (but ugly.)
http://jsfiddle.net/8rDXd/19/
$('input').click(function () {
$('input:checked').css('background','#FF0000');
$('input:checked+label').css('background','#ff0000');
});
you would of course need to "undo" the css change you made with jQuery to make it go away when the input is unchecked.
$('input').click(function () {
$('input').css('background','').filter(":checked").css('background','#FF0000');
$('input+label').css('background','');
$('input:checked+label').css('background','#ff0000');
});
http://jsfiddle.net/8rDXd/20/
AFTER UPDATE
Keep track of the status of the radio buttons. For example, use .data() to keep an in-memory state of the radio buttons.
$(function () {
var $radio = $(":radio");
$radio.filter(":checked").data("checked", true);
$radio.on("click", function () {
if ($(this).data("checked")) {
alert("Already selected");
}
$radio.data("checked", false).filter(":checked").data("checked", true);
});
});
See it live here.
BEFORE UPDATE
I think you want to use .change() here.
$('input:radio').change(function () {
$('input, input+label').css('background', '');
$('input:checked, input:checked+label').css('background', '#f00');
}).change();
See it live here.