roojs-ui.js
[roojs1] / Roo / form / HtmlEditor.js
index d41ac6c..1371905 100644 (file)
@@ -23,7 +23,8 @@
  * @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/>
@@ -199,11 +200,16 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
             
         }
         
+        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
@@ -427,7 +433,7 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
     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!
@@ -437,6 +443,10 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
                 }
             }
             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);
@@ -605,7 +615,7 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
     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)
@@ -657,17 +667,23 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
         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();
@@ -676,10 +692,35 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
                 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();
         }
     },
@@ -693,16 +734,19 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
                 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();
@@ -820,7 +864,7 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
         
         
          
-        var range = this.createRange(this.getSelection());
+        var range = this.createRange(this.getSelection()).cloneRange();
         
         if (Roo.isIE) {
             var parent = range.parentElement();
@@ -1001,11 +1045,28 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
     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) {
@@ -1038,7 +1099,16 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
             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) {
@@ -1113,10 +1183,17 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
                 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!?
@@ -1227,3 +1304,16 @@ Roo.form.HtmlEditor.cwhite= [
         'font-size'
 ];
 
+
+Roo.form.HtmlEditor.swapCodes   =[ 
+    [    8211, "--" ], 
+    [    8212, "--" ], 
+    [    8216,  "'" ],  
+    [    8217, "'" ],  
+    [    8220, '"' ],  
+    [    8221, '"' ],  
+    [    8226, "*" ],  
+    [    8230, "..." ]
+]; 
+
+    
\ No newline at end of file