Javascript search with includes for each DIV - javascript

I am trying to develop a filter function with includes. As for now, I have 3 main DIV, and each main DIV has its own DIV. The current script I have now only worked on main DIV.
Instead of highlighting main DIV, I only want to highlight matched char DIV.
For example, when key in 'inner', Inner First and Inner Sec will be highlighted. When key in 'Inner First', only DIV for Inner First will be highlighted.
Would appreciate if anyone of you can help me. Thanks in advance.
function myFunction() {
var input = document.getElementById("Search");
var filter = input.value.toLowerCase();
var nodes = document.getElementsByClassName('target');
for (i = 0; i < nodes.length; i++) {
nodes[i].style.backgroundColor = "";
if (input.value !== '') {
if (nodes[i].innerText.toLowerCase().includes(filter)) {
nodes[i].style.backgroundColor = "blue";
for (j = 0; j < nodes[i].length; j++) {
nodes[j].style.backgroundColor = "";
if (input.value !== '') {
if (nodes[j].innerText.toLowerCase().includes(filter)) {
nodes[j].style.backgroundColor = "grey";
for (k = 0; k < nodes[j].length; k++) {
nodes[k].style.backgroundColor = "";
if (input.value !== '') {
if (nodes[k].innerText.toLowerCase().includes(filter)) {
nodes[k].style.backgroundColor = "yellow";
} else {
nodes[k].style.backgroundColor = "red";
}
}
}
} else {
nodes[j].style.backgroundColor = "red";
}
}
}
} else {
nodes[i].style.backgroundColor = "red";
}
}
}
}
<table align="center" width="20%">
<tr>
<td style="padding-right: 10px">
<input type="text" id="Search" title="Type in a name">
<button onclick="myFunction()">
Click to search
</button>
</td>
</tr>
</table>
<br>
<div class="target">
This is my DIV element.
<div class="target">
Inner First
<div class="target">
Inner Sec
</div>
</div>
</div>
<div class="target">
This is another Div element.
</div>
<div class="target">
Can you find me?
</div>

The problem with your code is that node.innerText also gives the text of the child elements. To fix this, you should use node.childNodes[0].nodeValue which will only give the node's text.
Moreover, you are doing nested loops but referencing incorrectly:
for (j = 0; j < nodes[i].length; j++).
nodes[i].length here is undefined. Maybe you mean nodes[i].children.length?
Also, your code is hard to follow with all the nested loops which does the same thing and just differ in color. I suggest you make a recursive function.
Please see below function if I what I'm thinking is correct. I guess you wanted to put different colors depending of the level of the node in the heirarchy. (Open your developer tool to see console.log outputs)
var input;
var filter;
var nodes;
var colors;
function myFunction() {
//initialize variables
input = document.getElementById("Search");
filter = input.value.toLowerCase();
nodes = document.getElementsByClassName('target');
// store colors here for accessing via index
colors = ['blue', 'grey', 'yellow', 'green'];
if (filter !== '') {
updateNodesBg(nodes); //neat
}
}
function updateNodesBg(lNodes, colorIdx) {
colorIdx = colorIdx || 0; // this will be the index of the color
for (var i = 0; i < lNodes.length; i++) {
var currentNode = lNodes[i];
var currentText = currentNode.childNodes[0].nodeValue;
var innerText = currentNode.innerText;
console.log('currentText and innerText EQUAL?', currentText === innerText);
if (currentText.toLowerCase().includes(filter)) {
currentNode.style.backgroundColor = colors[colorIdx]; //pass in the index to get the color
} else {
currentNode.style.backgroundColor = 'red'; //else, we should color red
}
if (currentNode.children && currentNode.children.length > 0) {
updateNodesBg(currentNode.children, colorIdx + 1); //if the node has children, call `updateNodesBg` recursively
}
}
}
<table align="center" width="20%">
<tr>
<td style="padding-right: 10px">
<input type="text" id="Search" title="Type in a name">
<button onclick="myFunction()">
Click to search
</button>
</td>
</tr>
</table>
<br>
<div class="target">
This is my DIV element.
<div class="target">
Inner First 1
<div class="target">
Inner Sec 1
<div>Inner Third 1</div>
</div>
<div class="target">
Inner Sec 2
<div>Inner Third 1</div>
<div>Inner Third 2
<div>Inner Fourth 1</div>
</div>
</div>
</div>
<div class="target">
Inner First 2
<div class="target">
Inner Sec 2
<div>Inner Third 2</div>
</div>
</div>
</div>
<div class="target">
This is another Div element.
</div>
<div class="target">
Can you find me?
</div>
Note that .nodeValue has different returns depending on the type of the node:
Node Value of nodeValue
CDATASection Content of the CDATA section
Comment Content of the comment
Document null
DocumentFragment null
DocumentType null
Element null
NamedNodeMap null
EntityReference null
Notation null
ProcessingInstruction Entire content excluding the target
Text Content of the text node

