Knockout JS clear inputs on focus - javascript

I'm building an app with knockout that's very number/input heavy. I'm refractoring my code to put everything into observableArrays so I can then bind these arrays to my HTML and all that is visible in the HTML is a template and Knockout is doing the leg-work to render all the elements inside this template.
My problem now lies with the fact my pre-existing clear input fields on focus script isn't working and I'm not entirely sure why or how to get it working.
This is the pre-existing script and is written with jQuery and I feel that there's now a conflict happening between Knockout and jQuery. Unfortunately I don't know to go about rewriting the script in Knockout.
$('input:not(.total-val)').on('focus', function() {
var default_value = $(this).val();
if ($(this).val() == default_value) {
$(this).val('');
}
$(this).blur(function () {
if($(this).val().length == 0) /*Small update*/
{
$(this).val(default_value);
}
});
});
Thanks in advance!

You should use Knockout's hasFocus binding instead of jQuery's on('focus'). I fear that jQuery is conflicting with Knockout's binding events and causing your text to disappear on focus. Here's an example:
<p>
Name:
<b data-bind="visible: !editing(), text: name, click: edit"> </b>
<input data-bind="visible: editing, value: name, hasFocus: editing" />
</p>
<p><em>Click the name to edit it; click elsewhere to apply changes.</em></p>
JavaScript:
function PersonViewModel(name) {
// Data
this.name = ko.observable(name);
this.editing = ko.observable(false);
// Behaviors
this.edit = function() { this.editing(true) }
}
ko.applyBindings(new PersonViewModel("Bert Bertington"));

There was a conflict was with jQuery vs Knockout fighting for control over the generated inputs. I fixed this issue be refactoring the clear input script in Vanilla.
$('input:not(.total-val)').attr({'onfocus':'onFocus(this)', 'onblur':'onBlur(this)'})
var default_value;
onFocus = function(input) {
default_value = input.value;
if (input.value == default_value) {
input.value = ''
}
}
onBlur = function(input) {
if (input.value == '') {
input.value = default_value;
}
}

Related

Issues displaying a dynamically updated HTML input value

