Need to check class exist in multiple div using javascript - javascript

There are multiple divs of step_input as class and inside those divs may or may not consists spans with same class. I need to check whether a particular span exist in any of the div with class as step_input. Then change the color of spans with same class which exists in selectable-tags class.I had to use javascript only
Here in the fiddle span1 exists in the step_input class. So its color in selectable-tags needs to be changed.
Here's a fiddle Link
var parentz = document.querySelectorAll('step_input');
for(i=0;i<document.querySelectorAll('.selectable-tags > span').length;i++)
{
tagclassName='ing-tag_'+i;
for(k=0;k<parentz.length;k++)
if ( parentz[k].querySelector("."+tagclassName) !== null) {
document.querySelector('.selectable-tags > tagclassName').style.backgroundColor="#fafafa";
}
}
<div class="selectable-tags" >
<span data-class="label" style="background-color: red;" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div class="selectable-tags" >
<span style="background-color: red" data-class="label" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div id="step_input_0" name="step" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true"> This does not contains anything
</div>
<div value="" id="step_input_1" name="step" placeholder="Tell us about step 2" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true"> <span style="background-color: red;" data-class="label" class="ing-tag_0" contenteditable="false"> Span1 </span>Thw color of span 1 in selectable tags needs to change </div>
Edit: When a span with is detected in the step_input. Its corresponding one in .selectable_tags class 's color changes. Like here Span1 with class 'ing-tag_1' is in step_input class. Now the color of Span1 in the div with class selectable_tags 's color needs to be change. Please suggest a better way to do this if there's one.

You need to change color each selectable tag one by by one. The following would check and color the tag which are present in the step_input
var parentz = document.querySelectorAll('.step_input');
console.log(parentz);
for(i=0;i<document.querySelectorAll('.selectable-tags > span').length;i++){console.log(document.querySelectorAll('.selectable-tags > span'));
tagclassName='ing-tag_'+i;
for(k=0;k<parentz.length;k++){
if ( parentz[k].querySelector("."+tagclassName) !== null) {
colorthem= document.querySelectorAll('.selectable-tags > .'+tagclassName) ;console.log(colorthem);
for(l=0;l<colorthem.length;l++)
{console.log(colorthem[l]);
colorthem[l].style.backgroundColor="red";
} }
}}
<div class="selectable-tags" >
<span data-class="label" style="background-color: red;" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div class="selectable-tags" >
<span style="background-color: red" data-class="label" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div id="step_input_0" name="step" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true"> This does not contains anything
</div>
<div value="" id="step_input_1" name="step" placeholder="Tell us about step 2" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true"> <span style="background-color: red;" data-class="label" class="ing-tag_0" contenteditable="false"> Span1 </span>Thw color of span 1 in selectable tags needs to change </div>

Is it this what you need?
var parentz = document.querySelectorAll('.step_input');
var selectable = document.querySelectorAll('.selectable-tags');
for(j=0; j < selectable.length; j++){
var current = selectable[j];
var spans = current.querySelectorAll('.selectable-tags > span');
for(i=0; i < spans.length; i++){
tagclassName='ing-tag_'+i;
for(k=0; k < parentz.length; k++){
if (parentz[k].querySelector("."+tagclassName)) {
selectable[j].querySelector('.' +tagclassName).style.backgroundColor="#fafafa";
}
}
}
}
<div class="selectable-tags" >
<span data-class="label 11" style="background-color: red;" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div class="selectable-tags" >
<span style="background-color: red" data-class="label" class="ing-tag_0"> Span1 </span>
<span style="background-color: red;" data-class="label" class="ing-tag_1"> wqq </span>
</div>
<div id="step_input_0" name="step" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true"> This does not contains anything
</div>
<div value="" id="step_input_1" name="step" placeholder="Tell us about step 2" class="recipe-create-text_box_rectangle stepbox step_input" contenteditable="true">
<span style="background-color: red;" data-class="label" class="ing-tag_0" contenteditable="false"> Span1 </span>
Thw color of span 1 in selectable tags needs to change
</div>

