PDA

View Full Version : [FIXED-92][3.0.0/2.x] HtmlEditor readOnly and disabled not working



Nam
17 Feb 2008, 8:27 PM
I originally posted a thread into the Help forum, but it has been suggested that I post it here...

If I add the config options (which are listed in the docs) "readOnly: true" and "disabled: true" nothing actually happens. The content is still editable, and it's not disabled. Example code is posted in the following link to the other thread...

http://extjs.com/forum/showthread.php?p=125101

Condor
17 Feb 2008, 11:04 PM
You could use the following workaround for enable/disable:


Ext.override(Ext.form.HtmlEditor, {
onDisable: function(){
if(this.rendered){
this.wrap.mask();
}
Ext.form.HtmlEditor.superclass.onDisable.call(this);
},
onEnable: function(){
if(this.rendered){
this.wrap.unmask();
}
Ext.form.HtmlEditor.superclass.onEnable.call(this);
}
});

Nam
17 Feb 2008, 11:16 PM
awesome, what about the readOnly part though? I want someone to be able to view the contents and scroll, just not edit the content.

Thanks

Nam
21 Feb 2008, 1:10 PM
anyone know a workaround to make the htmleditor field readonly?

ortizSWF
22 Feb 2008, 5:34 PM
I did something like this, but i dont know if this could help you as well.


Ext.override(Ext.form.HtmlEditor, {
/**
* Set a readonly mask over the editor
* @param {Boolean} readOnly - True to set the read only property, False to switch to the editor
*/
setReadOnly: function(readOnly){
if(readOnly){
this.syncValue();
var roMask = this.wrap.mask();
roMask.dom.style.filter = "alpha(opacity=100);"; //IE
roMask.dom.style.opacity = "1"; //Mozilla
roMask.dom.style.background = "white";
roMask.dom.style.overflow = "scroll";
roMask.dom.innerHTML = this.getValue();
this.el.dom.readOnly = true;
} else {
if(this.rendered){
this.wrap.unmask();
}
this.el.dom.readOnly = false;
}
}
});

Also you need to add this in onRender method:


this.setReadOnly(this.readOnly);

Complete:


// private
onRender : function(ct, position){
Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
this.el.dom.style.border = '0 none';
this.el.dom.setAttribute('tabIndex', -1);
this.el.addClass('x-hidden');
if(Ext.isIE){ // fix IE 1px bogus margin
this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
}
this.wrap = this.el.wrap({
cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
});

this.createToolbar(this);

this.tb.items.each(function(item){
if(item.itemId != 'sourceedit'){
item.disable();
}
});

var iframe = document.createElement('iframe');
iframe.name = Ext.id();
iframe.frameBorder = 'no';

iframe.src=(Ext.SSL_SECURE_URL || "javascript:false");

this.wrap.dom.appendChild(iframe);

this.iframe = iframe;

if(Ext.isIE){
iframe.contentWindow.document.designMode = 'on';
this.doc = iframe.contentWindow.document;
this.win = iframe.contentWindow;
} else {
this.doc = (iframe.contentDocument || window.frames[iframe.name].document);
this.win = window.frames[iframe.name];
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(){
if(this.doc.body || this.doc.readyState == 'complete'){
Ext.TaskMgr.stop(task);
this.doc.designMode="on";
this.initEditor.defer(10, this);
}
},
interval : 10,
duration:10000,
scope: this
};
Ext.TaskMgr.start(task);

if(!this.width){
this.setSize(this.el.getSize());
}

this.setReadOnly(this.readOnly);

}

all Code:


