4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-form-field-HtmlEditor'>/**
19 </span> * Provides a lightweight HTML Editor component. Some toolbar features are not supported by Safari and will be
20 * automatically hidden when needed. These are noted in the config options where appropriate.
22 * The editor's toolbar buttons have tooltips defined in the {@link #buttonTips} property, but they are not
23 * enabled by default unless the global {@link Ext.tip.QuickTipManager} singleton is
24 * {@link Ext.tip.QuickTipManager#init initialized}.
26 * An Editor is a sensitive component that can't be used in all spots standard fields can be used. Putting an
27 * Editor within any element that has display set to 'none' can cause problems in Safari and Firefox due to their
28 * default iframe reloading bugs.
32 * Simple example rendered with default options:
35 * Ext.tip.QuickTipManager.init(); // enable tooltips
36 * Ext.create('Ext.form.HtmlEditor', {
39 * renderTo: Ext.getBody()
42 * Passed via xtype into a container and with custom options:
45 * Ext.tip.QuickTipManager.init(); // enable tooltips
46 * new Ext.panel.Panel({
47 * title: 'HTML Editor',
48 * renderTo: Ext.getBody(),
54 * xtype: 'htmleditor',
55 * enableColors: false,
56 * enableAlignments: false
60 Ext.define('Ext.form.field.HtmlEditor', {
61 extend:'Ext.Component',
63 labelable: 'Ext.form.Labelable',
64 field: 'Ext.form.field.Field'
66 alias: 'widget.htmleditor',
67 alternateClassName: 'Ext.form.HtmlEditor',
69 'Ext.tip.QuickTipManager',
72 'Ext.toolbar.Toolbar',
74 'Ext.layout.component.field.HtmlEditor'
78 '<div id="{cmpId}-toolbarWrap" class="{toolbarWrapCls}"></div>',
79 '<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
80 'style="{size}" autocomplete="off"></textarea>',
81 '<iframe id="{cmpId}-iframeEl" name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
88 <span id='Ext-form-field-HtmlEditor-cfg-enableFormat'> /**
89 </span> * @cfg {Boolean} enableFormat
90 * Enable the bold, italic and underline buttons
93 <span id='Ext-form-field-HtmlEditor-cfg-enableFontSize'> /**
94 </span> * @cfg {Boolean} enableFontSize
95 * Enable the increase/decrease font size buttons
97 enableFontSize : true,
98 <span id='Ext-form-field-HtmlEditor-cfg-enableColors'> /**
99 </span> * @cfg {Boolean} enableColors
100 * Enable the fore/highlight color buttons
103 <span id='Ext-form-field-HtmlEditor-cfg-enableAlignments'> /**
104 </span> * @cfg {Boolean} enableAlignments
105 * Enable the left, center, right alignment buttons
107 enableAlignments : true,
108 <span id='Ext-form-field-HtmlEditor-cfg-enableLists'> /**
109 </span> * @cfg {Boolean} enableLists
110 * Enable the bullet and numbered list buttons. Not available in Safari.
113 <span id='Ext-form-field-HtmlEditor-cfg-enableSourceEdit'> /**
114 </span> * @cfg {Boolean} enableSourceEdit
115 * Enable the switch to source edit button. Not available in Safari.
117 enableSourceEdit : true,
118 <span id='Ext-form-field-HtmlEditor-cfg-enableLinks'> /**
119 </span> * @cfg {Boolean} enableLinks
120 * Enable the create link button. Not available in Safari.
123 <span id='Ext-form-field-HtmlEditor-cfg-enableFont'> /**
124 </span> * @cfg {Boolean} enableFont
125 * Enable font selection. Not available in Safari.
128 <span id='Ext-form-field-HtmlEditor-cfg-createLinkText'> /**
129 </span> * @cfg {String} createLinkText
130 * The default text for the create link prompt
132 createLinkText : 'Please enter the URL for the link:',
133 <span id='Ext-form-field-HtmlEditor-cfg-defaultLinkValue'> /**
134 </span> * @cfg {String} [defaultLinkValue='http://']
135 * The default value for the create link prompt
137 defaultLinkValue : 'http:/'+'/',
138 <span id='Ext-form-field-HtmlEditor-cfg-fontFamilies'> /**
139 </span> * @cfg {String[]} fontFamilies
140 * An array of available font families
149 defaultFont: 'tahoma',
150 <span id='Ext-form-field-HtmlEditor-cfg-defaultValue'> /**
151 </span> * @cfg {String} defaultValue
152 * A default value to be put into the editor to resolve focus issues (defaults to (Non-breaking space) in Opera
153 * and IE6, (Zero-width space) in all other browsers).
155 defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
157 fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
159 componentLayout: 'htmleditor',
161 // private properties
164 sourceEditMode : false,
171 initComponent : function(){
175 <span id='Ext-form-field-HtmlEditor-event-initialize'> /**
176 </span> * @event initialize
177 * Fires when the editor is fully initialized (including the iframe)
178 * @param {Ext.form.field.HtmlEditor} this
181 <span id='Ext-form-field-HtmlEditor-event-activate'> /**
182 </span> * @event activate
183 * Fires when the editor is first receives the focus. Any insertion must wait until after this event.
184 * @param {Ext.form.field.HtmlEditor} this
187 <span id='Ext-form-field-HtmlEditor-event-beforesync'> /**
188 </span> * @event beforesync
189 * Fires before the textarea is updated with content from the editor iframe. Return false to cancel the
191 * @param {Ext.form.field.HtmlEditor} this
192 * @param {String} html
195 <span id='Ext-form-field-HtmlEditor-event-beforepush'> /**
196 </span> * @event beforepush
197 * Fires before the iframe editor is updated with content from the textarea. Return false to cancel the
199 * @param {Ext.form.field.HtmlEditor} this
200 * @param {String} html
203 <span id='Ext-form-field-HtmlEditor-event-sync'> /**
204 </span> * @event sync
205 * Fires when the textarea is updated with content from the editor iframe.
206 * @param {Ext.form.field.HtmlEditor} this
207 * @param {String} html
210 <span id='Ext-form-field-HtmlEditor-event-push'> /**
211 </span> * @event push
212 * Fires when the iframe editor is updated with content from the textarea.
213 * @param {Ext.form.field.HtmlEditor} this
214 * @param {String} html
217 <span id='Ext-form-field-HtmlEditor-event-editmodechange'> /**
218 </span> * @event editmodechange
219 * Fires when the editor switches edit modes
220 * @param {Ext.form.field.HtmlEditor} this
221 * @param {Boolean} sourceEdit True if source edit, false if standard editing.
226 me.callParent(arguments);
233 <span id='Ext-form-field-HtmlEditor-method-createToolbar'> /**
234 </span> * Called when the editor creates its toolbar. Override this method if you need to
235 * add custom toolbar buttons.
236 * @param {Ext.form.field.HtmlEditor} editor
239 createToolbar : function(editor){
242 tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
243 baseCSSPrefix = Ext.baseCSSPrefix,
244 fontSelectItem, toolbar, undef;
246 function btn(id, toggle, handler){
249 cls : baseCSSPrefix + 'btn-icon',
250 iconCls: baseCSSPrefix + 'edit-'+id,
251 enableToggle:toggle !== false,
253 handler:handler||editor.relayBtnCmd,
254 clickEvent:'mousedown',
255 tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
256 overflowText: editor.buttonTips[id].title || undef,
262 if (me.enableFont && !Ext.isSafari2) {
263 fontSelectItem = Ext.widget('component', {
265 '<select id="{id}-selectEl" class="{cls}">',
266 '<tpl for="fonts">',
267 '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
272 cls: baseCSSPrefix + 'font-select',
273 fonts: me.fontFamilies,
274 defaultFont: me.defaultFont
276 childEls: ['selectEl'],
277 onDisable: function() {
278 var selectEl = this.selectEl;
280 selectEl.dom.disabled = true;
282 Ext.Component.superclass.onDisable.apply(this, arguments);
284 onEnable: function() {
285 var selectEl = this.selectEl;
287 selectEl.dom.disabled = false;
289 Ext.Component.superclass.onEnable.apply(this, arguments);
299 if (me.enableFormat) {
307 if (me.enableFontSize) {
310 btn('increasefontsize', false, me.adjustFont),
311 btn('decreasefontsize', false, me.adjustFont)
315 if (me.enableColors) {
319 cls: baseCSSPrefix + 'btn-icon',
320 iconCls: baseCSSPrefix + 'edit-forecolor',
321 overflowText: editor.buttonTips.forecolor.title,
322 tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
324 menu : Ext.widget('menu', {
327 xtype: 'colorpicker',
332 clickEvent: 'mousedown',
333 handler: function(cp, color) {
334 me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
336 this.up('menu').hide();
342 cls: baseCSSPrefix + 'btn-icon',
343 iconCls: baseCSSPrefix + 'edit-backcolor',
344 overflowText: editor.buttonTips.backcolor.title,
345 tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
347 menu : Ext.widget('menu', {
350 xtype: 'colorpicker',
355 clickEvent: 'mousedown',
356 handler: function(cp, color) {
358 me.execCmd('useCSS', false);
359 me.execCmd('hilitecolor', color);
360 me.execCmd('useCSS', true);
363 me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
366 this.up('menu').hide();
374 if (me.enableAlignments) {
378 btn('justifycenter'),
383 if (!Ext.isSafari2) {
384 if (me.enableLinks) {
387 btn('createlink', false, me.createLink)
391 if (me.enableLists) {
394 btn('insertorderedlist'),
395 btn('insertunorderedlist')
398 if (me.enableSourceEdit) {
401 btn('sourceedit', true, function(btn){
402 me.toggleSourceEdit(!me.sourceEditMode);
409 toolbar = Ext.widget('toolbar', {
410 renderTo: me.toolbarWrap,
411 enableOverflow: true,
415 if (fontSelectItem) {
416 me.fontSelect = fontSelectItem.selectEl;
418 me.mon(me.fontSelect, 'change', function(){
419 me.relayCmd('fontname', me.fontSelect.dom.value);
425 me.mon(toolbar.el, 'click', function(e){
429 me.toolbar = toolbar;
432 onDisable: function() {
434 this.callParent(arguments);
437 onEnable: function() {
438 this.bodyEl.unmask();
439 this.callParent(arguments);
442 <span id='Ext-form-field-HtmlEditor-method-setReadOnly'> /**
443 </span> * Sets the read only state of this field.
444 * @param {Boolean} readOnly Whether the field should be read only.
446 setReadOnly: function(readOnly) {
448 textareaEl = me.textareaEl,
449 iframeEl = me.iframeEl,
452 me.readOnly = readOnly;
455 textareaEl.dom.readOnly = readOnly;
458 if (me.initialized) {
459 body = me.getEditorBody();
461 // Hide the iframe while setting contentEditable so it doesn't grab focus
462 iframeEl.setDisplayed(false);
463 body.contentEditable = !readOnly;
464 iframeEl.setDisplayed(true);
466 me.setDesignMode(!readOnly);
469 body.style.cursor = readOnly ? 'default' : 'text';
471 me.disableItems(readOnly);
475 <span id='Ext-form-field-HtmlEditor-method-getDocMarkup'> /**
476 </span> * Called when the editor initializes the iframe with HTML contents. Override this method if you
477 * want to change the initialization markup of the iframe (e.g. to add stylesheets).
479 * **Note:** IE8-Standards has unwanted scroller behavior, so the default meta tag forces IE7 compatibility.
480 * Also note that forcing IE7 mode works when the page is loaded normally, but if you are using IE's Web
481 * Developer Tools to manually set the document mode, that will take precedence and override what this
482 * code sets by default. This can be confusing when developing, but is not a user-facing issue.
485 getDocMarkup: function() {
487 h = me.iframeEl.getHeight() - me.iframePad * 2;
488 return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;cursor:text}</style></head><body></body></html>', me.iframePad, h);
492 getEditorBody: function() {
493 var doc = this.getDoc();
494 return doc.body || doc.documentElement;
499 return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
504 return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
508 onRender: function() {
511 me.onLabelableRender();
513 me.addChildEls('toolbarWrap', 'iframeEl', 'textareaEl');
515 me.callParent(arguments);
517 me.textareaEl.dom.value = me.value || '';
519 // Start polling for when the iframe document is ready to be manipulated
520 me.monitorTask = Ext.TaskManager.start({
521 run: me.checkDesignMode,
526 me.createToolbar(me);
527 me.disableItems(true);
530 initRenderTpl: function() {
532 if (!me.hasOwnProperty('renderTpl')) {
533 me.renderTpl = me.getTpl('labelableRenderTpl');
535 return me.callParent();
538 initRenderData: function() {
539 return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
542 getSubTplData: function() {
543 var cssPrefix = Ext.baseCSSPrefix;
546 id: this.getInputId(),
547 toolbarWrapCls: cssPrefix + 'html-editor-tb',
548 textareaCls: cssPrefix + 'hidden',
549 iframeName: Ext.id(),
550 iframeSrc: Ext.SSL_SECURE_URL,
551 size: 'height:100px;'
555 getSubTplMarkup: function() {
556 var data = this.getSubTplData();
557 return this.getTpl('fieldSubTpl').apply(data);
560 getBodyNaturalWidth: function() {
564 initFrameDoc: function() {
568 Ext.TaskManager.stop(me.monitorTask);
571 me.win = me.getWin();
574 doc.write(me.getDocMarkup());
577 task = { // must defer to wait for browser to be ready
579 var doc = me.getDoc();
580 if (doc.body || doc.readyState === 'complete') {
581 Ext.TaskManager.stop(task);
582 me.setDesignMode(true);
583 Ext.defer(me.initEditor, 10, me);
590 Ext.TaskManager.start(task);
593 checkDesignMode: function() {
596 if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
601 <span id='Ext-form-field-HtmlEditor-method-setDesignMode'> /**
603 * Sets current design mode. To enable, mode can be true or 'on', off otherwise
605 setDesignMode: function(mode) {
612 doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
617 getDesignMode: function() {
618 var doc = this.getDoc();
619 return !doc ? '' : String(doc.designMode).toLowerCase();
622 disableItems: function(disabled) {
623 this.getToolbar().items.each(function(item){
624 if(item.getItemId() !== 'sourceedit'){
625 item.setDisabled(disabled);
630 <span id='Ext-form-field-HtmlEditor-method-toggleSourceEdit'> /**
631 </span> * Toggles the editor between standard and source edit mode.
632 * @param {Boolean} sourceEditMode (optional) True for source edit, false for standard
634 toggleSourceEdit: function(sourceEditMode) {
636 iframe = me.iframeEl,
637 textarea = me.textareaEl,
638 hiddenCls = Ext.baseCSSPrefix + 'hidden',
639 btn = me.getToolbar().getComponent('sourceedit');
641 if (!Ext.isBoolean(sourceEditMode)) {
642 sourceEditMode = !me.sourceEditMode;
644 me.sourceEditMode = sourceEditMode;
646 if (btn.pressed !== sourceEditMode) {
647 btn.toggle(sourceEditMode);
649 if (sourceEditMode) {
650 me.disableItems(true);
652 iframe.addCls(hiddenCls);
653 textarea.removeCls(hiddenCls);
654 textarea.dom.removeAttribute('tabIndex');
658 if (me.initialized) {
659 me.disableItems(me.readOnly);
662 iframe.removeCls(hiddenCls);
663 textarea.addCls(hiddenCls);
664 textarea.dom.setAttribute('tabIndex', -1);
667 me.fireEvent('editmodechange', me, sourceEditMode);
668 me.doComponentLayout();
671 // private used internally
672 createLink : function() {
673 var url = prompt(this.createLinkText, this.defaultLinkValue);
674 if (url && url !== 'http:/'+'/') {
675 this.relayCmd('createlink', url);
679 clearInvalid: Ext.emptyFn,
681 // docs inherit from Field
682 setValue: function(value) {
684 textarea = me.textareaEl;
685 me.mixins.field.setValue.call(me, value);
686 if (value === null || value === undefined) {
690 textarea.dom.value = value;
696 <span id='Ext-form-field-HtmlEditor-method-cleanHtml'> /**
697 </span> * If you need/want custom HTML cleanup, this is the method you should override.
698 * @param {String} html The HTML to be cleaned
699 * @return {String} The cleaned HTML
702 cleanHtml: function(html) {
704 if (Ext.isWebKit) { // strip safari nonsense
705 html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
709 * Neat little hack. Strips out all the non-digit characters from the default
710 * value and compares it to the character code of the first character in the string
711 * because it can cause encoding issues when posted to the server.
713 if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
714 html = html.substring(1);
719 <span id='Ext-form-field-HtmlEditor-method-syncValue'> /**
720 </span> * Syncs the contents of the editor iframe with the textarea.
723 syncValue : function(){
725 body, html, bodyStyle, match;
726 if (me.initialized) {
727 body = me.getEditorBody();
728 html = body.innerHTML;
730 bodyStyle = body.getAttribute('style'); // Safari puts text-align styles on the body element!
731 match = bodyStyle.match(/text-align:(.*?);/i);
732 if (match && match[1]) {
733 html = '<div style="' + match[0] + '">' + html + '</div>';
736 html = me.cleanHtml(html);
737 if (me.fireEvent('beforesync', me, html) !== false) {
738 me.textareaEl.dom.value = html;
739 me.fireEvent('sync', me, html);
744 //docs inherit from Field
745 getValue : function() {
748 if (!me.sourceEditMode) {
751 value = me.rendered ? me.textareaEl.dom.value : me.value;
756 <span id='Ext-form-field-HtmlEditor-method-pushValue'> /**
757 </span> * Pushes the value of the textarea into the iframe editor.
760 pushValue: function() {
764 v = me.textareaEl.dom.value || '';
765 if (!me.activated && v.length < 1) {
768 if (me.fireEvent('beforepush', me, v) !== false) {
769 me.getEditorBody().innerHTML = v;
771 // Gecko hack, see: https://bugzilla.mozilla.org/show_bug.cgi?id=232791#c8
772 me.setDesignMode(false); //toggle off first
773 me.setDesignMode(true);
775 me.fireEvent('push', me, v);
781 deferFocus : function(){
782 this.focus(false, true);
785 getFocusEl: function() {
788 return win && !me.sourceEditMode ? win : me.textareaEl;
792 initEditor : function(){
793 //Destroying the component during/before initEditor can cause issues.
796 dbody = me.getEditorBody(),
797 ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
801 ss['background-attachment'] = 'fixed'; // w3c
802 dbody.bgProperties = 'fixed'; // ie
804 Ext.DomHelper.applyStyles(dbody, ss);
810 Ext.EventManager.removeAll(doc);
815 * We need to use createDelegate here, because when using buffer, the delayed task is added
816 * as a property to the function. When the listener is removed, the task is deleted from the function.
817 * Since onEditorEvent is shared on the prototype, if we have multiple html editors, the first time one of the editors
818 * is destroyed, it causes the fn to be deleted from the prototype, which causes errors. Essentially, we're just anonymizing the function.
820 fn = Ext.Function.bind(me.onEditorEvent, me);
821 Ext.EventManager.on(doc, {
829 // These events need to be relayed from the inner document (where they stop
830 // bubbling) up to the outer document. This has to be done at the DOM level so
831 // the event reaches listeners on elements like the document body. The effected
832 // mechanisms that depend on this bubbling behavior are listed to the right
834 fn = me.onRelayedEvent;
835 Ext.EventManager.on(doc, {
836 mousedown: fn, // menu dismisal (MenuManager) and Window onMouseDown (toFront)
837 mousemove: fn, // window resize drag detection
838 mouseup: fn, // window resize termination
839 click: fn, // not sure, but just to be safe
840 dblclick: fn, // not sure again
845 Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
848 Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
851 // We need to be sure we remove all our events from the iframe on unload or we're going to LEAK!
852 Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
853 doc.editorInitialized = true;
855 me.initialized = true;
857 me.setReadOnly(me.readOnly);
858 me.fireEvent('initialize', me);
865 beforeDestroy : function(){
867 monitorTask = me.monitorTask,
871 Ext.TaskManager.stop(monitorTask);
877 Ext.EventManager.removeAll(doc);
879 if (doc.hasOwnProperty(prop)) {
887 Ext.destroyMembers(me, 'tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
893 onRelayedEvent: function (event) {
894 // relay event from the iframe's document to the document that owns the iframe...
896 var iframeEl = this.iframeEl,
897 iframeXY = iframeEl.getXY(),
898 eventXY = event.getXY();
900 // the event from the inner document has XY relative to that document's origin,
901 // so adjust it to use the origin of the iframe in the outer document:
902 event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
904 event.injectEvent(iframeEl); // blame the iframe for the event...
906 event.xy = eventXY; // restore the original XY (just for safety)
910 onFirstFocus : function(){
914 me.disableItems(me.readOnly);
915 if (Ext.isGecko) { // prevent silly gecko errors
917 selection = me.win.getSelection();
918 if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
919 range = selection.getRangeAt(0);
920 range.selectNodeContents(me.getEditorBody());
921 range.collapse(true);
925 me.execCmd('useCSS', true);
926 me.execCmd('styleWithCSS', false);
931 me.fireEvent('activate', me);
935 adjustFont: function(btn) {
936 var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
937 size = this.getDoc().queryCommandValue('FontSize') || '2',
938 isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
940 size = parseInt(size, 10);
943 // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px
947 else if (size <= 13) {
950 else if (size <= 16) {
953 else if (size <= 18) {
956 else if (size <= 24) {
962 size = Ext.Number.constrain(size, 1, 6);
964 isSafari = Ext.isSafari;
965 if (isSafari) { // safari
968 size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
970 this.execCmd('FontSize', size);
974 onEditorEvent: function(e) {
975 this.updateToolbar();
978 <span id='Ext-form-field-HtmlEditor-method-updateToolbar'> /**
979 </span> * Triggers a toolbar update by reading the markup state of the current selection in the editor.
982 updateToolbar: function() {
984 btns, doc, name, fontSelect;
995 btns = me.getToolbar().items.map;
998 if (me.enableFont && !Ext.isSafari2) {
999 name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
1000 fontSelect = me.fontSelect.dom;
1001 if (name !== fontSelect.value) {
1002 fontSelect.value = name;
1006 function updateButtons() {
1007 Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
1008 btns[name].toggle(doc.queryCommandState(name));
1011 if(me.enableFormat){
1012 updateButtons('bold', 'italic', 'underline');
1014 if(me.enableAlignments){
1015 updateButtons('justifyleft', 'justifycenter', 'justifyright');
1017 if(!Ext.isSafari2 && me.enableLists){
1018 updateButtons('insertorderedlist', 'insertunorderedlist');
1021 Ext.menu.Manager.hideAll();
1027 relayBtnCmd: function(btn) {
1028 this.relayCmd(btn.getItemId());
1031 <span id='Ext-form-field-HtmlEditor-method-relayCmd'> /**
1032 </span> * Executes a Midas editor command on the editor document and performs necessary focus and toolbar updates.
1033 * **This should only be called after the editor is initialized.**
1034 * @param {String} cmd The Midas command
1035 * @param {String/Boolean} [value=null] The value to pass to the command
1037 relayCmd: function(cmd, value) {
1038 Ext.defer(function() {
1041 me.execCmd(cmd, value);
1046 <span id='Ext-form-field-HtmlEditor-method-execCmd'> /**
1047 </span> * Executes a Midas editor command directly on the editor document. For visual commands, you should use
1048 * {@link #relayCmd} instead. **This should only be called after the editor is initialized.**
1049 * @param {String} cmd The Midas command
1050 * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
1052 execCmd : function(cmd, value){
1056 doc.execCommand(cmd, false, value === undef ? null : value);
1061 applyCommand : function(e){
1064 c = e.getCharCode(), cmd;
1066 c = String.fromCharCode(c);
1088 <span id='Ext-form-field-HtmlEditor-method-insertAtCursor'> /**
1089 </span> * Inserts the passed text at the current cursor position.
1090 * Note: the editor must be initialized and activated to insert text.
1091 * @param {String} text
1093 insertAtCursor : function(text){
1100 range = me.getDoc().selection.createRange();
1102 range.pasteHTML(text);
1107 me.execCmd('InsertHTML', text);
1114 fixKeys: function() { // load time branching for fastest keydown performance
1123 range = doc.selection.createRange();
1125 range.collapse(true);
1126 range.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
1130 else if (k === e.ENTER) {
1131 range = doc.selection.createRange();
1133 target = range.parentElement();
1134 if(!target || target.tagName.toLowerCase() !== 'li'){
1136 range.pasteHTML('<br />');
1137 range.collapse(false);
1148 if (e.getKey() === e.TAB) {
1151 me.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
1163 me.execCmd('InsertText','\t');
1166 else if (k === e.ENTER) {
1168 me.execCmd('InsertHtml','<br /><br />');
1174 return null; // not needed, so null
1177 <span id='Ext-form-field-HtmlEditor-method-getToolbar'> /**
1178 </span> * Returns the editor's toolbar. **This is only available after the editor has been rendered.**
1179 * @return {Ext.toolbar.Toolbar}
1181 getToolbar : function(){
1182 return this.toolbar;
1185 <span id='Ext-form-field-HtmlEditor-property-buttonTips'> /**
1186 </span> * @property {Object} buttonTips
1187 * Object collection of toolbar tooltips for the buttons in the editor. The key is the command id associated with
1188 * that button and the value is a valid QuickTips object. For example:
1192 * title: 'Bold (Ctrl+B)',
1193 * text: 'Make the selected text bold.',
1194 * cls: 'x-html-editor-tip'
1197 * title: 'Italic (Ctrl+I)',
1198 * text: 'Make the selected text italic.',
1199 * cls: 'x-html-editor-tip'
1205 title: 'Bold (Ctrl+B)',
1206 text: 'Make the selected text bold.',
1207 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1210 title: 'Italic (Ctrl+I)',
1211 text: 'Make the selected text italic.',
1212 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1215 title: 'Underline (Ctrl+U)',
1216 text: 'Underline the selected text.',
1217 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1219 increasefontsize : {
1221 text: 'Increase the font size.',
1222 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1224 decreasefontsize : {
1225 title: 'Shrink Text',
1226 text: 'Decrease the font size.',
1227 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1230 title: 'Text Highlight Color',
1231 text: 'Change the background color of the selected text.',
1232 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1235 title: 'Font Color',
1236 text: 'Change the color of the selected text.',
1237 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1240 title: 'Align Text Left',
1241 text: 'Align text to the left.',
1242 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1245 title: 'Center Text',
1246 text: 'Center text in the editor.',
1247 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1250 title: 'Align Text Right',
1251 text: 'Align text to the right.',
1252 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1254 insertunorderedlist : {
1255 title: 'Bullet List',
1256 text: 'Start a bulleted list.',
1257 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1259 insertorderedlist : {
1260 title: 'Numbered List',
1261 text: 'Start a numbered list.',
1262 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1266 text: 'Make the selected text a hyperlink.',
1267 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1270 title: 'Source Edit',
1271 text: 'Switch to source editing mode.',
1272 cls: Ext.baseCSSPrefix + 'html-editor-tip'
1276 // hide stuff that is not compatible
1277 <span id='Ext-form-field-HtmlEditor-event-blur'> /**
1278 </span> * @event blur
1281 <span id='Ext-form-field-HtmlEditor-event-change'> /**
1282 </span> * @event change
1285 <span id='Ext-form-field-HtmlEditor-event-focus'> /**
1286 </span> * @event focus
1289 <span id='Ext-form-field-HtmlEditor-event-specialkey'> /**
1290 </span> * @event specialkey
1293 <span id='Ext-form-field-HtmlEditor-cfg-fieldCls'> /**
1294 </span> * @cfg {String} fieldCls @hide
1296 <span id='Ext-form-field-HtmlEditor-cfg-focusCls'> /**
1297 </span> * @cfg {String} focusCls @hide
1299 <span id='Ext-form-field-HtmlEditor-cfg-autoCreate'> /**
1300 </span> * @cfg {String} autoCreate @hide
1302 <span id='Ext-form-field-HtmlEditor-cfg-inputType'> /**
1303 </span> * @cfg {String} inputType @hide
1305 <span id='Ext-form-field-HtmlEditor-cfg-invalidCls'> /**
1306 </span> * @cfg {String} invalidCls @hide
1308 <span id='Ext-form-field-HtmlEditor-cfg-invalidText'> /**
1309 </span> * @cfg {String} invalidText @hide
1311 <span id='Ext-form-field-HtmlEditor-cfg-msgFx'> /**
1312 </span> * @cfg {String} msgFx @hide
1314 <span id='Ext-form-field-HtmlEditor-cfg-allowDomMove'> /**
1315 </span> * @cfg {Boolean} allowDomMove @hide
1317 <span id='Ext-form-field-HtmlEditor-cfg-applyTo'> /**
1318 </span> * @cfg {String} applyTo @hide
1320 <span id='Ext-form-field-HtmlEditor-cfg-readOnly'> /**
1321 </span> * @cfg {String} readOnly @hide
1323 <span id='Ext-form-field-HtmlEditor-cfg-tabIndex'> /**
1324 </span> * @cfg {String} tabIndex @hide
1326 <span id='Ext-form-field-HtmlEditor-method-validate'> /**
1327 </span> * @method validate