How can I apply function to all elements of a class? - javascript

I am a novice and I have a page that displays job offers, I want to create a function that changes the logo of a company according to the company name mentionned in first 50 characters. The function below works only for the first element of a class. How can I make it work with all the class elements independently?
function logo_switch() {
let anonce = document.querySelector(".anonce").querySelector(".anonceText").innerHTML;
console.log(anonce);
let logo_A = anonce.indexOf('A');
let logo_B = anonce.indexOf('B');
let logo_C = anonce.indexOf('C');
let logo_D = anonce.indexOf('D');
let logo_E = anonce.indexOf('E');
let logo_F = anonce.indexOf('F');
let logo_G = anonce.indexOf('G');
var img = document.querySelector(".anonceLogo");
if ((logo_A > 0) && (logo_A < 50)) {
img.setAttribute("src", "img/a.png");
} else {
console.log(0);
};
if ((logo_B > 0) && (logo_B < 50)) {
img.setAttribute("src", "img/b.jpg");
} else {
console.log(0);
};
if ((logo_C > 0) && (logo_C < 50)) {
img.setAttribute("src", "img/c.jpg");
} else {
console.log(0);
};
if ((logo_D > 0) && (logo_D < 50)) {
img.setAttribute("src", "img/d.jpg");
} else {
console.log(0);
};
if ((logo_E > 0) && (logo_E < 50)) {
img.setAttribute("src", "img/e.jpg");
} else {
console.log(0);
};
if ((logo_F > 0) && (logo_F < 50)) {
img.setAttribute("src", "img/f.png");
} else {
console.log(0);
};
if ((logo_G > 0) && (logo_G < 50)) {
img.setAttribute("src", "img/g.png");
} else {
console.log(0);
};
};
<body onload="logo_switch()">
<div class="anonce">
<h2>Job 1</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
A
</p>
</div>
</div>
<div class="anonce">
<h2>Job 2</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
B
</p>
</div>
</div>
<div class="anonce">
<h2>Job 3</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
C
</p>
</div>
</div>
<div class="anonce">
<h2>Job 4</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
D
</p>
</div>
</div>
</body>

One approach is as below, with explanatory comments in the JavaScript:
const logo_switch = () => {
// using document.querySelectorAll() to retrieve all matching elements, along with
// and Array-literal and the spread operator to convert the iterable NodeList into
// an Array to provide access to Array methods:
let anonceTextElements = [...document.querySelectorAll(".anonceText")];
// the letters (or company names) you're looking for:
const logoLetters = ['A', 'B', 'c', 'D', 'E', 'F', 'G'];
// iterating over the anonceTextElements using Array.prototype.forEach()
// (note that this is entirely possible with NodeList.prototype.forEach(),
// but I use Array methods on this type of collection often enough - to
// filter, map, slice... - that I find it worth always converting to an
// Array for further modification, but that's purely my bias):
anonceTextElements.forEach(
// passing the current element (not the text, the element):
(elem) => {
// retrieve the text of the element, using String.prototype.trim() to
// remove leading and trailing white-space, and then trimming that to
// to the first 50 character with String.prototype.slice():
let text = elem.textContent.trim().slice(0, 50)
// using Array.prototype.filter() to filter the Array to keep only the
// relevant array-elements:
logoLetters
// we keep only the letters for which the provided assessment returns
// true/truthy values; here we're looking to see if the retrieved
// element text contains the current letter/company name:
.filter((letter) => text.includes(letter))
// the remaining elements are passed on to Array.prototype.forEach():
.forEach(
(matchedLetter) => {
elem
// here we navigate to closest ancestor element matching the '.anonce'
.closest('.anonce')
// from there we find the first of any elements matching the supplied
// 'img' selector, and update/set its src property using a template-
// literal, to interpolate the variable (matchedLetter) into the string:
.querySelector('img').src = `img/${matchedLetter}.png`;
});
});
}
logo_switch();
<div class="anonce">
<h2>Job 1</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
A
</p>
</div>
</div>
<div class="anonce">
<h2>Job 2</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
B
</p>
</div>
</div>
<div class="anonce">
<h2>Job 3</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
C
</p>
</div>
</div>
<div class="anonce">
<h2>Job 4</h2>
<div class="anonceBody">
<img class="anonceLogo">
<p class="anonceText">
D
</p>
</div>
</div>
References:
Array.prototype.forEach().
Array.prototype.filter().
Array.prototype.some().
document.querySelector().
document.querySelectorAll().
Element.closest().
Element.querySelector().
Element.querySelectorAll().
NodeList.prototype.forEach().
String.prototype.includes().
String.prototype.slice().

