Parse numbers from single digit html elements - javascript

I would like to find numbers on websites which have a specific digit length.
Finding normal numbers is easy, but I would also like to find numbers where the digits are separated into multiple HTML elements and also on different nesting levels.
I think one way would be to go down the tree to the last elements, check if it's a number and go up for x levels and check if the pattern repeats, extract the numbers. But I'm not sure how to find out if an element is on it's last branch.
I guess there is also leaner solution. Maybe someone has a better idea?
const body = `
<body>
<div id="not-enogh-digits>
213
</div>
<div id="normal-number>
1235345
</div>
<div id="one-level-child-elements">
<span>1</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>7</span>
</div>
<div id="multi-digit-elements">
<span>12</span>
<span>42</span>
<span>62</span>
</div>
<section>
<div id="multi-level-child-elements">
<span>
<b>
1
</b>
</span>
<span>
<b>
3
</b>
</span>
<span>
<b>
4
</b>
</span>
<span>
<b>
5
</b>
</span>
<span>
<b>
7
</b>
</span>
<span>
<b>
8
</b>
</span>
</div>
</section>
</body>
`;
const getNumbers = (minimumDigits, maxLevelsUp) => {
const matches = [];
// get easy numbers
const easyNumbersRegex = />.*[\t\n\r\s]*(\d+)[\t\n\r\s]*.*<\//g;
const regexResult = body.matchAll(easyNumbersRegex);
const easyNumbers = Array.from(regexResult);
easyNumbers.map((number) =>
number.length >= minimumDigits ? matches.push(number[1]) : null
);
// get multi level numbers
return matches;
};
console.log(getNumbers(2, 2));
Output:
[213, 1235345, 124262, 134578]

Related

How do I remove all of the nested span tags within a span tag in javascript?

I have innerHTML that looks like this:
<span class="test"> <span> </span> Hello I am here <span class="test1"> </span> </span>
I want to remove all of the nested span tags so that I get this:
<span class="test"> Hello I am here </span>
I have tried using .replace('', '').replace('', '') in but would have to check the last span somehow and also there could be different spans that are dynamically being made from google docs so it would be better if I could do a replace on all of the spans that is not the first or last span.
Try This
$('.test').find('span').remove()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="test"> <span>dummy data </span> Hello I am here <span class="test1"> dummay data</span> </span>
This will work
"use strict";
const elm = document.querySelector(".test");
elm.innerHTML = elm.innerText;
console.log(elm.outerHTML);
<span class="test"><span> </span> Hello I am here <span class="test1"> </span> </span>
Use this code to get rid of any empty span elements.
const allSpan = document.querySelectorAll("span");
allSpan.forEach(item => {
if(item.childElementCount === 0 && item.textContent.trim().length === 0){
item.parentElement.removeChild(item)
}
})
<span class="test">
<span> </span> Hello I am here <span class="test1"> </span>
</span>;
You can see the result by inspecting the code in the browser
You can do this by setting the outer span's textContent to it's own textContent - because reading an element's textContent doesn't return any markup tags intersperse with the text.
Resetting textContent also avoids the content of text being parsed by the HTML parser, as it would if used to set the outer element's innerHTML property.
"use strict";
let testSpan = document.querySelector(".test");
testSpan.textContent = testSpan.textContent;
console.log( testSpan.outerHTML);
<span class="test"><span> </span> Hello I am here <span class="test1"> </span> </span>
If you wanted to you could replace consecutive whitespace characters witha single space character before assigning back textContent.

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});
}

map multiple div elements into array

Faced with mapping problem, it returns for me a blank array with two empty elements. Having a button where on click it gets related div block, then I'm trying to get type and number and push them into array. What I am doing wrong here?
<div class="chapter">
<div class="span">
<div class="contact">
<span class="type">
2
</span>
<span class="number">
1111111111
</span>
</div>
<div class="contact">
<span class="type">
4
</span>
<span class="number">
33333333333
</span>
</div>
</div>
</div>
function func(el) {
let block = $(el).closest("div.chapter")
let arr = $(block.find('.contact')).map(function () {
let val = $(this).find('.type, .number').val();
return val;
}).get();
console.log(arr) //result: ["", ""]
}
The .val() method is primarily used to get the values of form elements such as input, select and textarea. You need to use text() method for this, as text() string containing the combined text of matched elements.
Using .val() on span element:
console.log( $('.type').val() )
// Return empty string
console.log( typeof $('.type').val() )
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="type">2</span>
Using .text() on span element:
console.log( $('.type').text() )
// Returns '2'
console.log( typeof $('.type').text() )
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="type">2</span>
Also call them individually for each element like this:
let arr = block.find('.contact').map(function() {
let type = $(this).find('.type').text().trim();;
let number = $(this).find('.number').text().trim();;
return { type, number};
}).get();
This will return you array of objects, where each object has text content of type & number class elements.
DEMO:
let arr = $('.span').find('.contact').map(function() {
let type = $(this).find('.type').text().trim();
let number = $(this).find('.number').text().trim();
return { type, number};
}).get();
console.log( arr )
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="span">
<div class="contact">
<span class="type">
2
</span>
<span class="number">
1111111111
</span>
</div>
<div class="contact">
<span class="type">
4
</span>
<span class="number">
33333333333
</span>
</div>
</div>
Your code does not match with the HTML markup you have provided. You can simply loop through all the element with class contact and find the element inside with specific class to from the object.
Please Note: The span element does not have the value property, you have to use .text().
function func() {
let arr = $('.contact').map(function () {
return {
type: +$(this).find('.type').text().trim(), //find text and convert to number using +
number: +$(this).find('.number').text().trim()//find text and convert to number using +
}
}).get();
console.log(arr);
}
func();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="span">
<div class="contact">
<span class="type">
2
</span>
<span class="number">
1111111111
</span>
</div>
<div class="contact">
<span class="type">
4
</span>
<span class="number">
33333333333
</span>
</div>
</div>
you can use simple JavaScript it's easy!
document.querySelectorAll(".contact").forEach((elm)=>{
arr=[] ;
arr.push(elm.children[0].innerText);
arr.push(elm.children[1].innerText);
console.log(arr)
})

