* @class Ext.form.HtmlEditor
* @extends Ext.form.Field
* Provides a lightweight HTML Editor component.
- * WARNING - THIS CURRENTlY ONLY WORKS ON FIREFOX - USE FCKeditor for a cross platform version
+ *
+ * This has been tested on Fireforx / Chrome.. IE may not be so great..
*
* <br><br><b>Note: The focus/blur and validation marking functionality inherited from Ext.form.Field is NOT
* supported by this editor.</b><br/><br/>
}
+ st += '<style type="text/css">' +
+ 'IMG { cursor: pointer } ' +
+ '</style>';
+
+
return '<html><head>' + st +
//<style type="text/css">' +
//'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
//'</style>' +
- ' </head><body></body></html>';
+ ' </head><body class="roo-htmleditor-body"></body></html>';
},
// private
syncValue : function(){
if(this.initialized){
var bd = (this.doc.body || this.doc.documentElement);
- this.cleanUpPaste();
+ //this.cleanUpPaste(); -- this is done else where and causes havoc..
var html = bd.innerHTML;
if(Roo.isSafari){
var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
}
}
html = this.cleanHtml(html);
+ // fix up the special chars..
+ html = html.replace(/([\x80-\uffff])/g, function (a, b) {
+ return "&#"+b.charCodeAt()+";"
+ });
if(this.fireEvent('beforesync', this, html) !== false){
this.el.dom.value = html;
this.fireEvent('sync', this, html);
onEditorEvent : function(e){
this.fireEvent('editorevent', this, e);
// this.updateToolbar();
- this.syncValue();
+ this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
},
insertTag : function(tg)
this.doc.execCommand(cmd, false, value === undefined ? null : value);
this.syncValue();
},
-
+
+
/**
* Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
* to insert tRoo.
- * @param {String} text
+ * @param {String} text | dom node..
*/
- insertAtCursor : function(text){
+ insertAtCursor : function(text)
+ {
+
+
+
if(!this.activated){
return;
}
+ /*
if(Roo.isIE){
this.win.focus();
var r = this.doc.selection.createRange();
r.pasteHTML(text);
this.syncValue();
this.deferFocus();
+
}
- }else if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
+ return;
+ }
+ */
+ if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
this.win.focus();
- this.execCmd('InsertHTML', text);
+
+
+ // from jquery ui (MIT licenced)
+ var range, node;
+ var win = this.win;
+
+ if (win.getSelection && win.getSelection().getRangeAt) {
+ range = win.getSelection().getRangeAt(0);
+ node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
+ range.insertNode(node);
+ } else if (win.document.selection && win.document.selection.createRange) {
+ // no firefox support
+ var txt = typeof(text) == 'string' ? text : text.outerHTML;
+ win.document.selection.createRange().pasteHTML(txt);
+ } else {
+ // no firefox support
+ var txt = typeof(text) == 'string' ? text : text.outerHTML;
+ this.execCmd('InsertHTML', txt);
+ }
+
+ this.syncValue();
+
this.deferFocus();
}
},
switch(c){
case 'b':
cmd = 'bold';
- break;
+ break;
case 'i':
cmd = 'italic';
- break;
+ break;
+
case 'u':
cmd = 'underline';
+ break;
+
case 'v':
this.cleanUpPaste.defer(100, this);
return;
- break;
+
}
if(cmd){
this.win.focus();
- var range = this.createRange(this.getSelection());
+ var range = this.createRange(this.getSelection()).cloneRange();
if (Roo.isIE) {
var parent = range.parentElement();
cleanUpPaste : function()
{
// cleans up the whole document..
- // console.log('cleanuppaste');
+ Roo.log('cleanuppaste');
this.cleanUpChildren(this.doc.body);
+ var clean = this.cleanWordChars(this.doc.body.innerHTML);
+ if (clean != this.doc.body.innerHTML) {
+ this.doc.body.innerHTML = clean;
+ }
+ },
+
+ cleanWordChars : function(input) {
+ var he = Roo.form.HtmlEditor;
+
+ var output = input;
+ Roo.each(he.swapCodes, function(sw) {
+ var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
+ output = output.replace(swapper, sw[1]);
+ });
+ return output;
},
+
+
cleanUpChildren : function (n)
{
if (!n.childNodes.length) {
return;
}
- if (Roo.form.HtmlEditor.remove.indexOf(node.tagName.toLowerCase()) > -1) {
+
+ var remove_keep_children= Roo.form.HtmlEditor.remove.indexOf(node.tagName.toLowerCase()) > -1;
+
+ // remove <a name=....> as rendering on yahoo mailer is bored with this.
+
+ if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
+ remove_keep_children = true;
+ }
+
+ if (remove_keep_children) {
this.cleanUpChildren(node);
// inserts everything just before this node...
while (node.childNodes.length) {
cleanStyle(a.name,a.value);
}
/// clean up MS crap..
+ // tecnically this should be a list of valid class'es..
+
+
if (a.name == 'class') {
if (a.value.match(/^Mso/)) {
node.className = '';
}
+
+ if (a.value.match(/body/)) {
+ node.className = '';
+ }
}
// style cleanup!?
'font-size'
];
+
+Roo.form.HtmlEditor.swapCodes =[
+ [ 8211, "--" ],
+ [ 8212, "--" ],
+ [ 8216, "'" ],
+ [ 8217, "'" ],
+ [ 8220, '"' ],
+ [ 8221, '"' ],
+ [ 8226, "*" ],
+ [ 8230, "..." ]
+];
+
+
\ No newline at end of file