Why function 'runFunc("keyboard", "mouse")' change only three Classes - javascript

In this code, I made a function runFunc(previousClass, newClass) for changing class but only three classes changes by clicking a button. Why should we click button three times to change all the classes.
<div class="parent_class" id="parent">
<div class="keyboard">1</div>
<div class="keyboard">2</div>
<div class="keyboard">3</div>
<div class="keyboard">4</div>
<div class="keyboard">5</div>
<div class="keyboard">6</div>
</div>
<br><br>
<button onclick="runFunc('keyboard', 'mouse')">Change Class</button>
<script>
var a;
function runFunc(previousClass, newClass) {
var i;
var a1 = typeof previousClass;
var a2 = typeof newClass;
if (a1 === "string" && a2 === "string") {
var a = document.getElementsByClassName(previousClass);
console.log(a);
for ( i = 0; i < a.length; i++ ) {
a[i].className = newClass;
}
var b = document.getElementsByClassName(newClass);
console.log(b);
console.log("\n\n")
}
}
</script>
</body>

It's because when you are replacing classname in first element it's automatically removed from the list, so the "old" second element become now first, but your loop advances forward and skips "old" second element and so on.
So what you can do is simply keep changing classname in first element until the list is empty:
var a;
function runFunc(previousClass, newClass) {
var i;
var a1 = typeof previousClass;
var a2 = typeof newClass;
if (a1 === "string" && a2 === "string") {
var a = document.getElementsByClassName(previousClass);
console.log(a);
while (a.length)
{
a[0].className = newClass;
}
var b = document.getElementsByClassName(newClass);
console.log(b);
console.log("\n\n")
}
}
<div class="parent_class" id="parent">
<div class="keyboard">1</div>
<div class="keyboard">2</div>
<div class="keyboard">3</div>
<div class="keyboard">4</div>
<div class="keyboard">5</div>
<div class="keyboard">6</div>
</div>
<br><br>
<button onclick="runFunc('keyboard', 'mouse')">Change Class</button>

Related

How to find/remove last text portion of innerHTML

I have a <div> element that contains both html elements and text. I want to find/remove the last or the last nth or the nth text only portion of it.
So for example
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I had a method to delete the last text character, the first call would delete z and the second call would delete g. Or if I had a method to find the 4th character, it would return d.
It sounds like you only care about the text nodes, so probably something like this so you can just delete the nth character:
var div = document.getElementById("foo");
const getTextNodes = (el, nodes) => {
nodes = nodes || [];
for (var i = 0; i < el.childNodes.length; i++) {
var curNode = el.childNodes[i];
if (curNode.nodeName === "#text") {
if (curNode.textContent.trim().length) {
nodes.push(curNode);
}
} else {
getTextNodes(curNode, nodes);
}
}
return nodes;
}
console.log(getTextNodes(div).map((el) => el.textContent));
const deleteNthCharacter = (el, n) => {
n--; // since we want to be "1 indexed"
const nodes = getTextNodes(el);
let len = 0;
for (let i = 0; i < nodes.length; i++) {
const curNode = nodes[i];
if (len + curNode.textContent.length > n) {
curNode.textContent = curNode.textContent.substring(0, n - len) + curNode.textContent.substring(n + 1 - len);
break;
} else {
len += curNode.textContent.length;
}
}
}
deleteNthCharacter(div, 2);
deleteNthCharacter(div, 7);
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understood your question correctly this should do the trick:
function deleteLastChar(targetId){
const target = document.getElementById(targetId);
let lastWithText = -1;
//find last child that has text set
target.childNodes.forEach((child, iter) => {
if(child.innerText != undefined && child.innerText.length > 0){
lastWithText = iter;
}
});
// exit if no valid text node was found
if(lastWithText === -1)
return;
const lastNode = target.childNodes[lastWithText];
lastNode.innerText = lastNode.innerText.slice(0, -1);
}
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understand the question this is probably what you're looking for
let x = document.getElementById('foo').children;
function erase() {
for (let i = x.length - 1; i >=0; i--) {
if(x[i].textContent.length > 0) {
const textC = x[i].textContent;
x[i].textContent = textC.substring(0, textC.length - 1);
return;
}
}
}
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
<button onclick="erase()">Erase</button>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="foo">
<span id="bar">abcdefg</span><br>
<span id="baz">z</span><br><br>
<div id="result"></div>
<div id="result2"></div>
</div>
<script type="text/javascript">
var s = function(x){
return document.querySelector(x)
}
log = console.log;
var span1 = s("#bar")
var span2 = s("#baz")
var result = s("#result")
var result2 = s("#result2")
var res = span1.innerText.charAt(4)
// with the charAt method
result.innerText = " Result is : " +res+"\n\n"
// with regular Expression
var reg = /e/
result2.innerText = " Result2 is : " +span1.innerText.match(reg)
</script>
</body>
</html>