You need to check if the text is in the current div, then in any child divs.
InnerText and textContent both concatenate text of the parent and all children, so you'll need to figure out where the text is actually coming from.
I do this recursively, because I don't think you'll have that many layers of divs. If there is a lot of nesting, then you'd need to take an iterative approach
function myFunction()
{
let targets = document.querySelectorAll('.target');
targets.forEach(target => target.style.background = 'white');
let filterText = document.getElementById('Search').value;
if(filterText != '')
{
let result = [...targets].filter(target => target.textContent.includes(filterText));
result.forEach(r => { checkSelf(r, filterText); checkKids(r, filterText); });
}
}
function checkSelf(element, filterText)
{
let selfText = element.textContent;
for(let child of element.children)
{
selfText = selfText.replace(child.textContent, '');
}
if(selfText.includes(filterText))
{
element.style.background = 'limegreen';
}
else
{
element.style.background = 'white';
}
}
function checkKids(element, filterText)
{
for(let child of element.children)
{
if(!child.textContent.includes(filterText))
{
child.style.background = 'white';
}
else
{
checkKids(child, filterText);
}
}
}
<table align="center" width="20%">
<tr>
<td style="padding-right: 10px">
<input type="text" id="Search" title="Type in a name">
<button onclick="myFunction()">
Click to search
</button>
</td>
</tr>
</table>
<br>
<div class="target">
This is my DIV element.
<div class="target">
Inner First
<div class="target">
Inner Sec
</div>
</div>
</div>
<div class="target">
This is another Div element.
</div>
<div class="target">
Can you find me?
</div>

Related

Javascript 3 x 3 flexbox with button increasing number

I have a box 2 x 2 using flex property with number 0 inside each box, and a button to click
function click() {
var id = "item-";;
for(var i = 1; i <= 6; i++) {
id = id + i;
var element = document.getElementById(id);
var value = element.innerHTML;
value++;
document.getElementById(id).innerHTML = value;
}
}
<div class="flex-container">
<div class="container-1">
<div id="item-1">0</div>
<div id="item-2">0</div>
<div id="item-3">0</div>
</div>
<div class="container-2">
<div id="item-4">0</div>
<div id="item-5">0</div>
<div id="item-6">0</div>
</div>
</div>
<button class="btn" onclick="click()">Click</button>
I want to create a function click() that if I click a button then the number inside the box will increase, but not all numbers in all boxes. I want the number increasing box by box.
But my function only increases the value in the first box. Can someone let me know what should I do, please?
Currently, first iteration of the for () will work because id will become item-1, but the second iteration you will create the new id, but you just append i, so it becomes item-12 instead of item-2
Just only remember the id and prefix it with item- when you use it. Then after each press, update the innerHTML and increase the counter, or reset to 1 if we've just updated the last <div>
var currentIndex = 1;
function incrementButton() {
let element = document.getElementById('item-' + currentIndex);
element.innerHTML = ++element.innerHTML;
currentIndex = (currentIndex === 6) ? 1 : ++currentIndex;
}
<div class="flex-container">
<div class="container-1">
<div id="item-1">0</div>
<div id="item-2">0</div>
<div id="item-3">0</div>
</div>
<div class="container-2">
<div id="item-4">0</div>
<div id="item-5">0</div>
<div id="item-6">0</div>
</div>
</div>
<button class="btn" onclick="incrementButton()">Click</button>

change the text of every element in a class javascript

How do I change the text of all elements in a class
If the element is in a division do I need to do anything else?
P.S. I hardly know js so plz help.
enter image description here
You can use querySelectorAll and with a foreach set the new text:
const examples = document.querySelectorAll('.example');
examples.forEach(example => {
example.innerHTML = 'new text';
});
<div class="example">
text 1
</div>
<div class="example">
text 2
</div>
I hope these examples can help you
function myFunction()
{
x=document.getElementsByClassName("infoblock"); // Find the elements
for(var i = 0; i < x.length; i++){
x[i].innerText="text changed!"; // Change the content
}
}
function myFunction2()
{
x=document.getElementsByClassName("notationgrade"); // Find the first span elements
y=document.getElementsByClassName("percentgrade"); // Find the second span elements
for(var i = 0; i < x.length; i++){
x[i].innerText="text 1 changed!"; // Change the content
}
for(var i = 0; i < y.length; i++){
y[i].innerText="text 2 changed!"; // Change the content
}
}
<body>
<div class="class-stats fsClassStatsAverage">
<p><span class="infoblock notationgrade">old text 1 </span></p>
<p> <span class="infoblock percentgrade">old text 2</span></p>
</div>
<button type="button" onclick="myFunction()">Change All Spans</button>
<button type="button" onclick="myFunction2()">Change Each Span</button>
</body>

