Get concatenate string of multiple value variable in Javascript - javascript

I've a list of div
<div data-attr="sel" data-num="1"></div>
<div data-attr="notSel" data-num="2"></div>
<div data-attr="sel" data-num="3"></div>
I'm tryng to get a string only div with the data-attr="sel" set.
function SI_MoveTasks() {
var getSelected = document.querySelector('[data-attr~="sel"]');
var selectedNums = getSelected.dataset.num;
alert(selectedNums);
}
Now i get (1), how can i get the concatenate string (1,3)?
Thanks for support.

DEMO -> http://jsfiddle.net/0d54ethw/
Use querySelectorAll instead of querySelector since the latter only selects the first element as opposed to all of them.
Then use for loop as shown below
var getSelected = document.querySelectorAll('[data-attr~="sel"]');
var selectedNums = [];
for (var i = 0; i < getSelected.length; i++) {
selectedNums.push(getSelected[i].dataset.num);
}
alert(selectedNums.join(','));

You would need to use document.querySelectorAll to get all matching elements. document.querySelector returns only the first matching element, or null if there is none.
function SI_MoveTasks() {
var getSelected = document.querySelectorAll('[data-attr~="sel"]');
console.log(getSelected);
var selectedNums = '(';
for(var i=0; i< getSelected.length; i++) {
if (selectedNums !== '(') {
selectedNums += ',';
}
selectedNums += getSelected[i].dataset.num;
}
selectedNums += ')';
alert(selectedNums);
}
SI_MoveTasks();
Thats a working code, jsFiddle is: https://jsfiddle.net/3kjye452/

Related

Can I concat a string and a variable to select a DOM element in JavaScript?

I have tried Googling this question but no luck. Probably because I'm asking the wrong way. Any help is much appreciated.
I have variables copy1, copy2, etc. I want to iterate through them and select each one to check if it's contents has a certain number of characters. When I use any variation of the below, it will either console an error or output a string in the console.
var copy1 = document.getElementById('copy1');
var copy2 = document.getElementById('copy2');
var copy3 = document.getElementById('copy3');
for(var i=0;i<4;i++){
console.log(copy+i);
console.log("copy"+i);
};
Ideally I would be able to select an element and style that via javascript.
Much appreciated
Thanks All.
Moe
Agree with #jaromanda-x:
var copy1 = document.getElementById('copy1');
var copy2 = document.getElementById('copy2');
var copy3 = document.getElementById('copy3');
for (var i=1; i<4; i++) {
console.log(window['copy'+i]);
};
Or you can use more simple example, like:
for (var i=1; i<4; i++) {
var name = 'copy' + i;
console.log(document.getElementById(name));
};
Or even:
for (var i=1; i<4; i++) {
console.log(document.getElementById('copy' + i));
};
You can store the properties in an object where values are set to the DOM element
let copies = {
1 : document.getElementById('copy1'),
2 : document.getElementById('copy2'),
3 : document.getElementById('copy3')
}
for (let [key, prop] of Object.entries(copies)) {
console.log(key, prop)
}
console.log(copies[1], copies[2], copies[3]);
Or use attribute begins with and attribute ends with selectors with .querySelector()
let n = 1;
let copy1 = document.querySelector(`[id^=copy][id$='${n}']`); // `#copy1`
let copy2 = document.querySelector(`[id^=copy][id$='${++n}']`); // `#copy2`
for (let i = 1; i < 4; i++) {
console.log(document.querySelector("[id^=copy][id$=" + i + "]"));
}
Since nobody has addressed your "certain number of characters" requirement yet, I thought I would.
You could always use jQuery or write your own $ method, which works as a document.getElementById() wrapper function.
Here is a jsfiddle to see it in action.
HTML
<div id="copy1">01234</div>
<div id="copy2">012345678</div>
<div id="copy3">0123456789 0123456789</div>
JavaScript
// Isn't this just a brilliant short-cut?
function $(id) {
return document.getElementById(id);
}
for (let i=1; i<4; i++){
let obj = $('copy' + i);
let value = (obj) ? obj.innerText : '';
console.log('value.length:', value.length);
};

