Using HTMLFilter addrules in CKEDITOR, I'm trying to remove the height/width from the STYLE of plain text.
They don't return the actual object just plain text style so I really can't use jQuery or other DOM manipulation tools.
I have the below regex code that successfully removes HEIGHT and WIDTH but still leaves the actual dimensions.
I'm new to regular expressions so I'm sure it's something rather simple. Just not sure what.
Thank you.
var str = "width:100px;height:200px;float:left;";
var regex = /(height|width):(?=(.*?);)/gi;
console.log(str.replace(regex,""));
You used a lookahead, and it is a non-consuming pattern, i.e. the text it matches does not become part of the whole match value. Thus, it does not get removed
Use a pattern like
/(?:height|width):[^;]*;/gi
See the regex demo.
Details
(?:height|width) - a non-capturing group matching either height or width
: - a colon
[^;]* - a negated character class matching 0+ chars other than ;
; - a semi-colon.
See JS demo:
var str = "width:100px;height:200px;float:left;";
var regex = /(?:height|width):[^;]*;/gi;
console.log(str.replace(regex,""));
A non-regex solution with javascript built-ins methods to remove the height/width from the STYLE of plain text.
function isNotWidthHeight(style) {
return style.toLowerCase().indexOf("width") === -1 && style.toLowerCase().indexOf("height") === -1 && style;
}
var str = "margin:0 auto;width:100px;height:200px;float:left;";
var array = str.split(';').filter(isNotWidthHeight);
console.log(array.join(';'));
You need to capture the values too.
.*? instead of (?=(.*?);) will be enough.
var str = "width:100px;height:200px;float:left;";
var regex = /(height|width):.*?;/gi;
console.log(str.replace(regex,""));
Pretty close, you just need an extra group and something to wait until either ; or word boundary, \b. This will grab any setting including calc or whatever settings can follow until the ; or end of inline style.
var str = "width:100px;height:200px;float:left;";
var str2 = "width:calc(100vh - 20px);height:100%;float:left;";
var regex = /((width|height):[\s\S]+?;|\b)/gi;
console.log(str.replace(regex,""));
console.log(str2.replace(regex,""));
Related
I'm trying to get all characters after "."(dot) and set some styling to them with JavaScript.
Example: $10.12 . I want to set some styling to numbers "12".
I have this number dynamically created in phtml file inside span.
I tried something like this, but without success:
var aa = document.getElementById('testdiv').innerHTML; // gets my span
var bb = aa.toString().split(".")[1]; // gets all numbers after "."
bb.setAttribute("style","width: 500px;");
Thanks to everyone! You really helped me. I would vote for every answer, but unfortunately I can't vote yet.
Your mistake begins here:
var aa = document.getElementById('testdiv').innerHTML; // gets my span
That's not your span, but its HTML contents. To take care of setting the width, you need something like this instead:
var aa = document.getElementById('testdiv'); // gets my span
aa.style.width = "500px";
You can only apply styling to HTML elements, not text nodes.
Try this instead:
var elem = document.getElementById('testdiv');
var parts = elem.innerHTML.toString().split(".");
parts[1] = "<div style=\"width: 500px\">" + parts[1] + "</div>";
elem.innerHTML = parts.join(".");
I've used because it's immediately apparent that a style has been applied, but if you want the number to appear consistent, as in "$10.12" without the "12" on a new line, you will probably need to apply additional styles or rethink how you're outputting the HTML.
You cannot set style to the textNode, the work around is to create an element to wrap the character after "." by using span. The idea is simple. First split it by "." and check if it has "." inside, if yes, create an element to wrap it and set style. Finally, join it back by "."
var inner = document.getElementById('testdiv').innerHTML;
var arr = inner.toString().split(".");
if(arr.length > 1)
{
arr[1] = '<span style="display: inline-block; width: 500px;">' + arr[1] + '</span>';
}
newContent = arr.join(".");
document.getElementById('testdiv').innerHTML = newContent;
You could do something like this:
document.getElementById('testdiv').innerHTML = document.getElementById('testdiv').innerHTML.replace( /(\d+).(\d+)/, '$1.<span id="end">$2</span>' );
document.getElementById('end').style.fontWeight = 'bold';
jsFiddle example
Your example fails at bb.setAttribute since you're trying to set an attribute on a string instead of a node. What you need to do is essentially rebuild the 10.12 with <span> elements surrounding the text you want to alter, and then you can use other JavaScript methods to modify the styling. The method you were using was almost correct, except the last part won't work because the split() method returns a string, not a node.
You can do this with regexp:
onlyDigitsText = text.replace(/\.([0-9]*)/g, ".<span class='highlighted'>$1</span>");
JsFiddle example
Try
var elem = document.getElementById('testdiv');
elem.innerHTML = elem.innerHTML.replace( /(\d+)\.(\d+)/g, '$1.<span class="decimalPart">$2</span>' );
// (\d+) one or more digits
// \. a dot character. Must be escaped otherwise it means ANY character
// (\d+) one or more digits
// g regex flag to replace all instances, not just one.
Then in your css add styling for the decimalPart class
.decimalPart {
width: 500px;
}
This has the added advantage of separating your styles from your html.
UPDATE
Following your comment to get the character just before the number use
elem.innerHTML.replace( /(\s)([^\s\d]*?)(\d+)\.(\d+)/g, '$1<span class="currencySymbol">$2</span>$3.<span class="decimalPart">$4</span>' );
// (\s) space, tab, carriage return, new line, vertical tab, form feed
// ([\s\d]*?) any set of characters that are not a digit or the above zero or more times
// (\d+) one or more digits
// \. a dot character. Must be escaped otherwise it means ANY character
// (\d+) one or more digits
// g regex flag to replace all instances, not just one.
Please note I have made an allowance for currency symbols that take up more than a single character.
I am struggling with a regex in javascript that needs the text after # to the first word boundary, but not match it if it is part of an url. So
#test - should match test
sometext#test2 - should match test2
xx moretext#test3 - should match test3
http://test.com#tab1 - should not match tab1
I am replacing the text after the hash with a link (but not the hash character itself). There can be more than one hash in the text, and it should match them all (I guess I should use /g for that).
Matching the part after the hash is quite easy: /#\b(.+?)\b/g, but not matching it if the string itself starts with "http" is something I cannot solve. I should probably use a negative look-around, but I am having problems getting my head around that.
Any help is greatly appreciated!
Try this regex using a negative lookahead instead since JS doesn't support lookbehinds:
/^(?!http:\/\/).*#\b(.+?)\b/
You may want to check for www too, depending on your conditions.
Edit: Then you can do this:
str = str.replace(re.exec(str)[1], 'replaced!');
http://jsfiddle.net/j7c79/2/
Edit 2: Sometimes a regex alone is not the way to go if it gets too complicated. Try a different approach:
var txt = "asdfgh http://asdf#test1 #test2 woot#test3";
function replaceHashWords(str, rep) {
var isUrl = /^http/.test(str), result = [];
!isUrl && str.replace(/#\b(.+?)\b/g, function(a,b){ result.push(b); });
return str.replace((new RegExp('('+ result.join('|') +')','g')), rep);
}
alert(replaceHashWords(txt, 'replaced!'));
// asdfgh http://asdf#replaced! #replaced! woot#replaced!
As regex is, often (if not always), quite expensive to use, I'd suggest using basic string, and array, methods to determine whether a given set of characters represents an URL (though I'm assuming that all URLS will start with the http string):
$('ul li').each(
function() {
var t = $(this).text(),
words = t.split(/\s+/),
foundHashes = [],
word = '';
for (var i = 0, len = words.length; i < len; i++) {
word = words[i];
if (word.indexOf('http') == -1 && word.indexOf('#') !== -1) {
var match = word.substring(word.indexOf('#') + 1);
foundHashes.push(match);
}
}
// the following just shows what, if anything, was found
// and can definitely be safely omitted
if (foundHashes.length) {
var newSpan = $('<span />', {
'class': 'matchedWords'
}).text(foundHashes.join(', ')).appendTo($(this));
}
});
JS Fiddle demo (with some timing information printed to the console).
References:
jQuery:
appendTo().
each().
text().
'Vanilla' JavaScript
Array.join().
String.indexOf().
String.split().
String.substring().
This would require a lookbehind, something sadly lacking from JavaScript's capabilities.
However, if your subject string is some HTML and those URLs are in href attributes, you can create a document out of it and search for text nodes, only replacing their nodeValues instead of the whole HTML string.
I have some text content (read in from the HTML using jQuery) that looks like either of these examples:
<span>39.98</span><br />USD
or across multiple lines with an additional price, like:
<del>47.14</del>
<span>39.98</span><br />USD
The numbers could be formatted like
1,234.99
1239,99
1 239,99
etc (i.e. not just a normal decimal number). What I want to do is get just whatever value is inside the <span></span>.
This is what I've come up with so far, but I'm having problems with the multiline approach, and also the fact that there's potentially two numbers and I want to ignore the first one. I've tried variations of using ^ and $, and the "m" multiline modifier, but no luck.
var strRegex = new RegExp(".*<span>(.*?)</span>.*", "g");
var strPrice = strContent.replace(strRegex, '$1');
I could use jQuery here if there's a way to target the span tag inside a string (i.e. it's not the DOM we're dealing with at this point).
You could remove all line breaks from the string first and then run your regex:
strContent = strContent.replace(/(\r\n|\n|\r)/gm,"");
var strRegex = new RegExp(".*<span>(.*?)</span>.*", "g");
var strPrice = strContent.replace(strRegex, '$1');
This is pretty easy with jQuery. Simply wrap your HTML string inside a div and use jQuery as usual:
var myHTML = "<span>Span 1 HTML</span><span>Span 2 HTML</span><br />USD";
var $myHTML = $("<div>" + myHTML + "</div>");
$myHTML.find("span").each(function() {
alert($(this).html());
});
Here's a working fiddle.
try using
"[\s\S]*<span>(.*?)</span>[\s\S]*"
instead of
".*<span>(.*?)</span>.*"
EDIT: since you're using a string to define your regex don't forget to esacpe your backslashes, so
[\s\S]
would be
[\\s\\S]
You want this?
var str = "<span>39.98</span><br />USD\n<del>47.14</del>\n\n<span>40.00</span><br />USD";
var regex = /<span>([^<]*?)<\/span>/g;
var matches = str.match(regex);
for (var i = 0; i < matches.length; i++)
{
document.write(matches[i]);
document.write("<br>");
}
Test here: http://jsfiddle.net/9LQGK/
The matches array will contain the matches. But it isn't really clear what you want. What does there's potentially two numbers and I want to ignore the first one means?
I have some content, for example:
If you have a question, ask for help on StackOverflow
I have a list of synonyms:
a={one typical|only one|one single|one sole|merely one|just one|one unitary|one small|this solitary|this slight}
ask={question|inquire of|seek information from|put a question to|demand|request|expect|inquire|query|interrogate}
I'm using JavaScript to:
Split synonyms based on =
Looping through every synonym, if found in content replace with {...|...}
The output should look like:
If you have {one typical|only one|one single|one sole|merely one|just one|one unitary|one small|this solitary|this slight} question, {question|inquire of|seek information from|put a question to|demand|request|expect|inquire|query|interrogate} for help on StackOverflow
Problem:
Instead of replacing the entire word, it's replacing every character found. My code:
for(syn in allSyn) {
var rtnSyn = allSyn[syn].split("=");
var word = rtnSyn[0];
var synonym = (rtnSyn[1]).trim();
if(word && synonym){
var match = new RegExp(word, "ig");
postProcessContent = preProcessContent.replace(match, synonym);
preProcessContent = postProcessContent;
}
}
It should replace content word with synonym which should not be in {...|...}.
When you build the regexps, you need to include word boundary anchors at both the beginning and the end to match whole words (beginning and ending with characters from [a-zA-Z0-9_]) only:
var match = new RegExp("\\b" + word + "\\b", "ig");
Depending on the specific replacements you are making, you might want to apply your method to individual words (rather than to the entire text at once) matched using a regexp like /\w+/g to avoid replacing words that themselves are the replacements for others. Something like:
content = content.replace(/\w+/g, function(word) {
for(var i = 0, L = allSyn.length; i < L; ++i) {
var rtnSyn = allSyn[syn].split("=");
var synonym = (rtnSyn[1]).trim();
if(synonym && rtnSyn[0].toLowerCase() == word.toLowerCase()) return synonym;
}
});
Regular expressions include something called a "word-boundary", represented by \b. It is a zero-width assertion (it just checks something, it doesn't "eat" input) that says in order to match, certain word boundary conditions have to apply. One example is a space followed by a letter; given the string ' X', this regex would match it: / \bX/. So to make your code work, you just have to add word boundaries to the beginning and end of your word regex, like this:
for(syn in allSyn) {
var rtnSyn = allSyn[syn].split("=");
var word = rtnSyn[0];
var synonym = (rtnSyn[1]).trim();
if(word && synonym){
var match = new RegExp("\\b"+word+"\\b", "ig");
postProcessContent = preProcessContent.replace(match, synonym);
preProcessContent = postProcessContent;
}
}
[Note that there are two backslashes in each of the word boundary matchers because in javascript strings, the backslash is for escape characters -- two backslashes turns into a literal backslash.]
For optimization, don't create a new RegExp on each iteration. Instead, build up a big regex like [^{A-Za-z](a|ask|...)[^}A-Za-z] and an hash with a value for each key specifying what to replace it with. I'm not familiar enough with JavaScript to create the code on the fly.
Note the separator regex which says the match cannot begin with { or end with }. This is not terribly precise, but hopefully acceptable in practice. If you genuinely need to replace words next to { or } then this can certainly be refined, but I'm hoping we won't have to.
I'm trying to remove the whitespaces from a textarea . The below code is not appending the text i'm selecting from two dropdowns. Can somebody tell me where i'd gone wrong? I'm trying to remove multiple spaces within the string as well, will that work with the same? Dont know regular expressions much. Please help.
function addToExpressionPreview() {
var reqColumnName = $('#ddlColumnNames')[0].value;
var reqOperator = $('#ddOperator')[0].value;
var expressionTextArea = document.getElementById("expressionPreview");
var txt = document.createTextNode(reqColumnName + reqOperator.toString());
if (expressionTextArea.value.match(/^\s+$/) != null)
{
expressionTextArea.value = (expressionTextArea.value.replace(/^\W+/, '')).replace(/\W+$/, '');
}
expressionTextArea.appendChild(txt);
}
> function addToExpressionPreview() {
> var reqColumnName = $('#ddlColumnNames')[0].value;
> var reqOperator = $('#ddOperator')[0].value;
You might as well use document.getElementById() for each of the above.
> var expressionTextArea = document.getElementById("expressionPreview");
> var txt = document.createTextNode(reqColumnName + reqOperator.toString());
reqOperator is already a string, and in any case, the use of the + operator will coerce it to String unless all expressions or identifiers involved are Numbers.
> if (expressionTextArea.value.match(/^\s+$/) != null) {
There is no need for match here. I seems like you are trying to see if the value is all whitespace, so you can use:
if (/^\s*$/.test(expressionTextArea.value)) {
// value is empty or all whitespace
Since you re-use expressionTextArea.value several times, it would be much more convenient to store it an a variable, preferably with a short name.
> expressionTextArea.value = (expressionTextArea.value.replace(/^\W+/,
> '')).replace(/\W+$/, '');
That will replace one or more non-word characters at the end of the string with nothing. If you want to replace multiple white space characters anywhere in the string with one, then (note wrapping for posting here):
expressionTextArea.value = expressionTextArea.value.
replace(/^\s+/,'').
replace(/\s+$/, '').
replace(/\s+/g,' ');
Note that \s does not match the same range of 'whitespace' characters in all browsers. However, for simple use for form element values it is probably sufficient.
Whitespace is matched by \s, so
expressionTextArea.value.replace(/\s/g, "");
should do the trick for you.
In your sample, ^\W+ will only match leading characters that are not a word character, and ^\s+$ will only match if the entire string is whitespace. To do a global replace(not just the first match) you need to use the g modifier.
Refer this link, you can get some idea. Try .replace(/ /g,"UrReplacement");
Edit: or .split(' ').join('UrReplacement') if you have an aversion to REs