Switching the divs via script in wordpress

I have the following code to switch between 2 divs:
<script>
function SwapDivsWithClick(div1,div2)
{
d1 = document.getElementById(div1);
d2 = document.getElementById(div2);
if( d2.style.display == "none" )
{
d1.style.display = "none";
d2.style.display = "block";
}
else
{
d1.style.display = "block";
d2.style.display = "none";
}
}
var divs = [ "zdroj1", "zdroj2" ];
function toggle(layer) {
var d
for(var i = 0; i < divs.length; i += 1) {
d = document.getElementById(divs[i]);
d.style.display = 'none';
}
d = document.getElementById(layer);
d.style.display = '';
}
</script>
And the HTML part:
<table>
<tbody>
<tr>
<td class="btn" style="text-align: center;"><a href="javascript:toggle('zdroj1')" ><b>VIDEO 1</b></a></div></td>
<td class="btn" style="text-align: center;"><a href="javascript:toggle('zdroj2')" ><b>VIDEO 2</b></a></div></td>
</tr>
</tbody>
</table>
<div id="zdroj1">
VIDEO CODE 1</div>
<div id="zdroj2" style="display:none;">
VIDEO CODE 2</div>
How can I add more divs and show only that one which link is clicked? I think that there must be more if functions in the script but I am not sure, because I am a newbie in this part of coding. Thanks in advance!
Edit: Based on your needs to have a dynamic amount of divs/buttons on each page see the code below. Instead of manually creating the click eventListener you need to get an array(-ish) of the buttons based on a common class name (querySelector could also be used for this) and add the event listener to each. The buttons should be created with a data-attribute (or other identifier) that corresponds to one of the divs you want to toggle.
Inside the function that is called you can loop through all your msg divs, hide them all and unhide the one that matches the data-attribute of the button that was clicked. This method allows you to have any number of buttons and divs as long as each button has a matching div for it to toggle.
// Find all the buttons and divs that have the common className for each
var buttons = document.getElementsByClassName('button')
var divs = document.getElementsByClassName('msg')
function toggle() {
// Loop through the divs and hide them all
for(var i = 0; i < divs.length; i += 1) {
divs[i].style.display = 'none';
}
// Show the div whose id matches the data-message attribute of the button that was clicked
document.getElementById(this.dataset.message).style.display = 'block';
}
// Add a click listener to each button to run the toggle function
for(var i = 0; i < buttons.length; i += 1) {
buttons[i].addEventListener('click', toggle, false)
}
<table>
<tbody>
<tr>
<!-- Add a common class to all buttons and a data-message attribute to each button
that corresponds to the id of the div it will toggle on-->
<td class="btn"><button class="button" data-message="msg1">VIDEO 1</button></td>
<td class="btn"><button class="button" data-message="msg2">VIDEO 2</button></td>
<td class="btn"><button class="button" data-message="msg3">VIDEO 3</button></td>
<td class="btn"><button class="button" data-message="msg4">VIDEO 3</button></td>
</tr>
</tbody>
</table>
<!-- Add a common class to all divs that will be toggled -->
<div class="msg" id="msg1">
VIDEO CODE 1
</div>
<div class="msg" id="msg2" style="display:none;">
VIDEO CODE 2
</div>
<div class="msg" id="msg3" style="display:none;">
VIDEO CODE 3
</div>
<div class="msg" id="msg4" style="display:none;">
VIDEO CODE 4
</div>

Looping Through Classes And Changing Color

