jQuery, get text from neighbouring input within a div - javascript

I have a component on my page which looks like this:
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>
A component list can have multiple component pairs nested within it. When performing a search a query cannot be made for a serial number if a part number is not present, therefore when performing a keyup event on the .serial field I need to get the text from the part number field. I would store this in a data model, but by referencing the current serial field I should be able to traverse to the part number field.
Here is what I have tried, when my page loads I bind a keyup event on the serial field, I pass this as the selector so I have reference to the (sender) current field in getData():
$(document).on("keyup", '.serial', function() { getData(this, "SERIAL") });
Then in getData I want to be able to traverse up my DOM structure to the current componentPair group and then traverse into the left div and get the value from Part Number input field.
Here is what I tried:
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log(elem.closest('input[class^="part"]'))
serial = elem.value
}
... Other erroneous code to perform the search
}
As you can see, here I use console.log(elem.closest('input[class^="part"]')) to find the closest component with the class of part, after reading jQuery documentation I believe this should work, but I get an undefined function error. I then tried to use the parent() selector and parentsUntil() selector but each of them threw an undefined function error.
If I console log, elem I get:
<input type="text" class="serial" placeholder="SERIAL NUMBER">
Which is what I would expect, so I don't see why I can't use elem.parent().parent() to traverse to componentPair and then dive into the tree structure to pull the information out.
I am using jQuery 1.11.3, any help would be greatly appreciated.

The issue is because .part is not a parent of .serial. You need to use closest() to find a common parent, then find() to get the element you require. Try this:
var serial = $(elem).closest('.componentPair').find('.part').val();

The reason you get undefined function error is that elem is not a jQuery object, it's a HTMLElement, so wrap it in $().
Then .closest() won't work the way you think, it will only search through itself and its parents.
Try this:
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log($(elem).parent().siblings().find('input[class^="part"]'));
serial = elem.value
}
}
$(document).on("keyup", '.serial', function() {getData(this, "SERIAL") });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>

You have issue with elem.closest('input[class^="part"]'), this should be $(elem).closest('input[class^="part"]') . Because elem is the input's object itself. so you can not directly call closest()
Here is the working code :
$(document).on("keyup", '.serial', function() { getData(this, "SERIAL") });
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log($(elem).parent().parent().find('.part'));
serial = $(elem).parent().parent().find('.part').val();
alert(serial);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>

Related

Getting another element through a method thats related to the current operation

Sorry for the bad title, simple couldn't figure out how to explain my problem.
Let's say i have 4 of these fields, and not just one. I want to increment or decrement each input field. Each input field has a "+" and "-" that does incremental and decremental tasks.
I have setup a method that register the v-on click even to a method. But how do i get what input field it was incremented on, cause 'this' would return the buttons of +/-
normally i would just use jquery with .parent().find('.input-number'); but i feel like this is dirty, and excessive for such a small thing. most be a better approach?
This is my markup
<div class="form-group">
<span class="input-number-decrement" v-on:click="decrement()">–</span>
<input class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="increment()">+</span>
</div>
and looks like this
example of the field
any help would great, since i'm stuck at this part :)
I have created one javascript function for increment and decrement value by 1.
HTML
<div class="form-group">
<span class="input-number-decrement" v-on:click="inc_dec('dec')">-</span>
<input class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="inc_dec('inc')">+</span>
</div>
Javascript
<script type="text/javascript">
function inc_dec(flag){
var pack1 = document.getElementById('pack1');
var inc_dec_by = 1;
if(flag=='inc'){
pack1.value = parseInt(pack1.value)+inc_dec_by;
}
if(flag=='dec'){
pack1.value = parseInt(pack1.value)-inc_dec_by;
}
}
</script>
I am assuming above code is a vue component.
<div class="form-group">
<span class="input-number-decrement" v-on:click="decrement()">–</span>
<inputn v-model="value" class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="increment()">+</span>
</div>
In the script define a variable to hold the value.Then manipulate values using defined methods
<script>
export default{
data: {
value
},
methods: {
decrement: function (event) {
},
increment: function (event) {
}
}
}
</script>

Why doesn't empty() work on input in search bar?

