HTML / JAVASCRIPT : Disable HTML CONTENT in contentEditable=true - javascript

What I want?
I want a div what works like a textarea, I don't want to have the ability to edit things in the div, and paste images and so on just plain text.
Example
www.facebook.com
- The best example is facebook's news feed.
Why I need this way?
If you check out facebook's news feed, you well see that the area where you can write your post, expands as you write your post or hit a lots of enters.
This is the same reason why I want to use a div with contentEditable, because in textarea I can't do that.
#
PLEASE NO JQUERY only JAVASCRIPT

Resizable Textarea using pure JavaScript without frameworks:
<html>
<head>
<script>
function taOnInput()
{
var dis = this;
setTimeout(
function(){
var span = document.createElement("div");
span.innerHTML = escape(dis.value).replace(/[%]0A/g, "<br/>")+"<br/>."; //Extra BR for padding... TextArea uses %0A, not \n
span.style.width = dis.offsetWidth+"px";
span.style.padding = "0px";
span.style.fontFamily = "Lucida Console";
document.body.appendChild(span); //Offset height doesnt work when not in DOM tree i guess =/? or is it a hack
dis.style.height = span.offsetHeight+"px";
document.body.removeChild(span);
}, 1
); //setTimeout=hack, since oKP is called BEFORE character append.
}
window.onload = function()
{
var resizableTA = document.getElementById("resizableTA");
resizableTA.onkeypress = taOnInput;
}
</script>
<title>ItzWarty - Untitled Document</title>
</head>
<body>
<textarea id="resizableTA">Trololololol</textarea>
</body>
</html>
Very hackish, put it together in less than 10 minutes. Hopefully it'll at least give you an idea.
ONLY tested on Google Chrome 5.0.308.0
Explanation of code, since i fail at commenting
1) before window.onload, the textarea of id "resizableTA" has been created and appended to document.body of DOM tree.
2) window.onload attaches an event handler, taOnInput [textarea on input].
3) textarea on input creates a dummy span, forces its width to the width of the textarea and font style to "Lucida Console", which AFAIK is the default font for textareas, copies the value of the textarea to the span's innerHTML, while replacing %0A [newline that textareas use] with [line break]...
4) span's offsetHeight is the height of the span, which can now be used to force the height of the textarea.
Can anyone confirm that Lucida Console is the default font of textarea? Is it Consola? Courier New? I assumed any fixed-width font would work. I don't use Mac, so I dont know what fonts it shared with windows, though i think Courier New is a better choice...

You don't have to use a DIV. You can still have a textarea and expand it when necessary.
Here is a jQuery plugin that does just that: http://plugins.jquery.com/project/TextAreaResizer
Here is a demo: http://www.itsavesyou.com/TextArea_Resizer_example.htm

