jQuery closest element with an attribute that contains a value - javascript

I have some HTML code that looks like this:
<tr id="nbContent_GR1">...</tr>
<tr id="nbContent_GR2">...</tr>
<tr id="nbContent_GR3">...</tr>
<tr id="nbContent_GR4">...</tr>
<tr id="nbContent_GR5">...</tr>
<tr id="nbContent_GR6">...</tr>
Within one of the rows, I want to traverse up the DOM to find the closest element that has an ID attribute that starts with "nbContent_GR". So basically I want to be able to find the parent TR element without knowing its exact ID, just the first one that starts with "nbContent_GR". Is this possible? If so, how would I go about it?
BTW, I'm aware of the closest() and "contains" selectors, just not sure if contains can be used on attribute values or not.

Just do:
tr = $(this).closest("[id^='nbContent_GR']");
that will traverse the DOM up until it finds a parent with ID starting with 'nbContent_GR'

.closest('[id^="nbContent_GR"]')

Two useful pages to look at:
http://api.jquery.com/closest/
http://api.jquery.com/attribute-starts-with-selector/
I think you can combine these for a solution.
From within the TR, find the closest TR. Then use the 'starts with' selector to find an ID which starts with your required value.
E.g.:
$(this).closest("tr").parent().find("id^='nbContent_GR'");

