This function in Javascript doesn't works as desired. But when written in C, it works as desired.
var patt_2 = function()
{
for(i=5;i>=1;i--)
{
for(j=1;j<i;j++)
{
$("#panel8").append(" ");
}
for(k=5;k>=i;k--)
{
$("#panel8").append("*");
}
$("#panel8").append("<br/>");
}
};
Undesired output
Desired Output
You could give your #panel8 element the following to allow for non characters to also allow multiple whitespace:
#panel8 {
white-space: pre;
}
You can read here what this does, quote:
This value prevents user agents from collapsing sequences of white space. Lines are only broken at preserved newline characters.
Basically HTML collapses whitespace characters (" ") to create one space, if you use you overcome this issue but creates uglier code in general (since you'll have to append " " to your string all the time).
If your element can have white-space: pre; then this is a clean and easy solution which doesn't require you to edit your script!
P.S. It's not JS in which it's not working but rather HTML or the HTML parser that collapses the whitespace.
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.
I have made a javascript function to replace some words with other words in a text area, but it doesn't work. I have made this:
function wordCheck() {
var text = document.getElementById("eC").value;
var newText = text.replace(/hello/g, '<b>hello</b>');
document.getElementById("eC").innerText = newText;
}
When I alert the variable newText, the console says that the variable doesn't exist.
Can anyone help me?
Edit:
Now it replace the words, but it replaces it with <b>hello</b>, but I want to have it bold. Is there a solution?
Update:
In response to your edit, about your wanting to see the word "hello" show up in bold. The short answer to that is: it can't be done. Not in a simple textarea, at least. You're probably looking for something more like an online WYSIWYG editor, or at least a RTE (Richt Text Editor). There are a couple of them out there, like tinyMCE, for example, which is a decent WYSIWYG editor. A list of RTE's and HTML editors can be found here.
First off: As others have already pointed out: a textarea element's contents is available through its value property, not the innerText. You get the contents alright, but you're trying to update it through the wrong property: use value in both cases.
If you want to replace all occurrences of a string/word/substring, you'll have to resort to using a regular expression, using the g modifier. I'd also recommend making the matching case-insensitive, to replace "hello", "Hello" and "HELLO" all the same:
var txtArea = document.querySelector('#eC');
txtArea.value = txtArea.value.replace(/(hello)/gi, '<b>$1</b>');
As you can see: I captured the match, and used it in the replacement string, to preserve the caps the user might have used.
But wait, there's more:
What if, for some reason, the input already contains <b>Hello</b>, or contains a word containing the string "hello" like "The company is called hellonearth?" Enter conditional matches (aka lookaround assertions) and word boundaries:
txtArea.value = txtArea.value.replace(x.value.replace(/(?!>)\b(hello)\b(?!<)/gi, '<b>$1</b>');
fiddle
How it works:
(?!>): Only match the rest if it isn't preceded by a > char (be more specific, if you want to and use (?!<b>). This is called a negative look-ahead
\b: a word boundary, to make sure we're not matching part of a word
(hello): match and capture the string literal, provided (as explained above) it is not preceded by a > and there is a word boundary
(?!<): same as above, only now we don't want to find a matching </b>, so you can replace this with the more specific (?!<\/b>)
/gi: modifiers, or flags, that affect the entire pattern: g for global (meaning this pattern will be applied to the entire string, not just a single match). The i tells the regex engine the pattern is case-insensitive, ie: h matches both the upper and lowercase character.
The replacement string <b>$1</b>: when the replacement string contains $n substrings, where n is a number, they are treated as backreferences. A regex can group matches into various parts, each group has a number, starting with 1, depending on how many groups you have. We're only grouping one part of the pattern, but suppose we wrote:
'foobar hello foobar'.replace(/(hel)(lo)/g, '<b>$1-$2</b>');
The output would be "foobar <b>hel-lo</b> foobar", because we've split the match up into 2 parts, and added a dash in the replacement string.
I think I'll leave the introduction to RegExp at that... even though we've only scratched the surface, I think it's quite clear now just how powerful regex's can be. Put some time and effort into learning more about this fantastic tool, it is well worth it.
If <textarea>, then you need to use .value property.
document.getElementById("eC").value = newText;
And, as mentioned Barmar, replace() replaces only first word. To replace all word, you need to use simple regex. Note that I removed quotes. /g means global replace.
var newText = text.replace(/hello/g, '<b>hello</b>');
But if you want to really bold your text, you need to use content editable div, not text area:
<div id="eC" contenteditable></div>
So then you need to access innerHTML:
function wordCheck() {
var text = document.getElementById("eC").innerHTML;
var newText = text.replace(/hello/g, '<b>hello</b>');
newText = newText.replace(/<b><b>/g,"<b>");//These two lines are there to prevent <b><b>hello</b></b>
newText = newText.replace(/<\/b><\/b>/g,"</b>");
document.getElementById("eC").innerHTML = newText;
}
We know that \n is used to feed a new line in JavaScript.
How should I use it for an output (in a for-loop):
str=prompt("Enter any string!");
for(i=0;i<str.length;i++)
{
document.write('\n'+str.charCodeAt(i));
}
or
str=prompt("Enter any string!");
for(i=0;i<str.length;i++)
{
document.write('\n'+str.charCodeAt(i));
}
Neither seems to work.
This has nothing to do with JavaScript. In HTML, all whitespace (including newlines) is collapsed and treated as a single space.
To do a line break in HTML:
Use <br>
Or organize your text into paragraphs with <p>...</p>, etc.)
Or if you're outputting some form of formatted text (like code), you can do that in a <pre>...</pre> element (or any element with the white-space: pre, white-space: pre-wrap, or white-space: pre-line style applied to it).
If you're writing to the document you'll want document.write('<br/>'+str.charCodeAt(i));
- or to set your output in a <pre> tag (or another element with the a style attribute of white-space:pre).
I made a much better solution. See it in action https://repl.it/#mamamia5x/Example
In css do
h1 span::before {
content: "\A";
white-space: pre;
}
Replace the h1 with whatever you have. Now, whenever you do <span>, a new line will break. So whenever someone says /n, it'll do the <span> and make a new line.
if (txt.charAt(i) == '/' && txt.charAt(i + 1) =='n'){
document.getElementById("text").innerHTML += " <span>";
i = i + 2;
}
Here is it in action https://repl.it/#mamamia5x/Example, and here is a project I am using it for https://live-stream.mamamia5x.repl.co/.
I also made it work with <br>. If you want to do that, you can do
if (txt.charAt(i) == '<' && txt.charAt(i + 1) == 'b' && txt.charAt(i + 2) == 'r' && txt.charAt(i + 3) == '>'){
You can also mix the two together, and it can allow /n and <br>.
use document.writeln() method .
The writeln() method is identical to the write() method, with the addition of writing a newline character after each statement.
try this
str=prompt("Enter any string!");
for(i=0;i<str.length;i++)
{
document.writeln(str.charCodeAt(i));
}
use <br> instead of \n
it relative to HTML
I want to cut this string into 50 characters where (after a space) it starts counting up to 50 (excluding spaces), and if the section is over 50 it inserts a space. So far, I can cut it up, but I don't know how to specify "exclude spaces". Tried [^\s] but no joy.
var str = " http://this.domain.com/fff/222/widget.css http://www.domain.com/myfolder/uploads/1/3/3/7/2332053/custom_themes/8787687678644/more_custom_themes/files/my-main_style.css?8763487634 http://cdn.domain.com/folder/images/thisfolder/common.css?9444"
str.replace(/\s(\w.{50})/g,' $1 ');
Try this:
var str = " http://this.domain.com/fff/222/widget.css http://www.domain.com/myfolder/uploads/1/3/3/7/2332053/custom_themes/8787687678644/more_custom_themes/files/my-main_style.css?8763487634 http://cdn.domain.com/folder/images/thisfolder/common.css?9444"
str = str.replace(/([^ ]{50})/g, "$1 ");
If your reason for doing this is to prevent a long string from breeaking out of its area in a browser window, you may want to try the CSS solution:
CSS has a word-wrap property, which you can use to tell the browser to break long words even if they don't have a natural break-point.
#divwithlongword {
word-wrap: break-word;
}
Now if you have HTML as follows:
<div id='divwithlongword'>myextraordinarilyandexcessivelylongdomainnamegoeshere.com</div>
...it will wordwrap where it needs to within the domain name.
This is supported in all major browsers -- see http://caniuse.com/#search=wordwrap
Hope that helps.
You use the following regex:
(\S{50})
\S - Matches any character that is not a whitespace character (spaces, tabs, line breaks).
I have an HTML page that I generate from the data contained in a database. The database sometimes contains long strings that the browser can't break because the strings don't contain breakable characters (space, point, comma, etc...).
Is there any way to fix this using html, css or even javascript?
See this link for an example of the problem.
Yes you can, just set the css property of the box to:
.some_selector {
word-wrap: break-word;
}
Edit: Some testing shows that it does work with a div or a p - a block level element - but it does not work with a table cell, nor when the div is put inside a table cell.
Tested and works in IE6, IE7, IE8, Firefox 3.5.3 and Chrome.
Works:
<div style="word-wrap: break-word">aaaaaaaaaaaaaaaaaaaaaaddddddddddddddddddddddddddddddddddddddddddaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa </div>
Based on this article and this one as well: the "Shy Hyphen" or "Soft Hyphen" can be written in HTML as: / / ­ (173 dec = AD hex). They all convert to the U+00AD character.
The JavaScript textContent and nodeValue of the DOM Text Nodes are not 'entity encoded' - they just contain the actual entities. In order to write these characters you must therefore encode them yourself: \xAD is a simple way to write the same character in a JavaScript string. String.fromCharCode(173) would also work.
Based on your own VERY good answer - a jQuery Plugin version:
$.fn.replaceInText = function(oldText, newText) {
// contents() gets all child dom nodes -- each lets us operate on them
this.contents().each(function() {
if (this.nodeType == 3) { // text node found, do the replacement
if (this.textContent) {
this.textContent = this.textContent.replace(oldText, newText);
} else { // support to IE
this.nodeValue = this.nodeValue.replace(oldText, newText);
}
} else {
// other types of nodes - scan them for same replace
$(this).replaceInText(oldText, newText);
}
});
return this;
};
$(function() {
$('div').replaceInText(/\w{10}/g, "$&\xAD");
});
A side note:
I think that the place this should happen is NOT in JavaScript - it should be in the server side code. If this is only a page used to display data- you could easily do a similar regexp replace on the text before it is sent to the browser. However the JavaScript solution offers one advantage(or disadvantage depending on how you want to look at it) - It doesn't add any extraneous characters to the data until the script executes, which means any robots crawling your HTML output for data wont see the shy hyphens. Although the HTML spec interprets it as a "hyphenation hint" and an invisible character its not guaranteed across the rest of the Unicode world: (quote from Unicode standard via the second article I linked)
U+00AD soft hyphen indicates a
hyphenation point, where a line-break
is preferred when a word is to be
hyphenated. Depending on the script,
the visible rendering of this
character when a line break occurs may
differ (for example, in some scripts
it is rendered as a hyphen -, while in
others it may be invisible).
Another Note:
Found in this other SO Question - it seems that the "Zero Width Space" character / / U+200b is another option you might want to explore. It would be \x20\x0b as a javascript string.
As it has been pointed out numerous times, no, there is nothing you can do about it, without preprocessing the strings programmatically before displaying them.
I know there is a strategy with inserting the soft hyphen character (), where needed, but does not seem like a popular option.
Check out this question: Soft hyphen in HTML ( vs. )
It is also possible to use word-break css property to cut every word on the element edge.
.selector_name {
word-break: break-all;
}
<p class="selector_name">some words some words some words some words</p>
you can obtain:
some word|
s some wo|<-edge of the element
rds some |
words som|
e words |
There is special character or that could do it.
For example:
Dzielenie wyrazów
could be display like:
1. dzie
2. le
3. nie wy
5. ra
6. zow
I'm answering my own question here...
Based on your answers, I came up with this solution (thanks to #CMS in this question for his help).
This script breaks any word that is more than 30 characters long by inserting a space at the 31st position.
Here is the fixed version: link
I have one problem left, I'd rather insert a then a space. But the assigning node.nodeValue or node.textContent causes the insertion of the text not the tag.
<script type="text/javascript">
$(function() {
replaceText(/\w{30}/g, "$& ", document.body);
});
function replaceText(oldText, newText, node) {
node = node || document.body; // base node
var childs = node.childNodes, i = 0;
while (node = childs[i]) {
if (node.nodeType == 3) { // text node found, do the replacement
if (node.textContent) {
node.textContent = node.textContent.replace(oldText, newText);
} else { // support to IE
node.nodeValue = node.nodeValue.replace(oldText, newText);
}
} else { // not a text mode, look forward
replaceText(oldText, newText, node);
}
i++;
}
}
</script>
I'll wait a few days before I accept this answer in case someone comes up with a simpler solution.
Thanks
The issue with using and the solutions above is that an extra character is still there, and with a copy/paste action (even in plain text) it comes out.
I would use instead the tag <wbr> that is not visible and is not considered when copying.
For example, to have email addresses break in two lines (only when there is not enough space) I use this:
echo str_replace( "#","<wbr>#", $email );
That results in something like this:
name.surname
#website.com
You can use jQuery to achieve that, but How : Let me explain a little bit. First you need to add the reference and there is a plug-in which may help you : Read More Plugin - JQuery But you need to penetrate your code during the fetch phase. At this point you can handle this problem in HttpHandler or Page_PreInit phase but w/o any server side code it must be hard or perhaps there isn't any way. I don't know but you should be able to add something in your database-fetched html page.
It's easier to break up the long words from a text string, before you add them to the document.
It would also be nice to avoid orphans, where you have only one or two characters on the last line.
This method will insert spaces in every unspaced run of characters longer than n,
splitting it so that there are at least min characters on the last line.
function breakwords(text, n, min){
var L= text.length;
n= n || 20;
min= min || 2;
while(L%n && L%n<min)--n;
var Rx= RegExp('(\\w{'+n+',}?)','g');
text= text.replace(Rx,'$1 ');
return text;
}
//test
var n=30, min=5;
var txt= 'abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz012345678 abcdefghijklmnopqrstuvwxyz01234567 abcdefghijklmnopqrstuvwxyz0123456';
txt=txt.replace(/(\w{30,})/g,function(w){return breakwords(w,n,min)});
alert(txt.replace(/ +/g,'\n'))
/* returned value: (String)
abcdefghijklmnopqrstuvwxyz0123
456789
abcdefghijklmnopqrstuvwxyz0123
45678
abcdefghijklmnopqrstuvwxyz012
34567
abcdefghijklmnopqrstuvwxyz01
23456
*/