Find row index using jQuery - javascript

<div class="parent">
<div class="formRow js-TextBox"><a></div> <------ index 0
<div class="formRow js-Image"><a></div> <------ index 1
<div class="formRow js-TextBox"><a></div><------ index 2
<div class="formRow js-ImageList"><------ index 3
<div class="formRow js-Image"><a></div> <-- **This should return 3 but is returning 4 because I search index on the basis of formRow**
</div>
Code to find the formRow index
var parent = $(this).parents("div.formRow");
var rowIndex = parent.parent().find("div.formRow").index(parent);
Please refer to above code and advise how I can find the index of formRow for which I have clicked on anchor element a.
The problem is that the last form row contains another formRow, but I want the index of parent form row.

I'd remove ambiguity and provide the row number to the element at render time, i.e.
<div class="formRow js-TextBox" id="row<%= rownumber %>"><a></div>
Or as the ID to the anchor:
<div class="formRow js-TextBox"><a id="row<%= rownumber %>"></div>
There are a multitude of ways to approach this. I always find that if something seems to hard then I'm approaching it from the wrong direction (or just plain wrong).

Can you modify the above - I'd add another css class - primaryRow to the first three and use that instead of formRow in the jQuery expression
OK - The run this code:
$('.parent > div').addClass('primaryRow');
to add the class.
Then
var rowIndex = $('.primaryRow').index($(this).parents().find('.primaryRow'));

This works.
$('a').click(function(){
var i = $(this).parents('.parent > .formRow').index('.parent > .formRow');
alert(i);
return false;
});
Check it out: jsfiddle

Related

JavaScript possible to select all elements with classname that starts with (...)? [duplicate]

I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:
<form>
<input type="text" onfocus="showfields(1);">
<input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
function showfields(page){
//hide all items that have a class starting with page*
var patt1 = /^page/;
var items = document.getElementsByClassName(patt1);
console.log(items);
for(var i = 0; i < items.length; i++){
items[i].style.display = "none";
}
//now show all items that have class 'page'+page
var item = document.getElementsByClassName('page' + page);
item.style.display = '';
}
</script>
When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page').
The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.
getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).
The best approach is to use multiple classes…
<div class="page page1">
i.e. This div is a page, it is also a page1.
Then you can simply document.getElementsByClassName('page').
Failing that, you can look to querySelector and a substring matching attribute selector:
document.querySelectorAll("[class^=page]")
… but that will only work if pageSomething is the first listed class name in the class attribute.
document.querySelectorAll("[class*=page]")
… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".
That said, you could use the last approach and then loop over .classList to confirm if the element should match.
var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
for (var i = 0; i < potentials.length; i++) {
var potential = potentials[i];
console.log(potential);
classLoop:
for (var j = 0; j < potential.classList.length; j++) {
if (potential.classList[j].match(/^page/)) {
console.log("yes");
potential.style.background = "green";
continue elementLoop;
}
}
console.log("no");
potential.style.background = "red";
}
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Previous answers contain parts of the correct one, but none really gives it.
To do this, you need to combine two selectors in a single query, using the comma , separator.
The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).
By combining both selectors, we have our classStartsWith selector:
document.querySelectorAll('[class^="page"],[class*=" page"]')
.forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
You can use jQuery solution..
var $divs = $('div[class^="page"]');
This will get all the divs which start with classname page
$(document).ready(function () {
$("[class^=page]").show();
$("[class^=page]").hide();
});
Use this to show hide div's with specific css class it will show/hide all div's with css class mention.

Jquery assign second child attribute