Ext.override(Ext.form.HtmlEditor, {
/**
* Set a readonly mask over the editor
* @param {Boolean} readOnly - True to set the read only property, False to switch to the editor
*/
setReadOnly: function(readOnly){
if(readOnly){
this.syncValue();
var roMask = this.wrap.mask();
roMask.dom.style.filter = "alpha(opacity=100);"; //IE
roMask.dom.style.opacity = "1"; //Mozilla
roMask.dom.style.background = "white";
roMask.dom.style.overflow = "scroll";
roMask.dom.innerHTML = this.getValue();
this.el.dom.readOnly = true;
} else {
if(this.rendered){
this.wrap.unmask();
}
this.el.dom.readOnly = false;
}
},
// private
onRender : function(ct, position){
Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
this.el.dom.style.border = '0 none';
this.el.dom.setAttribute('tabIndex', -1);
this.el.addClass('x-hidden');
if(Ext.isIE){ // fix IE 1px bogus margin
this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
}
this.wrap = this.el.wrap({
cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
});

this.createToolbar(this);

this.tb.items.each(function(item){
if(item.itemId != 'sourceedit'){
item.disable();
}
});

var iframe = document.createElement('iframe');
iframe.name = Ext.id();
iframe.frameBorder = 'no';

iframe.src=(Ext.SSL_SECURE_URL || "javascript:false");

this.wrap.dom.appendChild(iframe);

this.iframe = iframe;

if(Ext.isIE){
iframe.contentWindow.document.designMode = 'on';
this.doc = iframe.contentWindow.document;
this.win = iframe.contentWindow;
} else {
this.doc = (iframe.contentDocument || window.frames[iframe.name].document);
this.win = window.frames[iframe.name];
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(){
if(this.doc.body || this.doc.readyState == 'complete'){
Ext.TaskMgr.stop(task);
this.doc.designMode="on";
this.initEditor.defer(10, this);
}
},
interval : 10,
duration:10000,
scope: this
};
Ext.TaskMgr.start(task);

if(!this.width){
this.setSize(this.el.getSize());
}

this.setReadOnly(this.readOnly);

}
});

Example:
JS:

Ext.onReady(function(){

Ext.QuickTips.init();

var html = '<h4>An Ordered List:</h4><ol><li>Coffee</li><li>Tea</li><li>Milk</li></ol><br><br>' +
'<h4>With a normal border:</h4><table border="1"><tr><td>First</td><td>Row</td></tr><tr><td>Second</td><td>Row</td></tr></table><h4>With a thick border:</h4><table border="8"><tr><td>First</td><td>Row</td></tr><tr><td>Second</td><td>Row</td></tr></table><h4>With a very thick border:</h4><table border="15"><tr><td>First</td><td>Row</td></tr><tr><td>Second</td><td>Row</td></tr></table>' +
'<br><br><p>An image from W3Schools:<img src="http://www.w3schools.com/images/ie.gif"></p>';

Editor = new Ext.form.HtmlEditor({
id:'edi',
fieldLabel:'Biography',
width: 500,
readOnly: true,
height: 250,
anchor:'98%',
value: html
});

var top = new Ext.FormPanel({
labelAlign: 'top',
frame:true,
title: 'Multi Column, Nested Layouts and Anchoring',
bodyStyle:'padding:5px 5px 0',
width: 600,
items: [Editor],
buttons: [{
text: 'Enable',
handler: function(){
Editor.setReadOnly(false);
}
},{
text: 'Disable',
handler: function(){
Editor.setReadOnly(true);
}
}]
});


top.render(document.body);

});

PD: You could have problems with the CSS... This could help me at its moment

Greetings... ~o)

queej
3 Dec 2008, 1:55 PM
This works great. Thank you for the complete example!

queej
11 Jan 2009, 8:53 AM
As mentioned above, it does have a problem with falling back to the CSS of the page, which is ext-all.css. Therefore, it loses all bullets, etc. Is there anyway to tweak the above solution and still preserve the isolation of styles from the ext-all.css?

queej
11 Jan 2009, 9:39 AM
Tweaked the above example so that it would not use the innerHTML, which inherits the ext-all.js styles, and changed the opacity of the mask to allow the actual editor text to be seen. Then I hide the toolbar. This provides a reasonable non-edit mode.



roMask.dom.style.filter = "alpha(opacity=0);"; //IE
roMask.dom.style.opacity = "0"; //Mozilla
roMask.dom.style.background = "white";
roMask.dom.style.overflow = "scroll";
//roMask.dom.innerHTML = this.getValue(); // removed


Hope this is useful to someone else who wants to disable the htmleditor.

NepalPro
24 Mar 2009, 1:26 AM
Very useful ...

squarefan
23 Apr 2009, 11:58 PM
UPDATE:
nevermind, you just have to remove