Loop through more querySelectorAll matches

i'm trying to get the innerHTML out of two different ids to count words. Therefore i used querySelectorAll with two id matches. I only get the first match back. Is this method even possible?
function() {
var wordCounts;
var wordCountTemp = document.querySelectorAll("#text-block-10, #text-block-12");
var i;
for(i = 0; i < wordCountTemp.length; i++){
wordCounts = wordCountTemp[i].innerHTML;
wordCounts.replace(/(^\s*)|(\s*$)/gi,"");
wordCounts.replace(/[ ]{2,}/gi," ");
wordCounts.replace(/\n /,"\n");
return wordCounts.split(" ").length;
}
}
Thanks a lot for your help!
Best regards,
Toni
You return from your function prior to doing anything with any element other than the first one returned from querySelectorAll. In addition, replace does not modify the string, it returns a new copy. Thus, the count you are returning is that of wordCountTemp[i].innerHTML.split(" ").length.
Your original code: (with comments)
function() {
var wordCounts;
var wordCountTemp = document.querySelectorAll("#text-block-10, #text-block-12");
var i;
for(i = 0; i < wordCountTemp.length; i++){
wordCounts = wordCountTemp[i].innerHTML;
wordCounts.replace(/(^\s*)|(\s*$)/gi,""); //Has no effect
wordCounts.replace(/[ ]{2,}/gi," "); //Has no effect
wordCounts.replace(/\n /,"\n"); //Has no effect
//This next line returns your result in the first pass through the loop.
// Only the first element returned by querySelectorAll is acted upon.
// No other element is processed other than the first one.
return wordCounts.split(" ").length;
}
}
Note: I am changing innerHTML to textContent. I'm assuming that you only want to count the words which are text (i.e. not HTML code, scripts, etc.). I also changed the variable name wordCountTemp to nodeList as that is more descriptive of what it is (it is, in fact, a NodeList)
To use a similar structure to what you are already using:
function countWords() {
var wordCounts;
var totalWordCount=0;
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
wordCounts = nodeList[i].textContent;
wordCounts = wordCounts.replace(/(^\s*)|(\s*$)/gi,"");
wordCounts = wordCounts.replace(/[ ]{2,}/gi," ");
wordCounts = wordCounts.replace(/\n /,"\n");
totalWordCount += wordCounts.split(" ").length;
}
return totalWordCount; //return the total count after all passes through loop
}
Instead of assigning your result of each replace to wordCounts over and over again to progressively modify it, you could just directly act on the new string returned by replace:
function countWords() {
var totalWordCount=0;
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
totalWordCount += nodeList[i].textContent
.replace(/(^\s*)|(\s*$)/gi,"")
.replace(/[ ]{2,}/gi," ")
.replace(/\n /,"\n")
.split(" ").length;
}
return totalWordCount; //return the total count after all passes through loop
}
Using regular expressions is, relatively, expensive. not really that much, but there is no reason not to optimize in this situation. Instead of performing all of the replace functions for each element, it is more efficient to, within the loop, concatenate the strings returned by textContent. Then, after you have one big long string with all the text from all the elements, you can perform the replace and split actions once.
function countWords() {
var allText='';
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
allText += ' ' + nodeList[i].textContent;
}
//return the total count after getting the textContent from all elements
return allText.replace(/(^\s*)|(\s*$)/gi,"")
.replace(/[ ]{2,}/gi," ")
.replace(/\n /,"\n")
.split(" ").length;
}
Note: All of the above assume that none of the elements returned by the querySelectorAll are children of other elements which are returned. If they are, you will be counting the same text twice.
Try this:
Array.from(document.querySelectorAll("#text-block-10, #text-block-12"))
.map(x => x.innerHTML
.replace(/(^\s*)|(\s*$)/gi,"")
.replace(/[ ]{2,}/gi," ")
.replace(/\n /,"\n")
.split(" ")
.length)
.reduce((a, b) => a + b)

Filter an array of tags with props

