OscarGodson / EpicEditor

EpicEditor is an embeddable JavaScript Markdown editor with split fullscreen editing, live previewing, automatic draft saving, offline support, and more. For developers, it offers a robust API, can be easily themed, and allows you to swap out the bundled Markdown parser with anything you throw at it.
http://epiceditor.com
MIT License
4.25k stars 338 forks source link

Text area container issue #312

Open lazeravik opened 10 years ago

lazeravik commented 10 years ago

hi thanx for this editor it is awesome. though i found a lot of problems(maybe bugs) while customizing the ui, and i end up editing the script for getting a nice fluid ui.

I created buttons for common markdowns so that user don't have to remember all the codes. also created some function to put those markups into a textarea. i dont how to use the function to write those inside the editable body, or is there anyway to sync between textarea and editable div?

my buttons for adding markdowns:

<button class="editor_toolbar_btn" Onclick="formatText(document.getElementById('edit_area'),'**','**')"><i class="fa fa-bold"></i></button>
<button class="editor_toolbar_btn" Onclick="formatText(document.getElementById('edit_area'),'*','*')"><i class="fa fa-italic"></i></button>
<button class="editor_toolbar_btn" Onclick="formatText(document.getElementById('edit_area'),'(',')')"><i class="fa fa-link"></i></button>

and edit_area is the text area

and the javascript code for adding the markdowns:

function formatText(el,tagstart,tagend) {
    if (el.setSelectionRange) {
        el.value = el.value.substring(0,el.selectionStart) + tagstart + el.value.substring(el.selectionStart,el.selectionEnd) + tagend + el.value.substring(el.selectionEnd,el.value.length)
    }
    else {
        // IE code here...
    }
  }
OscarGodson commented 10 years ago

Right now there isn't really a good way of doing these types of extensions. There's a ticket for this here tho: https://github.com/OscarGodson/EpicEditor/issues/33

However, we do have some APIs like getElement and you could use, like, editor.getElement('wrapper') which will return the div that wraps the two iframes. Here's the docs for that: http://epiceditor.com/#getelementelement

The other thing is you most likely would NOT want to put HTML like buttons in the editor body because the editor body is all editable (contenteditable). My suggestion would be placing it in the wrapper and hiding/showing it when you switch to preview and back. Basically a hidden floating panel.

As for getting that JS in there, there's a bunch of ways to do it. This is a good writeup of how: http://stackoverflow.com/questions/16194398/inject-a-javascript-function-into-an-iframe

and, using those examples above, you could use the getElement('wrapperIframe') for the iframe to inject your script into.

Does that help at all?

As for syncing between a textarea and editable div, the built in textarea option (you pass the ID or element in the options hash) will sync the textarea for you.

lazeravik commented 10 years ago

The other thing is you most likely would NOT want to put HTML like buttons in the editor body because the editor body is all editable ( contenteditable ). My suggestion would be placing it in the wrapper and hiding/showing it when you switch to preview and back. Basically a hidden floating panel

i did not put any buttons.in the editable body. I simply created toolbar as a floating dock(although no hide and sick). It is not attached to the editable area. And thnx for.
getElement('wrapperIframe')

i am gonna try it out later, and then post here back if any problem found.

lazeravik commented 10 years ago

I am stuck on editable body,

getElement('wrapperIframe')

And for

As for syncing between a textarea and editable div, the built in textarea option (you pass the ID or element in the options hash) will sync the textarea for you.

Can you provide some code or any ref??

OscarGodson commented 10 years ago

Not totally sure what you're stuck on exactly.

Originally you said you weren't going to touch the editable body? Again, I'd suggest against touching that for anything that's not meant to be for editing. Example: formatting text, good. Adding a button bar in the editor HTML, bad.

getElement('wrapperIframe') just returns the iframe which contains the editor and previewer iframes as well as the floating preview/fullscreen button panel. From there you can inject your JS using one of the methods provided in the Stackoverflow post.

As for the syncing, just pass in textarea: 'my-textarea-id' to have it sync with a textarea, or, just place it in the epiceditor div. So:

The HTML:

<div id="epiceditor"></div>
<textarea id="foo"></textarea>

The JS:

var editor = new EpicEditor({ textarea: 'foo' })

OR, even easier:

<div id="epiceditor"><textarea></textarea></div>

The JS:

var editor = new EpicEditor()
lazeravik commented 10 years ago

here is a script i found when searching for this issue, and you wrote this code there.

$textarea = $('#editor_box');

// When it loads put the exiting content in there
editor.on('load', function (file) {
  $textarea.val(file.content);
});

//Everytime it's updated, update the textarea
editor.on('update', function (file) {
  $textarea.val(file.content);
});

// Everything is all setup, so load!
editor.load();

it works but only one way, i mean it will sync only what i entered in the editable body, with the text area.

but how about sync both ways, i mean, if anything in the textarea change i want to make that change appear in the editable body, and if any changes happen to the editable body, i want it to show in the textarea as well. so they both sync with each other, whenever i made any changes to any of them.

is it possible??

Again, I'd suggest against touching that for anything that's not meant to be for editing. Example: formatting text, good. Adding a button bar in the editor HTML, bad.

why is it bad??

OscarGodson commented 10 years ago

That code above is old and exactly what the textarea option I mentioned above does. You can manually sync the other way, but im not sure why. It'd help to know what you actually want to achieve to know HOW to sync the textarea. I doubt you'll have a textarea and EpicEditor next to each other synced, right? So, what is the goal you're trying to accomplish? If you really do have then next to each other and want to sync it just do a (assuming jQuery)

var editor = new EpicEditor().load();
$('textarea').on('keyup', function () {
  editor.importFile(null, $(this).val());
});

or something.

And it's bad because, as I mentioned, the contents of the editor are wiped out and manipulated all the time. You can't expect a component you place in there to stay in there. For example, if you importFile the entire editor contents are destroyed.

OscarGodson commented 10 years ago

Ah didnt mean to close it and comment yet. Stupid web app on a phone... hold on. Updating my post.

OscarGodson commented 10 years ago

OK, updated my answer

Kryptonit3-zz commented 10 years ago

Here is a cleaner way.

$('textarea').on('keyup', function () {
  editor._setupTextareaSync();
});
editor.on('update', function(){
  $('textarea').trigger('keyup');    
});

change 'textarea' to the ID of your textarea element.

like '#myTextarea' or something. both instances. or it will target all textarea's (you may just have one but it is good practice to target elements specifically and not use 'blind' targeting.

lazeravik commented 10 years ago

Ok, gonna try it.

Kryptonit3-zz commented 10 years ago

updated my comment.

OscarGodson commented 10 years ago

Underscores are private methods. I would highly advise against using those since they aren't tested, can be ripped out or changed at anytime and aren't supported.

Kryptonit3-zz commented 10 years ago

OscarGodson - What would be another way of running that function? Because it does exactly what I needed it to do. If it renames in the future, then ill rename with it. Can we suggest a built in public function that reruns the textarea sync?

OscarGodson commented 10 years ago

Triggering an update event should do that. If not that's probably a bug.