* 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);
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()
{
tag: 'button',
type: 'button',
- cls: 'btn btn-primary',
+ cls: 'btn btn-primary period',
html: 'AM'
}
var minutes = this.time.getMinutes();
var period = 'AM';
+ if(hours > 11){
+ period = 'PM';
+ }
+
if(hours == 0){
hours = 12;
}
- if(hours > 11){
- period = 'PM';
- }
if(hours > 12){
hours = hours - 12;
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){
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);
},
- 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');
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'
+ }
+ ]
+ }
+
+ ]
}
- ]
- }
]
}
});
tag: 'table',
cls: 'table-condensed',
cn:[
- Roo.bootstrap.DateField.content
+ Roo.bootstrap.TimeField.content,
+ Roo.bootstrap.TimeField.footer
]
}
]
});
+//<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 == ' '){
+ 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 = ' ';
+ }
+
+ 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('    ');
+ 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','    ');
+ 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