Is there a way to assign nested div attribute with variable? Like
<div>
<div>
123456
</div>
</div>
Become
<div>
<div sectionid="123">
123456
</div>
</div>
BTW above component will be created by JavaScript.
I've tried something like this, but it didn't work.
var a = $('<div><div>123456</div></div>');
a.eq(":nth-child(2)").attr("sectionid", "123");
Try this snippet.
//FOR DOM HTML
console.log("FOR DOM HTML");
//1st way
$('#input > div').find('div').attr("sectionid","123");
console.log($('#input').html());
//2nd way
$('#input > div > div').attr("sectionid","321");
console.log($('#input').html());
//JS HTML
console.log("FOR JS OBJECT");
var input = $('<div><div>123456</div></div>');
//1st way
input.eq(0).children().attr('sectionid', '456');
console.log(input[0].outerHTML);
var input = $('<div><div>123456</div></div>');
//2nd way
$(input[0]).children().attr('sectionid', '789');
console.log(input[0].outerHTML);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="input">
<div>
<div>
123456
</div>
</div>
</div>
nth-child(2) maches elements that are the second child element of their parent. This is not the case for your div, it is the first element of the parent div.
.eq finds an element at a specific index. It is not the place to pass a selector.
The child selector, >, will find a child element, i.e. div>div will find a div that is an immediate child of a div.
Note that the code you've provided, $('<div></div>123456<div></div>');, doesn't create a DOM tree like the one you've pasted.
Update, now that the code is edited, the value of a is a div with a child div. Since a.find will perform a search within a, you don't have to use a child selector, but can find the div immediately:
a.find('div')
Just apply attribute to children. No complicated 'find', eq(), etc.
var a = $('<div><div>123456</div></div>');
a.children().attr('sectionid', '123');
$('body').append(a);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Why don't you add it in the first place? Not clear if you add it later!
$(document).ready(function() {
var sectionid = "123";
var a = $('<div><div sectionid="' + sectionid + '">123456</div></div>');
$('body').append(a);
});
div[sectionid]{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Try this - I have added comments to the code to explain what is happening.
Inspect the element to see that the attribute is added
var a = $('<div><div>123456</div></div>'); // change this to match the structure you want
a.children() // .children gets the direct descendant (which should be the nested div
.eq(0) // gets the first in the array that is returned (if there are multiple direct descendents) - it is a 0 based index selector
.attr('sectionid', '123');
$('body').append(a)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
More information about .children()
More information about .eq()
try it :
$(document).ready(function(){
$("div").eq(1).attr("sectionid","123");
})

Count number of first layer/set of children in cloned element

I am trying to count the number of it's first layer of children not including it's child of child of child.. This is my codes
HTML
<div class="container">
<div class="row">
<div class="btn-container col-md-12">
Hello
</div>
</div>
</div>
JS
$('a').click(function(){
var c = $(this).closest('.row').clone();
$(this).after( c );
var count = $(this).closest('.row').find('.btn-container').length;
alert(count);
});
The alert should always return 1 since the cloned element is appended inside of it.
jsFiddle
I tried ..
.find() but also as I expected, it will count all inside of it.. Child of child of child and so on...
var parent = $(this).closest('.row');
var count = $('.btn-container', parent).length;
But still can not get what I want.
I already think of adding a name/class specifying to them. Like btn-container first-children ..
But I am wondering if there is a jQuery trick that will make it simplier.
find('.btn-container') will select all descendants .btn-container. You should use direct child selector > like following.
$('a').click(function () {
var c = $(this).closest('.row').clone();
$(this).after(c);
var count = $(this).closest('.row').find('>.btn-container').length;
//---------------------------------------^^--------------------
alert(count);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="btn-container col-md-12">
Hello
</div>
</div>
</div>
Rather than find() you could use children(). From jQuery .children() documentation:
The .children() method differs from .find() in that .children() only
travels a single level down the DOM tree while .find() can traverse
down multiple levels to select descendant elements (grandchildren,
etc.) as well
var count = $(this).closest('.row').children('optional-selector').length;

Siblings with same attribute value

I have a div structure like
<div>
<div class='class1'>contens</div>
<div class='class2'>contens</div>
<div class='class2'>contens</div>
<div class='class2'>contens</div>
<div class='class3'>contens</div>
<div class='class2'>contens</div>
<div class='class1'>contens</div>
</div>
Here I want to write a selector which will select all the div elements with class='class2', they should be adjacent to each other. i.e I should select only index 1,2,3 but not div index 5 since its not adjacent to group.
Please Help here.
You can use the adjacent sibling selector
var elems = $('.class2 + .class2').add( $('.class2 + .class2').prev() )
FIDDLE
or caching the selector (with an argument to a IIFE)
var elems = (function(x) {return x.add( x.prev() )})($('.class2 + .class2'));
FIDDLE
Here is an alternative solution with .filter:
For example:
$('.class2').filter(function() {
return $(this).prev('.class2').add($(this).next('.class2')).length > 0;
});
It filters out the elements that don't have a sibling with class .class2.

filter out which span to update

I have the following div collection in my HTML. It's designed to dynamically replicate according to user interaction.
<div class="bill-item">
<!-- Section for a single item -->
<div class="bill-item-img">
<!-- Section for Item pic -->
</div>
<div class="bill-item-description">
<!-- Section for Item description and pricing -->
<div class="bill-item-name">
<p class="bill-item-name-left">Normal Cofee</p><p class="bill-item-name-right">170.00</p>
<div class="clear"></div>
</div>
<div class="bill-item-price">
<span>170.00 USD</span>
</div>
<div class="bill-item-amount">
<span>2</span>
</div>
</div>
<div class="bill-amount-selection">
<!-- Section where the increment & decrement of item amount goes -->
<a class="amount-increase" href="#"></a>
<a class="amount-decrease" href="#"></a>
</div>
</div>
This is the HTML Rendered image of the elements.
I've written the following script to increase the bill-item-amount span value.
$(".amount-increase").click(function(){
x+=1;
$(".bill-item-amount span").html(x);
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$(".bill-item-amount span").html(x);
}
});
This works great but, it updates the value of both the span elements. what I want is to catch the event of the clicked element (which I do now) and increase the span value of the respective span. How can I filter out which span to update using javascript.?
Something like $(this).parents('.bill-item').find('.bill-item-amount span') should select the right element.
Inside your callback this is assigned to the eventSource.
You should walk the dom tree from the clicked element up until you reach the .bill-item element and the go down to the .bill-item-amount span node
$(".amount-increase").click(function(){
var $span = $(this).parent().parent().find(".bill-item-amount span");
var x = $span.html();
x+=1;
$span.html(x);
});
$(".amount-decrease").click(function(){
var $span = $(this).parent().parent().find(".bill-item-amount span");
var x = $span.html();
if(!x<=0){
x-=1;
$span.html(x);
}
});
Hi dimal update your code:
$(".amount-increase").click(function(){
x+=1;
$(".bill-item-amount").html(x);
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$(".bill-item-amount").html(x);
}
});
dont add span inside the selector [ it changes entire span values]
$(".amount-increase").click(function(){
x+=1;
$("use ur increase span id here").html(x); //
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$("use ur decrease span id here").html(x);
}
});
Inside each function the selector $(".bill-item-amount span") will find all the <span> amounts in the document. You can walk the DOM to find the correct <span> using jQuery or plain JavaScript. You seem to be using jQuery functions so my answer also uses jQuery.
The following code combines the two actions into a single function that increases or decreases the amount based on the class name of the <a> clicked. I also added a return false so that the browser will not follow the href="#" on the anchor.
$('.bill-amount-selection').on('click', 'a', function(){
var change = this.className == 'amount-increase' ? 1 : -1
var $amount = $(this).closest('.bill-item').find('.bill-item-amount span')
var amount = parseInt($amount.html(), 10) + change
$amount.html(amount < 0 ? 0 : amount)
return false
});
The use of .on() means that jQuery v1.7+ is required. I can supply a compatible function with lower jQuery versions if necessary.

Categories

Resources