I did not get what you're asking for, but as far as I can see, the selector .selectable-tags > span should work fine for direct children. Which you did already.
EDIT:
First of all,
var parentz = document.querySelectorAll('step_input');
this line checks for tags with the name step_input which does not exist in your HTML, there are IDs with step_input_0 for that you'll need to prepare an array of ID by running a loop. Otherwise you can use document.getElementsByName("step")
Again,
You just have to traverse the DOM, to access the span inside divs with name name it would look something like:
const divsWithStep = document.getElementsByName("step");
divsWithStep.forEach((div)=>{
div.querySelector('span').style.backgroundColor="#fafafa";
})
Again, I think you should look up on DOM traversing, let me know.

Related

How to find start and end index of DOM text selection?

In jQuery Terminal I want to add an API that will return indices of the selection.
Example HTML I have:
<div class="cmd" style="width: 100%; --cursor-line:1; top: 0px;">
<div class="cmd-wrapper" style="">
<span class="cmd-prompt" style="visibility: visible; margin-left: 0px;">
<span data-text="> ">
<span style="width: 2ch;">> </span>
</span>
</span>
<div role="presentation" aria-hidden="true" class="cmd-end-line">
<span data-text="H">
<span>H</span>
</span>
<span data-text="e">
<span>e</span>
</span>
<span data-text="l">
<span>l</span>
</span>
<span data-text="l">
<span>l</span>
</span>
<span data-text="o">
<span>o</span>
</span>
<span data-text=" ">
<span> </span>
</span>
<span data-text="W">
<span>W</span>
</span>
<span data-text="o">
<span>o</span>
</span>
<span data-text="r">
<span>r</span>
</span>
<span data-text="l">
<span>l</span>
</span>
<span data-text="d">
<span>d</span>
</span>
<span data-text=" ">
<span> </span>
</span>
</div>
<div class="cmd-cursor-line" role="presentation" aria-hidden="true">
<span>
<span data-text="x">
<span>x</span>
</span>
<span data-text="x">
<span>x</span>
</span>
<span data-text="x">
<span>x</span>
</span>
<span data-text="x">
<span>x</span>
</span>
<span data-text="x">
<span>x</span>
</span>
</span>
<span class="cmd-cursor" style="">
<span data-text="" class="end">
<span> <span></span></span>
</span>
</span>
<span></span>
</div>
</div>
<textarea autocapitalize="off" spellcheck="false" tabindex="1" class="cmd-clipboard" data-cmd-prompt="> " style=""></textarea>
</div>
This is copy-paste of the DOM after entering "Hello World\nxxxxx" and formatted and pretty printed using https://jsonformatter.org/html-pretty-print
My question is what should I do to get the selection indices?
For example, I have a command like this:
> He|lo wor|d
I should get [2, 8] and if the selection is outside of the range: example
>|>> Hello| world
where >>> is prompt I should get [0, 5] I don't care about the negative. I should also handle when the whole selection is outside
|>>>| Hello World
it should return [0, 0] or null.
How would to implement something like this? Note: that I only care about window.getSelection API it's 100% support, not need to be silly and support
IE8.
You want something like
var range = window.getSelection().getRangeAt(0);
var start = range.startOffset;
var end = range.endOffset;
Note that this code assumes that range.startContainer === range.endContainer (which it often does). If you want to get the text / the length of the text between the start and the end containers, you need to recursively traverse the DOM between them. There is also an issue where the length of the text in the DOM is not the same as the length of the text in HTML (browsers sometimes add spaces and other HTML elements)
You'd be right if you guessed that I've worked a bunch in Javascript with selections. IMO it's kind of a nightmare. Tim Down has written a very popular package called Rangy which I recommend it a lot. You should check it out and see if it meets the requirements of what you are doing.
I've solved the issue myself:
var selection = window.getSelection();
var start = $(selection.anchorNode);
var end = $(selection.focusNode);
var before = start.closest('.cmd [role="presentation"]').prevUntil('.cmd-prompt');
var count = 0;
if (before.length > 1) {
count = before.find('[data-text]').length;
}
var s = start.closest('.cmd [role="presentation"] [data-text]');
var e = end.closest('.cmd [role="presentation"] [data-text]');
if ((s.length || e.length)) {
start = count + s.index();
end = count + e.index() + 1;
console.log({start, end});
}

