Find index of item within a specific div where multiple divs exist - javascript

I have a HTML set up of many images, wrapped in divs, which are wrapped 4 items to a row. Example, 4 items per row, 2 rows:
<div class="staff-wrapper">
<div class="staff-row">
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
</div>
<div class="staff-row">
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
<div class="staff-item">
<img>
</div>
</div>
</div>
I want to be able to identify, when clicking on the image, which index this item has within its row.
So if the 3rd item of a row is clicked, the value will be 3. The possible answers should only ever be 1,2,3 or 4 because there can only ever be maximum 4 items per row.
I almost have this, however I'm finding the result is always based on the whole of the list of items, so I'm getting answers like 7 for the last item. Instead this should be 3`, because it's the third item in it's row.
Here is what I have:
var itemPosition = $(".staff-row img").index(this);
Any ideas?
JS Fiddle https://jsfiddle.net/vo6hz1zc/

You should be finding the index of the parent of the this which is img that's clicked.
Also add 1 as indexes start from 0
$('.staff-item img').click(function(){
var itemPosition = $(this).parent().index() + 1;
console.log(itemPosition);
});
JSFiddle

What you want is getting the right row first, and then get the index you could loop trough the rows:
$('.staff-item img').click(function(){
$this=$(this);
var itemPosition = $(".staff-row").each(function(){
itemPosition=$("img",$(this)).index($this);
if(itemPosition>-1){
console.log(itemPosition);
}
});
});
A better option is just select the child from this if thats possible is selecting the parent and search in the parent:
$('.staff-item img').click(function(){
var itemPosition = $(this).parent().index();
console.log(itemPosition)
});

Try this.
$('.staff-item img').click(function(){
var itemPosition = $(this).closest(".staff-row").find(".staff-item img").index(this);
alert(itemPosition);
});
Updated your jsfiddle https://jsfiddle.net/prakashlaxkar/vo6hz1zc/3/ as well. Thanks

Related

Remove repeated after 1st occurrence

I'm trying to clean up the results presented on my HTML file with Jquery. I want to keep removing words that are repeated more than one time.
A quick example
Accents Australian
Accents English (RP)
Dance Hip Hop
Dance Jazz
It should be output as
Accents
Australian
English (RP)
Dance
Hip Hop
Jazz
My original HTML looks like this
<div role="list" class="skill-items">
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>Australian</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Jaz</div>
</div>
</div>
I tried my best but I'm not landing in a good place
$('.skill-category').text(function(index, oldText) {
return oldText.replace($(this).parent().next().find('.skill-category').text(), '');
})
Any suggestion?
Please check below working code:
const category = [...document.querySelectorAll('.skill-item > .skill-category')];
const texts = new Set(category.map(x => x.innerHTML));
category.forEach(category => {
if(texts.has(category.innerHTML)){
texts.delete(category.innerHTML);
}
else{
category.remove()
}
})
As per you question and shared HTML above is the working code for the same and if you add more similar things it will help.
Please let me know if you find any issues
Your question can be broken into two problems:
You want to group the elements with the same value for .skill-category
You want to change <div> elements into a list.
Grouping the elements could by done like so:
For every category, take a look at the previous element.
Does it contain the same category? If not, then continue to the next category.
If so, take everything after .skill-category (in your example HTML, that's a single <div>. Cut-and-paste it at the end of the aforementioned previous element.
For the second problem:
Changing an element (<div> to <li>) is not possible. You can create a new <li> and move what's inside the <div> into it. Of course, you'll need a <ul> that wraps the <li>s as well.
Take the .skill-category elements
Find all the content that follows the category (in your case, 1+ <div> elements)
Put the contents of the matched elements into a new <li>.
Put all the <li>s of a single category into a <ul>.
Remove the matched elements (in your case, the <div>(s)) since we've moved all their content to a different node. They're now empty tags and useless.
Put the <ul> after the .skill-category.
// Grouping the results.
$('.skill-category').each(function() {
// Get the previous .skill-item and find the category.
var prev = $(this).parent().prev('.skill-item').find('.skill-category');
// Check if the previous category === this category.
var same = !!(prev.length && prev.text() === $(this).text());
if (!same) {
return; // Do nothing.
}
// Take every element after the category and move it to the
// previous .skill-item.
prev.after($(this).nextAll());
// Then remove the now-empty category.
// All content has been moved to the previous element, after all.
$(this).parent().remove();
});
// Wrapping the contents of a category in a list.
$('.skill-category').each(function() {
var list = $('<ul></ul');
// Find everything after the category.
$(this).nextAll().each(function() {
// Create a <li> and move the child elements to it.
// Then add the <li> to the <ul>.
$('<li></li>').append($(this).contents()).appendTo(list);
}).remove(); // remove the now empty elements.
// Add the list to current .skill-category.
$(this).append(list);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div role="list" class="skill-items">
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>Australian</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Jaz</div>
</div>
</div>

How to edit childrens div?

I have this HTML code (and the number of components that I want to edit it's variable, it could be 3 or 20).
I have created a small example with similar scenario on my website
As you can see my script is able to edit the father div and add the classname. Same for firstchild.
I would like to edit all divs inside firstchild but not the immediately div, it has to be two inside.
Any ideas why my code is not working on the last part?
Thanks.
// WORKS OK
var firstc = document.getElementById('father');
firstc.classList.add("father-class");
firstc.children[0].children[0].children[0].setAttribute("id", "firstchild"); // WORKS OK
var second = document.getElementById('firstchild');
second.classList.add("child-class");
// NOT WORKING
var grandchildren = second.children[0].children[0].children[0];
for (let z = 0; z < grandchildren.length; z++) {
grandchildren[z].classList.add("slide");
}
<div id="father">
<div>
<div>
<div id="firstchild">
<div>
<div>
<div class="random63637236">
<li>1</li>
</div>
<div class="generic">
<li>2</li>
</div>
<div class="italy_gdgd">
<li>3</li>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
the problem in your code is the last children[0]. you are selecting only the first div, it's not an array. Fix that line and everything will work
var grandchildren = second.children[0].children[0].children;
As a side note: if for some reason the first or the second .children[0] are undefined you will get an error.
A better approach is to use querySelectorAll which returns an array;
if your array it is empty, nothing happens.
second.querySelectorAll('#firstchild > div > div > div')
.forEach(el => el.classList.add('slide'))

jQuery: how to get the index of an element in the selection array?

I have an HTML structure like this:
<div class="container">
<div class="item">
1
2
3
</div>
<div class="item">
4
5
6
</div>
</div>
I select all the A-s with jQuery, and get a total of 6 objects here. I want to get the index of the A in the array of 6 (so I can detect which A has been clicked, for example), but when I use .index() I get the index of the element relative to its parent. So for the 5th A I get the same index as for the 2nd, because te 5th is actually the second in its group within its div.item:
$('a').click(function(){
console.log ( $(this).index() ); // returns "1" for the 5th A
});
So is there a way to get the index of the clicked element within the array of the selection, instead of within the parent in the DOM?
You can pass the clicked element to the index method:
var $a = $('.container > .item > a').click(function() {
console.log ( $a.index(this) );
});
Take a look at jquery documentation for .index(). You could modify your code as following to get the desired result:
$('.container').on("click", "a", function(){
console.log ( $("a").index($(this)));
});
$('a').click(function(){
$("#result").text($('a').toArray().indexOf(this));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">
1
2
3
</div>
<div class="item">
4
5
6
</div>
</div>
<div id="result"></div>

jQuery how to replace all contents of an element into another?

Say I have 3 elements like below with different html contents:
<div id='result1'> <p>One</p> </div>
<div id='result2'> <p>Two</p> </div>
<div id='result3'> <p>Three</p> </div>
How can I copy just contents within the div element to the next one so that the final result looks like this?
<div id='result1'> <p>New content</p> </div>
<div id='result2'> <p>One</p> </div>
<div id='result3'> <p>Two</p> </div>
There will be new content for replacement and the last content can be discarded.
To clarify, I'll have something like:
<div id='new'> <p>New content</p> </div>
where I want to grab '<p>New content</p>' as new content to use.
What do you think?
To push the content down, reverse the collection and set the HTML to the HTML of the previous one.
var elems = $($('[id^=result]').get().reverse());
elems.html(function(i) {
return elems.eq(i+1).html();
}).last().html('New Content');
FIDDLE
You can use .html() on the element you want to change the content. For accessing particular element you can use ID Selector (“#id”) with Child Selector (“parent > child”).
Live Demo
$('#result1 > p').html('New content');
Edit to move contents to next elements you can iterate through all elements and start assigning the context of second last to last, third last to second last and so on
Live Demo
elements = $('[id^=result] > p');
len = elements.length;
elements.each(function(idx, el){
if(idx == elements.length-1) return;
$('#result'+ (len-idx) + ' p').html($('#result' + (len-idx-1) + ' p').html());
});
$('#result1 > p').html('New content');
try JS fiddle
I am suggesting to add a Parent Grid and use jquery first() and last(), These controls will function like a queue.
$('#Pdiv').children().last().remove();
$('#Pdiv').first().prepend("<div id='new'> <p>I am New One</p></div>");
alert($('#Pdiv').children().first().html());

jQuery: Finding elements which contain certain text

I have a calendar with an event list below it on my page. When the user clicks on the next or previous button, I want to populate a div with the contents of rows only containing the currently displayed month and year on the calendar. Here's the structure of the rows (created with Drupal 7 Views).
<div id="all-events">
<div class="views-rows">
<div class="field-date">
<div class="field-content">
<span>June 2011</span>
</div>
</div>
</div>
<div class="views-rows">
<div class="field-event-title">
<div class="field-content">
<span>Some Event</span>
</div>
</div>
</div>
</div>
I got this far with jQuery, but I'm getting a huge list of errors:
$('#calendar span.fc-button-next').live('click', function(){
var month = $('#calendar .fc-header-title h2').html();
$('.event-list').fadeOut(350, function(){
$(this).html('');
$('#all-events').each('.views-rows',function(){
// Code goes here...
});
});
});
I should also mention that I'm using FullCalendar to create the calendar, so it's created with this plugin. Right now I can get the current month the user is viewing, but I want to go through the list and find all rows that contain this month and display them in the .event-list div.
I couldn't fully understand what you want, but to filter elements by its text use filter
<div>text 1</div>
<div> not this text </div>
JS
$("div").filter(function(){
return $(this).text().indexOf("text 1") >= 0; // if contains desired text
}).html("this one matches 'text 1'");
See this example on jsFiddle
This seems wrong:
$('#all-events').each('.views-rows',function(){...});
How about this:
$('.views-rows', '#all-events').each(function(){...});
Since version 1.1.4, jQuery has a contains selector to select elements containing a specific text.
$('#calendar span.fc-button-next').live('click', function(){
var month = $('#calendar .fc-header-title h2').html();
$('.event-list').fadeOut(350, function(){
var event_list = $(this).html('');
$('#all-events .views-rows:contains(' + month + ')').each(function(){
event_list.append($(this).html);
});
event_list.fadeIn();
});
});

Categories