在 Opera 上,一个基于Web的富内容

分享于 

18分钟阅读

Web开发

  繁體

Sample Image - Editor/Editor.gif

介绍

周围有大量基于web的富文本编辑器。 列出以下部分:

#http://xstandard.com/ - xstandard编辑器的所见即所得,创建严格的XHTML标记。

#http://www.fckeditor.net/ - 适用于 IE 和基于mozilla浏览器的FCKEditor。

#http://www.kevinroth.com/rte/demo.htm - kevin富文本编辑器的跨浏览器。

# codeproject编辑器的文章。

开始之前,我想先说明我不想被理解。 所有 上面 富内容编辑器都做了出色的工作: 他们把无聊的文本转换成一个完全可以编辑的条目。 他们的开发团队为 improve/enhance/support 提供了巨大的力量。 我完全尊重他们的工作。 这篇文章决不是一种补充方法。 我只是想从不同的角度来看看。 完成。

还有许多其他丰富的内容编辑器,它们提供了不同的。 所有这些编辑器都利用浏览器的 ContentEditable mode模式来创建所谓的"你所看到的就是你所得到的"。

但是,启用富文本内容的版本不是标准。 所以每个供应商都有自己的实现。

此外,对 ContentEditable 模式的支持是有限的: 只有基于mozilla的浏览器和 IE 目前支持它。 当第三个浏览器出来并说"你们在那里 out ! 我也有自己的方法来实现to模式"没有人可以某种方式实施它们。 因为没有任何声明的标准用于丰富内容创建。

接下来会发生什么我们将重新分叉我们的代码以支持这两个浏览器。 突然出现十个浏览器弹出十个不同的API implemantation。 你将拥有两个 chocies: 要么花费十倍的精力,然后创建代码spagethi来处理所有可能的情况,或者忽略少数少数的少数浏览器的浏览器。

但情况不应该是这样的:

实际上,编辑HTML文档的标准方法是万维网联合会推荐的标准方法:

对文档对象模型进行收费 !

我们可以通过操作的DOM 来获得丰富的内容可以编辑性,我们可以向任何收费的DOM浏览器添加丰富的内容支持;不仅仅是Mozilla和。

我知道我们不能支持地球上的每一个浏览器。 但 imho,至少应该给所有支持收费的浏览器提供 opportunuties。

但是,这真的需要?

这类产品的必要性是另一。 正如 上面 所提到的,大多数web使用 IE 和mozilla族浏览器来实现内容可以编辑性。

另一个讨论的观点可能是网页上wysiwyg的适用性和必要性。 换句话说,使用textareas和的模板管理和所见即所得的东西就更好了,比如 Macromedia Contribute Macromedia Macromedia。

根据我的网络统计,Opera 用户的流量少于我的1% %。 % 1 $ d,大约为 %,大约为 IE %/5 %的其余部分)。

所以人们对于基于mozilla的浏览器和 IE ( 组成我的传入网络流量 96 -99% )的编辑器很高兴。

我高兴当然不会。 但那是我,只有我 : )

代码项目的一个目标是manifesing疯狂的思考,不是?

可以能是一个想法,将它从一个techy思想从一个更合理的地方,平均用户可以能利用。

我听到你说"philosopy,让我们看看工作完成了"。 我们来了

实现

测试文章编辑器的最佳方法是编写文章,这样我可以了解我添加的功能,可以通过编辑 Editor,让我从编辑器 kill

请相信我,我在Opeara中写这篇文章: 我最喜欢的浏览器,我的第一个是 Mozilla,我从来没有考虑过互联网 Exploder,shame我

编辑器使用几个js类来实现:

[__strong__]DraggableLayer:The classis used to add drag-drop support and DOM integration.ToolTip:This classis used to pop tiny tooltip on hovering over the node anchors 
(the images with a white plus on them).DOMManager:The objectis used to seek parent-child relations as well asremoveempty text nodes which cause problem in Opera and Mozilla.WindowObject:This classis used to get the inner dimensions and scroll ofsets of the
browser window.TextFormatter:The objectis used to remove extra markup that is usedfor editing purposes only. Moreover, it makes the tags lowercase,
so the markup will be more or less standards-compatible.Editor:Editor is the model for the article editing application GUI (the view).

你可以使用编辑器对文章进行大量格式化,添加图像,添加链接,还可以创建有效的xhtml严格代码。 我试图让GUI变得简单,但我不是可用性专家。 我对任何 ideas/sketches/mock-ups 都开放,可以进一步提高可用性。

编辑器对象

对于那些新的MVC ( 模型视图控制器) 范例: 编辑器对象是编辑器的模型。 将模型与视图分离;我们可以更改视图,更改布局,更改样式 等等 不需要更改后面的js代码。

这里有一个高度截断的编辑器的Prototype。





_this=_Editor.prototype;



function _Editor() {


 /*initialize members*/


 /**/


}


/*public methods*/


_this.setActiveNodeName=function(strValue){...};


_this.setActiveNode=function(obj){...};


_this.getActiveNode=function(){...};


