Knockout JS: Change event not firing for HTML5 date on iPad - html

I am using Knockout JS library to bind the HTML5 input controls in my Web application which is intended to run on iPad (iOS5, Safari 5.1). The binding works fine for the input types like text and select but not for date. After selecting a date value through the datepicker the value is not getting bound to the viewModel property (in effect not getting saved).
This is how my HTML looks.
<input id="dob" name="dob" type="date" data-bind="value: dob" />
I tried to work around with a custom binding where I initialized a change event handler.
ko.bindingHandlers.datePicker = {
init: function (element, valueAccessor) {
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).val(value);
}
};
Changing the HTML code to -
<input id="dob" name="dob" type="date" data-bind="datePicker: dob" />
Strangely, even that event is not firing. Please note that in both of the scenarios the binding happens perfectly in Windows XP on Opera and Safari browsers.
Ultimately, I got the solution to my problem by using the 'blur' event instead of 'change' in the custom binding. Now the event handler is being called and I am manually setting the value from the date control.
Now my question is, is it something that I am not doing correctly and if not then why doesn't the change event of the HTML5 date control not fire, whether by default or through custom binding? I want the date control to work as it is supposed to.

You are not doing anything wrong from a Knockout perspective. Those events really just are not fired (without Knockout even in the picture) from what I can tell by testing and by researching it a bit.
You can avoid a custom binding by doing:
<input type="date" data-bind="value: myDate, valueUpdate: 'blur'" />

I had similar issue, but in my case, even the blur event is actually not fired. So I used input event with valueUpdate property, and resolved the problem.

Related

Why is the html input time control losing focus when it is bound to a property in blazor?

I have a html input time control in my razor page. When I click inside the control, it automatically highlights the hours part to enter hours. When the hours is entered, the control loses focus. It works fine if I remove the #bind from the element and it highlights the minutes part.
How can I make it work without removing #bind ? Thanks for any suggestions.
<input type="time" class="form-control"
step="300" #onblur="#(async () => await Update())"
#bind="Timer.Time" />
Don't know what is "Timer.Time"...However, here's how you can do it. You can improve on it, and format it according to your requirements.
<input type="time" class="form-control" #bind="#value" />
<div>#value</div>
#code {
private DateTime value = DateTime.Now;
}

How to change the value that shows up when an HTML input field spinner is clicked for the first time?

