I want to build a lightweight online text editor like google doc, but quite quite lighter than that.
What I mean is, I only want to realize the following three functions:
input/delete characters
create/delete a new line
indent
But I'm not quite sure how to build it.
Here is my idea:
Treat every line as a single div.
Monitor the keyboard event, when user hit enter, create a new div
According to my method, I need to set the div's contentEditable=true
However, after that, whenever I hit enter, a newline is created inside the div.
So, how to stop that? (can it only be solved by using javascript?)
Or, is there any other way to achieve my goal?
Just use event.preventDefault(); like so:
$(document).bind("keydown keypress", function(event) {
if ( event.which == 13 ) {
event.preventDefault();
// Your code here
}
});
I think you mean text editors like tinymce or CKEditor. You can make them as lighter as you want.
Be careful about letting people do this on your webpage -- if you're not properly escaping/monitoring input, they can wreak havoc on the page itself preventing them from being able to save things, etc.
Most of these editors implement their editor as an embedded iframe. Since it's being served from the same port, protocol and host, you have full script access to it.
So you make a tag in the iframe editable, and leave all the controls outside the iframe. When they click on a control, you make that happen in the iframe.
When they save, you just grab the contents of the iframe's div.
I would read the keyboard events and just modify the DOM to reflect those keyboard changes. The biggest problem you will have is to position the 'caret' (vertical line').View this SO question to do this correctly -> calculate-text-width-with-javascript
Another alternativ, and one that I prefer, is to use the tag. Its a more lightweight solution and comes with text measurement built-in. Google Closure library has a lot of support for this built in -> Closure Library, and example with text selection -> Canvas Text
Related
I am making an HTML textarea that accepts tab key input using JavaScript.
When I searched for a solution on the web, I found this answer, but after some fiddling, I found out that ctrl+z stops working after I hit tab key.
Doing some more experiments revealed that changing the value attribute was likely the culprit of this problem. Here is a small scale code example that you can hopefully reproduce this behavior yourself.
https://codepen.io/MartianLord/pen/gORKPGp?editors=1010
I managed to find a workaround using document.execCommand to simulate the user input, but this method is deprecated as you can see here, so I am looking for a more up to date solution.
To support ctrl+z while using tab in <textarea>, you need to implement undo, redo functions to connect with <textarea>. When the <textarea> changes, record the changes in the history, and revert when ctrl+z key input occurs.
UndoRedojs is a library for this task.
I think there will be a lot of work to be done, such as setting the selection position, in order to fully implement it. I recommend using a text editor that has already been created.
I am allowing my users to add YouTube embedded videos via the TinyMCE editor. I know that the content of the WYSIWYG is going into a responsive website, I want to automatically wrap the in the fluid width video wrapper (https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php).
So anywhere we have an Iframe inserted I want to wrap that in a div class=videoWrapper. I can't seem to find how I can wrap around existing content. Thanks in advance.
There are two questions here that will change how you can do this...
At what point do you have to have this <div> in place?
Does it have to happen when content is inserted?
Can you do this work when you go to save the content?
What are the ways people can insert this video data?
Do you have a custom UI to do this?
Are you relying on the TinyMCE Insert Media dialog?
Other?
To address item #1 above:
If you don't need to add this at the moment the content is added you can always add this when the content is posted to the server for storage. You can walk the DOM and look for the releavant <iframe> tags and wrap them in the <div>. This is likely the simplest approach as you only do this on content save and its done on the server which is a more controlled environment. This would also catch people using code view and removing your wrapper <div> in a subsequent editing session.
If you have to add things on the fly then item #2 becomes important...
If you have only one way to add the <iframe> then you can look at how they are doing that and see if that approach fires any event(s) that you can use to be notified (e.g. there are events for paste, keyup, etc). If there are multiple ways to add this data (Insert Media, copy/paste, code view, etc) then it will be pretty hard to find events that work for all of these possible approaches.
Note: Not all TinyMCE plugins fire events for everything they are doing so you may not find an event that you can catch right when the content is entered regardless of how its added.
If that is the case you can use one of TinyMCE's generic events (e.g. 'change') and look for unwrapped <iframe> tags at that time:
tinymce.init({
selector: '#myTextarea',
setup: function (editor) {
editor.on('change', function () {
//Update the DOM here
});
}
})
The built in editor events are documented here: https://www.tinymce.com/docs/advanced/events/
As we know can set contenteditable in DIV to allow editable. It can make same like Textarea.
However there's the most big different are the "content copy and paste" to DIV and Textarea.
DIV is allow html/plain but Textarea only serve plain text.
Below are the method to solve those problem:-
Method 1 - Direct using window.clipboardData.getData('Text') ( will prompt for asking permission).
Problem : Mozilla and chrome are not support clipboarddata.
Method 2 - Using flash.
Problem : Flash v.10 has upgraded to new rules which cannot get clipboarddata without user first initialize.
Method 3- Using "onpaste" event. When data paste on div -> Set focus
on hidden textarea -> Get value from hidden textarea and set into div
by using setTimeout -> clear hidden textarea.
Problem : The timing set value to hidden textarea are not consistent.
I have saw google was doing well on this.
For IE , use clipboarddata.
For Mozilla,others (not support html5) - Anyone know how google done it ?
Hint: use iframe designmode ?
For Chrome (support html5) - Just set DIV to Contenteditable="plaintext-only".
The trick that I use for this kind of thing is to have an offscreen <textarea>, which is not visible to the user.
The textarea is focussed and has a keyboard handler that notices whether the user is typing in the textarea. As I detect the user is typing, I grab the value of the textarea and dump it in the div.
This is the basic idea. You'll need a bit more to get the look and feel right:
you can't just hide the textarea with display:none or visibility:hidden because that will generally make it insensitive to typing and events too. So you need to make it really small and position it outside the screen, or stack it behind some other element.
you're going to have to detect whether the textarea blurs and decide if you need to refocus it.
You'll want a click handler on the div so that if people click the div you can focus to the textarea instead so people can start typing again.
The nice thing about this approach is that general keyboard handling, like ctrl+cursor, and cut+paste etc. all work exactly as expected without having to code that yourself - you're just piggybacking on the existing functionality of the textarea.
Here's an example of how this works:
http://js1k.com/2012-love/demo/1168
(A javascript shell)
I am in need of a contenteditable plugin that will work well on all browsers + smartphones. I tried Codemirror but it was not working well on iphone. Then I tried Editarea and it works very well, but it is 150Kb, uses an iframe and has a lot of unnecessary code for me. What i need is a simple contenteditable area that will not allow the pasting of photos or other styled text and works well on phones as well.
You'll probably have to write your own handler since your logic is very custom. You'll have to disallow keyboard shortcuts like ctrl-b if you do not want to allow bolding for example. For paste, the best strategy to clean it is to inject a hidden div int o your contenteditable area and then place the cursor in it to force the pasted content into it. At that point you can reference the div and clean out unwanted data e.g. images. Finall you can take the content and put it after the div and then remove the div.
Also consider pasting from Word which can be very messy. In the paste handling you can even make an ajax call with the data to clean it server side.
I have a small text editor in my home page ( a textarea ) where I can paste text. How can I get this text in a variable before it would be pasted? I know that there is this function:
clipboardData.getData()
but it doesn't work in Firefox, and I want something for all the browsers.I am using HTML and Javascript.
thanks
The short answer is that in general you can't get the text before it is pasted. What you can do is what big web-based WYSIWYG editors such as CKEditor and TinyMCE do, which is:
Detect a Ctrl-v / shift-ins event using a keypress event handler
In that handler, save the current user selection, add a <div> element off-screen (say at left -1000px) to the document, move the caret to be inside that div, thus effectively redirecting the paste
Set a very brief timer (say 1 millisecond) in the event handler to call another function that retrieves the HTML content from the div and does whatever processing is required, removes the div from the document, restores the user selection and inserts the processed HTML.
Note that this will only work for keyboard paste events and not pastes from the context or edit menus. By the time the paste event fires, it's too late to redirect the caret into the div (in some browsers, at least).
Getting the clipboard to work across all browsers is tricky and I believe it's safe to assume there's no way to make it work with only JavaScript, unless you're targeting one specific browser (usually IE). I used ZeroClipboard for this: http://code.google.com/p/zeroclipboard/ - it seems to do its job OK.