append method is not working in for loop

I have multiple json object and each object have multiple same, For example:
A->
- A1
-A1A
-A1A
- A2
-A2A
-A2A
- A3
-A3A
-A3A
I have tired to execute in below code but it's not working. Can you please suggest me what is the issue in my code?
subscriptionbarMyData = JSON.parse(window.localStorage.getItem('subscriptionBarJson'));
$('.total-month-cost-product-header-names').text('').addClass('hidden');
for (var key in subscriptionbarMyData) {
if (subscriptionbarMyData.hasOwnProperty(key)) {
var val = subscriptionbarMyData[key];
$('.total-month-cost-product-header')
.find('.total-month-cost-product-header-names')
.removeClass('hidden')
.addClass('show')
.text(val.Name + val.ProductPrice);
var addonvalue = subscriptionbarMyData[key]["Add-on"];
for (var keyval in addonvalue) {
if (addonvalue != undefined) {
var TotalOneCostProduct = $('.total-month-cost-product-items').text('');
for (var keyval in addonvalue) {
// var dataValues = addonvalue[keyval].Name;
$('.total-month-cost-product-header-names')
.text(addonvalue[keyval].Name)
.appendTo(TotalOneCostProduct);
}
}
}
}
}
<div class="summary-block">
<div class="total-month-cost-summary">
<div class="total-month-cost-product-header">
<div class="total-month-cost-product-header-names"></div>
<div class="total-month-cost-product-header-price"></div>
</div>
<div class="total-month-cost-product-items">
<div class="total-month-cost-product-item-names"></div>
<div class="total-month-cost-product-item-price"></div>
</div>
</div>
</div>

Get DOM path from a node to another

I need a method that, taken as parameters two nodes (node1 and node2), returns the minimum path that leads to node2 from node1.
Ideally, it returns an array of nodes, but for the moment it's OK to a string. So for example:
P
/ \
#text U
/ \
B I
| |
#text #text
function foo(node1, node2) {
...
}
when I run it in this way, for example on the nodes P (root) and B:
var res = foo(P, B);
console.log(res);
I obtain:
res = Array[3] {
0: P (class=..., id=...)
1: U (class=..., id=...)
2: B (class=..., id=...)
}
or, in the form of string:
res = "P(class=..., id=...) > U(class=..., id=...) > B(class=..., id=...)";
If the nodes have attributes (such as id or class), then returns even those (as in the example).
I searched the internet methods that did similar things but I found only methods that return the full path of the entire document and not between two nodes.
For example, I tried this method doesn't work for me because it returns the full path of a single node.
function getDomPath(el) {
var stack = [];
while ( el.parentNode != null ) {
console.log(el.nodeName);
var sibCount = 0;
var sibIndex = 0;
for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
var sib = el.parentNode.childNodes[i];
if ( sib.nodeName == el.nodeName ) {
if ( sib === el ) {
sibIndex = sibCount;
}
sibCount++;
}
}
if ( el.hasAttribute('id') && el.id != '' ) {
stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
} else if ( sibCount > 1 ) {
stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
} else {
stack.unshift(el.nodeName.toLowerCase());
}
el = el.parentNode;
}
return stack.slice(1); // removes the html element
}
Another thing, I would use pure JavaScript, no jQuery.
I have no idea how to do what I need, a your help would be greatly appreciated.
Thank you
<!DOCTYPE html>
<html>
<script>
window.onload = function() {
console.log(min_path(
document.getElementById("4"),
document.getElementById("9")
));
};
function min_path(node1, node2) {
if(node1 === node2) {
return node1;
}
var node_1_ancestors = get_ancestors(node1);
var node_2_ancestors = get_ancestors(node2);
var divergent_index = 0;
while(node_1_ancestors[divergent_index] === node_2_ancestors[divergent_index]) {
divergent_index++;
}
var path = [];
for(var i = node_1_ancestors.length - 1; i >= divergent_index - 1; i--) {
path.push(node_1_ancestors[i]);
}
for(var i = divergent_index; i < node_2_ancestors.length; i++) {
path.push(node_2_ancestors[i]);
}
return path;
}
function get_ancestors(node) {
var ancestors = [node];
while(ancestors[0] !== null) {
ancestors.unshift(ancestors[0].parentElement);
}
return ancestors;
}
</script>
</head>
<body>
<div id="0">
<div id="1">
<div id="2">
<span id="3"></span>
<span id="4">node1</span>
</div>
<div id="5">
<p id="6"></p>
<span id="7">
<div id="8">
<div id="9">node2</div>
<div id="10"></div>
</div>
</span>
</div>
</div>
<div id="11"></div>
</div>
</body>
</html>
Edit: It was going in to an infinite loop when the nodes were equal, so I added a check for that.

