i have a textarea where user types his codes and a div tag where it renders how it will be displayed on a webpage. I am using custom tags to format user codes like [b]bold text[/b] instead of <b>bold text </b> i am using string.replace() function to replace custom tag with original to tag preview user codes. But how can use forward slash(/) as matching pattern
i have already gone though couples of know method . i have tried
string.replace(/[\/b]/gi,"</b>");
string.replace(/[\x2Fb]/gi,"</b>");
string.replace(/[\x2F b]/gi,"</b>");
Here is code how i am really doing it in my project
//Helper Function
function $(id){
return document.getElementById(id);
}
//Helper Variables//
//Display Preview of question
function render(){//
var question_content = $("question_content").value;
//Sanitizing data//
var entitles = {//List of all Html entitles & custum entitles
'<':"<",
'>':">",
'\n':"<br>",
'[b]':"<b>",
'[/b]':"</b>",
'[i]':"<i>",
'[/i]':"</i>",
'[code]':"<code class='prettyprint'>",
'[/code]':"</code>"
}
question_content = question_content.replace(/<|>|\n|[b]|[\/b]/gi, function (html_ent){return entitles[html_ent];});
//question_content = question_content.replace(/'/, "</b>");
var preview = $("preview");
preview.innerHTML = question_content;
//prettyPrint();
}
Actually, the first approach would have worked if you didn't forget about escaping brackets:
string.replace(/\[\/b]/gi,"</b>");
Only the opening one should be escaped, though; regex engine is smart enough to differentiate between ] as a literal symbol and as a metasymbol (that closed that character class subexpression).
Overall, you can simplify your code by using something like this:
var codes = ['b', 'i', 'code'];
// here goes a little hack to enable special decoration for some elements
codes.code = 'class="prettyprint"';
var string = 'abc[b]abc[/b]da[code]s[/code][something]d';
string.replace(/\[(\/?)([a-z]+)]/gi, function(m, p1, p2) {
return codes.indexOf(p2) !== -1
? '<' + p1 + p2 + (!p1 && p2 in codes ? ' ' + codes[p2] : '') + '>'
: m
});
It's certainly possible to express the same algorithm with a dictionary (object), like this:
var decorators = {
b: '', i: '',
code: 'class="prettyprint"'
};
var string = 'abc[b]abc[/b]da[code]s[/code][something]d';
string.replace(/\[(\/?)([a-z]+)]/gi, function(m, p1, p2) {
return p2 in decorators
? '<' + p1 + p2 +
(!p1 && decorators[p2] ? ' ' + decorators[p2] : '') + '>'
: m;
});
Related
Not certain if this can be done in regexp under javascript, but thought it would be interesting to see if it is possible.
So thought I would clean up a piece of html to remove most tags, literally just dropping them, so <H1><img><a href ....>. And that would be relatively simple (well, stole the basis from another post, thanks karim79 Remove HTML Tags in Javascript with Regex).
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex = /(<([^>]+)>)/ig
var outString = inString.replace(regex, "");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But then I started thinking, is there a way where I can control regex execution. So lets say that I want to keep certain tabs, like b,br,i and maybe change H1-6 to b. So in pseudo code, something like:
for ( var i in inString.regex.hits ) {
if ( hits[i] == H1 ) {
hits[i] = b;
}
}
The issue is that I want the text thats not HTML tags to stay as it is, and I want it to just cut out by default. One option would of course be to change the ones I want to keep. Say change <b> to [[b]], once that is done to all the ones of interest. Then put them back to <b> once all unknown have been removed. So like this (only for b, and not certain the code below would work):
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex-remHTML = /(<([^>]+)>)/ig
var regex-hideB = /(<b>)/ig
var regex-showB = /([b])/ig
var outString = inString.replace(regex-hideB, "[b]");
outString = outString.replace(regex-remHTML, "");
outString = outString.replace(regex-showB, "<b>");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But would it be possible to be smarter, writing cod ethat says here is a peice of HTML tag, run this code against the match.
As Tim Biegeleisen sai in its comment, maybe a better solution could be using a parser instead of a Regex...
By the way, if you want to control what is going to be changed by the regex you can pass a callback to the String.prototype.replace:
var input = "<div><h1>CIAO Bello</h1></div>";
var output = input.replace(/(<([^>]+)>)/gi, (val) => {
if(val.indexOf("div") > -1) {
return "";
}
return val;
})
;
console.log("output", output);
So, I have strings pulled from a JSON array like this:
Hg22+
CO32-
Al3Cl23+
These numbers need to be superscript or subscript, with rules. It's only numbers 0-9, and if that number has a plus or minus after it, it needs to be superscript, meaning I need to change the string to <sup>3+</sup>. All other numbers, if they haven't been superscripted, need to be subscripted. Here are a few examples of what I need:
C12H22O11 (s, sucrose) = <sub>1</sub><sub>2</sub>H<sub>2</sub><sub>2</sub>O<sub>1</sub><sub>1</sub> (s, sucrose)
Al3Cl23+ = Al<sub>3</sub>Cl<sub>2</sub><sup>3+</sup>
Hg22+ = Hg<sub>2</sub><sup>2+</sup>
I can do it, but very sloppily. I am really open to a good way to change string like above. If anyone can help out I'd be really appreciative!
Thanks!
Easy.
var result = input.replace(/\d([+-]?)/g,function(match,plus) {
var s = plus ? "sup" : "sub";
return "<"+s+">"+match+"</"+s+">";
});
Done.
Slightly modified from #Niet the Dark Absol's answer
var tests = ['Hg22+', 'CO32-', 'Al3Cl23+','C12H22O11 (s, sucrose)'];
function chemize(input) {
return input.replace(/\d([\+\-]?)/g,function(match,plus) {
var s = plus ? "sup" : "sub";
return "<"+s+">"+match+"</"+s+">";
});
}
for(var z in tests) {
var test = tests[z];
console.log('"' + test + '" --> ' + chemize(test) );
}
Output:
"Hg22+" --> Hg<sub>2</sub><sup>2+</sup>
"CO32-" --> CO<sub>3</sub><sup>2-</sup>
"Al3Cl23+" --> Al<sub>3</sub>Cl<sub>2</sub><sup>3+</sup>
"C12H22O11 (s, sucrose)" --> C<sub>1</sub><sub>2</sub>H<sub>2</sub><sub>2</sub>O<sub>1</sub><sub>1</sub> (s, sucrose)
sorry i couldn't think of better title ! plus my english sucks
her is my first plugin (basically i repackaged some js code as a plugin )
it adds a comma , separator to value every 3 digit , when someone types something inside textfield
(function($){
$.fn.num = function(userop){
var options = $.extend( {seperator:','} , userop );
$(this).keyup(function(e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace( /\,/g, "");
var x = nStr.split( '.' );
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while ( rgx.test(x1) ) {
x1 = x1.replace( rgx, '$1' + options.seperator + '$2' );
}
$(this).val( x1 + x2 );
})
}
})(jQuery);
$('.number_input').num();
but problem is if i put 123456 in my textfield
var n = $('.number_input').val();
console.log(n);
will return 123,456
which is fine but it suppose to be a numeric value and each time user has to extract commas manually
by running it trough something like
n = Number($.trim(n.replace(/\,/g,'')));
is there any way to add this line to my plugin so it gets executed when someone runs .val() on textfild ?
basically i want to write comma remover once not every single time that i get each effected textfield value
If you change the default .val() method with the combination of the .data(), you'll be able the do what you want. Note that change .val() can have undesired effect (mostly when user try to override .val() aswell...)
Anyway, the first thing to do is give a data to every element that are active number. So in you init, add this code :
this.data('__numered', true);
Now we can detect if the element as a formatting.
Then here come the tricky part : overriding.
You'll have to save the old .val() method :
$.fn.__val = $.fn.val;
Then recreate .val() but check if its a numbered item :
$.fn.val = function(set){
if(typeof set === 'undefined'){
if(this.first().data('__numered'))
return Number($.trim(this.first().__val().replace(/\,/g,'')));
else
return this.first().__val();
}else
return this.__val(set)
}
Fiddle : http://jsfiddle.net/Tw77J/1/
First of all
I think I'm suggesting a better way to do what you are asking, instead of directly answering.
If you use, my solution, your plugin gives the users the option of getting what they want. (You cant predict what users need)
My Solution:
You can add this simple code:
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
So your plugin would become:
(function ($) {
$.fn.num = function (userop) {
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
var options = $.extend({
seperator: ','
}, userop);
$(this).keyup(function (e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace(/\,/g, "");
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + options.seperator + '$2');
}
$(this).val(x1 + x2);
});
};
})(jQuery);
Remember, you are the creator of the plugin, and you can impose some rules for the developers using your plugin.
That said, ask your users to use $('selector').num('val'); to get the value without commas, and $('selector').val(), if they want it with comma.
So to brush up:
Use $('selector').num('val'); // with comma
Use $('selector').val(); // without comma
Put that in readme file or any document file.
Live demo!
Also, don't forget me to add me as a contributor to the plugin, If my answer helped you ;)
I have been working on this most of the morning but to no end. I am trying to execute a button that uses OnClick Java in Salesforce.com and it keeps throwing errors. I think the issue may be with special characters in the data as it works when I simply use just text. But any time numbers or any special characters are present I get the error "unexpected token ILLEGAL". Can anyone help me to see what I am doing wrong and how I can get away from failing when special characters are involved?
{!REQUIRESCRIPT("/soap/ajax/28.0/connection.js")}
var opptyObj = new sforce.SObject("Opportunity");
var caseObj = new sforce.SObject("Case");
var today = new Date();
var sOpptyId = "{!Case.Opportunity__c}";
if( sOpptyId != "")
{
alert("This case is already tied to an opportunity!");
}
else
{
opptyObj.AccountId = "{!Case.AccountId}";
opptyObj.CloseDate = sforce.internal.dateTimeToString(today);
opptyObj.Description="{!Case.Description}";
opptyObj.Case__c = "{!Case.Id}";
opptyObj.Name = "{!Case.Subject}";
opptyObj.StageName = "Estimate in Progress";
opptyObj.Created_from_Case__c = "Y";
opptyObj.Type = "New Business";
opptyObj.Amount = ".01";
var opptyresult = sforce.connection.create([opptyObj]);
if (opptyresult[0].success=='false')
{
alert("Opportunity creation failed: " + opptyresult[0].errors.message);
}
else
{
caseObj.Id = '{!Case.Id}';
caseObj.Opportunity__c = opptyresult[0].id;
caseObj.Status = "Estimate in Progress";
var caseResult = sforce.connection.update([caseObj]);
if(caseResult[0].success == 'false')
{
alert("Case update failed: " + caseResult[0].errors.message);
}
else
{
alert("An opportunity has been created and linked to this case.");
location.reload(true);
}
}
}
Assuming this is some kind of template, whatever is rendering this needs to properly escape some values in the strings it's inserting.
Given this:
opptyObj.Description="{!Case.Description}";
Let's say I enter a description consisting of this:
"That is awesome," said John.
When that is rendered in your template the result is this:
opptyObj.Description=""That is awesome," said John.";
As you might be able to see, the result is a syntax error.
You need to escape quote characters in an text inserted this way. And without knowing what is technology rendering this template I can't give you any specifics, but you want to replace " with \" and ' with \'. The \ escapes characters, forcing them to be treated as literal characters in the string instead of other special meaning.
This must be done as it's being inserted into the script. Something in the spirit of this:
opptyObj.Description="{!Case.Description.replace(/'/, "\\'").replace(/"/, '\\"')}
Exactly how to do that depends on what language or template engine is being used here. But th eresult should look like this:
opptyObj.Description="\"That is awesome,\" said John.";
Ruby on Rails implements an escape_javascript method, which sanitizes data for injection into Javascript. It does the following replacements. It seems like a good baseline.
'\\' => '\\\\'
'</' => '<\/'
"\r\n" => '\n'
"\n" => '\n'
"\r" => '\n'
'"' => '\\"'
"'" => "\\'"
UPDATE:
According to this: http://www.salesforce.com/us/developer/docs/pages/Content/pages_security_tips_scontrols.htm
It looks like you want the JSENCODE function. Something like this, perhaps?
opptyObj.Description="{!JSENCODE(Case.Description)}";
How to replace all HTML tags from <anything> to \n<anything> and </anything> to <anything>\n
var text = "<anything>welcome</anything><anything>Hello</anything>";
result
var text = "\n<anything>welcome</anything>\n\n<anything>Hello</anything>\n";
This code will help you (match all tags)
</?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)/?>
You can prettify xml without regex:
var text = "<anything>welcome</anything><anything>Hello</anything>";
var xml = new XML("<root>" + text + "</root>");
console.log(xml.children().toXMLString());
output:
<anything>welcome</anything>
<anything>Hello</anything>
Just don't parse HTML using regex. Read this: http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html
In JavaScript, you can turn HTML into DOM using the .innerHTML property, and after that you can use other DOM methods to traverse it.
Simple example (needs Firebug):
var div = document.createElement('div');
var html = '<p>foo <span>bar</span><br /></p>';
div.innerHTML = html;
function scan(node, depth)
{
depth = depth || 0;
var is_tag = node.nodeType == 1;
var self_contained = false;
if (is_tag) {
self_contained = node.childNodes.length == 0;
var tag_name = node.tagName.toLowerCase();
console.log('<' + tag_name + (self_contained ? ' /' : '') + '>', depth);
} else {
console.log(node.data);
}
for (var i = 0, n = node.childNodes.length; i < n; i++) {
scan(node.childNodes[i], depth + 1);
}
if (!self_contained && is_tag) {
console.log('</' + tag_name + '>', depth);
}
}
scan(div);
Output:
<div> 0
<p> 1
foo
<span> 2
bar
</span> 2
<br /> 2
</p> 1
</div> 0
You could also modify this to output attributes and use the depth argument for indentation.
Try this:
str.replace(/<(\/?)[a-zA-Z]+(?:[^>"']+|"[^"]*"|'[^']*')*>/g, function($0, $1) {
return $1 === "/" ? $0+"\n" : "\n"+$0;
})
Expanding on #Amarghosh's answer:
Assuming the HTML you are trying to parse is more complicated than your example (which I would guess it is) you may want to convert your HTML page into XHTML. This will allow you to use treat it as XML and do a number of things including:
Use an XSL to transform the data
Use .NET's extensive set of XML
libraries to extract and manipulate the data.
I have done this in the past with a free .NET library called SGML.
text = text.replace(/<(?!\/)/g, "\n<"); // replace every < (which are not followed by /) by \n<