View
1.400
Download
7
Embed Size (px)
DESCRIPTION
KISSY Editor Design 2 For D2 2012
Citation preview
KISSY Editor 设计(2)
kissyteam@weibo,twitter
yiminghe@twitter
2012.06.25 Draft
大纲
• 1. KISSY Editor 简介
• 2. 编辑器基本原理
• 3. KISSY Editor 实践
– 3.1 API
– 3.2 设计
– 3.4 使用
KISSY Editor ?
KISSY Editor
又一个开源的可视化编辑器
底层以及 UI 基于 KISSY 框架
编辑核心算法借鉴 CKEditor
应用于淘宝商品发布/店铺装修/论坛/….
KISSY Editor
KISSY Editor
• Toggle Button
• Select
KISSY Editor
• Overlay
• ContextMenu
KISSY Editor
• Bubble
编辑器基本原理
编辑器基本原理
• contentEditable
• designMode
• 使某个元素可编辑
– Iframe.contentWindow.document.body.conten
tEditable = true
• http://www.w3.org/TR/html5/editing.html#attr-
contenteditable
编辑器基本原理
• document.execCommand
编辑器基本原理
• Range/Selection
– IE (<=8)
• Selection: http://msdn.microsoft.com/en-
us/library/ie/ms535869(v=vs.85).aspx
– createRange/clear/empty
• Range: http://msdn.microsoft.com/en-
us/library/ie/ms535872(v=vs.85).aspx
– compareEndPoints/move/select/parentElement
编辑器基本原理
• Range/Selection
– W3c
– http://www.w3.org/TR/DOM-Level-2-
Traversal-Range/ranges.html
– Selection
• rangeCount/getRangeAt/addRange/removeRange
– Range
• startContainer/startOffset/endContainer/endOffset
编辑器基本原理
编辑器基本原理
• 根据规范由 javascript 实现浏览器内置的编辑算法– http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html
Body
P
12
P
34
p
56 strong
7
89
编辑器基本原理
• 编辑 api
– 加粗
– xhtml DTDBody
P
1 strong
2
P
strong
34
p
strong
5678
9
编辑器基本原理
• 编辑 api
– 标题 h1
p
123 strong
456
789
编辑器基本原理
• 编辑 api
– 标题 h1
h1
123 strong
456
789
其他兼容性问题
• Copy/paste
– Word
• Html parser
<font face="宋体"></font><p
style="margin: 0cm 0cm 0pt;"
class="MsoNormal"><span lang="EN-
US"><font face="Calibri">123<b
style="mso-bidi-font-weight:
normal;">456</b>789<?xml:namespace
prefix = o ns = "urn:schemas-microsoft-
com:office:office"
/><o:p></o:p></font></span></p><font
face="宋体"></font>
123456789<p>123<strong>456</strong>789</p>
其他兼容性问题
• 换行
– P / Br ?table
tr
td
123456
其他兼容性问题
• 图片选择
– 输入内容
• IE/firefox/chrome
• 失去焦点选区丢失
– IE
• ………
KISSY Editor
• API
• 设计
• 使用
KISSY Editor
• 基于 KISSY
– 模块化机制
– 组件基础设施
• 事件
• 属性
• 方法
• 生命周期
– 使用 KISSY UI
KISSY Component
KISSY Editor
API
KISSY.use(“editor”, function (S,Editor){
S.use(“plugin1,plugin2”, function (S,P1,P2){
new Editor({
// …
plugins:[
new P1({…}), P2
]
});});});
不启用自动 combine 时推荐 use ”editor/full”
继承属性
• width/height
– 高宽(包括工具栏与状态栏)
• focused
– 是否编辑区起始具备焦点
• prefixCls
– 编辑器 UI 样式前缀
继承属性
• xclass
– 组件嵌套时的快速生成
new Overlay({
children:[{
xclass: ’editor’,
width:500,
height:500
}]
});
继承属性
• srcNode
– 从已有节点生成编辑器组件
• render
– 编辑器组件渲染容器
继承属性
• listeners
– 方便绑定事件
• plugins
– 添加插件
new Editor({
listeners:{
focus: function(){}
}}).render;
编辑器属性
• customStyle
– 作用于编辑区域的特有样式
• customLink
– 作用于编辑区域的特有样式链接
• attachForm
– 绑定所属 form submit 事件
编辑器方法
• addButton– 添加按钮到工具栏
• addSelect– 添加 select 到工具栏
• insertHtml
– 插入 html 到光标位置
• execCommand– 执行自定义命令
设计
KISSY Loader
dom event node ua base
component
Html
Parser
&
xhtml
dtd
range selection
button select menu Edit API
Editor & plugins
overlay
模块
• 所有代码都是模块
KISSY.add("editor/range",function(S,DOM){
},{
requires:['dom']
});
懒加载
• 懒加载非初始模块
懒加载
• 使用 KISSY.use
KISSY.add("editor/plugin/image",function(S,DOM){
xx.on("click",function(){
S.use("editor/plugin/image/dialog");
});
});
按需自动 combo
• 仅加载需要的模块
– 最优的链接数与代码引入大小
KISSY.use("editor",function(){
KISSY.use("editor/plugin/fontSize/,editor/plugin
/fontFamily/",
function(){
// use plugins
});});
按需自动 combo
无障碍
• Aria in KISSY UI
– Tab 支持
– 所有功能键盘可访问
– Aria 标记
• 编辑区域快捷键
插件
• 具备介入组件生命周期能力的普通模块
createDOM renderUI bindUI syncUI
插件示例
KISSY.add("editor/plugin/bold/index",function(){
function FontSize(cfg){this.cfg=cfg;}
FontSize.prototype={
renderUI:function(editor){
editor.addButton(...);
}
};
return FontSize;
});
消息通信
• 核心插件
• 插件插件
editor.fire("selectionChange
");
editor.on("selectionChange",
function(){
});
editor
plugin2
Plugin1plugin3
命令系统
• document.execCommand
• editor.execCommand
editor
fontSize
fontFamily
bold
editor.execCommand("fontSize","1
8px");
editor.execCommand("fontFamily",
"kaiti");
editor.execCommand("bold",true);
单元测试
• 部分核心 jasmine
单元测试describe("cloneContents", function () {
it(“works for simple text node”, function () {
var range = new Range(document);
range.setStart(text, 2);
range.setEnd(text, 5);
var f = range.cloneContents();
var newDiv = KISSY.all("<div>").appendTo("body");
newDiv.append(f);
expect(myHtml(newDiv)).toBe("345");
});
});
使用
引入脚本
<script src='http://a.tbcdn.cn/s/kissy/1.3.0/seed-
min.js'></script>
<!-- or -->
<script src='http://a.tbcdn.cn/s/kissy/1.3.0/kissy-
min.js'></script>
载入模块、插件
// 自动 combo
KISSY.config("combine",true);
// editor 核心/种子文件
KISSY.use("editor",function(S,Editor){
// editor 插件
S.use("editor/plugin1,editor/plugin2...",
function(S,Plugin1,Plugin2){});
});
初始化
• 从已有节点产生
new Editor({
width:,
height:,
srcNode:'#editor',
plugins:[
new Plugin1({..}),
Plugin2
]
});
初始化
• 全新创建编辑器
new Editor({
width:,
height:,
render:'#editorContainer',
plugins:[
new Plugin1({..}),
Plugin2
]
});
定制插件
• 实现指定接口的普通模块
• editor.addButton
• editor.addSelect
• editor.execCommand
• editor.insertHtml
回顾
• 了解 KISSY Editor
• 编辑器基本原理
• KISSY Editor 设计
下一步
• I18n 全球化
• 主题 Theme 架构
• 单元测试完善
• 紧密结合 KISSY UI