buildSDK/dependancy_bootstrap.txt
[roojs1] / roojs-bootstrap-debug.js
index 95405e0..c89dc2d 100644 (file)
@@ -11796,98 +11796,11 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
      * valid according to {@link Date#parseDate} (defaults to 'H:i').
      */
     format : "H:i",
-    
-    
-    UTCDate: function()
-    {
-        return new Date(Date.UTC.apply(Date, arguments));
-    },
-    
-    UTCTime: function()
-    {
-        return new Date(Date.UTC.apply(Date, arguments));
-    },
-    
-    UTCToday: function()
-    {
-        var today = new Date();
-        return this.UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
-    },
-    
-    UTCTodayTime: function()
-    {
-        var today = new Date();
-        return this.UTCTime(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes());
-    },
-    
-    getDate: function() {
-            var d = this.getUTCDate();
-            return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
-    },
-    
-    getUTCDate: function() {
-            return this.date;
-    },
-    
-    setDate: function(d) {
-            this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
-    },
-    
-    setUTCDate: function(d) {
-            this.date = d;
-            this.setValue(this.formatDate(this.date));
-    },
-        
+       
     onRender: function(ct, position)
     {
         
         Roo.bootstrap.TimeField.superclass.onRender.call(this, ct, position);
-//        
-//        this.language = this.language || 'en';
-//        this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : this.language.split('-')[0];
-//        this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : "en";
-//        
-//        this.isRTL = Roo.bootstrap.DateField.dates[this.language].rtl || false;
-//        this.format = this.format || 'm/d/y';
-//        this.isInline = false;
-//        this.isInput = true;
-//        this.component = this.el.select('.add-on', true).first() || false;
-//        this.component = (this.component && this.component.length === 0) ? false : this.component;
-//        this.hasInput = this.component && this.inputEL().length;
-        
-//        if (typeof(this.minViewMode === 'string')) {
-//            switch (this.minViewMode) {
-//                case 'months':
-//                    this.minViewMode = 2;
-//                    break;
-//                case 'years':
-//                    this.minViewMode = 3;
-//                    break;
-//                case 'day':
-//                    this.minViewMode = 1;
-//                    break;
-//                default:
-//                    this.minViewMode = 0;
-//                    break;
-//            }
-//        }
-        
-//        if (typeof(this.viewMode === 'string')) {
-//            switch (this.viewMode) {
-//                case 'months':
-//                    this.viewMode = 2;
-//                    break;
-//                case 'years':
-//                    this.viewMode = 2;
-//                    break;
-//                case 'day':
-//                    this.viewMode = 1;
-//                    break;
-//                default:
-//                    this.viewMode = 0;
-//                    break;
-//            }
-//        }
                 
         this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.TimeField.template);
         
@@ -11900,54 +11813,22 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
         this.picker().on('click', this.onClick, this);
         
         this.picker().addClass('datepicker-dropdown');
-        
-//        this.startViewMode = this.viewMode;
-        
-//        this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
-        
-//        this.setStartDate(this.startDate);
-//        this.setEndDate(this.endDate);
-        
-//        this.setDaysOfWeekDisabled(this.daysOfWeekDisabled);
-        
-//        this.fillDow();
-//        this.fillMonths();
+    
         this.fillTime();
         this.update();
-//        this.showMode();
-        
-//        if(this.showTime){
-            
-//            var dayFoot = this.picker().select('>.datepicker-days tfoot th', true).first();
-//            var timeFoot = this.picker().select('>.datepicker-time tfoot th', true).first();
-//
-//            var dayFootIcon = this.picker().select('>.datepicker-days tfoot span.picker-switch-icon', true).first();
-//            var timeFootIcon = this.picker().select('>.datepicker-time tfoot span.picker-switch-icon', true).first();
-//            
-//            timeFoot.addClass('switch-calendar');
-//            dayFoot.addClass('switch-time');
-//            
-//            timeFootIcon.addClass('switch-calendar');
-//            timeFootIcon.addClass('glyphicon-calendar');
-//            
-//            dayFootIcon.addClass('switch-time');
-//            dayFootIcon.addClass('glyphicon-time');
             
         this.pop.select('span.hours-up', true).first().on('click', this.onIncrementHours, this);
         this.pop.select('span.hours-down', true).first().on('click', this.onDecrementHours, this);
         this.pop.select('span.minutes-up', true).first().on('click', this.onIncrementMinutes, this);
         this.pop.select('span.minutes-down', true).first().on('click', this.onDecrementMinutes, this);
-        this.pop.select('button', true).first().on('click', this.onTogglePeriod, this);
+        this.pop.select('button.period', true).first().on('click', this.onTogglePeriod, this);
+        this.pop.select('button.ok', true).first().on('click', this.setTime, this);
 
-//        }else{
-//            Roo.each(this.picker().select('tfoot th', true).elements, function(v){
-//                v.remove();
-//            });
-//        }
-//        
-//        if(this.isInline) {
-//            this.show();
-//        }
+    },
+    
+    onClick: function(e) {
+        e.stopPropagation();
+        e.preventDefault();
     },
     
     picker : function()
@@ -12045,7 +11926,7 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
                         {
                             tag: 'button',
                             type: 'button',
-                            cls: 'btn btn-primary',
+                            cls: 'btn btn-primary period',
                             html: 'AM'
                             
                         }
@@ -12142,24 +12023,9 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
         this.pop.select('button', true).first().dom.innerHTML = period;
         
     },
-//    
-//    showMode: function(dir) {
-//        if (dir) {
-//            this.viewMode = Math.max(this.minViewMode, Math.min(3, this.viewMode + dir));
-//        }
-//        
-//        Roo.each(this.picker().select('>div',true).elements, function(v){
-//            v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-//            v.hide();
-//        });
-//        this.picker().select('>.datepicker-'+Roo.bootstrap.DateField.modes[this.viewMode].clsName, true).first().show();
-//        
-//    },
     
     place: function()
