Iterating through data-* elements using JQuery $.children() and $.each()? - javascript

I want to be able to iterate through my HTML code and pick every element that harbors the "data-" attribute and collect it's value. I have looked on the web and only found ways to collect data on specific data- elements. I need to get the data-* value without knowing the element name, and so I found the .children() jquery method. However I don't know how to implement it all together.
Here's a quick example of what I'm doing:
HTML:
<div data-example="master">
<div data-example="i">
<div data-example="a">
<span data-example="1"></span>
</div>
<div data-example="b">
<span data-example="2"></span>
</div>
</div>
<div data-example="ii">
<div data-example="c">
<span data-example="3"></span>
</div>
<div data-example="d">
<span data-example="4"></span>
</div>
</div>
</div>
JavaScript:
var master = [];
$("#master").children(function() {
var element = $(this);
var data = element.data('example');
master.push(data);
}
So for this particular example, I want my end-game to have the master array equal [i, a, 1, b, 2, ii, c, 3, d, 4].
But I'm not doing it right because nothing is happening when I trigger the JQuery event.

Use Attribute selector and apply Array.prototype.map over it.
console.log(Array.from($('[data-example]')).map(function(elem) {
return $(elem).data('example');
}));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div data-example="master">
<div data-example="i">
<div data-example="a">
<span data-example="1"></span>
</div>
<div data-example="b">
<span data-example="2"></span>
</div>
</div>
<div data-example="ii">
<div data-example="c">
<span data-example="3"></span>
</div>
<div data-example="d">
<span data-example="4"></span>
</div>
</div>
</div>

Related

Get values from ID HTML and save in array

I'm doing a view where once I click I'm displaying
For Loop
I am having a view that captures a QR code and displays it on the screen, what I want to do next is take these values by iterating the elements with a for loop and save it in an array, in this case my ID is id="scanned-result" and I want to iterate each containing values and saving to an array.
I am doing this but for some reason it is not performing the operation correctly. I would like to know what I should correct?
function SubmitCodes() {
var QRCodeval= document.querySelectorAll('scanned-result');
var arr = [];
for (var i in QRCodeval) {
alert(QRCodeval[i]);
arr.push( QRCodeval[i]);
}
alert(arr.val);
}
VIEW
<div class="container">
<div class="row">
<div class="col-md-12" style="text-align: center;margin-bottom: 20px;">
<div id="reader" style="display: inline-block;"></div>
<div class="empty"></div>
<div id="scanned-result">
<div>[1] - https://www.investopedia.com/terms/q/quick-response-qr-code.asp</div>
<div>[2] - https://www.dropbox.com/s/705b6p4a2ydvayx/EN-Poster.pdf?dl=0</div></div>
</div>
</div>
</div>
There are several issues with your code. To select element by ID using querySelector you need to use # selector, also to select the divs inside you can use element > element selector.
var QRCodeval = document.querySelectorAll("#scanned-result>div");
querySelectorAll returns a nodeList. So you need to iterate through it to get value of individual elements. But you should not use for..in. You can use forEach instead.
function submitCodes() {
var QRCodeval = document.querySelectorAll("#scanned-result>div");
var arr = [];
QRCodeval.forEach((el) => arr.push(el.innerHTML));
console.log(arr)
}
submitCodes();
<div class="container">
<div class="row">
<div class="col-md-12" style="text-align: center;margin-bottom: 20px;">
<div id="reader" style="display: inline-block;"></div>
<div class="empty"></div>
<div id="scanned-result">
<div>[1] - https://www.investopedia.com/terms/q/quick-response-qr-code.asp</div>
<div>[2] - https://www.dropbox.com/s/705b6p4a2ydvayx/EN-Poster.pdf?dl=0</div>
</div>
</div>
</div>
</div>
To get the text inside of the elements you can use innerHTML.
Since there is no <scanned-result></scanned-result> element on your page, as charlietfl pointed out, you won't get any results.
Since your HTML markup is the following:
<div id="scanned-result">
<!-- … -->
</div>
You are looking for an ID.
And the valid ID query in a CSS selector is a #, because of that you should query like:
var QRCodeval = document.querySelectorAll('#scanned-result')
I've changed the iteration to fill the array with the lines inside the ID scanned-result. Would that help ?
function SubmitCodes() {
var QRCodeval = document.getElementById('scanned-result').children;
var arr = [];
for (var i = 0; i < QRCodeval.length; i++) {
arr.push(QRCodeval[i].innerText)
}
console.log(arr)
}
<div class="container">
<div class="row">
<div class="col-md-12" style="text-align: center;margin-bottom: 20px;">
<div id="reader" style="display: inline-block;"></div>
<div class="empty"></div>
<div id="scanned-result">
<div>[1] - https://www.investopedia.com/terms/q/quick-response-qr-code.asp</div>
<div>[2] - https://www.dropbox.com/s/705b6p4a2ydvayx/EN-Poster.pdf?dl=0</div>
</div>
</div>
</div>
</div>

Add a Like + Sort Function to existing dynamic funcion

I wrote a function that dynamically creates a webpage for me based on a json database.
Now I want to add 2 functions:
If you click the like img (its got the id button) the like counter should increase on the webpage by 1. Pretty easy just a on(click) with jQuery variable++ and then .text(variable)
A sort function - based on the likes one item received, you should be able to sort it (most liked div first, 2nd, 3rd....
I can write it for each individually with individual variables when I give all the like buttons and outputs a separate id but I wanted to make it dynamic so if you add new data to json file it dynamically works with the like and sort function.
The likes are not saved anywhere for now.
Since sitting on it for 3h and google so much and so much stackoverflow I think I overloaded my brain with different stuff and now nothing seems to work ^^
function filmInsert(insert) {
$.each(film, function(i, data) { //.each statt loop
let box =
`<div class="boxwrapper">
<div class="imgbox">
<img src="${data.img}" alt="${data.titel}">
</div>
<div class="textbox">
<h3>${data.titel}</h3>
<p>${data.beschreibung}</p>
<p> <a id="button${data.id}">
<img src="img/budspencer_official.png"> Like
</a>
<span class="output${data.id}">${data.likes}</span>
</p>
</div>
</div>`;
insert.append(box);
});
}
I've added a container element for the boxwrapper items as I assume you have one and as it's better to have one instead of just adding the sorted items to the body of the HTML document.
$(document).on("click", ".textbox a", function() {
let likes = parseInt($(this).closest(".textbox").find("span").text());
$(this).closest(".textbox").find("span").text(likes + 1);
});
$("#sort").on("click", function() {
let divs = $(".boxwrapper")
let sorted = divs.sort(function(a, b) {
return $(a).find("span").text() < $(b).find("span").text() ? 1 : -1;
});
$(".container").html(sorted);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="boxwrapper">
<div class="imgbox">
<img src="example.gif" alt="Title">
</div>
<div class="textbox">
<h3>Titel</h3>
<p>Description</p>
<p> <a id="button1">
<img src="https://dummyimage.com/40x40/000/fff&text=1"> Like
</a>
<span class="output1">0</span>
</p>
</div>
</div>
<div class="boxwrapper">
<div class="imgbox">
<img src="example.gif" alt="Title">
</div>
<div class="textbox">
<h3>Titel 2</h3>
<p>Description 2</p>
<p> <a id="button2">
<img src="https://dummyimage.com/40x40/000/fff&text=2"> Like
</a>
<span class="output2">0</span>
</p>
</div>
</div>
</div>
<button id="sort">
Sort
</button>

Link simillary name classes so that when one is clicked the other is given a class

Basically, I'm asking for a way to optimize this code. I'd like to cut it down to a few lines because it does the same thing for every click bind.
$("#arch-of-triumph-button").click(function(){
$("#arch-of-triumph-info").addClass("active-info")
});
$("#romanian-athenaeum-button").click(function(){
$("#romanian-athenaeum-info").addClass("active-info")
});
$("#palace-of-parliament-button").click(function(){
$("#palace-of-parliament-info").addClass("active-info")
});
Is there a way to maybe store "arch-of-triumph", "romanian-athenaeum", "palace-of-parliament" into an array and pull them out into a click bind? I'm thinking some concatenation maybe?
$("+landmarkName+-button").click(function(){
$("+landmarkName+-info").addClass("active-info")
});
Is something like this even possible?
Thanks in advance for all your answers.
EDIT: Here's the full HTML.
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button"></div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button"></div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Assuming you're not able to modify your HTML markup (in which case with use of CSS classes would be cleaner), a solution to your question would be as shown below:
// Assign same click handler to all buttons
$("#arch-of-triumph-button, #romanian-athenaeum-button, #palace-of-parliament-button")
.click(function() {
// Extract id of clicked button
const id = $(this).attr("id");
// Obtain corresponding info selector from clicked button id by replacing
// last occurrence of "button" pattern with info.
const infoSelector = "#" + id.replace(/button$/gi, "info");
// Add active-info class to selected info element
$(infoSelector).addClass("active-info");
});
Because each .landmark-button looks to be in the same order as its related .landmark-info, you can put both collections into an array, and then when one is clicked, just find the element with the same index in the other array:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
This does not rely on IDs at all - feel free to completely remove those from your HTML to declutter, because they don't serve any purpose now that they aren't being used as selectors.
Live snippet:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
.active-info {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button">click</div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button">click</div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Older answer, without knowing the HTML: You can extract the ID of the clicked button, slice off the button part of it, and then select it concatenated with -info:
$(".landmark-button").click(function() {
const infoSel = this.id.slice(0, this.id.length - 6) + 'info';
$(infoSel).addClass('active-info');
});
A much more elegant solution would probably be possible given the HTML, though.

Using class tree to delete specific HTML elements

How can I use vanilla JS to find and delete elements with a specific class X where the parent has class Y?
Example. Given
<div class="likes noise1">
<div class="count noise2">
42
</div>
</div>
<div class="retweets noise3">
<div class="count noise4">
7
</div>
</div>
<div class="messages noise5">
<div class="count noise6">
2
</div>
</div>
I would like to delete the first two ".count" elements (the childs of ".likes" and ".retweets"). The messages div however should be left untouched.
I have tried using querySelectorAll which return a frozen NodeList and iterating it, without success.
You can loop through all the elements to check the Element.className property of the Node.parentNode to remove the element like the following way:
document.querySelectorAll('.count').forEach(function(el){
var classN = el.parentNode.className
if(classN.includes('likes') || classN.includes('retweets'))
el.remove();
});
<div class="likes">
<div class="count">
42
</div>
</div>
<div class="retweets">
<div class="count">
7
</div>
</div>
<div class="messages">
<div class="count">
2
</div>
</div>
OR: You can simply simply specify both the classes as part of the selector, in which case you do not need to check the parentNode as the selector will give you only the elements inside the parents:
document.querySelectorAll('.likes > .count, .retweets > .count').forEach(function(el){
el.parentNode.remove();
});
<div class="likes">
<div class="count">
42
</div>
</div>
<div class="retweets">
<div class="count">
7
</div>
</div>
<div class="messages">
<div class="count">
2
</div>
</div>
Another alternative, further to those already given is to keep an array of the css selector you'll need to find your targets. From there, it's just a simple matter of using querySelector so that the result is still live, albeit in a loop.
"use strict";
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onWindowLoaded, false);
function onWindowLoaded(evt)
{
var tgtSelectors = [ '.likes > .count', '.retweets > .count' ];
tgtSelectors.forEach(removeBySelector);
}
function removeBySelector(curSelector)
{
var tgt = document.querySelector(curSelector);
while (tgt != undefined)
{
tgt.remove();
tgt = document.querySelector(curSelector);
}
}
<div class="likes">
<div class="count">42</div>
</div>
<div class="retweets">
<div class="count">7</div>
</div>
<div class="messages">
<div class="count">2</div>
</div>

Jquery: How to clone <div> based on the count?

I am trying to use jquery clone() for displaying cards on my web page. When the page loads it has to clone card div based on the count of rooms in that particular location. I hardcoded count as roomcount. I tried using simple for loop as per https://stackoverflow.com/a/12835644/6915446, However it doubles the count of divs each time. Please provide me right inputs.
<div class="container-fluid">
<div class="row-fluid">
<div class="col-lg-2">
<div class="card">
<h6 class="card-header">NC001
<ul class="card-header-pills pull-xs-right">
<span class="badge badge-primary" aria-hidden="true">2</span>
<!-- <span class="glyphicon glyphicon-user" aria-hidden="true"></span> -->
</ul>
</h6>
<div class="card-block" id="scrollCard">
<h4 class="card-title"></h4>
<!-- <p class="card-text">ICU : 12.00 AM</p>
<p class="card-text">VEN : 1.00 AM</p> -->
</div>
</div>
<script>
var roomcount = 3;
$(document).ready(function() {
for(var i=0; i< roomcount; i++) {
$(".col-lg-2").clone().appendTo(".row-fluid");
}
});
</script>
</div>
Thanks.
When the count is 2, it clones to display 4 divs:
When the count is 3, it clones to displays 8 divs:
I think you might be cloning an array?
After you have cloned
$(".col-lg-2")
once it becomes an array, so when you clone it again you get 4?
Try using
$(".col-lg-2:first").
Tom
When you select an element by it's class name, jquery returns an array of all the matching objects.
So once you've cloned an item with the same class name, the next time you call $(".col-lg-2"); it will actually fetch 2 items and clone them, and the next time it will fetch 4 items and clone them etc.
To avoid it (and as a best practice) you should cache the element you are cloning:
var roomcount = 3,
$cloned = $('.col-lg-2');
for(var i = 0; i < roomcount; i++) {
$cloned.clone().appendTo('.row-fluid');
}
that way you always clone just that one object you cached.
NOTE: make sure you don't have an id on the cloned object since you'll be creating multiple items with the same id and id should be unique
The clone() method makes a copy of selected elements, including child nodes, text and attributes.
You can save the value of $(".col-lg-2") in a variable, and clone it, these way you are improving performance as you are not going to query the DOM multiple times:
var roomcount = 3,
$colLg2 = $('.col-lg-2');
for(var i = 0; i < roomcount; i++) {
$colLg2.clone().appendTo('.row-fluid');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row-fluid">
<div class="col-lg-2">
<div class="card">
<h6 class="card-header">NC001
<ul class="card-header-pills pull-xs-right">
<span class="badge badge-primary" aria-hidden="true">2</span>
<!-- <span class="glyphicon glyphicon-user" aria-hidden="true"></span> -->
</ul>
</h6>
<div class="card-block" id="scrollCard">
<h4 class="card-title"></h4>
<!-- <p class="card-text">ICU : 12.00 AM</p>
<p class="card-text">VEN : 1.00 AM</p> -->
</div>
</div>
</div>
</div>

Categories

Resources