Find first instance of specific value and add ID, repeated - javascript

Given a series of div's with known values is it possible to create a filter or array that finds the first instance of the values and adds an ID over multiple items? Here's the basic structure:
<div class="boxes">
<div class="box"><time>2017</time></div>
<div class="box"><time>2016</time></div>
<div class="box"><time>2015</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2013</time></div>
</div>
And here's the snippet I'm using to find one of the values:
var elems = $('.box').filter(function(){
return this.textContent.trim() === "2014"
}).first().attr('id', 'one');
I'm not sure the best way to go about looking for additional instances?
For example, it feels like there's a better way than simply repeating the argument. The novice in me admittedly does not know what this type of function would be called.
var elems = $('.box').filter(function(){
return this.textContent.trim() === "2014"
}).first().attr('id', 'one');
var elems = $('.box').filter(function(){
return this.textContent.trim() === "2017"
}).first().attr('id', 'one');
It would be a bonus to not have to add the specific value, i.e. 2017 (<time id="one">2017</time>), 2016 (<time id="two">2016</time>) but I'm not even sure if that's realistic.
Working Fiddle: https://jsfiddle.net/heykenneth/gn4gmvt0/1/.

You can do this by wrapping up parameters of the code you've already written:
markFirstYear("2014", "one");
markFirstYear("2015", "two");
markFirstYear("2016", "three");
markFirstYear("2017", "four");
// ... etc
function markFirstYear(year, id) {
var elems = $('.box').filter(function(){
return this.textContent.trim() === year
}).first().attr('id', id);
}
#one {color:red;}
#two {color:blue;}
#three {color:green;}
#four {color:purple;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="boxes">
<div class="box"><time>2017</time></div>
<div class="box"><time>2016</time></div>
<div class="box"><time>2015</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2013</time></div>
</div>