I'm struggling to get the behaviour I need - as follows:
A HTML form is pre-populated with a value via jQuery. When the user focuses on the input field I want the form to clear. On blur from the form, the form should repopulate the form with the existing value.
I have a solution that clears and repopulates the form but it fails as soon as anything is typed in.
This is what I have so far:
var x = "Default";
$(function () {
$("input").attr({
"value": x
});
$("input").focus(function () {
$("input").attr({
"value": ""
});
});
$("input").blur(function () {
$("input").attr({
"value": x
});
});
});
https://jsfiddle.net/thepeted/p74kfdt8/6/
If I look in developer tools, I can see the input value is changing dynamically in the DOM, but in the case that the user has typed something in to the form, the display no longer updates.
I'd love to understand why this is happening (ie, why it works in one case and not the other). Also, if there is a better way of approaching the problem.
As pointed out by Stijn, best practice would be to use the placeholder attibute.
However if you do want to use a function for it. I would check on the focus if the value is the default value or not. If so, empty the input, if not, don't do anything.
On blur, you also only want to place the default value back if the value is empty... so check for that aswell.
var x = "Default";
$(function() {
$('input[type=text]').val(x);
$('input[type=text]').on('focus', function() {
var elem = $(this);
if (elem.val() == x)
elem.val('');
}).on("blur", function() {
var elem = $(this);
if (elem.val() == '')
elem.val(x);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
Your edited jsfiddle.
updated code:
$("input").blur(function () {
$("input").val(x);
});
Personnaly, I'd use the placeholder attribute as everyone pointed out. If you too are facing the need to support older browsers and some others that do not support the placeholder attribute, use this snippet I've made:
$('input[placeholder]').each(function(){
var $this = $(this);
$this.val($this.attr('placeholder')).css('color','888888');
$this.focus(function(){
if($(this).val() == $(this).attr('placeholder'))
$(this).val('').css('color','');
});
$this.blur(function(){
if($(this).val() == '')
$(this).val($(this).attr('placeholder')).css('color','888888');
});
});
This script will find all inputs with a placeholder attribute, give it's value to the input, and add the correct events. I've left the css calls just to show you where to put the codes to mimic the greyed text like modern browsers do.
Try this code
var x = "Default";
$(function () {
$("input").val(x);
$("input").focus(function () {
$("input").val("");
});
$("input").blur(function () {
$("input").val(x);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="text"/>

Use Enter as Tab with knockout binding and KendoUI dropdown

I have a page that uses KendoUI controls with knockout binding, and I need to use Enter instead of Tab to navigate through controls.
I managed to make it work great by using the solution posted here by Damien Sawyer and enhancing it with Shift-Enter as suggested by Andre Van Zuydam
ko.bindingHandlers.nextFieldOnEnter = {
init: function (element, valueAccessor, allBindingsAccessor) {
j$(element).on('keydown', 'input, select', function (e) {
var self = j$(this)
, form = j$(element)
, focusable
, next
;
var tabElements = 'input,a,select,button,textarea';
if (e.shiftKey) {
if (e.keyCode === 13) {
focusable = form.find(tabElements).filter(':visible');
prev = focusable.eq(focusable.index(this) - 1);
if (prev.length) {
prev.focus();
} else {
form.submit();
}
}
}
else
if (e.keyCode === 13) {
focusable = form.find(tabElements).filter(':visible');
var nextIndex = focusable.index(this) === focusable.length - 1 ? 0 : focusable.index(this) + 1;
next = focusable.eq(nextIndex);
next.focus();
return false;
}
});
} };
(my code uses j$ instead of $ for jquery because the project uses also mootools and I redefined jquery as j$)
However, I have a problem with kendoUI DropDown lists. The problem it is not or element, so it does not get focus (instead it is a span with special classes and unselecteable="on" attribute).
How should I update the ko binding code to set focus to dropdown on Enter? It works with Tab
Thanks
Doing the best I can without having a Kendo sample I can test this out on, but I think you should be able to achieve this. When Kendo creates a dropdown, as you said it adds a bunch of other elements and isn't given focus the same way as a regular select element. You can find a kendo select, however, by first finding its parent span with the class of k-dropdown.
Try adding k-dropdown to tabElements as a class selector:
var tabElements = 'input,a,select,button,textarea,.k-dropdown';
Then, adjust the part where you give focus by adding a condition to check for Kendo dropdown. So instead of just this:
prev.focus();
Try something like this:
if (prev.hasClass('k-dropdown')) {
prev.children('select').first().data("kendoDropDownList").focus();
} else {
prev.focus();
}

activate readonly back after editing the input jquery

how can i activate the readonly back after finishing the edit of the input ?
this is my code for now :
<script type="text/javascript">
$(document).ready(function () {
$("input").bind('click focus', function(){
$('input').each(function(){
$(this).attr("readonly", false);
});
});
});
</script>
an input like this :
<input type="text" class="m" readonly="readonly" id="anchor_text">
i think something with focusout, i need to put readonly back when i go to the next input, so the edited input can't be change unless i hit again click on it.
try:
$("input").bind('click focus', function(){
$(this).attr("readonly", false);
}).bind('blur', function(){
$(this).attr("readonly", true);
});​
demo : http://jsfiddle.net/DkCvu/1/
I'm sorry, but I'm struggling to see the point of this. If I get this right, you want the input field not to be editable until it is clicked or selected by the user (which is basically how input fields work anyhow: you can't change their value unless you select them). After these input fields loose their focus, they should go back to being read only. If this is the case, you're over complicating things. However, that is none of my business. The best way to get this done IMO, is by delegating the event.
I therefore put together a couple of fiddles, on pure JS, on jQuery. Both are far from perfect, but should help you on your way.
Regular JS (fiddle here):
var dv = document.getElementById('inputDiv');
if (!dv.addEventListener)
{
dv.attachEvent('onfocusin',switchRO);
dv.attachEvent('onfocusout',switchRO);
}
else
{
dv.addEventListener('focus',switchRO,true);
dv.addEventListener('blur',switchRO,true);
}
function switchRO (e)
{
var self;
e = e || window.event;
self = e.target || e.srcElement;
if (self.tagName.toLowerCase() === 'input')
{
switch (e.type)
{
case 'onfocusin':
case 'focus':
self.removeAttribute('readonly');
break;
default:
self.setAttribute('readonly','readonly');
}
}
return true;
}
In jQuery, this might look something like this (jQuery with .on, jsfiddle here):
$('#inputDiv input').on(
{
focus: function()
{
$(this).removeAttr('readonly');
},
blur: function()
{
$(this).attr('readonly','readonly');
}
});
​
I posted both jQuery and pure JS, because I find it both informative and educational to know what goes on behind the screens in jQuery.

ASP.NET implementing a search box like stackoverflow search box

I use VS2010,C# to develop an ASP.NET web app, I'm going to implement a search box like the one used in Stackoverflow (or other sites), initially there is a phrase (for instance "search") in the search text box, when user click in text box, its text is emptied and user can type his phrase, but if he leaves the text box (lost focus) empty, again the phrase "search" is displayed, how can I implement this nice effect?
thanks
This is the textbox watermark plugin which I use:
http://code.google.com/p/jquery-watermark/
I then created the following code which uses the title attribute for the watermark text for all elements with the .textbox_watermark class
var Textbox_Watermark =
{
init: function () {
var textboxWatermarks = $(".textbox_watermark");
for (var i = 0, ii = textboxWatermarks.length; i < ii; i++) {
$(textboxWatermarks[i]).watermark(textboxWatermarks[i].title);
}
}
}
Textbox_Watermark.init();
Then when focus is on the textbox, the watermark is removed.
You will need the jQuery framework for this to work
Here is a little script I use for just this purpose. It does required JQuery though, but if that is an option for you then give it a try. (there is probably a javascript alternative for this too, but I dont know it)
function addInputBlur(selector, text) {
var element = $(selector);
element.blur(function () {
if ($(this).val() == "") {
$(this).val(text);
$(this).addClass("InputBlur");
}
else {
$(this).removeClass("InputBlur");
}
});
element.focus(function () {
if ($(this).val() == text) {
$(this).removeClass("InputBlur");
$(this).val("");
}
});
element.blur();
}
Note: the "selector" param should be a JQuery selector value (i.e. "#MyTextbox")
Also, the "InputBlur" CSS class is just the style I use for the grey/italic font
I have seen the view source for stack overflow and what i notice is that they have a attribute named placeholder
<div id="hsearch">
<form id="search" action="/search" method="get" autocomplete="off">
<div>
<input autocomplete="off" name="q" class="textbox" **placeholder="search"** tabindex="1" type="text" maxlength="140" size="28" value="">
</div>
</form>
</div>
try this it works for mozilla ,, check for others
hope it helps
<input type="text"
onblur="javascript:if(this.value=='') this.value= this.defaultValue;"
onfocus="javascript:if(this.value==this.defaultValue) this.value='';"
id="txtSearch"
value="search"
name="txtSearch" />
You can do this in JavaScript using a function similar to this one:
/*
* applyDefaultValue() - Takes a DOM object and it's string value as paramters, when the element
* is focussed, the 'value' is blanked out, ready for user entry. When the item is blurred, if nothing was typed
* then the original value is restored.
*/
function applyDefaultValue(elem, val) {
elem.value = val;
elem.onfocus = function() {
if (this.value === val) {
this.value = ''; //On focus, make blank
}
}
elem.onblur = function() {
if (this.value === '') {
this.value = val; //If it's not in focus, use declared value
}
}
}
You can then apply this to items like this:
/*
* Onload function to set the default 'email address'/'search' value and blank out the password field
*/
window.onload = function() {
applyDefaultValue(document.getElementById('email'), 'Email Address');
}

If on .focusout form contains no value, revert to original value?

I'm trying to get my <input.../> fields to go blank on focus, and if on focus out they're still blank, revert them to their original values.
I would've thought this would work, but apparently not:
$('input').focus( function() {
var init_value = $(this).val();
$(this).val('');
});
$('input').focusout( function() {
var new_value = $(this).val();
if(new_value == "") {
$(this).val(init_value);
}
});
Any alterations/advice to get it working would be most appreciated ;)!
You should consider using the HTML5 placeholder attribute as a first option.
http://diveintohtml5.ep.io/forms.html#placeholder
With jQuery, you could modify your original script like this:
$('input').focus(function() {
$(this).val('');
});
$('input').focusout(function() {
if($(this).val('')){
$(this).val('Enter something');
}
});
Example: http://jsfiddle.net/jasongennaro/8bJcQ/
EDIT
Here is a revised script to deal with the situation as mentioned in your comment:
As for the jQuery option, that simply wouldn't do as it needs the
original value= value. I have perhaps 8 different text fields, the
instructions for which are the value, e.g. "Enter your email address",
"Enter your url", etc :(.
$('input').each(function(){
var a = $(this).attr('value');
$(this).focus(function() {
$(this).val('');
});
$(this).focusout(function() {
if($(this).val('')){
$(this).val(a);
}
});
});
Example 2: http://jsfiddle.net/jasongennaro/8bJcQ/3/
There is an easier method of doing this assuming a modern browser is used. Simply add the attribute placeholder="some text" and the browser will handle all this for you. If you must support older browsers, try this:
var init_value;
$('input').focus( function() {
init_value = $(this).val();
$(this).val('');
});
$('input').blur( function() {
var new_value = $(this).val();
if(new_value == "") {
$(this).val(init_value);
}
});
Your problem was the scope of init_value. You defined it inside an anonymous function, and could not access that value from a second anonymous function. To fix this you simply need to define init_value outside the scope of each event handler.
Also notice how I used .blur() instead of .focusout(). The jQuery API explains the difference between the two.

Categories

Resources