Inserting br into a textnode - javascript

This might seem odd. I have a div with the id of 'quotes', and inside there is a blockquote. I thought it would be interesting to add line breaks, if the quoted text were poetry, and I thought you could use a '#' as a conditional line break, and then replace this with the br element as follows:
function addBr() {
var c = document.getElementById("quotes");
var t = c.getElementsByTagName("blockquote");
var reg = new RegExp("#", "g");
for (var i = 0; i < t.length; i++) {
var r = t[i].lastChild.nodeValue.match(reg);
if (r !== null) {
var text = t[i].childNodes[0];
var q = t[i].lastChild.nodeValue.indexOf("#");
var x = document.createElement("br");
t[i].insertBefore(x, text.splitText(q));
t[i].lastChild.nodeValue = t[i].lastChild.nodeValue.replace(/\#/g, "");
}
}
}
This works, but only for the first instance, so I need a loop, but I can't figure that out.
The div would be like this:
<div id = 'quotes'>
<blockquote> Some line, # Some line, # Some line# </blockquote>
</div>
Any hints would be deeply appreciated.

Start with the last match of # within the text node and work backwards. The following function does this and also has the benefit of eliminating the unnecessary regex, uses clearer variable names and is shorter:
function addBr() {
var c = document.getElementById("quotes");
var t = c.getElementsByTagName("blockquote");
for (var i = 0; i < t.length; i++) {
var splitPos, textNode = t[i].lastChild;
while ( (splitPos = textNode.data.lastIndexOf("#")) != -1 ) {
var newTextNode = textNode.splitText(splitPos);
// Remove the # from the start of the new text node
newTextNode.deleteData(0, 1);
var br = document.createElement("br");
t[i].insertBefore(br, newTextNode);
}
}
}

I would suggest simply doing this:
function addBr() {
var c = document.getElementById("quotes");
var t = c.getElementsByTagName("blockquote");
for (var i = 0; i < t.length; i++)
r.innerHTML = r.innerHTML.replace(/#/g, "<br />");
}
What is a "conditional line break"? I don't see anything in your code that decides when to break the line...

Related

Regex function causing chrome to hang

I am trying to find specific words in an html page to replace, however when I run it the RegExp() function is causing chrome to hang. The code below is the section where this is happening
function test(findWord, replaceWord){
var searchregexp = new RegExp(findWord.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), "gi");
console.log(searchregexp);
var elements = document.getElementsByTagName('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];
if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace(searchregexp, replaceWord);
if (replacedText !== text) {
element.innerHTML = replacedText;
}
}
}
}
}
Based on some other things I've read it seems to be that the RegExp function is causing catastrophic backtracking, but I am not really sure why that's the case or how I would solve it.
The code works if I hardcode a specific regular expression like /replace/gi into text.replace(). However, if I try to make it so that the word being replaced doesn't have to be constant and using the new RegExp function chrome hangs

Get all text from a Div after a '-' up until the first character

