I'm trying to find the total amount group by data attribute name from a list using jQuery. Similar to grouping categories and find the sum.
For example, I would like to create something like this:
group1 = 3
group2 = 5
group3 = 3
from this list:
<span class="data-center" data-category="group1" data-amount="1"></span>
<span class="data-center" data-category="group2" data-amount="1"></span>
<span class="data-center" data-category="group2" data-amount="2"></span>
<span class="data-center" data-category="group1" data-amount="2"></span>
<span class="data-center" data-category="group2" data-amount="2"></span>
<span class="data-center" data-category="group3" data-amount="3"></span>
I wonder if there is some jQuery function help to achieve it, something like groupByName()?
Using pure JavaScript:
Example Here
function getCategoryTotal(cat) {
var total = 0,
elements = document.querySelectorAll('[data-category="' + cat + '"]');
Array.prototype.forEach.call(elements, function (el, i) {
total += parseInt(el.dataset.amount, 10);
});
return total;
}
console.log(getCategoryTotal('group1')); // 3
console.log(getCategoryTotal('group2')); // 5
console.log(getCategoryTotal('group3')); // 3
I guess you asked about a jQuery way of doing so, which I did:
$.fn.amountByData = function(dataAttr, amountDataAttr) {
if (typeof amountDataAttr == "undefined")
amountDataAttr = "amount";
var dataAmountArr = new Array();
$(this).each(function() {
var dataAttrVal = $(this).data(dataAttr);
if (typeof dataAmountArr[dataAttrVal] == "undefined")
dataAmountArr[dataAttrVal] = parseInt($(this).data(amountDataAttr));
else
dataAmountArr[dataAttrVal] += parseInt($(this).data(amountDataAttr));
});
return dataAmountArr;
};
Here's how I would achieve it jQuery way ! This gives a LOT of flexibility, because you can choose by which data attribute you want to calculate the amount based on, and you can also choose to precise a different amount data attribute if it is not named amount.
PS: I know an answer has already been chosen, but contrary to #Josh Crozier, I understood you wanted a jQuery method to achieve your goal.
Cheers,
Related
I am trying to make every article views having comma separated every 3 digit number. I have found the code for that.
But I have problem to find specific blogger post ID to use for the code to work fine.
Here's the whole code that I am trying to work on.
<--Viewable area /-->
<span class='entry-time'><b:if cond='data:allBylineItems.author and data:allBylineItems.timestamp.label'><span class='on'><data:allBylineItems.timestamp.label/></span></b:if><time class='published' expr:datetime='data:post.date.iso8601'><data:post.date/></time></span><span class='postviews1' style='margin-left:5px; display:display;'><a expr:name='data:post.id'/> <i class='far fa-eye'/> <span id='bacani'><span id='postviews'/></span> Views</span>
<--comma separated every 3 digit /-->
<script>var angka = document.getElementById('bacani').textContent;var reverse = angka.toString().split('').reverse().join(''),ribuan = reverse.match(/\d{1,3}/g);ribuan = ribuan.join(',').split('').reverse().join('');document.getElementById('bacani').innerHTML= ribuan;</script>
<--code for views count /-->
<script src='https://cdn.firebase.com/v0/firebase.js' type='text/javascript'/> <script> $.each($("a[name]"), function(i, e) { var elem = $(e).parent().find("#postviews"); var blogStats = new Firebase("https://sh-v-3da10-default-rtdb.firebaseio.com/" + $(e).attr("name")); blogStats.once("value", function(snapshot) { var data = snapshot.val(); var isnew = false; if(data == null) { data= {}; data.value = 0; data.url = window.location.href; data.id = $(e).attr("name"); isnew = true; } elem.text(data.value); data.value++; if(window.location.pathname!="/") { if(isnew) blogStats.set(data); else blogStats.child("value").set(data.value); } }); });</script>
I want to change:
<span id='bacani'><span id='postviews'/></span>
and
document.getElementById('bacani').textContent;
to have a specific value id which is post id from blogger. The only thing that i found from internet is
<data:post.id>
Is there any other way that i can make it work other than what I am thinking right now? I think I need specific new id to make it work for every article to have comma separated every 3 digit.
I try to use the code but it only work for one time only. I believe to make it work as a whole I need to use different code to read specific unique id base on data:.post.id from blogger post id itself. But i do not sure how to make it work. I am expecting when I know how to use different method which is making new code that find unique id for different article it would work fine.
You can just replace elem.text(data.value) to
// original count
var count = data.value;
// count separated by comma
var separatedCount = count.toString()
.split('').reverse().join('')
.match(/\d{1,3}/g).join(',')
.split('').reverse().join('');
elem.text(separatedCount);
The full code would be
<!-- code for views count -->
<script src='https://cdn.firebase.com/v0/firebase.js' type='text/javascript'/>
<script>
/*<![CDATA[*/
$.each($("a[name]"), function (i, e) {
var elem = $(e).parent().find("#postviews");
var blogStats = new Firebase("https://sh-v-3da10-default-rtdb.firebaseio.com/" + $(e).attr("name"));
blogStats.once("value", function (snapshot) {
var data = snapshot.val();
var isnew = false;
if (data == null) {
data = {};
data.value = 0;
data.url = window.location.href;
data.id = $(e).attr("name");
isnew = true;
}
// original count
var count = data.value;
// count separated by comma
var separatedCount = count.toString()
.split('').reverse().join('')
.match(/\d{1,3}/g).join(',')
.split('').reverse().join('');
elem.text(separatedCount);
data.value++;
if (window.location.pathname !== "/") {
if (isnew) blogStats.set(data); else blogStats.child("value").set(data.value);
}
});
});
/*]]>*/
</script>
Hi I have to find a missing number in an xml file. but I feel difficulty to find. Pls suggest some ideas.
Example
A file contains an <a> tag which include id i.e page-1,2... I need to find the missing numbers using jquery.
a.xml
<p>have a great <a id="page-1"/>day. How are you.</p>
<p><a id="page-2"/>Have a nice day.</p>
<p>How <a id="page-5"/>are you</p>
<p>Life is so exciting<a id="page-6"/></p>
My code
<script>
$(document).ready(function() {
$("#find").click(function(){
Fname = $("#myFile").val();
lpage = $("#lpage").val();
$.get(Fname, function(data){
var lines = data.split("\n");
if (lines.match(id="page-)) { //how to use regular exoreessi0n
alert("hi");
}
});
});
});
</script>
I'll take some assumptions regarding your input. Please add validations as necessary:
var lines = ['<p>have a great <a id="page-1"/>day. How are you.</p>',
'<p><a id="page-2"/>Have a nice day.</p>',
'<p>How <a id="page-5"/>are you</p>',
'<p>Life is so exciting<a id="page-6"/></p>'];
var sequences = [];
lines.forEach(function(line) {
// Not efficient but simple
// Let jQuery parse this string to object, so we won't need regexp
var obj = $(line);
// Assuming there's always A and ID attribute
var id = obj.find("a").attr("id").split("-");
// Assuming sequence is always last
sequences.push(parseInt(id[id.length - 1]));
});
sequences.sort();
// Again, inefficient, but will do the job
var last = sequences[sequences.length - 1];
for (var i = last; i >= 0; i--) {
if (sequences.indexOf(i) < 0) {
console.log(i + " is missing");
}
}
I know there are many similar questions posted, and have tried a couple solutions, but would really appreciate some guidance with my specific issue.
I would like to remove the following HTML markup from my string for each item in my array:
<SPAN CLASS="KEYWORDSEARCHTERM"> </SPAN>
I have an array of json objects (printArray) with a printArray.header that might contain the HTML markup.
The header text is not always the same.
Below are 2 examples of what the printArray.header might look like:
<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016
RECORD WINE PRICES AT <SPAN CLASS="KEYWORDSEARCHTERM">NEDBANK</SPAN> AUCTION
I would like the strip the HTML markup, leaving me with the following results:
MOST EMPOWERED COMPANIES 2016
RECORD WINE PRICES AT NEDBANK AUCTION
Here is my function:
var newHeaderString;
var printArrayWithExtract;
var summaryText;
this.setPrintItems = function(printArray) {
angular.forEach(printArray, function(printItem){
if (printItem.ArticleText === null) {
summaryText = '';
}
else {
summaryText = '... ' + printItem.ArticleText.substring(50, 210) + '...';
}
// Code to replace the HTML markup in printItem.header
// and return newHeaderString
printArrayWithExtract.push(
{
ArticleText: printItem.ArticleText,
Summary: summaryText,
Circulation: printItem.Circulation,
Headline: newHeaderString,
}
);
});
return printArrayWithExtract;
};
Try this function. It will remove all markup tags...
function strip(html)
{
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
Call this function sending the html as a string. For example,
var str = '<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016';
var expectedText = strip(str);
Here you find your expected text.
It can be done using regular expressions, see below:
var s1 = '<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016';
var s2 = 'RECORD WINE PRICES AT <SPAN CLASS="KEYWORDSEARCHTERM">NEDBANK</SPAN> AUCTION';
function removeSpanInText(s) {
return s.replace(/<\/?SPAN[^>]*>/gi, "");
}
$("#x1").text(removeSpanInText(s1));
$("#x2").text(removeSpanInText(s2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
1 ->
<span id="x1"></span>
<br/>2 ->
<span id="x2"></span>
For more info, see e.g. Javascript Regex Replace HTML Tags.
And jQuery is not needed, just used here to show the output.
I used this little replace function:
if (printItem.Headline === null) {
headlineText = '';
}
else {
var str = printItem.Headline;
var rem1 = str.replace('<SPAN CLASS="KEYWORDSEARCHTERM">', '');
var rem2 = rem1.replace('</SPAN>', '');
var newHeaderString = rem2;
}
I have the following:
<span class="label-info">3</span>
I have the following jquery
var replaceit = $(this).closest(':has(.label-info)').find('.label-info').text();
The value of the variable is always a single whole number but will not always be 3:
ie: 1, 2, 3, 4, 5.
I have tried this numerous ways and cannot get the value to change. My latest attempt was:
return $(this).closest(':has(.label-info)').html().replace(replaceit, (replaceit - 1));
My end result, is to subtract 1 from whatever the current value of "lable-info" is, and switch it with this new result. So a new span based on the value of 3 would become.
<span class="label-info">2</span>
How do I achieve this?
Updated Code for more clarity
html:
<div>
<span class="lable-info">3</span>
</div>
<div>
<a class="accept_friend">accept</a>
</div>
javascript:
$(document).on("click", "a.accept_friend", function() {
var checkValue = $(this).closest(':has(.name)').find('.name').text();
var removeit = $(this).closest(':has(.item)').find('.item').fadeOut();
var replaceit = $(this).closest(':has(.label-info)').find('.label-info').text();
$.ajax({
url: '/includes/accept_friend.php',
type: 'post',
data: {checkValue},
success:function(data){
return removeit;
$("a.remove_pending").text(function () {
return ('.label-info').html().replace(replacei, replaceit);
});
}
Notes:
I am not using id. I am using class. There are multiple classes with the same name. So I have to call by closest.
Getting a value from a span, subtracting it by 1 and updating the span(using jQuery):
HTML
<span class="label-info">3</span>
jQuery
var n = $(".label-info").text(),
n2 = n - 1;
$(".label-info").text(n2);
Hope it helps a bit
Please try below code
var currentVal = $(this).closest(':has(.label-info)').html();
var newValue = parseInt(currentVal - 1);
return newValue;
Hope this helps you
var replaceit = $(this).closest(':has(.label-info)').text();
$(this).closest(':has(.label-info)').text(replaceit-1);
Example fiddle https://jsfiddle.net/nzdtnoas/
You can use .text( function ) to changing text of element to another string.
$(".label-info").text(function(i, text){
return text - 1;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="label-info">3</span>
I have a list with about 10 000 customers on a web page and need to be able to search within this list for matching input. It works with some delay and I'm looking for the ways how to improve performance. Here is simplified example of HTML and JavaScript I use:
<input id="filter" type="text" />
<input id="search" type="button" value="Search" />
<div id="customers">
<div class='customer-wrapper'>
<div class='customer-info'>
...
</div>
</div>
...
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#search").on("click", function() {
var filter = $("#filter").val().trim().toLowerCase();
FilterCustomers(filter);
});
});
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-wrapper").show();
return;
}
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).parent().show();
} else {
$(this).parent().hide();
}
});
}
</script>
The problem is that when I click on Search button, there is a quite long delay until I get list with matched results. Are there some better ways to filter list?
1) DOM manipulation is usually slow, especially when you're appending new elements. Put all your html into a variable and append it, that results in one DOM operation and is much faster than do it for each element
function LoadCustomers() {
var count = 10000;
var customerHtml = "";
for (var i = 0; i < count; i++) {
var name = GetRandomName() + " " + GetRandomName();
customerHtml += "<div class='customer-info'>" + name + "</div>";
}
$("#customers").append(customerHtml);
}
2) jQuery.each() is slow, use for loop instead
function FilterCustomers(filter) {
var customers = $('.customer-info').get();
var length = customers.length;
var customer = null;
var i = 0;
var applyFilter = false;
if (filter.length > 0) {
applyFilter = true;
}
for (i; i < length; i++) {
customer = customers[i];
if (applyFilter && customer.innerHTML.toLowerCase().indexOf(filter) < 0) {
$(customer).addClass('hidden');
} else {
$(customer).removeClass('hidden');
}
}
}
Example: http://jsfiddle.net/29ubpjgk/
Thanks to all your answers and comments, I've come at least to solution with satisfied results of performance. I've cleaned up redundant wrappers and made grouped showing/hiding of elements in a list instead of doing separately for each element. Here is how filtering looks now:
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-info").show();
} else {
$(".customer-info").hide();
$(".customer-info").removeClass("visible");
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).addClass("visible");
}
});
$(".customer-info.visible").show();
}
}
And an test example http://jsfiddle.net/vtds899r/
The problem is that you are iterating the records, and having 10000 it can be very slow, so my suggestion is to change slightly the structure, so you won't have to iterate:
Define all the css features of the list on customer-wrapper
class and make it the parent div of all the list elements.
When your ajax request add an element, create a variable containing the name replacing spaces for underscores, let's call it underscore_name.
Add the name to the list as:
var customerHtml = "<div id='"+underscore_name+'>" + name + "</div>";
Each element of the list will have an unique id that will be "almost" the same as the name, and all the elements of the list will be on the same level under customer-wrapper class.
For the search you can take the user input replace spaces for underscores and put in in a variable, for example searchable_id, and using Jquery:
$('#'+searchable_id).siblings().hide();
siblings will hide the other elements on the same level as searchable_id.
The only problem that it could have is if there is a case of two or more repeated names, because it will try to create two or more divs with the same id.
You can check a simple implementation on http://jsfiddle.net/mqpsppxm/