I need a little help, this may seem easy, but I have an invert colors button on my webpage, and I would need to loop through elements with the class name of text.
Here's the code:
//Javascript File
var text = document.getElementsByClassName('text');
var button = document.getElementById('invertcolors');
function onClick() {
for (var i = 0; i < text.length; i++) {
//Do something like this:
//text[i].style.color =
}
}
button.addEventListener('click', onClick, false);
<!--Stuff here...-->
<div id="content">
<font id="text1" class="text">I walked in the forest</font>
<br>
<font id="text2" class="text">Through the grey concrete path</font>
<br>
<font id="text3" class="text">Holding on the dog</font>
</div>
<!--Stuff here...-->
I need to loop through the elements in the i variable, and set their color to white. I don't know how, can someone help? Thanks!
Please check the javascript code below:
var text = document.getElementsByClassName('text');
var button = document.getElementById('invertcolors');
function onClick() {
var selectedId
console.log(text[0].getAttribute( 'id' ));
for (var i = 0; i < text.length; i++) {
console.log(text[i].getAttribute('id'));
selectedId = text[i].getAttribute('id');
document.getElementById(selectedId).style.color = "white";
}
}
button.addEventListener('click', onClick, false);
And also check the code # https://jsfiddle.net/cskcvarma/akLx5tt8/7/
Please let me know if this helps.
var text = document.getElementsByClassName('text');
var button = document.getElementById('invertcolors');
function onClick(text) {
for (var i = 0; i < text.length; i++) {
text[i].style.color = '#fff';
}
}
button.addEventListener('click', onClick.bind(null, text), false);
You pretty much have the exact code you would need, see below for a working version of what you wanted.
var text = document.getElementsByClassName('text');
var button = document.getElementById('invertcolors');
function onClick() {
for (var i = 0; i < text.length; i++) {
text[i].style.color = '#f00';
}
}
button.addEventListener('click', onClick, false);
#invertcolors {
height:20px;
width:100px;
border:1px solid black;
border-radius:7px;
}
<div id="content">
<font id="text1" class="text">I walked in the forest</font>
<br>
<font id="text2" class="text">Through the grey concrete path</font>
<br>
<font id="text3" class="text">Holding on the dog</font>
</div>
<div id='invertcolors'>Button</div>
You can use querySelectorAll method to do that. The <font> element is not supported in HTML5 so you should replace it with for example <span> element.
var button = document.getElementById('click');
button.addEventListener('click',function(){
var elements = document.querySelectorAll('.text');
elements.forEach(function(a){
a.style.backgroundColor = 'yellow';
});
});
<div id="content">
<span id="text1" class="text">I walked in the forest</span>
<br>
<span id="text2" class="text">Through the grey concrete path</span>
<br>
<span id="text3" class="text">Holding on the dog</span>
</div>
<br/>
<button id="click">change style</button>

Show one div and hide the previous showing div

I have some links that will show a div when clicking it. When clicking another link, it should show the link's associated div and hide the previously shown div.
HTML
Text 1
Text 2
Text 3
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
Javascript
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
}
CSS
.hidden { display: none; }
.unhidden { display: block; }
How can I accomplish this?
Try with:
function unhide(divID) {
var unhidden = document.getElementsByClassName('unhidden');
for (var k in unhidden) {
unhidden[k].className='hidden';
}
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
}
You can do something like this :
function unhide(divID) {
var divs = document.getElementsByTagName('div');
foreach(var div in divs){
div.className = 'hidden';
if(div.id == divID)
div.className = 'unhidden';
}
}
Be careful with document.getElementsByTagName('div');, it will return you all divs on your document. You could adapt it using a wrapper.
For example :
HTML
<div id="wrapper">
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
</div>
JS :
var divs = document.getElementById('wrapper').getElementsByTagName('div');
Try this http://jsfiddle.net/L79H7/1/:
function unhide(divID) {
var divIds = [ "text1", "text2", "text3" ];
for ( var i = 0, len = divIds.length; i < len; i++) {
var item = document.getElementById(divIds[i]);
if (item) {
item.className = divID == divIds[i] ? 'unhidden' : 'hidden';
}
}
}
You could also store in an array the names of the divs you want to hide and iterate over it when unhiding one:
var divs= new Array("text1", "text2", "text3");
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
for (var i in divs){
if (divs[i] != divID){
item = document.getElementById(divs[i]);
if (item) {
item.className='hidden';
}
}
}
}
JSFiddle
You don't need exactly links for this, but if you insist change it to:
<a href="#" onclick='unhide("text3");'>Text 3</a>
Otherwise you can change it to:
<p onclick="unhide('text1')">Text 1</p>
<p onclick="unhide('text2')">Text 2</p>
<p onclick="unhide('text3')">Text 3</p>
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
And your function should look like this to add or remove classes:
function unhide(id){
yourElement = document.getElementById(id);
if(yourElement.className == "unhidden"){
yourElement.className = "hidden";
}else{
yourElement.className = "unhidden";
}
}
demo
<div id="text1" class="hidden"> 1 </div>
<div id="text2" class="hidden"> 2 </div>
<div id="text3" class="hidden"> 3 </div>
.hidden{ display:none; }
#text1{ display: block; }
function show(id) {
var item = document.getElementById(id);
var all = document.getElementsByClassName('hidden');
for(var i=0; i<all.length; i++)all[i].style.display = 'none';
if(item)item.style.display = 'block';
}
you can use jquery try the code below and import the jquery library first
$('#text1').show();
$('#text2').hide();
it is the easiest way

Categories

Resources