Changing CSS values with checkbox and javascript

I am trying to hide and display a div based on the state of a checkbox using javascript but I don't seem to be getting it right. I am not very experienced with js so I could be missing something very obvious. Any advice would be much appreciated. the target div is the on-toggle div in the second half of the html code.
var checkbox = document.querySelector("input[name=toggle]");
checkbox.addEventListener( 'change', function() {
if(this.checked) {
document.getElementById("on-toggle").style.display = "block";
document.getElementById("on-toggle").style.height = "auto";
} else {
document.getElementById("on-toggle").style.display = "none";
document.getElementById("on-toggle").style.height = "0";
}
<div id="switch">
<h2 id="CTA-switch">Turn creativity on </h2>
<div class="switch">
<input type="checkbox" name="toggle">
<label for="toggle">
<i class="bulb">
<span class="bulb-center"></span>
<span class="filament-1"></span>
<span class="filament-2"></span>
<span class="reflections">
<span></span>
</span>
<span class="sparks">
<i class="spark1"></i>
<i class="spark2"></i>
<i class="spark3"></i>
<i class="spark4"></i>
</span>
</i>
</label>
</div>
</div>
<div id="on-toggle">
<div id="references">
<h1>REFERENCE SITES</h1>
</div>
</div>
</div>
You'll need to grab an actual element so your javascript code works. The id "on-toggle" does not currently exist on any element on your html code.

How to edit HTML value if its in a class that cointains a specific href with javascript?

Well I am learning javascript and I am trying to write a function which would look if(href.contains(1234567) and change class="price" value to any number.
I tried googling but I cant seem to find an answer to this
<div class="product-info">
<a href="https:someUrl.com/1234567">
<div class="title">
Some Sweet Title
</div>
</a>
<div class="price">
ValueHereNeedsToBeAdded
</div>
</div>
I expect class="price" value to be changed to some number
You can use the a[href*=1234567]+.price selector to do it.
a[href*=1234567] select all <a> elements that have a href attribute value containing "1234567" and +.price select element has class price placed immediately after that a[href*=1234567].
Demo:
$('a[href*=1234567]+.price').text(123456)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-info">
<a href="https:someUrl.com/1234567">
<div class="title">
Some Sweet Title
</div></a>
<div class="price">
ValueHereNeedsToBeAdded
</div>
</div>
<a href="https:someUrl.com/test">
</a>
<div class="price">
ValueNoNeedsToBeAddedHere
</div>
A solution with jQuery:
function myFunction() {
var str = $('#link').attr('href');
if (str.indexOf("1234567") >= 0){
var x = document.getElementsByClassName("price");
var y = x[0];
y.classList.add('myClass');
y.classList.remove('price');
y.innerHTML = "123456"
}
}
myFunction();
.myClass{
background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-info">
<a id="link" href="https:someUrl.com/1234567">
<div class="title">
Some Sweet Title
</div>
</a>
<div class="price">
ValueHereNeedsToBeAdded
</div>
</div>
You can do without jquery :-
<div class="product-info">
<a href="https:someUrl.com/1234567" id="link_id" onclick="check(this.href)">
<div class="title">
Some Sweet Title
</div></a>
<div class="price" id="setvalue">
ValueHereNeedsToBeAdded
</div>
</div>
function check()
{
event.preventDefault();
var href = document.getElementById("link_id").getAttribute("href");
if(href.includes(1234567))
{
document.getElementById('setvalue').innerHTML = '1313133';
}
}

javascript array from existing divs innerHTML

Let's say i create dynamically some divs, each has it's dynamically created id (div0, div1, div2, etc.) and i'd like with a function to pass through currently existent divs and put their innerHTML into an array (one, two, three in this case), how can i achieve this in javascript?
html example:
<div contenteditable="false" id="div0">
one
<span id="one-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div1">
two
<span id="two-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div2">
three
<span id="three-close">
<i class="material-icons">close</i>
</span>
</div>
You could also use spread syntax
const divsContents = [...document.querySelectorAll("div>a")].map(e=>e.innerHTML);
console.log(divsContents);
<div contenteditable="false" id="div0">
one
<span id="one-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div1">
two
<span id="two-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div2">
three
<span id="three-close">
<i class="material-icons">close</i>
</span>
</div>
Using some magic from here, because document.querySelectorAll returns a NodeList and not an array, we can get the div elements into an array and use .map() to return the div content into an array.
var divs = [].slice.call(document.querySelectorAll('div'));
console.log(divs.map(div => div.innerHTML));
<div contenteditable="false" id="div0">
one
<span id="one-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div1">
two
<span id="two-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div2">
three
<span id="three-close">
<i class="material-icons">close</i>
</span>
</div>
Ideally you should be using a selector like #divcontainer > div to fetch all the divs in the container, but if you know all the ID's, you can use a selector such as:
document.querySelectorAll('#div0, #div1, #div2')
you can use jquery or javascript function for get your div:
myArray[0] = document.getElementByID("div0").innerHtml;
myArray[1] = document.getElementByID("div1").innerHtml;
myArray[2] = document.getElementByID("div2").innerHtml;
Give same class to divs and access by $('.class-name') or add a container div and get your div array by $('#divId div').
Use a loop after creating a divs collection using querySelectorAll:
let divs = document.querySelectorAll('div');
let arr = [];
for (let i = 0; i < divs.length; i++) {
arr.push(divs[i].innerHTML);
}
console.log(arr);
<div>hi</div>
<div>hi2</div>
<div>hi3</div>
Here is your solution
var arr = [];
function myFunction() {
var anchors = document.getElementsByTagName("a");
for(var i = 0; i < anchors.length; i++){
arr.push(anchors[i].text);
}
}
console.log(arr);
So many ways of doing this. Yet an other way: using ES6 Array.from
let divsA = Array.from(document.querySelectorAll("[id^='div'] a"));
divsA.map(a => console.log(a.innerHTML));
<div contenteditable="false" id="div0">
one
<span id="one-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div1">
two
<span id="two-close">
<i class="material-icons">close</i>
</span>
</div>
<div contenteditable="false" id="div2">
three
<span id="three-close">
<i class="material-icons">close</i>
</span>
</div>

Get value of a span inside the div when other span is clicked

Here is the structure that I have:
<div class="div1">
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text</span>
</span>
</div>
Question that I have when I click on the span2, is how to pick up via alert for example text of span3?
jQuery
$('.span2').on('click', function() {
var $span3 = $(this).closest('.span1').find('.span3');
console.log($span3.text());
});
Check Fiddle
Vanilla JS
let span2 = document.querySelectorAll('.span2');
Array.from(span2).forEach(function(elem) {
elem.addEventListener('click', function() {
let span3 = this.parentNode.querySelector('.span3');
console.log(span3.innerHTML);
});
});
Check Fiddle
You would need to target the closest parent which is span1 here that contains span3 and then get the text of that element.
Since you're using jQuery you've several choices so you could use .parents() or .siblings() or .next() or also closest() (as shown in Sushanth's answer), to target the related .span3 span :
$('.span2').on('click', function(){
$(this).parents('.span1').find('.span3').text();
//Or
$(this).siblings('.span3').text();
//Or
$(this).next('.span3').text();
})
Hope this helps.
$('.span2').on('click', function(){
console.log( $(this).parents('.span1').find('.span3').text() );
//Or
console.log( $(this).siblings('.span3').text() );
//Or
console.log( $(this).next('.span3').text() );
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div1">
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text</span>
</span>
</div>
Edit: Changed it if there are mutliple sets.
Here's a JavaScript example using .nextElementSibling property:
SNIPPET
var d1 = document.querySelector('.div1');
d1.addEventListener('click', function(e) {
var txt = e.target.nextElementSibling.textContent;
alert(txt);
}, false);
.span2 {
border: 1px solid black;
}
.span3 {
pointer-events: none
}
<div class="div1">
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text 1</span>
</span>
<br>
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text 2</span>
</span>
<br>
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text 3</span>
</span>
<br>
<span class="span1">
<span class="span2">X</span>
<span class="span3">some text 4</span>
</span>
</div>

Categories

Resources