Can I catch a js triggered change event? - javascript

I can use jquery to easily catch a change event of a select option when a user clicks it, however if javascript changes the select value, the 'change' event never triggers and needs to be manually triggered.
Is it possible to catch the value changing without manually having to trigger('change')?
Example fiddle here: https://jsfiddle.net/1fhbha4o/1/

Is it possible to catch the value changing without manually having to trigger('change')?
No. No event is fired when JavaScript code sets the value of a select. So your options are:
Have a common function you call both in response to a change event and also whenever your code changes the value (perhaps centralize changing the value so you don't forget to call it).
.trigger('change')
Polling the value to see if it changes (blech).
Re #1 and #2, you could give yourself a valWithNotify:
$.fn.valWithNotify = function(arg) {
if (arguments.length == 0) {
return this.val();
}
return this.each(function() {
$(this).val(arg).trigger("js-change"); // or just "change", but I'm not a
// fan of synthetic user events
});
};

Related

Ignite UI IgCurrencyEditor

I am trying to programmatically update a currency field to run the value changed event which holds a numeric calculation. I want the value to set to zero using something like.
$('.tester').igCurrencyEditor("setFocus");
$('.tester').igCurrencyEditor('option','value', 0);
Then when I blur out, or not sure what to do here, the valueChanged event should trigger as per the API docs (It can be raised on lost focus or on spin events).
But I can't seem to trigger the value changed event, it only works when I manually click into the input and change the number.
The valueChanging and valueChanged events would trigger when a user interaction changes the displayInput value of the editor, and the corresponding valueInput value is different from the display input one. The editors have adopted the same approach as all other Ignite UI controls where events do not trigger on API calls, because when an API call is performed, the developer can choose whether to invoke their event handler after the API call, or not.
There's two things that you can do to invoke your event handler. First one is to cache the event handler method and invoke it manually:
$('.tester').igCurrencyEditor({
...
valueChanged: valueChanged,
...
});
function valueChanged(event, ui) {
// event handler
};
$('.tester').igCurrencyEditor("setFocus");
$('.tester').igCurrencyEditor('option','value', 0);
valueChanged(null, { /* if you need arguments */ });
The second one is to extend the currency editor and override the method that performs the check whether these events should be triggered, and make it always trigger the events:
$.widget("ui.igCurrencyEditorExtension", $.ui.igCurrencyEditor, {
_processValueChanging: function (value) {
this._triggerInternalValueChange(value);
}
}
The second approach requires you to switch to using the igCurrencyEditorExtension and may cause side effects, as the method performs other checks as well.
Anyways, what Alex Marinov has suggested should work, but it depends on your editor configuration, depending on whether you've set nullValue, allow null values in the editor, etc.
you need a function like this:
function clearValue() {
$('.tester').igCurrencyEditor('option','value', "");
$('.tester').igCurrencyEditor('field').blur();
}
The result will be that the displayed value inside the currency editor is "$0.00" and the valueChanged event is fired.

jgGrid and event ResetFilterToolbar

I use last version free-jqGrig by Oleg.
I know that in versions, free-jqGrid, many other events are added in difference from jqGrid.
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events#list_of_events
Has re-read many similar answers, but events don't work for me.
jqGrid 'clearToolbar' without grid reload
Here something similar, but in an example an event when pressing the custom button.
It is necessary for me that when pressing on to ClearToolbar to add the custom check on event "jqGridToolbarBeforeClear" or "jqGridToolbarAfterClear".
The main reason of your problem is the usage of wrong event. The event jqGridToolbarBeforeClear will be triggered inside of the method clearToolbar, but you want to prevent processing of reloading of the grid inside of triggerToolbar. Thus you should use jqGridToolbarBeforeSearch event instead.
The mostly correct implementation of event handler jqGridToolbarBeforeSearch looks like the following:
$("#grid").on("jqGridToolbarBeforeSearch", function (e) {
var filters = $(this).jqGrid("getGridParam", "postData").filters;
if (typeof filters === "string") {
filters = $.parseJSON(filters);
}
if (filters) {
/* add here you custom tests */
return "stop";
}
return e.result; // forward the result of the last event handler
});
The main advantage of the usage events comparing to callback is the following: one can define multiple event handlers, but only one callback. If one event returns "stop" to prevent processing then the next event could overwrite the value with another value. To allow to stop processing in case of any event handler return "stop" one should use event.result in every event handler.

How to capture change in text when that change is through javascript function. Javascript change event is not working in this case

My Code is as below.
$(document).ready(function($)
{
var form = $("#video_detail_form");
var name = $("#videoTitle");
var nameInfo = $("#valid_videoTitle");
function validateName(){
//if it's NOT valid
var titleValue=$.trim(name.val());
if(titleValue.length == 0){
nameInfo.text("Please Enter Title");
return false;
}
//if it's valid
else{
nameInfo.text("");
return true;
}
}
name.blur(validateName);
name.keyup(validateName);
name.change(validateName);
$('#editVideoCancel').click(function(){
cancelVideoDetailAjaxCall( '/video/cancelVideoDetail', callBackCancelVideoDetail);
});
});
My cancelVideoDetailAjaxCall function changes text of the videoTitle input box. But my this code is not capturing that event by name.change.
If I change manually then it captures it. So when dynamically my callback function is changing the text then change event is not capturing it.
How should I capture that change?
You can actually extend your value change catching to all changes coming from some script using the jQuery val method, by setting a custom setter in jQuery.valHooks.
Imagine you change the input type to myCustomType, then you will implement jQuery.valHooks.myCustomType.set method which will be called each time val is used to set the input value, and you will include your specific call here. But I insist : it is not a best practice.
You will surely find explicit code on the web for that hooks.
As comments have mentioned, if you programmatically change the value via jQuery you must also trigger that change programmatically, if you want anything subscribed to it to register that change.
You can always make up your own events and trigger them accordingly if you don't want to "interfere" with other things already subscribed to regular events:
$el.on('mycustomevent', function() { ... })
$el.trigger('mycustomevent');
You can even subscribe with the same callback for the 'regular event' and your 'custom event':
$el.on('change', myChangeCallback);
...
$el.on('mycustomevent', myChangeCallback);
If you don't want to keep typing $el.val('...').trigger('mycustomevent') repeatedly, then declare a helper function that does that for you:
// helper function for changing the value
function changeInput(newVal) {
if(!this.$target) this.$target = $('#text'); // stash the target for reuse
this.$target
// programmatically change the value; does not fire 'change' event
.val(newVal)
// now trigger your custom action that behaves
.trigger('customaction'); // add extra parameters, etc
}
Full example: https://jsfiddle.net/drzaus/ds6g745s/8/

waiting till an on change handler is complete before saving model

I have a User model(Backbone.js) and I want to update its settings attribute and then save it to the server. Settings is in JSON format, and the way I have it set up is that settings is the string version and settingsJSON is the object version. I bind functions to the change event of each so that when one changes, it updates the other.
The problem I am having, is that the save method is running before the changed handler is finished running. Is there any way i could ensure that all event handlers for that model are complete or something like that?
how I'm calling it:
currentUser.get('settingsJSON').apps = appsEnabled;
currentUser.save();
My event handlers:
Initialize: function() {
var that = this;
this.on("change:settingsJSON", function(model){
model.set({settings: JSON.stringify(model.get('settingsJSON'))});
});
this.on("change:settings", function(model){
model.set({settingsJSON: JSON.parse(model.get('settings'))});
});
}
#fencliff:
The change event is firing when I run this and works properly, I had it print the new settings string to the console.
Are you sure that they are called synchronously? I added console.log('changed') to the end of the .on(change) and put console.log('saved') directly after currentUser.save() and every time the console read:
saved
changed
For now I have just made it so that I stringily the JSON and save it to settings directly before I save and that works fine.
Backbone events are executed synchronously. That means that unless you (or some library) has overridden some part of the event handling, the change handlers will have processed as soon as you execute the next line of code.
In you code example there is another problem. When you call
user.get('settingsJSON').apps = appsEnabled;
The change event will not fire, because the value of settingsJSON has not been changed, merely the contents of the object were modified. The model.attributes.settingsJSON is still the same object as before.
The events are fired only when you call set on the property, and the new value is a different object. For example:
user.set('settingsJSON', _.extend({}, user.get('settingsJSON'), {apps:appsEnabled});
Another problem, it would seem, is that your event handlers, if triggered, would cause the change event being fired twice for the property which was first set:
this.on("change:settingsJSON", function(model){
//-> changes settings, and set triggers change
model.set({settings: JSON.stringify(model.get('settingsJSON'))});
});
this.on("change:settings", function(model){
//-> changes settingsJSON, and set triggers change
model.set({settingsJSON: JSON.parse(model.get('settings'))});
});
To solve that issue, call set with {silent:true} or modify the model.attributes hash directly.
Edited with corrections by #muistooshort.
Edited again with further corrections

jQuery addClass when value of hidden input changes dyamically

I have a contact form that sends a value to a hidden input on successful completion of the sendmail function. I want to detect this value change and then use it to apply a class to a div/paragraph.
I asked a similar question recently and I'm aware that this requires the script to continually check the doc after DOM is loaded but even after adding .change() it just doesn't seem to want to add the class.
Here's the jQuery:
$(document).ready(function() {
$("#acf_success_sent").change(function(){
if ($("#acf_success_sent").val() == "1"){
$("#acf_verified").addClass('gone');
}
});
});
any help would be great. here's a link to a test version of form in case you're interested, everything works except the verified symbol doesn't disappear after a successful send http://seeshell.me/forms/contact.php
There'll be no "change" event fired when code updates the value of your <input> element, so the handler you've registered won't run. What you could do however is fire "change" from a watchdog:
var watchdog = setInterval(function() {
if ($('#acf_success_sent').val() !== originalValue)
$('#acf_success_sent').trigger('change');
}, 100);
How you set up "originalValue" depends on your application. You could, for example, keep a separate ".data()" value, and watch for whenever your saved value differs from the current "value" attribute. Or you could keep the value in a closure variable:
var watchdog = (function() {
var $acfSuccessSent = $('#acf_success_sent'), cachedValue = $acfSuccessSent.val();
return function() {
if (cachedValue !== $acfSuccessSent.val())
$acfSuccessSent.trigger('change');
};
})();

Categories