I'm writing a program that will use a CodeMirror instance and have a little element that pops up that you can, among other things, type text in. That text typing area is supposed to be one line high. I'm going to be doing a lot of the same stuff with that text typing area that I'm doing with the main CodeMirror instance, so I want to just use another instance of CodeMirror, but everything I've tried so far ends up too tall.
How do I make a CodeMirror instance that is just one line high and is horizontally scrollable? I'd like no line numbers, no gutters, etc., just the area for the text to be entered.
I tried several things including the code here (which I tried in whole and in parts): codemirror for just one-line-textfield?. The example prevents a user from typing more than one line of code in a code mirror instance, but it doesn't make it just one line high. There's other CodeMirror stuff there, though I'm not sure what all is there or how to get rid of it.
Edit:
re: #rfornal's request, here was the code and explanation I'm referring to (by Tigran Saluev):
Well, there is a way to make a single-line editor using rich capabilities of CodeMirror. First, you'll have to add a full-featured CodeMirror object (use a textarea).
Assume you've got var cm = CodeMirror(...). (Use value: ""). Then do
cm.setSize(200, cm.defaultTextHeight() + 2 * 4);
// 200 is the preferable width of text field in pixels,
// 4 is default CM padding (which depends on the theme you're using)
// now disallow adding newlines in the following simple way
cm.on("beforeChange", function(instance, change) {
var newtext = change.text.join("").replace(/\n/g, ""); // remove ALL \n !
change.update(change.from, change.to, [newtext]);
return true;
});
// and then hide ugly horizontal scrollbar
cm.on("change", function(instance, change) {
$(".CodeMirror-hscrollbar").css('display', 'none');
// (!) this code is using jQuery and the selector is quite imperfect if
// you're using more than one CodeMirror on your page. you're free to
// change it appealing to your page structure.
});
// the following line fixes a bug I've encountered in CodeMirror 3.1
$(".CodeMirror-scroll").css('overflow', 'hidden');
// jQuery again! be careful with selector or move this to .css file
This works just fine for me.
Everything I've tried so far still ends up taller than one line. There's probably a way to do this, I'm just not understanding how.
As per usual, this was user error. I had assumed that CodeMirror's styles would overwrite any styles that I had created for the container, but they didn't. My styles infected the CodeMirror instance and caused the weirdness.
Specifically:
- Setting position: relative somewhere where it shouldn't be (I'm not sure where)
- Setting display: inline-block somewhere where it shouldn't be (again, not sure what it specifically affected)
My apologies and I hope this helps someone else in the future.
Related
I started using cypress nowadays to learn better and deeper. I am faced with a problem that I can't handle. The problem is some kind of GUI effect working with mouse hover. While hovering my mouse on the element I can't see any information change into DOM. There are just ::before and ::after words appearing. I think I have to solve that problem with some javascript tricks. unfortunately, I am new to javascript and I don't have any idea if you help me I would be very happy. Thank you! (I want to assert in some way that grey background and plus icon is shown or not)
generically look like that
after the mouse hovers this grey background and plus icon comes
you can see elements DOM here
you can see the changes after the mouse hovers element
You can use the cypress-real-events plugin.
To install use the command:
npm i cypress-real-events
Then inside your cypress/support/e2e.{js,ts}, write:
import "cypress-real-events/support";
And in your code you can directly write:
cy.get("selector").realHover('mouse')
//Add assertions
Note: Since the above plugin uses Chrome DevTools Protocols to simulate native events, hence this will only work with Chromium-based browsers, so no firefox.
Into cypress' test try to use the method cy.wait("time here") following hover command.
This is very simple but for visual test this is so useful.
In order to access the :before or :after of an element, we have to do a little Cypress and JavaScript magic. This is answer is mostly from this link.
cy.get('.myClass')
.then($els => {
// get Window reference from element
const win = $els[0].ownerDocument.defaultView
// use getComputedStyle to read the pseudo selector
const before = win.getComputedStyle($els[0], ':before')
// read the value of the `content` CSS property
const contentValue = before.getPropertyValue('content')
// The above lines are just how we tell Cypress to get the `:before` value.
// There isn't a ton to understand outside of really diving into how elements and windows work together
expect(content).to.equal('foo');
})
So, using that same example, we can check for any CSS property on the element. For example, font-size:
cy.get('.myClass')
.then($els => {
const win = $els[0].ownerDocument.defaultView
const before = win.getComputedStyle($els[0], ':before')
const fontSize = before.getPropertyValue('font-size') // instead of `'font-size'`, you can substitute any CSS property
expect(fontSize).to.equal('20');
})
This can also be applied to :after, changing out ($els[0], ':before') with ($els[0], ':after').
Looking at your screenshots, I think you have a gray overlay element covering the original incident element.
The only code I can suggest is from the limited information is
cy.get('#IN-578')
.trigger('mouseover')
.should('not.be.visible')
The overlay has opacity 50%, so you can still see the incident details but from Cypress point of view the incident is covered so it will not be "visible".
If you don't have any luck with 'mouseover', try .realHover() from cypress-real-events.
After the above code, you should look for the overlay element in DOM and the + icon in the middle, select that icon and click it to take the action.
(I have only confirmed this to happen so far with Safari 12.1.2 on MacOS Mojave)
So I have a contenteditable div with a styled span (red) and some text inside it. Nothing weird yet.
However, when I do some operations on the text (keeping all the text still within the same styled span) some of the text loses its style even though inspecting the DOM shows it should be styled (red).
Here's a jsfiddle illustrating the issue above:
1: https://jsfiddle.net/tx71pqmv/5/
$('#editable').keypress((event) => {
if (event.key != 'Enter' || !event.shiftKey)
return;
event.preventDefault()
let sel = window.getSelection()
let range = sel.getRangeAt(0)
let newLine = $('<span>')
.addClass('br')
.attr('contenteditable', 'false')[0]
range.startContainer.splitText(range.startOffset) // 1
range.insertNode(newLine) // 2
})
The weird thing is that this issue happens under VERY specific conditions.
For example, if I step through the code using the debugger, or use setTimeout to delay the execution by even 1ms (see jsfiddle #2), then everything works as intended.
Or, even just getting rid of the ::before pseudo-element on the containing div (not even the styled span) fixes the issue (see jsfiddle #3). This should be totally unrelated!
Is there a cleaner solution to the problem that doesn't involve compromising on the css or using setTimeout?
Edit: Adding screenshots of the DOM structure after pressing shift+enter on the first jsfiddle, and the second. The DOM structure on both look identical, but the one on the right doesn't have styling applied to one of the text nodes:
Here shift+Enter and Enter behaving differently for the #editable div
Enter is creating a new child (div) of #editable div
means you have more child every time you press shift enter
but Shift + Enter is creating new line inside the child div > span
browsers behave differently for contenteditables
as MDN says
Use of contenteditable across different browsers has been painful for a long time because of the differences in generated markup between browsers.
Read this for more info:
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
new div created using enter
Answered:
Result can bee seen here: http://apitecture.com/dev/cked/index.2.html
Working code excerpt:
$('a.color').on({
click : function()
{
var self = $(this);
var editor = self.data('editor-instance') || CKEDITOR.instances['one'];
var button = self.data('editor-button') || editor.ui.create('TextColor');
if (!self.data('editor-instance'))
{
self.data('editor-instance', editor);
}
if (!self.data('editor-button'))
{
button._.id = self.attr('id');
self.data('editor-button', button);
}
button.click( editor );
}
});
I am working on a rich GUI based content editor.
I have come to conclusion, to use CKEditor for the text styling part, because it's 4th version comes with a lot of customization and configuration options, plus, is very well built.
I started to implement some of the commands in CK to my own toolbar, that isn't connected with CK. Apparently, my ventures weren't as easy as I thought they'd be...
http://apitecture.com/dev/cked/ <- here I have deployed a sandbox version.
On the left hand side, you can see a veeeery stripped down version of CK, and a custom toolbar.
On the right, exact replica, but with CK's native toolbar.
Simple commands, like Link and Bold, as you can see, are working, due to their simple nature.
The problem is with the Text Color button. It isn't bound to a command in CK, therefore I cannot execute it externally - well, at least I haven't found a way how.
Maybe somebody is pro enough with CK and could help me to figure this out?
The goal is to have the same functionality on my toolbar's button as the CK one.
I have found out, that upon clicking the Text Color, the color selection popup is appended to body, so, it doesn't extend upon CK styles and should, in theory, work standalone. Though, I cannot seem to find the code where the HTML is appended to body.
I have tried to get the UI button instance:
var color = CKEDITOR.instances['one'].ui.create('TextColor');
// and fire click on it
color.click();
But, that caused a partially expected (due to click not being started from toolbar) exception:
Uncaught TypeError: Cannot read property 'elementMode' of undefined ckeditor.js:552
CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.$ ckeditor.js:552
CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel ckeditor.js:541
e ckeditor.js:540
$.on.click cktest.js:59
v.event.dispatch jquery.min.js:2
o.handle.u
Seeing (from: console.log(color.click)) that the function accepts a parameter, I thought that I could provide any DOM element to it, by calling color.click( element );, that also caused error:
Uncaught TypeError: Cannot read property 'baseFloatZIndex' of undefined ckeditor.js:547
CKEDITOR.ui.panel.render ckeditor.js:547
o ckeditor.js:552
CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.$ ckeditor.js:553
CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel ckeditor.js:541
e ckeditor.js:540
$.on.click cktest.js:59
v.event.dispatch jquery.min.js:2
o.handle.u
Here is link to the source where the color plugin and it's buttons is introduced: https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/colorbutton/plugin.js
Update:
I think this happens with every single button, that has dropdowns instead of dialogs.
Update 2:
Reinmar's answer did show some light at the end of the tunnel: http://apitecture.com/dev/cked/index.2.html
In the example, the "Color" text-link on the right can be clicked, and the dropdown shows, plus, it functions perfectly (besides that the shadow is enforced). The only catch here is, it works for the first time. Resulting in:
TypeError: Cannot read property 'title' of undefined
at CKEDITOR.ui.panel.block.CKEDITOR.tools.createClass.$ (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:549:298)
at new b (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:26:149)
at Object.CKEDITOR.ui.panel.addBlock (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:547:503)
at CKEDITOR.ui.floatPanel.CKEDITOR.tools.createClass.proto.addBlock (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:553:409)
at CKEDITOR.ui.panelButton.CKEDITOR.tools.createClass.proto.createPanel (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:541:333)
at e [as click] (http://apitecture.com/dev/cked/ckeditor/ckeditor.js:540:304)
at HTMLAnchorElement.$.on.click (http://apitecture.com/dev/cked/cktest.2.js:64:24)
at HTMLAnchorElement.v.event.dispatch (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:38053)
at HTMLAnchorElement.o.handle.u (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:33916)
For every subsequent click.
You've asked a hardcore question :). I'm CKEditor core dev for last 1 year and I had to spend an hour digging in toolbar, panels and buttons. This part of CKE's API is really twisty and definitely lacks of documentation. But the worst part of it is that it's not really reusable, cause all the parts are tightly coupled.
Anyway. I tried to reuse colorbutton and I succeeded. On editor without toolbar plugin (this is important) I was able to open it for specified element:
And it even seems to work :) (at least on Chrome).
I'm curious how hard it will be for you to replace toolbar plugin with your own basic implementation (perhaps without a11y support and other heavy stuff). At the moment your bold and link buttons work correctly on Chrome, FF, Opera and IE7-9 (this in fact proves how cool CKE is because it does a lot in the background ;). I hope that you won't encounter any serious troubles.
Some tips:
You don't need to call editor.getCommand().exec(). There is an editor.execCommand() method.
You'll probably want to activate/deactivate buttons depending on context (caret location). Each command has its state and it's automatically updated on selectionChange event.
Good luck. And it will be cool if you share your thoughts and result of work with us :). Feedback will be very useful if someday we'll decide to improve this part of API.
Initially I asked this Question and written my own plugin to achieve the same,But i am facing very strange issue regarding to css of table.
After applying the plugin table cells borders are getting dis-sorted.
jsFiddle of the problem: Problem demo
In fiddle you can see that after first cell of the first tr, the header border line and table border line don't line up. I want the border line of thead cells and td cells to line up.
Can anyone tell me how to achieve that?
Lets start by doing a bit of a clean up of the code you posted so I can actually read your code and maintain a firm grasp on reality while we go down this rabbit hole.
If you write clean code, your problems will be exceptionally easier to see.
So lets clean it up and watch as all the problems here reveal themselves.
Step one: Your jsFiddle sets it to run "onDomReady," which basically means you've got $(document).ready(...) calling all the code in the box, which is fine, except you're got another got $(document).ready(...) inside there. Lets change that.
Step two: Lets add some white space and proper indentation in there, and stop using these one letter variable names.
{} are scope brackets, they should indent, not cover everything, they let us know what part of scope something is in.
Don't write .each() loops on one line, this adds no value and makes your code confusing to read.
$t should be called something meaningful, lets try element, because it holds the $(this) element, which is the active element you're working with.
w should be called something meaningful, but since you only use it twice I'm just going with element.width().
o needs to be less ambiguious, lets go with obj.
Step three: Selection structures
if(typeof(i)=='number')o.height=i;
else if(typeof(i)=='object')o=i;
else if(typeof(i)=='undefined')o={height:300}
Break that up, make it readable. Saving lines doesn't make you a better program, writing clean and easily understandable code will.
Why not use the switch-case statement?
switch (typeof(i)){
case "number":
o.height=i;
break;
case "object":
o=i;
break;
case "undefined":
o={height:300};
break;
}
Step four: Don't in-line styles. Just don't. There's no reason to do it, and it makes everyone's life harder.
Instead, lets just place the styles gently into the style sheet where it belongs, and make the parent=$('...') line look like parent=$('<div><div></div></div>').appendTo('body');.
Step five: Closure doesn't pass any value to arguments
After a bit of clean up, we see this block of code:
self.width(self.width() -
function(width){
var parent,child;
if(width===undefined){
parent=$('<div><div></div></div>').appendTo('body');
child=parent.children();
width= (child.innerWidth()) - (child.height(99).innerWidth());
parent.remove();
}
return width;
}()
);
Okay, that's a problem. Lets cut out a few lines to point out the problem here:
self.width(
self.width() -
function(width){
/*...*/
if(width===undefined){
/*...*/
}
return width;
}()
);
So, a quick refresher on this pattern you have here:
(function(arg1){
/*code*/
})(data);
Data gets passed to arg1. Arg1 declaires a variable in the scope local to that function, it doesn't get anything from outside. Outside data is passed in through the set of () that call the function, which your code had left abandoned. Think of it this way:
var msg = function(text) {
alert(text);
};
Then you call it as...
msg("hello world");
What your closure is doing is almost the same thing, except where you define your function, you also call it. Thus...
(function(text) {
alert(text);
})("hello world");
So, you need to pass a value of some sort into there, other wise this whole thing is always undefined. Lets do that. What are we passing? I have no way to be sure. This is why programmers need to add comments to their code.
Step six: Comment your code so people other than yourself will look at this code and have not a damn clue what you truthfuly wanted to do, and can only guess. It's like you posted a 200 point bounty and didn't bother helping people who want to help you. Why are you doing this to yourself, dude? Why couldn't you just go //This is what this does to give me a hint? What did I ever do to you?
Step Seven: Lets see if we can make the JS changes work with the JS Fiddle
Great odin... that HTML's 2000 lines long?
Okay, I'm working with pastebin here for the sake of saving space in the post here.
Alright, you started off with this: http://pastebin.com/xjmm4cev
You're using a lot of no-wrap, and putting classes onto individual elements. You shouldn't have to do this on each HTML element, CSS takes care of that very effectively, so lets go ahead and just rip out all the nowrap=nowrap and class="header" stuff (we'll put it back in a moment, but only ONE per group, not each element).
Then lets get rid of the useless blank lines.
Lets run this through HTML tidy and get it nice and indented correctly.
http://pastebin.com/uHtSZ4h5
Much easier to read over. Okay, so what do we see here? Well, it looks like you keep going in circles, cutting and pasting the same thing again and again. You also in-line javascript such as using onchange and onclick attributes. This is generally an awful thing to do to your code, and makes it hard to maintain (as I'm sure you've seen with this 2000+ line beast of cut+paste 27 times in a row).
So, lets take a look here:
elements, not inside a form
Elements in a table that are outside of rows, but not head/body/footer sections of a table
Code that's a huge pain to maintain because it keep going in circles, if you need to change this, you're basically screwed.
Lets fix all that.
We're going to use events in the tags, rather than in-line things. So, all of those in-line onchange and click attributes get the boot.
All of these inputs that are just floating around need to get put into a form, and taken out of this place in tables that only rows or table sections belong in.
Figure out how we can not have excessive input elements, if we can help it.
What the heck is the )="" that you have on every input button? Deleted.
So, here's all of your hidden boxes: http://pastebin.com/LXZSkvyf which I've removed, because we don't have a anywhere.
And here's what the code looks like without all of these weird things in it: http://pastebin.com/MiaJTGpb
Much more readable, but still not quite there.
Step 8: What can you do to make the HTML of the table work better?
You're using Thead and Tbody, and that's good.
You're using attributes for things like cellpadding, that's bad.
You've given each body row an ID. I don't feel you needed to do this, but it's not always bad. However, I'll show you how you could work without it.
You give some selects a select-box class, but it's nowhere in the css. I've removed it.
You give a title attribute to the selects that says "option_value". The title attribute is generally used to make a tool-tip popup when you leave the mouse over something. I'm not sure what you're going to do here, but that's bound to confuse your user. I'd highly suggest giving something better than option_value in that place.
You keep using the ID Submit_FMS_AddDelivery. HTML ID tags are meant to be unique, and used only once on one element. You've got it 27 times, that's bad. I don't think you need an ID on it, so I've removed it.
You've also got input-btn going on, I'm removing it, because you haven't shown it's used anywhere.
You probably don't need any of these ID tags on select and TR to be honest, so I'm pulling them.
What's that look like? Basically, you've got what's almost just the data, in it's nice pure form. That's good. http://pastebin.com/UNS6CAtb
Step 9: What were you trying to do?
Lets step back and take a look here.
All you really wanted to do was keep a fixed header, but you've ended up doing a lot of JavaScript hacks and manipulating the DOM in a lot of places. We need to stop doing this. Is there a simpler way to do what you want?
I'll have to expand on how to make this function with the rest of your stuff, but I get up for work in a few hours. I'll update again with more... But we'll get there.
Right now, because I haven't fixed what I took out, it doesn't look right. But I'm tired.
So, here's where we are so far: http://jsfiddle.net/5C6z7/
Plus those inputs we took out (and will be going back in later, in a different way)
Looks like all you have to do is to take the padding into account: each cell has 3 px padding both left and righ so you have to add 6 px to the width:
$t.find('tr:first th').each(function(){cols.push($(this).width()+6);});
Otherwise the cells with only one word inside will "push" the actual width a bit wider so that the word will fit and other cells with space to move will compensate by becoming a bit narrower. The header and the body both do this independently with different contents which creates the difference in actual cell widths.
EDIT: For Firefox you also need to widen the table so that the cells fit. After calculating the column widths add
var actualWidth = $t.width()+cols.length*6;
$t.width( actualWidth );
And later change the wrapper to:
$wrap.css({width:actualWidth,height:o.height,overflow:'auto'});
EDIT 2: To have both the header and the body scroll simultaneously you need to wrap them both to an outer div that handles the scrolling.
var $outerWrap = $( '<div>' ).css( {width:"300px", overflow:'auto' } );
var $wrap=$('<div>').css(
{ width:actualWidth,height:o.height,"overflow-y":'auto', "overflow-x":'hidden' }
);
$firstRow.wrap( $outerWrap );
$firstRow.after( $wrap );
$wrap.append( $t );
Demo: http://jsfiddle.net/YcRTz/2/
What about replacing '<th>' tags with '<td>' tags?
No extra js code required.
http://jsfiddle.net/spQAh/7/
Okay so instead of troubleshooting or using anything complex, I came up with simple CSS + JS solution to your problem. Take a look at http://jsfiddle.net/TdLQT/
Obviously, the process of making header static, can be made dynamic, meaning trigger it after user scrolls a bit or have it there by default or count other object's position from top window and trigger static behavior when it reaches or exceeds certain pixels. I can provide that if you give me details on exact design of your HTML page.
Anyways, I as you can see, have used fixed pixel heights which you can choose not to or make them elastic or dynamic. What is important to know is that, though solution relies on JS a bit, output position is purely from CSS. I am using classes to manipulate the position.
the simple solution is that when you calculate the width of the column you do not include padding. So you need to change the line
$t.find('tr:first th').each( function() {
cols.push($(this).width());
});
to
$t.find('tr:first th').each( function() {
cols.push($(this).outerWidth());
});
if your cells have margins use .outerWidth(true)
This works in quirks mode with IE7&8 and Chrome IE8 has a problem in strict mode. However I believe that that problem is caused by the added scrollbar. If you want to use IE8 in strict mode you have to allow for the width of the vertical scrollbar..
Oddly specific question, but I have a solution already to paste plain text in a <span contentEditable="true"> by using a hidden textarea, which seems to work really well, except that it breaks the browser's undo feature. Right off the bat I'm not worried about a cross-browser solution; I only care about Chrome. My approach looks roughly like this:
$('.editable').live('paste', function()
{
var $this = $(this);
//more code here to remember caret position, etc
$('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it's auto-sanitized by the textarea
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
});
});
So this works -- I can paste anything and it's reduced to plain text before going into the my contentEditable field -- but if I try to undo after pasting:
First undo undoes the paste.
Second undo tries to undo the changes to #clipboard, moving the focus away from my contentEditable.
I've tried everything I can think of to make the browser not try to undo the changes to #clipboard -- toggling display:none when it's not actively in use, toggling readonly and disabled state, destroying it at the end of and recreating it at the beginning of the event above, various other hacks -- but nothing seems to work.
Is this a terrible approach to sanitization? This is the first thing I've managed to really get working -- trying to clean up the markup after the paste occurs didn't work, as there are some things (entire HTML documents) which, when pasted, crash the browser, which I'd like to avoid.
Is there any way to make the #clipboard not undoable, or any other suggestions of how to get this working?
Edit
I managed to improve things a little bit by adding the line
$('#clipboard').val('');
Right after the execCommand line. This seems to neutralize undo completely: the caret no longer leaves the contentEditable field, but nothing gets undone at all. A bit of an improvement, but I'm still searching for a proper solution.
CodeMirror 1 does this by stripping away formatting after text is pasted. CodeMirror 2 does this by actually having an invisible textarea handle everything, and render the text and cursor manually.
CodeMirror's website describes how it works in more detail: http://codemirror.net/internals.html
Beyond that, there's always the CodeMirror source code. You can decide for yourself whether CodeMirror 1 or CodeMirror 2's approach is more suitable for your purposes. :)
Do you try that?
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
var t = document.body.innerHTML;
document.execCommand("undo");
document.body.innerHTML = t;
});
I think it can help.
But I think you must use event object. Unfortunately there may be a problem cuz security reasons.
In onpaste:
Store the current selection.
var sel = window.getSelection();
var rangeĀ = selObj.getRangeAt(0).cloneRange;
// Store the range object somewhere.
Modify the selection object to point to your hidden textarea.
Set a timeout with a delay of 0 (occurs immediately after paste).
In the timeout function, grab the data from the hidden textarea, then:
var sel = window.getSelection();
sel.removeAllRanges();
var range = // restore the range object from before.
sel.addRange(range);
document.execCommand("insertHTML", false, /* contents of your textarea here */);
Now if you wanted to do this for actual HTML content, you'd be in a world of hurt....
Insert a <pre contenteditable="true">...</pre>. As I recall that's exactly what I understand you want. (Unfortunately I'm not yet allowed to join everyone in the comments, but I suppose this is an attempt to answer anyway.)