Related

How do I make a search filter that you can only search for a specifc element within a set of divs?

Currently, I am able to search for a hall by typing anything that is within a hall container (including name, location, capacity), however, I only want to be able to filter results for searches for a hall name.
<div id="searchFilter" class="flexColumn">
<label for="searchFilterText">Search for Community Halls</label>
<input type="text" id="searchFilterText" placeholder="Search for the name of a community hall">
</div>
`<div class="hall">
<div class="info">
<p>${data.Halls[halls[i]].Location[0].Address}, ${data.Halls[halls[i]].Location[1].Suburb}<br>Capacity: ${data.Halls[halls[i]].Room[0]["Standing Capacity"]}</p>
</div>
<div class="image">
<img class="img" src="${data.Halls[halls[i]].Description[4].Photos}" alt="${data.Halls[halls[i]]["Hall Name"]}">
</div>
<div class="hallNameBox">
<p class="hallName">${data.Halls[halls[i]]["Hall Name"]}</p>
</div>
</div>`;
$(document).ready(function(){
$("#searchFilterText").on("keyup", function() {
let value = $(this).val().toLowerCase();
$(".hall").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
Instead of using toggle use show and hide.
(Use one, two, or three to test this reduced example).
$(function() {
$("#searchFilterText").on('keyup', function() {
// Grab the value
const value = $(this).val().toLowerCase();
// If it's not empty
if (value) {
// `filter` all the hall elements if
// the text of the hallName element doesn't start with
// the value and hide them
$('.hall').filter(function() {
const text = $(this).find('.hallName').text().toLowerCase();
return !text.startsWith(value);
}).hide();
// Otherwise show them
} else {
$('.hall').show();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="searchFilter" class="flexColumn">
<input type="text" id="searchFilterText" />
</div>
<div class="hall">
<div class="hallNameBox">
<p class="hallName">One</p>
</div>
</div>
<div class="hall">
<div class="hallNameBox">
<p class="hallName">Two</p>
</div>
</div>
<div class="hall">
<div class="hallNameBox">
<p class="hallName">Three</p>
</div>
</div>
$(document).ready(function(){
$("#searchFilterText").on("keyup", function() {
let value = $(this).val().toLowerCase();
$(".hall *").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
Is this what you want? If not, let me know.

How to send keypresses for an array of letters in JavaScript

I'm trying to come up with a solution to press keys virtually for a typing test. What I want is to get the text and store individual letters in an array and then press all keys with some delay in between each presses.
This is the HTML of the text layout. Imagine it has the word hello.
<div class="digit-container">
<div>
<span>h</span>
</div>
</div>
<div class="digit-container">
<div>
<span>e</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>o</span>
</div>
</div>
This is the JavaScript code I have come up with. I have managed to store these letters in an array.
wordList = document.querySelectorAll(".digit-container > div > span");
wordArray = [];
for (let i = 0; i < wordList.length; i++) {
individualWord = wordList[i].innerHTML;
wordArray.push(individualWord);
}
Now I would like JavaScript to send keypresses for this array of letters { "h", "e", "l", "l", "o" }. Basically when I'm pasting this code and press enter in the console, I would like JavaScript to press "Hello" with a milliseconds of delay in between keystrokes. How can I get JavaScript into press keys?
Here is the solution.
const elements = document.querySelectorAll(".digit-container > div > span");
const chars = Array.from(elements).map((item) => item.textContent);
const delay = 1000;
let i = 0;
const pressKey = () => {
setTimeout(() => {
const char = chars[i];
const event = new KeyboardEvent("keyup", {
key: char
});
document.body.dispatchEvent(event);
if (i !== chars.length - 1) {
i++;
pressKey();
}
}, delay);
};
pressKey();
document.body.addEventListener("keyup", (e) => {
console.log(e.key);
});
<div class="digit-container">
<div>
<span>h</span>
</div>
</div>
<div class="digit-container">
<div>
<span>e</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>l</span>
</div>
</div>
<div class="digit-container">
<div>
<span>o</span>
</div>
</div>

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>

Get dollar total of all elements with class using jQuery

I have the following html:
<div class="balance">
<div class="heading">
<p class="total"><span>00</span></p>
</div>
<div class="instance withdrawal">
<h3>Random</h3>
<p>desc</p>
<p class="amount">$350.<span>00</span></p>
</div>
<div class="instance deposit">
<h3>Added in</h3>
<p>desc</p>
<p class="amount">$1,250.<span>00</span></p>
</div>
<div class="instance withdrawal">
<h3>Bill</h3>
<p>desc</p>
<p class="amount">$50.<span>00</span></p>
</div>
</div>
<!--end wallet-container left-->
How can i use jQuery to add take total deposits, subtract the withdrawals and append it to the p.total?
Try this fiddle.
Edited to take floating points into account.
JS
$(function() {
var total = 0;
// Check each instance
$('.instance').each(function() {
var
$this = $(this),
clone = $this.find('.amount').clone(),
amount = 0,
floating = 0;
// Get floating point
floating = parseFloat('0.' + clone.find('span').text());
clone.find('span').remove();
// Get integer amount
amount = parseInt(clone.text().replace(/\D+/gim, ''), 10);
if (!isNaN(amount) && amount > 0) {
if ($this.is('.deposit')) total += (amount + floating); // Deposit
else if ($this.is('.withdrawal')) total -= (amount + floating); // Withdrawal
}
});
// Format total with commas
var formatted = ('' + parseInt(total, 10)).split('').reverse().join('');
formatted = formatted.replace(/(\d{3})/gim, '$1,');
formatted = formatted.split('').reverse();
if (formatted[0] == ',') formatted.shift();
formatted = formatted.join('');
$('.total').text('$' + parseInt(formatted, 10) + '.');
var decimal = (total - parseInt(total, 10)) * 100;
$('.total').append('<span>' + decimal + '</span>')
});
Try adjusting html slightly by placing $ character before first span element containing whole number including second sibling span element containing decimal number as descendants of .deposit , .withdrawal elements; utilizing data-* attribute to reference object containing withdrawal , deposit, total properties; Array.prototype.reduce() ; Number() ; String.prototype.replace() for comma , character ; .each()
var res = {
deposit: 0,
withdrawal: 0,
total: 0
};
function calculate(el) {
return el.get().reduce(function(a, b) {
return Number(a.textContent.replace(/,/g, "")) + Number(b.textContent)
})
}
$(".deposit, .withdrawal").each(function(i, el) {
res[$(el).data().type] += calculate($("span", el))
})
res.total = res.deposit - res.withdrawal;
$(".total span").html(res.total);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="balance">
<div class="heading">
<p class="total" data-type="total"><span>00</span>
</p>
</div>
<div class="instance withdrawal" data-type="withdrawal">
<h3>Random</h3>
<p>desc</p>
<p class="amount">$<span>350</span><span>.00</span>
</p>
</div>
<div class="instance deposit" data-type="deposit">
<h3>Added in</h3>
<p>desc</p>
<p class="amount">$<span>1,250</span><span>.00</span>
</p>
</div>
<div class="instance withdrawal" data-type="withdrawal">
<h3>Bill</h3>
<p>desc</p>
<p class="amount">$<span>50</span><span>.00</span>
</p>
</div>
</div>
<!--end wallet-container left-->

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