_this.setCurrentAction=function(intValue){...}; 


_this.isBlockLevel=function(strName){...}


_this.isInline=function(strName){...}


_this.isActiveNodeBlockLevel=function(){...}


_this.getActiveNodeName=function(){...};


_this.getCurrentAction=function(){...};


_this.init=function(){


 this.controlPane={


 /* 


 * Bind GUI elements to the Editor model


 * using this associative array.


 */


 };



 /*


 * create span elements that contain


 * icons which will initiate the editor when


 * clicking on them.


 */



 /*register events*/


};



_this.getExtendedNodeDescription=function(strNode){...};


_this._RadH1_click=function(evt){...};


_this._RadH2_click=function(evt){...};


_this._RadH3_click=function(evt){...};


_this._RadH4_click=function(evt){...};


_this._RadH5_click=function(evt){...};


_this._RadH6_click=function(evt){...};


_this._RadP_click=function(evt){...};


_this._RadPre_click=function(evt){...};


_this._RadStrong_click=function(evt){...};


_this._RadEm_click=function(evt){...};


_this._RadNormal_click=function(evt){...};


_this._btnChangeType_click=function(evt){...};


_this.toggleCommitAction=function(){...};


_this._btnEdit_click=function(evt) {...};


_this._blnPreview_click=function(evt){...};


_this._btnAddAfter_click=function(evt) {...};


_this._btnAddBefore_click=function(evt){...};


_this._btnMoveAfter_click=function(evt){...};


_this._btnMoveBefore_click=function(evt){...};


_this._btnCopyHere_click=function(evt){...};


_this._btnCopyBefore_click=function(evt){...};


_this._btnCopyAfter_click=function(evt){...};


_this._btnDelete_click=function(evt){...}


_this._btnCancel_click=function(evt){...}


_this.cancelAction=function(){...};


_this._resetGUI=function(){...};


_this.createProperNode=function(strName,strText){...};


_this.getProperNodeValue=function(objNode){...};


_this.getProperNode=function(objNode){...};


_this._btnCommit_click=function(evt){


 switch(Editor.getCurrentAction()){


 case Constant.Editor.Action.ADD_AFTER:


 Editor.addAfter(); 


 break;


 case Constant.Editor.Action.ADD_BEFORE:


 Editor.addBefore();


 break;


 case Constant.Editor.Action.MOVE_AFTER:


 Editor.moveAfter();


 break;


 case Constant.Editor.Action.MOVE_BEFORE:


 Editor.moveBefore();


 break;


 case Constant.Editor.Action.DUPLICATE:


 Editor.duplicate();


 break;


 case Constant.Editor.Action.DELETE_NODE:


 Editor.deleteNode();


 break;


 case Constant.Editor.Action.EDIT_TEXT:


 Editor.editText();


 break; 


 case Constant.Editor.Action.CHANGE_TYPE:


 Editor.changeType();


 break;


 default:


 break;


 }


 /*set GUI back to initial state*/


 Editor.cancelAction();


};



_this.addAfter=function(){...};


_this.addBefore=function(){...};


_this.moveAfter=function(){...};


_this.moveBefore=function(){...};


_this.duplicate=function(){...};


_this.deleteNode=function(){...};


_this.editText=function(){...};


_this.changeType=function(){...};


_this._appendControlsToFamily=function(nodeToInsert){...};


_this.organizeEditPane=function(){...};


_this.appendControls=function(theNode){...};


_this._edit_click=function(evt){...};



HTML

编辑器页面的HTML如下所示:


<div id="EditorArea" class="""textEditor">"" 


<h2>Introduction</h2>


</div>



<div id="EditorControls">


<h3 id="EditorInfo">Informational Heading</h3>


<div style="padding:10px;" id="EditorControlButtons">


<h4>transform</h4>


<div><input type="button" id="btnChangeType" value="change type" /></div>



<h4>alter</h4>


<div>


<input type="button" id="btnEdit" value="edit text" />


<input type="button" id="btnAddBefore" value="add before" />


<input type="button" id="btnAddAfter" value="add after" />


</div>


<h4>move</h4>


<div>


<input type="button" id="btnMoveBefore" value="move before/move up" />


<input type="button" id="btnMoveAfter" value="move after/move down" />


</div>


<h4>copy</h4>


<div>


<input type="button" id="btnCopyHere" value="duplicate element" />


</div>


<h4>remove</h4>


<div><input type="button" id="btnDelete" value="remove element" /></div>


</div>


<div style="padding:10px;">



<ul id="ListTagsBlockLevel">


... radio buttons.. .


</ul>



<ul id="ListTagsInline">


.... radio buttons.. .


</ul>



<textarea rows="10" cols="30" id="TxtContent"></textarea>


</div>



<div style="padding:10px;text-align:right;">


<input type="button" value="cancel" id="btnCancel" />


<input type="button" value="commit" id="btnCommit" />


</div>


</div>



的EditorArea层包括可以编辑内容,wheras EditorControls 包含GUI控件。

为了初始化编辑器,我们在页面加载中调用了它的 init() 方法。


window.onload=function() {


 Editor.init();


 document.getElementById("BtnArticleSource"


 ).onclick=BtnArticleSource_click;


};



function BtnArticleSource_click(evt){


 alert("This action may take some time and your browser may_


 hang for a few seconds.nPlease be patient.");



 var src=new EventObject(evt).getSource();



 document.getElementById("ArticleSource").value=


 TextFormatter.properHTML(


 Editor.controlPane.panel.EditorArea.getObject().innerHTML);


}



单击"检索文章的html"按钮时,将触发 BtnArticleSource_click 方法。 这将用文章的HTML填充页面底部的文本框。

你可以进一步研究代码。 我尽量把代码和标记写得尽可能的干净。 请随意表达任何查询和评论。

提示和用法

tip 本文的创建和修改是在节点基础上完成。 如果在编辑模式下工作,则将识别节点锚点( inline edit iconblock level edit icon )。 inline edit icon 用于对内联元素 block level edit icon 用于 add/edit/modify 块级别元素 ( 标题级别 1 -6,段落和预格式化的文本)。

tip 单击节点锚会弹出该特定节点的可用操作。 弹出是可以拖动的DHTML层( 我的后续文章将创建一个简单的drag&放置层)。

tip 双击文章上的任意位置可以切换到 preview preview preview preview模式。

tip 从我的经验来看: 使用编辑器花费了一些时间。 因为,你需要整整查看整个文档,而不是一组段落和文本,以便复制和拖动。 但是当你习惯它的时候你变得更有创意了。 事实上,"重复元素"功能有时候是一个很好的helper。 此外,冒泡 block 级元素向上和向下是有趣的。

tip 所有节点( 内联和块级别) 可用的操作:

# 收费类型:更改节点的类型,例如你可以将文本元素转换为链接或者图片。

#添加: 在该节点之前添加一个元素。

#添加: 在该节点之后添加一个元素。

# 在/上移前移动 在节点层次结构中将节点向上移动。

#/下移: 在节点层次结构中向下移动节点。

#重复: 创建一个相同的节点并在选定节点之后放置它。

#移除: 完全删除选定节点。 警告这里操作无法撤消。

# 剪切节点:删除节点,并将节点内容复制到临时方差。

#复制节点: 将节点内容复制到临时方差;它不删除原始节点。

# 在选择节点之前,将复制或者剪切节点粘贴到

#粘贴: 在选择节点之后粘贴复制或者剪切节点。

tip 仅对 inline 节点可用的操作:

#edit: 更改节点( 文本和( 源。链接。宽度等如果可用) )的内容。

tip inline 节点的可用类型:

#强文本: 粗体文本。

#强调文本: 斜体文本。

#普通文本: 普通文本。

#链接:一个链接链接。

#图像:lovely image

tip 块级别节点的可用类型:

#标题级别 1: 一级标题。

#标题级别 2: 第二级标题。

#标题级别 3: 第三级标题。

#标题级别 4: 第四级标题。

#标题级别 5: 第五级标题。

#标题级别 6: 第六级标题。

#

# 预先格式化的预先格式化文本:预格式化文本( 通常用于格式化代码)。

可以做的事情,以提高收费的Editor编辑

从现在开始,我将发布新版本到收费的编辑器,以收费 sardalya ( http://www.sarmal.com/sardalya/ )。 感兴趣的人可以按照下面。 下面是一个清楚的清单。 尽管我想提醒你我对positive&负criticisims的建议是开放的,这样我就可以进一步提高的编辑

# 插入列表和嵌套列表的能力。

# 添加对其他标签的支持( 如 <q>,<blockquote>,<hr/> )

# 向弹出界面添加一些描述性图标。

# 在预格式化的文本中添加标签,这对于 Opera 和其他非支持浏览器的缩进代码( 如果你的Opera 不支持它,它会优雅地转换- 可以添加一个按钮来复制标签字符( 从隐藏的字段中可能是 be ) ) 非常有用。

# 更多鼠标交互( 如拖动ancor并将它的拖动到另一个锚将移动节点befoore第二个,移动拖动将复制它等。)。

# 允许选择和修改多个节点(。例如 将两个paragraps加粗,将三个标题转换为段落等)。

# 允许创建和修改嵌套元素( 例如 <强> <> 强和强调文本 </em> </strong> )。

# 指定特定opearations的键盘快捷键。

# 能够添加预定义的笑脸图像,项目符号图片,头像等。

请注意读者

我只包括了我在本项目中使用的s@rdalya API的必要部分,并不偏离主题并保持代码小。 你可以在以下位置找到整个 api: http://www.sarmal.com/sardalya/

但是,web上的API目前不包含编辑器。 编辑器将被添加到下一个稳定的relase。

还要注意,这是一个开发版本,并没有针对web进行优化。 一个优化的版本以及使用示例和文档将在不久。

历史记录

#Article Article。

#released released released released。 ( 以前版本为 1.0.0 )。 文章相应更新。


相关文章