I'm trying to write a function that will find an instance of text within a div and console.log all text that is after the '-' character. After the '-' character there are sometimes spaces and tabs, so I want to remove these up until the first text character. Here's what I have so far (that is not working at all):
var countryData = $(".countries-title").next().text();
//var regex = /(?<= - ).*/g;
let stringArray = countryData.replace(/\t/g, '').split('\r\n');
console.log(stringArray);
Any help is appreciated. Thanks
console.log('here is a - whole bunch of text'.match(/-\s*(.*)$/)[1]) will log out "whole bunch of text". Is that along the lines of what you are looking for? Let me know if you want me to elaborate.
Assuming you want to maintain all hyphens and formatting after the first hyphen and subsequent spaces you could use:
let textAfterHyphen = countryData.replace(/\s*-\s*/, '');
I am not sure if I understood all but here you have my solution:
$(document).ready(function returnString() {
$("#click-target").on("click",function(){
var newString = [];
var resultString = [];
var onlyChar =$(".target").text();
newString = onlyChar.split("");
for(var i = 0; i < newString.length; i++){
if(newString[i] == "-"){
resultString = newString.slice(i+1,newString.length).join("");
}
}
var k = 0;
for(var j = 0; j < resultString.length; j++){
if(resultString.charCodeAt(j) > 64 && resultString.charCodeAt(j) < 91){
k += j;
}
}
console.log(resultString.slice(k,resultString.length));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="target">Text- *^^^***Text to display</div>
<button id ="click-target">Click</button>

Using RegExp With Replace and Arrays

I am running a RegExp on a user input to test for capitals of 3 or more in a row. I have a loop that finds the RegExp and then adds it to an array. Another loop that creates a new array. When I run the .replace it seems that that array isn't being looped over.
var abbrBracket = /\([A-Z]{3,30}\)/g;
var abbrBracketArr = [];
var a;
while (a = abbrBracket.exec(nonCode)) {
abbrBracketArr.push(a[0]);
}
var capFoundInArr = /[A-Z]{3,30}/g;
var abbrBracketArrRemove = [];
var b;
while (b = capFoundInArr.exec(abbrBracketArr)) {
abbrBracketArrRemove.push('(<abbr>' + b[0] + '</abbr>)');
}
for(var c = 0; c < abbrBracketArrRemove.length; c++){
nonCode = document.getElementById('cleanse').innerHTML;
//nonCode = nonCode.replace(new RegExp(/\([A-Z]{3,30}\)/), abbrBracketArrRemove[c]);
nonCode = nonCode.replace(new RegExp(abbrBracketArr[c]), abbrBracketArrRemove[c]);
document.getElementById('cleanse').innerHTML = nonCode;
}
The results show if there are two (or more) of the same abbreviations, the first is executed multiple times the next is skipped.
Saying that, I am using the exact same code to run a second query for replace and I am not getting this error.
var abbrNoBracket = /\s[A-Z]{3,30}/g;
var abbrNoBracketArr = [];
var d;
while (d = abbrNoBracket.exec(nonCode)) {
abbrNoBracketArr.push(d[0]);
}
var abbrNoBracketArrRemove = [];
var e;
while (e = capFoundInArr.exec(abbrNoBracketArr)) {
abbrNoBracketArrRemove.push(' <abbr title="">' + e[0] + '</abbr>');
}
for(var f = 0; f < abbrNoBracketArrRemove.length; f++){
nonCode = document.getElementById('cleanse').innerHTML;
nonCode = nonCode.replace(new RegExp(abbrNoBracketArr[f]), abbrNoBracketArrRemove[f]);
document.getElementById('cleanse').innerHTML = nonCode;
}
In the first block, you can see I commented out a line, if I use the RegExp instead of the array. It works. Curious, why this would work for one, but not the other.
Found my error, which was very obvious after a good nights sleep.
I called a new RegExp on the array. Once I removed that, everything worked as it should.
for(var c = 0; c < abbrBracketArrRemove.length; c++){
nonCode = document.getElementById('cleanse').innerHTML;
//mistake
//nonCode = nonCode.replace(new RegExp(abbrNoBracketArr[f]), abbrNoBracketArrRemove[f]);
//corrected
nonCode = nonCode.replace(abbrBracketArr[c], abbrBracketArrRemove[c]);
document.getElementById('cleanse').innerHTML = nonCode;
}
Hopefully that helps someone else.

JavaScript: loop through DOM tree and replace text?

I need to use JavaScript to loop through the DOM tree of a webpage and replace every instance of the word 'hipster' with a different word UNLESS it is part of a link or image src. Example, if 'hipster' appears in a paragraph, it should be replaced.
But if it's in the src="" url for an image, that should not be replaced because if it replaces that word in a url, the url obviously breaks.
I've been having a really hard time implementing this. Here's one thing I tried:
var items = document.getElementsByTagName("*");
var i = 0;
for (i = 0; i < items.length; i++){
if(i.nodeType == 3){
i.html().replace(/hipster/gi, 'James Montour');
}
else{
//do nothing for now
}
}
You’re close, but:
document.getElementsByTagName('*') will never return text nodes; it gets elements only (and comment nodes in old versions of IE)
Text nodes don’t have an html() method
replace doesn’t modify strings in place
With that in mind, you can get every child of every element, check their types, read their nodeValues, and, if appropriate, replace the entire node:
var elements = document.getElementsByTagName('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];
if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace(/hipster/gi, 'James Montour');
if (replacedText !== text) {
element.replaceChild(document.createTextNode(replacedText), node);
}
}
}
}
Try it out on this page!
To use variables instead of 'hipster' replace:
var replacedText = text.replace(/hipster/gi, 'James Montour');
with these lines:
var needle = 'hipster';
var replacement = 'James Montour';
var regex = new RegExp(needle, "gi");
var replacedText = text.replace(regex, replacement);

Word count issue with JS

I am very, very new at JS with no programming experience and I am struggling with creating a script that counts words in a text box. I have the following code and I can't get anything to populate:
var myTextareaElement = document.getElementById("myWordsToCount");
myTextareaElement.onkeyup = function(){
var wordsCounted = myTextareaElement.value;
var i = 0;
var str = wordsCounted;
var words = str.split('');
for (var i = words.length; i++) {if (words[i].length > 0; i++) { words[i] };
}
And for the Span Id in my HTML, I put the following:
<span id="wordsCounted"></span>
Any direction I where I am royally messing up would be great. I have tried it in JS fiddle and can't get it to populate.
The split method needs a proper character, you can use an space " " or a regex to indicate any whitespace character: "My name is XXX".split(/\s+/) will show ["My", "name", "is", "XXX"].
If you just want the number of words you can do "My name is XXX".split(/\s+/).length, which will return 4.
Try this, this may do what you want. Instead of doing a for loop, just count how many words are there and display the length of the array.
var myTextareaElement = document.getElementById("myWordsToCount");
myTextareaElement.onkeyup = function(){
var wordsCounted = myTextareaElement.value;
var i = 0;
var str = wordsCounted;
var words = str.split('');
if (words.length > 0){
document.getElementById('wordsCounted').innerHTML = words.length;
}
}

Categories

Resources