Thanks a million for taking the time to read this :) First let me show you the example code I am dealing with:
<div id="section-0000001" class="section" data-section-223344="{"id":"123456", "type":"product"}">
<div>Section 0000001</div>
</div>
<div id="section-0000002" class="section" data-section-223344="{"id":"123456", "type":"category"}">
<div>Section 0000002</div>
</div>
<div id="section-123456" class="section" data-section-223344="{"id":"123456", "type":"showcase-product"}">
<div>Section 123456</div>
</div>
<div id="section-234567" class="section" data-section-223344="{"id":"234567", "type":"showcase-product"}">
<div>Section 234567</div>
</div>
<div id="section-345678" class="section" data-section-223344="{"id":"345678", "type":"showcase-product"}">
<div>Section 345678</div>
</div>
<div id="section-0000003" class="section" data-section-223344="{"id":"123456", "type":"image"}">
<div>Section 0000003</div>
</div>
What I want to achieve, is to add a class to all divs with the type 'showcase-product'. I do not have access to the original code so I need to do this with Jquery. There is unfortunately not a unique class to filter these out and the only thing unique is the showcase-product but as you can see that is part of an object within the data attribute and I cannot figure out how to access it.
If the attribute data-section-xxxxxx was the same, this would be much easier but each div has a unique value on the end but the first part data-section- is always the same.
I can loop through the divs with this:
$('.section').each(function(){
for(data in $(this).data())
console.log(data);
});
But I cannot figure out a way to filter out only the divs with type = showcase-product.
I also tried a different approach:
$( ".section" ).each(function( i ) {
element=this;
$.each(this.attributes, function() {
if(this.name.indexOf('data-section') != -1)
$(element).addClass("myClass");
});
});
This adds the class but it also adds it to the ones without type = showcase-product such as type = image or type = category.
I guess it might be something like
this.name.type.value.indeOf('data-section') != 1
But I am not sure of the correct syntax or how to access it especially since type is not the value, it's an object within the value.
Any help appreciated.
See this approach; what it does is explained in the comments:
$(".section").each(function(i, element) {
// get dataset values
var dataValues = Object.values(element.dataset);
// find if has type using a regular expression
var foundType = false;
for (var j = 0; j < dataValues.length; j++) {
if (dataValues[j].match(/\"type\":\"showcase-product\"/)) {
foundType = true; // one dataset value matched!
}
}
// skip this element if no match
if (!foundType) return;
// do your stuff with showcase-product here:
console.log(element, 'found!');
$(element).addClass("myClass");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="section-0000001" class="section" data-section-223344='{"id":"123456", "type":"product"}'>
<div>Section 0000001</div>
</div>
<div id="section-0000002" class="section" data-section-223344='{"id":"123456", "type":"category"}'>
<div>Section 0000002</div>
</div>
<div id="section-123456" class="section" data-section-223344='{"id":"123456", "type":"showcase-product"}'>
<div>Section 123456</div>
</div>
Related
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>
I have a html structure like the following:
<div id="first">
<div id="second">
<div class="inside"></div>
<div class="inside"></div>
<div class="inside"></div>
<div class="inside"></div>
<div class="inside"></div>
</div>
</div>
And the following javascript / jquery code:
$(".inside").mouseover(function(ev){
var el = ev.currentTarget;
//TODO: get real element
var el_position = 1;
});
What I want to do is check the number of ".inside" that is being hovered with the mouse. So, if I hover the first entry of ".inside" it should display "1". In the fourth it should display "4". But accessing the variable "el" (ev.currentTarget) has no "element position" property or anything of the alike that would allow me to understand the position of the actual hovered element in relation to "#second" (the first, second, third, etc .inside).
So, does anyone have any idea? Can I get some help? Thank you very much :)
You can use .index() which returns the 0-based index of the element within a collection
$(".inside").mouseover(function(ev) {
var el = ev.currentTarget;
//TODO: get real element
var el_position = $(el).index(".inside") + 1;
console.log(el_position);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div id="first">
<div id="second">
<div class="inside">1</div>
<div class="inside">2</div>
<div class="inside">3</div>
<div class="inside">4</div>
<div class="inside">5</div>
</div>
</div>
I'm currently struggling on a very simple javascript task, but I'm new to it, so its confusing me a lot.
e.g. html
<div class="item">
<div class="title">Item 1 Title</div>
<div class="description-1">lorum</div>
<div class="description-2">ipsum</div>
<div class="description-combined"></div>
</div>
So I need to combine paragraphs 1 & 2, and replace the empty info in paragraph 3. I don't use jQuery yet, so my research has caused struggle because of this.... i currently have:
var p1 = getElementsByClassName ('description-1').innerHTML;
var p2 = getElementsByClassName ('description-2').innerHTML;
var p3 = p1 + P2
document.getElementsByClassName ('description-combined').innerHTML = p3
I did have p3 to have p1.concat(p2) but that didn't work. I'm using it as an external file, so i may be missing out on putting something in my HTML file too.
The edit changes the question.
What I'd probably do is loop through the .item elements, combining the descriptions within.
document.getElementsByClassName is a property of document, not a freestanding function, and it returns a list of matching elements. It's also not as widely supported as document.querySelector and document.querySelectorAll, so I'd probably use those; for what we're talking about, we'll also want Element#querySelector.
// Get a list of the items and loop through it
Array.prototype.forEach.call(document.querySelectorAll(".item"), function(item) {
// Get the two description divs, and the combined, that
// are *within* this item
var d1 = item.querySelector(".description-1");
var d2 = item.querySelector(".description-2");
var c = item.querySelector(".description-combined");
// Set the combined text (this assumes we have them all)
c.innerHTML = d1.innerHTML + d2.innerHTML;
});
.description-combined {
color: green;
}
<div class="item">
<div class="title">Item 1 Title</div>
<div class="description-1">One description 1</div>
<div class="description-2">One description 2</div>
<div class="description-combined"></div>
</div>
<div class="item">
<div class="title">Item 2 Title</div>
<div class="description-1">2 description 1</div>
<div class="description-2">2 description 2</div>
<div class="description-combined"></div>
</div>
<div class="item">
<div class="title">Item 3 Title</div>
<div class="description-1">3 description 1</div>
<div class="description-2">3 description 2</div>
<div class="description-combined"></div>
</div>
The Array.prototype.forEach.call(list, function() { ... }); thing is a way to loop through anything that's like an array, but isn't an array. It's explained more in this other answer, which also has several alternatives.
I would like to change div order based on operating system.
For example on windows
<div class="first"> </div>
<div class="second"> </div>
<div class="third"> </div>
on Mac
<div class="third"> </div>
<div class="first"> </div>
<div class="second"> </div>
I have some this js to show and hide a div which is okay if I use a parent div but I would rather reorder.
if (navigator.appVersion.indexOf("Mac") > -1) {
$('#windows').hide();
$('#mac').show();
}
Here is one way:
if (navigator.appVersion.indexOf("Mac") > -1) {
$('.third').insertBefore('.first');
}
There is also .insertAfter() that you can use. I would use these methods for basic reordering like that seen in your example. If there is a lot of re-ordering required, I think a different approach may be better, like #Daniel's example
For a more general solution, you could store the order for each platform in an array and then go through the array and re-add the element to the container using $.appendTo().
Demo
HTML
<div id="container">
<div class="first">1</div>
<div class="second">2</div>
<div class="third">3</div>
</div>
JS
var macOrder = [".third", ".first", ".second"];
$(function () {
var container = $('#container');
for (var i = 0; i < macOrder.length; i++) {
$(macOrder[i]).appendTo(container);
}
});
I have a page similar to:
<div id="content">
<div id="boxes">
<div id="box:content:1:text" />
<div id="box:content:2:text" />
<div id="another_id" />
<div id="box:content:5:text" />
</div>
</div>
I want to know the number of div with id that matches the expression box:content:X:text (where X is a number). I can use pure javascript or jquery for doing that.
But inside boxes i can have several types of divs that i don't want to count ("another_id") and i can have gaps from the X of an element and the next element, they are not in sequence.
I was searching a way to gets the elements based on a regexp but i haven't found any interesting way. Is it a possibile approach ?
Thanks
jQuery:
$("div[id]").filter(function() {
return !(/^box:content:\d+:text$/.test(this.id));
}).size();
Pure JavaScript:
var elems = document.getElementsByTagName("div"),
count = 0;
for (var i=0, n=elems.length; i<n; ++i) {
if (typeof elems[i].id == "string" && /^box:content:\d+:text$/.test(this.id)) {
++count;
}
}
To expand on Boldewyn's comment, you can provide multiple classes delimited by spaces, and then work with those classes separately or in combination.
This probably removes the need for the ids, but I've left them in just in case:
<div id="content">
<div id="boxes">
<div id="box:content:1:text" class="box content 1 text" />
<div id="box:content:2:text" class="box content 2 text" />
<div id="another_id" />
<div id="box:content:5:text" class="box content 5 text" />
</div>
</div>
And then with jQuery you can count just the desired items with:
$j('#content>#boxes>.box.content.text').length
(or perhaps just use '#boxes>.box.text' or whatever works for what you're trying to match)