Run each for a class but once for group - javascript

I have a lot of elements with the same class. These elements are divided into groups by means of attribute "data-xxx"
<div class="myclass" data-n="group1"></div>
<div class="myclass" data-n="group1"></div>
<div class="myclass" data-n="group1"></div>
....
<div class="myclass" data-n="group2"></div>
<div class="myclass" data-n="group2"></div>
...
<div class="myclass" data-n="group3"></div>
...
...
How to perform a function on each item, but only once in each group using something like this?
$('.myclass').each(function(){
/// My function
});

Working example: http://jsfiddle.net/5sKqU/1/
$(document).ready(function() {
var group = {}; //an object that we're going to use as a hash
$('.myclass').each(function(){
if (group[$(this).attr('data-n')] != true) {
group[$(this).attr('data-n')] = true;
//do something here once per each group
alert('Group: '+ $(this).attr('data-n'));
}
});
});
I'm assuming that you only need this to run once on page load. If you could share more about your requirements, I can show you what changes you'll need to make.

Something like this maybe :
var groups = {};
$('.myclass').each(function(i, el) {
var n = $(el).data('n');
if(!groups[n]) {
groups[n] = $();
}
groups[n] = groups[n].add(el);
});
//At this point the object `groups` has one property per group,
//each value being a jquery collection comprising members of the group.
//Now the world's your oyster. You can loop through the groups
//with full access to each group's members if necessary.
$.each(groups, function(groupName, jq) {
//my function
});

You can set a certain HTML attribute on all group elements after processing the first one. After that, you can check the value of that attribute:
$('.myclass').each(function(){
if($(this).attr("processed")!="true") {
// process...
$("[data-n=" + $(this).attr("data-n")).attr("processed", "true");
} else {
// skip, or do something else with the element
}
});

You can select out each group with the jQuery attribute selector, like this:
$( '.myclass[data-n="groupX"]' );
I'm not sure if you meant that you only wanted to apply your function to one element in each group, but if so this will give you only the first in each:
$( '.myclass[data-n="groupX"]' ).first();
Given that you label your groups 1 through N you can just check if there is anything in the resulting set to determine when you have looped through every group.

Related

How to use jQuery to select deeply nested elements created dynamically with javascript