It seems to me that the best solution to this is still to use a textarea element, and to use Javascript to resize it as needed in response to content changes.
Textarea elements do allow for manual resizing by default (and this can be controlled by the "resize" CSS property. But sites that implement auto-expanding multi line text fields without rich formatting would primarily do so with textareas combined with styling and Javascript.

Related

Javascript find and higlight text between [quote][/quote] within textarea

I have this HTML code with pre-written message. My goal is to highlight text between [quote] [/quote] in a yellow background once I focus/click on the text area.
<textarea>
This is a test message.
[quote]Wise man said he is wise.[/quote] There could be more quotes too:
[quote]this is second quote [/quote]
He is correct.
</textarea>
Is it possible to do it with pure Javascript? I think it should be something like:
textarea onfocus="function()">
find text between [quote][/quote]
apply yellow background to found text: background Color='#ffc'
....
(and if there is no [quote] [/quote] found then it should do nothing, ie. no warnings).
Since you cannot do that using <textatea> i'd suggest to take a look at
<div contenteditable>
</div>
here's an example:
var area = document.getElementById("area");
var text = area.innerHTML;
area.innerHTML = text.replace(/\[\s*quote.*\](.*)[^[]*\[\s*\/quote.*\]/ig, "<span>$1</span>");
[contenteditable]{
white-space:pre-wrap;
}
[contenteditable] span{
background:#ffc;
}
<div id="area" contenteditable>
This is a test message.
[quote]Wise man said he is wise.[/quote] There could be more quotes too:
[quote]this is second quote [/quote]
He is correct.
</div>
Otherwise, since you cannot treat HTML elements inside a textarea like actual HTML elements in order to highlight them → you should create an in-memory element with the same size (font-size etc) of your textarea, do the above, calculate the positions of the generated span elements, than apply some higlight overlays over the respective positions over your textarea, take care that they "follow-up" if the window resizes... and the story goes...
Here's a jQuery plugin to achieve the above-mentioned:
http://mistic100.github.io/jquery-highlighttextarea/
Currently I'm investigating two approaches: Highlight Text Inside a Textarea, which describes how this plugin is done: https://github.com/lonekorean/highlight-within-textarea
And syntax higlighter for MediaWiki: source, description of approach.
Both of them use additional element behind textarea with the same font and positioning to show background colors. Textarea background is made transparent. Then on edit and scroll you sync contents and scroll between textarea and element behind.
Here is my simplified code for it: https://codepen.io/bunyk-1472854887/full/RLJbNq/
Core logic of the highlighter is like this (some details skipped):
textarea.addEventListener('keyup', textUpdate);
textarea.addEventListener('scroll', scrollUpdate);
function textUpdate() {
var html = html_escape(textarea.value);
enter code here
html = html.replace(/\[quote\](.*?)\[\/quote\]/g, '[quote]<span class="quote">$1</span>[/quote]');
background.innerHTML = html;
}
function scrollUpdate() {
background.scrollTop = textarea.scrollTop;
};

How do I add a default text to the beginning of an html text area?

Im building a personal little social network. As part of the design, all statuses should begin with a default text that shouldn't change, similar to "Hi, my name is…" and then the user finishes the rest. Kind of like an HTML5 placeholder that doesn't go away. What would be the best way to accomplish this?
Please refer this fiddle
If it serves the purpose, then please find the code below.
Markup:
<textarea id='status'>
Hi, my name is...
</textarea>
JavaScript:
document.querySelector('#status').addEventListener('input', function(e){
var defaultText = 'Hi, my name is...',
defaultTextLength = defaultText.length;
if(this.selectionStart === this.selectionEnd && this.selectionStart defaultTextLength {
this.value = defaultText;
}
});
Note: For some dumb reason, I assumed jQuery (note that you do not need jQuery for this, but makes it a little easier).
Here is one solution uses a combination of text-indent and an absolutely positioned <span> (for the prefix part).
Demo: http://jsfiddle.net/4YzZy/
$('textarea.withprefix').each(function() {
var prefix = $('<span/>')
.text($(this).data('prefix'))
.addClass('prefix')
.appendTo('body')
.css({
left: $(this).position().left + 'px',
top: $(this).position().top + 'px',
});
$(this).css({textIndent: prefix.outerWidth() + 'px'});
});
textarea, span.prefix {
font-family: arial; /* change these as needed, but ensure that the textarea and the span use the same font */
font-size: 1em;
font-weight: normal;
padding: 2px;
border-width: 1px;
}
span.prefix {
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="withprefix" data-prefix="Hi There, "></textarea>
If you want to use javascript to perform your task, you can set up some event listeners and then when the user makes a change, check to see if that change affected the text you want changed. Sarbbottam's new code does this, but it will replace any text you have already typed if you modify the original text. I have fixed this by saving the previous value of the textarea.
HTML:
<textarea id="text">Hello, my name is </textarea>
Javascript:
var defaultText = "Hello, my name is ";
var valueOnKeyDown = new Array();
document.getElementById("text").addEventListener("keydown", function() {
valueOnKeyDown.push(this.value);
}, false);
document.getElementById("text").addEventListener("keyup", function(e) {
if(valueOnKeyDown[0].substring(0, defaultText.length) != this.value.substring(0, defaultText.length)) {
this.value = valueOnKeyDown[0];
}
valueOnKeyDown = new Array();
}, false);
And of course a working demo.
Another option that may work that is not mentioned in the other answers is to set up a keydown/keypress event listener and get the caret position in the textarea using javascript. If it is less than the length of your default text, you just call event.preventDefault(). The main disadvantage to this is that it may not be possible to make this completely cross-browser compatible.
If the goal is that the user cannot change this text then you can do a couple of things:
add the text outside of the textarea (above it for instance)
Add the text outside of the textarea but place it behind the textarea using css. You can make the textarea transparent so the user can see the text. The problem there would be that the text the user types can fall over the text you placed in the background
Put it in a background image of the textarea
Place the text inside the textarea (<textarea>Hi, my name is </textarea>) and use JavaScript to test for what has been typed and change the text if it changes into something that you do not want. There are masking plugins that you can use to do this.
The best options would be the first option and the forth. I'd go the first as it is by far the easiest

How to get the HTML before, inside, and after a selection (not in textarea)?

Here is what I am trying to accomplish: When a user uses a mouse, keyboard, or touch to select text inside "myDiv" I want to acquire three discreet chunks of HTML: the HTML before the selection (to the "left" of it), the HTML inside the selection, and the HTML after the selection (to the "right" of it). The html should be as it would appear with myDiv.innerHTML.
The selection might start or end inside a tag pair (i.e., the isolated selection isn't necessarily valid HTML). I don't need to deal with special scenarios like absolute-positioned elements within the selection; all of the selections I am concerned with will be constrained to one div that will contain basic tags like strong, em, ul, ol, h1, image, and table.
The closest I've come is using rangy to snag the selection and calling selection.getRangeAt(0).cloneContents() to get the selection HTML. This works well enough until I make a selection that is invalid in isolation, and the browser alters the HTML of the document fragment to make it valid markup.
Extra Information: Here's why I need this:
I am creating a document feedback system, so I need to save the selection information to a database for later retrieval and reconstitution. Normally I would save the selection using the DOM path and the selected text, but the text may change between saving and reconstitution. For example, the author might move entire paragraphs around, delete sections, etc. The DOM path becomes pretty useless then.
So my (imperfect) plan is to store the selection as [offset, length, html_snippet]. That's the "position". I'll also store the html snippets that came directly before and after the selected text. This is the "context".
Using a combination of these data I should be able to relocate the originally selected text most of the time, even if it has moved or partially changed. When that fails, the UI will have a way to address it, but I'd like that to occur as infrequently as possible.
Superthanks!
I have several questions:
1.- When you say 'the html after the selection' - how would that html be any different than the html previous to the selection or viceversa? Is the 'selection' process itself tampering with the html because of your 'script' or whatever?
2.- You said the text selections are not taking place in textareas...what elements are you working with then? paragraphs? divs...? Narrowing it down would help.
3.- Have you thought about using jquery?
http://api.jquery.com/select/
Doing something like
$('#element_with_text_goes_here').select(function() {
//apply grabbing functions here, for example
//copy html 'before' selection:
$pre_html = $('html').clone();
// copy selection...see below:
// copy html 'after' selection'...same as before
});
Copy selection:
As noted here:
Selecting text in an element (akin to highlighting with your mouse)
Jason wrote the following function:
function selectText(element) {
var doc = document;
var text = doc.getElementById(element);
if (doc.body.createTextRange) { // ms
var range = doc.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (window.getSelection) { // moz, opera, webkit
var selection = window.getSelection();
var range = doc.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
}
}
With a live working demo that can be found here:
http://jsfiddle.net/edelman/KcX6A/339/
And a jquery plugin version here:
http://jsfiddle.net/edelman/KcX6A/340/
Which you can use for the obtention of the selected text. You'll just have to tweak it accordingly since he was approaching it from a reversed angle.
The more details you can give us...the better we can help.
Hope this helps
G
This code gets html/text from user's selection, but it works in IE only. The code works with cross-tag selection too. (Globals used to keep the code short.)
<script>
function selected(){
thediv=document.getElementById('div');
res=document.getElementById('htm');
userSelection=document.selection;
userRange=userSelection.createRange();
/* For wider scale of elements */
// rangeParent=userRange.parentElement();
// if(rangeParent!=thediv) userRange.moveToElementText(rangeParent);
rangeText=userRange.htmlText; // OR: rangeText=userRange.text;
res.innerText=rangeText;
return;
}
</script>
</head>
<body onload="document.onselectionchange=selected;">
<div id="div">
<h1>The great testpage</h1>
<p>A paragraph with some text</p>
<p>This paragraph <b>contains</b> a child element.</p>
<p>And this is the last paragraph.</p>
<table>
<tr><td>Cell1-1</td><td>cell1-2</td></tr>
<tr><td>Cell2-1</td><td>cell2-2</td></tr>
</table>
<ol>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ol>
</div>
<br>
<span id="htm"></span>
</body>
Content before&after selection in the thediv you'll get like this: prepost=thediv.innerHTML/innerText.split(rangeText);
If the page contains any other elements but thediv, they have to be made unselectable.

Filter out HTML Tag onpaste for div and oncopy too

I have an editable DIV in my site to send a forum message. People can edit their messages (Bold, Italic, underline, add links and more)
But I want when some one paste or drop (- drop is not necessary, but paste it is) their text I want it to go in the DIV without HTML tags - clean, just text. (like if some one is going to word and make the text 200 points size, then copy & paste it in my DIV, they will have a very different message... and I don't want it to happen).
How can I scan the text coming from the clipboard to remove any HTML tags and then paste it in the DIV?
<html>
<head>
<script type="text/javascript" language="javascript">
function PasteFilter()
{
//windows.clipboardData filter on paste to go here
}
function CopyFilter()
{
//windows.clipboardData filter on copy to go here
}
</script>
</head>
<body>
<Div class="body" onpaste="PasteFilter()" oncopy="CopyFilter">
<!-- div content goes here.-->
</Div>
</body>
</html>
I would like to also apply the same filter with COPY too.
Thanks
I believe there are 2 ways to do this:
1) The easy way - insert the following code in PasteFilter():
var foo = window.clipboardData.getData('Text');
window.clipboardData.setData('Text', foo);
the first line gets the Text value of clipboardData (already stripped of HTML tags)
and the second line sets the clipboardData to the plain text...
(Tested on IE8)
2) The other way - if for some reason that isn't suitable for you..
In PasteFilter(), you trigger another function with a small delay timeout.
In that function, you get the innerHTML contents of the DIV and run a regular expression to remove all tags.
Example:
function PasteFilter()
{
setTimeout('foo()', 200);
}
function foo()
{
var contents = document.getElementById("test").innerHTML;
var new_contents = contents.replace(/(<([^>]+)>)/g, ""); // taken from http://css-tricks.com/snippets/javascript/strip-html-tags-in-javascript/
document.getElementById("test").innerHTML = new_contents;
}
The problem with this method is that you lose the caret position...
Hope this helps...

CKEDITOR.replace() is hiding the textarea that I want converted

I'm using Javascript to create a textarea that I want to be a ckeditor. My code is something like
var html = '<textarea name="text"></textarea>';
$('#mydiv').append(html);
var textareas = document.getElementsByTagName('textarea');
// Could be more than one textarea
for (i = 0; i<textareas.lenght; i++) {
var textarea = textareas[i];
CKEDITOR.replace(textarea.name);
}
When I run this code and check the output the textarea is hidden. Inspecting it in firebug I'm getting a style="visibilty:hidden". However removing this just gives me a textarea and not a ckeditor. Does anyone have any suggestions on how to solve it.
Putting it as a div worked but the examples all seemed to be in textareas.
The hiding is correct. Because the <textarea/> has no wysiwyg support. The .replace() method replaces the <textarea/> with it's wysiwyg Editor. That's why it's hidden.
CKEDITOR.replace(elementOrIdOrName, config)
Replaces a or a DOM element (DIV) with a CKEditor instance. Source
As you can see in the documentation you don't need to append the <textarea/>, instead you could use your div directly:
CKEDITOR.replace('mydiv')

Categories