text: /*!
   * MIT
   */
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.MidasCommand
   * @extends Ext.util.Observable
   * <p>A base plugin for extending to create standard Midas command buttons.</p>
   */
  Ext.ns('Ext.ux.form.HtmlEditor');
  
  Ext.ux.form.HtmlEditor.MidasCommand = Ext.extend(Ext.util.Observable, {
      // private
      init: function(cmp){
          this.cmp = cmp;
          this.btns = [];
          this.cmp.on('render', this.onRender, this);
          this.cmp.on('initialize', this.onInit, this, {
              delay: 100,
              single: true
          });
      },
      // private
      onInit: function(){
          Ext.EventManager.on(this.cmp.getDoc(), {
              'mousedown': this.onEditorEvent,
              'dblclick': this.onEditorEvent,
              'click': this.onEditorEvent,
              'keyup': this.onEditorEvent,
              buffer: 100,
              scope: this
          });
      },
      // private
      onRender: function(){
          var midasCmdButton, tb = this.cmp.getToolbar(), btn;
          Ext.each(this.midasBtns, function(b){
              //if (Ext.isObject(b)) {
  						if (typeof(b)=='object') {
                  midasCmdButton = {
  										tabIndex:-1,
                      iconCls: 'x-edit-' + b.cmd,
                      handler: function(){
                          this.cmp.relayCmd(b.cmd);
                      },
                      scope: this,
                      tooltip: b.tooltip ||
                      {
                          title: b.title
                      },
                      overflowText: b.overflowText || b.title
                  };
              } else {
                  midasCmdButton = new Ext.Toolbar.Separator();
              }
              btn = tb.addButton(midasCmdButton);
              if (b.enableOnSelection) {
                  btn.disable();
              }
              this.btns.push(btn);
          }, this);
      },
      // private
      onEditorEvent: function(){
          var doc = this.cmp.getDoc();
          Ext.each(this.btns, function(b, i){
              if (this.midasBtns[i].enableOnSelection || this.midasBtns[i].disableOnSelection) {
                  if (doc.getSelection) {
                      if ((this.midasBtns[i].enableOnSelection && doc.getSelection() !== '') || (this.midasBtns[i].disableOnSelection && doc.getSelection() === '')) {
                          b.enable();
                      } else {
                          b.disable();
                      }
                  } else if (doc.selection) {
                      if ((this.midasBtns[i].enableOnSelection && doc.selection.createRange().text !== '') || (this.midasBtns[i].disableOnSelection && doc.selection.createRange().text === '')) {
                          b.enable();
                      } else {
                          b.disable();
                      }
                  }
              }
              if (this.midasBtns[i].monitorCmdState) {
                  b.toggle(doc.queryCommandState(this.midasBtns[i].cmd));
              }
          }, this);
      }
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.Divider
   * @extends Ext.util.Observable
   * <p>A plugin that creates a divider on the HtmlEditor. Used for separating additional buttons.</p>
   */
  Ext.ux.form.HtmlEditor.Divider = Ext.extend(Ext.util.Observable, {
      // private
      init: function(cmp){
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
      },
      // private
      onRender: function(){
          this.cmp.getToolbar().addButton([new Ext.Toolbar.Separator()]);
      }
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.IndentOutdent
   * @extends Ext.ux.form.HtmlEditor.MidasCommand
   * <p>A plugin that creates two buttons on the HtmlEditor for indenting and outdenting of selected text.</p>
   */
  Ext.ux.form.HtmlEditor.IndentOutdent = Ext.extend(Ext.ux.form.HtmlEditor.MidasCommand, {
      // private
      midasBtns: ['|', {
          cmd: 'indent',
          tooltip: {
              title: t("Indent Text")
          },
          overflowText: t("Indent Text")
      }, {
          cmd: 'outdent',
          tooltip: {
              title: t("Outdent Text")
          },
          overflowText: t("Outdent Text")
      }]
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.RemoveFormat
   * @extends Ext.ux.form.HtmlEditor.MidasCommand
   * <p>A plugin that creates a button on the HtmlEditor that will remove all formatting on selected text.</p>
   */
  Ext.ux.form.HtmlEditor.RemoveFormat = Ext.extend(Ext.ux.form.HtmlEditor.MidasCommand, {
      midasBtns: ['|', {
          enableOnSelection: true,
          cmd: 'removeFormat',
          tooltip: {
              title: t("Remove Formatting")
          },
          overflowText: t("Remove Formatting")
      }]
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.SubSuperScript
   * @extends Ext.ux.form.HtmlEditor.MidasCommand
   * <p>A plugin that creates two buttons on the HtmlEditor for superscript and subscripting of selected text.</p>
   */
  Ext.ux.form.HtmlEditor.SubSuperScript = Ext.extend(Ext.ux.form.HtmlEditor.MidasCommand, {
      // private
      midasBtns: ['|', {
          enableOnSelection: true,
          cmd: 'subscript',
          tooltip: {
              title: 'Subscript'
          },
          overflowText: 'Subscript'
      }, {
          enableOnSelection: true,
          cmd: 'superscript',
          tooltip: {
              title: 'Superscript'
          },
          overflowText: 'Superscript'
      }]
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.SpecialCharacters
   * @extends Ext.util.Observable
   * <p>A plugin that creates a button on the HtmlEditor for inserting special characters.</p>
   */
  Ext.ux.form.HtmlEditor.SpecialCharacters = Ext.extend(Ext.util.Observable, {
      /**
       * @cfg {Array} specialChars
       * An array of additional characters to display for user selection.  Uses numeric portion of the ASCII HTML Character Code only. For example, to use the Copyright symbol, which is &#169; we would just specify <tt>169</tt> (ie: <tt>specialChars:[169]</tt>).
       */
      specialChars: [],
      /**
       * @cfg {Array} charRange
       * Two numbers specifying a range of ASCII HTML Characters to display for user selection. Defaults to <tt>[160, 256]</tt>.
       */
      charRange: [160, 256],
      // private
      init: function(cmp){
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
      },
      // private
      onRender: function(){
          var cmp = this.cmp;
          var btn = this.cmp.getToolbar().addButton({
              iconCls: 'x-edit-char',
  						tabIndex:-1,
              handler: function(){
                  if (this.specialChars.length) {
                      Ext.each(this.specialChars, function(c, i){
                          this.specialChars[i] = ['&#' + c + ';'];
                      }, this);
                  }
                  for (i = this.charRange[0]; i < this.charRange[1]; i++) {
                      this.specialChars.push(['&#' + i + ';']);
                  }
                  var charStore = new Ext.data.ArrayStore({
                      fields: ['char'],
                      data: this.specialChars
                  });
                  this.charWindow = new Ext.Window({
                      title: 'Insert Special Character',
                      width: 436,
                      autoHeight: true,
                      layout: 'fit',
                      items: [{
                          xtype: 'dataview',
                          store: charStore,
                          ref: '../charView',
                          autoHeight: true,
                          multiSelect: true,
                          tpl: new Ext.XTemplate('<tpl for="."><div class="char-item">{char}</div></tpl><div class="x-clear"></div>'),
                          overClass: 'char-over',
                          itemSelector: 'div.char-item',
                          listeners: {
                              dblclick: function(t, i, n, e){
                                  this.insertChar(t.getStore().getAt(i).get('char'));
                                  this.charWindow.close();
                              },
                              scope: this
                          }
                      }],
                      buttons: [{
                          text: 'Insert',
                          handler: function(){
                              Ext.each(this.charWindow.charView.getSelectedRecords(), function(rec){
                                  var c = rec.get('char');
                                  this.insertChar(c);
                              }, this);
                              this.charWindow.close();
                          },
                          scope: this
                      }, {
                          text: 'Cancel',
                          handler: function(){
                              this.charWindow.close();
                          },
                          scope: this
                      }]
                  });
                  this.charWindow.show();
              },
              scope: this,
              tooltip: {
                  title: 'Insert Special Character'
              },
              overflowText: 'Special Characters'
          });
      },
      /**
       * Insert a single special character into the document.
       * @param c String The special character to insert (not just the numeric code, but the entire ASCII HTML entity).
       */
      insertChar: function(c){
          if (c) {
              this.cmp.insertAtCursor(c);
          }
      }
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.Table
   * @extends Ext.util.Observable
   * <p>A plugin that creates a button on the HtmlEditor for making simple tables.</p>
   */
  Ext.ux.form.HtmlEditor.Table = Ext.extend(Ext.util.Observable, {
      // private
      cmd: 'table',
      /**
       * @cfg {Array} tableBorderOptions
       * A nested array of value/display options to present to the user for table border style. Defaults to a simple list of 5 varrying border types.
       */
      tableBorderOptions: [['none', 'None'], ['1px solid #000', 'Sold Thin'], ['2px solid #000', 'Solid Thick'], ['1px dashed #000', 'Dashed'], ['1px dotted #000', 'Dotted']],
      // private
      init: function(cmp){
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
      },
      // private
      onRender: function(){
          var cmp = this.cmp;
          var btn = this.cmp.getToolbar().addButton({
              iconCls: 'x-edit-table',
  						tabIndex:-1,
              handler: function(){
                  if (!this.tableWindow){
                      this.tableWindow = new Ext.Window({
                          title: 'Insert Table',
                          closeAction: 'hide',
                          items: [{
                              itemId: 'insert-table',
                              xtype: 'form',
                              border: false,
                              plain: true,
                              bodyStyle: 'padding: 10px;',
                              labelWidth: 60,
                              labelAlign: 'right',
                              items: [{
                                  xtype: 'numberfield',
                                  allowBlank: false,
                                  allowDecimals: false,
                                  fieldLabel: 'Rows',
                                  name: 'row',
                                  width: 60
                              }, {
                                  xtype: 'numberfield',
                                  allowBlank: false,
                                  allowDecimals: false,
                                  fieldLabel: 'Columns',
                                  name: 'col',
                                  width: 60
                              }, {
                                  xtype: 'combo',
                                  fieldLabel: 'Border',
                                  name: 'border',
                                  forceSelection: true,
                                  mode: 'local',
                                  store: new Ext.data.ArrayStore({
                                      autoDestroy: true,
                                      fields: ['spec', 'val'],
                                      data: this.tableBorderOptions
                                  }),
                                  triggerAction: 'all',
                                  value: 'none',
                                  displayField: 'val',
                                  valueField: 'spec',
                                  width: 90
                              }]
                          }],
                          buttons: [{
                              text: 'Insert',
                              handler: function(){
                                  var frm = this.tableWindow.getComponent('insert-table').getForm();
                                  if (frm.isValid()) {
                                      var border = frm.findField('border').getValue();
                                      var rowcol = [frm.findField('row').getValue(), frm.findField('col').getValue()];
                                      if (rowcol.length == 2 && rowcol[0] > 0 && rowcol[0] < 10 && rowcol[1] > 0 && rowcol[1] < 10) {
                                          var html = "<table>";
                                          for (var row = 0; row < rowcol[0]; row++) {
                                              html += "<tr>";
                                              for (var col = 0; col < rowcol[1]; col++) {
                                                  html += "<td width='20%' style='border: " + border + ";'>" + row + "-" + col + "</td>";
                                              }
                                              html += "</tr>";
                                          }
                                          html += "</table>";
                                          this.cmp.insertAtCursor(html);
                                      }
                                      this.tableWindow.hide();
                                  }else{
                                      if (!frm.findField('row').isValid()){
                                          frm.findField('row').getEl().frame();
                                      }else if (!frm.findField('col').isValid()){
                                          frm.findField('col').getEl().frame();
                                      }
                                  }
                              },
                              scope: this
                          }, {
                              text: 'Cancel',
                              handler: function(){
                                  this.tableWindow.hide();
                              },
                              scope: this
                          }]
                      });
  
                  }else{
                      this.tableWindow.getEl().frame();
                  }
                  this.tableWindow.show();
              },
              scope: this,
              tooltip: {
                  title: 'Insert Table'
              },
              overflowText: 'Table'
          });
      }
  });
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.Word
   * @extends Ext.util.Observable
   * <p>A plugin that creates a button on the HtmlEditor for pasting text from Word without all the jibberish html.</p>
   */
  Ext.ux.form.HtmlEditor.Word = Ext.extend(Ext.util.Observable, {
  	curLength: 0,
  	lastLength: 0,
  	lastValue: '',
  	wordPasteEnabled: true,
  	// private
      init: function(cmp){
  
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
  		this.cmp.on('initialize', this.onInit, this, {delay:100, single: true});
  
      },
  	// private
  	onInit: function(){
  
  		/*Ext.EventManager.on(this.cmp.getDoc(), {
              'keyup': this.checkIfPaste,
              scope: this
          });*/
  		this.lastValue = this.cmp.getValue();
  		this.curLength = this.lastValue.length;
  		this.lastLength = this.lastValue.length;
  
  	},
  	// private
  	/*checkIfPaste: function(e){
  
  		var diffAt = 0;
  
  		if (e.V == e.getKey() && e.ctrlKey && this.wordPasteEnabled){
  
  			//this.cmp.setValue(this.fixWordPaste(this.cmp.getValue()));
  			//return;
  
  			//console.log('ja');
  
  			this.curLength = this.cmp.getValue().length;
  
  			this.cmp.suspendEvents();
  
  			diffAt = this.findValueDiffAt(this.cmp.getValue());
  			var parts = [
  				this.cmp.getValue().substr(0, diffAt),
  				this.fixWordPaste(this.cmp.getValue().substr(diffAt, (this.curLength - this.lastLength))),
  				this.cmp.getValue().substr((this.curLength - this.lastLength)+diffAt, this.curLength)
  			];
  			this.cmp.setValue(parts.join(''));
  
  			this.cmp.resumeEvents();
  
  			this.lastLength = this.cmp.getValue().length;
  			this.lastValue = this.cmp.getValue();
  		}
  
  
  
  	},*/
  	// private
  	findValueDiffAt: function(val){
  
  		for (i=0;i<this.curLength;i++){
  			if (this.lastValue[i] != val[i]){
  				return i;
  			}
  		}
  
  	},
      /**
       * Cleans up the jubberish html from Word pasted text.
       * @param wordPaste String The text that needs to be cleansed of Word jibberish html.
       * @return {String} The passed in text with all Word jibberish html removed.
       */
      fixWordPaste: function(wordPaste) {
  
  		//console.log('fix paste');
  
  		///<\/?H2[^>]*>/ig, /<\/?H3[^>]*>/g, /<\/?H4[^>]*>/g,/<\/?H5[^>]*>/g, /<\/?H6[^>]*>/g,
  
          var removals = [/&nbsp;/ig, /[\r\n]/g, /<(xml|style)[^>]*>.*?<\/\1>/ig, /<\/?(meta|object|span)[^>]*>/ig,
  			/<\/?[A-Z0-9]*:[A-Z]*[^>]*>/ig, /(lang|class|type|href|name|title|id|clear)=\"[^\"]*\"/ig, /style=(\'\'|\"\")/ig, /<![\[-].*?-*>/g,
  			/MsoNormal/g, /<\\?\?xml[^>]*>/g, /<\/?o:p[^>]*>/g, /<\/?v:[^>]*>/g, /<\/?o:[^>]*>/g, /<\/?st1:[^>]*>/g, /&nbsp;/g,
              /<\/?SPAN[^>]*>/ig, /<\/?FONT[^>]*>/ig, /<\/?STRONG[^>]*>/ig, /<\/?H1[^>]*>/ig,  /<\/?P[^>]*><\/P>/g, /<!--(.*)-->/g, /<!--(.*)>/g, /<!(.*)-->/g, /<\\?\?xml[^>]*>/g,
              /<\/?o:p[^>]*>/g, /<\/?v:[^>]*>/g, /<\/?o:[^>]*>/g, /<\/?st1:[^>]*>/g, /style=\"[^\"]*\"/g, /style=\'[^\"]*\'/g, /lang=\"[^\"]*\"/g,
              /lang=\'[^\"]*\'/g, /class=\"[^\"]*\"/g, /class=\'[^\"]*\'/g, /type=\"[^\"]*\"/g, /type=\'[^\"]*\'/g, /href=\'#[^\"]*\'/g,
              /href=\"#[^\"]*\"/g, /name=\"[^\"]*\"/g, /name=\'[^\"]*\'/g, / clear=\"all\"/g, /id=\"[^\"]*\"/g, /title=\"[^\"]*\"/g,
              /<span[^>]*>/g, /<\/?span[^>]*>/g, /class=/g,/<script[^>]*>.*<\/script>/ig];
  
          Ext.each(removals, function(s){
              wordPaste = wordPaste.replace(s, "");
          });
  
          // keep the divs in paragraphs
          wordPaste = wordPaste.replace(/<div[^>]*>/g, "<p>");
          wordPaste = wordPaste.replace(/<\/?div[^>]*>/g, "</p>");
          return wordPaste;
  
      },
  	// private
      onRender: function() {
  
          this.cmp.getToolbar().add({
              iconCls: 'x-edit-wordpaste',
              /*pressed: true,*/
  						tabIndex:-1,
              handler: function(t){
                  //t.toggle(!t.pressed);
                  //this.wordPasteEnabled = !this.wordPasteEnabled;
  				this.cmp.setValue(this.fixWordPaste(this.cmp.getValue()));
              },
              scope: this,
  			overflowText:'Word paste',
              tooltip: {
                  text: t("Cleans text pasted from Word or other Rich Text applications")
              }
          });
  
      }
  });/**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.HR
   * @extends Ext.util.Observable
   * <p>A plugin that creates a button on the HtmlEditor for inserting a horizontal rule.</p>
   */
  Ext.ux.form.HtmlEditor.HR = Ext.extend(Ext.util.Observable, {
      // private
      cmd: 'hr',
      // private
      init: function(cmp){
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
      },
      // private
      onRender: function(){
          var cmp = this.cmp;
          var btn = this.cmp.getToolbar().addButton({
              iconCls: 'x-edit-hr',
  						tabIndex:-1,
              handler: function(){
                  if (!this.hrWindow){
  
                      this.hrWindow = new Ext.Window({
  												width:400,
  												autoHeight:true,
  												resizable:false,
                          title: t("Insert Horizontal Rule"),
                          closeAction: 'hide',
  												focus: function(){
  													this.items.get(0).form.findField('hrwidth').focus(true);
  												},
                          items: [{
                              itemId: 'insert-hr',
                              xtype: 'form',
                              border: false,
                              bodyStyle: 'padding: 10px;',
                              labelWidth: 60,
                              labelAlign: 'right',
                              items: [{
                                  xtype: 'label',
                                  html: t("Enter the width of the Rule in percentage<br/> followed by the % sign at the end, or to<br/> set a fixed width ommit the % symbol.")+'<br/>&nbsp;'
                              }, {
  
                                  xtype: 'textfield',
                                  maskRe: /[0-9]|%/,
                                  regex: /^[1-9][0-9%]{1,3}/,
                                  fieldLabel: t("Width"),
                                  name: 'hrwidth',
  																value:'100%',
                                  width: 60,
                                   listeners: {
                                      specialkey: function(f, e){
                                          if ((e.getKey() == e.ENTER || e.getKey() == e.RETURN) && f.isValid()) {
                                              this.doInsertHR();
                                          }else{
                                              f.getEl().frame();
                                          }
                                      },
                                      scope: this
                                  }
                              }]
                          }],
                          buttons: [{
                              text: t("Insert"),
                              handler: function(){
                                  var frm = this.hrWindow.getComponent('insert-hr').getForm();
                                  if (frm.isValid()){
                                      this.doInsertHR();
                                  }else{
                                      frm.findField('hrwidth').getEl().frame();
                                  }
      						},
                              scope: this
                          }, {
                              text: t("Cancel"),
                              handler: function(){
                                  this.hrWindow.hide();
                              },
                              scope: this
                          }]
                      });
                  }else{
                      this.hrWindow.getEl().frame();
                  }
                  this.hrWindow.show();
              },
              scope: this,
              tooltip: {
                  title: t("Insert Horizontal Rule")
              },
              overflowText: t("Insert Horizontal Rule")
          });
      },
      // private
      doInsertHR: function(){
          var frm = this.hrWindow.getComponent('insert-hr').getForm();
          if (frm.isValid()) {
              var hrwidth = frm.findField('hrwidth').getValue();
              if (hrwidth) {
                  this.insertHR(hrwidth);
              } else {
                  this.insertHR('100%');
              }
              frm.reset();
              this.hrWindow.hide();
          }
      },
      /**
       * Insert a horizontal rule into the document.
       * @param w String The width of the horizontal rule as the <tt>width</tt> attribute of the HR tag expects. ie: '100%' or '400' (pixels).
       */
      insertHR: function(w){
          this.cmp.insertAtCursor('<hr width="' + w + '">');
      }
  });
  
  
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @contributor Somani - http://www.sencha.com/forum/member.php?51567-Somani
   * @class Ext.ux.form.HtmlEditor.HeadingButtons
   * @extends Ext.ux.form.HtmlEditor.MidasCommand
   * <p>A plugin that creates a button on the HtmlEditor that will have H1 and H2 options. This is used when you want to restrict users to just a few heading types.</p>
   * NOTE: while 'heading' should be the command used, it is not supported in IE, so 'formatblock' is used instead. Thank you IE.
   */
  
  Ext.ux.form.HtmlEditor.HeadingButtons = Ext.extend(Ext.ux.form.HtmlEditor.MidasCommand, {
      // private
      midasBtns: ['|', {
          enableOnSelection: true,
          cmd: 'formatblock',
          value: '<h1>',
          tooltip: {
              title: '1st Heading'
          },
          overflowText: '1st Heading'
      }, {
          enableOnSelection: true,
          cmd: 'formatblock',
          value: '<h2>',
          tooltip: {
              title: '2nd Heading'
          },
          overflowText: '2nd Heading'
      }]
  }); 
  
  /**
   * @author Shea Frederick - http://www.vinylfox.com
   * @class Ext.ux.form.HtmlEditor.HeadingMenu
   * @extends Ext.util.Observable
   * <p>A plugin that creates a menu on the HtmlEditor for selecting a heading size. Takes up less room than the heading buttons if your going to have all six heading sizes available.</p>
   */
  Ext.ux.form.HtmlEditor.HeadingMenu = Ext.extend(Ext.util.Observable, {
      init: function(cmp){
          this.cmp = cmp;
          this.cmp.on('render', this.onRender, this);
      },
      // private
      onRender: function(){
          var cmp = this.cmp;
          var btn = this.cmp.getToolbar().addItem({
              xtype: 'combo',
              displayField: 'display',
              valueField: 'value',
              name: 'headingsize',
              forceSelection: true,
              mode: 'local',
              triggerAction: 'all',
              width: 100,
              emptyText: 'Heading',
              store: {
                  xtype: 'arraystore',
                  autoDestroy: true,
                  fields: ['value','display'],
                  data: [['H1','1st Heading'],['H2','2nd Heading'],['H3','3rd Heading'],['H4','4th Heading'],['H5','5th Heading'],['H6','6th Heading'],['P','Paragraph']]
              },
              listeners: {
                  'select': function(combo,rec){
                      this.relayCmd('formatblock', '<'+rec.get('value')+'>');
                      combo.reset();
                  },
                  scope: cmp
              }
          });
      }
  });
  