I created a survey with an HTML number input field and I would like to change the value that shows up when the number input spinner is clicked or when the user presses up or down ("ArrowUp", "ArrowDown") for the first time.
The below code and the accompanying fiddle provide an example. When the spinner (the buttons on the right side of the input field) is clicked, the number field starts at 0. I would like to be able to change this initial value (e.g., set is to .53).
<input type="number" min="-1" max="1" step="0.01" />
https://jsfiddle.net/pkzz6pno/
The input field needs to be empty otherwise (to avoid influencing user responses as much as possible and to make it obvious that the field has not been filled out). Therefore, using "value" or "defaultValue" doesn't lead to the desired solution. Using a placeholder doesn't work either as this does not change the starting value of the spinner.
I also found some add-ons that allow this to be done and some instructions on how to switch the spinner off (http://www.virtuosoft.eu/code/bootstrap-touchspin/) but I was hoping to find a less intrusive solution.
As I undestood you need a solution where initial value appears only after user starts interacting with an input. For that reason I suggest reacting on input event. The approach is demonstrated below:
var initialValue = 0.53;
var $spinner = $("#spinner");
function setDefaultValue() {
$(this).val(initialValue);
$(this).off("input", setDefaultValue);
}
$spinner.on("input", setDefaultValue);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="spinner" type="number" min="-1" max="1" step="0.01" />
$(function() {
var startVal = 0.53;
var firstClick = false;
$("#myId").focus(function() {
if (!firstClick) {
$(this).val(startVal);
firstClick = true;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="myId" type="number" min="-1" max="1" step="0.01" />
Here is an example showing a spinner with start value when clicking on it (or by clicking the arrows). Here is the approach :
I used .focus() JQuery function that let me be able to bind an action when user click on every component of the item (such as the arrows in this example).
To be able to not reset the value when clicking out and in again, I used a boolean, that is initialized to false when DOM is loaded.
Then, when the user click for the first time, we enter the function that set default value to the spinner and the var firstClick that was false is changed to true.
When trying to blur and focus again, the function that set a default value is not tiggered because the value of firstClick is true.
Since this is a custom behavior, I don't think you can perform such a process without JavaScript. Here I used JQuery, which is a package tool made from JavaScript plain.

Knockout binding not updating after dragging the text with mouse in firefox

I have one simple textbox and span binded with the knockout observable like this
function ViewModel(){
var self=this;
self.name=ko.observable();
}
and
<input type="text" data-bind="value: name"/>
<br/>
<h1 data-bind="text: name"></h1>
<h2>dragdata</h2>
here is the fiddle for this http://jsbin.com/UqugasE/3/edit
Now when I drag some text from some source and put it into the textbox and lose focus the binding is updating only in Chrome and Ie9+, but it is not working in firefox(25.0)..
I think that in firefox the value is only updating after user have key interaction with the input box and lose focus..
Any idea or solution for this..
P.S
I can update the value of the binding with
valueUpdate:'input'
but I just wanted to know the reason why it is not working with firefox.
It seems to be a know bug :
https://github.com/knockout/knockout/issues/683
It's caused by FF does'nt support values update event (change event) like others.
As you said, you can do it with the valueUpdate databindingHandlers.
<input type="text" data-bind="value: name, valueUpdate:'input'"/>

problem with Chrome form handling: input onfocus="this.select()"

I'm using the following HTML code to autoselect some text in a form field when a user clicks on the field:
<input onfocus="this.select()" type="text" value="Search">
This works fine in Firefox and Internet Explorer (the purpose being to use the default text to describe the field to the user, but highlight it so that on click they can just start typing), but I'm having trouble getting it to work in Chrome. When I click the form field in Chrome the text is highlighted for just a split second and then the cursor jumps to the end of the default text and the highlighting goes away.
Any ideas on how to get this working in Chrome as well?
Instead of binding to onfocus event you must bind this action into onclick event and it will work as you wanted.
<input onclick="this.select()" id="txt1" name="txt1" type="text" value="Search">
If you really insist on sticking with onfocus, then you'll need to add onmouseup="return false" too.
This works best for me...
<input type="text" onfocus="this.searchfocus = true;" onmouseup="if(this.searchfocus) {this.select(); this.searchfocus = false;}" />
The mouseup event fires after onfocus.
This is a solution working in Firefox, Chrome and IE, both with keyboard focus and mouse focus. It also handles correctly clicks following the focus (it moves the caret and doesn't reselect the text):
<input
onmousedown="this.clicked = 1;"
onfocus="if (!this.clicked) this.select(); else this.clicked = 2;"
onclick="if (this.clicked == 2) this.select(); this.clicked = 0;"
>
With keyboard focus, only onfocus triggers which selects the text because this.clicked is not set. With mouse focus, onmousedown triggers, then onfocus and then onclick which selects the text in onclick but not in onfocus (Chrome requires this).
Mouse clicks when the field is already focused don't trigger onfocus which results in not selecting anything.
The way I got around this was by creating a wrapper function that uses setTimeout() to delay the actual call to select(). Then I just call that function in the focus event of the textbox. Using setTimeout defers the execution until the call stack is empty again, which would be when the browser has finished processing all the events that happened when you clicked (mousedown, mouseup, click, focus, etc). It's a bit of a hack, but it works.
function selectTextboxContent(textbox)
{
setTimeout(function() { textbox.select(); }, 10);
}
Then you can do something like this to do the selection on focus:
<input onfocus="selectTextboxContent(this);" type="text" value="Search">
Building on Jason's answer, here is a function that replaces the "select" function of DOM input nodes with an updated version that has the timeout built in:
if (/chrome/i.test(navigator.userAgent)) {
HTMLInputElement.prototype.brokenSelectFunction =
HTMLInputElement.prototype.select;
HTMLInputElement.prototype.select = function() {
setTimeout(function(closureThis) { return function() {
closureThis.brokenSelectFunction();
}; }(this), 10);
};
}
Basically, (in Chrome only) we just renamed the built-in but broken select() function to brokenSelectFunction() and then added a new function to all inputs called select() that calls brokenSelectFunction() after a delay. Now, just call select() normally, as the built-in select function has been replaced by the fixed function with Jason's delay suggestion.
This way, you don't have to worry about changing your existing calls to use a wrapper function (and once this is resolved in Chrome, you can just remove the above shim and go back to normal).
textbox.select(); // now runs select with setTimeout built-in (in Chrome only)
Edit: you might want to change the user-agent match from "chrome" to "webkit", as this issue happens in all webkit-browsers including Safari, and this fix will work for any of them.
Just use <input onmouseup=select()>. That works in all browsers.
This question was posted five years ago, but with HTML5, you can make this feature with the placeholder attribute.
<input type="text" name="fname" placeholder="First name">
onfocus="setTimeout(function(){select(this)})"
or onfocus="setTimeout(function(){select(this)},118)" for Firefox.
Thanks ilawton. This works for me
<input type="text" onfocus="this.searchfocus = true;" onmouseup="if(this.searchfocus) {this.select(); this.searchfocus = false;}" />

Preventing Firefox from remembering the input value on refresh with a meta tag

When I refresh a page with Firefox, the values of the check boxes, input fields, etc. are kept.
Is there a way to make Firefox not keep them, using a meta tag without JavaScript?
For an input tag there's the attribute autocomplete you can set:
<input type="text" autocomplete="off" />
You can use autocomplete for a form too.
If you want to prevent remembering field values after reload, while still getting to use autocomplete:
First define autocomplete off in the markup:
<input id="the-input" type="text" autocomplete="off" />
Then re-enable autocomplete programatically:
document.getElementById('the-input').autocomplete = 'on';
this will disable autocomplete just at the right time when the page loads and re-enable it so it can be used (but the field value will be empty as it should).
If it does not work for you, try wrapping the js code in a setTimeout or requestAnimationFrame.
// Internet Explorer fix - do this at the end of the page
var oninit_async_reset = setInterval(function() { resetFormIEFix(); }, 500);
function resetFormIEFix() {
$('#inputid').val('');
if (typeof oninit_async_reset != 'undefined')
clearInterval(oninit_async_reset);
}