Split string and in some cases remove - javascript

I've got a product title which I'm splitting and inserting a linebreak using javascript like this:
<script>
function myFunction() {
var str = "How are you - doing today?";
var res = str.split("-").join('<br>');
document.getElementById("demo").innerHTML = res;
}
</script>
This works for most case scenarios, however in some cases I will need to remove the second line completely. So everything after the - will need to be removed. Only within that element though, so if I've got this for example
<h3>This is a product - title</h3>
the result should be
<h3>This is a product</h3>
Again this only needs to apply to elements with a certain class. Anybody got any idea ow to do this?

Why not us a simple replace,
string = string.replace(/-/g, '<br>');
or for complete deletion, take
string = string.replace(/-.*$/g, '');

Check className of the element:
function myFunction() {
const str = `How are you - doing today?`
const first = str.split(`-`)[0]
const all = str.split(`-`).join(`<br/>`)
const el = document.getElementById(`demo`)
const el.innerHTML = el.className === `any-name` ? first : all
}

Try this:
(function() {
// For splitted titles
var split = document.querySelectorAll(".dash-split");
var splits = [];
split.forEach(function(spl) {
splits.push(spl.innerHTML.split("-").join("<br>"));
});
console.log(splits); // Outputs ["This is <br> split!"]
// For removed titles
var removedEls = document.querySelectorAll(".dash-split");
var removed = [];
removedEls.forEach(function(rem) {
removed.push(rem.innerText.split("-")[0].trim());
});
console.log(removed); // Outputs ["This is"]
})();
<!DOCTYPE html>
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<div>
<h1 class="dash-split">This is - split!</h1>
<h1 class="dash-remove">This is - removed!</h1>
</div>
</body>
</html>

This should get you what you want, provided the script runs at the end of the document. For wrapping, it keys off of the class title-wrap.
<html>
<head></head>
<body>
<h3>This is a product - title</h3>
<h3 class="title title-wrap">This is a product - with a wrapped title</h3>
<h3>This is a product - with another title</h3>
<script>
(function() {
var titles = document.querySelectorAll('h3');
titles.forEach(function(o, i) {
var title = o.innerHTML;
if (/title-wrap/ig.test(o.className)) {
o.innerHTML = title.replace(/-/g, '<br />');
} else {
o.innerHTML = title.replace(/-.*$/g, '');
}
});
})();
</script>
</body>
</html>

Related

I want to replace . with <br>tag using javascript

