I'm trying to find all sibling elements using the .siblings([selector]) method. Although i'm not sure how the selector method should be written, or where i'm going wrong with my current selector method.
I have the html:
<div>
<div>
<label for="username">Username</label>
<input class="username" type="text" placeholder="Username" id="username"/>
</div>
<div>
<label for="Password">Password</label>
<input class="password" type="password" placeholder="Password" id="password"/>
</div>
<div>
<button id="login">Login</button>
</div>
</div>
When the button is clicked, if the username or password fields are not entered, I want to add a class to the unfilled elements.
When the button is clicked, the script is run:
if (username not entered) {
jQuery(this).parent('div').siblings(function (a) {
if (a.children('input').length > 0 && a.children('input')[0].hasClass('username'))
return true;
else return false;
}).addClass('input-empty');
}
However this jQuery call returns both the div containing the username field and the div containing the password field. Why does this return the password field if I have specified that it must contain an input tag with the class 'username'?
Look at the documentation:
.siblings( [selector ] )
The method accepts one argument, which is optional, and is a selector.
selector
Type: Selector
A string containing a selector expression to match elements against.
If you pass a selector, it must be a string.
jQuery(this).parent('div').siblings(function (a) {
You are passing a function, which is not a string.
Use the :has() psuedo-class to select elements with specific descendants.
Related
I am doing this for validating multiple input fields with different data intake using a generic function to which I can pass RegExp output and display the validation message or icon.
This is my HTML code
<div class="form-group">
<label for="fname" class="form-lable">First name</label>
<input type="text" id="fname" name="fname" class="form-input" required>
<div for="fname">
<span class="validation-container success"><i class="bi bi-check2"></i></span>
<span class="validation-container error"><i class="bi bi-x"></i></span>
</div>
</div>
<div class="form-group">
<label for="lname" class="form-lable">First name</label>
<input type="text" id="lname" name="lname" class="form-input" required>
<div for="lname">
<span class="validation-container success"><i class="bi bi-check2"></i></span>
<span class="validation-container error"><i class="bi bi-x"></i></span>
</div>
</div>
This is what I am doing
$('#fname').on('keyup', function () {
$('.validation-container').hide();
});
$('#lname').on('keyup', function () {
$('.validation-container').hide();
});
What it does:
It's doing that thing for both of the inputs.
$('#fname').on('keyup', function () {
$(this).parent().find('.validation-container').hide();
let check = fnameRegExp.test($(this).val());
let success = ".validation-container.success";
let wrong = ".validation-container.error";
validateInput(check, success, wrong);
});
What I am doing here is sending regex match, success as well as wrong classes to the function. If the input is not matched with the regex then it will display the div having that wrong class.
function validateInput(check, success, wrong) {
if (check) {
$(success).show();
checkAll();
} else {
$(wrong).show();
}
}
And I am calling that function on keyup for each input. what it does is, it shows validation signs (✅, ❎) for every input.
change this
<div for="fname" id="fnameValidators">
<span class="validation-container success"><i class="bi bi-check2"></i></span>
<span class="validation-container error"><i class="bi bi-x"></i></span>
</div>
$('#fname').on('keyup', function () {
$('#fnameValidators').hide();
});
Similarly make changes for last name.
TL;DR
Use
$(this).parent().find('.validation-container').hide();
To hide only the element with that class within the same container.
Longer version
$('.validation-container') searches in the whole DOM. To restrict it, you can use this selector within another element. Since you're reading the keyup event on the input, you can simply use $(this) to obtain the input object. Then go over 1 level with .parent() to select the <div class="form-group"> containing it and finally use find('.validation-container') to select the correct span you want to hide.
As one-liner:
$(this).parent().find('.validation-container').hide();
Even more dynamic
If you want to make this even more dynamic, you can avoid calling a keyup event for each separate input, and create a single function that manages all your inputs correctly.
$('.form-lable').on('keyup', function () {
var type = $(this).attr('id')
// You can use the variable type to distinguish between the two inputs
$(this).parent().find('.validation-container').hide();
});
Try this
$('#fname').on('keyup', function () {
$("div[for='fname']").find('.validation-container').hide();
});
$('#lname').on('keyup', function () {
$("div[for='lname']").find('.validation-container').hide();
});
I have an HTML form with two DOM elements that work together - input and error message. When the form is submitted and the input is empty, I want to apply some code to the error message. My problem is that my HTML for the position of the error message is constructed differently based on the platform - desktop or mobile - and I cannot do anything about it.
Example desktop:
<form name="form">
<div>
<input type="text" name="input-one">
<div class="error-message"></div>
</div>
<div>
<input type="text" name="input-two">
<div class="error-message"></div>
</div>
...
</form>
Example mobile:
<form name="form">
<div>
<input type="text" name="input-one">
</div>
<div class="error-message"></div>
<div>
<input type="text" name="input-two">
</div>
<div class="error-message"></div>
...
</form>
You can see, that based on the platform, the error message can be part of the same or a different parent. For that reason I cannot use jQuery's .next() selector. I tried using also .closest() selector, but that transfers the DOM upwards and also doesn't work.
So what I am trying to achieve is - with a relative reference of a DOM element (in this case input), find the first following DOM element containing a specific class (in this case "error-message").
Example Javascript stub:
$('[name=form]').find(':text:visible').each(function (i, el) {
// select the next error message
});
Is there any combination of selectors that can help me achieve this?
It's unfortunate that this couldn't have been handled with CSS, but if you're really stuck with that structure, then assuming $input is a jQuery object for the input element, then:
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
nextAll will select all following siblings that match the selector. parent will go up to the parent, and next will match the following sibling, but only if it matches the selector. Since one or the other of those will be empty, you'll end up with a set of one element — the error message element.
Desktop:
$("input").on("input", function() {
const $input = $(this);
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
$error.text("Count: " + $input.val().length);
});
<form>
<div>
<input type="text" name="input-one">
<div class="error-message"></div>
</div>
<div>
<input type="text" name="input-two">
<div class="error-message"></div>
</div>
Type in either input to see a count in its error box.
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Mobile:
$("input").on("input", function() {
const $input = $(this);
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
$error.text("Count: " + $input.val().length);
});
<form>
<div>
<input type="text" name="input-one">
</div>
<div class="error-message"></div>
<div>
<input type="text" name="input-two">
</div>
<div class="error-message"></div>
Type in either input to see a count in its error box.
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I have simple registration form and the password inputs are:
<label for="pass">Password:</label>
<div class="input-group input-group-md">
<span class="input-group-addon" id="sizing-addon1"><span class="glyphicon glyphicon-cog"></span></span>
<input type="password" class="form-control" placeholder="Password" aria-describedby="sizing-addon1" id="pass">
</div>
<br>
<label for="pass_confirm">Confirm password:</label>
<div class="input-group input-group-md">
<span class="input-group-addon" id="sizing-addon1"><span class="glyphicon glyphicon-envelope"></span></span>
<input type="password" class="form-control" placeholder="Confirm password" aria-describedby="sizing-addon1" id="confirmPass">
</div>
<br>
<p id="passwordMatch"></p>
I want the paragraph with id="passwordMatch" to show up and depending on the result to show the exact text needed. My jquery code is:
$('#confirmPass').on('keyup', function () {
if ($('#confirmPass').val() == $('#pass').val()) {
$('#passwordMatch')[0].style.display = "block";
// use array to convert jquery to object $('#passwordMatch').html('Password match!').css('color', 'green');
} else {
$('#passwordMatch').html('Password do not match!').css('color', 'red');
}
});
But when i type some random passwords in the inputs the console is telling me that the .style attribute is not defined. Before that i was using $('this') but i found out that i get an object and because of that i cant access DOM directly. Nevermind, changed it with if('#confirmPass').val() and i still get the same error.
If you need to access the DOM object directly you should use $('#passwordMatch')[0].style.display = "block";
But as you already use jQuery I suggest you to use $('#passwordMatch').show();
The problem is that you're using .style on a jquery Selector - try this instead of .style:
$('#passwordMatch').css("display", "block");
change the line of code to:
$('#passwordMatch').css({'display':'block'});
$('#passwordMatch') returns a collection, so it doesn't have a style attribute. You should probably pick whether you are going to be using jQuery or pure javascript and stick to it. jQuery -> $('#passwordMatch').css('display','block');
If you really wanted to, you could also do:
$('#confirmPass').on('keyup', function () {
if ($('#confirmPass').val() == $('#pass').val()) {
$('#passwordMatch')[0].style.display = "block";
$('#passwordMatch').html('Password match!').css('color', 'green');
} else {
$('#passwordMatch').html('Password do not match!').css('color', 'red');
}
});
<div class="container">
<div class="well" data-id="myApp">
// Data-Bind is Here
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
// Data-Bind is Here
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
I want to get html element that have "data-bind" attribute for example I want to Get something like this :
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
if I change above code like this :
<div class="container">
// Data-Bind is HERE Now
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
// Data-Bind is HERE Now
<input type="text" value="" class="form-control input-sm" />
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
now I want to get element like this :
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
How can I have function for get active element that set data-bind for it , when data-bind read I can get correspondingly element of it
I need general way not for specific event or ...
If you are using JQuery then you can use "has attribute" selector. For example:
$("[data-bind]")
You can get all elements with a data-bind attribute with the jquery attribute selector.
$("*[data-bind]")
Next you can refine the selector in various ways, e.g. to consider only certain tags or choosing only a slice of the result,or by employing jquery filters:
$("div[data-bind], input[data-bind], p.data-carrier[data-bind]"); // consider only div, input, or p elements, the latter only when having class data-carrier
$("*[data-bind]:first"); // use the first match only
$("*[data-bind]")[1]; // use the second match only
$("*[data-bind]").filter(":even"); // use only matches with an even index in the list of matches
$("*[data-bind]").each ( function ( idx, element ) { /* your code */ } ); // the most general approach: iterate through the results and decide upon each element what to do next
Are you looking for this in jquery:
var elem = $('.container').find('[data-bind]');
Use $("*[data-bind]")[0].outerHTML
It will you the outerHTML of the element.
Working Fiddle
it wont submit even though the fields are not empty
here's the form:
<form id="form" role="form" method='POST' action="user_add-post.php">
<div class="form-group">
<p><label class="control-label">Title</label><br />
<input style="width: 40%" class="form-control" type="text" name="postTitle"/>
</div>
<div class="form-group">
<p><label lass="control-label">Description</label><br />
<textarea name="postDesc" cols="60" rows="10"></textarea>
</div>
<div class="form-group">
<p><label>Content</label></p>
<textarea name="postCont" cols="60" rows="10"></textarea>
</div>
<input type='submit' name="submit" class='btn btn-primary' value='Submit'></form>
and here's my jquery to check if the input fields are empty:
$('#form').submit(function() {
if ($.trim($("#postTitle").val()) === "" || $.trim($("#postDesc").val()) === "" || $.trim($("#postCont").val()) === "") {
alert('All fields required');
return false;
} });
now why won't it submit? it keeps on saying that all fields are required even though I already fill up the fields.
You have missed to add id in input boxes,
<input style="width: 40%" class="form-control" type="text" name="postTitle"/>
Change it to
<input style="width: 40%" class="form-control" type="text" id="postTitle" name="postTitle"/>
for next text box aswell ,Please Refer
you do not have define the ids so change the condition to
if ($.trim($('[name="postTitle"]').val()) === "" || $.trim($('[name="postDesc"]').val()) === "" || $.trim($('[name="postCont"]').val()) === "")
You have not given the ids to any of your form field, use global selector with condition
here is the working fiddle of your task
`$("input[name=postTitle]").val()` //name selector instead of id
If condition should be like this:
if ($("#postTitle").val().trim() == "" || $("#postDesc").val().trim() == "" || $("#postCont").val().trim() == "") {
See for any JS errors if you are getting. Also , try it on various browsers. You are not using ID attribute, but Name attritute, so it may not work on Firefox,Chrome and may work on IE7 and below. Hope this helps you
Provide Id to input element in html code.
Jquery code is fine
here is the correct code of html
<input style="width: 40%" class="form-control" type="text" name="postTitle" id="postTitle"/>
Yes like everyone else is saying if you are going to use selectors then you need those id's on the form fields. Or you can use the names like this:
$("[name=postTitle]").val()
$("[name=postDesc]").val()
$("[name=postCont]").val()
Here is your jquery with the above:
$('#form').submit(function() {
if ($("[name=postTitle]").val().trim() == "" || $("[name=postDesc]").val().trim() == "" || $("[name=postCont]").val().trim() == "") {
alert('All fields required');
return false;
} });
As others have said, the selectors are based on ID but using name attribute values. So you can add ID attributes, change the selector or use a different strategy.
Since the listener is on the form, this within the function references the form and all form controls with a name are available as named properties of the form. So you can easily test the value contains something other than whitespace with a regular expression, so consider:
var form = this;
var re = /^\s*$/;
if (re.test(form.postTitle.value) || re.test(form.postDesc.value) || re.test(form.postCont.value) {
/* form is not valid */
}
which is a lot more efficient than the OP.
Given the above, a form control with a name of submit will mask the form's submit method so you can't call form.submit() or $('#formID').submit().