I want to use the editor feature of XUL to save changes in a document and read from it on load (I am developing an extension)
//NotePad.xul
<editor id="edit" type="content" editortype="html" src="about:blank" flex="1"/>
//NotePad.js
function initEditor(){
var editor = document.getElementById("myEditor");
editor.contentDocument.designMode = 'on';
}
I tried Changing the src attribute to an html doc i have locally but it didnt work.
So what i actually wanna do is :
Get the text written in the editor (something like .getAttribute('value'), but i didnt find a way to do so)
Write to it from javascript (something like setAttribute('value'))
Thanks in advance, i am really stuck in here.
After Complicating things myself using a lot of code i finally found it, and it is really dumb to be honest, well here is how it gets done :
to set text :
var editor = content.document.getElementById("myEditor");
editor.contentDocument.documentElement.innerHTML += "Whatever your text is";
and get text it is obvious :
editor.contentDocument.documentElement.innerHTML
to think that i spent a loooot of time in this is ...
well the innerHTML varies, it depends on what you gave to editortype either html or text, so in case the editortype is set to text in that case we should use innerText.
Related
I'm turning here as a last resort. I've scoured google and I'm having troubles coming to a solution. I have a form with a textarea element that allows you to type html in the area and it will render the HTML markup live as you type if you have the preview mode active. Not too different from the way StackOverflow shows the preview below a new post.
However, I have recently discovered that my functionality has a vulnerability. All I got to do is type something like:
</textarea>
<script>alert("Hello World!");</script>
<textarea style="display: none;">
And not only does this run from within the textarea live, if you save the form and reload said data on a different page this code still executes within the textarea on said different page but unbeknownst to the user; to them all the see is a textarea (if there is no alert obviously).
I found this post; Live preview of textarea input with javascript html, and attempted to refactor my JS to the accepted answer there, because I noticed I couldn't write a script tag in the JSFiddle example, though maybe that's some JSFiddle blocking that behaviour, but I couldn't get it working within my JS file.
These few lines is what I use to live render HTML markup:
$(".main").on("keyup", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
$(".main").on("keydown", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
Is there a way this can be refactored so it's safe? My only idea at the moment is to wipe the live preview and use a toggle on/off and encode it, but I really think this is a cool feature and would like to keep it live instead of toggle. Is there a way to "live encode" it or escape certain tags or something?
In order to sanitise your text area preview simply replace all the < and > with their html character code equivalents:
function showPreview()
{
var value = $('#writer').val().trim();
value = value.replace("<", "<");
value = value.replace(">", ">");
$('#preview').html(value);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="writer" onInput="showPreview();">
</textarea>
<br/>
<hr/>
<div id="preview">
</div>
Edit: Actually, I think this solution is a little cleaner, and makes the below code unnecessary. In the velocity page all that is needed is to take advantage of the Spring framework. So I replace the textarea with this like so:
#springBindEscaped("myJavaObj.textAreaText" true)
<textarea id="actualTextArea" name="${status.expression}" class="myClass" rows="10" cols="120">$!status.value</textarea>
This paired with some backend Java validation and it ends up being a much cleaner solution.
But if you want a non-spring/ velocity solution, then this below works just fine
I cobbled together a quick fix as my main purpose is to eliminate the ability for others to execute scripts easily. It's not ideal, and I"m not claiming it to be the best answer, so if someone finds a better solution, please do share. I created a "sanitize" function like so:
function sanitize(text){
var sanitized = text.replace("<script>", "");
sanitized = sanitized.replace("</script>", "");
return sanitized;
}
Then the previous two event handlers now look like:
$(".main").on("keyup", "#actualTextArea", function () {
var textAreaMarkup = $('#actualTextArea').val();
var sanitizedMarkup = sanitize(textAreaMarkup );
$('#actualTextArea').val(sanitizedMarkup);
$('#previewTextArea').html(sanitizedMarkup);
});
// This one can remain unchanged and infact needs to be
// If it's the same as above it will wipe the text area
// on a highlight-backspace
$(".main").on("keydown", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
Along with Java side sanitation to prevent anything harmful being stored in the DB, this serves my purpose, but I'm very open to a better solution if it exists.
I have my own custom non-jQuery ajax which I use for programming web applications. I recently ran into problems with IE9 using TinyMCE, so am trying to switch to CKeditor
The editable text is being wrapped in a div, like so:
<div id='content'>
<div id='editable' contenteditable='true'>
page of inline text filled with ajax when links throughout the site are clicked
</div>
</div>
When I try to getData on the editable content using the examples in the documentation, I get an error.
I do this:
CKEDITOR.instances.editable.getData();
And get this:
Uncaught TypeError: Cannot call method 'getData' of undefined
So I figure that it doesn't know where the editor is in the dom... I've tried working through all editors to get the editor name, but that doesn't work-- no name appears to be found.
I've tried this:
for(var i in CKEDITOR.instances) {
alert(CKEDITOR.instances[i].name);
}
The alert is just blank-- so there's no name associated with it apparently.
I should also mention, that despite my best efforts, I cannot seem to get the editable text to have a menu appear above it like it does in the Massive Inline Editing Example
Thanks for any assistance you can bring.
Jason Silver
UPDATE:
I'm showing off my lack of knowledge here, but I had never come across "contenteditable='true'" before, so thought that because I was able to type inline, therefore the editor was instantiated somehow... but now I'm wondering if the editor is even being applied to my div.
UPDATE 2:
When the page is loaded and the script is initially called, the div does not exist. The editable div is sent into the DOM using AJAX. #Zee left a comment below that made me wonder if there is some other command that should be called in order to apply the editor to that div, so I created a button in the page with the following onclick as a way to test this approach: (adapted from the ajax example)
var editor,html='';config = {};editor=CKEDITOR.appendTo('editable',config, html );
That gives the following error in Chrome:
> Uncaught TypeError: Cannot call method 'equals' of undefined
> + CKEDITOR.tools.extend.getEditor ckeditor.js:101
> b ckeditor.js:252
> CKEDITOR.appendTo ckeditor.js:257
> onclick www.pediatricjunction.com:410
Am I headed in the right direction? Is there another way to programmatically tell CKEditor to apply the editor to a div?
UPDATE 3:
Thanks to #Reinmar I had something new to try. The most obvious way for me to test to see if this was the solution was to put a button above the content editable div that called CKEDITOR.inlineAll() and inline('editable') respectively:
<input type='button' onclick=\"CKEDITOR.inlineAll();\" value='InlineAll'/>
<input type='button' onclick=\"CKEDITOR.inline('editable');\" value='Inline'/>
<input type='button' onclick=\"var editor = CKEDITOR.inline( document.getElementById( 'editable' ) );\" value='getElementById'/>
This returned the same type of error in Chrome for all three buttons, namely:
Uncaught TypeError: Cannot call method 'equals' of undefined ckeditor.js:101
+ CKEDITOR.tools.extend.getEditor ckeditor.js:101
CKEDITOR.inline ckeditor.js:249
CKEDITOR.inlineAll ckeditor.js:250
onclick
UPDATE 4:
Upon further fiddling, I've tracked down the problem being related to json2007.js, which is a script I use which works with Real Simple History (RSH.js). These scripts have the purpose of tracking ajax history, so as I move forward and back through the browser, the AJAX page views is not lost.
Here's the fiddle page: http://jsfiddle.net/jasonsilver/3CqPv/2/
When you want to initialize inline editor there are two ways:
If element which is editable (has contenteditable attribute) exists when page is loaded CKEditor will automatically initialize an instance for it. Its name will be taken from that element's id or it will be editor<number>. You can find editors initialized automatically on this sample.
If this element is created dynamically, then you need to initialize editor on your own.
E.g. after appending <div id="editor" contenteditable="true">X</div> to the document you should call:
CKEDITOR.inline( 'editor' )
or
CKEDITOR.inlineAll()
See docs and docs.
You can find editor initialized this way on this sample.
The appendTo method has different use. You can initialize themed (not inline) editor inside specified element. This method also accepts data of editor (as 3rd arg), when all other methods (CKEDITOR.inline, CKEDITOR.replace, CKEDITOR.inlineAll) take data from the element they are replacing/using.
Update
I checked that libraries you use together with CKEditor are poorly written and cause errors you mentioned. Remove json2007.js and rsh.js and CKEditor works fine.
OK, so I have tracked down the problem.
The library I was using for tracking Ajax history and remembering commands for the back button, called Real Simple History, was using a script called json2007 which was intrusive and extended native prototypes to the point where things broke.
RSH.js is kind of old, and I wasn't using it to it's full potential anyway, so my final solution was to rewrite the essential code I needed for that, namely, a listener that watched for anchor (hash) changes in the URL, then parsed those changes and resubmitted the ajax command.
var current_hash = window.location.hash;
function check_hash() {
if ( window.location.hash != current_hash ) {
current_hash = window.location.hash;
refreshAjax();
}
}
hashCheck = setInterval( "check_hash()", 50 );
'refreshAjax()' was an existing function anyway, so this is actually a more elegant solution than I was using with Real Simple History.
After stripping out the json2007.js script, everything else just worked, and CKEditor is beautiful.
Thanks so much for your help, #Reinmar... I appreciate your patience and effort.
I have integrated CKEditor into my website CMS. The Preview button works but I cannot get it to use stylesheets (CSS). I have edited the preview.html located in:
Website/ckeditor/plugins/preview/
But it doesn't seem to listen to any of the html I wrap around the code that pulls the content from the WYSIWYG editor.
As I understand this bit of code:
<script>
var doc = document;
doc.open();
doc.write( window.opener._cke_htmlToLoad );
doc.close();
delete window.opener._cke_htmlToLoad;
</script>
Pulls in whatever is in the editor, so I should be able to wrap around that html to include elements that will be available for every page? And links to stylesheets?
Anyone ever done this? Is it possible?
The "window.opener._cke_htmlToLoad" seems to be a string (containing a complete html document).
To get the innerHtml of the <body></body>, you can use this regex:
var doc = window.opener._cke_htmlToLoad; // is string
var innerBody = ( doc.replace(/((?:.(?!<\s*body[^>]*>))+.<\s*body[^>]*>)|(<\s*\/\s*body\s*\>.+)/g,'') );
document.getElementById('insertIntoMe').innerHTML = innerBody;
From my testing this seems only to work in Firefox. But Chrome and Internet Explorer directly display the window document without allowing any changes. So maybe somebody else can provide a better solution?
What I want to do is pretty simple. Above my blog I want to have a text paragraph with an explanation of the site. However I do not want it to be at the top of every page on the site ONLY the index page. My host has a very restrictive format. I've already asked them for help and it isn't possible with their editor. I cannot edit all of the html but I can change some. Javascript seems to be allowed so I have been trying things like:
<SCRIPT LANGUAGE="JAVASCRIPT" TYPE="TEXT/JAVASCRIPT">
<!--
if (url==http://mysiteaddress/index.html)
{document.write('Welcome to my site')}
//-->
</SCRIPT>
Taking out the if statement, it successfully writes 'Welcome to My site'. So I'm wondering what is wrong with the if statement. I've also tried adding an 'else' in order to see output on any page but have not had any luck.
I obviously don't know much yet so any help would be appreciated. Thanks!
The url is available via location.href - not sure why you think url exists.
Besides that, mime types are lowercase and the language attribute is obsolete. So use <script type="text/javascript">.
Additionally it'd be better if you didn't use the infamous document.write but document.getElementById('someDiv').innerHTML = 'your html here';
Or get jQuery and simply write $('#someDiv').html('your html here');
Just to add, you can prepend an element to the body element like this:
var p = document.createElement("p");
p.innerHTML = "I am a paragraph";
document.body.insertBefore(p, document.body.firstChild);
You can try it here.
Reference: https://developer.mozilla.org/En/DOM/Node.insertBefore
I am playing around with creating an HTML-textarea based plain text editor to edit my scripts (using e.g. Mozilla Prism + a localhost install/ webserver). It works fine so far, but when I want to insert something at the cursor position, it gets slow in Firefox when there is a lot of text in the textarea (Chrome works fine). E.g. with 133k filled in the textarea it takes around 1 sec to perform inserting 4 spaces.
I already have and use elm.selectionStart and elm.selectionEnd. Based on these I then copy the text, manipulate it, and set the value back into the textarea -- perhaps that is what's causing the bottleneck (I'm using the similar approach as answered on this site before). Ideally, I would probably like to have something like elm.selectedText = 'foobar' but can't find this...
It doesn't necessarily need to be crossbrowser...
Can someone help?
According to this article on codemirror, using designMode is faster than using a textarea, because you can edit parts of the content instead of editing the whole text in one go.
There's an API that replaces the selected text: textarea.setRangeText('text').
Here's a demo:
const textarea = document.querySelector('textarea');
textarea.addEventListener('click', () => {
textarea.setRangeText('WOW');
});
<textarea rows="10" cols="40">Click anywhere or select any text in here. It will be replaced by WOW</textarea>
There's also document.execCommand('insertText') with undo support but it's not cross-browser. Try insert-text-textarea for a cross-browser solution.