javascript/jquery to replace text conditionally with random text from an array

I would like to replace a string with a random string from an array if that string equals a certain condition.
So far I have this (which doesn't address the condition part).
the html:
<div>
<span class ="test">foo</span>
</div>
<div>
<span class ="test">bar</span>
</div>
<div>
<span class ="test">test</span>
</div>
<div>
<span class ="test">random</span>
</div>
the code:
$(".test").each(function () {
var quotes = new Array("foo", "bar", "baz", "chuck"),
randno = quotes[Math.floor(Math.random() * quotes.length)];
$('.test').text(randno);
});
This sets every ".test" class the same thing. I get:
foo
foo
foo
foo
or
bar
bar
bar
bar
How do I make this only replace the string if it equals say "foo"?
If I have multiple "foos" How do i get each "foo" it replaces to be random not all set to the same thing?
You need to use this in the .each() callback method
$(".test").each(function() {
var quotes = new Array("foo", "bar", "baz", "chuck"),
randno = quotes[Math.floor(Math.random() * quotes.length)];
//Check condition
if ($(this).text() === "foo") {
$(this).text(randno);
}
});
Alternatively you can also use .text(function)
var quotes = new Array("foo", "bar", "baz", "chuck");
$(".test").text(function(_, text) {
var randno = quotes[Math.floor(Math.random() * quotes.length)];
//Check condition
if (text === "foo") {
return randno;
}
return text;
});
$(function() {
var quotes = new Array("foo", "bar", "baz", "chuck");
$(".test").text(function(_, text) {
var randno = quotes[Math.floor(Math.random() * quotes.length)];
//Check condition
if (text === "foo") {
return randno;
}
return text;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span class="test">foo</span>
</div>
<div>
<span class="test">bar</span>
</div>
<div>
<span class="test">test</span>
</div>
<div>
<span class="test">random</span>
</div>
Another approach is to shuffle the replacements array, than use it:
/* Famous shuffle function */
Array.prototype.shuffle = function() {
for (var j, x, i = this.length; i; j = Math.floor(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
return this;
};
$.fn.extend({
randomReplace: function(text, replacements) {
replacements.shuffle();
return this.each(function () {
if( $(this).text().toLowerCase()==text.toLowerCase() )
$(this).text(replacements.pop());
});
}
});
$('.test').randomReplace('foo', ['one', 'two', 'three', 'four', 'five', 'six']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="test">foo</span>
<span class="test">bar</span>
<span class="test">foo</span>
<span class="test">foo</span>
<span class="test">bar</span>

Get a PACK OF ELEMENTS with the same class prefix and/or same suffix and then update this PACK

Let's have an example:
<div class="gg-1"></div> // 1
<div class="gg-1"></div> // 1
<div class="gg-1"></div> // 1
<div class="gg-3"></div> // 3
<div class="gg-3"></div> // 3
<div class="gg-5"></div> // 5
<div class="gg-5"></div> // 5
How could I update those divs classes to get the below result?
<div class="gg-1"></div> // 1
<div class="gg-1"></div> // 1
<div class="gg-1"></div> // 1
<div class="gg-2"></div> // 2
<div class="gg-2"></div> // 2
<div class="gg-3"></div> // 3
<div class="gg-3"></div> // 3
Pure Javascript needed (JQuery as additional).
My function below could help you in getting elements by class with a prefix:
function scn$(container,selectorTag,prefix) {
var items = [], myPosts = document.getElementById(container).getElementsByTagName(selectorTag);
for (var i = 0; i < myPosts.length; i++) {
// Omit Undefined Null Check
if (myPosts[i].className.lastIndexOf(prefix,0) === 0) {
items.push(myPosts[i]);
}
}
return items;
}
So for now we can select our elements by scn$('container','div','gg-').
What's next? Any ideas/clues?
Try below approach and let me know,
DEMO: http://jsfiddle.net/pmc3g/
(function() {
function scn$(container, selectorTag, prefix) {
var items = [],
myPosts = document.getElementById(container).getElementsByTagName(selectorTag);
var prevClass = null, curVal = 0;
for (var i = 0; i < myPosts.length; i++) {
var curClass = myPosts[i].className;
// Omit Undefined Null Check
if (curClass.lastIndexOf(prefix, 0) === 0) {
if (prevClass != curClass) {
prevClass = curClass;
curVal++;
}
myPosts[i].className = prefix + curVal;
items.push(myPosts[i]);
console.log(myPosts[i].className);
}
}
return items;
}
scn$('container', 'div', 'gg-');
})();

Categories

Resources