I have some JavaScript/jQuery code that watches for the "changed" event on a checkbox:
$(control).change(function() {
alert("changed to: " + $(this).is(":checked"));
});
This works fine.
I'd like to create a reference to the change() function on the particular object, and call it indirectly, like so:
var onSomeChange = $(control).change;
onSomeChange(function() {
alert("changed to: " + $(this).is(":checked"));
});
I need to call it indirectly because I'll want to switch the method I'm assigning to onSomeChange with a different one, depending on the circumstances. (The single assignment to onSomeChange is just here for illustration).
This doesn't work. In Firebug I get this error:
this.bind is not a function
How can I get a reference to an object's method and call it without calling it from the object directly?
Background
The context may be significant; if there's an entirely different way to do what I want, that's fine too.
The behavior of the change event in JavaScript is a bit different for check boxes and radio buttons. A check box fires change whenever its state changes (checked or unchecked). However, radio buttons (in Firefox at least; I think it's even more complicated in other browsers) only fire a change for the radio button group as a whole. That's understandable, but I want to bind different actions to the states of the individual radio buttons. (Specifically, I want to potentially hide or show certain divs depending on the radio button states).
I think I can handle the event discrepancies by binding a custom event to each radio and then triggering it based on a change in the group. So I have extended jQuery to add a radioChange() method. This method
Now, I'd like to swap out this code with something that calls a different event-handling method depending on the type of the control. (Aside: it's because radio button seem to be handled differently than check boxes, so I have a different radio-button-specific event). I've added a radioChanged() extension method to jQuery to support this.
Now I want to have a method that registers a listener to either changed() or radioChanged() depending on the type of the object. Determining that is easy:
var change = $(control).is(":radio") ? $(control).radioChange : $(control).change;
The problem is that I can't actually call the method at the change reference without generating the error above.
Is there something else I should be doing to make this work?
Answer to original question:
You need to apply it on a object which has bind as prototype. probably enough to just pass $(control) as object in question, or perhaps $ is enough.
var $control = $(control);
var change = $control.change;
change.call( $control,
function() {
alert("changed to: " + $(this).is(":checked"));
}
);
sounds like you just need to call the bind event and pass it the targeted event string
$(control).bind($(control).is(":radio") ? "radioChange", "change", function () {});
Related
I have a modal with an accordion in it. There is an anchor tag for each image on the page that can open the modal window. Inside the modal, the accordion has slide switches where the user can choose to turn on or off a value for that image.
The undesired behavior occurs after one input has changed on a specific image. I am receiving the value of the input values that were previously changed as well.
What I would like to see is for each image to have it own values, that is, the values that were changed specific to that image. I shouldn't see the values from any other image. In addition, if I change the value of a specific image to
true, I don't want to see that value set to true for any other image. I hope this all makes sense. I'm not very savvy with JavaScript but I've tried to explain as best I can.
This is what the JavaScript looks like
$(".glyphicon-tags").on('click', function(){
var iid = $(this).data('iid'); // this is the imageId
$(".onoffswitch ").on("click", function(){
var tid = $(this).data('tid'); // this is the tagId
alert(iid + ' ' + tid);
});
});
Using
$(".onoffswitch ").off("click").on("click", function(){
should fix it.
The way you've got it now, every time glyphicon-tags is clicked, you just keep on adding extra event handlers for "onoffswitch" and never removing the old ones. Next time onoffswitch is clicked, it runs all the defined event handlers. Setting an event handler on an element doesn't remove the old one (unless you're running IE6 or something), it adds an extra one to the existing list of handlers.
The "off" method removes previously defined event handlers on an element. See http://api.jquery.com/off/ for more details of the options you can pass in etc.
I'm writing a simple single page application with Express.js. At the bottom of the page is a form, and this form is used to add users to a table, or to update a specific user. The 'submit' button will have a different function depending on the ID of the button at the time it is pressed.
Inside my document.ready function, I have 2 lines of interest:
$('#btnAddUser').on('click', addUser);
$('#btnUpdateUser').on('click', updateUser);
I also have methods that change the value of this id from #btnAddUser to #btnUpdateUser, and vice versa. I can get the ID to change. The issue is that the document.ready function doesn't seem to consider these changes.
For instance, the app starts out with the id #btnAddUser. Then I change it to have the Id #updateUser, and I can see that this works. When I press the button, though, the addUser method fires instead of the updateUser method, and I'm not sure why.
Pointy's answer should work, but this is an X->Y problem. You shouldn't be trying to toggle functionality by changing an element's ID.
Instead, store a value somewhere that says what the button should do, and then use that. You could use a data-* attribute on the button if you want:
<!-- Dynamically change data-action and value as needed -->
<input id="btnUserAction" type="button" data-action="add" value="Add" />
$('#btnUserAction').on('click', function (e) {
var action = ($(this).data("action") === "add") ? addUser : updateUser;
action.call(this, e);
});
Alternatively, you could have two separate buttons and show/hide them. Either approach should work.
You can get the effect you want by using event delegation to set up the handlers:
$(document).on('click', '#btnAddUser', addUser);
$(document).on('click', '#btnUpdateUser', updateUser);
By doing it that way, you defer the inspection of the element until the time a "click" actually happens. With your code, the elements were located at the time the handlers were assigned. After that, it doesn't matter what the "id" value is because the handler is directly associated with the DOM node (via an internal map that jQuery maintains).
This won't work, because the click event is assigned one time when ready function executes. I think the better way is to have two buttons and show/hide them instead of changing the id.
Another way would be to store the action you want in an attribute:
$('#mybutton').click(function() {
var action = $(this).attr("data-action");
if(action == "do_this")
// ...
});
And for changing the action:
$('#mybutton').attr("data-action", "do_this");
I have a select inside HTML
<select id="league" name="league">
which I'm listening for changes inside my javascript.
var league = dojo.byId("league");
dojo.connect(league, "onchange", function (evt) { //do stuff }
Which works fine.
However I have a link that I can click which updates the select:
League
The link works as it updates the selected value of the select with the following function.
function updateSelection(NewLeague){
dojo.byId('league').value = NewLeague; // works
dojo.byId('league').onChange; //this isnt working
//dojo.byId('league').onChange(); //this throws: TypeError: dojo.byId("league").onChange is not a function
}
My problem, as I've read through other stack posts is that programmatically updating the value wont trigger onChange, thus I need to call onchange in the code (shown above). As per the comments inline, the onChange isn't being triggered or throws an error. My first thought that it has something to do with the dojo.Connect which listens for onChange, but I havent found any information that says I cant do this, nor any explanation how to get around it.
Any ideas?
Select onchange doesn't fire for programattic changes, you need to fire it yourself with league.onchange();
As noted by #Greg, the call should be lowercase.
Additionally, I don't know if dojo has a trigger method, but in jQuery this would be done as jQuery('#league').trigger('change').
Depending on your version of dojo you may also want to check: http://dojotoolkit.org/reference-guide/1.8/dojo/connect.html
Have you tried just calling the select by it's id using normal js?
document.getElementById('league').onchange.call();
As others have said, you need to trigger the event yourself, just setting the value does not do that. See the code on How to trigger event in JavaScript? to see how in a cross-browser way.
The server sends some JSON. It contains a list of structured data. I display this data as a list of textboxes, each of which has its own onClick event. On click, the value of the textbox is set to whatever is in the structured data (which is an unique ID, which means that each textbox should display the ID on click).
When I first click on any textbox, its value is set correctly -- with the ID from the data from the server. But as I click on other textboxes, they display IDs from the first-click textbox!
I've tried both closure var and $.proxy(), but they doesn't seem to work. I've checked the contents of myAttribute and they change on each iteration of the $.each() function. The click() event, however, seems to be evaluated at "runtime" and doesn't update.
The questions are:
How do I fix my problem, so that myProcessedAttribute will contain the correct data instead of the data on first click?
I feel my approach of having four nested functions might not be best practice.. Or is it?
Code:
$.ajax({
[...]
success: function (data) {
[...]
$.each(data.listOfData, function () {
[...]
var myAttribute = this.myCoolAttribute; // <-- closure
jQuery('<p/>')
[...]
.click(function () {
var myProcessedAttribute = process(myAttribute);
[jquery ui dialog...]
create: function () {
// it always contains the same data
// the data on first click, after that, it never changes.
$("#myDialog").html(myProcessedAttribute);
}
});
});
}
});
EDIT: I've just put alert(myProcessedAttribute) in click() and create events. In the former event, the alert displayed correct data. In latter event, the alert was displayed only on first click, but it never appeared again on subsequent clicks!
MY SOLUTION: I thought that on calling .dialog({...}) the new dialog replaces the old one, but I was wrong. I've solved the problem by destroying the old dialog before creating a new one.
BETTER SOLUTION: See answer below.
"create" event is called when dialog is created.
Second time you open dialog, create event is not fired, because dialog object already exist on that element.
If you want different values on same dialog widget, use "open" event.
This is a sample
http://jsfiddle.net/RaWrC/
I have several field
$("#a1").change(function(){
console.log('fire'); });
but when value change not user event not work
form[0].val = 100;
event not work
how can i catch this change data ?
ps data changes from different places not my code suggestions like trigger('change') not good idea
I do not think that events will fire when you set the value in that fashion.
Does it work when you set the value of the element in the browser?
What you can do is call form[0].change(), and it should work.
Changing the value property will not fire the change event.
In fact, your code should be changing value and not val.
You could call it explicitly after updating it.
form[0].value = 100;
form.change();
But you mention that is not an option.
The only other way is to poll for changes.
You could define a way of working with the controls inside your form. Create a javascript function that external developers can call to set the value of a given field and make them use that method. Then you can fire change or do whatever you want to your hearts content.