I am trying to replace the symbol at the end of a paragraph, when some event happens. The original symbol is a square box ☐ and I use its ASCII in the code.
A sample Paragraph would be Problem No:1 ☐
This symbol is to be replaced by the symbol of a square box with a cross inside ☒
SO final paragraph would like Problem No:1 ☒
The routine to change the end symbol is as follows:
$(document).on("change", 'input[type=radio]', function (e) {
e.preventDefault();
var x = $(this).attr('id');
var y = x.substring(17);
var z = $("#QuestionBankLink"+y).text();
var a = z.substring(0,13);
var b = a + " ☒";
$("#QuestionBankLink"+y).text(b);
});
As one can understand the id of the paragraph is QuestionBankLink followed by a number (basically a reference)
Now my problem is when the code is executed everything works fine except the fact that instead of symbol at the end I get the full set of characters of the ASCII. So what I get is:
Problem No:1 ☒
Where am I wrong?
Change $("#QuestionBankLink"+y).text(b); to $("#QuestionBankLink"+y).html(b);
The .text() method injects text exactly as it's in the string, with all tags and entities
You don't need to get the substring to find the character and replace. In Jquery replace function you can directly provide the charecter to replace as given below.
$("#QuestionBankLink"+y).text($("#QuestionBankLink"+y).text().replace('☐','☒'));
I have attached a demo snippet below
$(document).ready(function() {
$('#replace').click(function(){
$("p").text($("p").text().replace('☐','☒'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
Problem No:1 ☐
</p>
<button id='replace'>
Replace
</button>
Instead of " ☒" (or in hexadeciaml " ☒")
use " ☒" or " \u2612"
☒ is an HTML decimal numeric character entity reference. Characters in HTML are Unicode codepoints.
"\u2612" is a JavaScript escaped literal for a UTF-16 code unit. UTF-16 is a character encoding for the Unicode character set.
"☒" is a JavaScript literal. It will work if your editor, saved file encoding, optional HTML meta charset tag, server's HTTP Content-Type charset header all line up, on, for example, UTF-8—which should not be a problem.
Of course, ☒, being a Unicode character, can be used in HTML, too.
Related
I'm currently experimenting with TipTap, an editor framework.
My goal is to build a Custom Node extension for TipTap that wraps a single word in <w>-Tags, whenever a user is typing text. In TipTap I can write an InputRule with Regex for this purpose
For example the rule /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/ will match text between two tildes (~text~) and wrap it with <strike>-Tags.
Click here for my Codesandbox
I was trying for so long and can't figure it out. Here are the rules that I tried:
/**
* Regex that matches a word node during input
*/
// Will match words between two tilde characters; I'm using this expression from the documentation as my starting point.
//const inputRegex = /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/
// Will match a word but will append the following text to that word without the space inbetween
//const inputRegex = /\b\w+\b\s$/
// Will match a word but will append the following text to previous word without the space inbetween; Will work with double spaces
//const inputRegex = /(?:^|\s\b)(?:[^\s])(\w+\b)(?:\s)$/
// Will match a word but will swallow every second character
//const inputRegex = /\b([^\s]+)\b$/g
// Will match every second word
//const inputRegex = /\b([^\s]+)\b\s(?:\s)$/
// Will match every word but swallow spaces; Will work if I insert double spaces
const inputRegex = /\b([^\s]+)(?:\b)\s$/
The problem here is the choice of delimiter, which is space.
This becomes clear when we see the code for markInputRule.ts (line 37 to be precise)
if (captureGroup) {
const startSpaces = fullMatch.search(/\S/)
const textStart = range.from + fullMatch.indexOf(captureGroup)
const textEnd = textStart + captureGroup.length
const excludedMarks = getMarksBetween(range.from, range.to, state.doc)
When we are using '~' as delimiters, the input rule tries to place the markers for start and end, without the delimiters and provide the enclosed-text to the extension tag (CustomItalic, in your case). You can clearly test this when entering strike-through text with enclosing '~', in which case the '~' are extracted out and the text is put inside the strike-through tag.
This is exactly the cause of your double-space problem, when you are getting the match of a word with space, the spaces are replaced and then the text is entered into the tag.
I have tried to work around this using negative look-ahead patterns, but the problem remains in the code of the file mentioned above.
What I would suggest here is to copy the code in markInputRule.ts and make a custom InputRule as per your requirements, which would be way easier than working with the in-built one. Hope this helps.
I assume the problem lies within the "space". Depending on the browser, the final "space" is either not represented at all in the underlying html (Firefox) or replaced with (e.g. Chrome).
I suggest you replace the \s with (\s|\ ) in your regex.
My goal is to take a markdown text and create the necessary bold/italic/underline html tags.
Looked around for answers, got some inspiration but I'm still stuck.
I have the following typescript code, the regex matches the expression including the double asterisk:
var text = 'My **bold\n\n** text.\n'
var bold = /(?=\*\*)((.|\n)*)(?<=\*\*)/gm
var html = text.replace(bold, '<strong>$1</strong>');
console.log(html)
Now the result of this is : My <\strong>** bold\n\n **<\strong> text.
Everything is great aside from the leftover double asterisk.
I also tried to remove them in a later 'replace' statement, but this creates further issues.
How can I ensure they are removed properly?
With your pattern (?=\*\*)((.|\n)*)(?<=\*\*) you assert (not match) with (?=\*\*) that there is ** directly to the right.
Then directly after that, you capture the ** using ((.|\n)*) so then it becomes part of the match.
Then at the end you assert again with (?<=\*\*) that there is ** directly to the left, but ((.|\n)*) has already matched it.
This way so you will end up with all the ** in the match.
You don't need lookarounds at all, as you are already using a capture group.
In Javascript you could match the ** on the left and right and capture any character in a capture group:
\*\*([^]*?)\*\*
Regex demo
But I would suggest using a dedicated parser to parse markdown instead of using a regex.
Just make another call to replaceAll removing the ** with and empty string.
var text = 'My **bold\n\n** text.\n'
var bold = /(?=\*\*)((.|\n)*)(?<=\*\*)/gm
var html = text.replace(bold, '<strong>$1</strong>');
html = html.replaceAll(/\*\*/gm,'');
console.log(html)
I'm outputting values from a database (it isn't really open to public entry, but it is open to entry by a user at the company -- meaning, I'm not worried about XSS).
I'm trying to output a tag like this:
Click Me
DESCRIPTION is actually a value from the database that is something like this:
Prelim Assess "Mini" Report
I've tried replacing " with \", but no matter what I try, Firefox keeps chopping off my JavaScript call after the space after the word Assess, and it is causing all sorts of issues.
I must bemissing the obvious answer, but for the life of me I can't figure it out.
Anyone care to point out my idiocy?
Here is the entire HTML page (it will be an ASP.NET page eventually, but in order to solve this I took out everything else but the problem code)
<html>
<body>
edit
</body>
</html>
You need to escape the string you are writing out into DoEdit to scrub out the double-quote characters. They are causing the onclick HTML attribute to close prematurely.
Using the JavaScript escape character, \, isn't sufficient in the HTML context. You need to replace the double-quote with the proper XML entity representation, ".
" would work in this particular case, as suggested before me, because of the HTML context.
However, if you want your JavaScript code to be independently escaped for any context, you could opt for the native JavaScript encoding:
' becomes \x27
" becomes \x22
So your onclick would become:DoEdit('Preliminary Assessment \x22Mini\x22');
This would work for example also when passing a JavaScript string as a parameter to another JavaScript method (alert() is an easy test method for this).
I am referring you to the duplicate Stack Overflow question, How do I escape a string inside JavaScript code inside an onClick handler?.
<html>
<body>
edit
</body>
</html>
Should do the trick.
Folks, there is already the unescape function in JavaScript which does the unescaping for \":
<script type="text/javascript">
var str="this is \"good\"";
document.write(unescape(str))
</script>
The problem is that HTML doesn't recognize the escape character. You could work around that by using the single quotes for the HTML attribute and the double quotes for the onclick.
<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>
This is how I do it, basically str.replace(/[\""]/g, '\\"').
var display = document.getElementById('output');
var str = 'class="whatever-foo__input" id="node-key"';
display.innerHTML = str.replace(/[\""]/g, '\\"');
//will return class=\"whatever-foo__input\" id=\"node-key\"
<span id="output"></span>
If you're assembling the HTML in Java, you can use this nice utility class from Apache commons-lang to do all the escaping correctly:
org.apache.commons.lang.StringEscapeUtils Escapes and unescapes
Strings for Java, Java Script, HTML, XML, and SQL.
Please find in the below code which escapes the single quotes as part of the entered string using a regular expression. It validates if the user-entered string is comma-separated and at the same time it even escapes any single quote(s) entered as part of the string.
In order to escape single quotes, just enter a backward slash followed by a single quote like: \’ as part of the string. I used jQuery validator for this example, and you can use as per your convenience.
Valid String Examples:
'Hello'
'Hello', 'World'
'Hello','World'
'Hello','World',' '
'It\'s my world', 'Can\'t enjoy this without me.', 'Welcome, Guest'
HTML:
<tr>
<td>
<label class="control-label">
String Field:
</label>
<div class="inner-addon right-addon">
<input type="text" id="stringField"
name="stringField"
class="form-control"
autocomplete="off"
data-rule-required="true"
data-msg-required="Cannot be blank."
data-rule-commaSeparatedText="true"
data-msg-commaSeparatedText="Invalid comma separated value(s).">
</div>
</td>
JavaScript:
/**
*
* #param {type} param1
* #param {type} param2
* #param {type} param3
*/
jQuery.validator.addMethod('commaSeparatedText', function(value, element) {
if (value.length === 0) {
return true;
}
var expression = new RegExp("^((')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))(((,)|(,\\s))(')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))*$");
return expression.test(value);
}, 'Invalid comma separated string values.');
I have done a sample one using jQuery
var descr = 'test"inside"outside';
$(function(){
$("#div1").append('Click Me');
});
function DoEdit(desc)
{
alert ( desc );
}
And this works in Internet Explorer and Firefox.
You can copy those two functions (listed below), and use them to escape/unescape all quotes and special characters. You don't have to use jQuery or any other library for this.
function escape(s) {
return ('' + s)
.replace(/\\/g, '\\\\')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\u00A0/g, '\\u00A0')
.replace(/&/g, '\\x26')
.replace(/'/g, '\\x27')
.replace(/"/g, '\\x22')
.replace(/</g, '\\x3C')
.replace(/>/g, '\\x3E');
}
function unescape(s) {
s = ('' + s)
.replace(/\\x3E/g, '>')
.replace(/\\x3C/g, '<')
.replace(/\\x22/g, '"')
.replace(/\\x27/g, "'")
.replace(/\\x26/g, '&')
.replace(/\\u00A0/g, '\u00A0')
.replace(/\\n/g, '\n')
.replace(/\\t/g, '\t');
return s.replace(/\\\\/g, '\\');
}
Escape whitespace as well. It sounds to me like Firefox is assuming three arguments instead of one. is the non-breaking space character. Even if it's not the whole problem, it may still be a good idea.
You need to escape quotes with double backslashes.
This fails (produced by PHP's json_encode):
<script>
var jsonString = '[{"key":"my \"value\" "}]';
var parsedJson = JSON.parse(jsonString);
</script>
This works:
<script>
var jsonString = '[{"key":"my \\"value\\" "}]';
var parsedJson = JSON.parse(jsonString);
</script>
You can use the escape() and unescape() jQuery methods. Like below,
Use escape(str); to escape the string and recover again using unescape(str_esc);.
I am using below regex to find the content of title tag in a given string:
alert("<title >kjkj</title><title>jjjjj</title>".match(/<title[^>]*>([^<]+)<\/title>/)[1]);
Next I want to find the content of meta property="og:title" :
<meta property="og:title" content="The Rock" /> is a string
I have no clue how to do that. I can't use jQuery or create any DOM element. Its pure a string and i have to work on a given string only
Ok, no DOM, here is the regex:
/content\=\"([A-Za-z0-9 _]*)\"/
And if for some reason there are other content attributes in the string that you don't want to match you can just be more specific:
/meta\sproperty\=\"og\:title\"\scontent\=\"([A-Za-z0-9 _]*)\"/
This is a very helpful site where it is easy to test regexes of different types.
While it is possible, and generally suggested, to get attributes without using regex, I've created one that will attempt to pull all attributes from an html tag string.
var string = 'Next >';
var regex = new RegExp('[\\s\\r\\t\\n]*([a-z0-9\\-_]+)[\\s\\r\\t\\n]*=[\\s\\r\\t\\n]*([\'"])((?:\\\\\\2|(?!\\2).)*)\\2', 'ig');
var attributes = {};
while ((match = regex.exec(string))) {
attributes[match[1]] = match[3];
}
Outputs:
{
href: "next.html",
onclick: "var target='_blank'; window.open(this.href + \"?test=1\", target); return false;",
target: "_self",
title: "'Next' >>"
}
It works by expecting an equals sign that follows letters, numbers, underscores and hyphens, and is also followed by either a quotation mark or apostrophe. It'll use the match for the apostrophe/quotation mark to determine when the attribute ends, in case the attribute also contains other apostrophe or quotation marks.
I've tried to account for possible line breaks and spacing, however, I've still found some edge cases where it will have issues where the attribute contains an equals signs.
EDIT
Adjusted the above code to double escape whitespace and lines, as well as fix issues with nested equals signs = and escaped quotes \" and apostrophes \'.
You can get title tag text and meta tag attributes simply using this Jquery.
var title = $('title').text();
var meta_property = $('meta').attr('property');
Here is an example:
$(function() {
$('#test').change(function() {
$('#length').html($('#test').val().length)
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=test maxlength=10></textarea>
length = <span id=length>0</span>
Fill textarea with lines (one character at one line) until browser allows.
When you finish, leave textarea, and js code will calculate characters too.
So in my case I could enter only 7 characters (including whitespaces) before chrome stopped me. Although value of maxlength attribute is 10:
Here's how to get your javascript code to match the amount of characters the browser believes is in the textarea:
http://jsfiddle.net/FjXgA/53/
$(function () {
$('#test').keyup(function () {
var x = $('#test').val();
var newLines = x.match(/(\r\n|\n|\r)/g);
var addition = 0;
if (newLines != null) {
addition = newLines.length;
}
$('#length').html(x.length + addition);
})
})
Basically you just count the total line breaks in the textbox and add 1 to the character count for each one.
Your carriage returns are considered 2 characters each when it comes to maxlength.
1\r\n
1\r\n
1\r\n
1
But it seems that the javascript only could one of the \r\n (I am not sure which one) which only adds up to 7.
It seems like the right method, based on Pointy's answer above, is to count all new lines as two characters. That will standardize it across browsers and match what will get sent when it's posted.
So we could follow the spec and replace all occurrences of a Carriage Return not followed by a New Line, and all New Lines not followed by a Carriage Return, with a Carriage Return - Line Feed pair.
var len = $('#test').val().replace(/\r(?!\n)|\n(?!\r)/g, "\r\n").length;
Then use that variable to display the length of the textarea value, or limit it, and so on.
For reasons unknown, jQuery always converts all newlines in the value of a <textarea> to a single character. That is, if the browser gives it \r\n for a newline, jQuery makes sure it's just \n in the return value of .val().
Chrome and Firefox both count the length of <textarea> tags the same way for the purposes of "maxlength".
However, the HTTP spec insists that newlines be represented as \r\n. Thus, jQuery, webkit, and Firefox all get this wrong.
The upshot is that "maxlength" on <textarea> tags is pretty much useless if your server-side code really has a fixed maximum size for a field value.
edit — at this point (late 2014) it looks like Chrome (38) behaves correctly. Firefox (33) however still doesn't count each hard return as 2 characters.
It looks like that javascript is considering length of new line character also.
Try using:
var x = $('#test').val();
x = x.replace(/(\r\n|\n|\r)/g,"");
$('#length').html(x.length);
I used it in your fiddle and it was working. Hope this helps.
That is because an new line is actually 2 bytes, and therefore 2 long. JavaScript doesn't see it that way and therefore it will count only 1, making the total of 7 (3 new lines)
Here's a more universal solution, which overrides the jQuery 'val' function. Will be making this issue into a blog post shortly and linking here.
var originalVal = $.fn.val;
$.fn.val = function (value) {
if (typeof value == 'undefined') {
// Getter
if ($(this).is("textarea")) {
return originalVal.call(this)
.replace(/\r\n/g, '\n') // reduce all \r\n to \n
.replace(/\r/g, '\n') // reduce all \r to \n (we shouldn't really need this line. this is for paranoia!)
.replace(/\n/g, '\r\n'); // expand all \n to \r\n
// this two-step approach allows us to not accidentally catch a perfect \r\n
// and turn it into a \r\r\n, which wouldn't help anything.
}
return originalVal.call(this);
}
else {
// Setter
return originalVal.call(this, value);
}
};
If you want to get remaining content length of text area then you can use match on the string containing the line breaks.
HTML:
<textarea id="content" rows="5" cols="15" maxlength="250"></textarea>
JS:
var getContentWidthWithNextLine = function(){
return 250 - content.length + (content.match(/\n/g)||[]).length;
}
var value = $('#textarea').val();
var numberOfLineBreaks = (value.match(/\n/g)||[]).length;
$('#textarea').attr("maxlength",500+numberOfLineBreaks);
works perfectly on google already in IE have to avoid the script! In IE the 'break-line' is counted only once, so avoid this solution in IE!
Textareas are still not fully in sync among browsers. I noticed 2 major problems: Carriage returns and Character encodings
Carriage return
By default are manipulated as 2 characters \r\n (Windows style).
The problem is that Chrome and Firefox will count it as one character. You can also select it to observe there is an invisivle character selected as a space.
A workaround is found here:
var length = $.trim($(this).val()).split(" ").join("").split('\n').join('').length;
Jquery word counts when user type line break
Internet explorer on the other hand will count it as 2 characters.
Their representation is :
Binary: 00001101 00001010
Hex: 0D0A
, and are represented in UTF-8 as 2 characters and counted for maxlength as 2 characters.
The HTML entities can be
1) Created from javascript code:
<textarea id='txa'></textarea>
document.getElementById("txa").value = String.fromCharCode(13, 10);
2) Parsed from the content of the textarea:
Ansi code:
<textarea>Line one.
Line two.</textarea>
3) Inserted from keyboard Enter key
4) Defined as the multiline content of the textbox
<textarea>Line one.
Line two.</textarea>
Character Encoding
Character encoding of an input field like textarea is independent than the character encoding of the page. This is important if you plan to count the bytes. So, if you have a meta header to define ANSI encoding of your page (with 1 byte per character), the content of your textbox is still UTF-8 with 2 bytes per character.
A workaround for the character encoding is provided here:
function htmlEncode(value){
// Create a in-memory div, set its inner text (which jQuery automatically encodes)
// Then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
function htmlDecode(value){
return $('<div/>').html(value).text();
}
HTML-encoding lost when attribute read from input field