I've tried this
<html>
<head>
<title>None</title>
</head>
<body>
<p id="text">just some random text. random text</p>
<button type="button" onclick="strReplace();">Replace</button>
<script>
function strReplace(){
var myStr = document.getElementById("text");
var mySte = myStr.textContent;
console.log(mySte);
</script>
</body>
and I want this following outcome
just some random text
random text
You can use this regex to find and replace string without breaking html: /(?!<[^>]+)\.(?![^<]+>)/g
[myattr]
{
background-color: pink;
}
[myattr]:after
{
content: "this element's attribute is: " attr(myattr);
background-color: lightgreen;
margin: 1em;
}
p > span
{
background-color: lightblue;
}
<html>
<head>
<title>None</title>
</head>
<body>
<p id="text">just some. random text. <span myattr="text.with.dots">nested.html</span> end.
<span>i < 40. But i is also > 30. What are valid values of i?</span>
</p>
<button type="button" onclick="strReplace();">Replace</button>
<script>
function strReplace(){
var myStr = document.getElementById("text");
myStr.innerHTML = myStr.innerHTML.replace(/(?!<[^>]+)\.(?![^<]+>)/g, "<br>");
console.log(myStr.innerHTML);
}
</script>
</body>
To directly answer the question:
var outputHtml = inputText.replace(/\./g, '<br />');
The Javascript replace method will by default replace the first instance of something (the first . in this case), so the g regex modifier tells it to replace them all. The \. in the regex is because . is a special character in regexes. This will replace every dot in the text.
What about ellipsis?
This technique won't work well on text that contains literal ellipsis, like this:
Hello world...
If your text is likely to contain this, and you want that to be ignored, then the following regex is more appropriate:
/[^\.](\.)[^\.]/g
This'll match any . which is not surrounded by other .
var outputHtml = inputText.replace(/[^\.](\.)[^\.]/g, '<br />');
Handling HTML
In the question here, the input is actually coming from the DOM. We can't replace . on its innerHTML as it would replace content inside HTML tags as well. So, if your input text is coming from the DOM like this (and not, say, a textarea), then the safest route is to apply the replacement only to text nodes. That is done like this:
document.getElementById("start").addEventListener("click", () => {
var inputNode = document.getElementById("text");
replace(inputNode);
});
function replace(node) {
if(!node) {
return;
}
if (node.nodeName == '#text') {
// We've found a text node. Apply the regex to it now.
// Note that you can use either of the above regexes here.
var inputText = node.textContent;
var lines = inputText.split(/\./g);
if(lines.length > 1) {
// It had at least one dot in it.
// Swap in this new set, each with a <br /> between them.
var parent = node.parentNode;
var nextSibling = node.nextSibling;
parent.removeChild(node);
lines.forEach((line, i) => {
if(i != 0){
// insert the <br>
var br = document.createElement('br');
parent.insertBefore(br, nextSibling);
}
var textNode = document.createTextNode(line);
parent.insertBefore(textNode, nextSibling);
});
}
} else {
// Loop through each child node.
// We go backwards such that completed replacements don't affect the loop.
for(var i=node.childNodes.length - 1; i>=0; i--) {
replace(node.childNodes[i]);
}
}
}
<html>
<head>
<title>None</title>
</head>
<body>
<p id="text">just some random text. random text</p>
<button type="button" id="start">Replace</button>
</body>
</html>
If you're starting from a HTML string inside a browser, you can then use the above replace method and the browsers internal parsing to safely only affect the actual text:
function replaceHtmlString(html) {
var div = document.createElement('div');
div.innerHTML = html;
replace(div);
return div.innerHTML;
}

Too Much Recursion Error When Trying to Find All HTML Comments

The script below is meant to find all html comments in the page (there are 4) and return them as one string. I ran the script below and received a "Too Much Recursion" error.
Have I created an infinite loop or did I do something else?
function findComment()
{
var olElement = document.getElementById("everything");//this is the id for my body element
var comments = new Array();
if (olElement.nodeType == 8)
{
comments[comments.length] = olElement;
} else if(olElement.childNodes.length>0)
{
for (var i = 0; i<olElement.childNodes.length; i++)
{
comments = comments.concat(findComment(olElement.childNodes[i]));
}
}
alert(comments);
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
window.onload = findComment;
This is a rough cut version of how you could do it with a recursion. It is not really elegant but will do the work:
function fico(el){
if (el.nodeType==8) return [el.textContent.trim()]
else return [...el.childNodes].map(fico);
}
console.log(fico(document.querySelector("#everything")).toString().replace(/,+/g,", "));
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Depending on the html input the function will return an array of subarrays with further levels of subarrays. To flatten it I used the Array-method toString() and then replace() with a regular expression to throw out the multiple commas in the result. There is still a superfluous one at the beginning ;-)
And here is an alternative version that uses a global comments array like you used in your code:
var comments=[];
function fico(el){
if (el.nodeType==8) comments.push(el.textContent.trim());
else [...el.childNodes].forEach(fico);
}
fico(document.querySelector("#everything")); // collect comments ...
console.log(comments.join(', ')); // ... and display them
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Move the olElements variable outside the function and pass in the element you want to search. The recursion you have is always starting with 'everything';
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
var olElement = document.getElementById("everything");//this is the id for my body element
alert(findComment(olElement));
Update: I tried both methods above and received error that either "element" or "el" is null. So...progress. I've pulled together my full code and html and posted below:
<!DOCTYPE html>
<html>
<head>
<title>A Simple Page</title>
<script>
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
var olElement = document.getElementById("everything");//this is the id for my body element
window.onload = alert(findComment(olElement));
</script>
</head>
<body>
<div id="everything">
<h1>Things to Do</h1><!--this is a title-->
<ol id="toDoList"><!--this is a list-->
<li>Mow the lawn</li><!--this is a list item-->
<li>Clean the windows</li>
<li>Answer your email</li>
</ol>
<p id="toDoNotes">Make sure all these things are done so you can get some rest.</p>
</div>
</body>
</html>

How can I get user input in java script and display this input on page?

I am new to java and am trying to create a game that simulates hangman. I am trying to get the letters from the user after they input on keyboard. However, when I type something it doesn't make any difference, it doesn't output whether it is correct or incorrect. I think I may not be using the event in my guessLetter() function correctly, any help would be greatly appreciated.
window.addEventListener("DOMContentLoaded", function() {
var word = ['taco'];
let randNum = Math.floor(Math.random() * word.length);
let chosenWord = word[randNum];
let underScore = [];
let docUnderScore = document.getElementsByClassName('underScore');
let docRightGuess = document.getElementsByClassName('rightGuess');
let docWrongGuess = document.getElementsByClassName('wrongGuess');
console.log(chosenWord); //lets grader cheat
let generateUnderscore = () => {
for (let i = 0; i < chosenWord.length; i++) {
underScore.push('_');
}
return underScore;
}
document.onkeyup = function guessLetter(event) {
let letter = String.fromCharCode(event.keyCode || event.code).toLowerCase();
if (chosenWord.indexOf(letter) > -1) {
rightWord.push(letter);
underScore[chosenWord.indexOf(letter)] = letter;
docUnderScore[0].innerHTML = underScore.join(' ');
docRightGuess[0].innerHTML = rightWord;
if (underScore.join('') === chosenWord) {
alert('CONGRATS! YOU WIN!!!');
} else {
wrongWord.push(letter);
docWrongGuess[0].innerHTML = wrongWord;
}
}
underScore[0].innerHTML = generateUnderscore().join(' ');
}
});
<!DOCTYPE html>
<html>
<head>
<h1> Hangman </h1>
<div id="guesses">
<div class="letter" id="letter" </div>
</div>
</head>
<body>
</body>
<div class="container">
<div class="underScore">_ _ _ _</div>
<div class="rightGuess"> right guess </div>
<div class="wrongGuess"> wrong guess </div>
</div>
</html>
In the JS console, ReferenceErrors are being thrown as a result of the fact that the rightWord and wrongWord variables have not been defined.
You are writing the in head tag why ? it doesn't shown in your web page , place the html tags within body.

Use slice(); method to achieve an arithmetic operation

My aim is to use a single input to collect numbers and strings then use it to determine a math operation.
For example, I parse in values such as √64 intending to find the square root of 64. Knowing that this is no valid javascript, so I decided to get the first character with result[0]; which is "√" and then slice out the remaining values with result.slice(1); which is "64", then when the condition that result[0] == "√" is true then Math.sqrt(sliceVal) . This seems perfect and runs well in a mobile editor, but doesn't run in any web browser.
function actn() {
var input = document.getElementById("input").value;
var display = document.getElementById("display");
var result = input.toString();
var firstVal = result[0];
if (firstVal == "√") {
var sliceVal = result.slice(1);
display.innerHTML = Math.sqrt(sliceVal);
}
}
I do not know why It is not running at your end but It is working perfectly according to your requirement I tested above code :)
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function actn() {
var input = document.getElementById("test").value;
var result = input.toString();
var firstVal = result[0];
if (firstVal == "√") {
var sliceVal = result.slice(1);
alert(Math.sqrt(sliceVal));
}
alert("No match found");
}
</script>
</head>
<body>
<input type="text" id="test" />
<button type="button" onclick="actn()">Test</button>
</body>
</html>
Checking ASCII value instead of character comparison should work.
<html>
<body>
<input type="text" id="input" />
<button type="button" id="sqrRoot">Square Root</button>
<h1 id="display"></h1>
<script>
function actn() {
var input = document.getElementById("input").value;
var display = document.getElementById("display");
var result = input.toString();
var firstVal = result[0];
/* Ascii value for √ is 8730 */
if (firstVal.charCodeAt(0) === 8730) {
var sliceVal = result.slice(1);
display.innerHTML = Math.sqrt(sliceVal);
}
}
document.getElementById("sqrRoot").addEventListener("click", function () {
actn();
});
</script>
</body>
</html>