-    {
-//        if(this.isInline) return;
-        
+    {   
         this.picker().removeClass(['bottom', 'top']);
         
         if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
@@ -12178,31 +12044,7 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
         
         this.picker().setTop(this.inputEl().getHeight()).setLeft(this.inputEl().getLeft() - this.el.getLeft());
     },
-    
-//    parseDate : function(value){
-//        if(!value || value instanceof Date){
-//            return value;
-//        }
-//        var v = Date.parseDate(value, this.format);
-//        if (!v && this.useIso) {
-//            v = Date.parseDate(value, 'Y-m-d');
-//        }
-//        if(!v && this.altFormats){
-//            if(!this.altFormatsArray){
-//                this.altFormatsArray = this.altFormats.split("|");
-//            }
-//            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
-//                v = Date.parseDate(value, this.altFormatsArray[i]);
-//            }
-//        }
-//        return v;
-//    },
-    
-//    formatDate : function(date, fmt){
-//        return (!date || !(date instanceof Date)) ?
-//        date : date.dateFormat(fmt || this.format);
-//    },
-    
+  
     onFocus : function()
     {
         Roo.bootstrap.TimeField.superclass.onFocus.call(this);
@@ -12228,347 +12070,19 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
         this.picker().hide();
         this.pop.hide();
         
-        this.setValue(this.time.format(this.format));
-        
     },
     
-    onMousedown: function(e){
-        e.stopPropagation();
-        e.preventDefault();
+    setTime : function()
+    {
+        this.hide();
+        this.setValue(this.time.format(this.format));
     },
-//    
-//    keyup: function(e){
-//        Roo.bootstrap.DateField.superclass.keyup.call(this);
-//        this.update();
-//        
-//    },
     
-//    fireKey: function(e){
-//        if (!this.picker().isVisible()){
-//            if (e.keyCode == 27) // allow escape to hide and re-show picker
-//                this.show();
-//            return;
-//        }
-//        var dateChanged = false,
-//        dir, day, month,
-//        newDate, newViewDate;
-//        switch(e.keyCode){
-//            case 27: // escape
-//                this.hide();
-//                e.preventDefault();
-//                break;
-//            case 37: // left
-//            case 39: // right
-//                if (!this.keyboardNavigation) break;
-//                dir = e.keyCode == 37 ? -1 : 1;
-//                
-//                if (e.ctrlKey){
-//                    newDate = this.moveYear(this.date, dir);
-//                    newViewDate = this.moveYear(this.viewDate, dir);
-//                } else if (e.shiftKey){
-//                    newDate = this.moveMonth(this.date, dir);
-//                    newViewDate = this.moveMonth(this.viewDate, dir);
-//                } else {
-//                    newDate = new Date(this.date);
-//                    newDate.setUTCDate(this.date.getUTCDate() + dir);
-//                    newViewDate = new Date(this.viewDate);
-//                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
-//                }
-//                if (this.dateWithinRange(newDate)){
-//                    this.date = newDate;
-//                    this.viewDate = newViewDate;
-//                    this.setValue(this.formatDate(this.date));
-//                    this.update();
-//                    e.preventDefault();
-//                    dateChanged = true;
-//                }
-//                break;
-//            case 38: // up
-//            case 40: // down
-//                if (!this.keyboardNavigation) break;
-//                dir = e.keyCode == 38 ? -1 : 1;
-//                if (e.ctrlKey){
-//                    newDate = this.moveYear(this.date, dir);
-//                    newViewDate = this.moveYear(this.viewDate, dir);
-//                } else if (e.shiftKey){
-//                    newDate = this.moveMonth(this.date, dir);
-//                    newViewDate = this.moveMonth(this.viewDate, dir);
-//                } else {
-//                    newDate = new Date(this.date);
-//                    newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
-//                    newViewDate = new Date(this.viewDate);
-//                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
-//                }
-//                if (this.dateWithinRange(newDate)){
-//                    this.date = newDate;
-//                    this.viewDate = newViewDate;
-//                    this.setValue(this.formatDate(this.date));
-//                    this.update();
-//                    e.preventDefault();
-//                    dateChanged = true;
-//                }
-//                break;
-//            case 13: // enter
-//                this.setValue(this.formatDate(this.date));
-//                this.hide();
-//                e.preventDefault();
-//                break;
-//            case 9: // tab
-//                this.setValue(this.formatDate(this.date));
-//                this.hide();
-//                break;
-//        }
-//    },
-    
-    
-    onClick: function(e) {
+    onMousedown: function(e){
         e.stopPropagation();
         e.preventDefault();
-        
-        var target = e.getTarget();
-        
-//        if(target.nodeName.toLowerCase() === 'i'){
-//            target = Roo.get(target).dom.parentNode;
-//        }
-        
-        var nodeName = target.nodeName.trim();
-        var className = target.className.trim();
-        var html = target.innerHTML;
-        
-        Roo.log('nodeName');
-        Roo.log(nodeName);
-        
-        Roo.log('className');
-        Roo.log(className);
-        
-        Roo.log('html');
-        Roo.log(html);
-        
-        
-//        switch(nodeName.toLowerCase()) {
-//            case 'th':
-//                switch(className) {
-//                    case 'switch':
-//                        this.showMode(1);
-//                        break;
-//                    case 'prev':
-//                    case 'next':
-//                        var dir = Roo.bootstrap.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
-//                        switch(this.viewMode){
-//                                case 0:
-//                                        this.viewDate = this.moveMonth(this.viewDate, dir);
-//                                        break;
-//                                case 1:
-//                                case 2:
-//                                        this.viewDate = this.moveYear(this.viewDate, dir);
-//                                        break;
-//                        }
-//                        this.fill();
-//                        break;
-//                    case 'today':
-//                        var date = new Date();
-//                        this.date = this.UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
-//                        this.fill()
-//                        this.setValue(this.formatDate(this.date));
-//                        this.hide();
-//                        break;
-//                     case 'switch-time':
-//                        this.showMode(-1);
-//                        this.fill();
-//                        break;
-//                     case 'switch-calendar':
-//                         this.showMode(1);
-//                         this.fill();
-//                         break;
-//                }
-//                break;
-//            case 'span':
-//                if (className.indexOf('disabled') === -1) {
-//                    this.viewDate.setUTCDate(1);
-//                    if (className.indexOf('month') !== -1) {
-//                        this.viewDate.setUTCMonth(Roo.bootstrap.DateField.dates[this.language].monthsShort.indexOf(html));
-//                    } else if(className.indexOf('picker-switch-icon') !== -1){
-//                        if(className.indexOf('switch-time') !== -1){
-//                            this.showMode(-1);
-//                            this.fill();
-//                        }else{
-//                            this.showMode(1);
-//                            this.fill();
-//                        }
-//                        
-//                        break;
-//                        
-//                    } else {
-//                        var year = parseInt(html, 10) || 0;
-//                        this.viewDate.setUTCFullYear(year);
-//                        
-//                    }
-//                    this.showMode(-1);
-//                    this.fill();
-//                }
-//                break;
-//                
-//            case 'td':
-//                if (className.indexOf('day') !== -1 && className.indexOf('disabled') === -1){
-//                    var day = parseInt(html, 10) || 1;
-//                    var year = this.viewDate.getUTCFullYear(),
-//                        month = this.viewDate.getUTCMonth();
-//
-//                    if (className.indexOf('old') !== -1) {
-//                        if(month === 0 ){
-//                            month = 11;
-//                            year -= 1;
-//                        }else{
-//                            month -= 1;
-//                        }
-//                    } else if (className.indexOf('new') !== -1) {
-//                        if (month == 11) {
-//                            month = 0;
-//                            year += 1;
-//                        } else {
-//                            month += 1;
-//                        }
-//                    }
-//                    this.date = this.UTCDate(year, month, day,0,0,0,0);
-//                    this.viewDate = this.UTCDate(year, month, Math.min(28, day),0,0,0,0);
-//                    this.fill();
-//                    this.setValue(this.formatDate(this.date));
-//                    this.hide();
-//                }
-//                break;
-//        }
     },
     
-//    setStartDate: function(startDate){
-//        this.startDate = startDate || -Infinity;
-//        if (this.startDate !== -Infinity) {
-//            this.startDate = this.parseDate(this.startDate);
-//        }
-//        this.update();
-//        this.updateNavArrows();
-//    },
-//
-//    setEndDate: function(endDate){
-//        this.endDate = endDate || Infinity;
-//        if (this.endDate !== Infinity) {
-//            this.endDate = this.parseDate(this.endDate);
-//        }
-//        this.update();
-//        this.updateNavArrows();
-//    },
-//    
-//    setDaysOfWeekDisabled: function(daysOfWeekDisabled){
-//        this.daysOfWeekDisabled = daysOfWeekDisabled || [];
-//        if (typeof(this.daysOfWeekDisabled) !== 'object') {
-//            this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
-//        }
-//        this.daysOfWeekDisabled = this.daysOfWeekDisabled.map(function (d) {
-//            return parseInt(d, 10);
-//        });
-//        this.update();
-//        this.updateNavArrows();
-//    },
-//    
-//    updateNavArrows: function() {
-//        var d = new Date(this.viewDate),
-//        year = d.getUTCFullYear(),
-//        month = d.getUTCMonth();
-//        
-//        Roo.each(this.picker().select('.prev', true).elements, function(v){
-//            v.show();
-//            switch (this.viewMode) {
-//                case 0:
-//
-//                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
-//                        v.hide();
-//                    }
-//                    break;
-//                case 1:
-//                case 2:
-//                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
-//                        v.hide();
-//                    }
-//                    break;
-//            }
-//        });
-//        
-//        Roo.each(this.picker().select('.next', true).elements, function(v){
-//            v.show();
-//            switch (this.viewMode) {
-//                case 0:
-//
-//                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
-//                        v.hide();
-//                    }
-//                    break;
-//                case 1:
-//                case 2:
-//                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
-//                        v.hide();
-//                    }
-//                    break;
-//            }
-//        })
-//    },
-//    
-//    moveMonth: function(date, dir){
-//        if (!dir) return date;
-//        var new_date = new Date(date.valueOf()),
-//        day = new_date.getUTCDate(),
-//        month = new_date.getUTCMonth(),
-//        mag = Math.abs(dir),
-//        new_month, test;
-//        dir = dir > 0 ? 1 : -1;
-//        if (mag == 1){
-//            test = dir == -1
-//            // If going back one month, make sure month is not current month
-//            // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
-//            ? function(){
-//                return new_date.getUTCMonth() == month;
-//            }
-//            // If going forward one month, make sure month is as expected
-//            // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
-//            : function(){
-//                return new_date.getUTCMonth() != new_month;
-//            };
-//            new_month = month + dir;
-//            new_date.setUTCMonth(new_month);
-//            // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
-//            if (new_month < 0 || new_month > 11)
-//                new_month = (new_month + 12) % 12;
-//        } else {
-//            // For magnitudes >1, move one month at a time...
-//            for (var i=0; i<mag; i++)
-//                // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
-//                new_date = this.moveMonth(new_date, dir);
-//            // ...then reset the day, keeping it in the new month
-//            new_month = new_date.getUTCMonth();
-//            new_date.setUTCDate(day);
-//            test = function(){
-//                return new_month != new_date.getUTCMonth();
-//            };
-//        }
-//        // Common date-resetting loop -- if date is beyond end of month, make it
-//        // end of month
-//        while (test()){
-//            new_date.setUTCDate(--day);
-//            new_date.setUTCMonth(new_month);
-//        }
-//        return new_date;
-//    },
-//
-//    moveYear: function(date, dir){
-//        return this.moveMonth(date, dir*12);
-//    },
-//
-//    dateWithinRange: function(date){
-//        return date >= this.startDate && date <= this.endDate;
-//    },
-
-//    remove: function() {
-//        this.picker().remove();
-//    },
-    
     onIncrementHours: function()
     {
         Roo.log('onIncrementHours');
@@ -12613,15 +12127,39 @@ Roo.apply(Roo.bootstrap.TimeField,  {
     content : {
         tag: 'tbody',
         cn: [
-        {
-            tag: 'tr',
-            cn: [
             {
-                tag: 'td',
-                colspan: '7'
+                tag: 'tr',
+                cn: [
+                {
+                    tag: 'td',
+                    colspan: '7'
+                }
+                ]
+            }
+        ]
+    },
+    
+    footer : {
+        tag: 'tfoot',
+        cn: [
+            {
+                tag: 'tr',
+                cn: [
+                {
+                    tag: 'th',
+                    colspan: '7',
+                    cls: '',
+                    cn: [
+                        {
+                            tag: 'button',
+                            cls: 'btn btn-info ok',
+                            html: 'OK'
+                        }
+                    ]
+                }
+
+                ]
             }
-            ]
-        }
         ]
     }
 });
@@ -12640,7 +12178,8 @@ Roo.apply(Roo.bootstrap.TimeField,  {
                     tag: 'table',
                     cls: 'table-condensed',
                     cn:[
-                    Roo.bootstrap.DateField.content
+                    Roo.bootstrap.TimeField.content,
+                    Roo.bootstrap.TimeField.footer
                     ]
                 }
                 ]
@@ -13056,7 +12595,1256 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
 });
 
  
+//<script type="text/javascript">
+
 /*
+ * Based  Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ * LGPL
+ *
+ */
+/**
+ * @class Roo.HtmlEditorCore
+ * @extends Roo.Component
+ * Provides a the editing component for the HTML editors in Roo. (bootstrap and Roo.form)
+ *
+ * any element that has display set to 'none' can cause problems in Safari and Firefox.<br/><br/>
+ */
+
+Roo.HtmlEditorCore = function(config){
+    
+    
+    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
+    this.addEvents({
+        /**
+         * @event initialize
+         * Fires when the editor is fully initialized (including the iframe)
+         * @param {Roo.HtmlEditorCore} this
+         */
+        initialize: true,
+        /**
+         * @event activate
+         * Fires when the editor is first receives the focus. Any insertion must wait
+         * until after this event.
+         * @param {Roo.HtmlEditorCore} this
+         */
+        activate: true,
+         /**
+         * @event beforesync
+         * Fires before the textarea is updated with content from the editor iframe. Return false
+         * to cancel the sync.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        beforesync: true,
+         /**
+         * @event beforepush
+         * Fires before the iframe editor is updated with content from the textarea. Return false
+         * to cancel the push.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        beforepush: true,
+         /**
+         * @event sync
+         * Fires when the textarea is updated with content from the editor iframe.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        sync: true,
+         /**
+         * @event push
+         * Fires when the iframe editor is updated with content from the textarea.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        push: true,
+        
+        /**
+         * @event editorevent
+         * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
+         * @param {Roo.HtmlEditorCore} this
+         */
+        editorevent: true
+    });
+     
+};
+
+
+Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
+
+
+     /**
+     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
+     */
+    
+    owner : false,
+    
+     /**
+     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
+     *                        Roo.resizable.
+     */
+    resizable : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: 500,
+    
+    /**
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
+     */
+    stylesheets: false,
+    
+    // id of frame..
+    frameId: false,
+    
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
+    
+     
+    
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor initializes the iframe with HTML contents. Override this method if you
+     * want to change the initialization markup of the iframe (e.g. to add stylesheets).
+     */
+    getDocMarkup : function(){
+        // body styles..
+        var st = '';
+        Roo.log(this.stylesheets);
+        
+        // inherit styels from page...?? 
+        if (this.stylesheets === false) {
+            
+            Roo.get(document.head).select('style').each(function(node) {
+                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
+            });
+            
+            Roo.get(document.head).select('link').each(function(node) { 
+                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
+            });
+            
+        } else if (!this.stylesheets.length) {
+                // simple..
+                st = '<style type="text/css">' +
+                    'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
+                   '</style>';
+        } else {
+            Roo.each(this.stylesheets, function(s) {
+                st += '<link rel="stylesheet" type="text/css" href="' + s +'" />'
+            });
+            
+        }
+        
+        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 class="roo-htmleditor-body"></body></html>';
+    },
+
+    // private
+    onRender : function(ct, position)
+    {
+        var _t = this;
+        //Roo.HtmlEditorCore.superclass.onRender.call(this, ct, position);
+        this.el = this.owner.inputEl ? this.owner.inputEl() : this.owner.el;
+        
+        
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden hide');
+        
+        
+        
+        if(Roo.isIE){ // fix IE 1px bogus margin
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        }
+       
+        
+        this.frameId = Roo.id();
+        
+         
+        
+        var iframe = this.owner.wrap.createChild({
+            tag: 'iframe',
+            cls: 'form-control', // bootstrap..
+            id: this.frameId,
+            name: this.frameId,
+            frameBorder : 'no',
+            'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL  :  "javascript:false"
+        }, this.el
+        );
+        
+        
+        this.iframe = iframe.dom;
+
+         this.assignDocWin();
+        
+        this.doc.designMode = 'on';
+       
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
+
+        
+        var task = { // must defer to wait for browser to be ready
+            run : function(){
+                //console.log("run task?" + this.doc.readyState);
+                this.assignDocWin();
+                if(this.doc.body || this.doc.readyState == 'complete'){
+                    try {
+                        this.doc.designMode="on";
+                    } catch (e) {
+                        return;
+                    }
+                    Roo.TaskMgr.stop(task);
+                    this.initEditor.defer(10, this);
+                }
+            },
+            interval : 10,
+            duration: 10000,
+            scope: this
+        };
+        Roo.TaskMgr.start(task);
+
+        
+         
+    },
+
+    // private
+    onResize : function(w, h)
+    {
+         Roo.log('resize: ' +w + ',' + h );
+        //Roo.HtmlEditorCore.superclass.onResize.apply(this, arguments);
+        if(!this.iframe){
+            return;
+        }
+        if(typeof w == 'number'){
+            
+            this.iframe.style.width = w + 'px';
+        }
+        if(typeof h == 'number'){
+            
+            this.iframe.style.height = h + 'px';
+            if(this.doc){
+                (this.doc.body || this.doc.documentElement).style.height = (h - (this.iframePad*2)) + 'px';
+            }
+        }
+        
+    },
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode){
+        
+        this.sourceEditMode = sourceEditMode === true;
+        
+        if(this.sourceEditMode){
+            Roo.get(this.iframe).addClass(['x-hidden','hide']);     //FIXME - what's the BS styles for these
+            
+        }else{
+            Roo.get(this.iframe).removeClass(['x-hidden','hide']);
+            //this.iframe.className = '';
+            this.deferFocus();
+        }
+        //this.setSize(this.owner.wrap.getSize());
+        //this.fireEvent('editmodechange', this, this.sourceEditMode);
+    },
+
+    
+  
+
+    /**
+     * Protected method that will not generally be called directly. If you need/want
+     * custom HTML cleanup, this is the method you should override.
+     * @param {String} html The HTML to be cleaned
+     * return {String} The cleaned HTML
+     */
+    cleanHtml : function(html){
+        html = String(html);
+        if(html.length > 5){
+            if(Roo.isSafari){ // strip safari nonsense
+                html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+            }
+        }
+        if(html == '&nbsp;'){
+            html = '';
+        }
+        return html;
+    },
+
+    /**
+     * HTML Editor -> Textarea
+     * Protected method that will not generally be called directly. Syncs the contents
+     * of the editor iframe with the textarea.
+     */
+    syncValue : function(){
+        if(this.initialized){
+            var bd = (this.doc.body || this.doc.documentElement);
+            //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!
+                var m = bs ? bs.match(/text-align:(.*?);/i) : false;
+                if(m && m[1]){
+                    html = '<div style="'+m[0]+'">' + html + '</div>';
+                }
+            }
+            html = this.cleanHtml(html);
+            // fix up the special chars.. normaly like back quotes in word...
+            // however we do not want to do this with chinese..
+            html = html.replace(/([\x80-\uffff])/g, function (a, b) {
+                var cc = b.charCodeAt();
+                if (
+                    (cc >= 0x4E00 && cc < 0xA000 ) ||
+                    (cc >= 0x3400 && cc < 0x4E00 ) ||
+                    (cc >= 0xf900 && cc < 0xfb00 )
+                ) {
+                        return b;
+                }
+                return "&#"+cc+";" 
+            });
+            if(this.owner.fireEvent('beforesync', this, html) !== false){
+                this.el.dom.value = html;
+                this.owner.fireEvent('sync', this, html);
+            }
+        }
+    },
+
+    /**
+     * Protected method that will not generally be called directly. Pushes the value of the textarea
+     * into the iframe editor.
+     */
+    pushValue : function(){
+        if(this.initialized){
+            var v = this.el.dom.value;
+            
+            if(v.length < 1){
+                v = '&#160;';
+            }
+            
+            if(this.owner.fireEvent('beforepush', this, v) !== false){
+                var d = (this.doc.body || this.doc.documentElement);
+                d.innerHTML = v;
+                this.cleanUpPaste();
+                this.el.dom.value = d.innerHTML;
+                this.owner.fireEvent('push', this, v);
+            }
+        }
+    },
+
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
+    },
+
+    // doc'ed in Field
+    focus : function(){
+        if(this.win && !this.sourceEditMode){
+            this.win.focus();
+        }else{
+            this.el.focus();
+        }
+    },
+    
+    assignDocWin: function()
+    {
+        var iframe = this.iframe;
+        
+         if(Roo.isIE){
+            this.doc = iframe.contentWindow.document;
+            this.win = iframe.contentWindow;
+        } else {
+            if (!Roo.get(this.frameId)) {
+                return;
+            }
+            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
+            this.win = Roo.get(this.frameId).dom.contentWindow;
+        }
+    },
+    
+    // private
+    initEditor : function(){
+        //console.log("INIT EDITOR");
+        this.assignDocWin();
+        
+        
+        
+        this.doc.designMode="on";
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
+        
+        var dbody = (this.doc.body || this.doc.documentElement);
+        //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
+        // this copies styles from the containing element into thsi one..
+        // not sure why we need all of this..
+        var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
+        ss['background-attachment'] = 'fixed'; // w3c
+        dbody.bgProperties = 'fixed'; // ie
+        Roo.DomHelper.applyStyles(dbody, ss);
+        Roo.EventManager.on(this.doc, {
+            //'mousedown': this.onEditorEvent,
+            'mouseup': this.onEditorEvent,
+            'dblclick': this.onEditorEvent,
+            'click': this.onEditorEvent,
+            'keyup': this.onEditorEvent,
+            buffer:100,
+            scope: this
+        });
+        if(Roo.isGecko){
+            Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
+        }
+        if(Roo.isIE || Roo.isSafari || Roo.isOpera){
+            Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
+        }
+        this.initialized = true;
+
+        this.owner.fireEvent('initialize', this);
+        this.pushValue();
+    },
+
+    // private
+    onDestroy : function(){
+        
+        
+        
+        if(this.rendered){
+            
+            //for (var i =0; i < this.toolbars.length;i++) {
+            //    // fixme - ask toolbars for heights?
+            //    this.toolbars[i].onDestroy();
+           // }
+            
+            //this.wrap.dom.innerHTML = '';
+            //this.wrap.remove();
+        }
+    },
+
+    // private
+    onFirstFocus : function(){
+        
+        this.assignDocWin();
+        
+        
+        this.activated = true;
+         
+    
+        if(Roo.isGecko){ // prevent silly gecko errors
+            this.win.focus();
+            var s = this.win.getSelection();
+            if(!s.focusNode || s.focusNode.nodeType != 3){
+                var r = s.getRangeAt(0);
+                r.selectNodeContents((this.doc.body || this.doc.documentElement));
+                r.collapse(true);
+                this.deferFocus();
+            }
+            try{
+                this.execCmd('useCSS', true);
+                this.execCmd('styleWithCSS', false);
+            }catch(e){}
+        }
+        this.owner.fireEvent('activate', this);
+    },
+
+    // private
+    adjustFont: function(btn){
+        var adjust = btn.cmd == 'increasefontsize' ? 1 : -1;
+        //if(Roo.isSafari){ // safari
+        //    adjust *= 2;
+       // }
+        var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
+        if(Roo.isSafari){ // safari
+            var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
+            v =  (v < 10) ? 10 : v;
+            v =  (v > 48) ? 48 : v;
+            v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
+            
+        }
+        
+        
+        v = Math.max(1, v+adjust);
+        
+        this.execCmd('FontSize', v  );
+    },
+
+    onEditorEvent : function(e){
+        this.owner.fireEvent('editorevent', this, e);
+      //  this.updateToolbar();
+        this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
+    },
+
+    insertTag : function(tg)
+    {
+        // could be a bit smarter... -> wrap the current selected tRoo..
+        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
+            
+            range = this.createRange(this.getSelection());
+            var wrappingNode = this.doc.createElement(tg.toLowerCase());
+            wrappingNode.appendChild(range.extractContents());
+            range.insertNode(wrappingNode);
+
+            return;
+            
+            
+            
+        }
+        this.execCmd("formatblock",   tg);
+        
+    },
+    
+    insertText : function(txt)
+    {
+        
+        
+        var range = this.createRange();
+        range.deleteContents();
+               //alert(Sender.getAttribute('label'));
+               
+        range.insertNode(this.doc.createTextNode(txt));
+    } ,
+    
+     
+
+    /**
+     * Executes a Midas editor command on the editor document and performs necessary focus and
+     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    relayCmd : function(cmd, value){
+        this.win.focus();
+        this.execCmd(cmd, value);
+        this.owner.fireEvent('editorevent', this);
+        //this.updateToolbar();
+        this.owner.deferFocus();
+    },
+
+    /**
+     * Executes a Midas editor command directly on the editor document.
+     * For visual commands, you should use {@link #relayCmd} instead.
+     * <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    execCmd : function(cmd, value){
+        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 | dom node.. 
+     */
+    insertAtCursor : function(text)
+    {
+        
+        
+        
+        if(!this.activated){
+            return;
+        }
+        /*
+        if(Roo.isIE){
+            this.win.focus();
+            var r = this.doc.selection.createRange();
+            if(r){
+                r.collapse(true);
+                r.pasteHTML(text);
+                this.syncValue();
+                this.deferFocus();
+            
+            }
+            return;
+        }
+        */
+        if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
+            this.win.focus();
+            
+            
+            // 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();
+        }
+    },
+ // private
+    mozKeyPress : function(e){
+        if(e.ctrlKey){
+            var c = e.getCharCode(), cmd;
+          
+            if(c > 0){
+                c = String.fromCharCode(c).toLowerCase();
+                switch(c){
+                    case 'b':
+                        cmd = 'bold';
+                        break;
+                    case 'i':
+                        cmd = 'italic';
+                        break;
+                    
+                    case 'u':
+                        cmd = 'underline';
+                        break;
+                    
+                    case 'v':
+                        this.cleanUpPaste.defer(100, this);
+                        return;
+                        
+                }
+                if(cmd){
+                    this.win.focus();
+                    this.execCmd(cmd);
+                    this.deferFocus();
+                    e.preventDefault();
+                }
+                
+            }
+        }
+    },
+
+    // private
+    fixKeys : function(){ // load time branching for fastest keydown performance
+        if(Roo.isIE){
+            return function(e){
+                var k = e.getKey(), r;
+                if(k == e.TAB){
+                    e.stopEvent();
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        r.collapse(true);
+                        r.pasteHTML('&#160;&#160;&#160;&#160;');
+                        this.deferFocus();
+                    }
+                    return;
+                }
+                
+                if(k == e.ENTER){
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        var target = r.parentElement();
+                        if(!target || target.tagName.toLowerCase() != 'li'){
+                            e.stopEvent();
+                            r.pasteHTML('<br />');
+                            r.collapse(false);
+                            r.select();
+                        }
+                    }
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+                
+            };
+        }else if(Roo.isOpera){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.win.focus();
+                    this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
+                    this.deferFocus();
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+            };
+        }else if(Roo.isSafari){
+            return function(e){
+                var k = e.getKey();
+                
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.execCmd('InsertText','\t');
+                    this.deferFocus();
+                    return;
+                }
+               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+             };
+        }
+    }(),
+    
+    getAllAncestors: function()
+    {
+        var p = this.getSelectedNode();
+        var a = [];
+        if (!p) {
+            a.push(p); // push blank onto stack..
+            p = this.getParentElement();
+        }
+        
+        
+        while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+            a.push(p);
+            p = p.parentNode;
+        }
+        a.push(this.doc.body);
+        return a;
+    },
+    lastSel : false,
+    lastSelNode : false,
+    
+    
+    getSelection : function() 
+    {
+        this.assignDocWin();
+        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+    },
+    
+    getSelectedNode: function() 
+    {
+        // this may only work on Gecko!!!
+        
+        // should we cache this!!!!
+        
+        
+        
+         
+        var range = this.createRange(this.getSelection()).cloneRange();
+        
+        if (Roo.isIE) {
+            var parent = range.parentElement();
+            while (true) {
+                var testRange = range.duplicate();
+                testRange.moveToElementText(parent);
+                if (testRange.inRange(range)) {
+                    break;
+                }
+                if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            return parent;
+        }
+        
+        // is ancestor a text element.
+        var ac =  range.commonAncestorContainer;
+        if (ac.nodeType == 3) {
+            ac = ac.parentNode;
+        }
+        
+        var ar = ac.childNodes;
+         
+        var nodes = [];
+        var other_nodes = [];
+        var has_other_nodes = false;
+        for (var i=0;i<ar.length;i++) {
+            if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ? 
+                continue;
+            }
+            // fullly contained node.
+            
+            if (this.rangeIntersectsNode(range,ar[i]) && this.rangeCompareNode(range,ar[i]) == 3) {
+                nodes.push(ar[i]);
+                continue;
+            }
+            
+            // probably selected..
+            if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(range,ar[i]) && (this.rangeCompareNode(range,ar[i]) > 0)) {
+                other_nodes.push(ar[i]);
+                continue;
+            }
+            // outer..
+            if (!this.rangeIntersectsNode(range,ar[i])|| (this.rangeCompareNode(range,ar[i]) == 0))  {
+                continue;
+            }
+            
+            
+            has_other_nodes = true;
+        }
+        if (!nodes.length && other_nodes.length) {
+            nodes= other_nodes;
+        }
+        if (has_other_nodes || !nodes.length || (nodes.length > 1)) {
+            return false;
+        }
+        
+        return nodes[0];
+    },
+    createRange: function(sel)
+    {
+        // this has strange effects when using with 
+        // top toolbar - not sure if it's a great idea.
+        //this.editor.contentWindow.focus();
+        if (typeof sel != "undefined") {
+            try {
+                return sel.getRangeAt ? sel.getRangeAt(0) : sel.createRange();
+            } catch(e) {
+                return this.doc.createRange();
+            }
+        } else {
+            return this.doc.createRange();
+        }
+    },
+    getParentElement: function()
+    {
+        
+        this.assignDocWin();
+        var sel = Roo.isIE ? this.doc.selection : this.win.getSelection();
+        
+        var range = this.createRange(sel);
+         
+        try {
+            var p = range.commonAncestorContainer;
+            while (p.nodeType == 3) { // text node
+                p = p.parentNode;
+            }
+            return p;
+        } catch (e) {
+            return null;
+        }
+    
+    },
+    /***
+     *
+     * Range intersection.. the hard stuff...
+     *  '-1' = before
+     *  '0' = hits..
+     *  '1' = after.
+     *         [ -- selected range --- ]
+     *   [fail]                        [fail]
+     *
+     *    basically..
+     *      if end is before start or  hits it. fail.
+     *      if start is after end or hits it fail.
+     *
+     *   if either hits (but other is outside. - then it's not 
+     *   
+     *    
+     **/
+    
+    
+    // @see http://www.thismuchiknow.co.uk/?p=64.
+    rangeIntersectsNode : function(range, node)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
+    
+        var rangeStartRange = range.cloneRange();
+        rangeStartRange.collapse(true);
+    
+        var rangeEndRange = range.cloneRange();
+        rangeEndRange.collapse(false);
+    
+        var nodeStartRange = nodeRange.cloneRange();
+        nodeStartRange.collapse(true);
+    
+        var nodeEndRange = nodeRange.cloneRange();
+        nodeEndRange.collapse(false);
+    
+        return rangeStartRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeEndRange) == -1 &&
+               rangeEndRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeStartRange) == 1;
+        
+         
+    },
+    rangeCompareNode : function(range, node)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
+        
+        
+        range.collapse(true);
+    
+        nodeRange.collapse(true);
+     
+        var ss = range.compareBoundaryPoints( Range.START_TO_START, nodeRange);
+        var ee = range.compareBoundaryPoints(  Range.END_TO_END, nodeRange);
+         
+        //Roo.log(node.tagName + ': ss='+ss +', ee='+ee)
+        
+        var nodeIsBefore   =  ss == 1;
+        var nodeIsAfter    = ee == -1;
+        
+        if (nodeIsBefore && nodeIsAfter)
+            return 0; // outer
+        if (!nodeIsBefore && nodeIsAfter)
+            return 1; //right trailed.
+        
+        if (nodeIsBefore && !nodeIsAfter)
+            return 2;  // left trailed.
+        // fully contined.
+        return 3;
+    },
+
+    // private? - in a new class?
+    cleanUpPaste :  function()
+    {
+        // cleans up the whole document..
+         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) {// change the chars to hex code
+        var he = Roo.HtmlEditorCore;
+        
+        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;
+        }
+        for (var i = n.childNodes.length-1; i > -1 ; i--) {
+           this.cleanUpChild(n.childNodes[i]);
+        }
+    },
+    
+    
+        
+    
+    cleanUpChild : function (node)
+    {
+        var ed = this;
+        //console.log(node);
+        if (node.nodeName == "#text") {
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        
+        if (Roo.HtmlEditorCore.black.indexOf(node.tagName.toLowerCase()) > -1) {
+            // remove node.
+            node.parentNode.removeChild(node);
+            return;
+            
+        }
+        
+        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
+        
+        // remove <a name=....> as rendering on yahoo mailer is borked with this.
+        // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
+        
+        //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) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
+            }
+            node.parentNode.removeChild(node);
+            return;
+        }
+        
+        if (!node.attributes || !node.attributes.length) {
+            this.cleanUpChildren(node);
+            return;
+        }
+        
+        function cleanAttr(n,v)
+        {
+            
+            if (v.match(/^\./) || v.match(/^\//)) {
+                return;
+            }
+            if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
+                return;
+            }
+            if (v.match(/^#/)) {
+                return;
+            }
+//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
+            node.removeAttribute(n);
+            
+        }
+        
+        function cleanStyle(n,v)
+        {
+            if (v.match(/expression/)) { //XSS?? should we even bother..
+                node.removeAttribute(n);
+                return;
+            }
+            var cwhite = typeof(ed.cwhite) == 'undefined' ? Roo.HtmlEditorCore.cwhite : ed.cwhite;
+            var cblack = typeof(ed.cblack) == 'undefined' ? Roo.HtmlEditorCore.cblack : ed.cblack;
+            
+            
+            var parts = v.split(/;/);
+            var clean = [];
+            
+            Roo.each(parts, function(p) {
+                p = p.replace(/^\s+/g,'').replace(/\s+$/g,'');
+                if (!p.length) {
+                    return true;
+                }
+                var l = p.split(':').shift().replace(/\s+/g,'');
+                l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
+                
+                
+                if ( cblack.indexOf(l) > -1) {
+//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
+                    //node.removeAttribute(n);
+                    return true;
+                }
+                //Roo.log()
+                // only allow 'c whitelisted system attributes'
+                if ( cwhite.length &&  cwhite.indexOf(l) < 0) {
+//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
+                    //node.removeAttribute(n);
+                    return true;
+                }
+                
+                
+                 
+                
+                clean.push(p);
+                return true;
+            });
+            if (clean.length) { 
+                node.setAttribute(n, clean.join(';'));
+            } else {
+                node.removeAttribute(n);
+            }
+            
+        }
+        
+        
+        for (var i = node.attributes.length-1; i > -1 ; i--) {
+            var a = node.attributes[i];
+            //console.log(a);
+            
+            if (a.name.toLowerCase().substr(0,2)=='on')  {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            if (Roo.HtmlEditorCore.ablack.indexOf(a.name.toLowerCase()) > -1) {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            if (Roo.HtmlEditorCore.aclean.indexOf(a.name.toLowerCase()) > -1) {
+                cleanAttr(a.name,a.value); // fixme..
+                continue;
+            }
+            if (a.name == 'style') {
+                cleanStyle(a.name,a.value);
+                continue;
+            }
+            /// 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 = '';
+                }
+                continue;
+            }
+            
+            // style cleanup!?
+            // class cleanup?
+            
+        }
+        
+        
+        this.cleanUpChildren(node);
+        
+        
+    }
+    
+    
+    // hide stuff that is not compatible
+    /**
+     * @event blur
+     * @hide
+     */
+    /**
+     * @event change
+     * @hide
+     */
+    /**
+     * @event focus
+     * @hide
+     */
+    /**
+     * @event specialkey
+     * @hide
+     */
+    /**
+     * @cfg {String} fieldClass @hide
+     */
+    /**
+     * @cfg {String} focusClass @hide
+     */
+    /**
+     * @cfg {String} autoCreate @hide
+     */
+    /**
+     * @cfg {String} inputType @hide
+     */
+    /**
+     * @cfg {String} invalidClass @hide
+     */
+    /**
+     * @cfg {String} invalidText @hide
+     */
+    /**
+     * @cfg {String} msgFx @hide
+     */
+    /**
+     * @cfg {String} validateOnBlur @hide
+     */
+});
+
+Roo.HtmlEditorCore.white = [
+        'area', 'br', 'img', 'input', 'hr', 'wbr',
+        
+       'address', 'blockquote', 'center', 'dd',      'dir',       'div', 
+       'dl',      'dt',         'h1',     'h2',      'h3',        'h4', 
+       'h5',      'h6',         'hr',     'isindex', 'listing',   'marquee', 
+       'menu',    'multicol',   'ol',     'p',       'plaintext', 'pre', 
+       'table',   'ul',         'xmp', 
+       
+       'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
+      'thead',   'tr', 
+     
+      'dir', 'menu', 'ol', 'ul', 'dl',
+       
+      'embed',  'object'
+];
+
+
+Roo.HtmlEditorCore.black = [
+    //    'embed',  'object', // enable - backend responsiblity to clean thiese
+        'applet', // 
+        'base',   'basefont', 'bgsound', 'blink',  'body', 
+        'frame',  'frameset', 'head',    'html',   'ilayer', 
+        'iframe', 'layer',  'link',     'meta',    'object',   
+        'script', 'style' ,'title',  'xml' // clean later..
+];
+Roo.HtmlEditorCore.clean = [
+    'script', 'style', 'title', 'xml'
+];
+Roo.HtmlEditorCore.remove = [
+    'font'
+];
+// attributes..
+
+Roo.HtmlEditorCore.ablack = [
+    'on'
+];
+    
+Roo.HtmlEditorCore.aclean = [ 
+    'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc' 
+];
+
+// protocols..
+Roo.HtmlEditorCore.pwhite= [
+        'http',  'https',  'mailto'
+];
+
+// white listed style attributes.
+Roo.HtmlEditorCore.cwhite= [
+      //  'text-align', /// default is to allow most things..
+      
+         
+//        'font-size'//??
+];
+
+// black listed style attributes.
+Roo.HtmlEditorCore.cblack= [
+      //  'font-size' -- this can be set by the project 
+];
+
+
+Roo.HtmlEditorCore.swapCodes   =[ 
+    [    8211, "--" ], 
+    [    8212, "--" ], 
+    [    8216,  "'" ],  
+    [    8217, "'" ],  
+    [    8220, '"' ],  
+    [    8221, '"' ],  
+    [    8226, "*" ],  
+    [    8230, "..." ]
+]; 
+
+    /*
  * - LGPL
  *
  * HtmlEditor