This may be late but for those of you who like me want it a bit different way, I figured out this way.
$(document).on('click', '.btn-info', function() {
var cardId = $(this).closest(".cardClass").attr("id");
alert(cardId);
console.log(cardId);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div id="card1" class="cardClass">
<button type="button" class="btn btn-info"></button>
</div>
<div id="card2" class="cardClass">
<button type="button" class="btn btn-info"></button>
</div>
<div id="card3" class="cardClass">
<button type="button" class="btn btn-info"></button>
</div>
<div id="cardn" class="cardClass">
<button type="button" class="btn btn-info"></button>
</div>
</div>

Related

How to get all fields in class

I have multiple classes with different number of fields inside them, 1 class example:
<div class="row form-row-extra-phone spacer">
<div class="col-12">
<div class="input-group">
<input type="tel" name="extraPhone-0-phone_number" class="form-control" placeholder="Extra Phone Number" maxlength="128" id="id_extraPhone-0-phone_number">
<div class="input-group-append">
<a class="btn btn-success btn-circle btn-sm add-form-row" href="#" role="button" id="plus_payment_data">+</a>
</div>
</div>
</div>
</div>
I want to iterate on all the fields inside the classes that have the attribute "name" and "id" , and add 1 to the number inside (in the example name="extraPhone-0-phone_number" -> name="extraPhone-1-phone_number")
I can select the class by:
$('.form-row-extra-phone')
How can I iterate on all the fileds inside it that contain the attributes 'name' and 'id'?
I assume you mean <div class="row form-row-extra-phone spacer"> when you speak about a class? This is an element, not a class.
Class can be a problematic term, because it can refer to CSS/DOM classes or Javascript classes, which are totally unrelated.
So if you have <div class="something"> then something is a CSS/DOM class, but the entire thing is not that class but an element having that class.
Now also what you refer to by fields are also just elements.
So what you want is to select all elements that have the class form-row-extra-phone and of them all descendant elements with an name attribute. And thats pretty easy. Basically in a CSS selector the (space) is the selector for descendant elements.
So you can select .form-row-extra-phone [name].
So what you probably want is something like this:
document.querySelectorAll('.form-row-extra-phone [name]')
.forEach(elem => elem.name.replace(/[0-9]/, x => Number(x) + 1));
When you use ^= it means starts with, and $= means ends with.
If condition is (name AND id)
$('.form-row-extra-phone input[name^="extraPhone"][id^="id_extraPhone"]')
If condition is (name OR id)
$('.form-row-extra-phone input[name^="extraPhone"],input[id^="id_extraPhone"]')
check this https://api.jquery.com/multiple-attribute-selector/ or google for "jQuery Multiple attributes selector"

Want to get the previous input from the button where I click on it

I want to get the previous input id from the button (point of view).
With the needs of my website, there will be at least 8 inputs like this and buttons of course.
So in order to facilite the task and avoid writing one function by input, I think this is way better to get the id of the 'previous' input from the button where I click.
I've browsed StackOverflow, but found nothing interesting in my case.
So here is the HTML code :
<div class="col-sm-3">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" ><i class="fas fa-link"></i></span>
</div>
<input type="text" name="first_map_link" class="form-control" id="first_map_link" placeholder="Lien première map...">
</div>
</div>
<div class="row">
<div class="col-sm-1">
<button class="btn btn-outline-info btn-get-infos"><i class="fas fa-search"></i></button>
</div>
</div>
I've tried with that : Undefined
$('.btn-get-infos').closest('input').attr('id')
Same with siblings. jQuery solution is prefered.
Thanks in advance
The issue is because closest() goes up the DOM looking for parent elements, while the input you want to find is a child of a sibling to a parent of the button you click on. With that in mind you'll need a combination of closest(), prev() and find(), like this:
var id = $('.btn-get-infos').closest('.row').prev('.col-sm-3').find('input').prop('id')
You'll need to walk up and down the DOM properly to find reference. Something like this:
$('.btn-get-infos').prev().find('input').attr('id');
Or if you're firing a click event, it can use the this keyword:
$this = $(this); //ref to the button clicked
$this.prev().('input').attr('id');
Give that a go and let us know if it works, dude. attr() i think was deprecated a while back, so new practise is to use prop().
Edit: I realise now that prev() only looks through previous siblings - ignore me :)

Traversing in jquery through multiple elements

So I am trying to traverse through multiple elements and I seem to be having a problem. I have 2 divs that have two child elements each - an input and a link. Inside the link there is also an image. When I click on the input button of the first div, I want to be able to traverse to it's sibling(the link{a tag}) and into the links child(the img tag) and get its source attribute which I will then use to change the image of the second div. Here's an excerpt of the code
HTML:
<div id="item">
<img src="img/deli/1.jpg" alt="Owl Image" id="homeimage">
<input type="submit" id="btn1" class="btn btn-default dropdown-toggle viewbuttons" value="View Item" onclick='changeImage( "img/deli/1.jpg" );'>
</div>
<div class="item">
<img src="img/deli/2.jpg" alt="Owl Image" id="homeimage">
<input type="submit" id="btn" class="btn btn-default dropdown-toggle viewbuttons" value="View Item" onclick='changeImage( "img/deli/2.jpg" );'>
</div>
JQUERY:
$(document).ready(function(e){
$('input#btn1').on('click', function(){
var changeThis = $('input#btn1').siblings('#yeezy').children('img').attr('src');
$("#homeimage").attr("img", changeThis);
})
});
Thank you in advance
IDs must be unique. ID selector only selects the first matching element in the document. You are getting/setting src attribute of one element, i.e. both $('input#btn1').siblings('#yeezy').children('img') and $("#homeimage") refer to the same element.
Either use different IDs or use class attributes. Also note that since IDs must be unique, $('input#btn1').siblings('#yeezy') doesn't make a lot of sense. You could simply select the element using an ID selector: $('#yeezy');
There are a few things off with your code. You use the id "homeimage" twice, but there should only ever be one of a given id. You have the onclick attributes set to a different function besides the one you want to run, so you should remove those. Finally, when you try to change the src attribute of the homeimage, you call the function on the img attr: ("img", changeThis);
Make sure that all of your ID's are unique, remove any onclick atrributes from your elements, and then replace:
$("#homeimage").attr("img", changeThis);
with:
$('#homeimage').attr('src', changeThis);

JQuery pseudo selector :visible is working at one place but not at other place

I am trying to select those input fields on page to validate which are visible on layout. I am able to find out this through one way but with another way its not actually working. What I am getting is my selector is working for direct child but not for grand children.
I want to select only those elements ids which are actually visible on layout to validate them as they should not be blank.
Jsfiddle Demo
HTML
<div id="createdDiv1">
<div id="row11">
<div class="hide">
<input type="text" class="blk" id="inp_11"/>
</div>
</div>
<div id="row12">
<div>
<input type="text" class="blk" id="inp_12" />
</div>
</div>
</div>
<div id="createdDiv2">
<div id="row21" class="hide">
<div>
<input type="text" class="blk" id="inp_21" />
</div>
</div>
<div id="row22" class="">
<div>
<input type="text" class="blk" id="inp_22" />
</div>
</div>
</div>
<button onclick="subCheck('#createdDiv1 :visible')">check 1st</button>
<button onclick="subCheck('#createdDiv2 :visible')">check 2nd</button>
JavaScript
function subCheck(inBlock) {
inBlock=(inBlock==undefined)?'':inBlock;
var ids=[];
$(inBlock+' .blk').each(function(){
ids.push($(this).attr('id'));
});
console.log(ids);
}
CSS
.hide{
display:none;
}
Note: I don't want to change my subCheck() function since its generalized for all valiations, what I need to know how can I make it work with :visible selector or something similar to it to work with multi-levels checks for visible elements.
Sorry If I am making it ambiguous for you. I am not sure what exactly to explain in words.
use :not to exclude the class .hide:
<button onclick="subCheck('#createdDiv1 .inputDiv:not(\'.hide\')')">
check 1st
</button>
<button onclick="subCheck('#createdDiv2 .inputDiv:not(\'.hide\')')">
check 2nd
</button>
Fiddle: http://jsfiddle.net/Z4PSV/1/
Although I wouldn't suggest using onclick at all though, instead:
<button class="subcheck" data-id="createdDiv1">check 1st</button>
<button class="subcheck" data-id="createdDiv2">check 2nd</button>
<script>
$(document).on('click', '.subcheck' function() {
//Creates string as: '#createdDiv1 .inputDiv:not('hide')
var ft = "#" + $(this).data('id') + " .inputDiv:not('.hide')";
subCheck( ft );
});
</script>
Fiddle: http://jsfiddle.net/kY8Wh/
Lastly, if you were wishing to implement your :visible then:
<button onclick="subCheck('#createdDiv1 .inputDiv:visible')">
check 1st
</button>
<button onclick="subCheck('#createdDiv2 .inputDiv:visible')">
check 2nd
</button>
Fiddle: http://jsfiddle.net/Zgm78/
Would be sufficient too.
The issue is that you scan all the inner .blk elements of a visibile top element using each, in this case the element itself is visible, but hidden from the middle parent.
I know you won't change your subCheck function, bu you can simply solve the issue by checking there the visibility of the child element .blk.
Visibile selector take care of the effective visibility of the element (direct or nested):
Elements are considered visible if they consume space in the document.
Visible elements have a width or height that is greater than zero.
Elements with visibility: hidden or opacity: 0 are considered visible,
since they still consume space in the layout.
Elements that are not in a document are considered to be hidden;
jQuery does not have a way to know if they will be visible when
appended to a document since it depends on the applicable styles.
I think that this change will not break anything in your code.
Code:
function subCheck(inBlock) {
inBlock=(inBlock==undefined)?'':inBlock;
var ids=[];
$(inBlock+' .blk:visible').each(function(){
ids.push($(this).attr('id'));
});
//console.log(ids);
alert(ids);
}
Demo: http://jsfiddle.net/IrvinDominin/her4Y/

Embedding database ID of element in HTML for Ajax request

There is given code:
<div id="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div id="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<script>
$(".edit").click(function() { var id = $(this).parent().attr("id"); /* do some Ajax here, edit element in database with given id*/});
$(".delete").click(function() { var id = $(this).parent().attr("id"); /* do some Ajax here, delete element in database with given id*/});
</script>
There is a database with some elements, these elements have ID and I would like to do some actions on these elements via Ajax. I need database ID of element so that I can do some Ajax requests on this element. Solution above works, however there are some flaws - it is dependent from HTML structure (for example when I wrap button with some other element then parent() will not work because HTML structure changed).
How to store the better way database IDs of elements in HTML so JavaScript can get it for example for Ajax requests?
Why not do something like this using the data() method:
<div>
<p>SOMELEMENT</p>
<button class="edit" data-id="256">EDIT</button>
<button class="delete" data-id="256">DELETE</button>
</div>
<div>
<p>SOMELEMENT2</p>
<button class="edit" data-id="257">EDIT</button>
<button class="delete" data-id="257">DELETE</button>
</div>
Now that you have the data-id associated with your buttons, you can do:
$(".edit").click(function() {
var id = $(this).data("id");
/* do some Ajax here, edit element in database with given id*/
});
EXAMPLE
Although you already have a (completely valid) accepted answer, I wanted to offer another way of solving your problem that removes the burden of having to attach data to every button, instead relying on a class that can be used to get a handle to the actual item/record/entry to which the data is attached, as my HTML tends to have such a class anyway I found this pretty convenient (I'll use a list of comments as an example):
<div class="comment" data-id="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div class="comment" data-id="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<script>
$(".comment .edit" ).click(function() { var id = $(this).closest('.comment').data('id'); });
$(".comment .delete").click(function() { var id = $(this).closest('.comment').data('id'); });
</script>
Key is the .closest() jQuery function that travels up the DOM tree to find the '.comment' div that represents the comment entry. This means that as long as you keep your .edit and .delete elements inside the .comment DIV, you're free to modify your HTML structure without having to worry about your JavaScript, and without having to add the data-* attributes in multiple places.
You could use data attributes. Instead of having the id of an data entity be represented by an html id attribute. These are attributes of the form data-*.
Your code could then look like this:
<div data-elementid="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div data-elementid="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
<script>
$(".edit").click(function() { var id = $(this).parent().data('elementid'); });
$(".delete").click(function() { var id = $(this).parent().data('elementid'); });
</script>
John Resig writes about it here:
http://ejohn.org/blog/html-5-data-attributes/
Additionally you could set the data attribute on the button elements, then you wouldn't have to traverse up to the parent() to get the id.
If you want to go deeper, check out a js framework like Angular.js, Ember.js or Backbone.js. The idea is that the DOM shouldn't be used for storing data, only presenting it. Javascript models can then be used to store your application data.

Categories

Resources