if(!this.width){
this.setSize(this.el.getSize());
}


works great, but when I define the height - it's not taking that parameter anymore.

do you maybe have a fix for that?

cheers,
squarefan

leon.i
24 Jun 2009, 6:40 AM
anyone know a workaround to make the htmleditor field readonly?


I've been using this ReadOnly workaround, yet still haven't found a way to allow the area to be scrolled.

Any updates on this?

krzak
23 Jul 2009, 3:05 AM
It's still in 3.0.
setting disable: true, still alow to edit content

leon.i
23 Jul 2009, 4:04 AM
Yeh, HtmlEditor has caused the most pain out of ExtJS for me.

Anyway, I managed to get around the issue by resizing the mask that is created. If there is scroll bars I simply pull it in by the scrollbar wide (hhaaackkk!) but wasn't aware of another solution.

mystix
23 Jul 2009, 5:03 AM
[ moved to 3.x Bugs from 2.x Bugs ]

mjlecomte
23 Jul 2009, 5:28 AM
Yeh, HtmlEditor has caused the most pain out of ExtJS for me.
Actually I recall Jack saying in the css screencast that it was one of the most difficult to do also.

Condor
23 Jul 2009, 6:05 AM
The correct way to implement read-only mode would be to set designMode to "off".

Juvs
13 Aug 2009, 5:15 PM
@ortizSWF

When you use setValue() needs to handle too..


// docs inherit from Field
setValue : function(v){
Ext.form.HtmlEditor.superclass.setValue.call(this, v);
this.pushValue();
//This for set read only
this.setReadOnly(this.readOnly);
},

evant
18 Aug 2009, 8:51 AM
A fix for this has been added to the trunk.

Juvs
31 Aug 2009, 10:24 AM
For which version?


A fix for this has been added to the trunk.

Condor
31 Aug 2009, 11:11 AM
The Ext SVN trunk is the source for the next Ext minor release (Ext 3.1).

wemerson.januario
16 Jan 2010, 6:16 AM
I can't make it work. it doesn't happen nothing diferent for me.

phernaca
19 Apr 2010, 6:56 AM
Hi,

I've tried your code Queej, well actually the one from ortizSWF but with your updates.
Unfortunately it does not work and obtain the same behaviour as if it was set to disabled.
I'm using version 2.2.1. Please could you tell me which versions of ExtJS did you use?

Thanks in advance.



Tweaked the above example so that it would not use the innerHTML, which inherits the ext-all.js styles, and changed the opacity of the mask to allow the actual editor text to be seen. Then I hide the toolbar. This provides a reasonable non-edit mode.



roMask.dom.style.filter = "alpha(opacity=0);"; //IE
roMask.dom.style.opacity = "0"; //Mozilla
roMask.dom.style.background = "white";
roMask.dom.style.overflow = "scroll";
//roMask.dom.innerHTML = this.getValue(); // removed
Hope this is useful to someone else who wants to disable the htmleditor.

queej
19 Apr 2010, 7:10 AM
Hey phernaca,

I used it with 2.1.1. It's been more than a year since I wrote that, but it has been in use in production for a year, so I think it is working okay. Below is the complete code, which includes a resizer. I hope it is helpful.

Cheers,
-queej



* @class Ext.ux.esaHtmlEditor
* @extends Ext.Component
* @constructor
* Create a new HtmlEditor
* @param {Object} config The config object
*/
Ext.namespace('Ext.ux');
Ext.ux.esaHtmlEditor = function(config){
Ext.ux.esaHtmlEditor.superclass.constructor.call(this, config);
if (config.width && typeof config.width != 'number')
this.pWidth = config.width;

var Me=this;
this.on('initialize', function(){
new Ext.Resizable(Me.getResizeEl(), {
handles: 's',
pinned:true,
minWidth:700,
minHeight: 50,
resizeElement: function(){ // override default resizing
var size = this.proxy.getSize();
Me.setSize(Me.pWidth?Me.pWidth:size.width, size.height);
return size;
}
});
});

}