So I have an object in my code and I use js to add the properties of the object to an array named rec based on users interaction. then I use a function named unRec to get unique elements of the array. Then I add the values returned by unRec to the HTML. Then I use jquery to wrap each of the values in anchor tags. So the code is basically like this
obj= {
0: "<span>module1</span>",
1: "<span>module1</span>",
2:"<span>module1</span>",
3:"<span>module2</span>",
4:"<span>module2</span>",
5:"<span>module3</span>",
6:"<span>module3</span>",
7:"<span>module3</span>",
8:"<span>module3</span>",
9:"<span>module4</span>"
}
function unRec(arr){
preRec = [];
for (j of arr){
if (preRec.indexOf(j)=== -1) {
preRec.push(j);
}
}
return (preRec);
}
Recom.innerHTML = unRec(rec);
$('#congrat #recom span').wrap('')
Now am unable to select the created anchors. Hence this function doesn't work
$('#congrat #recom .disp').click(function(e) {
var url = $(this).attr('href') + '#' + $(this).text();
$('#module').html('loading...).load(url); e.preventDefault();
});
I have tried to use find to select the anchors but it still doesn't work. This is the test
var t = $('#congrat #recom').find ('a').length;
console.log(t);
The HTML is basically like this:
<div id="congrat">
<span id="recom"></span>
</div>
<div id="module">click on one of the modules above<div>
Please provide a solution to select the created anchors. Thanks in advance

Select the elements with at least one value in their data attribute, which is included in a certain array

I am writing a filtering function, in which I need to select the elements that have a certain value in their data attribute, and those values are included in an array, allow me to explain it in an example:
For example, I have three elements and a button as follows:
<div data-foo="aa,cc,ff" ></div>
<div data-foo="bb,cc,ff" ></div>
<div data-foo="bb,dd,ee" ></div>
<div class="button" data-boo="aa,ff" ></div>
The data-foo in each element contains comma-separated values. When I click on the button, I create an array (myArray in the code below) from its data attribute, then I need to select those elements that at least one of the values in that myArray is in their data-foo, for a clear explanation please see the code below:
$( ".button" ).click(function() {
// First I make an array from the button's data attribute
var myArray = $(this).data('boo').split(',');
// Select should be elements that their da-foo has at least one
// — of values in the array above
var Select = "?"
});
How the Select variable can target the first two elements, since the first one has both "aa" and "ff", and the second element has "ff".
I really tried to put it the way that makes sense, if it is not clear enough, please let me know and I will be happy to explain more, thank you.
You can use Attribute Contains Selector:
$( ".button" ).click(function() {
// First I make an array from the button's data attribute
var myArray = $(this).data('boo').split(',');
// produces array of strings like '[data-foo*="aa"]'
var selectors = myArray.map(function(value) {
return '[data-foo*="' + value + '"]';
});
// searches by selectors joined by comma, returns all elements
// that satisfy at least one selector
var selectedElements = $(selectors.join(','));
});
Lets use Array.prototype.some for this:
$(".button").click(function() {
// First I make an array from the button's data attribute
var myArray = $(this).data('boo').split(',');
// Select should be elements that their da-foo has at least one
// — of values in the array above
var Select = $("div[data-foo]"); //select all elements with data-foo
Select.each(function(index, element) {
var isInMyArray = $(element).data("foo").split(",").some(function(element) {
if ( myArray.indexOf(element) != -1)
{return true;}//if true then element is in myArray
}); //using some here - if one value is found in array return true.
console.log(isInMyArray);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-foo="aa,cc,ff"></div>
<div data-foo="bb,cc,ff"></div>
<div data-foo="bb,dd,ee"></div>
<div class="button" data-boo="aa,ff">test</div>

How to get a class name based on div hover in jquery

I'm looking for a way to fetch the class name based on hovering on a div. Both div has same id but slightly different class name. take a look at the below example:
<div id="1-someid" class="1-example-class border cz">
...more element goes here....
</div>
and
<div id="2-someid" class="2-example-class border cz">
...more element goes here....
</div>
Update: I've made the id name unique based on expert's opinion posted below. :) Thanks for all the helps.
Now what I want is, when user hover on the div with 1-example-class it will return me the class name 1-example-class. and when people will hover on the div with 2-example-class it will return me 2-example-class name.
So that I can use parseInt() on that name to fetch the number, 1, 2, 3 and so on.
Also please note that writing a static script for just 1-example-class or 2-example-class will not help as there are many more divs like this with 3, 4, 5 and so on attached to it.
Can anyone help? I have tried the following but it didn't helped.
$('#someid').hover(function() {
var class_names = $(this).attr('class');
var class_name = class_names.split( ' ' );
var c = parseInt( class_name[0] );
console.log( c );
});
If anyone can help it will be really helpful.
Attribute selector and Regex is the way to go:
$("[class*=example-class]").hover(function() {
var c = this.className.match(/(\d+)-example-class/)[1];
console.log(c);
});
$("[class*=example-class]") matches all elements that their class
attribute includes 'example-class' string.
this.className.match(/(\d+)-example-class/)[1] gives the related
number.
Here is a way to do it based on your current configuration:
$('div').hover(function() {
// grab class attribute, split on space character (like you're doing already)
var class_names = $(this).attr('class').split( ' ' );
// loop through each class
$.each( class_names, function( k,v ){
// see if this 1 class matches your example
if ( v.indexOf("example-class") > 0 ){
// if it does, remove text part of class name
var this_num = v.replace( '-example-class', '' );
// output numeric value only to console
console.log( parseInt( this_num ) );
}
});
});
This method does not expect the same class configuration (meaning the classes in your class attribute can be in any order, so long as it does contain the example string). In your question, the code expects first class listed to be the example string class.
See this example: https://jsfiddle.net/31505tw1/
In the example, I have replaced your duplicate IDs into classes. As others have pointed out, HTML spec requires each ID to be unique.
There are several ways to do this- but other users are correct that your issue is in using the same ID multiple times, that's the only reason the code you already have doesn't work. If you use one of the other shared classes as your selector your original script will work:
$('.border').hover(function() {
var class_names = $(this).attr('class');
var class_name = class_names.split( ' ' );
var c = parseInt( class_name[0] );
console.log( c );
});
Firstly, you should use unique ID's on your div's: https://stackoverflow.com/a/9454716/984323
Not only for the HTML to be valid, but your jQuery script wouldn't be able to differentiate between the two. Then you can target each div and the rest of your code seems to work.
<div id="someid" class="1-example-class border cz">
...more element goes here....
</div>
<div id="someid2" class="2-example-class border cz">
...more element goes here....
</div>
https://jsfiddle.net/05r8f013/1
ID's must be unique all over html. Since you are using classname to get the data, you can add name field to the div:
<div name="someid" class="1-example-class border cz">
...more element goes here....
</div>
<div name="someid" class="2-example-class border cz">
...more element goes here....
</div>
$('[name="someid"]').hover(function() {
var class_names = $(this).attr('class');
var class_name = class_names.split( ' ' );
var c = parseInt( class_name[0] );
console.log( c );
});
Maybe you could for example:
$('div').hover(function(){
if ( $(this).attr('class') == 'some class' ) {
//Do something
} else {
//Do something else...
}
You could do a Regex on the hovered items that match on the pattern of the class name:
<div name="someid" class="1-example-class border cz">
...more element goes here....
</div>
<script>
$('#someid').hover(function() {
var className = this.className.match(/(\d)-example-class/);
if(className){
console.log(className[0]) // 1-example-classname
console.log(className[1]) // 1
}
});

Get numerical value from parent with id like 'post-1' and use it in jQuery function

I'm trying to figure out the following.
I have following jQuery code:
var as = "";
var bPlay = 0;
audiojs.events.ready(function() {
as = audiojs.createAll();
$(".audiojs .play-pause").click(function() {
var e = $(this).parents(".audiojs").index(".audiojs");
$.each(as, function(t, n) {
if (t != e && as[t].playing) {
as[t].pause()
}
})
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar").stop();
}
})
});
In a nutshell it preforms list of things when someone clicks particular .audiojs instance on a page. 1) checks if there is any other instance playing, if there is pauses it. And if it is playing applies fluctuate function to elements on a page that have class="bar". This is the issue! I don't want to apply it to all .bar's on a page, but only to a specific group that is associated with particular .audiojs instance (the one that is being clicked and is playing).
I thought of the following solution. Each .audiojs instance is inside a div tag that has id like "post-1", "post-2" etc.. where numerical value is post id from database. I can add this numerical id to bar, so it would be like bar-1, bar-2 etc... However after this I'm having issues.
For javascript to work I need to retrieve numerical value from "post-[id]" associated with audiojs instance that is being clicked and than store it somehow, so I can use it like this afterwards
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar-[value retrieved from post-...]").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar-[value retrieved from post...]").stop();
}
Could someone explain to me how it can be achieved?
Honestly, the easiest way would be to stick it in a custom data-* attribute on the <div id="post-X"> element, like so:
<div id="post-1" data-bar="bar-1">...</div>
Then, you said your .audiojs element is inside that <div>, so just go from this inside the event handler to that <div> element (using .closest()) and get the value of it:
var barId = $(this).closest('[id^="post-"]').attr('data-bar');
Then when you need to use it:
$("." + barId).each(function(i) {
fluctuate($(this));
});
Instead of embedding the value in a class or ID, use a data-* attribute:
<div class="audiojs" data-fluctuate-target="bar-1">
<button type="button" class="play-pause">
<!-- ... -->
</button>
</div>
<div class="bar-1">
<!-- ... -->
</div>
In your click event handler, use the following to fluctuate or stop the correct elements:
var fluctuateClass = $(this).closest('.audiojs').attr('data-fluctuate-target');
$('.' + fluctuateClass).each(function () {
if (bPlay == 1) {
fluctuate($(this));
} else {
$(this).stop();
}
});

How can the IDs of visible jqGrid grids be determined?

I have a page with severl jqGrids, but only one is visible at a time. I want a simple function to return which one is visible at any time. Is there some function like this, which would show which divs are visible:
$('div').each(function(){
if($(this).is(':visible')){
alert($(this).attr('id'));
}
});
Is there something like this that can parse through all jqGrids on a page?
Thanks!
You need probably something like the following
$("table.ui-jqgrid-btable:visible").attr('id');
If no grid are on the table you will get undefined value. If more as one grid is visible you will get the id of the first one.
To have array of ids of all visible grids you can use the following code
var ids = $.map($("table.ui-jqgrid-btable:visible"), function(value) {
return value.id;
});
// now we have all ids in the array
alert(ids.join()); // display all as comma-separated
You can make the above code more safe with the test for grid expandos:
var ids = $.map($("table.ui-jqgrid-btable:visible"), function(value) {
if (value.grid) { return value.id; }
});
// now we have all ids in the array
alert(ids.join()); // display all as comma-separated
As far as I have seen, All grids are wrapped with a div class ui-jqgrid. So try something like below,
$('div.ui-jqgrid:visible').each(function () {
alert(this.id); //above would return the gview_<table_id> or gbox_<table_id> or
//something_<table_id>
alert($(this).find('.ui-jqgrid-btable').attr('id')); //should return table_id
});

Categories

Resources