First create array of all values you have, then just get unique values from that array and finally iterate through unique array.
var myArr = new Array();
$('.box time').each(function(){
myArr.push($(this).text());
});
var unique = myArr.filter(function(item, index, array) {
return index == myArr.indexOf(item);
});
for (var i = 0; i <= unique.length; i++) {
var elems = $('.box').filter(function() {
return this.textContent.trim() === unique[i];
}).first().attr('class', 'one');
}
.one {color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="boxes">
<div class="box"><time>2017</time></div>
<div class="box"><time>2016</time></div>
<div class="box"><time>2015</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2014</time></div>
<div class="box"><time>2013</time></div>
</div>

Related

How can I sort divs with javascript

I would like to sort a few divs in ascending order based on their data-id. How can I do that?
<div class="container" data-id="1000">
<div id="H1"></div>
<div id="sub">sub 1</div>
<div id="sub">sub 2</div>
</div>
<div class="container" data-id="3000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>
<div class="container" data-id="2000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>
I've found the solution to my problem a while ago:
function sortOut() {
// get the classname chapcontainer
var classname = document.getElementsByClassName('container');
// create a variable and put the classes it into an array.
var divs = [];
for (var i = 0; i < classname.length; ++i) {
divs.push(classname[i]);
}
// Sort the divs based on data-id.
divs.sort(function(a, b) {
return +a.getAttribute("data-id") - +b.getAttribute("data-id");
});
};
divs.sort does the trick. More info about this function can be found here:
https://www.w3schools.com/jsref/jsref_sort.asp

How to detect number of elements has text start with special word using jquery?

I have a tag like below:
<section id="sec">
<div id="item1">item1</div>
<div id="item2">item2</div>
<div id="item3">item3</div>
<div id="abcitem1">abcitem1</div>
</section>
I want to check how many div tags contextText start with item. May I know is there any easier way that writes for condition and count them one by one(like Jquery)?
Use .filter() to filtering selected elements and use regex in .match() to check existence of item in element text.
var count = $("#sec div").filter(function(){
return $(this).text().match(/^item/);
}).length;
console.log(count);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="sec">
<div id="item1">item1</div>
<div id="item2">item2</div>
<div id="item3">item3</div>
<div id="abcitem1">abcitem1</div>
</section>
var res=0;
$( "#sec div" ).each(function( index ) {
var str= $(this).text() ;
if(str.startsWith("item")==true){
res++;
}
});
console.log(res); //returns 3
You could use reduce function to get the occurrence of elements which start with 'item'.
This is a native javascript solution, which uses startsWith, so you do not have to mess around with regular expressions.
var childDivs = document.getElementById('sec')
.getElementsByTagName('div');
var counter = Array.from(childDivs)
.reduce((accumulator, currentValue) => {
if (currentValue.innerHTML.startsWith('item')) {
return accumulator = accumulator + 1;
}
return accumulator;
}, 0);
console.log( counter );
<section id="sec">
<div id="item1">item1</div>
<div id="item2">item2</div>
<div id="item3">item3</div>
<div id="abcitem1">abcitem1</div>
</section>
Without any jQuery or regex
var nodes = document.querySelectorAll('#sec div')
var count = 0
nodes.forEach(node => count += node.innerText.startsWith('item'))
console.log(count)
<section id="sec">
<div id="item1">item1</div>
<div id="item2">item2</div>
<div id="item3">item3</div>
<div id="abcitem1">abcitem1</div>
</section>
it's possible to add booleans to a number, true means 1 and false means 0
Here is a pure JS way to count it.
function checkItemsCount(section) {
if (!section) return 0;
const sec = document.querySelector(section);
const items = sec.querySelectorAll('div');
let count = 0;
for (let i = 0; i < items.length; i++) {
if (/^item/.test(items[i].innerText)) count++;
}
return count;
}
console.log(checkItemsCount('#sec'));
<section id="sec">
<div id="item1">item1</div>
<div id="item2">item2</div>
<div id="item3">item3</div>
<div id="abcitem1">abcitem1</div>
</section>

How to loop through JavaScript object in HTML?

I want to loop through a JavaScript object and repeat an html script as many times as the object length.
Here, I have the following in a script tag
<script>
var obj;
ipcRenderer.on('requests-results', (event, hosSchema) => {
obj = hosSchema
})
</script>
obj is an array retrieved from Mongo database as the picture below shows:
and I have the following inside <body> tag:
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">.1.</span>
<p>.2.</p>
</div>
<div class="card-action">
.3.
.4.
</div>
</div>
</div>
</div>
How can I loop through obj to repeat the code between <div> tag as many times as obj.length?
I would suggest you to use Handlebars as #Amit mentioned.
first move out the code inside <div id="page-inner"> as below:
<div id="page-inner">
</div>
<script id= "requests-template" type="text/x-handlebars-template">
<div class="row">
{{#each requests}}
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">{{this.fieldName}}</span>
<p>{{this.fieldName}}</p>
</div>
<div class="card-action">
{{this.fieldName}}
{{this.fieldName}}
</div>
</div>
</div>
{{/each}}
</div>
</script>
Then inside another script page of type text/javascript you create the requests and assigned obj/hosSchema to it as below:
<script type="text/javascript">
var requestInfo = document.getElementById('requests-template').innerHTML;
var template = Handlebars.compile(requestInfo);
var requestData = template({
requests: obj
})
$('#page-inner').html(requestData);
</script>
NOTE: you need handlebars package installed (npm install handlebars --save)
Use templating script like Handlebars.js, Mustache.js or underscore.js.
Check below link for more description.
http://www.creativebloq.com/web-design/templating-engines-9134396
Try this:
var divlist = document.getElementsByTagName['div'];
var duplicate = null;
var rowIndex = -1;
var found = false;
for(var i = 0;i<obj.length;i++)
{
if(!found)
for(var p = 0;p<divlist.length;p++)
{
if(rowIndex != -1 && duplicate != null)
{
//set a Boolean to true and break
found = true;
break;
}
if(divlist[p].className == "col-md-4 col-sm-4")
{
//copy the element
duplicate = divlist[p];
}
else if(divlist[p].className == "row")
{
//identify the row's index
rowIndex = p;
}
}
//append the duplicate
divlist[rowIndex].appendChild(duplicate);
}

Array: Put multple objects in array

i am having a function like below
var resultObject = {
testResult: $('.test').map(function() {
return {name: $(this).text(), no:'1'};
}).get()
};
console.log(resultObject);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test2">1</div>
<div class="test2">2</div>
<div class="test2">3</div>http://stackoverflow.com/questions/ask#
The field "no" should be according to the class="test2"but it doesn't seem like i can do something like .map() in .map()
Big Updated!!
I see there are so many answer below and most of them can solve the issues and I just figured out a way to fix my problem too.
Please let me share it and see if there's anything else i shall improve.
var test1= "";
$(".test" ).each(function( index ) {
test1 = $(this).text();
});
var test2= $('.test2').map(function() {
return {name: $(this).text(), no:test1};
}).get()
var sovCategories = test2;
You don't need a second loop. You can use .eq() to select the element by the same index.
var resultObject = {
testResult: $('.test').map(function(i) {
return {
name: $(this).text(),
no: $('.test2').eq(i).text(),
};
}).get()
};
console.log(resultObject);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test2">1</div>
<div class="test2">2</div>
<div class="test2">3</div>
And just because I had fun, a bit shorter version as arrow function too! ;)
var resultObject = {
testResult: $('.test').map((i, e) => ({
name: $(e).text(),
no: $('.test2').eq(i).text()
})).get()
};
console.log(resultObject);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test2">1</div>
<div class="test2">2</div>
<div class="test2">3</div>
You can use below to find the div by the number of the iteration, however this might not be the best thing to do. See below the snippet..
var resultObject = {
testResult: $('.test').map(function(i) {
return {name: $(this).text(), no: $('.test2').eq(i).text()};
}).get()
};
console.log(resultObject);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test2">1</div>
<div class="test2">2</div>
<div class="test2">3</div>http://stackoverflow.com/questions/ask#
Instead of doing above, better change your html and use data-attributes.
<div class="test" data-no="1">test1</div>
<div class="test" data-no="2">test2</div>
<div class="test" data-no="3">test3</div>
Doing it like this, you will be able to pull the data much easier:
var resultObject = {
testResult: $('.test').map(function(i) {
return {name: $(this).text(), no: $(this).data("no")};
}).get()
};
console.log(resultObject);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test" data-no="1">test1</div>
<div class="test" data-no="2">test2</div>
<div class="test" data-no="3">test3</div>
<div class="test2">1</div>
<div class="test2">2</div>
<div class="test2">3</div>http://stackoverflow.com/questions/ask#

JQuery Sort Divs by child divs

I have the following list of divs and I'd like to be able to sort them using Javascript / JQuery.
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
I'd like to be able to sort the items by their Genre/Name/Location alphabetically.
Example: If Sort by Genre was clicked, it would sort the items in 0-9 A-Z by Genre.
If any of you have any tips it would greatly be appreciated.
Cheers :)
You have to make a little change to html like following:
<div id="container">
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
jQuery
function sorting(tag) {
var items = $('div.item').sort(function(a, b) {
var txt1 = $.trim($('div.' + tag, a).text()),
txt2 = $.trim($('div.' + tag, b).text());
if (txt1 > txt2) return 1;
else return -1;
});
return items;
}
$('.buttons a').on('click', function(e) {
e.preventDefault();
$('div#container').html(sorting(this.id));
});
Working Sample
Ok, this would be my pure JS solution.
First, we should wrap your <div>s into a larger container.
<div id = "wrapper">
<div id = "item">...</div>
<div id = "item">...</div>
<div id = "item">...</div>
</div>
Now, let's define a constant - which property do you want to sort it by? (this will probably be a function parameter later in your code).
var propName = "genre";
Let's get all the <div>s and put them in an array.
var items = document.getElementsByClassName("item");
var itemsArray = new Array();
Let us sort them lexicographically according to the text of the selected property.
for (var i = 0; i < items.length; i++)
itemsArray.push(items[i]);
itemsArray.sort(function(a, b) {
var aProp = a.getElementsByClassName(propName)[0].firstChild.nodeValue;
var bProp = b.getElementsByClassName(propName)[0] .firstChild.nodeValue;
if (aProp < bProp)
return -1;
else if (aProp > bProp)
return 1;
else
return 0;
});
Let us construct a document fragment consisting of the sorted <div>s.
var fragment = document.createDocumentFragment();
for (var i = 0; i < itemsArray.length; i++)
fragment.appendChild(itemsArray[i].clone());
Finally, let us clear the contents of the <div id = "wrapper"> and replace it with the document fragment.
document.getElementById('wrapper').innerHTML = '';
document.getElementById('wrapper').appendChild(fragment);
Also, note that document.getElementsByClassName does not work in IE<9, but I was now really lazy to cope with that issue.
A fiddle: http://jsfiddle.net/nNXr4/
Check this beast:
function sortByCreatedOnAsc(a,b){
return $(a).find('.created_on').text() > $(b).find('.created_on').text();
}
function sortByCreatedOnDesc(a,b){
return $(a).find('.created_on').text() < $(b).find('.created_on').text();
}
function reorderEl(el){
var container = $('#tasks');
container.html('');
el.each(function(){
$(this).appendTo(container);
});
}
$('#created_on').click(function(){
if($(this).hasClass("asc")){
reorderEl($('.task').sort(sortByCreatedOnDesc));
$(this).removeClass("asc");
$(this).addClass("desc");
} else {
reorderEl($('.task').sort(sortByCreatedOnAsc));
$(this).removeClass("desc");
$(this).addClass("asc");
}
return false;
});
jsfiddle: http://jsfiddle.net/jKJc3/116/

Categories