Trim all characters except numbers

Im trying to get the percentage from two numbers. If you loook at the fiddle it works with the first number. For the second numbers I need to trim the first number a bit more, but unsure how.
The first number works.
The second number needs a regex that removes spaces and characters after the numbers.
The third one needs a regex that removes the comma in between numbers , and all characters after the dot.
The fourth one needs a regex that removes the characters before the numbers, the comma between numbers and the dot and all characters behind
How do I write it so it works in all cases? Whatever I try just brakes one or the others.
Fiddle:
https://jsfiddle.net/28dL2fvp/5/
Script:
$('.left').each(function() {
var frstCol = parseInt($(this).find('em.price.product-card-price').text().trim().replace(/[€\.]/g, ''), 10);
var seCol = parseInt($(this).find('em.price.product-card-price.before').text().trim(), 10);
var result = (frstCol / seCol) * 100;
$(this).find('a.pricebubble').text(parseInt(result)|| 0);
});
HTML:
<div class="left">
<em class="price product-card-price">
€1.019 // should count as 1019
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
1519
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
5 995:- // should count as 5995
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
987
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
11,823.00SEK // should count as 1183
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
1987
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
SEK11,823.00 // should count as 1183
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
1987
</em>
<a class="pricebubble"></a>
</div>
Replacing all but numeric characters
str.replace(new RegExp("[^0-9.]","gm"),"your string");
Suppose you have this string:
var str ="dsfdsf7834hf3876gfergh"
Then, str.replace(new RegExp("[^0-9.]","gm"),"foo");
will return "foofoofoofoofoofoo7834foofoo3876foofoofoofoofoofoo"
Try something like:
str.replace(/[\D]/g, '');
Please try this: (https://jsfiddle.net/28dL2fvp/6/)
$('.left').each(function() {
var frstCol = parseInt($(this).find('em.price.product-card-price').text().replace(/[^0-9.]/g, "").replace(/\.[0-9]*/, ""), 10);
var seCol = parseInt($(this).find('em.price.product-card-price.before').text().replace(/[^0-9.]/g, ""), 10);
var result = (frstCol / seCol) * 100;
console.log("frstCol: ", frstCol, ", seCol: ", seCol);
$(this).find('a.pricebubble').text(parseInt(result)|| 0);
});

I have 2 price values and I want to calculate the difference

I have 2 price range. Regular Price and Offer Price displayed on screen with the below HTML rendered.
I am trying to calculate the price difference using Javascript/jquery and insert a div with the discount price.
<div class="price-box">
<p class="old-price">
<span class="price-label">Regular Price:</span>
<span class="price" id="old-price-221">Rs17.00 </span>
</p>
<p class="special-price">
<span class="price-label">Special Price</span>
<span class="price" id="product-price-221">Rs14.45 </span>
</p>
<div>
<span>Discount Price:</span>
<span>XXXXXX</span>
</div>
</div>
I have this currency symbol also displayed along with the price. So, I am wondering how to calculate the difference between "Regular Price" and "Special Price".
Can some one please help me?
P.S. I searched the site and did not find the relevant answers.
There it is : http://jsfiddle.net/s7w98ngt/2/
jQuery part :
$('.price-box').each(function(){
var element = $(this),
oldPriceRaw = element.find('.old-price .price').text(),
specialPriceRaw = element.find('.special-price .price').text(),
oldPrice = parseFloat(oldPriceRaw.replace('Rs','')),
specialPrice = parseFloat(specialPriceRaw.replace('Rs','')),
diff = 'Rs'+(oldPrice - specialPrice).toFixed(2), // 2 numbers after the comma
diffElement = element.find('.diff-price');
diffElement.text(diff);
});
HTML a bit modified :
<div class="price-box">
<p class="old-price">
<span class="price-label">Regular Price:</span>
<span class="price" id="old-price-221">Rs17.00 </span>
</p>
<p class="special-price">
<span class="price-label">Special Price</span>
<span class="price" id="product-price-221">Rs14.45 </span>
</p>
<div>
<span>Discount Price:</span>
<span class="diff-price"></span>
</div>
</div>
The tricky thing was to get the current prices value as float numbers. Then, we just calcul the difference.

Categories

Resources