When clicking theinviteButton, the input search bar should clear out, but it doesn't work with my current code.
Am I targeting the element incorrectly?
$("#inviteButton").click(function(){
var userName = $("#searchUser").val();
if (userName.trim() != "") {
if (userName == myUserName) {
$("#connectToBox").append("You can't invite yourself");
$("#searchUser").empty(); // Doesn't work
} else {
socket.emit("checkUserConnect", userName, function(data){
if (data.result === undefined) {
console.log("No name");
$("#connectToBox").append("User does not exist");
$("#searchUser").empty(); // Doesn't work
} else {
console.log("name exists");
$("#searchUser").empty(); // Doesn't work
$("#connectToBox").append("Invite send");
UserID = data.result.id;
socket.emit("connectToUser", myUserName, UserID, currentConversation);
}
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="connectToBox">
<label for="search-2">Type in username</label>
<input type="search" name="search-2" id="searchUser" value="">
Connect
</div>
To empty an input field you would normally use:
$('#searchUser').val('')
Empty is used to clear away child nodes from elements like divs or p tags, but not for inputs.
Reason for that is that the text within an input is not represented as a child node of the element and instead stored on an html attribute of the input tag. Hence .empty() does not work for clearing the value.
You can clear the input field by using
$('#searchUser').val('');
$('#searchUser').val('');
This will work fine according to your application.
The empty() method removes all child nodes and content from the selected elements. Src: W3Schools
According to your requirement you need to reset the value of an input field, for that we have val() function. You can assign an empty string and it will work fine.
Using empty() won't work here.
Check these examples -
empty() working correctly -
function emptyOperation(){
$("div").empty();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="text" id="input-field" value="Random string">
</div>
<button onclick="emptyOperation()">Check</button>
empty() as per your code [won't work] -
function emptyOperation(){
$("#input-field").empty();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="text" id="input-field" value="Random string">
</div>
<button onclick="emptyOperation()">Check</button>
Solution to your problem -
function emptyOperation(){
$("#input-field").val('');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="text" id="input-field" value="Random string">
</div>
<button onclick="emptyOperation()">Check</button>

Can't select and hide any previous element

I'm about lose my mind with this problem. No form of jQuery selector seems to work in dynamically finding any elements above the link. I'm trying to access an element above the link and hide it. Using things like parent(), prev(), before(), closest(), ect. will show a non-null object but it won't respond to the hide() method.
<div class="row">
<div class="col-xs-5">
<div id="test_fields">
<li id="test_input" class="string input optional stringish">
<label class="label" for="test_input">Ingredient name</label>
<input type="text" name="test_input" value="afsfasf" id="test_input">
</li>
</div>
<input type="hidden" id="recipe_recipe_ingredients_attributes_0__destroy" name="recipe[recipe_ingredients_attributes][0][_destroy]">
Remove Ingredient
</div>
</div>
function remove_fields(link)
{
$(link).prev("input[type=hidden]").val('1'); // this doesn't work
var divToHide = $(link).prev('div');
$(divToHide).hide() // this doesn't work
//$('#test_fields').hide(); //this works
}
Try replacing the link as below:
Remove Ingredient
I'm not sure. But maybe this is the problem. Because I remember that I have had problem with 'this'previously and when I replaced that, it performed the job.
you can try .closest() and .find()
function remove_fields(link) {
$(link).closest('div[class^="col-xs"]').find("input[type=hidden]").val('1');
var div_to_hide = $(link).closest('div[class^="col-xs"]').find('#test_fields');
$(div_to_hide).hide();
//$('#test_fields').hide(); //this works
}
You can't change hidden input's "value" attribute by using .val(). You need to use:
$(link).prev("input[type=hidden]").attr('value', '1');
As I'm not really sure what do you want to do with this input, I'll just let it go like this.
.prev() fn goes only one previous element in the structure. As input is a <a>'s previous element, you can't select div like that. You can use .siblings() for instance.
$(link).siblings('div').hide();
If you break the code in pieces, it gets easier.
First I took the 'Link', from it I grabbed the nearest div above it, then I picked up the input.
I did not make many changes to your code.
function remove_fields(link)
{
var $link =$(link);
var $divToHide = $link.closest('div');
$divToHide.find("input[type='hidden']").val('1');
$divToHide.hide()
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="row">
<div class="col-xs-5">
<div id="test_fields">
<li id="test_input" class="string input optional stringish">
<label class="label" for="test_input">Ingredient name</label>
<input type="text" name="test_input" value="afsfasf" id="test_input">
</li>
</div>
<input type="hidden" id="recipe_recipe_ingredients_attributes_0__destroy" name="recipe[recipe_ingredients_attributes][0][_destroy]">
Remove Ingredient
</div>
</div>

find and replace certain attributes using cheerio

I have a html fragment similar to this
<div class="form-row">
<input type="text" id="foo1">
</div>
<div class="form-row">
<input type="text" id="foo2">
</div>
<div class="form-row">
<input type="text" id="foo3">
</div>
and I wanted to use cheerio to change the id tag to foobar[1,2,3]
my code is
var cheerio = require("cheerio");
var $ = cheerio.load("html as above");
var inputs = $('input[id]');
Object.keys(inputs).forEach(function(key,index) {
if (key == index) {
console.log(key,inputs[key])
//#1
});
at this point (//#1), I wanted to get the value of the id attribute, and according to the docs at https://github.com/cheeriojs/cheerio I can use the .data method to get and change the attribute in the element, but
inputs[key].data("id")
gives me a "TypeError: undefined is not a function" error
I know that I'm missing something simple, but can't see the wood for the trees and would appreciate some pointers.
thanks
update #1
just when I think I've got a grip on this, it slips from my fingers ..
now, I want to move an element :
I have
<label>xyz<i class="fa fa-list"></i></label>
and I want
<label>xyz</label><i class="fa fa-list"></i>
the code - that doesn't work ;) - is this
var icons = $('label i');
icons.each(function(index,icon) {
// #2 now that I've got an element what now ?
}
I know that icons.remove() will delete the element(s) but struggling to get them added to the right place.
The problem is inputs[key]) will be a dom element reference, which will not have methods like data()
Try to set the attribute value like
var cheerio = require("cheerio");
var $ = cheerio.load('<div class="form-row">\
<input type="text" id="foo1">\
</div>\
<div class="form-row">\
<input type="text" id="foo2">\
</div>\
<div class="form-row">\
<input type="text" id="foo3">\
</div>');
var inputs = $('input[id]');
inputs.attr('id', function(i, id){
return id.replace('foo', 'foobar')
});
console.log($.html())

Traversing with jQuery: cycle over children

Hi all I have an html structure like this:
<tr>
<td>
<div class="sigle-sz">
<span class="label-sz">36</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
<td>
<div class="sigle-sz">
<span class="label-sz">38</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
<td>
<div class="sigle-sz">
<span class="label-sz">40</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
</tr>
I created a jQuery function like this:
<script>
function pippo() {
//code here
}
$( document ).ready(function() {
$( ".sigle-sz" ).on('change', function() {
pippo();
});
});
</script>
I would, into the function "pippo()", cycle the <td> elements in the <tr> tag and save the input value in a variable.
If this is the $( ".sigle-sz" ) element, how I can do this cycle?
I put here my current code: https://jsfiddle.net/ydrunbzz/
You can use $.each() jQuery function:
var values; // define global var to use everywhere
function pippo(myClass) {
$.each(("." + myClass), function (index, value) {
values += value;
});
}
Tonnes of ways to solve this with an .each() loop. I think it's important to have a very readable loop if you are new, or else you'll lose track fast.
1) global variable
2) first make sure that the data is gathered when someone writes something in the inputs!
3) the pippo function will clear the global variable "arrSigle" (short for Array Sigle), and make sure it's only filled with the current numbers written down
$(document).ready(function () {
//1
var arrSigle= [];
//2
$( ".sigle-sz" ).find("input").on("change", function(){
pippo();
//just FYI, the "change" only fires when an input has a new value, and lose focus
// by any means. If it annoys you to have to click out of the box for pippo()
//to run, you might want to use "onkeyup" instead of "change".
//it will fire every time someone lets go of a key while inside the input
})
//3
function pippo(){
arrSigle.length = 0; //this clears the variable
$( ".sigle-sz" ).find("input").each(function(){
arrSigle.push($(this).val());
//this itterates over all the inputs and pushes them into the
//global variable.
})
//If you want some function to run right after all the
//numbers has been gathered, put it right under this comment.
}
});
We can all discuss how "efficient" this is, but considering how small your page probably is, i think it's more than justifiable to make it this simple

Categories