I want to have a text that overflows in another div, so I found and used this answer from another question at Stackoverflow.
The problem is that only plain text is displayed; links, bold/italics and paragraphs are ignored.
Here is the same jsfiddle from the answer, but with added html tags. How do i get to display them?
Code:
var currentCol = $('.col:first');
var text = currentCol.text();
currentCol.text('');
var wordArray=text.split(' ');
$.fn.hasOverflow = function() {
var div= document.getElementById( $(this).attr('id') );
return div.scrollHeight>div.clientHeight;
};
for ( var x = 0; x < wordArray.length; x++ ) {
var word = wordArray[x];
currentCol.append(word+' ');
if ( currentCol.hasOverflow() ) {
currentCol = currentCol.next('.col');
}
}
Any tips or advice will be appreciated :)
jQuery .text method returns only plain text. Try using .html instead.
Example:
var text = currentCol.html();
But if your tags contain any spaces (like <span class="some-class">) then the following line from your code will do a mess with your text
var wordArray=text.split(' ');
You might want to change it to
text = text.replace(/ (?![^<>]*>)/gi, '%^%');
var wordArray = text.split('%^%');
This is kind of workaround since you could iterate over each regex match and substring it on every space character but IMHO the above idea with %^% combination is much more simple. you can replace those 3 signs with anything you want. I just thought it is unique enough that won't be used in any other purpose.
Above regular expression is simplified and assumes that you don't use < and > signs in your text.
If you actually do I would recommend to replace them with < and > anyway.
Related
i use this javascript code to editing paragraph if it have links the code will make the link active to click by adding html href element
my problem is the result of this code be in one line
i want the paragraph result stay paragraph not 1 line
any idea?
thanks all
var collection = document.getElementsByClassName("Edit_desc");
for (let i=0; i<collection.length; i++) {
//Regex Expresson to match general URL used frequently.
var expression = /[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()#:%_\+.~#?&//=]*)?/gi;
//Creating Regex Object with the Regex Expression
var regex = new RegExp(expression);
//Fetch words from the Text Area , array named 'input_text_words' will contain all words separately
var input_text_words = collection[i].textContent.trim().split(/\s+/);
var input_text_number_of_words = input_text_words.length;
//Empty Paragraph Element
var paragraphElement = "";
//Traversing the words array
for(var index = 0 ; index < input_text_number_of_words ; index++){
//If the word matches the URL regex than print using so that link may appear.
if(input_text_words[index].match(regex)){
paragraphElement += ''+input_text_words[index]+'';
}
//Else if the word is not any url , simply print.
else{
paragraphElement += input_text_words[index];
}
if(index != input_text_number_of_words-1){
paragraphElement += ' ';
}
}
//Finally show the modified text in tha empty paragraph element.
collection[i].innerHTML = paragraphElement;
}
I suppose that your spaces are not caused by html tags like <br/>
So the problem is the splitting you do :
var input_text_words = collection[i].textContent.trim().split(/\s+/);
The ("string1 string2\nstring3").split(/\s+/); expression splittes the string into 3 items. Making you lose the lines part...
As a solution i suggest you use another regex that partially solves the problem
.split(/[^\S\r\n]/g)
witch i got from this guy
But this solution has possible issues, if the linke is at the start of the paragraph or if you can have a link with lines inside it ( done by a text-area for example ) that wont be selected. So be sure to check what do u need exactly and adjust the regex to something that suites you.
I want to start off by saying I am very very new to javascript, and basically did a lot of googling to find this place and various other resources. While I found a script to modify into something I wanted (and managed to get it to work) it interferes with any links that are made within the specified div. Is there a way to exclude the links from the javascript, and just have the javascript affect the text?
This is the javascript. While I have no problem getting the first part to work (where I replace quoted text), I can't seem to exclude links and images that has html which possesses quotation marks in them.
$("div.gam-posttem div").each(function(){
this.innerHTML = this.innerHTML.replace(/\"([^\"]+)\"/g,
'<div class="gam-quotetext">"$1"</div>');
});
$not('div.gam-posttem > div > a').each(function(){});
And here's the html I am using.
<div class="gam-posttem"><div class="gam-posttem1">
"quote here" and regular text here. "more quote here"
<br><br>Link is Here
</div></div>
Any help is greatly appreciated, and if you need any more info, such as CSS, please feel free to ask.
What makes this particularly tricky is that JavaScript Regular Expressions do not allow look-behind. What you want to do is try and match " pairs where there are an equal number of < and > characters (outside of other " characters) before it. And even if you could, that'd be a pretty nasty looking regex...
However, you only care about characters outside of <> pairs, which matching using Regex (while not advisable) is possible:
<(?:[^><\"\']*?(?:([\"\']).*?\1)?[^><\'\"]*?)+(?:>|$) will match all <> pairs, ignoring close angle brackets within quotes within the tag. Hence you want to match everything outside these tags.
There's probably a better way to do this, but you can try the following idea:
Match all tags
For each tag, get the start position and length => calculate end position
add the start index of the string to the front of the end positions
add the length of the string to the start positions
for each (end, start) pair (as we are inverting the matches), run your replace method and modify the string.
String.prototype.spliceish = function(start, end, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(end);
};
var tagMatch = /<(?:[^><\"\']*?(?:([\"\']).*?\1)?[^><\'\"]*?)+(?:>|$)/g;
var tokenMatch = /\"([^\"]+)\"/g;
function invertedMatch(htmlString) {
var returnString = htmlString;
var startIndexes = [],
lengths = [],
match = tagMatch.exec(htmlString);
while(match !== null)
{
startIndexes.push(match.index);
lengths.push(match[0].length);
match = tagMatch.exec(htmlString);
}
var endIndexes = startIndexes.map(function(val, ix) { return val + lengths[ix]; });
var invertedStarts = [0].concat(endIndexes); // we are inverting, so capture start text.
var invertedEnds = startIndexes.concat(htmlString.length);
// will need to go backwards
for(var i = invertedStarts.length - 1; i >= 0; i--) {
var start = invertedStarts[i],
end = invertedEnds[i];
var stringReplace = htmlString.substring(start, end);
returnString = returnString.spliceish(start, end, stringReplace.replace(tokenMatch,
'<div class="gam-quotetext">"$1"</div>'));
};
return returnString;
}
$("#root").html(invertedMatch($("#root").html()));
.gam-quotetext{
color: green
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="root">
<div class="gam-posttem">
<div class="gam-posttem1">
"quote here" and regular text here. "more quote here"
<br>
<br>
Link is Here
</div>
</div>
</div>
I'm making a webcode editor, I'm working on the text markup so I wrote this regex : /\b(?:abstract|arguments|boolean|break|byte|case|catch|char|const|class|continue|debugger|default|delete|do|double|else|enum|eval|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|let|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|var|void|volatile|while|with|yield|alert|all|anchor|anchors|area|assign|blur|button|checkbox|clearInterval|clearTimeout|clientInformation|close|closed|confirm|constructor|crypto|decodeURI|decodeURIComponent|defaultStatus|document|element|elements|embed|embeds|encodeURI|encodeURIComponent|escape|event|fileUpload|focus|form|forms|frame|innerHeight|innerWidth|layer|layers|link|location|mimeTypes|navigate|navigator|frames|frameRate|hidden|history|image|images|offscreenBuffering|open|opener|option|outerHeight|outerWidth|packages|pageXOffset|pageYOffset|parent|parseFloat|parseInt|password|pkcs11|plugin|prompt|propertyIsEnum|radio|reset|screenX|screenY|scroll|secure|select|self|setInterval|setTimeout|status|submit|taint|text|textarea|top|unescape|untaint|window|onblur|onclick|onerror|onfocus|onkeydown|onkeypress|onkeyup|onmouseover|onload|onmouseup|onmousedown|onsubmit)\b(?=(?:[^"]*"[^"]*")*[^"]*$)(?=(?:[^']*'[^']*')*[^']*$)(?![^<]*>)(?![^\/*]*\*\/)/gm
This the group of reserved words
/\b(?:abstract|arguments|boolean|break|byte|case|catch|char|const|class|continue|debugger|default|delete|do|double|else|enum|eval|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|let|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|var|void|volatile|while|with|yield|alert|all|anchor|anchors|area|assign|blur|button|checkbox|clearInterval|clearTimeout|clientInformation|close|closed|confirm|constructor|crypto|decodeURI|decodeURIComponent|defaultStatus|document|element|elements|embed|embeds|encodeURI|encodeURIComponent|escape|event|fileUpload|focus|form|forms|frame|innerHeight|innerWidth|layer|layers|link|location|mimeTypes|navigate|navigator|frames|frameRate|hidden|history|image|images|offscreenBuffering|open|opener|option|outerHeight|outerWidth|packages|pageXOffset|pageYOffset|parent|parseFloat|parseInt|password|pkcs11|plugin|prompt|propertyIsEnum|radio|reset|screenX|screenY|scroll|secure|select|self|setInterval|setTimeout|status|submit|taint|text|textarea|top|unescape|untaint|window|onblur|onclick|onerror|onfocus|onkeydown|onkeypress|onkeyup|onmouseover|onload|onmouseup|onmousedown|onsubmit)\b
This skip markup if in double quotes
(?=(?:[^"]*"[^"]*")*[^"]*$)
This skip markup if in single quotes
(?=(?:[^']*'[^']*')*[^']*$)
This skip markup if in a tag <>
(?![^<]*>)
This skip markup if in a comment /* */
(?![^\/*]*\*\/)
Now I'm stuck on the last piece of cake, I need to skip markup if in a comment // [single line]
(?!\/\/[\w\s\'\"][^\n]*)|(?!\/\/)
Any suggestion?
My suggestion is not to use a regex for this kind of parsing job. Since you are building something in Javascript, you can use jison to convert a grammar that you design into a working javascript function that will parse text according to your grammar.
if you are curious this is my solution, please let me know if your eyes are bleeding or if it is a good solution :
//finding the string that I need to manipulate
regcomment2 =/(\/\/[\w\s\'\"][^\n]*)|(\/\/)/gm;
//this the loop to find and replace
var str = finale.match(regcomment2);
if(finale.match(regcomment2)){
str = str.toString();
var arr = str.split(",");
var arrcheck = str.split(",");
var text = "";
var i;
for (i = 0; i < arr.length; i++) {
//writing right code
arr[i]= arr[i].replace(/(<.*?[^ok]>)/g,"");
console.log("Commento Split Dopo = " + arr[i]);
console.log("Commento Arr2 = " + arrcheck[i]);
//replace original code with right code
finale = finale.replace(arrcheck[i],arr[i]);
}
A little help required please...
I have a regular expression that matches characters at the start of a string as follows:
If I have a set of strings like so:
Ray Fox
Foster Joe
Finding Forrester
REGEX
/\bfo[^\b]*?\b/gi
This will match 'FO' in Fox, Foster, and Forrester as expected:
However, I am faced with an issue where if the set of strings are wrapped in html tags like so;-
<span class="fontColor1">Ray Fox</span>
<span class="fontColor2">Foster Joe</span>
<span class="fontColor3">Finding Forrester</span>
This will match 'FO' in fontColor* as well.
I'm fairly green with Regular expressions, I need a little help updating the query so that it only searches values between HTML tags where HTML tags exist, but still works correctly if HTML tags do not exist.
You can use a html parser and extract pure text, and match that.
var root;
try {
root = document.implementation.createHTMLDocument("").body;
}
catch(e) {
root = document.createElement("body");
}
root.innerHTML = '<span class="fontColor1">Ray Fox</span>\
<span class="fontColor2">Foster Joe</span>\
<span class="fontColor3">Finding Forrester</span>';
//If you are using jQuery
var text = $(root).text();
//Proceed as normal with the text variable
If you are not using jQuery, you can replace $(root).text() with findText(root), where findText:
function findText(root) {
var ret = "",
nodes = root.childNodes;
for (var i = 0; i < nodes.length; ++i) {
if (nodes[i].nodeType === 3) {
ret += nodes[i].nodeValue;
} else if (nodes[i].nodeType === 1) {
ret += findText(nodes[i]);
}
}
return ret;
}
What about
<.*?span.*?>(.*?)<\s?\/.*?span.*?>
And where do you have text where html tags don't exist? That makes no sense.
EDIT:
This solution will not match nested tags, but as the question is written, that doesn't seem to be an issue.
I'm trying to replace text inside an HTML string with Javascript.
The tricky part is that I need to replace the text only if it isn't inside a tag (meaning it's not part of an attribute):
var html_str = '<div>hi blah blah<img src="img.jpg" alt="say hi" />hi!</div>';
In this example, after I do html_str.replace("hi","hello"); I want to replace only the text inside the div and a tags, avoiding the <img alt=".." or the href="....
Some more info:
html_str = document.body.innerHTML;, therefore the elements are unknown. The example above is only an example.
Regex are more than welcome.
The hi and hello values are inside varaibles, meaning the actual replace is like so: html_str.replace(var1,var2);
The REAL code is this:
var html_str = document.body.innerHTML;
var replaced_txt = "hi";
var replace_with = "hello";
var replaced_html = html_str.replace(replaced_txt,replace_with);
I hope I explained myself well.
Thanks in advance.
This maybe?
var obj = {'hi':'hello','o':'*','e':'3','ht':'HT','javascrpit':'js','ask':'ASK','welcome':'what\'s up'}; // This may contain a lot more data
(function helper(parent, replacements) {
[].slice.call(parent.childNodes, 0).forEach(function (child) {
if (child.nodeType == Node.TEXT_NODE) {
for (var from in replacements) {
child.nodeValue = child.nodeValue.replace(from, replacements[from]);
}
}
else {
helper(child, replacements);
}
});
}(document.body, obj));
http://jsfiddle.net/G8fYq/4/ (uses document.body directly)
If you want to make the changes visible immediately then you could also pass document.body and forget about the whole container stuff.
Update to allow for multiple replacements in one run.
You could also try XPath in javascript, though the following solution will not work in IE.
var
replacements = {'hi':'hello','o':'*','e':'3','ht':'HT','javascrpit':'js','ask':'ASK','welcome':'what\'s up'},
elements = document.evaluate('//text()', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null),
i = 0,
textNode, from;
for (; i < elements.snapshotLength; i += 1) {
textNode = elements.snapshotItem(i);
for (from in replacements) {
if (replacements.hasOwnProperty(from)) {
textNode.nodeValue = textNode.nodeValue.replace(from, replacements[from]);
}
}
}
Actually it is possible to use this simple regex negative lookahead:
(?![^<>]*>)
Just add it to your match pattern and it will exclude any content as attributes in tags. Here is an example:
Javascript regex: Find all URLs outside <a> tags - Nested Tags
You can try this, but regexp and HTML are not friends:
var str = '<div>hi blah blah<img src="img.jpg" alt="say hi" />hi!</div>',
rx = new RegExp('(\>[^\>]*)' + 'hi' + '([^\>=]*\<)', 'g');
str = str.replace(rx, '$1hello$2');