`

为CKEditor添加Readonly按钮和Upload Image按钮

阅读更多

问题内容

 

转自:http://cjkz.52biancheng.com/article/20110618/newpr-941.html
做Web开辟,尤其是企业使用这块的开辟者,最终都防止不了需求用到Html Editor。这一块我之前用的FCKEditor 2.4,如今FCKEditor曾经不存在了,取而代之的是CKEditor。研讨了一下,发现CKEditor的外部构造的确比FCKEditor时代有了很年夜改善(不外依然还有很年夜的改良余地),之前FCKEditor别扭的设置装备摆设体式格局在CKEditor外面被JSON片面庖代了。上面是我这两天的研讨效果,思索到研讨进程中在网上搜刮到的这方面的材料还比拟少,所以在这里记载一下,进展能帮到异样需求的冤家。
CKEditor版本:我研讨的CKEditor的版本是3.1,也是今朝的最新版本,这个版本我发现官网上只供应了php版。下载地址:http://ckeditor.com/download。
问题:
1.默许的CKEditor没有上传功用,假如要上传文件/图片需求CKFinder合营。而我的使用情况是ASP.net,即便装置了CKFinder也没法合营CKEditor运用。
2.CKEditor不供应只读功用,它只供应了一个Preview按钮,点击当前是弹出一个新窗口,窗口内容是编纂器的内容。这不是我想要的Preview结果。
目的:
1.默许的CKEditor的拔出图片功用是会弹出一个对话框,要求输出图片的URL地址。我进展能在输出URL地址的文本框边上放一个Upload按钮,可以上传当地的图片到效劳器,然后URL内主动获取图片在效劳器上的拜访URL。
2.在CKEditor对象栏上添加一个Readonly按钮,点击当前完成Preview功用--一切对象栏按钮弗成用,内容弗成编纂。
3.修正不要触及CKEditor源代码的修正,轻易当前CKEditor晋级。
完成:
1.代码【1】:
//////////////////////////////////////////////////////////////////////////////////////////////////////////
function addUploadButton(editor){
CKEDITOR.on('dialogDefinition', function( ev ){
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if ( dialogName == 'image' ){
var infoTab = dialogDefinition.getContents( 'info' );
infoTab.add({
type : 'button',
id : 'upload_image',
align : 'center',
label : 'upload',
onClick : function( evt ){
var thisDialog = this.getDialog();
var txtUrlObj = thisDialog.getContentElement('info', 'txtUrl');
var txtUrlId = txtUrlObj.getInputElement().$.id;
addNestedImage(txtUrlId);
}
}, 'browse'); //place front of the browser button
}
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
阐明:
1.dialogDefinition是一个事情,经过对这一事情编程可以到达不修正源代码的状况下修正CKEditor的对话框。每个CKEditor的对话框都有一个名字。点击拔出Image按钮后弹出的对话框的名字是image。
2.每个对话框由多个选项卡构成,经过getContents的办法可以定位选项卡。填写image Url的文本框在info选项卡内。
3.经过add办法可认为选项卡添加新的元素。add办法有2个参数,第一个是JSON花样的元素描绘,第二个参数是新元素的拔出地位,没有的话新元素就添加到选项卡最初。browse是image url文本框旁边默许的按钮,平日是设置装备摆设了CKFinder当前才干看到。我由于没有装置CKFinder,所以看不到这个按钮,但无妨碍我借用它给我的Upload按钮定位。
4.Upload按钮的花样界说。分歧的对话框元素有分歧的属性。我这里是参考CKEditor的源码里其他按钮的花样界说出来的。type是元素的类型,id是标识符,要阐明的是这个id不是最终的HTML元素的id,而是给CKEditor本人外部运用的id(经过getContentElement()办法,见前面)。label是按钮上的文字。onClick就是点击按钮后执行的举措。
5.我的设法主意是点击按钮后弹出一个新窗口,在新窗口中完成文件/图片上传功用。上传完毕时前往图片的URL,然后把这个URL填到image URL文本框里。addNestedImage(txtUrlId)就是做的这件事。参数txtUrlId就是image URL的文本框的id(HTML元素的id)。经过
var thisDialog = this.getDialog();
var txtUrlObj = thisDialog.getContentElement('info', 'txtUrl');
var txtUrlId = txtUrlObj.getInputElement().$.id;
这三行代码可以完成JSON'id和HTML'id的转换。txtUrl就是image URL文本框的JSON id。这是看源码看来的。
6.addNestedImage的内容和CKEditor根本有关,代码就不放这儿了,根本思绪是:承受一个目的参数theElementId,然后用window.open翻开一个新的窗口,相似.../UploadImage.aspx?return_id=theElementId。UploadImage.aspx就是一个通俗的上传页面,aspx在这块做的十分复杂了,代码就不写了。需求阐明的是上传完毕后,需求执行一段js代码,内容是将上传的图片在效劳器上的URL反写到theElementId指定的元素中。代码年夜致如下:
var tmpObj = window.opener.document.getElementById("<%=URL参数return_id%>");
if (tmpObj != null){
var tmpImageUrl = "<%=图片在server上的URL%>";
tmpObj.value = tmpImageUrl;
tmpObj.setAttribute("value", tmpImageUrl);
tmpObj.fireEvent("onchange");
}
window.close();
最初用window.close()关失落窗口就好了。

2.代码【2】:
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Temporary workaround for providing editor 'read-only' toggling functionality.   
( function(){
var cancelEvent = function( evt ){
evt.cancel();
};

CKEDITOR.editor.prototype.readOnly = function( isReadOnly ){
// Turn off contentEditable
/*
if ( this.document ){
this.document.$.body.disabled = isReadOnly;
if ( CKEDITOR.env.ie ){  
this.document.$.body.contentEditable = !isReadOnly;
}else{
this.document.$.designMode = (isReadOnly ? "off" : "on");
}
}
*/

// Prevent key handling.
this[ isReadOnly ? 'on' : 'removeListener' ]( 'key', cancelEvent, null, null, 0 );
this[ isReadOnly ? 'on' : 'removeListener' ]( 'selectionChange', cancelEvent, null, null, 0 );

// Disable all commands in wysiwyg mode.
var command,
commands = this._.commands,
mode = this.mode;

for ( var name in commands ){
if (name != "ReadonlyCmd"){
command = commands[ name ];
if ( isReadOnly ) {
command.disable();
}else{
command[ command.modes[ mode ] ? 'enable' : 'disable' ]();
}
this[ isReadOnly ? 'on' : 'removeListener' ]( 'state', cancelEvent, null, null, 0 );
}
}

var i,j,k;
var toolbars = this.toolbox.toolbars;
for ( i = 0; i < toolbars.length; i++ ){
var toolbarItems = toolbars[i].items;
for ( j = 0; j < toolbarItems.length; j++ ){
var combo = toolbarItems[j].combo;
if ( combo ){
combo.setState( isReadOnly ? CKEDITOR.TRISTATE_DISABLED : CKEDITOR.TRISTATE_OFF );
}
var button = toolbarItems[j].button;
if ( button && button.createPanel ){
button.setState( isReadOnly ? CKEDITOR.TRISTATE_DISABLED : CKEDITOR.TRISTATE_OFF );
}
}
}
}
} )();
//代码【3】:
function addReadonlyButton(editor, theMode){
editor.on('pluginsLoaded', function( ev ){
var savedState = CKEDITOR.TRISTATE_OFF;
var i,j,k;
editor.addCommand( 'ReadonlyCmd', {
exec : function (e){
switch (this.state){
case CKEDITOR.TRISTATE_OFF :
editor.readOnly(true);
  break;
case CKEDITOR.TRISTATE_ON :
editor.readOnly(false);
break;
}
this.toggleState();
savedState = this.state;
},
canUndo : false
});

editor.ui.addButton( 'Readonly', {
label : 'Readonly',
command : 'ReadonlyCmd'
});

editor.on( 'mode', function() {
editor.getCommand( 'ReadonlyCmd' ).setState( savedState );
}, null, null, 100 );
});
setReadonlyButtonStyle();
}

function setReadonlyButtonStyle(){
var cssText = ''
+ '.cke_button_ReadonlyCmd .cke_icon{'
+ ' display: none !important;'
+ '}'
+ '.cke_button_ReadonlyCmd .cke_label{'
+ ' display: inline !important;'
+ '}';
importStyle(cssText);
}
function importStyle(theCssText){
var styleElement = document.createElement('style');
styleElement.setAttribute("type", "text/css");

if (styleElement.styleSheet) { //for IE
styleElement.styleSheet.cssText = theCssText;
}else{ //for FF
var textNode = document.createTextNode(theCssText);
styleElement.appendChild(textNode);
}

var headElement = document.getElementsByTagName('head')[0];
headElement.appendChild(styleElement);
}
//代码【4】:
function initEditor(theName, theMode, theWidth, theHeight){
var editor = CKEDITOR.replace(theName, {
language : 'en',
skin : 'office2003',
startupFocus : true,
toolbar : [ //remove Save, NewPage, Form and input elements, add Readonly
['Source','-','Readonly','-','Templates'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
'/',
['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','Image','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
'/',
['Styles','Format','Font','FontSize'],
['TextColor','BGColor'],
['Maximize', 'ShowBlocks','-','About']
],
width : theWidth,
height : theHeight
});
addUploadButton(editor);
addReadonlyButton(editor);
if (theMode == "VIEW"){
setTimeout(function(){
editor.execCommand('ReadonlyCmd'); //click readonly
}, 500);
}
setTimeout(function(){
var tmpObj = document.getElementById("cke_" + theName);
var tmpInputs = tmpObj.getElementsByTagName("input");
if (tmpInputs.length > 0){
tmpInputs[0].style.display = "none";
}
}, 500);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
阐明:
1.代码【2】是为CKEditor扩展readonly的功用。代码【3】是为CKEditor添加Readonly按钮,代码【2】是将readonly按钮显示在对象栏上,同时包孕其他的设置装备摆设。
2.代码【4】是一个封装函数,轻易当前移植到其他的Html Editor。参数theName是数据源的id,theMode指明Html Editor的形态,"EDIT"是编纂形态,"VIEW"是只读形态。theWidth和theHeight是Html Editor的宽和高。CKEDITOR.replace()就不说了,用过CKEditor的都晓得。要害是toolbar : [...,'Readonly'...这就是将Readonly按钮显示在对象栏上。而Readonly按钮的界说经过代码【3】完成。
3.CKEDITOR.replace()前往CKEditor的实例editor,然后经过挪用后面界说的addUploadButton()和addReadonlyButton()完成给CKEditor非侵入的修正对话框和对象栏。
4.假如theMode是"VIEW",则手动挪用一次Redonly按钮,相当于按一下Readonly按钮。
5.最初一段是将CKEditor的一个文本框潜藏起来。每个CKEditor编纂器末尾都有一个input元素显示在页面上。我不晓得CKEditor为什么要把这个input元素显示出来,看着真别扭。不论它,用户看不见就好。
6.代码【3】就是完成Readonly按钮的界说。每个CKEditor的按钮其实都至多包孕2局部内容,一局部是对象栏上的按钮,这是用户看得见的局部,另一局部是点击这个按钮后CKEditor执行的举措。在CKEditor外面是一个command对象。经过pluginsLoaded这个事情可认为CKEditor添加新的button和command。添加buttong经过editor.ui.addButton停止,添加command经过editor.addCommand停止。先界说Command,然后界说button的时分经过指定button的JSON command属性将command和button联系关系起来。这里command和button没有必定联络,完全可以界说一个新的button,然后执行现有的command。
7.editor.on( 'mode', function(){...}, null, null, 100 )这个是用来完成Readonly按钮的无效和非无效形态。平日CKEditor假如是EDIT形态,那么Readonly是可用的,假如CKEditor曾经是VIEW形态了,那么我进展Readonly就是曾经按下去的样子。mode事情就是做这事的。
8.setReadonlyButtonStyle()和importStyle()是界说Readonly按钮的外不雅。看CKEditor的Sample看来的,没什么好说的。不界说的话按钮看不到。原本我想给Readonly按钮加个图标,就象Source一样,然则掉败了。有晓得怎样弄的兄弟请指点一下。
9.代码【2】是界说点击Readonly按钮当前执行的editor.readOnly(),这是对CKEditor的扩展。这一段我开端不断搞不定,只到从Google上搜到http://cksource.com/forums/viewtopic.php?f=11&t=15659这篇文章。外面garry.yao兄对我十分有协助。这里感激一下。然则garry.yao兄的代码只完成了通俗按钮的禁用,点击Readonly当前没有禁用Style,Format,Font,Color这些按钮。我添加了一些代码,完成这些功用。
10.将代码【1】【2】【3】【4】兼并放到一个js文件中,然后在页面onload的时分执行initEditor()就可以了。

  • 大小: 1.3 MB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics