JQuery blur is not working after DDL item chage - javascript

I am using ASP.NET 4.5 to develop my application. In my application I have a dropdownlist (DDL) and some textbox controls. The textbox controls are holding some numeric values. There are some calculations depending upon the values in the textboxes and calculation will occur when any of the controls go out of focus. I have used the blur event for this purpose:
$("#MainContent_txtQty").blur(function () {
alert('1');
var Qty = $("#MainContent_txtNewQty");
}
$("#MainContent_txtRate").blur(function () {
alert('1');
var Qty = $("#MainContent_txtNewQty");
}
However when I change the DDL item the blur is not working. I have placed all my controls inside an update panel.

UpdatePanel could load asynchronously, so maybe the DDL is not the same that had the event subscription when his value is not changed.
To intercept the load of the updatepanel, try this:
<script>
///<summary>
/// This will fire on initial page load,
/// and all subsequent partial page updates made
/// by any update panel on the page
///</summary>
function pageLoad(){
///SELECT DDL AND SUBSCRIBE BLUR HERE
}
</script>
This pageLoad() function should be called when the updatePanel chenges, so you can try to select DDL "again" (to be explicit, again is a wrong term because the DDL is a new DDL, not the same that was before, even if has the same ID) and subscribe the blur event here
The result should be the subscription of the new DDL element every time that the update panel changes

Related

How to determine if an Element was created dynamically

I have an existing system built using jQuery, Backbone.js and a REST-ish back-end written in C#. The application is an SPA with forms to fill and navigation. My job is to build a "Navigation Interceptor" to connect on the application so the system detects whether a field was modified in the current view so that when the user navigates, he will be warned that fields were modified and be requested to save or cancel the changes.
The way I designed it is using jQuery. To make it short, I use a selector on input, select, etc.. and bind a change event to it. Then I use a selector on links and buttons, unbind all click events, bind my "interceptor" (if a field has changed, ask before navigating) and then rebind all click events after my interceptor. I use stopImmediatePropagation() to cancel the regular navigation events, resulting in a kind of wrapper around the events.
By doing so, I have 2 problems:
Calling .val() on a field does not trigger the change event which is fine since I populate the fields dynamically. The problem is that the bootstrap date pickers does not seem to be setting the value using .val() resulting in all date fields having the "changed" state when initialized.
Elements dynamically created (e.g.: field in accordion panel created after the page has loaded) don't accept the events resulting in forms not firing the change event of my navigation interceptor.
My question is regarding the 2 above elements:
Is there a way to determine if a specific field is a date picker and bind the change event on that field so that when I populate it, the change event does not fire, but when the users do, it does (I tried binding on the changeDate event but the setDate method seems to be firing the changeDate event also)?
Is there a way to determine if the element was dynamically created (e.g.: $(''))? The problem is that I do not have a specific selector for a single field, so I think I cannot use delegation ($(document).on('change', 'someFieldSelectorICannotKnow', function () {});). All I have is a handle on the jQuery element ($(this) in a .each(fn) iteration).
#2 Solved using event delegation on all fields and skipping the handler if the field is not a form field
Solution of #2:
NavigationInterceptor.prototype.bindChangeEventOnAllEditableFields = function () {
var self = this;
var fieldsSelector = $(this.configuration.selectors.formFields.join(', '));
$(fieldsSelector).each(function () {
var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, $(this));
if (isFormField && self.configuration.debug.highlight.fields.unchanged && $(this).attr('type') === 'radio') {
$(this).parent().css('background-color', self.configuration.debug.highlight.fields.unchanged);
} else if (isFormField && self.configuration.debug.highlight.fields.unchanged) {
$(this).css('background-color', self.configuration.debug.highlight.fields.unchanged);
}
});
$(document).on('change', fieldsSelector, function (event) {
var field = $(event.target);
var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, field);
if (isFormField) {
self.hasFieldChanged = true;
if (self.configuration.debug.highlight.fields.changed) {
if (field.attr('type') === 'radio') {
field.parent().css('background-color', self.configuration.debug.highlight.fields.changed);
} else {
field.css('background-color', self.configuration.debug.highlight.fields.changed);
}
}
}
});
return this;
}
var unchangeable_classes = ['decorative', 'constant'];
$(document).on('change', 'input,select,textarea', function () {
var $this=$(this);
for(var i =0;i<unchangeable_classes.length;++i){
if($this.hasClass(unchangeable_classes[i]))
return;
}
global_changed = true;
});
Why doesn't this work, it should? (Edited in response to comment.)
My thoughts>>
1)A way to stop calling changeDate() after calling setDate(), you could just call event.stopPropogation(), it will prevent the event from bubbling up
2)while creating a dynamic element, you could add any property of your wish. For eg
var iDiv = document.createElement('div');
iDiv.isDynamic = true;
then while iterating through the element, check for isDynamic property
Why not add a benign class tag to the element
$('#foo').addClass('bar');
then you can check for the class to see if it was created
if ($('#foo').hasClass('bar'))
alert('was created');
Note that when you add elements you have to re-attach the events. So if you have a global document event and then add an element, that element won't be included unless you explicitly attach the new element.
I'm posting the answer for my question #1.
What I did is modify bootstrap's source. When calling setDate like so:
$('#myDateInput').datepicker('setDate', new Date());
The code goes through the function setDates which calls update and setValue, the first one resulting in the date being set in the datepicker itself, the second one setting only the value in the input text field. What I did is remove the call to 'change' which triggers the change event on the field and left the custom event 'dateChange'. This results in my code not firing the change event when I call setDate, but calls it when the user sets a date using the picker itself.

Kendo numeric textbox change event without lost focus

Is it possible to configure the kendo numeric textbox that my bound view model will receive an update when i click on the spin or change the numbers with keys? At the moment, only if the numeric text box lose the focus my view model will receive the update event.
The kendo databinding option data-value-update ... has sadly no effect on numeric text boxes
Thanks for any help
I know it's kinda late but here is my solution:
var numericBox = $("#yournumericinput").data("kendoNumericTextBox");
.
.
.
numericBox.element.on("keyup", function (e) {
var newValue = e.target.value;
numericBox.value(newValue);
numericBox.trigger("change");
});
That way the change event gets triggered immediately after the user has entered a new value, without having to wait for the blur event. Data validation checks are removed for brevity, but I advise you perform those as well.
And you could also bind the spin listener to trigger the change event.
numericBox.bind("spin", function (e) {
this.trigger("change");
});
You can try the below code. It works for me.
ViewModel
viewModel.bind("change", function (e) {
console.log("property Changed on spin ");
});
Razor code
<input id="tbSlideDuration" data-role="numerictextbox"
data-format="#"
data-min="1"
data-max="100"
data-bind="value:slideDuration, events: {spin:change}" />
this will call the change event under the hood :)

Handling HTML SELECT Options with event delegation to javascript on iPhone Safari

We are developing a web application with GUI customized to use on iPhone. A page on the app has 3 subsequent SELECT dropdowns, where selection of an option from 1st dropdown derives the options for 2nd dropdown, and so forth. The subsequent dropdown options are populated by javascript based on onchange event on previous dropdown.
The problem is that, on iPhone the options for a SELECT appears with 'prev' and 'next' links to move to previous and next control. When the 'next' link is clicked, then the control moves to next SELECT and displays the options. The javascript is triggered by onchange event for previous SELECT and populates the options for next SELECT. But on dropdown for 2nd SELECT displays the previous options before it is repopulated by the javascript.
Is there a workaround or event that can sequence execution of javascript and then selection of next control? Is there any event that can be triggered when a SELECT option is selected and before control leaves the SELECT element? Is there a handle for Next and Previous links for SELECT dropdown option display?
Maybe you could use the focus event, in jQuery this would be:
$('#select2').focus(function () {
// update select2's elements
});
Although the real question is when the iPhone overload comes in, and when the event get fired. And also can the select options be changed whilst in this view.
I had the same problem on my site. I was able to fix it by manually polling the selectedIndex property on the select control. That way it fires as soon as you "check" the item in the list. Here's a jQuery plugin I wrote to do this:
$.fn.quickChange = function(handler) {
return this.each(function() {
var self = this;
self.qcindex = self.selectedIndex;
var interval;
function handleChange() {
if (self.selectedIndex != self.qcindex) {
self.qcindex = self.selectedIndex;
handler.apply(self);
}
}
$(self).focus(function() {
interval = setInterval(handleChange, 100);
}).blur(function() { window.clearInterval(interval); })
.change(handleChange); //also wire the change event in case the interval technique isn't supported (chrome on android)
});
};
You use it just like you would use the "change" event. For instance:
$("#mySelect1").quickChange(function() {
var currVal = $(this).val();
//populate mySelect2
});
Edit: Android does not focus the select when you tap it to select a new value, but it also does not have the same problem that iphone does. So fix it by also wiring the old change event.

Disable asp.net button on when clicked

I have the javascript code below which disables an asp.net button during page postback. I also have a dropdownlist whose Autopostback property is set to true. Unfortunately, when i change the selectedItem in the dropdownlist, the button is disabled.
I want the Button disabled only when the page postback is caused by that same button, but not any other control on the page.
Some one please help on what change i should make to the code below to achieve this.
<script type="text/javascript">
// Get a reference to the PageRequestManager.
var prm = Sys.WebForms.PageRequestManager.getInstance();
// Using that prm reference, hook _initializeRequest
// and _endRequest, to run our code at the begin and end
// of any async postbacks that occur.
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
// Executed anytime an async postback occurs.
function InitializeRequest(sender, args) {
// Change the Container div's CSS class to .Progress.
$get('Container').className = 'Progress';
// Get a reference to the element that raised the postback,
// and disables it.
$get(args._postBackElement.id).disabled = true;
}
// Executed when the async postback completes.
function EndRequest(sender, args) {
// Change the Container div's class back to .Normal.
$get('Container').className = 'Normal';
// Get a reference to the element that raised the postback
// which is completing, and enable it.
$get(sender._postBackSettings.sourceElement.id).disabled = false;
}
</script>
Well, you're hooking into any asynchrous postback, sounds like you just want to hook into a particular button's postback.
However, you could fix this with minimal code adjustment, just by checking the ID of the control which triggered the postback before disabling it.
if (args._postBackElement.id == idOfTheButton)
$get(args._postBackElement.id).disabled = true;
Of course, if your button is a server-side button (asp:button), then you would need to either render out the client-id to the client from the server, or access it directly:
if (args._postBackElement.id == '<%= YourButton.ClientId %>')
$get(args._postBackElement.id).disabled = true;
As i said, there are better solutions than this (like only hooking into the postback event of the button, not any postback event).
But nonetheless, this should solve your problem.
You are referencing the id of the button here:
$get(args._postBackElement.id).disabled = true;
So all you need to do is to check the value of the ID prior to setting it to disabled:
if(args._postBackElement.id == '<%=MyButton.ClientID %>')
$get(args._postBackElement.id).disabled = true;

Checkbox onchange function

I have a page with a set of checkbox's, that I want to run a Javascript function on when there is a change (I have done something very similar with dropdown's - and that worked)
However with the checkbox's I have three problems:
my onChange event only runs "sometimes" (you have to change the focus between the different checkbox controls
when it does run it is returning the result of the previous checkbox (not the one just clicked on)
the jQuery always return the value true
Checkbox creation
<%= Html.CheckBox("sl-" + row.Id, value, new { onChange = "SuitabilityChecked("+row.Id+", "+key+")"})%>
Javascript
function SuitabilityChecked(providerId, parentRecordId) {
var params = {};
params.providerId = providerId;
params.parentRecordId = parentRecordId;
var value = $("#sl-" + providerId).val();
params.value = value;
$.getJSON("SuitabilityChecked", params, null);
};
Browsers are funny about radio buttons and check boxes and can delay the onchange until focus change. Try adding an onclick event to blur or call the change event directly.
Maybe something like this using jQuery Live (untested, off the top of my head):
$(':checkbox').live('click', function() { $(this).change(); });
What's happening:
Checkbox A clicked
Checkbox B clicked
Checkbox A has lost focus and fires onChange
Which makes it seem as if Checkbox B is returning the result of Checkbox A. If you were to press Tab after clicking Checkbox B in this scenario, you'd notice that its onChange would fire.

Categories

Resources