JS Auto select next input and detect last input - javascript

Im trying to auto jump to the next input once keypress is triggered but my code isnt working and I believe its todo with the next() select but can't seem to get it selected correctly.
HTML Form
<form method="POST" action="">
<div id="confirm-input">
#csrf
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
</div>
</form>
JS Code
$('.input').keyup(function (e) {
if (this.value.length == this.maxLength) {
var next = $(this).nextAll('input').first();
//Check if there is a next input.
if (next.length) {
next.focus();
} else {
$(this).blur
//AJAX CALL
}
}
});
Im using nextAll() as i believe it can look outside the div but not having any luck.

"Im using nextAll() as i believe it can look outside the div but not having any luck."
That's your problem right there. nextAll() only looks on the same tree level in the DOM. (Plunker here to demonstrate: http://plnkr.co/edit/u5t2Oy636xvl82WIgmvp?p=preview)
One possible solution would be to give your inputs successive ids, so that if your current input has an id of, say, "input-2", the look for "input-3" as the next input to focus on.
Update:
Here's a working Plunker that illustrates the above idea: http://plnkr.co/edit/UT5HydtxzyxkTIt5LBeZ?p=preview
$('.input').keyup(function (e) {
if (this.value.length == this.maxLength) {
var currId = $(this).attr('id');
var nextId = '#input-' + (Number(currId.split('-')[1]) + 1);
var next = $(nextId);
//Check if there is a next input.
if (next.length) {
next.focus();
} else {
$(this).blur
//AJAX CALL
}
}
}

My suggested solution is to determine how many elements match the selector then invoke .focus() using the index of each element, .blur() on the last element. You probably don't want to fire the AJAX call unless you've hit maxLength, hence the else if statement rather than just else.
var selector = "#confirm-input .input";
$(selector).keyup(function (e) {
var i = $(this).index(selector);
var len = $(selector).length - 1;
if (this.value.length == this.maxLength && i < len) {
$(selector).eq(i+1).focus();
}
else if(this.value.length == this.maxLength && i === len) {
$(this).blur();
//AJAX CALL
}
});

Related

Track inputs and toggle class with jQuery

What I am trying to achieve is track 20 inputs, if one is filled I want to add a class to a parent div of this input, if it becomes empty after I want the class to remove itself from the parent. This code does what I want when I run it in the console, how can I improve it so it can track the inputs and toggle the class?
$('.input').each(function() {
var $input = $(this);
if ($input.val()) {
var $parent = $input.closest('.card');
$parent.addClass('colored')
}
});
You can use an event to do so. For inputs, jQuery has the input event that fires every time the value of an input changes.
$(".input").on("input", function () {
if ($(this).val().length === 0)
$(this).closest('.card').removeClass("colored");
else
$(this).closest('.card').addClass("colored");
});
Your code checks for values at the initial run. You would need to attach events copy, paste, change, keypress, keydown, keyup and input. See example:
$('input').on('copy paste keydown keyup keypress change input', function(){
var $input = $(this);
if( $input.val() == '' ){
$input.parent('.form-group').addClass('empty');
} else {
$input.parent('.form-group').removeClass('empty');
}
});
.form-group {
margin-bottom:10px;
}
.form-group.empty > input {
border:2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<input name="name" type="text" placeholder="name"/>
</div>
<div class="form-group">
<input name="email" type="text" placeholder="email"/>
</div>
<div class="form-group">
<input name="address" type="text" placeholder="address"/>
</div>
This is the snippet Here. An keyup() function and an if check done them all.
$("input[type='text']").on("keyup",function(){
if($(this).val()!="")
{
$(this).parent().addClass("active");
}else{
$(this).parent().removeClass("active");
}
})
.active{
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="text" >
</div>
Thank you all for the answers, this is what worked for me after trying all the solutions. Hope it helps someone else.
function checkInputs() {
$('.input').each(function(){
if($(this).val() === ""){
$(this).parent().parent('.unit-card').removeClass('filled');
} else {
$(this).parent().parent('.unit-card').addClass('filled');
}
});
}

jQuery Field Not Being Removed After Appending it

I am running into an issue where I can't seem to get my jQuery script to remove fields after they have been added. I have tried a few changes, but nothing has worked.
$(function() {
var dataSourceField = $('#sign-up-organization-discovery-source');
var i = $('#sign-up-organization-discovery-source p').size() + 1;
$('#sign-up-add-discovery-source').on('click', function() {
$('<p><label for="discovery-source-field"><input type="text" id="discovery-source-field" size="20" name="discoverySource" value="" placeholder="Input Value" /></label> Remove</p>').appendTo(dataSourceField);
i++;
return false;
});
$('#remScnt').on('click', function() {
if (i > 2) {
$(this).parents('p').remove();
i--;
}
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<form action="/app/sign-up/organization" method="post">
<p>{{user.email}}</p>
<input type="hidden" name="admin" value="{{user.email}}">
<input type="hidden" name="organizationId">
<label for="sign-up-organization">Company/Organization Name</label>
<input type="text" class="form-control" id="sign-up-organization" name="organizationName" value="" placeholder="Company/Organization">
Add Another Discovery Source
<div id="sign-up-organization-discovery-source">
<input type="text" id="discovery-source-field" placeholder="Discovery Source" name="discoverySource">
</div>
<br />
<button type="submit">Submit</button>
</form>
Already have an account? Login here!
</div>
</div>
There are a couple problems here.
Firstly, an id is suppose to be unique! You are duplicating id attribute values each time you append the element.
Secondly, even if you were to use a class rather than an id, it still wouldn't work as expected because the clickable/removable a element doesn't exist in the DOM when you are attaching the event listeners.
You would either need to attach the event after appending the element, or you could use event delegation and attach the event to a common parent element that exists at the time.
Example Here
$('#sign-up-organization-discovery-source').on('click', '.remove', function() {
// ...
});
I changed Remove to: Remove.
Then I delegated the click event to the #sign-up-organization-discovery-source element.
$('##sign-up-organization-discovery-source').on('click', '#remScnt', function() {
if (i > 2) {
$(this).parents('p').remove();
i--;
}
return false;
});

clearing ng-messages in controller

I'm new to working with ng-message. I have an error message (form.$error below) showing up when I don't want it to, while a user is typing and changing their incorrect entry. how can I either a) use ng-focus properly or b) clear ng-messages in my controller when a user is typing? my attempt at a) using ng-focus is below but it isn't working. I also tried replacing ng-focus with ng-change but that still doesn't work. is it also possible to manually disable the error message from showing up in the controller by clearing ng-message?
my html. I attempt to set the form to valid when the user is typing.
<div class="col-xs-3">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code1">
</div>
further down in my html I have this other div where the error shows up when I don't want it to, when the user is typing.
<div ng-if="codeError"
ng-messages="form.$error">
<p ng-show="code1 === code2"
class="disabled-text long-error">Inputs can't be the same</p>
</div>
this is the main js in my controller:
$scope.checkCodes = function() {
if ($scope.code1 && $scope.code1 === $scope.code2) {
$scope.showUniqueError = true;
$scope.form.$setValidity("prop", false);
$scope.showError2 = false;
} else {
$scope.showUniqueError = false;
$scope.form.$setValidity("prop", true);
}
}
//tried to use this in ng-focus but not working.
$scope.setValid = function() {
$scope.form.$setValidity("prop", true);
}
You were pretty close you just had the wrong scope variable in your ng-if.
I also change the ng-blur attritbutes to ng-keyup. With ng-blur your error message would only be displayed if you click outside of the text box or another control gets focus.
In the live example you will see that if you type in the same value for each input box that your error will be displayed and if you change one of the input boxes to a different value then the error will be removed.
Live Example: http://codepen.io/larryjoelane/pen/QyOZNR
test html:
<div ng-app="test" ng-controller="testController"><!--begin app container-->
<div class="col-xs-3">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code1">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code2">
</div>
<div ng-if="showUniqueError"
ng-messages="form.$error">
<p ng-show="code1 === code2"
class="disabled-text long-error">Inputs can't be the same</p>
</div>
</div><!--end app container-->
Test Javascript(Unchanged other then adding module wrapper and closure):
(function(){
angular.module("test",[]).controller("testController",function($scope){
$scope.checkCodes = function() {
if ($scope.code1 && $scope.code1 === $scope.code2) {
$scope.showUniqueError = true;
$scope.form.$setValidity("prop", false);
$scope.showError2 = false;
} else {
$scope.showUniqueError = false;
$scope.form.$setValidity("prop", true);
}
}
//tried to use this in ng-focus but not working.
$scope.setValid = function() {
$scope.form.$setValidity("prop", true);
}
});//end controller
})();
You can do it without using ng-message.
<form class="form-signin hide" id="gbLoginForm" method="POST" name="loginform" ng-controller="LoginCtrl" novalidate>
<div class="form-group">
<label for="username">User Name</label>
<input type="text" class="form-control" id="username" name="email" placeholder="User name/email" ng-model="user.email" required autofocus>
<span class="has-error" ng-show="loginform.email.$dirty && loginform.email.$error.required">
<span class="help-block" ng-bind="getValue('EMPTYEMAIL')"></span>
</span>
<span class="has-error" ng-show="loginform.email.$dirty && !loginform.email.$error.required && loginform.email.$error.validemail">
<span class="help-block" ng-bind="getValue('INVALIDEMAIL')"></span>
</span>
</div></form>
// email field is empty
if(!$scope.user.email){
$scope.loginform.email.$dirty = true;
$scope.loginform.email.$setValidity('required', false);
return false;
}
//invalid email
if(!UtilityService.validateEmail($scope.user.email)) {
$scope.loginform.email.$dirty = true;
$scope.loginform.email.$setValidity('validemail', false);
return false;
}
You don't need use ng-blur or ng-keyup, because angular refresh your ngModel on change input.
To create the various checks can use directive use-form-error.
Live example jsfiddle.
<form name="ExampleForm">
<label>Code 1</label>
<input ng-model="code1" required/>
<label>Code 2</label>
<input ng-model="code2" required/>
<div use-form-error="isSame" use-error-expression="code1 && code1==code2" ng-show="ExampleForm.$error.isSame">Inputs can't be the same</div>
</form>

Jquery Keypress recognized after second press

<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input id="search_text" type="search" class="form-control" placeholder="Search" size="30">
<div class="form_control" id="search_info" style="width:283px;height:125px;top:86%;position:absolute;background-color:white; border: 1px solid #dce4ec;border-radius: 4px;display:none;"></div>
</div>
</form>
$("#search_text").keypress(function (){
if($("#search_text").val().length == 0)
{
$("#search_info").hide();
}
else if($("#search_text").val().length != 0)
{
$("#search_info").show();
}
});
My issue is that with this code it will only show
$("#search_info")
on the 2nd keypress. For example if i'm typing to the search field which I have as
$("#search_text"), $("#search_info") should show on the first press but it does not, when I more than one character into the search field it then shows $("#search_info").
I can't seem to figure it out.
Use keyup instead of keypress - as when keypress fires the value has not been inserted into the input yet.
$("#search_text").keyup(function (){
if($("#search_text").val().length == 0)
{
$("#search_info").hide();
}
else if($("#search_text").val().length != 0)
{
$("#search_info").show();
}
});
http://jsfiddle.net/qxh3x2s6/

jQuery hide/show some part of the form

I have a form which I am giving a part of it in the following:
<input type="checkbox" id="yes" name="yes" value="1" />Yes
<div id="divyes">
<div class="form-group">
<label for="hey">Hey</label>
<select class="form-control input-sm" id="hey" name="hey">
</select>
</div>
<div class="form-group">
<input type="text" class="form-control input-sm" id="yes2" name="yes2" />
</div>
<div class="form-group">
<input type="text" class="form-control input-sm" id="yes3" name="yes3" />
</div>
</div>
I am trying to show or hide some part of the form according to checkbox's checked statu.
$(function () {
$("#divyes").hide();
$("#yes").click(function () {
if ($("#yes").attr("checked")) {
$("#divyes").slideDown();
} else {
$("#divyes").slideUp();
$("#divyes > input").text("");
}
});
});
You can see the fiddle here
If I select jQuery 1.8.3 from the left panel it works fine but if I select 1.10.1 it does not work. I am also using 1.10.2 on my project. So I want to know how I can do my work without using .slideDown()/.show() and .slideUp()/.show()? In other words, is my logic good or can you offer better one?
Use the .change() event and an instance of this
$("#yes").change(function () {
if (this.checked) {
$("#divyes").slideDown();
} else {
$("#divyes").slideUp();
$("#divyes > input").text("");
}
});
The fail is happening on the .attr method - it should be .prop to check, however you can just do this.checked for an even faster result.
Fiddle: http://jsfiddle.net/a3j5V/4/
i made it with toggle
$('#divyes').toggle('slow');
http://jsfiddle.net/a3j5V/11/
$(function () {
var yes_cont = $("#divyes");
var yes_checkbox = $("#yes");
yes_cont.hide();
yes_checkbox.click(function () {
if ($(this).is(':checked')) {
yes_cont.slideToggle('up');
} else {
yes_cont.slideToggle('down');
}
});
});
http://jsfiddle.net/rY4Ts/15/

Categories