I have this short menu:
<ul>
<li class="voucher">
Holidays (<span data="0" class="counter" id="119">0</span>)
<ul id="menu2">
<li class="voucher">
Travel deals (<span data="119" class="counter" id="123">1</span>)
</li>
<li class="voucher">
Hotel offers (<span data="119" class="counter" id="120">2</span>)
</li>
<li class="voucher">
Villas offers(<span data="119" class="counter" id="121">1</span>)
</li>
</ul>
</li>
</ul>
and this js which has to collect all subcategories values in () and add that sum as (value ) for the main category Holidays:
var sum = 0;
$('.counter').each(function () {
var counter = $(this).html();
var id = $(this).attr('id');
if (counter == 0) {
// here I want to find and sum all values in ( ) for span that has attr data equal to 119 which is the id of the main category Holidays
sum += parseInt($('span').find("[data='" + id + "']").html(), 10) || 0;
alert(sum);
//here I want the sum of all subcategories -Holidays ( 4 )
$(this).html(sum);
}
});
but it doesn't work.. No errors, just doesnt sum correct and returns always 0
Please help with this if you are OK with JS,
Here is jsfiddle:
http://jsfiddle.net/europe77/w1uL5a8o/1/
You are trying to find by data attribute in span object.You need to use:
parseInt($("span[data='" + id + "']").html());
Also there were other issue that needs to be addressed. Here is the full working code:
var sum = 0;
$('.counter').each(function () {
var counter = $(this).html();
var id = $(this).attr('id');
sum += parseInt($(this).html(), 10) || 0;
});
alert(sum);
$('.counter:eq(0)').html(sum);
Working Demo
Related
I am traversing this DOM:
<ul>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
</ul>
With the following code:
var myNodelist = Array.from(document.querySelectorAll(".category"));
var obj = {};
for(var i = 0; i < myNodelist.length; i++){
//convert array to object with unique elements and number of times
each element is repeated
var x = myNodelist[i].innerHTML;
//console.log(x);
if(!obj[x]){
obj[x] = 1;
} else {
obj[x]++;
}
}
var index = 0;
var max = 0;
for(var obIndex in obj) {
// Traverse the object to get the element
if(obj[obIndex] > max) {
max = obj[obIndex];
index = obIndex.replace(" ", "");
}
}
console.log(index + " is max time repeated: " + max + " times." );
var v = document.getElementsByClassName("category");
for(var m = 0; m < myNodelist.length; m++) {
var subText = myNodelist[m].childNodes;
var len = subText.length;
for (var jj = 0; jj < len; jj++) {
if(subText[jj].nodeType === Node.TEXT_NODE) {
console.log(subText[jj].nodeValue);
subText[jj].nodeValue =
subText[jj].nodeValue.replace(/Mock/,"123");
}
}
}
Currently i am getting the index successfully with the value from the exertion of the highest text appearance in the DOM. Then i am looping through the Nodelist again, evaluating if its a,
Node.TEXT_NODE
https://developer.mozilla.org/de/docs/Web/API/Node/nodeType
Now i only know how to replace the
textNode.value
with another value.
What i am really trying to achieve is to get the parentNode of the textNode and add a class to it. If the condition for index (highest appearance) is met. What i found is
Adding a class to a given element. and
ParentNode MDN
The problem is i can't really figure out how to
access the parentNode out of the second for loop and add a class to
the parentNode, so all parents (span tags) that only have the index (text
value) get a certain class.
Thanks for help !
You can access to li using parentNode on the myNodelist[m]
var myNodelist = Array.from(document.querySelectorAll(".category"));
var obj = {};
for(var i = 0; i < myNodelist.length; i++){
//convert array to object with unique elements and number of times
//each element is repeated
var x = myNodelist[i].innerHTML;
//console.log(x);
if(!obj[x]){
obj[x] = 1;
} else {
obj[x]++;
}
}
var index = 0;
var max = 0;
for(var obIndex in obj) {
// Traverse the object to get the element
if(obj[obIndex] > max) {
max = obj[obIndex];
index = obIndex.replace(" ", "");
}
}
console.log(index + " is max time repeated: " + max + " times." );
var v = document.getElementsByClassName("category");
for(var m = 0; m < myNodelist.length; m++) {
var subText = myNodelist[m].childNodes;
var len = subText.length;
for (var jj = 0; jj < len; jj++) {
if(subText[jj].nodeType === Node.TEXT_NODE) {
if (obj[subText[jj].nodeValue] == max) {
myNodelist[m].parentNode.className += " red";
}
console.log(subText[jj].nodeValue);
subText[jj].nodeValue =
subText[jj].nodeValue.replace(/Mock/,"123");
}
}
}
.red {
color: red;
}
<ul>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
</ul>
What i am really trying to achieve is to get the parentNode of the
textNode and add a class to it.
You don't need to find it, you already have myNodelist[m] whose childNodes you were iterating.
If the condition for index (highest appearance) is met.
You have the node-Value with you here subText[jj].nodeValue, and you already have the obj having the number of appearances by the nodeValue
So, simply add this logic
if ( obj[ subText[jj].nodeValue ] == max )
{
//logic to add the class should be here
myNodelist[m].classList.add("otherclass");
}
subText[jj].nodeValue = subText[jj].nodeValue.replace(/Mock/,"123");
To get the parent of a text node just use myTextNode.parentNode and then use classList to add the class to the parent. This could also be achieved using the treewalker api.
function markMostOccurring(parentSelector, markFn) {
var parent = document.querySelector(parentSelector) || document.body;
var walker = document.createTreeWalker(parent, NodeFilter.SHOW_TEXT, {
acceptNode: node => !!node.nodeValue.trim()
});
var occurenceMap = {};
while(walker.nextNode()) {
var key = walker.currentNode.nodeValue.trim();
var nodes = occurenceMap[key] = occurenceMap[key] || [];
nodes.push(walker.currentNode);
}
var nodes = Object.keys(occurenceMap)
.sort((a, b) => occurenceMap[b].length - occurenceMap[a].length)
.map(key => occurenceMap[key])[0]
.forEach(node => markFn.call(node));
}
markMostOccurring('.container', function() {
this.parentNode.classList.add('mark');
this.nodeValue = this.nodeValue.replace('most', 'cat');
});
.mark {
color: red;
}
<ul class="container">
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
some text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
<li class="item">
<span class="category">
most occurring text
</span>
</li>
</ul>
I'm wanting to sort this UL numerically and alphabetically, using each items data-char value.
Note: I'm only wanting to sort the parent UL, not the child UL elements.
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
I'm able to accomplish this with jQuery by doing:
function sortCharLi(a, b) {
var va = a.dataset.char.toString().charCodeAt(0),
vb = b.dataset.char.toString().charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
$('ul > li').sort(sortCharLi).appendTo('ul');
But I'm needing to remove the jQuery dependency so that's not an option any more.
Any ideas how I may do this without jQuery?
JSBIN
You can get the ul using getElemetsByTagName and children li can be get from the element object using children property.
function order(ul) {
// get html children elements of li
// in case of ul children will be li
// ` Array.from` will hell helps to convert them into array
var elements = Array.from(ul.children);
// sort them with the same code
elements.sort(function(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0),
charCA = 'a'.charCodeAt(0);
// add weight if it's a number
if (va < charCA) va += 100;
if (vb < charCA) vb += 100;
// just get the difference and return to sort them
return va - vb;
});
// append back to update the order
// forEach can be used to update since it's in array format
elements.forEach(function(ele) {
ul.appendChild(ele)
});
}
// get ul tag from dom and pass as parameter
// although you can use id selector or querySelector, etc
// it depends up on your need, here you just need to pass the dom reference of `ul` to be sorted
order(document.getElementsByTagName('ul')[0]);
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
UPDATE :
If you want to use them in chain as in jQuery, then extend the prototype
NodeList.prototype.sortElements = function(custom) {
// if custom sort function passed then sort based on that
if (typeof custom === 'function')
return [].slice.call(this).sort(custom);
// otherwise apply sort method directly
return [].slice.call(this).sort();
// you can also use Array.from(this), which only works in latest browsers
}
Array.prototype.updateOrder = function() {
// iterate over array element
this.forEach(function(ele) {
// append to the parent element
ele.parentNode.appendChild(ele);
})
}
// sort them with the same code
function sortFn(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0),
charCA = 'a'.charCodeAt(0);
// add weight if it's a number
if (va < charCA) va += 100;
if (vb < charCA) vb += 100;
// just get the difference and return to sort them
return va - vb;
}
// get li elements which have `data-char` attribute
document.querySelectorAll('ul li[data-char]')
.sortElements(sortFn) // call sortElements methods we defined with custom sort function
.updateOrder(); // call updateOrder to update the order of element
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
This function preserves your original sorter method. The function expects the ul element to be passed:
function sortThem(ul) {
var nodes = Array.prototype.slice.call(ul.childNodes).filter(function(el) {
// Could use QSA with scope depending on browser support here
return el.tagName === 'LI';
});
nodes.sort(function(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
});
nodes.forEach(function(node) {
ul.appendChild(node);
});
}
You may use querySelectorAll for $('ul > li'). Pay attention, the right selector should be $('ul > li[data-char]') because you are inrested only in li tags having the data-char as attribute.
To convert the NodeList returned from querySelectorAll to array you can use Array.from.
To substitute the appendTo you may use forEach.
So the code could be:
function sortCharLi(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
window.onload = function() {
// $('ul > li').sort(sortCharLi).appendTo('ul');
Array.from(document.querySelectorAll('ul > li[data-char]')).sort(sortCharLi).forEach(function(element, index) {
element.parentNode.appendChild(element);
});
}
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
UPDATE
A shorter way to convert:
$('ul > li[data-char]').sort(sortCharLi).appendTo('ul');
to pure javaScript can be:
document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith();
In order to achieve this result the following methods have to be added:
NodeList.prototype.sort = function(callBack) {
if (typeof callBack === 'function') {
return [].slice.call(this).sort(callBack);
} else {
return [].slice.call(this).sort();
}
}
Array.prototype.replaceWith = function() {
this.forEach(function(element, index) {
element.parentNode.appendChild(element);
});
return this;
}
In this way there exist the possibility to chain methods like in jQuery:
function sortCharLi(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
NodeList.prototype.sort = function(callBack) {
if (typeof callBack === 'function') {
return [].slice.call(this).sort(callBack);
} else {
return [].slice.call(this).sort();
}
}
Array.prototype.replaceWith = function() {
this.forEach(function(element, index) {
element.parentNode.appendChild(element);
});
return this;
}
window.onload = function () {
document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith();
}
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
This is the best answer I can snap off from work, but it might need to be tailored to your html structure.
FUNCTION TO SORT UL WITHOUT JQUERY:
function sortUnorderedList(ul, sortDescending) {
if(typeof ul == "string")
ul = document.getElementById(ul);
// Idiot-proof, remove if you want
if(!ul) {
alert("The UL object is null!");
return;
}
// Get the list items and setup an array for sorting
var lis = ul.getElementsByTagName("LI");
var vals = [];
// Populate the array
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
// Sort it
vals.sort();
// Sometimes you gotta DESC
if(sortDescending)
vals.reverse();
// Change the list on the page
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
USAGE:
sortUnorderedList("ID_OF_LIST");
My HTML looks like:
<ul>
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
</ul>
What method should I use to get the maximum value from the data-target attributes? Do vanilla JavaScript or jQuery have some native functions for this or I should just use for loop to iterate through all the items and get the maximum value, shouldn't I?
One way (without bothering with an array);
var max = 0;
$("li[data-target]").each(function() {
max = Math.max(max, parseInt($(this).data("target"), 10));
});
alert(max);
use Math.max.apply() method to get max value from a numeric array.
var arr = $('li[data-target]').map(function(){
return $(this).data('target')
});
console.log(Math.max.apply(Math,arr));
Fiddle Demo
Try this: use .map() along with Math function:
var targets = $("li").map(function() {
return $(this).data("target");
}).get();
var max = Math.max.apply(Math,targets);
Demo
This should work...
var array = [];
$('li').each(function() {
array.push($(this).data('target'));
});
var maxNumber = Math.max.apply(Math, array);
alert(maxNumber);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
var maxVal = 0;
$('[data-target]').each(
function(){
if($(this).attr('data-target') > maxVal){
maxVal = $(this).attr('data-target');
}
});
fiddle
Try with this:
var maxValue = 0;
$("li").each(function(index,val){
var value = $(this).attr('data-target');
if(value > maxValue) maxValue= value;
});
Yes you can get max value using for each loop of jquery. For each value of li get its attribute data-target. e.g
var maxVal=0;
$(this).find('li').each(function(){
// cache jquery var
var current = $(this);
var val=parseInt(current.attr( "data-target" ));
if(val > maxVal){
maxVal=val;
}
});
console.log(maxVal);//Its the max value
Turak Vladyslav
below code will work you can check it once
var Lis = $('#test').find('li');
var dataArray = []
for(var i=0;i<Lis.length;i++){
dataArray.push($(Lis[i]).attr('data-target'))
}
var maxDatatTarget = Math.max.apply(null, dataArray)
alert("max data target value"+maxDatatTarget)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="test">
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
</ul>
Try this if it works for you :
function calculateMaxTarget(){
var attr[] = $('li').attr('data-target');
var max = 0;
for (var i=0; i < attr.length; i++) {
if(attr[i]>max){
max = attr[i];
}
};
return max;
}
I'm trying to create a piano on my page using two image files: white-key and black-key.
I've created them, but the black keys on the piano alternate in groups of 2 and 3 and I'd hide the black key images for indices [1, 4(1+3), 8(4+4), 11(8+3), 15(11+4), .., 54]. I'm unsure of how to go about doing this though.
This is how I created them.
HTML:
<div ng-controller="DrawCtrl as draw">
<ul class="white-keys">
<li ng-repeat="t in draw.range(56) track by $index">
<img ng-src={{draw.white_key}} />
</li>
</ul>
<ul class="black-keys">
<li ng-repeat="t in draw.range(55) track by $index">
<img ng-src={{draw.black_key}} />
</li>
</ul>
</div>
JS:
angular.module('app')
.controller('DrawCtrl', function() {
var self = this;
self.piano_back = 'img/background.png';
self.white_key = 'img/midi_white_up.png';
self.black_key = 'img/midi_black_up.png';
self.range = function(num) {
return new Array(num);
};
});
EDIT: Got it working thanks to hansmaad's answer.
HTML:
<ul class="black-keys">
<li ng-repeat="key in draw.keys" ng-switch="key.black">
<img ng-switch-when="true" ng-src={{draw.black_key}} />
<img ng-switch-when="false" ng-src={{draw.black_key}} class="black-hidden" />
</li>
</ul>
JS:
self.keys = [];
var keyGroupOf3 = true;
self.keys.push({black: true}); // first key is shown
var i = 1;
while (i < 54) {
self.keys.push({black: false});
// alwasy followed by at least two
self.keys.push({black: true});
self.keys.push({black: true});
if (keyGroupOf3){
self.keys.push({black: true});
i += 4;
} else {
i += 3;
}
I think you should create your keyboard in the controller as array of keys. You can then use a single ng-repeat to draw all the keys. To draw the right img for a key you can use ng-switch or store the imgage url in the key.
A simple example without images but using ng-class:
http://plnkr.co/edit/kIvRqdkbHHNcUXKzSLZC?p=preview
<div ng-controller="DrawCtrl as draw">
<ul >
<li ng-repeat="key in draw.keys" ng-class="{ 'black' : key.black, 'white' : !key.black}">
</li>
</ul>
</div>
Controller:
function DrawCtrl() {
this.keys = []
for(var i = 0, e = 55; i < e; ++i) {
this.keys.push({
black : isBlackKey(i)
});
}
function isBlackKey(i) {
// your piano logic here
return i % 2 == 0;
}
}
Using ng-switch you could do:
<ul>
<li ng-repeat="key in draw.keys" ng-switch="key.black">
<span ng-switch-when="true">Black key</span>
<span ng-switch-when="false">White key</span>
</li>
</ul>
Edit: This could be a simple, stupid algorithm to fill the keys array:
this.keys = []
var lastWasBlack = true;
var d = 5;
var next = 5;
for(var i = 0, e = 55; i < e; ++i) {
var isBlack = !lastWasBlack;
if (i === next) {
isBlack =!isBlack;
d = d === 5 ? 7 : 5;
next += d;
}
this.keys.push({
black : isBlack
});
lastWasBlack = isBlack;
}
}
http://plnkr.co/edit/kIvRqdkbHHNcUXKzSLZC?p=preview
Have a look at the below plunker. I haven't added any css. But just to hide and show the images you can use this link.
http://plnkr.co/edit/pgFKHShXpeS4EQhoaFTI?p=preview
<ul class="white-keys">
<li ng-repeat="t in draw.range(20) track by $index">
<img ng-src='http://lorempixel.com/g/50/15/technics' ng-hide="($index == 1 || $index == 4 || $index == 8 || $index == 11)"/>
</li>
</ul>
I have used ng-hide to hide the images at specific position.
Is this you are looking for? If not let me know.
I want to calculate the total per "row-counts" of all "counts" inside, and then sort "row" based on the "row-totals". But the totals add up all numbers with class="count" instead of 'for each' only those within it's parent "row-counts".
<div id="container">
<div class="row">
<div class="row-counts">
<span class="count">12</span>
<span class="count">4</span>
<span class="count">5</span>
<span class="count">7</span>
</div>
<div class="row-totals">
</div>
</div>
<div class="row">
<div class="row-counts">
<span class="count">4</span>
<span class="count">66</span>
<span class="count">0</span>
<span class="count">12</span>
</div>
<div class="row-totals">
</div>
</div>
<div class="row">
<div class="row-counts">
<span class="count">7</span>
<span class="count">99</span>
<span class="count">42</span>
<span class="count">17</span>
</div>
<div class="row-totals">
</div>
</div>
</div>
<script>
// to calculate sum of all numbers in .row-counts
$('.row-counts').each(function(){
var sum = 0;
var select = $(this).find('.count');
select.each(function()
{
sum += parseFloat($(this).text());
});
$('.row-totals').html(sum);
});
// to sort on .row-totals
$(".row-totals").orderBy(function() {return +$(this).text();}).appendTo("#container");
jQuery.fn.orderBy = function(keySelector)
{
return this.sort(function(a,b)
{
a = keySelector.apply(a);
b = keySelector.apply(b);
if (a > b)
return 1;
if (a < b)
return -1;
return 0;
});
};
</script>
Sorting plugin is from this topic: Sorting divs by number inside div tag and jQuery
Here you go. Code commented with some pointers. Hope this helps.
http://jsfiddle.net/N5Sd2/
// to calculate sum of all numbers in .row-counts
$('.row').each(function(index,RowElement){ // For each row
var thisRowTotal = $(RowElement).find('.row-totals'); // set output div in variable
var thisRowCounts = $(RowElement).find('.row-counts'); // set row count parent div in variable
var sum = 0; // create sum var
thisRowCounts.each(function(i,RowCountParent){ // for each row count parent
var select = $(RowCountParent).find('.count'); // find counts
select.each(function(i,e){ // for each count found
sum = sum + parseInt($(e).html()); // convert into integer and add to sum
}); // when finished
thisRowTotal.html(sum); // output sum to output div
});
});
// to sort on .row-totals
jQuery.fn.orderBy = function(keySelector) // MAKE SURE YOU INIT THE PLUGIN...
{
return this.sort(function(a,b)
{
a = keySelector.apply(a);
b = keySelector.apply(b);
if (a > b)
return 1;
if (a < b)
return -1;
return 0;
});
};
// ....BEFORE YOU CALL IT IN YOUR CODE! This line moved UNDER the plugin.
$(".row-totals").orderBy(function() {return +$(this).text();}).appendTo("#container");
I didn't test it, but I think you need one more level in your iteration. This should do the trick:
$('.row').each(function() {
var total = $(this).find('.row-totals');
var sum = 0;
$(this).find('.row-counts').each(function(){
var select = $(this).find('.count');
select.each(function() {
sum += parseFloat($(this).text());
});
total.html(sum);
});
});
And then use your sort plugin as usual.