Hei guys, im struggling with a problem here. I selected all elements from body tag into an array like so :
var DOMelementsOrder = [];
var elements = document.querySelectorAll('body > div');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
DOMelementsOrder.push(element);
console.log(DOMelementsOrder[i].offsetLeft);
}
What i'm trying to reach is to sort the tags in array by theyr prop offset left.
The console in for loop return "40,200,85". What i try to achieve is to sort the tags in DOMelementsOrder in order of theyr offsetLeft.
Any help? Thanks in advance.
ONLY WITH PURE JS
EDIT:
What i have tryed:
function bubbleSort(a, b)
{
var swapped;
do {
swapped = false;
for (var i=0; i < a.length-1; i++) {
if (a[i].b > a[i+1].b) {
var temp = a[i].b;
a[i].b = a[i+1].b;
a[i+1].b = temp;
swapped = true;
}
}
} while (swapped);
}
bubbleSort(DOMelementsOrder, DOMelementsOrder.offsetLeft);
console.log(DOMelementsOrder);
Use the Array.prototype.sort method and pass a compare function to compare the values of offsetLeft for each element.
// qSA doesn't return an array, so we have to convert it first
var elements = Array.prototype.slice.call(document.querySelectorAll('body > div'));
// then we can sort
var orderedElements = elements.sort(function(a, b) {
return a.offsetLeft - b.offsetLeft;
});

JQuery not replacing html

here is the deal, i have the following jquery code that should add the array values to specific #id, buf it does not replace the code, only add more, and i need a little help to make it replace the html on othe link click.
Code:
function changeClass(curClass){
switch(curClass){
case "Schoolgirl":
case "Fighter":
var charSkillsNames = ["text1","text2","text4","text5"];
//loop show array values
listSkillsNames(charSkillsNames);
break;
}
}
function listSkillsNames(arr){
var length = arr.length,
element = null;
$("#skills").html(function(){
for (var i = 0; i < length; i++) {
element = arr[i];
$(this).append("<li>"+element+"</li>");
}
});
}
this works well but i need it to replace the html inside the "#skills" id when i click on the link that makes it work
PS: problem is really here
The issue is that you don't empty the HTML of #skills element. Use $("#skills").html("") to empty it.
function listSkillsNames(arr){
var length = arr.length,
element = null;
var $skills = $("#skills");
$skills.html(""); // empty the HTML
for (var i = 0; i < length; i++) {
element = arr[i];
$skills.append("<li>"+element+"</li>"); // append new items
}
}
The problem is because you are keep appending new items to the element always without removing the existing items.
Just empty the skill element, also there is no need to use the .html(function(){}) here
function listSkillsNames(arr) {
var length = arr.length,
element = null;
var $skill = $("#skills").empty();
for (var i = 0; i < length; i++) {
element = arr[i];
$skill.append("<li>" + element + "</li>");
}
}

javascript /jQuery - For Loop

I have a query ajax response which I then use to set the array variables.
Is there anyway to use a 'For Loop' to change to #name so that I don't have to write out a line of code to set each array element.
array[0]=$('#event00',response).html();
array[1]=$('#event01',response).html();
array[2]=$('#event02',response).html();
array[3]=$('#event03',response).html();
So '#event00' could be used in a for loop to change to '#event01' etc
Use a regular for loop and format the index to be used in the selector.
var array = [];
for (var i = 0; i < 4; i++) {
var selector = '' + i;
if (selector.length == 1)
selector = '0' + selector;
selector = '#event' + selector;
array.push($(selector, response).html());
}
What about something like this?
var arr = [];
$('[id^=event]', response).each(function(){
arr.push($(this).html());
});
The [attr^=selector] selector matches elements on which the attr attribute starts with the given string, that way you don't care about the numbers after "event".
.each() should work for you. http://api.jquery.com/jQuery.each/ or http://api.jquery.com/each/ or you could use .map.
var newArray = $(array).map(function(i) {
return $('#event' + i, response).html();
});
Edit: I removed the adding of the prepended 0 since it is suggested to not use that.
If you must have it use
var newArray = $(array).map(function(i) {
var number = '' + i;
if (number.length == 1) {
number = '0' + number;
}
return $('#event' + number, response).html();
});

Categories