Ext.extend(Ext.ux.esaHtmlEditor, Ext.ux.HTMLEditor, {
defaultAutoCreate : {
tag: "textarea",
style:"width:700px;height:300px;",
autocomplete: "off",
cls: "x-hidden"
},

pushValue : function(){
if(this.initialized){
var v = this.el.dom.value;
if(this.fireEvent('beforepush', this, v) !== false){
(this.doc.body || this.doc.documentElement).innerHTML = v;
this.fireEvent('push', this, v);
}
}
},
onResize : function(w, h){
Ext.ux.esaHtmlEditor.superclass.onResize.apply(this, arguments);
if(this.el && this.iframe){
if(typeof w != 'number')
this.iframe.style.width = w;
if(typeof h != 'number')
this.iframe.style.height = h;
}
}

});

Ext.override(Ext.ux.esaHtmlEditor, {
/**
* Set a readonly mask over the editor
* @param {Boolean} readOnly - True to set the read only property, False to switch to the editor
*/
onDisable: function() {
this.setReadOnly( true );
},
onEnable: function() {
this.setReadOnly( false );
},
setReadOnly: function( readOnly ) {
if(readOnly){
this.syncValue();
var roMask = this.wrap.mask();
roMask.dom.style.filter = "alpha(opacity=0);"; //IE
roMask.dom.style.opacity = "0"; //Mozilla
roMask.dom.style.background = "white";
roMask.dom.style.overflow = "scroll";
roMask.dom.style.zIndex = 10; // dqj - eCornell - was hiding other dialogs
if ( this && this.width && this.width > 0 )
roMask.dom.style.width = this.width-19; // scrollbar width; no way to determine actual, according to ExtJS
//roMask.dom.innerHTML = this.getValue();
this.el.dom.readOnly = true;
} else {
if(this.rendered){
this.wrap.unmask();
}
this.el.dom.readOnly = false;
}
},

// private
onRender : function( ct, position ) {
Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
this.el.dom.style.border = '0 none';
this.el.dom.setAttribute('tabIndex', -1);
this.el.addClass('x-hidden');
if(Ext.isIE){ // fix IE 1px bogus margin
this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
}
this.wrap = this.el.wrap({
cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
});

this.createToolbar(this);

this.tb.items.each(function(item){
if(item.itemId != 'sourceedit'){
item.disable();
}
});

var iframe = document.createElement('iframe');
iframe.name = Ext.id();
iframe.frameBorder = 'no';

iframe.src=(Ext.SSL_SECURE_URL || "javascript:false");

this.wrap.dom.appendChild(iframe);

this.iframe = iframe;

if(Ext.isIE){
iframe.contentWindow.document.designMode = 'on';
this.doc = iframe.contentWindow.document;
this.win = iframe.contentWindow;
} else {
this.doc = (iframe.contentDocument || window.frames[iframe.name].document);
this.win = window.frames[iframe.name];
if ( !Ext.isGecko2 ) { // dqj
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(){
if(this.doc.body || this.doc.readyState == 'complete'){
Ext.TaskMgr.stop(task);
this.initEditor.defer(10, this);
this.doc.designMode="on";
}
},
interval : 10,
duration:10000,
scope: this
};
Ext.TaskMgr.start(task);

if(!this.width){
this.setSize(this.el.getSize());
}
}
});

phernaca
20 Apr 2010, 3:06 AM
Hi queej,

Thanks a lot!

I struggled yesterday cause I'm pretty newbie to extJS but I finally got my Editor with a nice 'alive' scrollbar when in view mode.

On the other hand I've still got a problem as I can not select the contents and so a copy/paste is not possible.

Does anybody know if is this feasible?

Thanks again,

phernaca

queej
20 Apr 2010, 4:19 AM
It's not ideal, but you could include a Copy button that issues a retrieval command to the editor.

phernaca
20 Apr 2010, 5:16 AM
Do you mean that it exists a plugin for the Toolbar that allows to copy the contents of an HtmlEditor to the clipboard?

If it is the case I'm pretty sure that it will be good enough.

queej
20 Apr 2010, 5:43 AM
I'm pretty sure there is functionality that will allow you to create your own button external to the editor, or to add a button to the editor. I have been using TinyMCE mostly, lately, so I don't remember the details. I would search the forums here.