Trouble getting real time word count from html textbox

I am very new to html and javascript. I have a textbox and am trying to count the number of words, then displaying the count in real time. I do not understand what I am doing wrong in this, or how to correct it. textContent does not make much sense to me.
<html>
<head>
<style>
input[type='text'] {width:50px;}
textarea {width:500px;height:300px;}
</style>
</head>
<body>
<div>
<h2>Test</h2>
<p>The number of words is <span id="wordCount"></span></p>
<textarea id="toCount"></textarea>
</div>
<script>
document.getElementById('toCount').addEventListener('input', function () {
var text = this.textContent,
count = text.trim().replace(/\s+/g, ' ').split(' ').length;
document.querySelector('.wordCount').textContent = count;
});
</script>
</body>
</html>
The error that I get right now says
Uncaught TypeError: Cannot set property 'textContent' of null
Your selector should be #wordCount, and the textarea content can be accessed using value:
<html>
<head>
<style>
input[type='text'] {width:50px;}
textarea {width:500px;height:300px;}
</style>
</head>
<body>
<div>
<h2>Test</h2>
<p>The number of words is <span id="wordCount"></span></p>
<textarea id="toCount"></textarea>
</div>
<script>
document.getElementById('toCount').addEventListener('input', function () {
var text = this.value,
count = text.trim().replace(/\s+/g, ' ').split(' ').length;
document.getElementById('wordCount').textContent = count;
});
</script>
</body>
</html>
The reason why you are getting null is: in selection, #wordCount is by Id, and .wordCount is by class. So document.querySelector('.wordCount') is returning null as there is no element with class wordCount.
The fix would be to simply change
document.querySelector('.wordCount').textContent = count;
to
document.querySelector('#wordCount').textContent = count;
Try this one.
document.getElementById('toCount').addEventListener('input', function () {
// var text = this.textContent,
var text = this.value,
count = text.trim().replace(/\s+/g, ' ').split(' ').length;
// document.querySelector('#wordCount').textContent = count;
document.querySelector('#wordCount').textContent = count;
});
try this.
document.getElementById('toCount').addEventListener('input', function () {
var text = this.value,
count = text.trim().split(' ').length;
document.querySelector('#wordCount').textContent = count;
});
Here is the jsfiddle

Categories

Resources