From db69aa0163cadfb17db561e447f4f6f74fe76d63 Mon Sep 17 00:00:00 2001
From: sjshare
Date: Mon, 16 May 2016 13:39:21 +0800
Subject: [PATCH 01/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9image.js=E6=9C=AC?=
=?UTF-8?q?=E5=9C=B0=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修改本地图片上传,当上传文件出现超出大小或格式不允许时,移除文件后文件总数及总大小出错问题。
---
dialogs/image/image.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dialogs/image/image.js b/dialogs/image/image.js
index d0257bded..c79062623 100644
--- a/dialogs/image/image.js
+++ b/dialogs/image/image.js
@@ -665,8 +665,10 @@
});
uploader.on('fileDequeued', function (file) {
- fileCount--;
- fileSize -= file.size;
+ if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= imageMaxSize) {
+ fileCount--;
+ fileSize -= file.size;
+ }
removeFile(file);
updateTotalProgress();
From ed5b7ef8240d01d34d5cfb49689c22aea6aae7d0 Mon Sep 17 00:00:00 2001
From: sjshare
Date: Mon, 16 May 2016 13:48:00 +0800
Subject: [PATCH 02/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9attachment.js=E6=9C=AC?=
=?UTF-8?q?=E5=9C=B0=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修改本地文件上传,当上传文件超出大小或格式不允许时,点击移除后文件总数及总大小出错bug。
---
dialogs/attachment/attachment.js | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/dialogs/attachment/attachment.js b/dialogs/attachment/attachment.js
index da73cc9d8..5e73d5e97 100755
--- a/dialogs/attachment/attachment.js
+++ b/dialogs/attachment/attachment.js
@@ -439,8 +439,10 @@
}
uploader.on('fileQueued', function (file) {
- fileCount++;
- fileSize += file.size;
+ if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= fileMaxSize) {
+ fileCount++;
+ fileSize += file.size;
+ }
if (fileCount === 1) {
$placeHolder.addClass('element-invisible');
@@ -451,8 +453,10 @@
});
uploader.on('fileDequeued', function (file) {
- fileCount--;
- fileSize -= file.size;
+ if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= fileMaxSize) {
+ fileCount--;
+ fileSize -= file.size;
+ }
removeFile(file);
updateTotalProgress();
@@ -753,4 +757,4 @@
};
-})();
\ No newline at end of file
+})();
From 70d1c643f0dac7bd0078beb9aa0c76c8de70652a Mon Sep 17 00:00:00 2001
From: Dafrok
Date: Thu, 2 Jun 2016 11:54:06 +0800
Subject: [PATCH 03/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9package.json=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0uglify=E7=9A=84dependence?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index 74f9e806c..79df27925 100644
--- a/package.json
+++ b/package.json
@@ -23,12 +23,13 @@
},
"dependencies": {
"grunt": "~0.4.1",
+ "grunt-contrib-clean": "~0.5.0",
"grunt-contrib-concat": "~0.3.0",
- "grunt-contrib-cssmin": "~0.6.0",
"grunt-contrib-copy": "~0.4.0",
- "grunt-transcoding": "~0.1.1",
+ "grunt-contrib-cssmin": "~0.6.0",
+ "grunt-contrib-uglify": "^1.0.1",
"grunt-text-replace": "~0.3.9",
- "grunt-contrib-clean": "~0.5.0"
+ "grunt-transcoding": "~0.1.1"
},
"devDependencies": {
"grunt": "~0.4.1"
From 689030e0a7af8cf0ccd471f37dd7e70d88f4a0e7 Mon Sep 17 00:00:00 2001
From: tangtanglove
Date: Mon, 20 Jun 2016 18:15:41 +0800
Subject: [PATCH 04/33] Update Uploader.class.php
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
iconv函数无法将unicode转换为utf-8(会有警告),更换为mb_convert_encoding函数
---
php/Uploader.class.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/php/Uploader.class.php b/php/Uploader.class.php
index 6332c9765..1966ab353 100755
--- a/php/Uploader.class.php
+++ b/php/Uploader.class.php
@@ -61,7 +61,7 @@ public function __construct($fileField, $config, $type = "upload")
$this->upFile();
}
- $this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']);
+ $this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = mb_convert_encoding($this->stateMap['ERROR_TYPE_NOT_ALLOWED'], 'utf-8', 'auto');
}
/**
From a83d116501ff00424e9a3108291546f33812d912 Mon Sep 17 00:00:00 2001
From: Phinome
Date: Sat, 16 Jul 2016 23:00:14 +0800
Subject: [PATCH 05/33] Update ISSUE_TEMPLATE.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
增加声明
---
ISSUE_TEMPLATE.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index e81009ddb..7ffa3545f 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,3 +1,5 @@
+**声明:如果不看该说明,只在标题中描述问题,一律忽略**
+
**首先**,感谢各位使用 UEditor,并来到这儿提 `ISSUE`。
**其次**,在回答大量用户提出的 `ISSUE` 的过程中,我们发现需要建立一个提 `ISSUE` 的规则,
From 6b7aaf2b2b8c28645a15b601f04a2d587543d9f3 Mon Sep 17 00:00:00 2001
From: phinome
Date: Fri, 19 Aug 2016 20:39:40 +0800
Subject: [PATCH 06/33] add FAQ wiki
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index a929c522b..1df6b7c43 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
Get Started
=====
+> 鉴于目前 ISSUE 较多而维护时间较少,更为重要的是有很多重复的问题,因此特意整理了一份常见问题的 [FAQ Wiki](https://github.com/fex-team/ueditor/wiki/FAQ)。
+
## ueditor富文本编辑器介绍
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。
From c79d8acb71109ac381543c2697d6da3cd9f79e4e Mon Sep 17 00:00:00 2001
From: Phinome
Date: Sun, 11 Dec 2016 20:13:36 +0800
Subject: [PATCH 07/33] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 1df6b7c43..58bf63a1e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
Get Started
=====
-> 鉴于目前 ISSUE 较多而维护时间较少,更为重要的是有很多重复的问题,因此特意整理了一份常见问题的 [FAQ Wiki](https://github.com/fex-team/ueditor/wiki/FAQ)。
+> 鉴于目前 ISSUE 较多而维护时间较少,且在进行后续的版本更新,目前暂时关闭 ISSUE,若社区有人跟进,欢迎和我们联系。重复的问题,请参阅常见问题的 [FAQ Wiki](https://github.com/fex-team/ueditor/wiki/FAQ)。
## ueditor富文本编辑器介绍
From 84d9f7881938b91d4d0c0f54ed4bf9f775903b53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=8B=BC=E6=97=8F=E5=B0=8F=E7=8B=88?= <1340641314@qq.com>
Date: Fri, 23 Dec 2016 14:55:20 +0800
Subject: [PATCH 08/33] Update buttonicon.css
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修复在webpack下的bug:
Module not found: Error: Cannot resolve 'file' or 'directory' ../images/charts.png in
---
themes/default/_css/buttonicon.css | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/themes/default/_css/buttonicon.css b/themes/default/_css/buttonicon.css
index 38f059e46..a4b242979 100755
--- a/themes/default/_css/buttonicon.css
+++ b/themes/default/_css/buttonicon.css
@@ -403,7 +403,7 @@
}
.edui-default .edui-for-charts .edui-icon {
- background: url( ../images/charts.png ) no-repeat 2px 3px!important;
+ background: url(../images/charts.png) no-repeat 2px 3px!important;
}
.edui-default .edui-for-inserttitlecol .edui-icon {
@@ -416,4 +416,4 @@
.edui-default .edui-for-simpleupload .edui-icon {
background-position: -380px 0px;
-}
\ No newline at end of file
+}
From 52d1fa74c434595cc5133a2deb7b33bea4aee6f0 Mon Sep 17 00:00:00 2001
From: Boatman
Date: Thu, 9 Feb 2017 17:30:11 +0800
Subject: [PATCH 09/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9htmlParser=E7=9A=84?=
=?UTF-8?q?=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F,=E5=A2=9E?=
=?UTF-8?q?=E5=BC=BAhtml=E8=A7=A3=E6=9E=90=E7=9A=84=E5=AE=B9=E9=94=99?=
=?UTF-8?q?=E8=83=BD=E5=8A=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
现有的htmlParser 节点正则表达式无法匹配:
修改正则表达式:
---
_src/core/htmlparser.js | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/_src/core/htmlparser.js b/_src/core/htmlparser.js
index 3d242fc16..375968111 100644
--- a/_src/core/htmlparser.js
+++ b/_src/core/htmlparser.js
@@ -26,7 +26,10 @@
var htmlparser = UE.htmlparser = function (htmlstr,ignoreBlank) {
//todo 原来的方式 [^"'<>\/] 有\/就不能配对上 这样的标签了
//先去掉了,加上的原因忘了,这里先记录
- var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
+ //var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
+ //以上的正则表达式无法匹配:
+ //修改为如下正则表达式:
+ var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g,
re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
//ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
@@ -194,4 +197,4 @@ var htmlparser = UE.htmlparser = function (htmlstr,ignoreBlank) {
text(currentParent, htmlstr.slice(nextIndex));
}
return root;
-};
\ No newline at end of file
+};
From 5df3d0a7d7c78b69c6e3d6d9e442f88a2b504381 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=9D=B3=E5=BF=97=E5=87=AF?=
Date: Fri, 26 May 2017 19:58:00 +0800
Subject: [PATCH 10/33] Fixed autoheight Plugin onscroll error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修复 autoheight 插件在 UE 实例销毁后,因 onscroll 事件监听没有正常取消监听导致 me.window 报 undefined 错误的问题
---
_src/plugins/autoheight.js | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/_src/plugins/autoheight.js b/_src/plugins/autoheight.js
index 6d2d0f11a..40950cb11 100644
--- a/_src/plugins/autoheight.js
+++ b/_src/plugins/autoheight.js
@@ -53,6 +53,7 @@ UE.plugins['autoheight'] = function () {
isFullscreen = f
});
me.addListener('destroy', function () {
+ domUtils.un(me.window, "scroll", fixedScrollTop);
me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight)
});
me.enableAutoHeight = function () {
@@ -99,17 +100,20 @@ UE.plugins['autoheight'] = function () {
});
//修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题
- var lastScrollY;
- window.onscroll = function(){
- if(lastScrollY === null){
- lastScrollY = this.scrollY
- }else if(this.scrollY == 0 && lastScrollY != 0){
- me.window.scrollTo(0,0);
- lastScrollY = null;
- }
- }
+ domUtils.on(me.window, "scroll", fixedScrollTop);
});
+ var lastScrollY;
+
+ function fixedScrollTop() {
+ if(!me.window) return;
+ if(lastScrollY === null){
+ lastScrollY = me.window.scrollY
+ }else if(me.window.scrollY == 0 && lastScrollY != 0){
+ me.window.scrollTo(0,0);
+ lastScrollY = null;
+ }
+ }
};
From 039c5ccebfaad6cdaaa1e22c212d45fe96780826 Mon Sep 17 00:00:00 2001
From: woleicom <572962673@qq.com>
Date: Tue, 13 Jun 2017 15:02:00 +0800
Subject: [PATCH 11/33] Create image.js
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
更改图片尺寸大小bug
---
dialogs/image/image.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dialogs/image/image.js b/dialogs/image/image.js
index c79062623..a7e822ea5 100644
--- a/dialogs/image/image.js
+++ b/dialogs/image/image.js
@@ -177,22 +177,22 @@
domUtils.on($G("title"), 'keyup', updatePreview);
domUtils.on($G("width"), 'keyup', function(){
- updatePreview();
if(locker.checked) {
var proportion =locker.getAttribute('data-proportion');
$G('height').value = Math.round(this.value / proportion);
} else {
_this.updateLocker();
}
+ updatePreview();
});
domUtils.on($G("height"), 'keyup', function(){
- updatePreview();
if(locker.checked) {
var proportion =locker.getAttribute('data-proportion');
$G('width').value = Math.round(this.value * proportion);
} else {
_this.updateLocker();
}
+ updatePreview();
});
domUtils.on($G("lock"), 'change', function(){
var proportion = parseInt($G("width").value) /parseInt($G("height").value);
From c036aa821f5015dc3c300fc8a3cdc50df862edad Mon Sep 17 00:00:00 2001
From: Phinome
Date: Tue, 13 Jun 2017 23:00:05 +0800
Subject: [PATCH 12/33] prettier format file
---
Gruntfile.js | 552 ++--
_parse/background.js | 31 +-
_parse/charts.js | 553 ++--
_parse/insertcode.js | 85 +-
_parse/list.js | 315 +-
_parse/parse.js | 676 ++--
_parse/table.js | 348 +-
_parse/video.js | 64 +-
_src/adapter/autosave.js | 31 +-
_src/adapter/editor.js | 1758 +++++-----
_src/adapter/editorui.js | 1780 +++++-----
_src/adapter/message.js | 115 +-
_src/api.js | 2 +-
_src/core/Editor.defaultoptions.js | 59 +-
_src/core/Editor.js | 3197 +++++++++---------
_src/core/EventBase.js | 337 +-
_src/core/Range.js | 3833 ++++++++++-----------
_src/core/Selection.js | 806 ++---
_src/core/ajax.js | 540 +--
_src/core/browser.js | 521 +--
_src/core/domUtils.js | 4961 ++++++++++++++--------------
_src/core/dtd.js | 613 +++-
_src/core/filternode.js | 256 +-
_src/core/filterword.js | 415 +--
_src/core/htmlparser.js | 385 ++-
_src/core/keymap.js | 70 +-
_src/core/loadconfig.js | 118 +-
_src/core/localstorage.js | 239 +-
_src/core/node.js | 946 +++---
_src/core/plugin.js | 140 +-
_src/core/utils.js | 2468 +++++++-------
_src/editor.js | 30 +-
_src/plugins/anchor.js | 186 +-
_src/plugins/autofloat.js | 283 +-
_src/plugins/autoheight.js | 244 +-
_src/plugins/autolink.js | 395 ++-
_src/plugins/autosave.js | 230 +-
_src/plugins/autosubmit.js | 78 +-
_src/plugins/autotypeset.js | 675 ++--
_src/plugins/autoupload.js | 378 ++-
_src/plugins/background.js | 237 +-
_src/plugins/basestyle.js | 300 +-
_src/plugins/blockquote.js | 360 +-
_src/plugins/catchremoteimage.js | 224 +-
_src/plugins/charts.js | 227 +-
_src/plugins/cleardoc.js | 72 +-
_src/plugins/contextmenu.js | 1032 +++---
_src/plugins/convertcase.js | 113 +-
_src/plugins/copy.js | 137 +-
_src/plugins/customstyle.js | 327 +-
_src/plugins/defaultfilter.js | 523 +--
_src/plugins/directionality.js | 253 +-
_src/plugins/dragdrop.js | 121 +-
_src/plugins/elementpath.js | 85 +-
_src/plugins/enterkey.js | 375 ++-
_src/plugins/fiximgclick.js | 625 ++--
_src/plugins/font.js | 771 ++---
_src/plugins/formatmatch.js | 205 +-
_src/plugins/horizontal.js | 168 +-
_src/plugins/iframe.js | 18 +-
_src/plugins/image.js | 390 ++-
_src/plugins/indent.js | 25 +-
_src/plugins/insertcode.js | 1038 +++---
_src/plugins/insertfile.js | 143 +-
_src/plugins/inserthtml.js | 441 +--
_src/plugins/insertparagraph.js | 47 +-
_src/plugins/justify.js | 171 +-
_src/plugins/keystrokes.js | 459 +--
_src/plugins/lineheight.js | 43 +-
_src/plugins/link.js | 266 +-
_src/plugins/list.js | 2402 +++++++-------
_src/plugins/music.js | 146 +-
_src/plugins/pagebreak.js | 285 +-
_src/plugins/paragraph.js | 306 +-
_src/plugins/paste.js | 576 ++--
_src/plugins/preview.js | 30 +-
_src/plugins/print.js | 11 +-
_src/plugins/puretxtpaste.js | 149 +-
_src/plugins/removeformat.js | 321 +-
_src/plugins/rowspacing.js | 55 +-
_src/plugins/scrawl.js | 8 +-
_src/plugins/searchreplace.js | 408 +--
_src/plugins/section.js | 522 +--
_src/plugins/selectall.js | 48 +-
_src/plugins/serverparam.js | 65 +-
_src/plugins/shortcutmenu.js | 110 +-
_src/plugins/simpleupload.js | 368 ++-
_src/plugins/snapscreen.js | 157 +-
_src/plugins/source.js | 530 +--
_src/plugins/table.action.js | 3434 ++++++++++---------
_src/plugins/table.cmds.js | 1853 ++++++-----
_src/plugins/table.core.js | 2276 +++++++------
_src/plugins/table.sort.js | 320 +-
_src/plugins/template.js | 62 +-
_src/plugins/time.js | 47 +-
_src/plugins/undo.js | 528 +--
_src/plugins/video.js | 229 +-
_src/plugins/webapp.js | 170 +-
_src/plugins/wordcount.js | 44 +-
_src/plugins/wordimage.js | 91 +-
_src/ui/autotypesetbutton.js | 249 +-
_src/ui/autotypesetpicker.js | 224 +-
_src/ui/breakline.js | 35 +-
_src/ui/button.js | 139 +-
_src/ui/cellalignpicker.js | 175 +-
_src/ui/colorbutton.js | 109 +-
_src/ui/colorpicker.js | 158 +-
_src/ui/combox.js | 179 +-
_src/ui/dialog.js | 843 ++---
_src/ui/mask.js | 100 +-
_src/ui/menu.js | 520 +--
_src/ui/menubutton.js | 69 +-
_src/ui/message.js | 145 +-
_src/ui/multiMenu.js | 72 +-
_src/ui/pastepicker.js | 125 +-
_src/ui/popup.js | 509 +--
_src/ui/separator.js | 35 +-
_src/ui/shortcutmenu.js | 461 +--
_src/ui/splitbutton.js | 178 +-
_src/ui/stateful.js | 216 +-
_src/ui/tablebutton.js | 61 +-
_src/ui/tablepicker.js | 179 +-
_src/ui/toolbar.js | 96 +-
_src/ui/ui.js | 2 +-
_src/ui/uibase.js | 155 +-
_src/ui/uiutils.js | 514 +--
ueditor.config.js | 940 +++---
ueditor.parse.js | 115 +-
128 files changed, 31794 insertions(+), 28269 deletions(-)
diff --git a/Gruntfile.js b/Gruntfile.js
index fc95f2c5d..6a2d90c75 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,277 +1,303 @@
-'use strict';
-
-module.exports = function (grunt) {
-
- var fs = require("fs"),
- Util = {
-
- jsBasePath: '_src/',
- parseBasePath: '_parse/',
- cssBasePath: 'themes/default/_css/',
-
- fetchScripts: function (readFile, basePath) {
-
- var sources = fs.readFileSync(readFile);
- sources = /\[([^\]]+\.js'[^\]]+)\]/.exec(sources);
- sources = sources[1].replace(/\/\/.*\n/g, '\n').replace(/'|"|\n|\t|\s/g, '');
- sources = sources.split(",");
- sources.forEach(function (filepath, index) {
- sources[ index ] = basePath + filepath;
- });
-
- return sources;
- },
-
- fetchStyles: function () {
-
- var sources = fs.readFileSync(this.cssBasePath + "ueditor.css"),
- filepath = null,
- pattern = /@import\s+([^;]+)*;/g,
- src = [];
-
- while (filepath = pattern.exec(sources)) {
- src.push(this.cssBasePath + filepath[ 1 ].replace(/'|"/g, ""));
- }
-
- return src;
-
- }
+"use strict";
+
+module.exports = function(grunt) {
+ var fs = require("fs"),
+ Util = {
+ jsBasePath: "_src/",
+ parseBasePath: "_parse/",
+ cssBasePath: "themes/default/_css/",
+
+ fetchScripts: function(readFile, basePath) {
+ var sources = fs.readFileSync(readFile);
+ sources = /\[([^\]]+\.js'[^\]]+)\]/.exec(sources);
+ sources = sources[1]
+ .replace(/\/\/.*\n/g, "\n")
+ .replace(/'|"|\n|\t|\s/g, "");
+ sources = sources.split(",");
+ sources.forEach(function(filepath, index) {
+ sources[index] = basePath + filepath;
+ });
+
+ return sources;
+ },
+
+ fetchStyles: function() {
+ var sources = fs.readFileSync(this.cssBasePath + "ueditor.css"),
+ filepath = null,
+ pattern = /@import\s+([^;]+)*;/g,
+ src = [];
+
+ while ((filepath = pattern.exec(sources))) {
+ src.push(this.cssBasePath + filepath[1].replace(/'|"/g, ""));
+ }
+ return src;
+ }
+ },
+ packageJson = grunt.file.readJSON("package.json"),
+ server = grunt.option("server") || "php",
+ encode = grunt.option("encode") || "utf8",
+ disDir = "dist/",
+ banner =
+ "/*!\n * " +
+ packageJson.name +
+ "\n * version: " +
+ packageJson.version +
+ "\n * build: <%= new Date() %>\n */\n\n";
+
+ //init
+ (function() {
+ server = typeof server === "string" ? server.toLowerCase() : "php";
+ encode = typeof encode === "string" ? encode.toLowerCase() : "utf8";
+
+ disDir = "dist/" + encode + "-" + server + "/";
+ })();
+
+ grunt.initConfig({
+ pkg: packageJson,
+ concat: {
+ js: {
+ options: {
+ banner: "/*!\n * " +
+ packageJson.name +
+ "\n * version: " +
+ packageJson.version +
+ "\n * build: <%= new Date() %>\n */\n\n" +
+ "(function(){\n\n",
+ footer: "\n\n})();\n",
+ process: function(src, s) {
+ var filename = s.substr(s.indexOf("/") + 1);
+ return (
+ "// " + filename + "\n" + src.replace("/_css/", "/css/") + "\n"
+ );
+ }
},
- packageJson = grunt.file.readJSON('package.json'),
- server = grunt.option('server') || 'php',
- encode = grunt.option('encode') || 'utf8',
- disDir = "dist/",
- banner = '/*!\n * ' + packageJson.name + '\n * version: ' + packageJson.version + '\n * build: <%= new Date() %>\n */\n\n';
-
- //init
- (function () {
-
- server = typeof server === "string" ? server.toLowerCase() : 'php';
- encode = typeof encode === "string" ? encode.toLowerCase() : 'utf8';
-
- disDir = 'dist/' + encode + '-' + server + '/';
-
- })();
-
- grunt.initConfig({
- pkg: packageJson,
- concat: {
- js: {
- options: {
- banner: '/*!\n * ' + packageJson.name + '\n * version: ' + packageJson.version + '\n * build: <%= new Date() %>\n */\n\n' +
- '(function(){\n\n',
- footer: '\n\n})();\n',
- process: function (src, s) {
- var filename = s.substr(s.indexOf('/') + 1);
- return '// ' + filename + '\n' + src.replace('/_css/', '/css/') + '\n';
- }
- },
- src: Util.fetchScripts("_examples/editor_api.js", Util.jsBasePath),
- dest: disDir + packageJson.name + '.all.js'
- },
- parse: {
- options: {
- banner: '/*!\n * ' + packageJson.name + ' parse\n * version: ' + packageJson.version + '\n * build: <%= new Date() %>\n */\n\n' +
- '(function(){\n\n',
- footer: '\n\n})();\n'
- },
- src: Util.fetchScripts("ueditor.parse.js", Util.parseBasePath),
- dest: disDir + packageJson.name + '.parse.js'
- },
- css: {
- src: Util.fetchStyles(),
- dest: disDir + 'themes/default/css/ueditor.css'
- }
+ src: Util.fetchScripts("_examples/editor_api.js", Util.jsBasePath),
+ dest: disDir + packageJson.name + ".all.js"
+ },
+ parse: {
+ options: {
+ banner: "/*!\n * " +
+ packageJson.name +
+ " parse\n * version: " +
+ packageJson.version +
+ "\n * build: <%= new Date() %>\n */\n\n" +
+ "(function(){\n\n",
+ footer: "\n\n})();\n"
},
- cssmin: {
- options: {
- banner: banner
- },
- files: {
- expand: true,
- cwd: disDir + 'themes/default/css/',
- src: ['*.css', '!*.min.css'],
- dest: disDir + 'themes/default/css/',
- ext: '.min.css'
- }
+ src: Util.fetchScripts("ueditor.parse.js", Util.parseBasePath),
+ dest: disDir + packageJson.name + ".parse.js"
+ },
+ css: {
+ src: Util.fetchStyles(),
+ dest: disDir + "themes/default/css/ueditor.css"
+ }
+ },
+ cssmin: {
+ options: {
+ banner: banner
+ },
+ files: {
+ expand: true,
+ cwd: disDir + "themes/default/css/",
+ src: ["*.css", "!*.min.css"],
+ dest: disDir + "themes/default/css/",
+ ext: ".min.css"
+ }
+ },
+ uglify: {
+ dist: {
+ options: {
+ banner: "/*!\n * " +
+ packageJson.name +
+ "\n * version: " +
+ packageJson.version +
+ "\n * build: <%= new Date() %>\n */"
},
- uglify: {
- dist: {
- options: {
- banner: '/*!\n * ' + packageJson.name + '\n * version: ' + packageJson.version + '\n * build: <%= new Date() %>\n */'
- },
- src: disDir + '<%= pkg.name %>.all.js',
- dest: disDir + '<%= pkg.name %>.all.min.js'
- },
- parse: {
- options: {
- banner: '/*!\n * ' + packageJson.name + ' parse\n * version: ' + packageJson.version + '\n * build: <%= new Date() %>\n */'
- },
- src: disDir + '<%= pkg.name %>.parse.js',
- dest: disDir + '<%= pkg.name %>.parse.min.js'
- }
+ src: disDir + "<%= pkg.name %>.all.js",
+ dest: disDir + "<%= pkg.name %>.all.min.js"
+ },
+ parse: {
+ options: {
+ banner: "/*!\n * " +
+ packageJson.name +
+ " parse\n * version: " +
+ packageJson.version +
+ "\n * build: <%= new Date() %>\n */"
},
- copy: {
- base: {
- files: [
- {
-
- src: [ '*.html', 'themes/iframe.css', 'themes/default/dialogbase.css', 'themes/default/images/**', 'dialogs/**', 'lang/**', 'third-party/**' ],
- dest: disDir
-
- }
- ]
- },
- demo: {
- files: [
- {
- src: '_examples/completeDemo.html',
- dest: disDir + 'index.html'
- }
- ]
- },
- php: {
-
- expand: true,
- src: 'php/**',
- dest: disDir
-
- },
- asp: {
-
- expand: true,
- src: 'asp/**',
- dest: disDir
-
- },
- jsp: {
-
- expand: true,
- src: 'jsp/**',
- dest: disDir
-
- },
- net: {
-
- expand: true,
- src: 'net/**',
- dest: disDir
-
- }
- },
- transcoding: {
-
- options: {
- charset: encode
- },
- src: [disDir + '**/*.html', disDir + '**/*.js', disDir + '**/*.css', disDir + '**/*.json', disDir + '**/*.jsp', disDir + '**/*.asp']
-
- },
- replace: {
-
- fileEncode: {
- src: [ disDir + '**/*.html', disDir + 'dialogs/**/*.js', disDir + '**/*.css', disDir + '**/*.php', disDir + '**/*.jsp', disDir + '**/*.ashx', disDir + '**/*.asp' ],
- overwrite: true,
- replacements: [
- {
- from: /utf-8/gi,
- to: 'gbk'
- }
- ]
- },
- demo: {
- src: disDir + 'index.html',
- overwrite: true,
- replacements: [
- {
- from: /\.\.\//gi,
- to: ''
- },
- {
- from: 'editor_api.js',
- to: packageJson.name + '.all.min.js'
- }
- ]
- },
- gbkasp: {
- src: [ disDir + 'asp/*.asp' ],
- overwrite: true,
- replacements: [
- {
- from: /65001/gi,
- to: '936'
- }
- ]
- }
-
- },
- clean: {
- build: {
- src: [
- disDir + "jsp/src",
- disDir + "*/upload",
- disDir + ".DS_Store",
- disDir + "**/.DS_Store",
- disDir + ".git",
- disDir + "**/.git"
- ]
- }
- }
-
- });
-
- grunt.loadNpmTasks('grunt-text-replace');
- grunt.loadNpmTasks('grunt-contrib-concat');
- grunt.loadNpmTasks('grunt-contrib-cssmin');
- grunt.loadNpmTasks('grunt-contrib-uglify');
- grunt.loadNpmTasks('grunt-contrib-copy');
- grunt.loadNpmTasks('grunt-transcoding');
- grunt.loadNpmTasks('grunt-contrib-clean');
-
- grunt.registerTask('default', 'UEditor build', function () {
-
- var tasks = [ 'concat', 'cssmin', 'uglify', 'copy:base', 'copy:' + server, 'copy:demo', 'replace:demo', 'clean' ];
-
- if (encode === 'gbk') {
- tasks.push('replace:fileEncode');
- if (server === 'asp') {
- tasks.push('replace:gbkasp');
- }
- }
-
- tasks.push('transcoding');
-
- //config修改
- updateConfigFile();
-
- grunt.task.run(tasks);
-
- });
-
-
- function updateConfigFile() {
-
- var filename = 'ueditor.config.js',
- file = grunt.file.read(filename),
- path = server + "/",
- suffix = server === "net" ? ".ashx" : "." + server;
+ src: disDir + "<%= pkg.name %>.parse.js",
+ dest: disDir + "<%= pkg.name %>.parse.min.js"
+ }
+ },
+ copy: {
+ base: {
+ files: [
+ {
+ src: [
+ "*.html",
+ "themes/iframe.css",
+ "themes/default/dialogbase.css",
+ "themes/default/images/**",
+ "dialogs/**",
+ "lang/**",
+ "third-party/**"
+ ],
+ dest: disDir
+ }
+ ]
+ },
+ demo: {
+ files: [
+ {
+ src: "_examples/completeDemo.html",
+ dest: disDir + "index.html"
+ }
+ ]
+ },
+ php: {
+ expand: true,
+ src: "php/**",
+ dest: disDir
+ },
+ asp: {
+ expand: true,
+ src: "asp/**",
+ dest: disDir
+ },
+ jsp: {
+ expand: true,
+ src: "jsp/**",
+ dest: disDir
+ },
+ net: {
+ expand: true,
+ src: "net/**",
+ dest: disDir
+ }
+ },
+ transcoding: {
+ options: {
+ charset: encode
+ },
+ src: [
+ disDir + "**/*.html",
+ disDir + "**/*.js",
+ disDir + "**/*.css",
+ disDir + "**/*.json",
+ disDir + "**/*.jsp",
+ disDir + "**/*.asp"
+ ]
+ },
+ replace: {
+ fileEncode: {
+ src: [
+ disDir + "**/*.html",
+ disDir + "dialogs/**/*.js",
+ disDir + "**/*.css",
+ disDir + "**/*.php",
+ disDir + "**/*.jsp",
+ disDir + "**/*.ashx",
+ disDir + "**/*.asp"
+ ],
+ overwrite: true,
+ replacements: [
+ {
+ from: /utf-8/gi,
+ to: "gbk"
+ }
+ ]
+ },
+ demo: {
+ src: disDir + "index.html",
+ overwrite: true,
+ replacements: [
+ {
+ from: /\.\.\//gi,
+ to: ""
+ },
+ {
+ from: "editor_api.js",
+ to: packageJson.name + ".all.min.js"
+ }
+ ]
+ },
+ gbkasp: {
+ src: [disDir + "asp/*.asp"],
+ overwrite: true,
+ replacements: [
+ {
+ from: /65001/gi,
+ to: "936"
+ }
+ ]
+ }
+ },
+ clean: {
+ build: {
+ src: [
+ disDir + "jsp/src",
+ disDir + "*/upload",
+ disDir + ".DS_Store",
+ disDir + "**/.DS_Store",
+ disDir + ".git",
+ disDir + "**/.git"
+ ]
+ }
+ }
+ });
+
+ grunt.loadNpmTasks("grunt-text-replace");
+ grunt.loadNpmTasks("grunt-contrib-concat");
+ grunt.loadNpmTasks("grunt-contrib-cssmin");
+ grunt.loadNpmTasks("grunt-contrib-uglify");
+ grunt.loadNpmTasks("grunt-contrib-copy");
+ grunt.loadNpmTasks("grunt-transcoding");
+ grunt.loadNpmTasks("grunt-contrib-clean");
+
+ grunt.registerTask("default", "UEditor build", function() {
+ var tasks = [
+ "concat",
+ "cssmin",
+ "uglify",
+ "copy:base",
+ "copy:" + server,
+ "copy:demo",
+ "replace:demo",
+ "clean"
+ ];
+
+ if (encode === "gbk") {
+ tasks.push("replace:fileEncode");
+ if (server === "asp") {
+ tasks.push("replace:gbkasp");
+ }
+ }
- file = file.replace(/php\//ig, path).replace(/\.php/ig, suffix);
+ tasks.push("transcoding");
- if (encode == 'gbk') {
- file = file.replace(/utf-8/gi, 'gbk');
- }
+ //config修改
+ updateConfigFile();
- //写入到dist
- if (grunt.file.write(disDir + filename, file)) {
+ grunt.task.run(tasks);
+ });
- grunt.log.writeln('config file update success');
+ function updateConfigFile() {
+ var filename = "ueditor.config.js",
+ file = grunt.file.read(filename),
+ path = server + "/",
+ suffix = server === "net" ? ".ashx" : "." + server;
- } else {
- grunt.log.warn('config file update error');
- }
+ file = file.replace(/php\//ig, path).replace(/\.php/ig, suffix);
+ if (encode == "gbk") {
+ file = file.replace(/utf-8/gi, "gbk");
}
+ //写入到dist
+ if (grunt.file.write(disDir + filename, file)) {
+ grunt.log.writeln("config file update success");
+ } else {
+ grunt.log.warn("config file update error");
+ }
+ }
};
diff --git a/_parse/background.js b/_parse/background.js
index acc8008ef..246bb0e74 100644
--- a/_parse/background.js
+++ b/_parse/background.js
@@ -1,16 +1,21 @@
-UE.parse.register('background', function (utils) {
- var me = this,
- root = me.root,
- p = root.getElementsByTagName('p'),
- styles;
+UE.parse.register("background", function(utils) {
+ var me = this,
+ root = me.root,
+ p = root.getElementsByTagName("p"),
+ styles;
- for (var i = 0,ci; ci = p[i++];) {
- styles = ci.getAttribute('data-background');
- if (styles){
- ci.parentNode.removeChild(ci);
- }
+ for (var i = 0, ci; (ci = p[i++]); ) {
+ styles = ci.getAttribute("data-background");
+ if (styles) {
+ ci.parentNode.removeChild(ci);
}
+ }
- //追加默认的表格样式
- styles && utils.cssRule('ueditor_background', me.selector + '{' + styles + '}', document);
-});
\ No newline at end of file
+ //追加默认的表格样式
+ styles &&
+ utils.cssRule(
+ "ueditor_background",
+ me.selector + "{" + styles + "}",
+ document
+ );
+});
diff --git a/_parse/charts.js b/_parse/charts.js
index c1339aee2..5dbf41a84 100644
--- a/_parse/charts.js
+++ b/_parse/charts.js
@@ -1,337 +1,288 @@
-UE.parse.register('charts',function( utils ){
-
- utils.cssRule('chartsContainerHeight','.edui-chart-container { height:'+(this.chartContainerHeight||300)+'px}');
- var resourceRoot = this.rootPath,
- containers = this.root,
- sources = null;
-
- //不存在指定的根路径, 则直接退出
- if ( !resourceRoot ) {
- return;
+UE.parse.register("charts", function(utils) {
+ utils.cssRule(
+ "chartsContainerHeight",
+ ".edui-chart-container { height:" +
+ (this.chartContainerHeight || 300) +
+ "px}"
+ );
+ var resourceRoot = this.rootPath,
+ containers = this.root,
+ sources = null;
+
+ //不存在指定的根路径, 则直接退出
+ if (!resourceRoot) {
+ return;
+ }
+
+ if ((sources = parseSources())) {
+ loadResources();
+ }
+
+ function parseSources() {
+ if (!containers) {
+ return null;
}
- if ( sources = parseSources() ) {
-
- loadResources();
-
- }
-
-
- function parseSources () {
+ return extractChartData(containers);
+ }
- if ( !containers ) {
- return null;
- }
-
- return extractChartData( containers );
-
- }
-
- /**
+ /**
* 提取数据
*/
- function extractChartData ( rootNode ) {
-
- var data = [],
- tables = rootNode.getElementsByTagName( "table" );
-
- for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) {
-
- if ( tableNode.getAttribute( "data-chart" ) !== null ) {
-
- data.push( formatData( tableNode ) );
-
- }
-
- }
-
- return data.length ? data : null;
-
+ function extractChartData(rootNode) {
+ var data = [],
+ tables = rootNode.getElementsByTagName("table");
+
+ for (var i = 0, tableNode; (tableNode = tables[i]); i++) {
+ if (tableNode.getAttribute("data-chart") !== null) {
+ data.push(formatData(tableNode));
+ }
}
- function formatData ( tableNode ) {
-
- var meta = tableNode.getAttribute( "data-chart" ),
- metaConfig = {},
- data = [];
+ return data.length ? data : null;
+ }
- //提取table数据
- for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) {
+ function formatData(tableNode) {
+ var meta = tableNode.getAttribute("data-chart"),
+ metaConfig = {},
+ data = [];
- var rowData = [];
+ //提取table数据
+ for (var i = 0, row; (row = tableNode.rows[i]); i++) {
+ var rowData = [];
- for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {
-
- var value = ( cell.innerText || cell.textContent || '' );
- rowData.push( cell.tagName == 'TH' ? value:(value | 0) );
-
- }
-
- data.push( rowData );
-
- }
-
- //解析元信息
- meta = meta.split( ";" );
- for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) {
-
- metaData = metaData.split( ":" );
- metaConfig[ metaData[ 0 ] ] = metaData[ 1 ];
-
- }
-
-
- return {
- table: tableNode,
- meta: metaConfig,
- data: data
- };
+ for (var j = 0, cell; (cell = row.cells[j]); j++) {
+ var value = cell.innerText || cell.textContent || "";
+ rowData.push(cell.tagName == "TH" ? value : value | 0);
+ }
+ data.push(rowData);
}
- //加载资源
- function loadResources () {
-
- loadJQuery();
-
+ //解析元信息
+ meta = meta.split(";");
+ for (var i = 0, metaData; (metaData = meta[i]); i++) {
+ metaData = metaData.split(":");
+ metaConfig[metaData[0]] = metaData[1];
}
- function loadJQuery () {
-
- //不存在jquery, 则加载jquery
- if ( !window.jQuery ) {
-
- utils.loadFile(document,{
- src : resourceRoot + "/third-party/jquery-1.10.2.min.js",
- tag : "script",
- type : "text/javascript",
- defer : "defer"
- },function(){
-
- loadHighcharts();
-
- });
-
- } else {
-
- loadHighcharts();
-
+ return {
+ table: tableNode,
+ meta: metaConfig,
+ data: data
+ };
+ }
+
+ //加载资源
+ function loadResources() {
+ loadJQuery();
+ }
+
+ function loadJQuery() {
+ //不存在jquery, 则加载jquery
+ if (!window.jQuery) {
+ utils.loadFile(
+ document,
+ {
+ src: resourceRoot + "/third-party/jquery-1.10.2.min.js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ loadHighcharts();
}
-
+ );
+ } else {
+ loadHighcharts();
}
-
- function loadHighcharts () {
-
- //不存在Highcharts, 则加载Highcharts
- if ( !window.Highcharts ) {
-
- utils.loadFile(document,{
- src : resourceRoot + "/third-party/highcharts/highcharts.js",
- tag : "script",
- type : "text/javascript",
- defer : "defer"
- },function(){
-
- loadTypeConfig();
-
- });
-
- } else {
-
- loadTypeConfig();
-
+ }
+
+ function loadHighcharts() {
+ //不存在Highcharts, 则加载Highcharts
+ if (!window.Highcharts) {
+ utils.loadFile(
+ document,
+ {
+ src: resourceRoot + "/third-party/highcharts/highcharts.js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ loadTypeConfig();
}
-
+ );
+ } else {
+ loadTypeConfig();
}
-
- //加载图表差异化配置文件
- function loadTypeConfig () {
-
- utils.loadFile(document,{
- src : resourceRoot + "/dialogs/charts/chart.config.js",
- tag : "script",
- type : "text/javascript",
- defer : "defer"
- },function(){
-
- render();
-
- });
-
+ }
+
+ //加载图表差异化配置文件
+ function loadTypeConfig() {
+ utils.loadFile(
+ document,
+ {
+ src: resourceRoot + "/dialogs/charts/chart.config.js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ render();
+ }
+ );
+ }
+
+ //渲染图表
+ function render() {
+ var config = null,
+ chartConfig = null,
+ container = null;
+
+ for (var i = 0, len = sources.length; i < len; i++) {
+ config = sources[i];
+
+ chartConfig = analysisConfig(config);
+
+ container = createContainer(config.table);
+
+ renderChart(container, typeConfig[config.meta.chartType], chartConfig);
}
+ }
- //渲染图表
- function render () {
-
- var config = null,
- chartConfig = null,
- container = null;
-
- for ( var i = 0, len = sources.length; i < len; i++ ) {
-
- config = sources[ i ];
-
- chartConfig = analysisConfig( config );
-
- container = createContainer( config.table );
-
- renderChart( container, typeConfig[ config.meta.chartType ], chartConfig );
-
- }
-
-
- }
-
- /**
+ /**
* 渲染图表
* @param container 图表容器节点对象
* @param typeConfig 图表类型配置
* @param config 图表通用配置
* */
- function renderChart ( container, typeConfig, config ) {
-
-
- $( container ).highcharts( $.extend( {}, typeConfig, {
-
- credits: {
- enabled: false
- },
- exporting: {
- enabled: false
- },
- title: {
- text: config.title,
- x: -20 //center
- },
- subtitle: {
- text: config.subTitle,
- x: -20
- },
- xAxis: {
- title: {
- text: config.xTitle
- },
- categories: config.categories
- },
- yAxis: {
- title: {
- text: config.yTitle
- },
- plotLines: [{
- value: 0,
- width: 1,
- color: '#808080'
- }]
- },
- tooltip: {
- enabled: true,
- valueSuffix: config.suffix
- },
- legend: {
- layout: 'vertical',
- align: 'right',
- verticalAlign: 'middle',
- borderWidth: 1
- },
- series: config.series
-
- } ));
-
- }
-
- /**
+ function renderChart(container, typeConfig, config) {
+ $(container).highcharts(
+ $.extend({}, typeConfig, {
+ credits: {
+ enabled: false
+ },
+ exporting: {
+ enabled: false
+ },
+ title: {
+ text: config.title,
+ x: -20 //center
+ },
+ subtitle: {
+ text: config.subTitle,
+ x: -20
+ },
+ xAxis: {
+ title: {
+ text: config.xTitle
+ },
+ categories: config.categories
+ },
+ yAxis: {
+ title: {
+ text: config.yTitle
+ },
+ plotLines: [
+ {
+ value: 0,
+ width: 1,
+ color: "#808080"
+ }
+ ]
+ },
+ tooltip: {
+ enabled: true,
+ valueSuffix: config.suffix
+ },
+ legend: {
+ layout: "vertical",
+ align: "right",
+ verticalAlign: "middle",
+ borderWidth: 1
+ },
+ series: config.series
+ })
+ );
+ }
+
+ /**
* 创建图表的容器
* 新创建的容器会替换掉对应的table对象
* */
- function createContainer ( tableNode ) {
-
- var container = document.createElement( "div" );
- container.className = "edui-chart-container";
-
- tableNode.parentNode.replaceChild( container, tableNode );
-
- return container;
-
- }
-
- //根据config解析出正确的类别和图表数据信息
- function analysisConfig ( config ) {
-
- var series = [],
- //数据类别
- categories = [],
- result = [],
- data = config.data,
- meta = config.meta;
-
- //数据对齐方式为相反的方式, 需要反转数据
- if ( meta.dataFormat != "1" ) {
-
- for ( var i = 0, len = data.length; i < len ; i++ ) {
-
- for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) {
-
- if ( !result[ j ] ) {
- result[ j ] = [];
- }
-
- result[ j ][ i ] = data[ i ][ j ];
-
- }
-
- }
-
- data = result;
-
+ function createContainer(tableNode) {
+ var container = document.createElement("div");
+ container.className = "edui-chart-container";
+
+ tableNode.parentNode.replaceChild(container, tableNode);
+
+ return container;
+ }
+
+ //根据config解析出正确的类别和图表数据信息
+ function analysisConfig(config) {
+ var series = [],
+ //数据类别
+ categories = [],
+ result = [],
+ data = config.data,
+ meta = config.meta;
+
+ //数据对齐方式为相反的方式, 需要反转数据
+ if (meta.dataFormat != "1") {
+ for (var i = 0, len = data.length; i < len; i++) {
+ for (var j = 0, jlen = data[i].length; j < jlen; j++) {
+ if (!result[j]) {
+ result[j] = [];
+ }
+
+ result[j][i] = data[i][j];
}
+ }
- result = {};
-
- //普通图表
- if ( meta.chartType != typeConfig.length - 1 ) {
-
- categories = data[ 0 ].slice( 1 );
-
- for ( var i = 1, curData; curData = data[ i ]; i++ ) {
- series.push( {
- name: curData[ 0 ],
- data: curData.slice( 1 )
- } );
- }
-
- result.series = series;
- result.categories = categories;
- result.title = meta.title;
- result.subTitle = meta.subTitle;
- result.xTitle = meta.xTitle;
- result.yTitle = meta.yTitle;
- result.suffix = meta.suffix;
-
- } else {
-
- var curData = [];
-
- for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) {
-
- curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] );
-
- }
-
- //饼图
- series[ 0 ] = {
- type: 'pie',
- name: meta.tip,
- data: curData
- };
-
- result.series = series;
- result.title = meta.title;
- result.suffix = meta.suffix;
+ data = result;
+ }
- }
+ result = {};
- return result;
+ //普通图表
+ if (meta.chartType != typeConfig.length - 1) {
+ categories = data[0].slice(1);
+ for (var i = 1, curData; (curData = data[i]); i++) {
+ series.push({
+ name: curData[0],
+ data: curData.slice(1)
+ });
+ }
+
+ result.series = series;
+ result.categories = categories;
+ result.title = meta.title;
+ result.subTitle = meta.subTitle;
+ result.xTitle = meta.xTitle;
+ result.yTitle = meta.yTitle;
+ result.suffix = meta.suffix;
+ } else {
+ var curData = [];
+
+ for (var i = 1, len = data[0].length; i < len; i++) {
+ curData.push([data[0][i], data[1][i] | 0]);
+ }
+
+ //饼图
+ series[0] = {
+ type: "pie",
+ name: meta.tip,
+ data: curData
+ };
+
+ result.series = series;
+ result.title = meta.title;
+ result.suffix = meta.suffix;
}
-});
\ No newline at end of file
+ return result;
+ }
+});
diff --git a/_parse/insertcode.js b/_parse/insertcode.js
index e34b9bc55..cda95a354 100644
--- a/_parse/insertcode.js
+++ b/_parse/insertcode.js
@@ -1,42 +1,49 @@
-UE.parse.register('insertcode',function(utils){
- var pres = this.root.getElementsByTagName('pre');
- if(pres.length){
- if(typeof XRegExp == "undefined"){
- var jsurl,cssurl;
- if(this.rootPath !== undefined){
- jsurl = utils.removeLastbs(this.rootPath) + '/third-party/SyntaxHighlighter/shCore.js';
- cssurl = utils.removeLastbs(this.rootPath) + '/third-party/SyntaxHighlighter/shCoreDefault.css';
- }else{
- jsurl = this.highlightJsUrl;
- cssurl = this.highlightCssUrl;
+UE.parse.register("insertcode", function(utils) {
+ var pres = this.root.getElementsByTagName("pre");
+ if (pres.length) {
+ if (typeof XRegExp == "undefined") {
+ var jsurl, cssurl;
+ if (this.rootPath !== undefined) {
+ jsurl =
+ utils.removeLastbs(this.rootPath) +
+ "/third-party/SyntaxHighlighter/shCore.js";
+ cssurl =
+ utils.removeLastbs(this.rootPath) +
+ "/third-party/SyntaxHighlighter/shCoreDefault.css";
+ } else {
+ jsurl = this.highlightJsUrl;
+ cssurl = this.highlightCssUrl;
+ }
+ utils.loadFile(document, {
+ id: "syntaxhighlighter_css",
+ tag: "link",
+ rel: "stylesheet",
+ type: "text/css",
+ href: cssurl
+ });
+ utils.loadFile(
+ document,
+ {
+ id: "syntaxhighlighter_js",
+ src: jsurl,
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ utils.each(pres, function(pi) {
+ if (pi && /brush/i.test(pi.className)) {
+ SyntaxHighlighter.highlight(pi);
}
- utils.loadFile(document,{
- id : "syntaxhighlighter_css",
- tag : "link",
- rel : "stylesheet",
- type : "text/css",
- href : cssurl
- });
- utils.loadFile(document,{
- id : "syntaxhighlighter_js",
- src : jsurl,
- tag : "script",
- type : "text/javascript",
- defer : "defer"
- },function(){
- utils.each(pres,function(pi){
- if(pi && /brush/i.test(pi.className)){
- SyntaxHighlighter.highlight(pi);
- }
- });
- });
- }else{
- utils.each(pres,function(pi){
- if(pi && /brush/i.test(pi.className)){
- SyntaxHighlighter.highlight(pi);
- }
- });
+ });
}
+ );
+ } else {
+ utils.each(pres, function(pi) {
+ if (pi && /brush/i.test(pi.className)) {
+ SyntaxHighlighter.highlight(pi);
+ }
+ });
}
-
-});
\ No newline at end of file
+ }
+});
diff --git a/_parse/list.js b/_parse/list.js
index 061b9e8fd..f50541928 100644
--- a/_parse/list.js
+++ b/_parse/list.js
@@ -1,94 +1,235 @@
-UE.parse.register('list',function(utils){
- var customCss = [],
- customStyle = {
- 'cn' : 'cn-1-',
- 'cn1' : 'cn-2-',
- 'cn2' : 'cn-3-',
- 'num' : 'num-1-',
- 'num1' : 'num-2-',
- 'num2' : 'num-3-',
- 'dash' : 'dash',
- 'dot' : 'dot'
- };
+UE.parse.register("list", function(utils) {
+ var customCss = [],
+ customStyle = {
+ cn: "cn-1-",
+ cn1: "cn-2-",
+ cn2: "cn-3-",
+ num: "num-1-",
+ num1: "num-2-",
+ num2: "num-3-",
+ dash: "dash",
+ dot: "dot"
+ };
+ utils.extend(this, {
+ liiconpath: "http://bs.baidu.com/listicon/",
+ listDefaultPaddingLeft: "20"
+ });
- utils.extend(this,{
- liiconpath : 'http://bs.baidu.com/listicon/',
- listDefaultPaddingLeft : '20'
- });
-
- var root = this.root,
- ols = root.getElementsByTagName('ol'),
- uls = root.getElementsByTagName('ul'),
- selector = this.selector;
-
- if(ols.length){
- applyStyle.call(this,ols);
- }
+ var root = this.root,
+ ols = root.getElementsByTagName("ol"),
+ uls = root.getElementsByTagName("ul"),
+ selector = this.selector;
- if(uls.length){
- applyStyle.call(this,uls);
- }
+ if (ols.length) {
+ applyStyle.call(this, ols);
+ }
- if(ols.length || uls.length){
- customCss.push(selector +' .list-paddingleft-1{padding-left:0}');
- customCss.push(selector +' .list-paddingleft-2{padding-left:'+ this.listDefaultPaddingLeft+'px}');
- customCss.push(selector +' .list-paddingleft-3{padding-left:'+ this.listDefaultPaddingLeft*2+'px}');
+ if (uls.length) {
+ applyStyle.call(this, uls);
+ }
- utils.cssRule('list', selector +' ol,'+selector +' ul{margin:0;padding:0;}\n' + selector + ' li{clear:both;}\n'+customCss.join('\n'), document);
- }
- function applyStyle(nodes){
- var T = this;
- utils.each(nodes,function(list){
- if(list.className && /custom_/i.test(list.className)){
- var listStyle = list.className.match(/custom_(\w+)/)[1];
- if(listStyle == 'dash' || listStyle == 'dot'){
- utils.pushItem(customCss,selector +' li.list-' + customStyle[listStyle] + '{background-image:url(' + T.liiconpath +customStyle[listStyle]+'.gif)}');
- utils.pushItem(customCss,selector +' ul.custom_'+listStyle+'{list-style:none;} '+ selector +' ul.custom_'+listStyle+' li{background-position:0 3px;background-repeat:no-repeat}');
+ if (ols.length || uls.length) {
+ customCss.push(selector + " .list-paddingleft-1{padding-left:0}");
+ customCss.push(
+ selector +
+ " .list-paddingleft-2{padding-left:" +
+ this.listDefaultPaddingLeft +
+ "px}"
+ );
+ customCss.push(
+ selector +
+ " .list-paddingleft-3{padding-left:" +
+ this.listDefaultPaddingLeft * 2 +
+ "px}"
+ );
- }else{
- var index = 1;
- utils.each(list.childNodes,function(li){
- if(li.tagName == 'LI'){
- utils.pushItem(customCss,selector + ' li.list-' + customStyle[listStyle] + index + '{background-image:url(' + T.liiconpath + 'list-'+customStyle[listStyle] +index + '.gif)}');
- index++;
- }
- });
- utils.pushItem(customCss,selector + ' ol.custom_'+listStyle+'{list-style:none;}'+selector+' ol.custom_'+listStyle+' li{background-position:0 3px;background-repeat:no-repeat}');
- }
- switch(listStyle){
- case 'cn':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:25px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:55px}');
- break;
- case 'cn1':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:30px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:55px}');
- break;
- case 'cn2':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:40px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:55px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-3{padding-left:68px}');
- break;
- case 'num':
- case 'num1':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:25px}');
- break;
- case 'num2':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-1{padding-left:35px}');
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft-2{padding-left:40px}');
- break;
- case 'dash':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft{padding-left:35px}');
- break;
- case 'dot':
- utils.pushItem(customCss,selector + ' li.list-'+listStyle+'-paddingleft{padding-left:20px}');
- }
+ utils.cssRule(
+ "list",
+ selector +
+ " ol," +
+ selector +
+ " ul{margin:0;padding:0;}\n" +
+ selector +
+ " li{clear:both;}\n" +
+ customCss.join("\n"),
+ document
+ );
+ }
+ function applyStyle(nodes) {
+ var T = this;
+ utils.each(nodes, function(list) {
+ if (list.className && /custom_/i.test(list.className)) {
+ var listStyle = list.className.match(/custom_(\w+)/)[1];
+ if (listStyle == "dash" || listStyle == "dot") {
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ customStyle[listStyle] +
+ "{background-image:url(" +
+ T.liiconpath +
+ customStyle[listStyle] +
+ ".gif)}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " ul.custom_" +
+ listStyle +
+ "{list-style:none;} " +
+ selector +
+ " ul.custom_" +
+ listStyle +
+ " li{background-position:0 3px;background-repeat:no-repeat}"
+ );
+ } else {
+ var index = 1;
+ utils.each(list.childNodes, function(li) {
+ if (li.tagName == "LI") {
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ customStyle[listStyle] +
+ index +
+ "{background-image:url(" +
+ T.liiconpath +
+ "list-" +
+ customStyle[listStyle] +
+ index +
+ ".gif)}"
+ );
+ index++;
}
- });
- }
-
-
-});
\ No newline at end of file
+ });
+ utils.pushItem(
+ customCss,
+ selector +
+ " ol.custom_" +
+ listStyle +
+ "{list-style:none;}" +
+ selector +
+ " ol.custom_" +
+ listStyle +
+ " li{background-position:0 3px;background-repeat:no-repeat}"
+ );
+ }
+ switch (listStyle) {
+ case "cn":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-1{padding-left:25px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-2{padding-left:40px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-3{padding-left:55px}"
+ );
+ break;
+ case "cn1":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-1{padding-left:30px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-2{padding-left:40px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-3{padding-left:55px}"
+ );
+ break;
+ case "cn2":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-1{padding-left:40px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-2{padding-left:55px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-3{padding-left:68px}"
+ );
+ break;
+ case "num":
+ case "num1":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-1{padding-left:25px}"
+ );
+ break;
+ case "num2":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-1{padding-left:35px}"
+ );
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft-2{padding-left:40px}"
+ );
+ break;
+ case "dash":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft{padding-left:35px}"
+ );
+ break;
+ case "dot":
+ utils.pushItem(
+ customCss,
+ selector +
+ " li.list-" +
+ listStyle +
+ "-paddingleft{padding-left:20px}"
+ );
+ }
+ }
+ });
+ }
+});
diff --git a/_parse/parse.js b/_parse/parse.js
index fe1275507..4c377e66c 100644
--- a/_parse/parse.js
+++ b/_parse/parse.js
@@ -1,327 +1,365 @@
-(function(){
- UE = window.UE || {};
- var isIE = !!window.ActiveXObject;
- //定义utils工具
- var utils = {
- removeLastbs : function(url){
- return url.replace(/\/$/,'')
- },
- extend : function(t,s){
- var a = arguments,
- notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false,
- len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length;
- for (var i = 1; i < len; i++) {
- var x = a[i];
- for (var k in x) {
- if (!notCover || !t.hasOwnProperty(k)) {
- t[k] = x[k];
- }
- }
- }
- return t;
- },
- isIE : isIE,
- cssRule : isIE ? function(key,style,doc){
- var indexList,index;
- doc = doc || document;
- if(doc.indexList){
- indexList = doc.indexList;
- }else{
- indexList = doc.indexList = {};
- }
- var sheetStyle;
- if(!indexList[key]){
- if(style === undefined){
- return ''
- }
- sheetStyle = doc.createStyleSheet('',index = doc.styleSheets.length);
- indexList[key] = index;
- }else{
- sheetStyle = doc.styleSheets[indexList[key]];
- }
- if(style === undefined){
- return sheetStyle.cssText
- }
- sheetStyle.cssText = sheetStyle.cssText + '\n' + (style || '')
- } : function(key,style,doc){
- doc = doc || document;
- var head = doc.getElementsByTagName('head')[0],node;
- if(!(node = doc.getElementById(key))){
- if(style === undefined){
- return ''
- }
- node = doc.createElement('style');
- node.id = key;
- head.appendChild(node)
- }
- if(style === undefined){
- return node.innerHTML
- }
- if(style !== ''){
- node.innerHTML = node.innerHTML + '\n' + style;
- }else{
- head.removeChild(node)
- }
- },
- domReady : function (onready) {
- var doc = window.document;
- if (doc.readyState === "complete") {
- onready();
- }else{
- if (isIE) {
- (function () {
- if (doc.isReady) return;
- try {
- doc.documentElement.doScroll("left");
- } catch (error) {
- setTimeout(arguments.callee, 0);
- return;
- }
- onready();
- })();
- window.attachEvent('onload', function(){
- onready()
- });
- } else {
- doc.addEventListener("DOMContentLoaded", function () {
- doc.removeEventListener("DOMContentLoaded", arguments.callee, false);
- onready();
- }, false);
- window.addEventListener('load', function(){onready()}, false);
- }
- }
-
- },
- each : function(obj, iterator, context) {
- if (obj == null) return;
- if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if(iterator.call(context, obj[i], i, obj) === false)
- return false;
- }
- } else {
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- if(iterator.call(context, obj[key], key, obj) === false)
- return false;
- }
- }
- }
- },
- inArray : function(arr,item){
- var index = -1;
- this.each(arr,function(v,i){
- if(v === item){
- index = i;
- return false;
- }
- });
- return index;
- },
- pushItem : function(arr,item){
- if(this.inArray(arr,item)==-1){
- arr.push(item)
- }
- },
- trim: function (str) {
- return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, '');
- },
- indexOf: function (array, item, start) {
- var index = -1;
- start = this.isNumber(start) ? start : 0;
- this.each(array, function (v, i) {
- if (i >= start && v === item) {
- index = i;
- return false;
- }
- });
- return index;
- },
- hasClass: function (element, className) {
- className = className.replace(/(^[ ]+)|([ ]+$)/g, '').replace(/[ ]{2,}/g, ' ').split(' ');
- for (var i = 0, ci, cls = element.className; ci = className[i++];) {
- if (!new RegExp('\\b' + ci + '\\b', 'i').test(cls)) {
- return false;
- }
- }
- return i - 1 == className.length;
- },
- addClass:function (elm, classNames) {
- if(!elm)return;
- classNames = this.trim(classNames).replace(/[ ]{2,}/g,' ').split(' ');
- for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){
- if(!new RegExp('\\b' + ci + '\\b').test(cls)){
- cls += ' ' + ci;
- }
- }
- elm.className = utils.trim(cls);
- },
- removeClass:function (elm, classNames) {
- classNames = this.isArray(classNames) ? classNames :
- this.trim(classNames).replace(/[ ]{2,}/g,' ').split(' ');
- for(var i = 0,ci,cls = elm.className;ci=classNames[i++];){
- cls = cls.replace(new RegExp('\\b' + ci + '\\b'),'')
- }
- cls = this.trim(cls).replace(/[ ]{2,}/g,' ');
- elm.className = cls;
- !cls && elm.removeAttribute('className');
- },
- on: function (element, type, handler) {
- var types = this.isArray(type) ? type : type.split(/\s+/),
- k = types.length;
- if (k) while (k--) {
- type = types[k];
- if (element.addEventListener) {
- element.addEventListener(type, handler, false);
- } else {
- if (!handler._d) {
- handler._d = {
- els : []
- };
- }
- var key = type + handler.toString(),index = utils.indexOf(handler._d.els,element);
- if (!handler._d[key] || index == -1) {
- if(index == -1){
- handler._d.els.push(element);
- }
- if(!handler._d[key]){
- handler._d[key] = function (evt) {
- return handler.call(evt.srcElement, evt || window.event);
- };
- }
-
-
- element.attachEvent('on' + type, handler._d[key]);
- }
- }
- }
- element = null;
+(function() {
+ UE = window.UE || {};
+ var isIE = !!window.ActiveXObject;
+ //定义utils工具
+ var utils = {
+ removeLastbs: function(url) {
+ return url.replace(/\/$/, "");
+ },
+ extend: function(t, s) {
+ var a = arguments,
+ notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false,
+ len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length;
+ for (var i = 1; i < len; i++) {
+ var x = a[i];
+ for (var k in x) {
+ if (!notCover || !t.hasOwnProperty(k)) {
+ t[k] = x[k];
+ }
+ }
+ }
+ return t;
+ },
+ isIE: isIE,
+ cssRule: isIE
+ ? function(key, style, doc) {
+ var indexList, index;
+ doc = doc || document;
+ if (doc.indexList) {
+ indexList = doc.indexList;
+ } else {
+ indexList = doc.indexList = {};
+ }
+ var sheetStyle;
+ if (!indexList[key]) {
+ if (style === undefined) {
+ return "";
+ }
+ sheetStyle = doc.createStyleSheet(
+ "",
+ (index = doc.styleSheets.length)
+ );
+ indexList[key] = index;
+ } else {
+ sheetStyle = doc.styleSheets[indexList[key]];
+ }
+ if (style === undefined) {
+ return sheetStyle.cssText;
+ }
+ sheetStyle.cssText = sheetStyle.cssText + "\n" + (style || "");
+ }
+ : function(key, style, doc) {
+ doc = doc || document;
+ var head = doc.getElementsByTagName("head")[0],
+ node;
+ if (!(node = doc.getElementById(key))) {
+ if (style === undefined) {
+ return "";
+ }
+ node = doc.createElement("style");
+ node.id = key;
+ head.appendChild(node);
+ }
+ if (style === undefined) {
+ return node.innerHTML;
+ }
+ if (style !== "") {
+ node.innerHTML = node.innerHTML + "\n" + style;
+ } else {
+ head.removeChild(node);
+ }
+ },
+ domReady: function(onready) {
+ var doc = window.document;
+ if (doc.readyState === "complete") {
+ onready();
+ } else {
+ if (isIE) {
+ (function() {
+ if (doc.isReady) return;
+ try {
+ doc.documentElement.doScroll("left");
+ } catch (error) {
+ setTimeout(arguments.callee, 0);
+ return;
+ }
+ onready();
+ })();
+ window.attachEvent("onload", function() {
+ onready();
+ });
+ } else {
+ doc.addEventListener(
+ "DOMContentLoaded",
+ function() {
+ doc.removeEventListener(
+ "DOMContentLoaded",
+ arguments.callee,
+ false
+ );
+ onready();
},
- off: function (element, type, handler) {
- var types = this.isArray(type) ? type : type.split(/\s+/),
- k = types.length;
- if (k) while (k--) {
- type = types[k];
- if (element.removeEventListener) {
- element.removeEventListener(type, handler, false);
- } else {
- var key = type + handler.toString();
- try{
- element.detachEvent('on' + type, handler._d ? handler._d[key] : handler);
- }catch(e){}
- if (handler._d && handler._d[key]) {
- var index = utils.indexOf(handler._d.els,element);
- if(index!=-1){
- handler._d.els.splice(index,1);
- }
- handler._d.els.length == 0 && delete handler._d[key];
- }
- }
- }
+ false
+ );
+ window.addEventListener(
+ "load",
+ function() {
+ onready();
},
- loadFile : function () {
- var tmpList = [];
- function getItem(doc,obj){
- try{
- for(var i= 0,ci;ci=tmpList[i++];){
- if(ci.doc === doc && ci.url == (obj.src || obj.href)){
- return ci;
- }
- }
- }catch(e){
- return null;
- }
+ false
+ );
+ }
+ }
+ },
+ each: function(obj, iterator, context) {
+ if (obj == null) return;
+ if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (iterator.call(context, obj[i], i, obj) === false) return false;
+ }
+ } else {
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ if (iterator.call(context, obj[key], key, obj) === false)
+ return false;
+ }
+ }
+ }
+ },
+ inArray: function(arr, item) {
+ var index = -1;
+ this.each(arr, function(v, i) {
+ if (v === item) {
+ index = i;
+ return false;
+ }
+ });
+ return index;
+ },
+ pushItem: function(arr, item) {
+ if (this.inArray(arr, item) == -1) {
+ arr.push(item);
+ }
+ },
+ trim: function(str) {
+ return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, "");
+ },
+ indexOf: function(array, item, start) {
+ var index = -1;
+ start = this.isNumber(start) ? start : 0;
+ this.each(array, function(v, i) {
+ if (i >= start && v === item) {
+ index = i;
+ return false;
+ }
+ });
+ return index;
+ },
+ hasClass: function(element, className) {
+ className = className
+ .replace(/(^[ ]+)|([ ]+$)/g, "")
+ .replace(/[ ]{2,}/g, " ")
+ .split(" ");
+ for (var i = 0, ci, cls = element.className; (ci = className[i++]); ) {
+ if (!new RegExp("\\b" + ci + "\\b", "i").test(cls)) {
+ return false;
+ }
+ }
+ return i - 1 == className.length;
+ },
+ addClass: function(elm, classNames) {
+ if (!elm) return;
+ classNames = this.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
+ for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]); ) {
+ if (!new RegExp("\\b" + ci + "\\b").test(cls)) {
+ cls += " " + ci;
+ }
+ }
+ elm.className = utils.trim(cls);
+ },
+ removeClass: function(elm, classNames) {
+ classNames = this.isArray(classNames)
+ ? classNames
+ : this.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
+ for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]); ) {
+ cls = cls.replace(new RegExp("\\b" + ci + "\\b"), "");
+ }
+ cls = this.trim(cls).replace(/[ ]{2,}/g, " ");
+ elm.className = cls;
+ !cls && elm.removeAttribute("className");
+ },
+ on: function(element, type, handler) {
+ var types = this.isArray(type) ? type : type.split(/\s+/),
+ k = types.length;
+ if (k)
+ while (k--) {
+ type = types[k];
+ if (element.addEventListener) {
+ element.addEventListener(type, handler, false);
+ } else {
+ if (!handler._d) {
+ handler._d = {
+ els: []
+ };
+ }
+ var key = type + handler.toString(),
+ index = utils.indexOf(handler._d.els, element);
+ if (!handler._d[key] || index == -1) {
+ if (index == -1) {
+ handler._d.els.push(element);
+ }
+ if (!handler._d[key]) {
+ handler._d[key] = function(evt) {
+ return handler.call(evt.srcElement, evt || window.event);
+ };
+ }
- }
- return function (doc, obj, fn) {
- var item = getItem(doc,obj);
- if (item) {
- if(item.ready){
- fn && fn();
- }else{
- item.funs.push(fn)
- }
- return;
- }
- tmpList.push({
- doc:doc,
- url:obj.src||obj.href,
- funs:[fn]
- });
- if (!doc.body) {
- var html = [];
- for(var p in obj){
- if(p == 'tag')continue;
- html.push(p + '="' + obj[p] + '"')
- }
- doc.write('<' + obj.tag + ' ' + html.join(' ') + ' >'+obj.tag+'>');
- return;
- }
- if (obj.id && doc.getElementById(obj.id)) {
- return;
- }
- var element = doc.createElement(obj.tag);
- delete obj.tag;
- for (var p in obj) {
- element.setAttribute(p, obj[p]);
- }
- element.onload = element.onreadystatechange = function () {
- if (!this.readyState || /loaded|complete/.test(this.readyState)) {
- item = getItem(doc,obj);
- if (item.funs.length > 0) {
- item.ready = 1;
- for (var fi; fi = item.funs.pop();) {
- fi();
- }
- }
- element.onload = element.onreadystatechange = null;
- }
- };
- element.onerror = function(){
- throw Error('The load '+(obj.href||obj.src)+' fails,check the url')
- };
- doc.getElementsByTagName("head")[0].appendChild(element);
- }
- }()
- };
- utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object','Boolean'], function (v) {
- utils['is' + v] = function (obj) {
- return Object.prototype.toString.apply(obj) == '[object ' + v + ']';
+ element.attachEvent("on" + type, handler._d[key]);
+ }
+ }
}
- });
- var parselist = {};
- UE.parse = {
- register : function(parseName,fn){
- parselist[parseName] = fn;
- },
- load : function(opt){
- utils.each(parselist,function(v){
- v.call(opt,utils);
- })
+ element = null;
+ },
+ off: function(element, type, handler) {
+ var types = this.isArray(type) ? type : type.split(/\s+/),
+ k = types.length;
+ if (k)
+ while (k--) {
+ type = types[k];
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else {
+ var key = type + handler.toString();
+ try {
+ element.detachEvent(
+ "on" + type,
+ handler._d ? handler._d[key] : handler
+ );
+ } catch (e) {}
+ if (handler._d && handler._d[key]) {
+ var index = utils.indexOf(handler._d.els, element);
+ if (index != -1) {
+ handler._d.els.splice(index, 1);
+ }
+ handler._d.els.length == 0 && delete handler._d[key];
+ }
+ }
}
- };
- uParse = function(selector,opt){
- utils.domReady(function(){
- var contents;
- if(document.querySelectorAll){
- contents = document.querySelectorAll(selector)
- }else{
- if(/^#/.test(selector)){
- contents = [document.getElementById(selector.replace(/^#/,''))]
- }else if(/^\./.test(selector)){
- var contents = [];
- utils.each(document.getElementsByTagName('*'),function(node){
- if(node.className && new RegExp('\\b' + selector.replace(/^\./,'') + '\\b','i').test(node.className)){
- contents.push(node)
- }
- })
- }else{
- contents = document.getElementsByTagName(selector)
- }
+ },
+ loadFile: (function() {
+ var tmpList = [];
+ function getItem(doc, obj) {
+ try {
+ for (var i = 0, ci; (ci = tmpList[i++]); ) {
+ if (ci.doc === doc && ci.url == (obj.src || obj.href)) {
+ return ci;
}
- utils.each(contents,function(v){
- UE.parse.load(utils.extend({root:v,selector:selector},opt))
- })
- })
+ }
+ } catch (e) {
+ return null;
+ }
+ }
+ return function(doc, obj, fn) {
+ var item = getItem(doc, obj);
+ if (item) {
+ if (item.ready) {
+ fn && fn();
+ } else {
+ item.funs.push(fn);
+ }
+ return;
+ }
+ tmpList.push({
+ doc: doc,
+ url: obj.src || obj.href,
+ funs: [fn]
+ });
+ if (!doc.body) {
+ var html = [];
+ for (var p in obj) {
+ if (p == "tag") continue;
+ html.push(p + '="' + obj[p] + '"');
+ }
+ doc.write(
+ "<" + obj.tag + " " + html.join(" ") + " >" + obj.tag + ">"
+ );
+ return;
+ }
+ if (obj.id && doc.getElementById(obj.id)) {
+ return;
+ }
+ var element = doc.createElement(obj.tag);
+ delete obj.tag;
+ for (var p in obj) {
+ element.setAttribute(p, obj[p]);
+ }
+ element.onload = element.onreadystatechange = function() {
+ if (!this.readyState || /loaded|complete/.test(this.readyState)) {
+ item = getItem(doc, obj);
+ if (item.funs.length > 0) {
+ item.ready = 1;
+ for (var fi; (fi = item.funs.pop()); ) {
+ fi();
+ }
+ }
+ element.onload = element.onreadystatechange = null;
+ }
+ };
+ element.onerror = function() {
+ throw Error(
+ "The load " + (obj.href || obj.src) + " fails,check the url"
+ );
+ };
+ doc.getElementsByTagName("head")[0].appendChild(element);
+ };
+ })()
+ };
+ utils.each(
+ ["String", "Function", "Array", "Number", "RegExp", "Object", "Boolean"],
+ function(v) {
+ utils["is" + v] = function(obj) {
+ return Object.prototype.toString.apply(obj) == "[object " + v + "]";
+ };
+ }
+ );
+ var parselist = {};
+ UE.parse = {
+ register: function(parseName, fn) {
+ parselist[parseName] = fn;
+ },
+ load: function(opt) {
+ utils.each(parselist, function(v) {
+ v.call(opt, utils);
+ });
}
+ };
+ uParse = function(selector, opt) {
+ utils.domReady(function() {
+ var contents;
+ if (document.querySelectorAll) {
+ contents = document.querySelectorAll(selector);
+ } else {
+ if (/^#/.test(selector)) {
+ contents = [document.getElementById(selector.replace(/^#/, ""))];
+ } else if (/^\./.test(selector)) {
+ var contents = [];
+ utils.each(document.getElementsByTagName("*"), function(node) {
+ if (
+ node.className &&
+ new RegExp("\\b" + selector.replace(/^\./, "") + "\\b", "i").test(
+ node.className
+ )
+ ) {
+ contents.push(node);
+ }
+ });
+ } else {
+ contents = document.getElementsByTagName(selector);
+ }
+ }
+ utils.each(contents, function(v) {
+ UE.parse.load(utils.extend({ root: v, selector: selector }, opt));
+ });
+ });
+ };
})();
diff --git a/_parse/table.js b/_parse/table.js
index 94156c068..fc3333c6f 100644
--- a/_parse/table.js
+++ b/_parse/table.js
@@ -1,161 +1,217 @@
-UE.parse.register('table', function (utils) {
- var me = this,
- root = this.root,
- tables = root.getElementsByTagName('table');
- if (tables.length) {
- var selector = this.selector;
- //追加默认的表格样式
- utils.cssRule('table',
- selector + ' table.noBorderTable td,' +
- selector + ' table.noBorderTable th,' +
- selector + ' table.noBorderTable caption{border:1px dashed #ddd !important}' +
- selector + ' table.sortEnabled tr.firstRow th,' + selector + ' table.sortEnabled tr.firstRow td{padding-right:20px; background-repeat: no-repeat;' +
- 'background-position: center right; background-image:url(' + this.rootPath + 'themes/default/images/sortable.png);}' +
- selector + ' table.sortEnabled tr.firstRow th:hover,' + selector + ' table.sortEnabled tr.firstRow td:hover{background-color: #EEE;}' +
- selector + ' table{margin-bottom:10px;border-collapse:collapse;display:table;}' +
- selector + ' td,' + selector + ' th{padding: 5px 10px;border: 1px solid #DDD;}' +
- selector + ' caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' +
- selector + ' th{border-top:1px solid #BBB;background:#F7F7F7;}' +
- selector + ' table tr.firstRow th{border-top:2px solid #BBB;background:#F7F7F7;}' +
- selector + ' tr.ue-table-interlace-color-single td{ background: #fcfcfc; }' +
- selector + ' tr.ue-table-interlace-color-double td{ background: #f7faff; }' +
- selector + ' td p{margin:0;padding:0;width:auto;height:auto;}',
- document);
- //填充空的单元格
+UE.parse.register("table", function(utils) {
+ var me = this,
+ root = this.root,
+ tables = root.getElementsByTagName("table");
+ if (tables.length) {
+ var selector = this.selector;
+ //追加默认的表格样式
+ utils.cssRule(
+ "table",
+ selector +
+ " table.noBorderTable td," +
+ selector +
+ " table.noBorderTable th," +
+ selector +
+ " table.noBorderTable caption{border:1px dashed #ddd !important}" +
+ selector +
+ " table.sortEnabled tr.firstRow th," +
+ selector +
+ " table.sortEnabled tr.firstRow td{padding-right:20px; background-repeat: no-repeat;" +
+ "background-position: center right; background-image:url(" +
+ this.rootPath +
+ "themes/default/images/sortable.png);}" +
+ selector +
+ " table.sortEnabled tr.firstRow th:hover," +
+ selector +
+ " table.sortEnabled tr.firstRow td:hover{background-color: #EEE;}" +
+ selector +
+ " table{margin-bottom:10px;border-collapse:collapse;display:table;}" +
+ selector +
+ " td," +
+ selector +
+ " th{padding: 5px 10px;border: 1px solid #DDD;}" +
+ selector +
+ " caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}" +
+ selector +
+ " th{border-top:1px solid #BBB;background:#F7F7F7;}" +
+ selector +
+ " table tr.firstRow th{border-top:2px solid #BBB;background:#F7F7F7;}" +
+ selector +
+ " tr.ue-table-interlace-color-single td{ background: #fcfcfc; }" +
+ selector +
+ " tr.ue-table-interlace-color-double td{ background: #f7faff; }" +
+ selector +
+ " td p{margin:0;padding:0;width:auto;height:auto;}",
+ document
+ );
+ //填充空的单元格
- utils.each('td th caption'.split(' '), function (tag) {
- var cells = root.getElementsByTagName(tag);
- cells.length && utils.each(cells, function (node) {
- if (!node.firstChild) {
- node.innerHTML = ' ';
-
- }
- })
+ utils.each("td th caption".split(" "), function(tag) {
+ var cells = root.getElementsByTagName(tag);
+ cells.length &&
+ utils.each(cells, function(node) {
+ if (!node.firstChild) {
+ node.innerHTML = " ";
+ }
});
+ });
- //表格可排序
- var tables = root.getElementsByTagName('table');
- utils.each(tables, function (table) {
- if (/\bsortEnabled\b/.test(table.className)) {
- utils.on(table, 'click', function(e){
- var target = e.target || e.srcElement,
- cell = findParentByTagName(target, ['td', 'th']);
- var table = findParentByTagName(target, 'table'),
- colIndex = utils.indexOf(table.rows[0].cells, cell),
- sortType = table.getAttribute('data-sort-type');
- if(colIndex != -1) {
- sortTable(table, colIndex, me.tableSortCompareFn || sortType);
- updateTable(table);
- }
- });
- }
+ //表格可排序
+ var tables = root.getElementsByTagName("table");
+ utils.each(tables, function(table) {
+ if (/\bsortEnabled\b/.test(table.className)) {
+ utils.on(table, "click", function(e) {
+ var target = e.target || e.srcElement,
+ cell = findParentByTagName(target, ["td", "th"]);
+ var table = findParentByTagName(target, "table"),
+ colIndex = utils.indexOf(table.rows[0].cells, cell),
+ sortType = table.getAttribute("data-sort-type");
+ if (colIndex != -1) {
+ sortTable(table, colIndex, me.tableSortCompareFn || sortType);
+ updateTable(table);
+ }
});
+ }
+ });
- //按照标签名查找父节点
- function findParentByTagName(target, tagNames) {
- var i, current = target;
- tagNames = utils.isArray(tagNames) ? tagNames:[tagNames];
- while(current){
- for(i = 0;i < tagNames.length; i++) {
- if(current.tagName == tagNames[i].toUpperCase()) return current;
- }
- current = current.parentNode;
- }
- return null;
+ //按照标签名查找父节点
+ function findParentByTagName(target, tagNames) {
+ var i,
+ current = target;
+ tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];
+ while (current) {
+ for (i = 0; i < tagNames.length; i++) {
+ if (current.tagName == tagNames[i].toUpperCase()) return current;
}
- //表格排序
- function sortTable(table, sortByCellIndex, compareFn) {
- var rows = table.rows,
- trArray = [],
- flag = rows[0].cells[0].tagName === "TH",
- lastRowIndex = 0;
+ current = current.parentNode;
+ }
+ return null;
+ }
+ //表格排序
+ function sortTable(table, sortByCellIndex, compareFn) {
+ var rows = table.rows,
+ trArray = [],
+ flag = rows[0].cells[0].tagName === "TH",
+ lastRowIndex = 0;
- for (var i = 0,len = rows.length; i < len; i++) {
- trArray[i] = rows[i];
- }
+ for (var i = 0, len = rows.length; i < len; i++) {
+ trArray[i] = rows[i];
+ }
- var Fn = {
- 'reversecurrent': function(td1,td2){
- return 1;
- },
- 'orderbyasc': function(td1,td2){
- var value1 = td1.innerText||td1.textContent,
- value2 = td2.innerText||td2.textContent;
- return value1.localeCompare(value2);
- },
- 'reversebyasc': function(td1,td2){
- var value1 = td1.innerHTML,
- value2 = td2.innerHTML;
- return value2.localeCompare(value1);
- },
- 'orderbynum': function(td1,td2){
- var value1 = td1[utils.isIE ? 'innerText':'textContent'].match(/\d+/),
- value2 = td2[utils.isIE ? 'innerText':'textContent'].match(/\d+/);
- if(value1) value1 = +value1[0];
- if(value2) value2 = +value2[0];
- return (value1||0) - (value2||0);
- },
- 'reversebynum': function(td1,td2){
- var value1 = td1[utils.isIE ? 'innerText':'textContent'].match(/\d+/),
- value2 = td2[utils.isIE ? 'innerText':'textContent'].match(/\d+/);
- if(value1) value1 = +value1[0];
- if(value2) value2 = +value2[0];
- return (value2||0) - (value1||0);
- }
- };
+ var Fn = {
+ reversecurrent: function(td1, td2) {
+ return 1;
+ },
+ orderbyasc: function(td1, td2) {
+ var value1 = td1.innerText || td1.textContent,
+ value2 = td2.innerText || td2.textContent;
+ return value1.localeCompare(value2);
+ },
+ reversebyasc: function(td1, td2) {
+ var value1 = td1.innerHTML,
+ value2 = td2.innerHTML;
+ return value2.localeCompare(value1);
+ },
+ orderbynum: function(td1, td2) {
+ var value1 = td1[utils.isIE ? "innerText" : "textContent"].match(
+ /\d+/
+ ),
+ value2 = td2[utils.isIE ? "innerText" : "textContent"].match(/\d+/);
+ if (value1) value1 = +value1[0];
+ if (value2) value2 = +value2[0];
+ return (value1 || 0) - (value2 || 0);
+ },
+ reversebynum: function(td1, td2) {
+ var value1 = td1[utils.isIE ? "innerText" : "textContent"].match(
+ /\d+/
+ ),
+ value2 = td2[utils.isIE ? "innerText" : "textContent"].match(/\d+/);
+ if (value1) value1 = +value1[0];
+ if (value2) value2 = +value2[0];
+ return (value2 || 0) - (value1 || 0);
+ }
+ };
- //对表格设置排序的标记data-sort-type
- table.setAttribute('data-sort-type', compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn:'');
+ //对表格设置排序的标记data-sort-type
+ table.setAttribute(
+ "data-sort-type",
+ compareFn && typeof compareFn === "string" && Fn[compareFn]
+ ? compareFn
+ : ""
+ );
- //th不参与排序
- flag && trArray.splice(0, 1);
- trArray = sort(trArray,function (tr1, tr2) {
- var result;
- if (compareFn && typeof compareFn === "function") {
- result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
- } else if (compareFn && typeof compareFn === "number") {
- result = 1;
- } else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) {
- result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
- } else {
- result = Fn['orderbyasc'].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
- }
- return result;
- });
- var fragment = table.ownerDocument.createDocumentFragment();
- for (var j = 0, len = trArray.length; j < len; j++) {
- fragment.appendChild(trArray[j]);
- }
- var tbody = table.getElementsByTagName("tbody")[0];
- if(!lastRowIndex){
- tbody.appendChild(fragment);
- }else{
- tbody.insertBefore(fragment,rows[lastRowIndex- range.endRowIndex + range.beginRowIndex - 1])
- }
+ //th不参与排序
+ flag && trArray.splice(0, 1);
+ trArray = sort(trArray, function(tr1, tr2) {
+ var result;
+ if (compareFn && typeof compareFn === "function") {
+ result = compareFn.call(
+ this,
+ tr1.cells[sortByCellIndex],
+ tr2.cells[sortByCellIndex]
+ );
+ } else if (compareFn && typeof compareFn === "number") {
+ result = 1;
+ } else if (
+ compareFn &&
+ typeof compareFn === "string" &&
+ Fn[compareFn]
+ ) {
+ result = Fn[compareFn].call(
+ this,
+ tr1.cells[sortByCellIndex],
+ tr2.cells[sortByCellIndex]
+ );
+ } else {
+ result = Fn["orderbyasc"].call(
+ this,
+ tr1.cells[sortByCellIndex],
+ tr2.cells[sortByCellIndex]
+ );
}
- //冒泡排序
- function sort(array, compareFn){
- compareFn = compareFn || function(item1, item2){ return item1.localeCompare(item2);};
- for(var i= 0,len = array.length; i 0){
- var t = array[i];
- array[i] = array[j];
- array[j] = t;
- }
- }
- }
- return array;
+ return result;
+ });
+ var fragment = table.ownerDocument.createDocumentFragment();
+ for (var j = 0, len = trArray.length; j < len; j++) {
+ fragment.appendChild(trArray[j]);
+ }
+ var tbody = table.getElementsByTagName("tbody")[0];
+ if (!lastRowIndex) {
+ tbody.appendChild(fragment);
+ } else {
+ tbody.insertBefore(
+ fragment,
+ rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1]
+ );
+ }
+ }
+ //冒泡排序
+ function sort(array, compareFn) {
+ compareFn =
+ compareFn ||
+ function(item1, item2) {
+ return item1.localeCompare(item2);
+ };
+ for (var i = 0, len = array.length; i < len; i++) {
+ for (var j = i, length = array.length; j < length; j++) {
+ if (compareFn(array[i], array[j]) > 0) {
+ var t = array[i];
+ array[i] = array[j];
+ array[j] = t;
+ }
}
- //更新表格
- function updateTable(table) {
- //给第一行设置firstRow的样式名称,在排序图标的样式上使用到
- if(!utils.hasClass(table.rows[0], "firstRow")) {
- for(var i = 1; i< table.rows.length; i++) {
- utils.removeClass(table.rows[i], "firstRow");
- }
- utils.addClass(table.rows[0], "firstRow");
- }
+ }
+ return array;
+ }
+ //更新表格
+ function updateTable(table) {
+ //给第一行设置firstRow的样式名称,在排序图标的样式上使用到
+ if (!utils.hasClass(table.rows[0], "firstRow")) {
+ for (var i = 1; i < table.rows.length; i++) {
+ utils.removeClass(table.rows[i], "firstRow");
}
+ utils.addClass(table.rows[0], "firstRow");
+ }
}
+ }
});
diff --git a/_parse/video.js b/_parse/video.js
index da8ff80eb..b49425377 100644
--- a/_parse/video.js
+++ b/_parse/video.js
@@ -1,34 +1,38 @@
-UE.parse.register('vedio',function(utils){
- var video = this.root.getElementsByTagName('video'),
- audio = this.root.getElementsByTagName('audio');
+UE.parse.register("vedio", function(utils) {
+ var video = this.root.getElementsByTagName("video"),
+ audio = this.root.getElementsByTagName("audio");
- document.createElement('video');document.createElement('audio');
- if(video.length || audio.length){
- var sourcePath = utils.removeLastbs(this.rootPath),
- jsurl = sourcePath + '/third-party/video-js/video.js',
- cssurl = sourcePath + '/third-party/video-js/video-js.min.css',
- swfUrl = sourcePath + '/third-party/video-js/video-js.swf';
+ document.createElement("video");
+ document.createElement("audio");
+ if (video.length || audio.length) {
+ var sourcePath = utils.removeLastbs(this.rootPath),
+ jsurl = sourcePath + "/third-party/video-js/video.js",
+ cssurl = sourcePath + "/third-party/video-js/video-js.min.css",
+ swfUrl = sourcePath + "/third-party/video-js/video-js.swf";
- if(window.videojs) {
- videojs.autoSetup();
- } else {
- utils.loadFile(document,{
- id : "video_css",
- tag : "link",
- rel : "stylesheet",
- type : "text/css",
- href : cssurl
- });
- utils.loadFile(document,{
- id : "video_js",
- src : jsurl,
- tag : "script",
- type : "text/javascript"
- },function(){
- videojs.options.flash.swf = swfUrl;
- videojs.autoSetup();
- });
+ if (window.videojs) {
+ videojs.autoSetup();
+ } else {
+ utils.loadFile(document, {
+ id: "video_css",
+ tag: "link",
+ rel: "stylesheet",
+ type: "text/css",
+ href: cssurl
+ });
+ utils.loadFile(
+ document,
+ {
+ id: "video_js",
+ src: jsurl,
+ tag: "script",
+ type: "text/javascript"
+ },
+ function() {
+ videojs.options.flash.swf = swfUrl;
+ videojs.autoSetup();
}
-
+ );
}
-});
\ No newline at end of file
+ }
+});
diff --git a/_src/adapter/autosave.js b/_src/adapter/autosave.js
index 1923aa874..722feb848 100644
--- a/_src/adapter/autosave.js
+++ b/_src/adapter/autosave.js
@@ -1,18 +1,17 @@
-UE.registerUI('autosave', function(editor) {
- var timer = null,uid = null;
- editor.on('afterautosave',function(){
- clearTimeout(timer);
-
- timer = setTimeout(function(){
- if(uid){
- editor.trigger('hidemessage',uid);
- }
- uid = editor.trigger('showmessage',{
- content : editor.getLang('autosave.success'),
- timeout : 2000
- });
-
- },2000)
- })
+UE.registerUI("autosave", function(editor) {
+ var timer = null,
+ uid = null;
+ editor.on("afterautosave", function() {
+ clearTimeout(timer);
+ timer = setTimeout(function() {
+ if (uid) {
+ editor.trigger("hidemessage", uid);
+ }
+ uid = editor.trigger("showmessage", {
+ content: editor.getLang("autosave.success"),
+ timeout: 2000
+ });
+ }, 2000);
+ });
});
diff --git a/_src/adapter/editor.js b/_src/adapter/editor.js
index ef9933a04..234797e86 100644
--- a/_src/adapter/editor.js
+++ b/_src/adapter/editor.js
@@ -2,820 +2,959 @@
///commands 全屏
///commandsName FullScreen
///commandsTitle 全屏
-(function () {
- var utils = baidu.editor.utils,
- uiUtils = baidu.editor.ui.uiUtils,
- UIBase = baidu.editor.ui.UIBase,
- domUtils = baidu.editor.dom.domUtils;
- var nodeStack = [];
-
- function EditorUI(options) {
- this.initOptions(options);
- this.initEditorUI();
- }
-
- EditorUI.prototype = {
- uiName:'editor',
- initEditorUI:function () {
- this.editor.ui = this;
- this._dialogs = {};
- this.initUIBase();
- this._initToolbars();
- var editor = this.editor,
- me = this;
-
- editor.addListener('ready', function () {
- //提供getDialog方法
- editor.getDialog = function (name) {
- return editor.ui._dialogs[name + "Dialog"];
- };
- domUtils.on(editor.window, 'scroll', function (evt) {
- baidu.editor.ui.Popup.postHide(evt);
- });
- //提供编辑器实时宽高(全屏时宽高不变化)
- editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
-
- UE.browser.ie && UE.browser.version === 6 && editor.container.ownerDocument.execCommand("BackgroundImageCache", false, true);
-
- //display bottom-bar label based on config
- if (editor.options.elementPathEnabled) {
- editor.ui.getDom('elementpath').innerHTML = ' ' + editor.getLang("elementPathTip") + ': ';
- }
- if (editor.options.wordCount) {
- function countFn() {
- setCount(editor,me);
- domUtils.un(editor.document, "click", arguments.callee);
- }
- domUtils.on(editor.document, "click", countFn);
- editor.ui.getDom('wordcount').innerHTML = editor.getLang("wordCountTip");
- }
- editor.ui._scale();
- if (editor.options.scaleEnabled) {
- if (editor.autoHeightEnabled) {
- editor.disableAutoHeight();
- }
- me.enableScale();
- } else {
- me.disableScale();
- }
- if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {
- editor.ui.getDom('elementpath').style.display = "none";
- editor.ui.getDom('wordcount').style.display = "none";
- editor.ui.getDom('scale').style.display = "none";
- }
-
- if (!editor.selection.isFocus())return;
- editor.fireEvent('selectionchange', false, true);
-
-
- });
-
- editor.addListener('mousedown', function (t, evt) {
- var el = evt.target || evt.srcElement;
- baidu.editor.ui.Popup.postHide(evt, el);
- baidu.editor.ui.ShortCutMenu.postHide(evt);
-
- });
- editor.addListener("delcells", function () {
- if (UE.ui['edittip']) {
- new UE.ui['edittip'](editor);
- }
- editor.getDialog('edittip').open();
- });
-
- var pastePop, isPaste = false, timer;
- editor.addListener("afterpaste", function () {
- if(editor.queryCommandState('pasteplain'))
- return;
- if(baidu.editor.ui.PastePicker){
- pastePop = new baidu.editor.ui.Popup({
- content:new baidu.editor.ui.PastePicker({editor:editor}),
- editor:editor,
- className:'edui-wordpastepop'
- });
- pastePop.render();
- }
- isPaste = true;
- });
-
- editor.addListener("afterinserthtml", function () {
- clearTimeout(timer);
- timer = setTimeout(function () {
- if (pastePop && (isPaste || editor.ui._isTransfer)) {
- if(pastePop.isHidden()){
- var span = domUtils.createElement(editor.document, 'span', {
- 'style':"line-height:0px;",
- 'innerHTML':'\ufeff'
- }),
- range = editor.selection.getRange();
- range.insertNode(span);
- var tmp= getDomNode(span, 'firstChild', 'previousSibling');
- tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
- domUtils.remove(span);
- }else{
- pastePop.show();
- }
- delete editor.ui._isTransfer;
- isPaste = false;
- }
- }, 200)
- });
- editor.addListener('contextmenu', function (t, evt) {
- baidu.editor.ui.Popup.postHide(evt);
- });
- editor.addListener('keydown', function (t, evt) {
- if (pastePop) pastePop.dispose(evt);
- var keyCode = evt.keyCode || evt.which;
- if(evt.altKey&&keyCode==90){
- UE.ui.buttons['fullscreen'].onclick();
- }
- });
- editor.addListener('wordcount', function (type) {
- setCount(this,me);
- });
- function setCount(editor,ui) {
- editor.setOpt({
- wordCount:true,
- maximumWords:10000,
- wordCountMsg:editor.options.wordCountMsg || editor.getLang("wordCountMsg"),
- wordOverFlowMsg:editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")
- });
- var opt = editor.options,
- max = opt.maximumWords,
- msg = opt.wordCountMsg ,
- errMsg = opt.wordOverFlowMsg,
- countDom = ui.getDom('wordcount');
- if (!opt.wordCount) {
- return;
- }
- var count = editor.getContentLength(true);
- if (count > max) {
- countDom.innerHTML = errMsg;
- editor.fireEvent("wordcountoverflow");
- } else {
- countDom.innerHTML = msg.replace("{#leave}", max - count).replace("{#count}", count);
- }
- }
-
- editor.addListener('selectionchange', function () {
- if (editor.options.elementPathEnabled) {
- me[(editor.queryCommandState('elementpath') == -1 ? 'dis' : 'en') + 'ableElementPath']()
- }
- if (editor.options.scaleEnabled) {
- me[(editor.queryCommandState('scale') == -1 ? 'dis' : 'en') + 'ableScale']();
+(function() {
+ var utils = baidu.editor.utils,
+ uiUtils = baidu.editor.ui.uiUtils,
+ UIBase = baidu.editor.ui.UIBase,
+ domUtils = baidu.editor.dom.domUtils;
+ var nodeStack = [];
+
+ function EditorUI(options) {
+ this.initOptions(options);
+ this.initEditorUI();
+ }
+
+ EditorUI.prototype = {
+ uiName: "editor",
+ initEditorUI: function() {
+ this.editor.ui = this;
+ this._dialogs = {};
+ this.initUIBase();
+ this._initToolbars();
+ var editor = this.editor,
+ me = this;
+
+ editor.addListener("ready", function() {
+ //提供getDialog方法
+ editor.getDialog = function(name) {
+ return editor.ui._dialogs[name + "Dialog"];
+ };
+ domUtils.on(editor.window, "scroll", function(evt) {
+ baidu.editor.ui.Popup.postHide(evt);
+ });
+ //提供编辑器实时宽高(全屏时宽高不变化)
+ editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
+
+ UE.browser.ie &&
+ UE.browser.version === 6 &&
+ editor.container.ownerDocument.execCommand(
+ "BackgroundImageCache",
+ false,
+ true
+ );
+
+ //display bottom-bar label based on config
+ if (editor.options.elementPathEnabled) {
+ editor.ui.getDom("elementpath").innerHTML =
+ '' +
+ editor.getLang("elementPathTip") +
+ ": ";
+ }
+ if (editor.options.wordCount) {
+ function countFn() {
+ setCount(editor, me);
+ domUtils.un(editor.document, "click", arguments.callee);
+ }
+ domUtils.on(editor.document, "click", countFn);
+ editor.ui.getDom("wordcount").innerHTML = editor.getLang(
+ "wordCountTip"
+ );
+ }
+ editor.ui._scale();
+ if (editor.options.scaleEnabled) {
+ if (editor.autoHeightEnabled) {
+ editor.disableAutoHeight();
+ }
+ me.enableScale();
+ } else {
+ me.disableScale();
+ }
+ if (
+ !editor.options.elementPathEnabled &&
+ !editor.options.wordCount &&
+ !editor.options.scaleEnabled
+ ) {
+ editor.ui.getDom("elementpath").style.display = "none";
+ editor.ui.getDom("wordcount").style.display = "none";
+ editor.ui.getDom("scale").style.display = "none";
+ }
- }
- });
- var popup = new baidu.editor.ui.Popup({
- editor:editor,
- content:'',
- className:'edui-bubble',
- _onEditButtonClick:function () {
- this.hide();
- editor.ui._dialogs.linkDialog.open();
- },
- _onImgEditButtonClick:function (name) {
- this.hide();
- editor.ui._dialogs[name] && editor.ui._dialogs[name].open();
-
- },
- _onImgSetFloat:function (value) {
- this.hide();
- editor.execCommand("imagefloat", value);
-
- },
- _setIframeAlign:function (value) {
- var frame = popup.anchorEl;
- var newFrame = frame.cloneNode(true);
- switch (value) {
- case -2:
- newFrame.setAttribute("align", "");
- break;
- case -1:
- newFrame.setAttribute("align", "left");
- break;
- case 1:
- newFrame.setAttribute("align", "right");
- break;
- }
- frame.parentNode.insertBefore(newFrame, frame);
- domUtils.remove(frame);
- popup.anchorEl = newFrame;
- popup.showAnchor(popup.anchorEl);
- },
- _updateIframe:function () {
- var frame = editor._iframe = popup.anchorEl;
- if(domUtils.hasClass(frame, 'ueditor_baidumap')) {
- editor.selection.getRange().selectNode(frame).select();
- editor.ui._dialogs.mapDialog.open();
- popup.hide();
- } else {
- editor.ui._dialogs.insertframeDialog.open();
- popup.hide();
- }
- },
- _onRemoveButtonClick:function (cmdName) {
- editor.execCommand(cmdName);
- this.hide();
- },
- queryAutoHide:function (el) {
- if (el && el.ownerDocument == editor.document) {
- if (el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName(el, 'a', true)) {
- return el !== popup.anchorEl;
- }
- }
- return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);
- }
- });
- popup.render();
- if (editor.options.imagePopup) {
- editor.addListener('mouseover', function (t, evt) {
- evt = evt || window.event;
- var el = evt.target || evt.srcElement;
- if (editor.ui._dialogs.insertframeDialog && /iframe/ig.test(el.tagName)) {
- var html = popup.formatHtml(
- '' + editor.getLang("property") + ': ' + editor.getLang("default") + ' ' + editor.getLang("justifyleft") + ' ' + editor.getLang("justifyright") + ' ' +
- ' ' + editor.getLang("modify") + '');
- if (html) {
- popup.getDom('content').innerHTML = html;
- popup.anchorEl = el;
- popup.showAnchor(popup.anchorEl);
- } else {
- popup.hide();
- }
- }
- });
- editor.addListener('selectionchange', function (t, causeByUi) {
- if (!causeByUi) return;
- var html = '', str = "",
- img = editor.selection.getRange().getClosedNode(),
- dialogs = editor.ui._dialogs;
- if (img && img.tagName == 'IMG') {
- var dialogName = 'insertimageDialog';
- if (img.className.indexOf("edui-faked-video") != -1 || img.className.indexOf("edui-upload-video") != -1) {
- dialogName = "insertvideoDialog"
- }
- if (img.className.indexOf("edui-faked-webapp") != -1) {
- dialogName = "webappDialog"
- }
- if (img.src.indexOf("http://api.map.baidu.com") != -1) {
- dialogName = "mapDialog"
- }
- if (img.className.indexOf("edui-faked-music") != -1) {
- dialogName = "musicDialog"
- }
- if (img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1) {
- dialogName = "gmapDialog"
- }
- if (img.getAttribute("anchorname")) {
- dialogName = "anchorDialog";
- html = popup.formatHtml(
- '' + editor.getLang("property") + ': ' + editor.getLang("modify") + ' ' +
- '' + editor.getLang("delete") + '');
- }
- if (img.getAttribute("word_img")) {
- //todo 放到dialog去做查询
- editor.word_img = [img.getAttribute("word_img")];
- dialogName = "wordimageDialog"
- }
- if(domUtils.hasClass(img, 'loadingclass') || domUtils.hasClass(img, 'loaderrorclass')) {
- dialogName = "";
- }
- if (!dialogs[dialogName]) {
- return;
- }
- str = '' + editor.getLang("property") + ': '+
- '' + editor.getLang("default") + ' ' +
- '' + editor.getLang("justifyleft") + ' ' +
- '' + editor.getLang("justifyright") + ' ' +
- '' + editor.getLang("justifycenter") + ' '+
- '' + editor.getLang("modify") + '';
-
- !html && (html = popup.formatHtml(str))
-
- }
- if (editor.ui._dialogs.linkDialog) {
- var link = editor.queryCommandValue('link');
- var url;
- if (link && (url = (link.getAttribute('_href') || link.getAttribute('href', 2)))) {
- var txt = url;
- if (url.length > 30) {
- txt = url.substring(0, 20) + "...";
- }
- if (html) {
- html += ''
- }
- html += popup.formatHtml(
- '' + editor.getLang("anthorMsg") + ': ' + txt + '' +
- ' ' + editor.getLang("modify") + '' +
- ' ' + editor.getLang("clear") + '');
- popup.showAnchor(link);
- }
- }
-
- if (html) {
- popup.getDom('content').innerHTML = html;
- popup.anchorEl = img || link;
- popup.showAnchor(popup.anchorEl);
- } else {
- popup.hide();
- }
- });
+ if (!editor.selection.isFocus()) return;
+ editor.fireEvent("selectionchange", false, true);
+ });
+
+ editor.addListener("mousedown", function(t, evt) {
+ var el = evt.target || evt.srcElement;
+ baidu.editor.ui.Popup.postHide(evt, el);
+ baidu.editor.ui.ShortCutMenu.postHide(evt);
+ });
+ editor.addListener("delcells", function() {
+ if (UE.ui["edittip"]) {
+ new UE.ui["edittip"](editor);
+ }
+ editor.getDialog("edittip").open();
+ });
+
+ var pastePop,
+ isPaste = false,
+ timer;
+ editor.addListener("afterpaste", function() {
+ if (editor.queryCommandState("pasteplain")) return;
+ if (baidu.editor.ui.PastePicker) {
+ pastePop = new baidu.editor.ui.Popup({
+ content: new baidu.editor.ui.PastePicker({ editor: editor }),
+ editor: editor,
+ className: "edui-wordpastepop"
+ });
+ pastePop.render();
+ }
+ isPaste = true;
+ });
+
+ editor.addListener("afterinserthtml", function() {
+ clearTimeout(timer);
+ timer = setTimeout(function() {
+ if (pastePop && (isPaste || editor.ui._isTransfer)) {
+ if (pastePop.isHidden()) {
+ var span = domUtils.createElement(editor.document, "span", {
+ style: "line-height:0px;",
+ innerHTML: "\ufeff"
+ }),
+ range = editor.selection.getRange();
+ range.insertNode(span);
+ var tmp = getDomNode(span, "firstChild", "previousSibling");
+ tmp &&
+ pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
+ domUtils.remove(span);
+ } else {
+ pastePop.show();
}
-
+ delete editor.ui._isTransfer;
+ isPaste = false;
+ }
+ }, 200);
+ });
+ editor.addListener("contextmenu", function(t, evt) {
+ baidu.editor.ui.Popup.postHide(evt);
+ });
+ editor.addListener("keydown", function(t, evt) {
+ if (pastePop) pastePop.dispose(evt);
+ var keyCode = evt.keyCode || evt.which;
+ if (evt.altKey && keyCode == 90) {
+ UE.ui.buttons["fullscreen"].onclick();
+ }
+ });
+ editor.addListener("wordcount", function(type) {
+ setCount(this, me);
+ });
+ function setCount(editor, ui) {
+ editor.setOpt({
+ wordCount: true,
+ maximumWords: 10000,
+ wordCountMsg:
+ editor.options.wordCountMsg || editor.getLang("wordCountMsg"),
+ wordOverFlowMsg:
+ editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")
+ });
+ var opt = editor.options,
+ max = opt.maximumWords,
+ msg = opt.wordCountMsg,
+ errMsg = opt.wordOverFlowMsg,
+ countDom = ui.getDom("wordcount");
+ if (!opt.wordCount) {
+ return;
+ }
+ var count = editor.getContentLength(true);
+ if (count > max) {
+ countDom.innerHTML = errMsg;
+ editor.fireEvent("wordcountoverflow");
+ } else {
+ countDom.innerHTML = msg
+ .replace("{#leave}", max - count)
+ .replace("{#count}", count);
+ }
+ }
+
+ editor.addListener("selectionchange", function() {
+ if (editor.options.elementPathEnabled) {
+ me[
+ (editor.queryCommandState("elementpath") == -1 ? "dis" : "en") +
+ "ableElementPath"
+ ]();
+ }
+ if (editor.options.scaleEnabled) {
+ me[
+ (editor.queryCommandState("scale") == -1 ? "dis" : "en") +
+ "ableScale"
+ ]();
+ }
+ });
+ var popup = new baidu.editor.ui.Popup({
+ editor: editor,
+ content: "",
+ className: "edui-bubble",
+ _onEditButtonClick: function() {
+ this.hide();
+ editor.ui._dialogs.linkDialog.open();
},
- _initToolbars:function () {
- var editor = this.editor;
- var toolbars = this.toolbars || [];
- var toolbarUis = [];
- var extraUIs = [];
- for (var i = 0; i < toolbars.length; i++) {
- var toolbar = toolbars[i];
- var toolbarUi = new baidu.editor.ui.Toolbar({theme:editor.options.theme});
- for (var j = 0; j < toolbar.length; j++) {
- var toolbarItem = toolbar[j];
- var toolbarItemUi = null;
- if (typeof toolbarItem == 'string') {
- toolbarItem = toolbarItem.toLowerCase();
- if (toolbarItem == '|') {
- toolbarItem = 'Separator';
- }
- if(toolbarItem == '||'){
- toolbarItem = 'Breakline';
- }
- var ui = baidu.editor.ui[toolbarItem];
- if (ui) {
- if(utils.isFunction(ui)){
- toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);
- }else{
- if(ui.id && ui.id != editor.key){
- continue;
- }
- var itemUI = ui.execFn.call(editor,editor,toolbarItem);
- if(itemUI){
- if(ui.index === undefined){
- toolbarUi.add(itemUI);
- continue;
- }else{
- extraUIs.push({
- index:ui.index,
- itemUI:itemUI
- })
- }
- }
- }
- }
- //fullscreen这里单独处理一下,放到首行去
- if (toolbarItem == 'fullscreen') {
- if (toolbarUis && toolbarUis[0]) {
- toolbarUis[0].items.splice(0, 0, toolbarItemUi);
- } else {
- toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);
- }
- continue;
- }
- } else {
- toolbarItemUi = toolbarItem;
- }
- if (toolbarItemUi && toolbarItemUi.id) {
-
- toolbarUi.add(toolbarItemUi);
- }
- }
- toolbarUis[i] = toolbarUi;
- }
-
- //接受外部定制的UI
-
- utils.each(extraUIs,function(obj){
- toolbarUi.add(obj.itemUI,obj.index)
- });
- this.toolbars = toolbarUis;
+ _onImgEditButtonClick: function(name) {
+ this.hide();
+ editor.ui._dialogs[name] && editor.ui._dialogs[name].open();
},
- getHtmlTpl:function () {
- return '' +
- ' ' +
- ' ' +
- ' ' +
- //modify wdcount by matao
- ' ' +
- ' | ' +
- ' | ' +
- ' | ' +
- '
' +
- ' ' +
- ' ';
+ _onImgSetFloat: function(value) {
+ this.hide();
+ editor.execCommand("imagefloat", value);
},
- showWordImageDialog:function () {
- this._dialogs['wordimageDialog'].open();
+ _setIframeAlign: function(value) {
+ var frame = popup.anchorEl;
+ var newFrame = frame.cloneNode(true);
+ switch (value) {
+ case -2:
+ newFrame.setAttribute("align", "");
+ break;
+ case -1:
+ newFrame.setAttribute("align", "left");
+ break;
+ case 1:
+ newFrame.setAttribute("align", "right");
+ break;
+ }
+ frame.parentNode.insertBefore(newFrame, frame);
+ domUtils.remove(frame);
+ popup.anchorEl = newFrame;
+ popup.showAnchor(popup.anchorEl);
},
- renderToolbarBoxHtml:function () {
- var buff = [];
- for (var i = 0; i < this.toolbars.length; i++) {
- buff.push(this.toolbars[i].renderHtml());
- }
- return buff.join('');
+ _updateIframe: function() {
+ var frame = (editor._iframe = popup.anchorEl);
+ if (domUtils.hasClass(frame, "ueditor_baidumap")) {
+ editor.selection.getRange().selectNode(frame).select();
+ editor.ui._dialogs.mapDialog.open();
+ popup.hide();
+ } else {
+ editor.ui._dialogs.insertframeDialog.open();
+ popup.hide();
+ }
},
- setFullScreen:function (fullscreen) {
-
- var editor = this.editor,
- container = editor.container.parentNode.parentNode;
- if (this._fullscreen != fullscreen) {
- this._fullscreen = fullscreen;
- this.editor.fireEvent('beforefullscreenchange', fullscreen);
- if (baidu.editor.browser.gecko) {
- var bk = editor.selection.getRange().createBookmark();
- }
- if (fullscreen) {
- while (container.tagName != "BODY") {
- var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position");
- nodeStack.push(position);
- container.style.position = "static";
- container = container.parentNode;
- }
- this._bakHtmlOverflow = document.documentElement.style.overflow;
- this._bakBodyOverflow = document.body.style.overflow;
- this._bakAutoHeight = this.editor.autoHeightEnabled;
- this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
-
- this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth;
- if (this._bakAutoHeight) {
- //当全屏时不能执行自动长高
- editor.autoHeightEnabled = false;
- this.editor.disableAutoHeight();
- }
-
- document.documentElement.style.overflow = 'hidden';
- //修复,滚动条不收起的问题
-
- window.scrollTo(0,window.scrollY);
- this._bakCssText = this.getDom().style.cssText;
- this._bakCssText1 = this.getDom('iframeholder').style.cssText;
- editor.iframe.parentNode.style.width = '';
- this._updateFullScreen();
- } else {
- while (container.tagName != "BODY") {
- container.style.position = nodeStack.shift();
- container = container.parentNode;
- }
- this.getDom().style.cssText = this._bakCssText;
- this.getDom('iframeholder').style.cssText = this._bakCssText1;
- if (this._bakAutoHeight) {
- editor.autoHeightEnabled = true;
- this.editor.enableAutoHeight();
- }
-
- document.documentElement.style.overflow = this._bakHtmlOverflow;
- document.body.style.overflow = this._bakBodyOverflow;
- editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + 'px';
- window.scrollTo(0, this._bakScrollTop);
- }
- if (browser.gecko && editor.body.contentEditable === 'true') {
- var input = document.createElement('input');
- document.body.appendChild(input);
- editor.body.contentEditable = false;
- setTimeout(function () {
- input.focus();
- setTimeout(function () {
- editor.body.contentEditable = true;
- editor.fireEvent('fullscreenchanged', fullscreen);
- editor.selection.getRange().moveToBookmark(bk).select(true);
- baidu.editor.dom.domUtils.remove(input);
- fullscreen && window.scroll(0, 0);
- }, 0)
- }, 0)
- }
-
- if(editor.body.contentEditable === 'true'){
- this.editor.fireEvent('fullscreenchanged', fullscreen);
- this.triggerLayout();
- }
-
- }
+ _onRemoveButtonClick: function(cmdName) {
+ editor.execCommand(cmdName);
+ this.hide();
},
- _updateFullScreen:function () {
- if (this._fullscreen) {
- var vpRect = uiUtils.getViewportRect();
- this.getDom().style.cssText = 'border:0;position:absolute;left:0;top:' + (this.editor.options.topOffset || 0) + 'px;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100);
- uiUtils.setViewportOffset(this.getDom(), { left:0, top:this.editor.options.topOffset || 0 });
- this.editor.setHeight(vpRect.height - this.getDom('toolbarbox').offsetHeight - this.getDom('bottombar').offsetHeight - (this.editor.options.topOffset || 0),true);
- //不手动调一下,会导致全屏失效
- if(browser.gecko){
- try{
- window.onresize();
- }catch(e){
-
- }
-
- }
+ queryAutoHide: function(el) {
+ if (el && el.ownerDocument == editor.document) {
+ if (
+ el.tagName.toLowerCase() == "img" ||
+ domUtils.findParentByTagName(el, "a", true)
+ ) {
+ return el !== popup.anchorEl;
}
- },
- _updateElementPath:function () {
- var bottom = this.getDom('elementpath'), list;
- if (this.elementPathEnabled && (list = this.editor.queryCommandValue('elementpath'))) {
-
- var buff = [];
- for (var i = 0, ci; ci = list[i]; i++) {
- buff[i] = this.formatHtml('' + ci + '');
- }
- bottom.innerHTML = '' + this.editor.getLang("elementPathTip") + ': ' + buff.join(' > ') + ' ';
-
+ }
+ return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);
+ }
+ });
+ popup.render();
+ if (editor.options.imagePopup) {
+ editor.addListener("mouseover", function(t, evt) {
+ evt = evt || window.event;
+ var el = evt.target || evt.srcElement;
+ if (
+ editor.ui._dialogs.insertframeDialog &&
+ /iframe/gi.test(el.tagName)
+ ) {
+ var html = popup.formatHtml(
+ "" +
+ editor.getLang("property") +
+ ': ' +
+ editor.getLang("default") +
+ ' ' +
+ editor.getLang("justifyleft") +
+ ' ' +
+ editor.getLang("justifyright") +
+ " " +
+ ' ' +
+ editor.getLang("modify") +
+ ""
+ );
+ if (html) {
+ popup.getDom("content").innerHTML = html;
+ popup.anchorEl = el;
+ popup.showAnchor(popup.anchorEl);
} else {
- bottom.style.display = 'none'
+ popup.hide();
}
- },
- disableElementPath:function () {
- var bottom = this.getDom('elementpath');
- bottom.innerHTML = '';
- bottom.style.display = 'none';
- this.elementPathEnabled = false;
-
- },
- enableElementPath:function () {
- var bottom = this.getDom('elementpath');
- bottom.style.display = '';
- this.elementPathEnabled = true;
- this._updateElementPath();
- },
- _scale:function () {
- var doc = document,
- editor = this.editor,
- editorHolder = editor.container,
- editorDocument = editor.document,
- toolbarBox = this.getDom("toolbarbox"),
- bottombar = this.getDom("bottombar"),
- scale = this.getDom("scale"),
- scalelayer = this.getDom("scalelayer");
-
- var isMouseMove = false,
- position = null,
- minEditorHeight = 0,
- minEditorWidth = editor.options.minFrameWidth,
- pageX = 0,
- pageY = 0,
- scaleWidth = 0,
- scaleHeight = 0;
-
- function down() {
- position = domUtils.getXY(editorHolder);
-
- if (!minEditorHeight) {
- minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight;
- }
-
- scalelayer.style.cssText = "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:"
- + editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1);
-
- domUtils.on(doc, "mousemove", move);
- domUtils.on(editorDocument, "mouseup", up);
- domUtils.on(doc, "mouseup", up);
+ }
+ });
+ editor.addListener("selectionchange", function(t, causeByUi) {
+ if (!causeByUi) return;
+ var html = "",
+ str = "",
+ img = editor.selection.getRange().getClosedNode(),
+ dialogs = editor.ui._dialogs;
+ if (img && img.tagName == "IMG") {
+ var dialogName = "insertimageDialog";
+ if (
+ img.className.indexOf("edui-faked-video") != -1 ||
+ img.className.indexOf("edui-upload-video") != -1
+ ) {
+ dialogName = "insertvideoDialog";
}
-
- var me = this;
- //by xuheng 全屏时关掉缩放
- this.editor.addListener('fullscreenchanged', function (e, fullScreen) {
- if (fullScreen) {
- me.disableScale();
-
- } else {
- if (me.editor.options.scaleEnabled) {
- me.enableScale();
- var tmpNode = me.editor.document.createElement('span');
- me.editor.body.appendChild(tmpNode);
- me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + 'px';
- domUtils.remove(tmpNode)
- }
- }
- });
- function move(event) {
- clearSelection();
- var e = event || window.event;
- pageX = e.pageX || (doc.documentElement.scrollLeft + e.clientX);
- pageY = e.pageY || (doc.documentElement.scrollTop + e.clientY);
- scaleWidth = pageX - position.x;
- scaleHeight = pageY - position.y;
-
- if (scaleWidth >= minEditorWidth) {
- isMouseMove = true;
- scalelayer.style.width = scaleWidth + 'px';
- }
- if (scaleHeight >= minEditorHeight) {
- isMouseMove = true;
- scalelayer.style.height = scaleHeight + "px";
- }
+ if (img.className.indexOf("edui-faked-webapp") != -1) {
+ dialogName = "webappDialog";
}
-
- function up() {
- if (isMouseMove) {
- isMouseMove = false;
- editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
- editorHolder.style.width = editor.ui._actualFrameWidth + 'px';
-
- editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2,true);
- }
- if (scalelayer) {
- scalelayer.style.display = "none";
- }
- clearSelection();
- domUtils.un(doc, "mousemove", move);
- domUtils.un(editorDocument, "mouseup", up);
- domUtils.un(doc, "mouseup", up);
+ if (img.src.indexOf("http://api.map.baidu.com") != -1) {
+ dialogName = "mapDialog";
}
-
- function clearSelection() {
- if (browser.ie)
- doc.selection.clear();
- else
- window.getSelection().removeAllRanges();
+ if (img.className.indexOf("edui-faked-music") != -1) {
+ dialogName = "musicDialog";
}
-
- this.enableScale = function () {
- //trace:2868
- if (editor.queryCommandState("source") == 1) return;
- scale.style.display = "";
- this.scaleEnabled = true;
- domUtils.on(scale, "mousedown", down);
- };
- this.disableScale = function () {
- scale.style.display = "none";
- this.scaleEnabled = false;
- domUtils.un(scale, "mousedown", down);
- };
- },
- isFullScreen:function () {
- return this._fullscreen;
- },
- postRender:function () {
- UIBase.prototype.postRender.call(this);
- for (var i = 0; i < this.toolbars.length; i++) {
- this.toolbars[i].postRender();
+ if (
+ img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1
+ ) {
+ dialogName = "gmapDialog";
+ }
+ if (img.getAttribute("anchorname")) {
+ dialogName = "anchorDialog";
+ html = popup.formatHtml(
+ "" +
+ editor.getLang("property") +
+ ': ' +
+ editor.getLang("modify") +
+ " " +
+ "" +
+ editor.getLang("delete") +
+ ""
+ );
+ }
+ if (img.getAttribute("word_img")) {
+ //todo 放到dialog去做查询
+ editor.word_img = [img.getAttribute("word_img")];
+ dialogName = "wordimageDialog";
+ }
+ if (
+ domUtils.hasClass(img, "loadingclass") ||
+ domUtils.hasClass(img, "loaderrorclass")
+ ) {
+ dialogName = "";
+ }
+ if (!dialogs[dialogName]) {
+ return;
}
- var me = this;
- var timerId,
- domUtils = baidu.editor.dom.domUtils,
- updateFullScreenTime = function () {
- clearTimeout(timerId);
- timerId = setTimeout(function () {
- me._updateFullScreen();
+ str =
+ "" +
+ editor.getLang("property") +
+ ": " +
+ '' +
+ editor.getLang("default") +
+ " " +
+ '' +
+ editor.getLang("justifyleft") +
+ " " +
+ '' +
+ editor.getLang("justifyright") +
+ " " +
+ '' +
+ editor.getLang("justifycenter") +
+ " " +
+ "' +
+ editor.getLang("modify") +
+ "";
+
+ !html && (html = popup.formatHtml(str));
+ }
+ if (editor.ui._dialogs.linkDialog) {
+ var link = editor.queryCommandValue("link");
+ var url;
+ if (
+ link &&
+ (url = link.getAttribute("_href") || link.getAttribute("href", 2))
+ ) {
+ var txt = url;
+ if (url.length > 30) {
+ txt = url.substring(0, 20) + "...";
+ }
+ if (html) {
+ html += '';
+ }
+ html += popup.formatHtml(
+ "" +
+ editor.getLang("anthorMsg") +
+ ': ' +
+ txt +
+ "" +
+ ' ' +
+ editor.getLang("modify") +
+ "" +
+ ' ' +
+ editor.getLang("clear") +
+ ""
+ );
+ popup.showAnchor(link);
+ }
+ }
+
+ if (html) {
+ popup.getDom("content").innerHTML = html;
+ popup.anchorEl = img || link;
+ popup.showAnchor(popup.anchorEl);
+ } else {
+ popup.hide();
+ }
+ });
+ }
+ },
+ _initToolbars: function() {
+ var editor = this.editor;
+ var toolbars = this.toolbars || [];
+ var toolbarUis = [];
+ var extraUIs = [];
+ for (var i = 0; i < toolbars.length; i++) {
+ var toolbar = toolbars[i];
+ var toolbarUi = new baidu.editor.ui.Toolbar({
+ theme: editor.options.theme
+ });
+ for (var j = 0; j < toolbar.length; j++) {
+ var toolbarItem = toolbar[j];
+ var toolbarItemUi = null;
+ if (typeof toolbarItem == "string") {
+ toolbarItem = toolbarItem.toLowerCase();
+ if (toolbarItem == "|") {
+ toolbarItem = "Separator";
+ }
+ if (toolbarItem == "||") {
+ toolbarItem = "Breakline";
+ }
+ var ui = baidu.editor.ui[toolbarItem];
+ if (ui) {
+ if (utils.isFunction(ui)) {
+ toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);
+ } else {
+ if (ui.id && ui.id != editor.key) {
+ continue;
+ }
+ var itemUI = ui.execFn.call(editor, editor, toolbarItem);
+ if (itemUI) {
+ if (ui.index === undefined) {
+ toolbarUi.add(itemUI);
+ continue;
+ } else {
+ extraUIs.push({
+ index: ui.index,
+ itemUI: itemUI
});
- };
- domUtils.on(window, 'resize', updateFullScreenTime);
-
- me.addListener('destroy', function () {
- domUtils.un(window, 'resize', updateFullScreenTime);
- clearTimeout(timerId);
- })
- },
- showToolbarMsg:function (msg, flag) {
- this.getDom('toolbarmsg_label').innerHTML = msg;
- this.getDom('toolbarmsg').style.display = '';
- //
- if (!flag) {
- var w = this.getDom('upload_dialog');
- w.style.display = 'none';
+ }
+ }
+ }
}
- },
- hideToolbarMsg:function () {
- this.getDom('toolbarmsg').style.display = 'none';
- },
- mapUrl:function (url) {
- return url ? url.replace('~/', this.editor.options.UEDITOR_HOME_URL || '') : ''
- },
- triggerLayout:function () {
- var dom = this.getDom();
- if (dom.style.zoom == '1') {
- dom.style.zoom = '100%';
- } else {
- dom.style.zoom = '1';
+ //fullscreen这里单独处理一下,放到首行去
+ if (toolbarItem == "fullscreen") {
+ if (toolbarUis && toolbarUis[0]) {
+ toolbarUis[0].items.splice(0, 0, toolbarItemUi);
+ } else {
+ toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);
+ }
+ continue;
}
+ } else {
+ toolbarItemUi = toolbarItem;
+ }
+ if (toolbarItemUi && toolbarItemUi.id) {
+ toolbarUi.add(toolbarItemUi);
+ }
+ }
+ toolbarUis[i] = toolbarUi;
+ }
+
+ //接受外部定制的UI
+
+ utils.each(extraUIs, function(obj) {
+ toolbarUi.add(obj.itemUI, obj.index);
+ });
+ this.toolbars = toolbarUis;
+ },
+ getHtmlTpl: function() {
+ return (
+ '' +
+ ' " +
+ ' ' +
+ " " +
+ //modify wdcount by matao
+ ' ' +
+ ' | ' +
+ ' | ' +
+ ' | ' +
+ "
" +
+ ' ' +
+ " "
+ );
+ },
+ showWordImageDialog: function() {
+ this._dialogs["wordimageDialog"].open();
+ },
+ renderToolbarBoxHtml: function() {
+ var buff = [];
+ for (var i = 0; i < this.toolbars.length; i++) {
+ buff.push(this.toolbars[i].renderHtml());
+ }
+ return buff.join("");
+ },
+ setFullScreen: function(fullscreen) {
+ var editor = this.editor,
+ container = editor.container.parentNode.parentNode;
+ if (this._fullscreen != fullscreen) {
+ this._fullscreen = fullscreen;
+ this.editor.fireEvent("beforefullscreenchange", fullscreen);
+ if (baidu.editor.browser.gecko) {
+ var bk = editor.selection.getRange().createBookmark();
+ }
+ if (fullscreen) {
+ while (container.tagName != "BODY") {
+ var position = baidu.editor.dom.domUtils.getComputedStyle(
+ container,
+ "position"
+ );
+ nodeStack.push(position);
+ container.style.position = "static";
+ container = container.parentNode;
+ }
+ this._bakHtmlOverflow = document.documentElement.style.overflow;
+ this._bakBodyOverflow = document.body.style.overflow;
+ this._bakAutoHeight = this.editor.autoHeightEnabled;
+ this._bakScrollTop = Math.max(
+ document.documentElement.scrollTop,
+ document.body.scrollTop
+ );
+
+ this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth;
+ if (this._bakAutoHeight) {
+ //当全屏时不能执行自动长高
+ editor.autoHeightEnabled = false;
+ this.editor.disableAutoHeight();
+ }
+
+ document.documentElement.style.overflow = "hidden";
+ //修复,滚动条不收起的问题
+
+ window.scrollTo(0, window.scrollY);
+ this._bakCssText = this.getDom().style.cssText;
+ this._bakCssText1 = this.getDom("iframeholder").style.cssText;
+ editor.iframe.parentNode.style.width = "";
+ this._updateFullScreen();
+ } else {
+ while (container.tagName != "BODY") {
+ container.style.position = nodeStack.shift();
+ container = container.parentNode;
+ }
+ this.getDom().style.cssText = this._bakCssText;
+ this.getDom("iframeholder").style.cssText = this._bakCssText1;
+ if (this._bakAutoHeight) {
+ editor.autoHeightEnabled = true;
+ this.editor.enableAutoHeight();
+ }
+
+ document.documentElement.style.overflow = this._bakHtmlOverflow;
+ document.body.style.overflow = this._bakBodyOverflow;
+ editor.iframe.parentNode.style.width =
+ this._bakEditorContaninerWidth + "px";
+ window.scrollTo(0, this._bakScrollTop);
+ }
+ if (browser.gecko && editor.body.contentEditable === "true") {
+ var input = document.createElement("input");
+ document.body.appendChild(input);
+ editor.body.contentEditable = false;
+ setTimeout(function() {
+ input.focus();
+ setTimeout(function() {
+ editor.body.contentEditable = true;
+ editor.fireEvent("fullscreenchanged", fullscreen);
+ editor.selection.getRange().moveToBookmark(bk).select(true);
+ baidu.editor.dom.domUtils.remove(input);
+ fullscreen && window.scroll(0, 0);
+ }, 0);
+ }, 0);
}
- };
- utils.inherits(EditorUI, baidu.editor.ui.UIBase);
-
-
- var instances = {};
-
- UE.ui.Editor = function (options) {
- var editor = new UE.Editor(options);
- editor.options.editor = editor;
- utils.loadFile(document, {
- href:editor.options.themePath + editor.options.theme + "/_css/ueditor.css",
- tag:"link",
- type:"text/css",
- rel:"stylesheet"
+ if (editor.body.contentEditable === "true") {
+ this.editor.fireEvent("fullscreenchanged", fullscreen);
+ this.triggerLayout();
+ }
+ }
+ },
+ _updateFullScreen: function() {
+ if (this._fullscreen) {
+ var vpRect = uiUtils.getViewportRect();
+ this.getDom().style.cssText =
+ "border:0;position:absolute;left:0;top:" +
+ (this.editor.options.topOffset || 0) +
+ "px;width:" +
+ vpRect.width +
+ "px;height:" +
+ vpRect.height +
+ "px;z-index:" +
+ (this.getDom().style.zIndex * 1 + 100);
+ uiUtils.setViewportOffset(this.getDom(), {
+ left: 0,
+ top: this.editor.options.topOffset || 0
});
+ this.editor.setHeight(
+ vpRect.height -
+ this.getDom("toolbarbox").offsetHeight -
+ this.getDom("bottombar").offsetHeight -
+ (this.editor.options.topOffset || 0),
+ true
+ );
+ //不手动调一下,会导致全屏失效
+ if (browser.gecko) {
+ try {
+ window.onresize();
+ } catch (e) {}
+ }
+ }
+ },
+ _updateElementPath: function() {
+ var bottom = this.getDom("elementpath"),
+ list;
+ if (
+ this.elementPathEnabled &&
+ (list = this.editor.queryCommandValue("elementpath"))
+ ) {
+ var buff = [];
+ for (var i = 0, ci; (ci = list[i]); i++) {
+ buff[i] = this.formatHtml(
+ '' +
+ ci +
+ ""
+ );
+ }
+ bottom.innerHTML =
+ '' +
+ this.editor.getLang("elementPathTip") +
+ ": " +
+ buff.join(" > ") +
+ " ";
+ } else {
+ bottom.style.display = "none";
+ }
+ },
+ disableElementPath: function() {
+ var bottom = this.getDom("elementpath");
+ bottom.innerHTML = "";
+ bottom.style.display = "none";
+ this.elementPathEnabled = false;
+ },
+ enableElementPath: function() {
+ var bottom = this.getDom("elementpath");
+ bottom.style.display = "";
+ this.elementPathEnabled = true;
+ this._updateElementPath();
+ },
+ _scale: function() {
+ var doc = document,
+ editor = this.editor,
+ editorHolder = editor.container,
+ editorDocument = editor.document,
+ toolbarBox = this.getDom("toolbarbox"),
+ bottombar = this.getDom("bottombar"),
+ scale = this.getDom("scale"),
+ scalelayer = this.getDom("scalelayer");
+
+ var isMouseMove = false,
+ position = null,
+ minEditorHeight = 0,
+ minEditorWidth = editor.options.minFrameWidth,
+ pageX = 0,
+ pageY = 0,
+ scaleWidth = 0,
+ scaleHeight = 0;
+
+ function down() {
+ position = domUtils.getXY(editorHolder);
+
+ if (!minEditorHeight) {
+ minEditorHeight =
+ editor.options.minFrameHeight +
+ toolbarBox.offsetHeight +
+ bottombar.offsetHeight;
+ }
- var oldRender = editor.render;
- editor.render = function (holder) {
+ scalelayer.style.cssText =
+ "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" +
+ editorHolder.offsetWidth +
+ "px;height:" +
+ editorHolder.offsetHeight +
+ "px;z-index:" +
+ (editor.options.zIndex + 1);
+
+ domUtils.on(doc, "mousemove", move);
+ domUtils.on(editorDocument, "mouseup", up);
+ domUtils.on(doc, "mouseup", up);
+ }
+
+ var me = this;
+ //by xuheng 全屏时关掉缩放
+ this.editor.addListener("fullscreenchanged", function(e, fullScreen) {
+ if (fullScreen) {
+ me.disableScale();
+ } else {
+ if (me.editor.options.scaleEnabled) {
+ me.enableScale();
+ var tmpNode = me.editor.document.createElement("span");
+ me.editor.body.appendChild(tmpNode);
+ me.editor.body.style.height =
+ Math.max(
+ domUtils.getXY(tmpNode).y,
+ me.editor.iframe.offsetHeight - 20
+ ) + "px";
+ domUtils.remove(tmpNode);
+ }
+ }
+ });
+ function move(event) {
+ clearSelection();
+ var e = event || window.event;
+ pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX;
+ pageY = e.pageY || doc.documentElement.scrollTop + e.clientY;
+ scaleWidth = pageX - position.x;
+ scaleHeight = pageY - position.y;
+
+ if (scaleWidth >= minEditorWidth) {
+ isMouseMove = true;
+ scalelayer.style.width = scaleWidth + "px";
+ }
+ if (scaleHeight >= minEditorHeight) {
+ isMouseMove = true;
+ scalelayer.style.height = scaleHeight + "px";
+ }
+ }
+
+ function up() {
+ if (isMouseMove) {
+ isMouseMove = false;
+ editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
+ editorHolder.style.width = editor.ui._actualFrameWidth + "px";
+
+ editor.setHeight(
+ scalelayer.offsetHeight -
+ bottombar.offsetHeight -
+ toolbarBox.offsetHeight -
+ 2,
+ true
+ );
+ }
+ if (scalelayer) {
+ scalelayer.style.display = "none";
+ }
+ clearSelection();
+ domUtils.un(doc, "mousemove", move);
+ domUtils.un(editorDocument, "mouseup", up);
+ domUtils.un(doc, "mouseup", up);
+ }
+
+ function clearSelection() {
+ if (browser.ie) doc.selection.clear();
+ else window.getSelection().removeAllRanges();
+ }
+
+ this.enableScale = function() {
+ //trace:2868
+ if (editor.queryCommandState("source") == 1) return;
+ scale.style.display = "";
+ this.scaleEnabled = true;
+ domUtils.on(scale, "mousedown", down);
+ };
+ this.disableScale = function() {
+ scale.style.display = "none";
+ this.scaleEnabled = false;
+ domUtils.un(scale, "mousedown", down);
+ };
+ },
+ isFullScreen: function() {
+ return this._fullscreen;
+ },
+ postRender: function() {
+ UIBase.prototype.postRender.call(this);
+ for (var i = 0; i < this.toolbars.length; i++) {
+ this.toolbars[i].postRender();
+ }
+ var me = this;
+ var timerId,
+ domUtils = baidu.editor.dom.domUtils,
+ updateFullScreenTime = function() {
+ clearTimeout(timerId);
+ timerId = setTimeout(function() {
+ me._updateFullScreen();
+ });
+ };
+ domUtils.on(window, "resize", updateFullScreenTime);
+
+ me.addListener("destroy", function() {
+ domUtils.un(window, "resize", updateFullScreenTime);
+ clearTimeout(timerId);
+ });
+ },
+ showToolbarMsg: function(msg, flag) {
+ this.getDom("toolbarmsg_label").innerHTML = msg;
+ this.getDom("toolbarmsg").style.display = "";
+ //
+ if (!flag) {
+ var w = this.getDom("upload_dialog");
+ w.style.display = "none";
+ }
+ },
+ hideToolbarMsg: function() {
+ this.getDom("toolbarmsg").style.display = "none";
+ },
+ mapUrl: function(url) {
+ return url
+ ? url.replace("~/", this.editor.options.UEDITOR_HOME_URL || "")
+ : "";
+ },
+ triggerLayout: function() {
+ var dom = this.getDom();
+ if (dom.style.zoom == "1") {
+ dom.style.zoom = "100%";
+ } else {
+ dom.style.zoom = "1";
+ }
+ }
+ };
+ utils.inherits(EditorUI, baidu.editor.ui.UIBase);
+
+ var instances = {};
+
+ UE.ui.Editor = function(options) {
+ var editor = new UE.Editor(options);
+ editor.options.editor = editor;
+ utils.loadFile(document, {
+ href:
+ editor.options.themePath + editor.options.theme + "/_css/ueditor.css",
+ tag: "link",
+ type: "text/css",
+ rel: "stylesheet"
+ });
+
+ var oldRender = editor.render;
+ editor.render = function(holder) {
+ if (holder.constructor === String) {
+ editor.key = holder;
+ instances[holder] = editor;
+ }
+ utils.domReady(function() {
+ editor.langIsReady
+ ? renderUI()
+ : editor.addListener("langReady", renderUI);
+ function renderUI() {
+ editor.setOpt({
+ labelMap: editor.options.labelMap || editor.getLang("labelMap")
+ });
+ new EditorUI(editor.options);
+ if (holder) {
if (holder.constructor === String) {
- editor.key = holder;
- instances[holder] = editor;
+ holder = document.getElementById(holder);
}
- utils.domReady(function () {
- editor.langIsReady ? renderUI() : editor.addListener("langReady", renderUI);
- function renderUI() {
- editor.setOpt({
- labelMap:editor.options.labelMap || editor.getLang('labelMap')
- });
- new EditorUI(editor.options);
- if (holder) {
- if (holder.constructor === String) {
- holder = document.getElementById(holder);
- }
- holder && holder.getAttribute('name') && ( editor.options.textarea = holder.getAttribute('name'));
- if (holder && /script|textarea/ig.test(holder.tagName)) {
- var newDiv = document.createElement('div');
- holder.parentNode.insertBefore(newDiv, holder);
- var cont = holder.value || holder.innerHTML;
- editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) ? editor.options.initialContent :
- cont.replace(/>[\n\r\t]+([ ]{4})+/g, '>')
- .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<');
- holder.className && (newDiv.className = holder.className);
- holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);
- if (/textarea/i.test(holder.tagName)) {
- editor.textarea = holder;
- editor.textarea.style.display = 'none';
-
-
- } else {
- holder.parentNode.removeChild(holder);
-
-
- }
- if(holder.id){
- newDiv.id = holder.id;
- domUtils.removeAttributes(holder,'id');
- }
- holder = newDiv;
- holder.innerHTML = '';
- }
-
- }
- domUtils.addClass(holder, "edui-" + editor.options.theme);
- editor.ui.render(holder);
- var opt = editor.options;
- //给实例添加一个编辑器的容器引用
- editor.container = editor.ui.getDom();
- var parents = domUtils.findParents(holder,true);
- var displays = [];
- for(var i = 0 ,ci;ci=parents[i];i++){
- displays[i] = ci.style.display;
- ci.style.display = 'block'
- }
- if (opt.initialFrameWidth) {
- opt.minFrameWidth = opt.initialFrameWidth;
- } else {
- opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
- var styleWidth = holder.style.width;
- if(/%$/.test(styleWidth)) {
- opt.initialFrameWidth = styleWidth;
- }
- }
- if (opt.initialFrameHeight) {
- opt.minFrameHeight = opt.initialFrameHeight;
- } else {
- opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;
- }
- for(var i = 0 ,ci;ci=parents[i];i++){
- ci.style.display = displays[i]
- }
- //编辑器最外容器设置了高度,会导致,编辑器不占位
- //todo 先去掉,没有找到原因
- if(holder.style.height){
- holder.style.height = ''
- }
- editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? '' : 'px');
- editor.container.style.zIndex = opt.zIndex;
- oldRender.call(editor, editor.ui.getDom('iframeholder'));
- editor.fireEvent("afteruiready");
- }
- })
- };
- return editor;
+ holder &&
+ holder.getAttribute("name") &&
+ (editor.options.textarea = holder.getAttribute("name"));
+ if (holder && /script|textarea/gi.test(holder.tagName)) {
+ var newDiv = document.createElement("div");
+ holder.parentNode.insertBefore(newDiv, holder);
+ var cont = holder.value || holder.innerHTML;
+ editor.options.initialContent = /^[\t\r\n ]*$/.test(cont)
+ ? editor.options.initialContent
+ : cont
+ .replace(/>[\n\r\t]+([ ]{4})+/g, ">")
+ .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<");
+ holder.className && (newDiv.className = holder.className);
+ holder.style.cssText &&
+ (newDiv.style.cssText = holder.style.cssText);
+ if (/textarea/i.test(holder.tagName)) {
+ editor.textarea = holder;
+ editor.textarea.style.display = "none";
+ } else {
+ holder.parentNode.removeChild(holder);
+ }
+ if (holder.id) {
+ newDiv.id = holder.id;
+ domUtils.removeAttributes(holder, "id");
+ }
+ holder = newDiv;
+ holder.innerHTML = "";
+ }
+ }
+ domUtils.addClass(holder, "edui-" + editor.options.theme);
+ editor.ui.render(holder);
+ var opt = editor.options;
+ //给实例添加一个编辑器的容器引用
+ editor.container = editor.ui.getDom();
+ var parents = domUtils.findParents(holder, true);
+ var displays = [];
+ for (var i = 0, ci; (ci = parents[i]); i++) {
+ displays[i] = ci.style.display;
+ ci.style.display = "block";
+ }
+ if (opt.initialFrameWidth) {
+ opt.minFrameWidth = opt.initialFrameWidth;
+ } else {
+ opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
+ var styleWidth = holder.style.width;
+ if (/%$/.test(styleWidth)) {
+ opt.initialFrameWidth = styleWidth;
+ }
+ }
+ if (opt.initialFrameHeight) {
+ opt.minFrameHeight = opt.initialFrameHeight;
+ } else {
+ opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;
+ }
+ for (var i = 0, ci; (ci = parents[i]); i++) {
+ ci.style.display = displays[i];
+ }
+ //编辑器最外容器设置了高度,会导致,编辑器不占位
+ //todo 先去掉,没有找到原因
+ if (holder.style.height) {
+ holder.style.height = "";
+ }
+ editor.container.style.width =
+ opt.initialFrameWidth +
+ (/%$/.test(opt.initialFrameWidth) ? "" : "px");
+ editor.container.style.zIndex = opt.zIndex;
+ oldRender.call(editor, editor.ui.getDom("iframeholder"));
+ editor.fireEvent("afteruiready");
+ }
+ });
};
+ return editor;
+ };
-
- /**
+ /**
* @file
* @name UE
* @short UE
* @desc UEditor的顶部命名空间
*/
- /**
+ /**
* @name getEditor
* @since 1.2.4+
* @grammar UE.getEditor(id,[opt]) => Editor实例
@@ -830,33 +969,30 @@
* UE.getEditor('containerId'); //返回刚创建的实例
*
*/
- UE.getEditor = function (id, opt) {
- var editor = instances[id];
- if (!editor) {
- editor = instances[id] = new UE.ui.Editor(opt);
- editor.render(id);
- }
- return editor;
- };
-
-
- UE.delEditor = function (id) {
- var editor;
- if (editor = instances[id]) {
- editor.key && editor.destroy();
- delete instances[id]
- }
- };
-
- UE.registerUI = function(uiName,fn,index,editorId){
- utils.each(uiName.split(/\s+/), function (name) {
- baidu.editor.ui[name] = {
- id : editorId,
- execFn:fn,
- index:index
- };
- })
-
+ UE.getEditor = function(id, opt) {
+ var editor = instances[id];
+ if (!editor) {
+ editor = instances[id] = new UE.ui.Editor(opt);
+ editor.render(id);
}
-
-})();
\ No newline at end of file
+ return editor;
+ };
+
+ UE.delEditor = function(id) {
+ var editor;
+ if ((editor = instances[id])) {
+ editor.key && editor.destroy();
+ delete instances[id];
+ }
+ };
+
+ UE.registerUI = function(uiName, fn, index, editorId) {
+ utils.each(uiName.split(/\s+/), function(name) {
+ baidu.editor.ui[name] = {
+ id: editorId,
+ execFn: fn,
+ index: index
+ };
+ });
+ };
+})();
diff --git a/_src/adapter/editorui.js b/_src/adapter/editorui.js
index 965b8b40d..8a3c85fd8 100644
--- a/_src/adapter/editorui.js
+++ b/_src/adapter/editorui.js
@@ -1,854 +1,1002 @@
//ui跟编辑器的适配層
//那个按钮弹出是dialog,是下拉筐等都是在这个js中配置
//自己写的ui也要在这里配置,放到baidu.editor.ui下边,当编辑器实例化的时候会根据ueditor.config中的toolbars找到相应的进行实例化
-(function () {
- var utils = baidu.editor.utils;
- var editorui = baidu.editor.ui;
- var _Dialog = editorui.Dialog;
- editorui.buttons = {};
-
- editorui.Dialog = function (options) {
- var dialog = new _Dialog(options);
- dialog.addListener('hide', function () {
-
- if (dialog.editor) {
- var editor = dialog.editor;
- try {
- if (browser.gecko) {
- var y = editor.window.scrollY,
- x = editor.window.scrollX;
- editor.body.focus();
- editor.window.scrollTo(x, y);
- } else {
- editor.focus();
- }
-
-
- } catch (ex) {
- }
- }
- });
- return dialog;
- };
-
- var iframeUrlMap = {
- 'anchor':'~/dialogs/anchor/anchor.html',
- 'insertimage':'~/dialogs/image/image.html',
- 'link':'~/dialogs/link/link.html',
- 'spechars':'~/dialogs/spechars/spechars.html',
- 'searchreplace':'~/dialogs/searchreplace/searchreplace.html',
- 'map':'~/dialogs/map/map.html',
- 'gmap':'~/dialogs/gmap/gmap.html',
- 'insertvideo':'~/dialogs/video/video.html',
- 'help':'~/dialogs/help/help.html',
- 'preview':'~/dialogs/preview/preview.html',
- 'emotion':'~/dialogs/emotion/emotion.html',
- 'wordimage':'~/dialogs/wordimage/wordimage.html',
- 'attachment':'~/dialogs/attachment/attachment.html',
- 'insertframe':'~/dialogs/insertframe/insertframe.html',
- 'edittip':'~/dialogs/table/edittip.html',
- 'edittable':'~/dialogs/table/edittable.html',
- 'edittd':'~/dialogs/table/edittd.html',
- 'webapp':'~/dialogs/webapp/webapp.html',
- 'snapscreen':'~/dialogs/snapscreen/snapscreen.html',
- 'scrawl':'~/dialogs/scrawl/scrawl.html',
- 'music':'~/dialogs/music/music.html',
- 'template':'~/dialogs/template/template.html',
- 'background':'~/dialogs/background/background.html',
- 'charts': '~/dialogs/charts/charts.html'
- };
- //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起
- var btnCmds = ['undo', 'redo', 'formatmatch',
- 'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase',
- 'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent',
- 'blockquote', 'pasteplain', 'pagebreak',
- 'selectall', 'print','horizontal', 'removeformat', 'time', 'date', 'unlink',
- 'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow',
- 'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable', 'drafts'];
-
- for (var i = 0, ci; ci = btnCmds[i++];) {
- ci = ci.toLowerCase();
- editorui[ci] = function (cmd) {
- return function (editor) {
- var ui = new editorui.Button({
- className:'edui-for-' + cmd,
- title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '',
- onclick:function () {
- editor.execCommand(cmd);
- },
- theme:editor.options.theme,
- showText:false
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- var state = editor.queryCommandState(cmd);
- if (state == -1) {
- ui.setDisabled(true);
- ui.setChecked(false);
- } else {
- if (!uiReady) {
- ui.setDisabled(false);
- ui.setChecked(state);
- }
- }
- });
- return ui;
- };
- }(ci);
- }
-
- //清除文档
- editorui.cleardoc = function (editor) {
+(function() {
+ var utils = baidu.editor.utils;
+ var editorui = baidu.editor.ui;
+ var _Dialog = editorui.Dialog;
+ editorui.buttons = {};
+
+ editorui.Dialog = function(options) {
+ var dialog = new _Dialog(options);
+ dialog.addListener("hide", function() {
+ if (dialog.editor) {
+ var editor = dialog.editor;
+ try {
+ if (browser.gecko) {
+ var y = editor.window.scrollY,
+ x = editor.window.scrollX;
+ editor.body.focus();
+ editor.window.scrollTo(x, y);
+ } else {
+ editor.focus();
+ }
+ } catch (ex) {}
+ }
+ });
+ return dialog;
+ };
+
+ var iframeUrlMap = {
+ anchor: "~/dialogs/anchor/anchor.html",
+ insertimage: "~/dialogs/image/image.html",
+ link: "~/dialogs/link/link.html",
+ spechars: "~/dialogs/spechars/spechars.html",
+ searchreplace: "~/dialogs/searchreplace/searchreplace.html",
+ map: "~/dialogs/map/map.html",
+ gmap: "~/dialogs/gmap/gmap.html",
+ insertvideo: "~/dialogs/video/video.html",
+ help: "~/dialogs/help/help.html",
+ preview: "~/dialogs/preview/preview.html",
+ emotion: "~/dialogs/emotion/emotion.html",
+ wordimage: "~/dialogs/wordimage/wordimage.html",
+ attachment: "~/dialogs/attachment/attachment.html",
+ insertframe: "~/dialogs/insertframe/insertframe.html",
+ edittip: "~/dialogs/table/edittip.html",
+ edittable: "~/dialogs/table/edittable.html",
+ edittd: "~/dialogs/table/edittd.html",
+ webapp: "~/dialogs/webapp/webapp.html",
+ snapscreen: "~/dialogs/snapscreen/snapscreen.html",
+ scrawl: "~/dialogs/scrawl/scrawl.html",
+ music: "~/dialogs/music/music.html",
+ template: "~/dialogs/template/template.html",
+ background: "~/dialogs/background/background.html",
+ charts: "~/dialogs/charts/charts.html"
+ };
+ //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起
+ var btnCmds = [
+ "undo",
+ "redo",
+ "formatmatch",
+ "bold",
+ "italic",
+ "underline",
+ "fontborder",
+ "touppercase",
+ "tolowercase",
+ "strikethrough",
+ "subscript",
+ "superscript",
+ "source",
+ "indent",
+ "outdent",
+ "blockquote",
+ "pasteplain",
+ "pagebreak",
+ "selectall",
+ "print",
+ "horizontal",
+ "removeformat",
+ "time",
+ "date",
+ "unlink",
+ "insertparagraphbeforetable",
+ "insertrow",
+ "insertcol",
+ "mergeright",
+ "mergedown",
+ "deleterow",
+ "deletecol",
+ "splittorows",
+ "splittocols",
+ "splittocells",
+ "mergecells",
+ "deletetable",
+ "drafts"
+ ];
+
+ for (var i = 0, ci; (ci = btnCmds[i++]); ) {
+ ci = ci.toLowerCase();
+ editorui[ci] = (function(cmd) {
+ return function(editor) {
var ui = new editorui.Button({
- className:'edui-for-cleardoc',
- title:editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || '',
- theme:editor.options.theme,
- onclick:function () {
- if (confirm(editor.getLang("confirmClear"))) {
- editor.execCommand('cleardoc');
- }
- }
+ className: "edui-for-" + cmd,
+ title:
+ editor.options.labelMap[cmd] ||
+ editor.getLang("labelMap." + cmd) ||
+ "",
+ onclick: function() {
+ editor.execCommand(cmd);
+ },
+ theme: editor.options.theme,
+ showText: false
});
- editorui.buttons["cleardoc"] = ui;
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState('cleardoc') == -1);
- });
- return ui;
- };
-
- //排版,图片排版,文字方向
- var typeset = {
- 'justify':['left', 'right', 'center', 'justify'],
- 'imagefloat':['none', 'left', 'center', 'right'],
- 'directionality':['ltr', 'rtl']
- };
-
- for (var p in typeset) {
-
- (function (cmd, val) {
- for (var i = 0, ci; ci = val[i++];) {
- (function (cmd2) {
- editorui[cmd.replace('float', '') + cmd2] = function (editor) {
- var ui = new editorui.Button({
- className:'edui-for-' + cmd.replace('float', '') + cmd2,
- title:editor.options.labelMap[cmd.replace('float', '') + cmd2] || editor.getLang("labelMap." + cmd.replace('float', '') + cmd2) || '',
- theme:editor.options.theme,
- onclick:function () {
- editor.execCommand(cmd, cmd2);
- }
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- ui.setDisabled(editor.queryCommandState(cmd) == -1);
- ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady);
- });
- return ui;
- };
- })(ci)
- }
- })(p, typeset[p])
- }
-
- //字体颜色和背景颜色
- for (var i = 0, ci; ci = ['backcolor', 'forecolor'][i++];) {
- editorui[ci] = function (cmd) {
- return function (editor) {
- var ui = new editorui.ColorButton({
- className:'edui-for-' + cmd,
- color:'default',
- title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '',
- editor:editor,
- onpickcolor:function (t, color) {
- editor.execCommand(cmd, color);
- },
- onpicknocolor:function () {
- editor.execCommand(cmd, 'default');
- this.setColor('transparent');
- this.color = 'default';
- },
- onbuttonclick:function () {
- editor.execCommand(cmd, this.color);
- }
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState(cmd) == -1);
- });
- return ui;
- };
- }(ci);
- }
-
-
- var dialogBtns = {
- noOk:['searchreplace', 'help', 'spechars', 'webapp','preview'],
- ok:['attachment', 'anchor', 'link', 'insertimage', 'map', 'gmap', 'insertframe', 'wordimage',
- 'insertvideo', 'insertframe', 'edittip', 'edittable', 'edittd', 'scrawl', 'template', 'music', 'background', 'charts']
- };
-
- for (var p in dialogBtns) {
- (function (type, vals) {
- for (var i = 0, ci; ci = vals[i++];) {
- //todo opera下存在问题
- if (browser.opera && ci === "searchreplace") {
- continue;
- }
- (function (cmd) {
- editorui[cmd] = function (editor, iframeUrl, title) {
- iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd];
- title = editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '';
-
- var dialog;
- //没有iframeUrl不创建dialog
- if (iframeUrl) {
- dialog = new editorui.Dialog(utils.extend({
- iframeUrl:editor.ui.mapUrl(iframeUrl),
- editor:editor,
- className:'edui-for-' + cmd,
- title:title,
- holdScroll: cmd === 'insertimage',
- fullscreen: /charts|preview/.test(cmd),
- closeDialog:editor.getLang("closeDialog")
- }, type == 'ok' ? {
- buttons:[
- {
- className:'edui-okbutton',
- label:editor.getLang("ok"),
- editor:editor,
- onclick:function () {
- dialog.close(true);
- }
- },
- {
- className:'edui-cancelbutton',
- label:editor.getLang("cancel"),
- editor:editor,
- onclick:function () {
- dialog.close(false);
- }
- }
- ]
- } : {}));
-
- editor.ui._dialogs[cmd + "Dialog"] = dialog;
- }
-
- var ui = new editorui.Button({
- className:'edui-for-' + cmd,
- title:title,
- onclick:function () {
- if (dialog) {
- switch (cmd) {
- case "wordimage":
- var images = editor.execCommand("wordimage");
- if (images && images.length) {
- dialog.render();
- dialog.open();
- }
- break;
- case "scrawl":
- if (editor.queryCommandState("scrawl") != -1) {
- dialog.render();
- dialog.open();
- }
-
- break;
- default:
- dialog.render();
- dialog.open();
- }
- }
- },
- theme:editor.options.theme,
- disabled:(cmd == 'scrawl' && editor.queryCommandState("scrawl") == -1) || ( cmd == 'charts' )
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function () {
- //只存在于右键菜单而无工具栏按钮的ui不需要检测状态
- var unNeedCheckState = {'edittable':1};
- if (cmd in unNeedCheckState)return;
-
- var state = editor.queryCommandState(cmd);
- if (ui.getDom()) {
- ui.setDisabled(state == -1);
- ui.setChecked(state);
- }
-
- });
-
- return ui;
- };
- })(ci.toLowerCase())
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function(
+ type,
+ causeByUi,
+ uiReady
+ ) {
+ var state = editor.queryCommandState(cmd);
+ if (state == -1) {
+ ui.setDisabled(true);
+ ui.setChecked(false);
+ } else {
+ if (!uiReady) {
+ ui.setDisabled(false);
+ ui.setChecked(state);
}
- })(p, dialogBtns[p]);
- }
-
- editorui.snapscreen = function (editor, iframeUrl, title) {
- title = editor.options.labelMap['snapscreen'] || editor.getLang("labelMap.snapscreen") || '';
- var ui = new editorui.Button({
- className:'edui-for-snapscreen',
- title:title,
- onclick:function () {
- editor.execCommand("snapscreen");
- },
- theme:editor.options.theme
-
- });
- editorui.buttons['snapscreen'] = ui;
- iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})["snapscreen"] || iframeUrlMap["snapscreen"];
- if (iframeUrl) {
- var dialog = new editorui.Dialog({
- iframeUrl:editor.ui.mapUrl(iframeUrl),
- editor:editor,
- className:'edui-for-snapscreen',
- title:title,
- buttons:[
- {
- className:'edui-okbutton',
- label:editor.getLang("ok"),
- editor:editor,
- onclick:function () {
- dialog.close(true);
- }
- },
- {
- className:'edui-cancelbutton',
- label:editor.getLang("cancel"),
- editor:editor,
- onclick:function () {
- dialog.close(false);
- }
- }
- ]
-
- });
- dialog.render();
- editor.ui._dialogs["snapscreenDialog"] = dialog;
- }
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState('snapscreen') == -1);
+ }
});
return ui;
- };
-
- editorui.insertcode = function (editor, list, title) {
- list = editor.options['insertcode'] || [];
- title = editor.options.labelMap['insertcode'] || editor.getLang("labelMap.insertcode") || '';
- // if (!list.length) return;
- var items = [];
- utils.each(list,function(key,val){
- items.push({
- label:key,
- value:val,
- theme:editor.options.theme,
- renderLabelHtml:function () {
- return '' + (this.label || '') + ' ';
- }
+ };
+ })(ci);
+ }
+
+ //清除文档
+ editorui.cleardoc = function(editor) {
+ var ui = new editorui.Button({
+ className: "edui-for-cleardoc",
+ title:
+ editor.options.labelMap.cleardoc ||
+ editor.getLang("labelMap.cleardoc") ||
+ "",
+ theme: editor.options.theme,
+ onclick: function() {
+ if (confirm(editor.getLang("confirmClear"))) {
+ editor.execCommand("cleardoc");
+ }
+ }
+ });
+ editorui.buttons["cleardoc"] = ui;
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState("cleardoc") == -1);
+ });
+ return ui;
+ };
+
+ //排版,图片排版,文字方向
+ var typeset = {
+ justify: ["left", "right", "center", "justify"],
+ imagefloat: ["none", "left", "center", "right"],
+ directionality: ["ltr", "rtl"]
+ };
+
+ for (var p in typeset) {
+ (function(cmd, val) {
+ for (var i = 0, ci; (ci = val[i++]); ) {
+ (function(cmd2) {
+ editorui[cmd.replace("float", "") + cmd2] = function(editor) {
+ var ui = new editorui.Button({
+ className: "edui-for-" + cmd.replace("float", "") + cmd2,
+ title:
+ editor.options.labelMap[cmd.replace("float", "") + cmd2] ||
+ editor.getLang(
+ "labelMap." + cmd.replace("float", "") + cmd2
+ ) ||
+ "",
+ theme: editor.options.theme,
+ onclick: function() {
+ editor.execCommand(cmd, cmd2);
+ }
});
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function(
+ type,
+ causeByUi,
+ uiReady
+ ) {
+ ui.setDisabled(editor.queryCommandState(cmd) == -1);
+ ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady);
+ });
+ return ui;
+ };
+ })(ci);
+ }
+ })(p, typeset[p]);
+ }
+
+ //字体颜色和背景颜色
+ for (var i = 0, ci; (ci = ["backcolor", "forecolor"][i++]); ) {
+ editorui[ci] = (function(cmd) {
+ return function(editor) {
+ var ui = new editorui.ColorButton({
+ className: "edui-for-" + cmd,
+ color: "default",
+ title:
+ editor.options.labelMap[cmd] ||
+ editor.getLang("labelMap." + cmd) ||
+ "",
+ editor: editor,
+ onpickcolor: function(t, color) {
+ editor.execCommand(cmd, color);
+ },
+ onpicknocolor: function() {
+ editor.execCommand(cmd, "default");
+ this.setColor("transparent");
+ this.color = "default";
+ },
+ onbuttonclick: function() {
+ editor.execCommand(cmd, this.color);
+ }
});
-
- var ui = new editorui.Combox({
- editor:editor,
- items:items,
- onselect:function (t, index) {
- editor.execCommand('insertcode', this.items[index].value);
- },
- onbuttonclick:function () {
- this.showPopup();
- },
- title:title,
- initValue:title,
- className:'edui-for-insertcode',
- indexByValue:function (value) {
- if (value) {
- for (var i = 0, ci; ci = this.items[i]; i++) {
- if (ci.value.indexOf(value) != -1)
- return i;
- }
- }
-
- return -1;
- }
- });
- editorui.buttons['insertcode'] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- if (!uiReady) {
- var state = editor.queryCommandState('insertcode');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('insertcode');
- if(!value){
- ui.setValue(title);
- return;
- }
- //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
- value && (value = value.replace(/['"]/g, '').split(',')[0]);
- ui.setValue(value);
-
- }
- }
-
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState(cmd) == -1);
});
return ui;
- };
- editorui.fontfamily = function (editor, list, title) {
-
- list = editor.options['fontfamily'] || [];
- title = editor.options.labelMap['fontfamily'] || editor.getLang("labelMap.fontfamily") || '';
- if (!list.length) return;
- for (var i = 0, ci, items = []; ci = list[i]; i++) {
- var langLabel = editor.getLang('fontfamily')[ci.name] || "";
- (function (key, val) {
- items.push({
- label:key,
- value:val,
- theme:editor.options.theme,
- renderLabelHtml:function () {
- return '' + (this.label || '') + ' ';
- }
- });
- })(ci.label || langLabel, ci.val)
+ };
+ })(ci);
+ }
+
+ var dialogBtns = {
+ noOk: ["searchreplace", "help", "spechars", "webapp", "preview"],
+ ok: [
+ "attachment",
+ "anchor",
+ "link",
+ "insertimage",
+ "map",
+ "gmap",
+ "insertframe",
+ "wordimage",
+ "insertvideo",
+ "insertframe",
+ "edittip",
+ "edittable",
+ "edittd",
+ "scrawl",
+ "template",
+ "music",
+ "background",
+ "charts"
+ ]
+ };
+
+ for (var p in dialogBtns) {
+ (function(type, vals) {
+ for (var i = 0, ci; (ci = vals[i++]); ) {
+ //todo opera下存在问题
+ if (browser.opera && ci === "searchreplace") {
+ continue;
}
- var ui = new editorui.Combox({
- editor:editor,
- items:items,
- onselect:function (t, index) {
- editor.execCommand('FontFamily', this.items[index].value);
- },
- onbuttonclick:function () {
- this.showPopup();
- },
- title:title,
- initValue:title,
- className:'edui-for-fontfamily',
- indexByValue:function (value) {
- if (value) {
- for (var i = 0, ci; ci = this.items[i]; i++) {
- if (ci.value.indexOf(value) != -1)
- return i;
- }
- }
-
- return -1;
- }
- });
- editorui.buttons['fontfamily'] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- if (!uiReady) {
- var state = editor.queryCommandState('FontFamily');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('FontFamily');
- //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
- value && (value = value.replace(/['"]/g, '').split(',')[0]);
- ui.setValue(value);
-
- }
+ (function(cmd) {
+ editorui[cmd] = function(editor, iframeUrl, title) {
+ iframeUrl =
+ iframeUrl ||
+ (editor.options.iframeUrlMap || {})[cmd] ||
+ iframeUrlMap[cmd];
+ title =
+ editor.options.labelMap[cmd] ||
+ editor.getLang("labelMap." + cmd) ||
+ "";
+
+ var dialog;
+ //没有iframeUrl不创建dialog
+ if (iframeUrl) {
+ dialog = new editorui.Dialog(
+ utils.extend(
+ {
+ iframeUrl: editor.ui.mapUrl(iframeUrl),
+ editor: editor,
+ className: "edui-for-" + cmd,
+ title: title,
+ holdScroll: cmd === "insertimage",
+ fullscreen: /charts|preview/.test(cmd),
+ closeDialog: editor.getLang("closeDialog")
+ },
+ type == "ok"
+ ? {
+ buttons: [
+ {
+ className: "edui-okbutton",
+ label: editor.getLang("ok"),
+ editor: editor,
+ onclick: function() {
+ dialog.close(true);
+ }
+ },
+ {
+ className: "edui-cancelbutton",
+ label: editor.getLang("cancel"),
+ editor: editor,
+ onclick: function() {
+ dialog.close(false);
+ }
+ }
+ ]
+ }
+ : {}
+ )
+ );
+
+ editor.ui._dialogs[cmd + "Dialog"] = dialog;
}
- });
- return ui;
- };
-
- editorui.fontsize = function (editor, list, title) {
- title = editor.options.labelMap['fontsize'] || editor.getLang("labelMap.fontsize") || '';
- list = list || editor.options['fontsize'] || [];
- if (!list.length) return;
- var items = [];
- for (var i = 0; i < list.length; i++) {
- var size = list[i] + 'px';
- items.push({
- label:size,
- value:size,
- theme:editor.options.theme,
- renderLabelHtml:function () {
- return '' + (this.label || '') + ' ';
+ var ui = new editorui.Button({
+ className: "edui-for-" + cmd,
+ title: title,
+ onclick: function() {
+ if (dialog) {
+ switch (cmd) {
+ case "wordimage":
+ var images = editor.execCommand("wordimage");
+ if (images && images.length) {
+ dialog.render();
+ dialog.open();
+ }
+ break;
+ case "scrawl":
+ if (editor.queryCommandState("scrawl") != -1) {
+ dialog.render();
+ dialog.open();
+ }
+
+ break;
+ default:
+ dialog.render();
+ dialog.open();
+ }
}
+ },
+ theme: editor.options.theme,
+ disabled:
+ (cmd == "scrawl" && editor.queryCommandState("scrawl") == -1) ||
+ cmd == "charts"
+ });
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function() {
+ //只存在于右键菜单而无工具栏按钮的ui不需要检测状态
+ var unNeedCheckState = { edittable: 1 };
+ if (cmd in unNeedCheckState) return;
+
+ var state = editor.queryCommandState(cmd);
+ if (ui.getDom()) {
+ ui.setDisabled(state == -1);
+ ui.setChecked(state);
+ }
});
- }
- var ui = new editorui.Combox({
- editor:editor,
- items:items,
- title:title,
- initValue:title,
- onselect:function (t, index) {
- editor.execCommand('FontSize', this.items[index].value);
- },
- onbuttonclick:function () {
- this.showPopup();
- },
- className:'edui-for-fontsize'
- });
- editorui.buttons['fontsize'] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- if (!uiReady) {
- var state = editor.queryCommandState('FontSize');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- ui.setValue(editor.queryCommandValue('FontSize'));
- }
- }
-
- });
- return ui;
- };
- editorui.paragraph = function (editor, list, title) {
- title = editor.options.labelMap['paragraph'] || editor.getLang("labelMap.paragraph") || '';
- list = editor.options['paragraph'] || [];
- if (utils.isEmptyObject(list)) return;
- var items = [];
- for (var i in list) {
- items.push({
- value:i,
- label:list[i] || editor.getLang("paragraph")[i],
- theme:editor.options.theme,
- renderLabelHtml:function () {
- return '' + (this.label || '') + ' ';
- }
- })
- }
- var ui = new editorui.Combox({
- editor:editor,
- items:items,
- title:title,
- initValue:title,
- className:'edui-for-paragraph',
- onselect:function (t, index) {
- editor.execCommand('Paragraph', this.items[index].value);
- },
- onbuttonclick:function () {
- this.showPopup();
+ return ui;
+ };
+ })(ci.toLowerCase());
+ }
+ })(p, dialogBtns[p]);
+ }
+
+ editorui.snapscreen = function(editor, iframeUrl, title) {
+ title =
+ editor.options.labelMap["snapscreen"] ||
+ editor.getLang("labelMap.snapscreen") ||
+ "";
+ var ui = new editorui.Button({
+ className: "edui-for-snapscreen",
+ title: title,
+ onclick: function() {
+ editor.execCommand("snapscreen");
+ },
+ theme: editor.options.theme
+ });
+ editorui.buttons["snapscreen"] = ui;
+ iframeUrl =
+ iframeUrl ||
+ (editor.options.iframeUrlMap || {})["snapscreen"] ||
+ iframeUrlMap["snapscreen"];
+ if (iframeUrl) {
+ var dialog = new editorui.Dialog({
+ iframeUrl: editor.ui.mapUrl(iframeUrl),
+ editor: editor,
+ className: "edui-for-snapscreen",
+ title: title,
+ buttons: [
+ {
+ className: "edui-okbutton",
+ label: editor.getLang("ok"),
+ editor: editor,
+ onclick: function() {
+ dialog.close(true);
}
- });
- editorui.buttons['paragraph'] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- if (!uiReady) {
- var state = editor.queryCommandState('Paragraph');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('Paragraph');
- var index = ui.indexByValue(value);
- if (index != -1) {
- ui.setValue(value);
- } else {
- ui.setValue(ui.initValue);
- }
- }
+ },
+ {
+ className: "edui-cancelbutton",
+ label: editor.getLang("cancel"),
+ editor: editor,
+ onclick: function() {
+ dialog.close(false);
}
-
- });
- return ui;
- };
-
-
- //自定义标题
- editorui.customstyle = function (editor) {
- var list = editor.options['customstyle'] || [],
- title = editor.options.labelMap['customstyle'] || editor.getLang("labelMap.customstyle") || '';
- if (!list.length)return;
- var langCs = editor.getLang('customstyle');
- for (var i = 0, items = [], t; t = list[i++];) {
- (function (t) {
- var ck = {};
- ck.label = t.label ? t.label : langCs[t.name];
- ck.style = t.style;
- ck.className = t.className;
- ck.tag = t.tag;
- items.push({
- label:ck.label,
- value:ck,
- theme:editor.options.theme,
- renderLabelHtml:function () {
- return '' + '<' + ck.tag + ' ' + (ck.className ? ' class="' + ck.className + '"' : "")
- + (ck.style ? ' style="' + ck.style + '"' : "") + '>' + ck.label + "<\/" + ck.tag + ">"
- + ' ';
- }
- });
- })(t);
+ }
+ ]
+ });
+ dialog.render();
+ editor.ui._dialogs["snapscreenDialog"] = dialog;
+ }
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState("snapscreen") == -1);
+ });
+ return ui;
+ };
+
+ editorui.insertcode = function(editor, list, title) {
+ list = editor.options["insertcode"] || [];
+ title =
+ editor.options.labelMap["insertcode"] ||
+ editor.getLang("labelMap.insertcode") ||
+ "";
+ // if (!list.length) return;
+ var items = [];
+ utils.each(list, function(key, val) {
+ items.push({
+ label: key,
+ value: val,
+ theme: editor.options.theme,
+ renderLabelHtml: function() {
+ return (
+ '' + (this.label || "") + " "
+ );
+ }
+ });
+ });
+
+ var ui = new editorui.Combox({
+ editor: editor,
+ items: items,
+ onselect: function(t, index) {
+ editor.execCommand("insertcode", this.items[index].value);
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ },
+ title: title,
+ initValue: title,
+ className: "edui-for-insertcode",
+ indexByValue: function(value) {
+ if (value) {
+ for (var i = 0, ci; (ci = this.items[i]); i++) {
+ if (ci.value.indexOf(value) != -1) return i;
+ }
}
- var ui = new editorui.Combox({
- editor:editor,
- items:items,
- title:title,
- initValue:title,
- className:'edui-for-customstyle',
- onselect:function (t, index) {
- editor.execCommand('customstyle', this.items[index].value);
- },
- onbuttonclick:function () {
- this.showPopup();
- },
- indexByValue:function (value) {
- for (var i = 0, ti; ti = this.items[i++];) {
- if (ti.label == value) {
- return i - 1
- }
- }
- return -1;
- }
- });
- editorui.buttons['customstyle'] = ui;
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- if (!uiReady) {
- var state = editor.queryCommandState('customstyle');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('customstyle');
- var index = ui.indexByValue(value);
- if (index != -1) {
- ui.setValue(value);
- } else {
- ui.setValue(ui.initValue);
- }
- }
- }
-
- });
- return ui;
- };
- editorui.inserttable = function (editor, iframeUrl, title) {
- title = editor.options.labelMap['inserttable'] || editor.getLang("labelMap.inserttable") || '';
- var ui = new editorui.TableButton({
- editor:editor,
- title:title,
- className:'edui-for-inserttable',
- onpicktable:function (t, numCols, numRows) {
- editor.execCommand('InsertTable', {numRows:numRows, numCols:numCols, border:1});
- },
- onbuttonclick:function () {
- this.showPopup();
- }
- });
- editorui.buttons['inserttable'] = ui;
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState('inserttable') == -1);
- });
- return ui;
- };
-
- editorui.lineheight = function (editor) {
- var val = editor.options.lineheight || [];
- if (!val.length)return;
- for (var i = 0, ci, items = []; ci = val[i++];) {
- items.push({
- //todo:写死了
- label:ci,
- value:ci,
- theme:editor.options.theme,
- onclick:function () {
- editor.execCommand("lineheight", this.value);
- }
- })
+ return -1;
+ }
+ });
+ editorui.buttons["insertcode"] = ui;
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ if (!uiReady) {
+ var state = editor.queryCommandState("insertcode");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("insertcode");
+ if (!value) {
+ ui.setValue(title);
+ return;
+ }
+ //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
+ value && (value = value.replace(/['"]/g, "").split(",")[0]);
+ ui.setValue(value);
}
- var ui = new editorui.MenuButton({
- editor:editor,
- className:'edui-for-lineheight',
- title:editor.options.labelMap['lineheight'] || editor.getLang("labelMap.lineheight") || '',
- items:items,
- onbuttonclick:function () {
- var value = editor.queryCommandValue('LineHeight') || this.value;
- editor.execCommand("LineHeight", value);
- }
+ }
+ });
+ return ui;
+ };
+ editorui.fontfamily = function(editor, list, title) {
+ list = editor.options["fontfamily"] || [];
+ title =
+ editor.options.labelMap["fontfamily"] ||
+ editor.getLang("labelMap.fontfamily") ||
+ "";
+ if (!list.length) return;
+ for (var i = 0, ci, items = []; (ci = list[i]); i++) {
+ var langLabel = editor.getLang("fontfamily")[ci.name] || "";
+ (function(key, val) {
+ items.push({
+ label: key,
+ value: val,
+ theme: editor.options.theme,
+ renderLabelHtml: function() {
+ return (
+ '' +
+ (this.label || "") +
+ " "
+ );
+ }
});
- editorui.buttons['lineheight'] = ui;
- editor.addListener('selectionchange', function () {
- var state = editor.queryCommandState('LineHeight');
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('LineHeight');
- value && ui.setValue((value + '').replace(/cm/, ''));
- ui.setChecked(state)
- }
- });
- return ui;
- };
+ })(ci.label || langLabel, ci.val);
+ }
+ var ui = new editorui.Combox({
+ editor: editor,
+ items: items,
+ onselect: function(t, index) {
+ editor.execCommand("FontFamily", this.items[index].value);
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ },
+ title: title,
+ initValue: title,
+ className: "edui-for-fontfamily",
+ indexByValue: function(value) {
+ if (value) {
+ for (var i = 0, ci; (ci = this.items[i]); i++) {
+ if (ci.value.indexOf(value) != -1) return i;
+ }
+ }
- var rowspacings = ['top', 'bottom'];
- for (var r = 0, ri; ri = rowspacings[r++];) {
- (function (cmd) {
- editorui['rowspacing' + cmd] = function (editor) {
- var val = editor.options['rowspacing' + cmd] || [];
- if (!val.length) return null;
- for (var i = 0, ci, items = []; ci = val[i++];) {
- items.push({
- label:ci,
- value:ci,
- theme:editor.options.theme,
- onclick:function () {
- editor.execCommand("rowspacing", this.value, cmd);
- }
- })
- }
- var ui = new editorui.MenuButton({
- editor:editor,
- className:'edui-for-rowspacing' + cmd,
- title:editor.options.labelMap['rowspacing' + cmd] || editor.getLang("labelMap.rowspacing" + cmd) || '',
- items:items,
- onbuttonclick:function () {
- var value = editor.queryCommandValue('rowspacing', cmd) || this.value;
- editor.execCommand("rowspacing", value, cmd);
- }
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function () {
- var state = editor.queryCommandState('rowspacing', cmd);
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue('rowspacing', cmd);
- value && ui.setValue((value + '').replace(/%/, ''));
- ui.setChecked(state)
- }
- });
- return ui;
- }
- })(ri)
+ return -1;
+ }
+ });
+ editorui.buttons["fontfamily"] = ui;
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ if (!uiReady) {
+ var state = editor.queryCommandState("FontFamily");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("FontFamily");
+ //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
+ value && (value = value.replace(/['"]/g, "").split(",")[0]);
+ ui.setValue(value);
+ }
+ }
+ });
+ return ui;
+ };
+
+ editorui.fontsize = function(editor, list, title) {
+ title =
+ editor.options.labelMap["fontsize"] ||
+ editor.getLang("labelMap.fontsize") ||
+ "";
+ list = list || editor.options["fontsize"] || [];
+ if (!list.length) return;
+ var items = [];
+ for (var i = 0; i < list.length; i++) {
+ var size = list[i] + "px";
+ items.push({
+ label: size,
+ value: size,
+ theme: editor.options.theme,
+ renderLabelHtml: function() {
+ return (
+ '' +
+ (this.label || "") +
+ " "
+ );
+ }
+ });
}
- //有序,无序列表
- var lists = ['insertorderedlist', 'insertunorderedlist'];
- for (var l = 0, cl; cl = lists[l++];) {
- (function (cmd) {
- editorui[cmd] = function (editor) {
- var vals = editor.options[cmd],
- _onMenuClick = function () {
- editor.execCommand(cmd, this.value);
- }, items = [];
- for (var i in vals) {
- items.push({
- label:vals[i] || editor.getLang()[cmd][i] || "",
- value:i,
- theme:editor.options.theme,
- onclick:_onMenuClick
- })
- }
- var ui = new editorui.MenuButton({
- editor:editor,
- className:'edui-for-' + cmd,
- title:editor.getLang("labelMap." + cmd) || '',
- 'items':items,
- onbuttonclick:function () {
- var value = editor.queryCommandValue(cmd) || this.value;
- editor.execCommand(cmd, value);
- }
- });
- editorui.buttons[cmd] = ui;
- editor.addListener('selectionchange', function () {
- var state = editor.queryCommandState(cmd);
- if (state == -1) {
- ui.setDisabled(true);
- } else {
- ui.setDisabled(false);
- var value = editor.queryCommandValue(cmd);
- ui.setValue(value);
- ui.setChecked(state)
- }
- });
- return ui;
- };
- })(cl)
+ var ui = new editorui.Combox({
+ editor: editor,
+ items: items,
+ title: title,
+ initValue: title,
+ onselect: function(t, index) {
+ editor.execCommand("FontSize", this.items[index].value);
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ },
+ className: "edui-for-fontsize"
+ });
+ editorui.buttons["fontsize"] = ui;
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ if (!uiReady) {
+ var state = editor.queryCommandState("FontSize");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ ui.setValue(editor.queryCommandValue("FontSize"));
+ }
+ }
+ });
+ return ui;
+ };
+
+ editorui.paragraph = function(editor, list, title) {
+ title =
+ editor.options.labelMap["paragraph"] ||
+ editor.getLang("labelMap.paragraph") ||
+ "";
+ list = editor.options["paragraph"] || [];
+ if (utils.isEmptyObject(list)) return;
+ var items = [];
+ for (var i in list) {
+ items.push({
+ value: i,
+ label: list[i] || editor.getLang("paragraph")[i],
+ theme: editor.options.theme,
+ renderLabelHtml: function() {
+ return (
+ '' +
+ (this.label || "") +
+ " "
+ );
+ }
+ });
}
-
- editorui.fullscreen = function (editor, title) {
- title = editor.options.labelMap['fullscreen'] || editor.getLang("labelMap.fullscreen") || '';
- var ui = new editorui.Button({
- className:'edui-for-fullscreen',
- title:title,
- theme:editor.options.theme,
- onclick:function () {
- if (editor.ui) {
- editor.ui.setFullScreen(!editor.ui.isFullScreen());
- }
- this.setChecked(editor.ui.isFullScreen());
- }
- });
- editorui.buttons['fullscreen'] = ui;
- editor.addListener('selectionchange', function () {
- var state = editor.queryCommandState('fullscreen');
- ui.setDisabled(state == -1);
- ui.setChecked(editor.ui.isFullScreen());
- });
- return ui;
- };
-
- // 表情
- editorui["emotion"] = function (editor, iframeUrl) {
- var cmd = "emotion";
- var ui = new editorui.MultiMenuPop({
- title:editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd + "") || '',
- editor:editor,
- className:'edui-for-' + cmd,
- iframeUrl:editor.ui.mapUrl(iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd])
+ var ui = new editorui.Combox({
+ editor: editor,
+ items: items,
+ title: title,
+ initValue: title,
+ className: "edui-for-paragraph",
+ onselect: function(t, index) {
+ editor.execCommand("Paragraph", this.items[index].value);
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ }
+ });
+ editorui.buttons["paragraph"] = ui;
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ if (!uiReady) {
+ var state = editor.queryCommandState("Paragraph");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("Paragraph");
+ var index = ui.indexByValue(value);
+ if (index != -1) {
+ ui.setValue(value);
+ } else {
+ ui.setValue(ui.initValue);
+ }
+ }
+ }
+ });
+ return ui;
+ };
+
+ //自定义标题
+ editorui.customstyle = function(editor) {
+ var list = editor.options["customstyle"] || [],
+ title =
+ editor.options.labelMap["customstyle"] ||
+ editor.getLang("labelMap.customstyle") ||
+ "";
+ if (!list.length) return;
+ var langCs = editor.getLang("customstyle");
+ for (var i = 0, items = [], t; (t = list[i++]); ) {
+ (function(t) {
+ var ck = {};
+ ck.label = t.label ? t.label : langCs[t.name];
+ ck.style = t.style;
+ ck.className = t.className;
+ ck.tag = t.tag;
+ items.push({
+ label: ck.label,
+ value: ck,
+ theme: editor.options.theme,
+ renderLabelHtml: function() {
+ return (
+ '' +
+ "<" +
+ ck.tag +
+ " " +
+ (ck.className ? ' class="' + ck.className + '"' : "") +
+ (ck.style ? ' style="' + ck.style + '"' : "") +
+ ">" +
+ ck.label +
+ "" +
+ ck.tag +
+ ">" +
+ " "
+ );
+ }
});
- editorui.buttons[cmd] = ui;
+ })(t);
+ }
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState(cmd) == -1)
+ var ui = new editorui.Combox({
+ editor: editor,
+ items: items,
+ title: title,
+ initValue: title,
+ className: "edui-for-customstyle",
+ onselect: function(t, index) {
+ editor.execCommand("customstyle", this.items[index].value);
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ },
+ indexByValue: function(value) {
+ for (var i = 0, ti; (ti = this.items[i++]); ) {
+ if (ti.label == value) {
+ return i - 1;
+ }
+ }
+ return -1;
+ }
+ });
+ editorui.buttons["customstyle"] = ui;
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ if (!uiReady) {
+ var state = editor.queryCommandState("customstyle");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("customstyle");
+ var index = ui.indexByValue(value);
+ if (index != -1) {
+ ui.setValue(value);
+ } else {
+ ui.setValue(ui.initValue);
+ }
+ }
+ }
+ });
+ return ui;
+ };
+ editorui.inserttable = function(editor, iframeUrl, title) {
+ title =
+ editor.options.labelMap["inserttable"] ||
+ editor.getLang("labelMap.inserttable") ||
+ "";
+ var ui = new editorui.TableButton({
+ editor: editor,
+ title: title,
+ className: "edui-for-inserttable",
+ onpicktable: function(t, numCols, numRows) {
+ editor.execCommand("InsertTable", {
+ numRows: numRows,
+ numCols: numCols,
+ border: 1
});
- return ui;
- };
-
- editorui.autotypeset = function (editor) {
- var ui = new editorui.AutoTypeSetButton({
- editor:editor,
- title:editor.options.labelMap['autotypeset'] || editor.getLang("labelMap.autotypeset") || '',
- className:'edui-for-autotypeset',
- onbuttonclick:function () {
- editor.execCommand('autotypeset')
+ },
+ onbuttonclick: function() {
+ this.showPopup();
+ }
+ });
+ editorui.buttons["inserttable"] = ui;
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState("inserttable") == -1);
+ });
+ return ui;
+ };
+
+ editorui.lineheight = function(editor) {
+ var val = editor.options.lineheight || [];
+ if (!val.length) return;
+ for (var i = 0, ci, items = []; (ci = val[i++]); ) {
+ items.push({
+ //todo:写死了
+ label: ci,
+ value: ci,
+ theme: editor.options.theme,
+ onclick: function() {
+ editor.execCommand("lineheight", this.value);
+ }
+ });
+ }
+ var ui = new editorui.MenuButton({
+ editor: editor,
+ className: "edui-for-lineheight",
+ title:
+ editor.options.labelMap["lineheight"] ||
+ editor.getLang("labelMap.lineheight") ||
+ "",
+ items: items,
+ onbuttonclick: function() {
+ var value = editor.queryCommandValue("LineHeight") || this.value;
+ editor.execCommand("LineHeight", value);
+ }
+ });
+ editorui.buttons["lineheight"] = ui;
+ editor.addListener("selectionchange", function() {
+ var state = editor.queryCommandState("LineHeight");
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("LineHeight");
+ value && ui.setValue((value + "").replace(/cm/, ""));
+ ui.setChecked(state);
+ }
+ });
+ return ui;
+ };
+
+ var rowspacings = ["top", "bottom"];
+ for (var r = 0, ri; (ri = rowspacings[r++]); ) {
+ (function(cmd) {
+ editorui["rowspacing" + cmd] = function(editor) {
+ var val = editor.options["rowspacing" + cmd] || [];
+ if (!val.length) return null;
+ for (var i = 0, ci, items = []; (ci = val[i++]); ) {
+ items.push({
+ label: ci,
+ value: ci,
+ theme: editor.options.theme,
+ onclick: function() {
+ editor.execCommand("rowspacing", this.value, cmd);
}
+ });
+ }
+ var ui = new editorui.MenuButton({
+ editor: editor,
+ className: "edui-for-rowspacing" + cmd,
+ title:
+ editor.options.labelMap["rowspacing" + cmd] ||
+ editor.getLang("labelMap.rowspacing" + cmd) ||
+ "",
+ items: items,
+ onbuttonclick: function() {
+ var value =
+ editor.queryCommandValue("rowspacing", cmd) || this.value;
+ editor.execCommand("rowspacing", value, cmd);
+ }
});
- editorui.buttons['autotypeset'] = ui;
- editor.addListener('selectionchange', function () {
- ui.setDisabled(editor.queryCommandState('autotypeset') == -1);
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function() {
+ var state = editor.queryCommandState("rowspacing", cmd);
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue("rowspacing", cmd);
+ value && ui.setValue((value + "").replace(/%/, ""));
+ ui.setChecked(state);
+ }
});
return ui;
- };
-
- /* 简单上传插件 */
- editorui["simpleupload"] = function (editor) {
- var name = 'simpleupload',
- ui = new editorui.Button({
- className:'edui-for-' + name,
- title:editor.options.labelMap[name] || editor.getLang("labelMap." + name) || '',
- onclick:function () {},
- theme:editor.options.theme,
- showText:false
- });
- editorui.buttons[name] = ui;
- editor.addListener('ready', function() {
- var b = ui.getDom('body'),
- iconSpan = b.children[0];
- editor.fireEvent('simpleuploadbtnready', iconSpan);
+ };
+ })(ri);
+ }
+ //有序,无序列表
+ var lists = ["insertorderedlist", "insertunorderedlist"];
+ for (var l = 0, cl; (cl = lists[l++]); ) {
+ (function(cmd) {
+ editorui[cmd] = function(editor) {
+ var vals = editor.options[cmd],
+ _onMenuClick = function() {
+ editor.execCommand(cmd, this.value);
+ },
+ items = [];
+ for (var i in vals) {
+ items.push({
+ label: vals[i] || editor.getLang()[cmd][i] || "",
+ value: i,
+ theme: editor.options.theme,
+ onclick: _onMenuClick
+ });
+ }
+ var ui = new editorui.MenuButton({
+ editor: editor,
+ className: "edui-for-" + cmd,
+ title: editor.getLang("labelMap." + cmd) || "",
+ items: items,
+ onbuttonclick: function() {
+ var value = editor.queryCommandValue(cmd) || this.value;
+ editor.execCommand(cmd, value);
+ }
});
- editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
- var state = editor.queryCommandState(name);
- if (state == -1) {
- ui.setDisabled(true);
- ui.setChecked(false);
- } else {
- if (!uiReady) {
- ui.setDisabled(false);
- ui.setChecked(state);
- }
- }
+ editorui.buttons[cmd] = ui;
+ editor.addListener("selectionchange", function() {
+ var state = editor.queryCommandState(cmd);
+ if (state == -1) {
+ ui.setDisabled(true);
+ } else {
+ ui.setDisabled(false);
+ var value = editor.queryCommandValue(cmd);
+ ui.setValue(value);
+ ui.setChecked(state);
+ }
});
return ui;
- };
-
+ };
+ })(cl);
+ }
+
+ editorui.fullscreen = function(editor, title) {
+ title =
+ editor.options.labelMap["fullscreen"] ||
+ editor.getLang("labelMap.fullscreen") ||
+ "";
+ var ui = new editorui.Button({
+ className: "edui-for-fullscreen",
+ title: title,
+ theme: editor.options.theme,
+ onclick: function() {
+ if (editor.ui) {
+ editor.ui.setFullScreen(!editor.ui.isFullScreen());
+ }
+ this.setChecked(editor.ui.isFullScreen());
+ }
+ });
+ editorui.buttons["fullscreen"] = ui;
+ editor.addListener("selectionchange", function() {
+ var state = editor.queryCommandState("fullscreen");
+ ui.setDisabled(state == -1);
+ ui.setChecked(editor.ui.isFullScreen());
+ });
+ return ui;
+ };
+
+ // 表情
+ editorui["emotion"] = function(editor, iframeUrl) {
+ var cmd = "emotion";
+ var ui = new editorui.MultiMenuPop({
+ title:
+ editor.options.labelMap[cmd] ||
+ editor.getLang("labelMap." + cmd + "") ||
+ "",
+ editor: editor,
+ className: "edui-for-" + cmd,
+ iframeUrl: editor.ui.mapUrl(
+ iframeUrl ||
+ (editor.options.iframeUrlMap || {})[cmd] ||
+ iframeUrlMap[cmd]
+ )
+ });
+ editorui.buttons[cmd] = ui;
+
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState(cmd) == -1);
+ });
+ return ui;
+ };
+
+ editorui.autotypeset = function(editor) {
+ var ui = new editorui.AutoTypeSetButton({
+ editor: editor,
+ title:
+ editor.options.labelMap["autotypeset"] ||
+ editor.getLang("labelMap.autotypeset") ||
+ "",
+ className: "edui-for-autotypeset",
+ onbuttonclick: function() {
+ editor.execCommand("autotypeset");
+ }
+ });
+ editorui.buttons["autotypeset"] = ui;
+ editor.addListener("selectionchange", function() {
+ ui.setDisabled(editor.queryCommandState("autotypeset") == -1);
+ });
+ return ui;
+ };
+
+ /* 简单上传插件 */
+ editorui["simpleupload"] = function(editor) {
+ var name = "simpleupload",
+ ui = new editorui.Button({
+ className: "edui-for-" + name,
+ title:
+ editor.options.labelMap[name] ||
+ editor.getLang("labelMap." + name) ||
+ "",
+ onclick: function() {},
+ theme: editor.options.theme,
+ showText: false
+ });
+ editorui.buttons[name] = ui;
+ editor.addListener("ready", function() {
+ var b = ui.getDom("body"),
+ iconSpan = b.children[0];
+ editor.fireEvent("simpleuploadbtnready", iconSpan);
+ });
+ editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
+ var state = editor.queryCommandState(name);
+ if (state == -1) {
+ ui.setDisabled(true);
+ ui.setChecked(false);
+ } else {
+ if (!uiReady) {
+ ui.setDisabled(false);
+ ui.setChecked(state);
+ }
+ }
+ });
+ return ui;
+ };
})();
diff --git a/_src/adapter/message.js b/_src/adapter/message.js
index ffe2e6df2..d9b14b019 100644
--- a/_src/adapter/message.js
+++ b/_src/adapter/message.js
@@ -1,64 +1,67 @@
-UE.registerUI('message', function(editor) {
+UE.registerUI("message", function(editor) {
+ var editorui = baidu.editor.ui;
+ var Message = editorui.Message;
+ var holder;
+ var _messageItems = [];
+ var me = editor;
- var editorui = baidu.editor.ui;
- var Message = editorui.Message;
- var holder;
- var _messageItems = [];
- var me = editor;
+ me.setOpt("enableMessageShow", true);
+ if (me.getOpt("enableMessageShow") === false) {
+ return;
+ }
- me.setOpt('enableMessageShow', true);
- if (me.getOpt('enableMessageShow') === false) {
- return;
- }
-
- me.addListener('ready', function(){
- holder = document.getElementById(me.ui.id + '_message_holder');
- updateHolderPos();
- setTimeout(function(){
- updateHolderPos();
- }, 500);
- });
+ me.addListener("ready", function() {
+ holder = document.getElementById(me.ui.id + "_message_holder");
+ updateHolderPos();
+ setTimeout(function() {
+ updateHolderPos();
+ }, 500);
+ });
- me.addListener('showmessage', function(type, opt){
- opt = utils.isString(opt) ? {
- 'content': opt
- } : opt;
- var message = new Message({
- 'timeout': opt.timeout,
- 'type': opt.type,
- 'content': opt.content,
- 'keepshow': opt.keepshow,
- 'editor': me
- }),
- mid = opt.id || ('msg_' + (+new Date()).toString(36));
- message.render(holder);
- _messageItems[mid] = message;
- message.reset(opt);
- updateHolderPos();
- return mid;
- });
+ me.addListener("showmessage", function(type, opt) {
+ opt = utils.isString(opt)
+ ? {
+ content: opt
+ }
+ : opt;
+ var message = new Message({
+ timeout: opt.timeout,
+ type: opt.type,
+ content: opt.content,
+ keepshow: opt.keepshow,
+ editor: me
+ }),
+ mid = opt.id || "msg_" + (+new Date()).toString(36);
+ message.render(holder);
+ _messageItems[mid] = message;
+ message.reset(opt);
+ updateHolderPos();
+ return mid;
+ });
- me.addListener('updatemessage',function(type, id, opt){
- opt = utils.isString(opt) ? {
- 'content': opt
- } : opt;
- var message = _messageItems[id];
- message.render(holder);
- message && message.reset(opt);
- });
+ me.addListener("updatemessage", function(type, id, opt) {
+ opt = utils.isString(opt)
+ ? {
+ content: opt
+ }
+ : opt;
+ var message = _messageItems[id];
+ message.render(holder);
+ message && message.reset(opt);
+ });
- me.addListener('hidemessage',function(type, id){
- var message = _messageItems[id];
- message && message.hide();
- });
+ me.addListener("hidemessage", function(type, id) {
+ var message = _messageItems[id];
+ message && message.hide();
+ });
- function updateHolderPos(){
- if (!holder || !me.ui) return;
- var toolbarbox = me.ui.getDom('toolbarbox');
- if (toolbarbox) {
- holder.style.top = toolbarbox.offsetHeight + 3 + 'px';
- }
- holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1;
+ function updateHolderPos() {
+ if (!holder || !me.ui) return;
+ var toolbarbox = me.ui.getDom("toolbarbox");
+ if (toolbarbox) {
+ holder.style.top = toolbarbox.offsetHeight + 3 + "px";
}
-
+ holder.style.zIndex =
+ Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1;
+ }
});
diff --git a/_src/api.js b/_src/api.js
index bb206ca62..0c78d47fe 100644
--- a/_src/api.js
+++ b/_src/api.js
@@ -59,4 +59,4 @@
/**
* UEditor模拟dom节点对象
* @class uNode
- */
\ No newline at end of file
+ */
diff --git a/_src/core/Editor.defaultoptions.js b/_src/core/Editor.defaultoptions.js
index 18a7132aa..46afe312e 100644
--- a/_src/core/Editor.defaultoptions.js
+++ b/_src/core/Editor.defaultoptions.js
@@ -1,31 +1,30 @@
//维护编辑器一下默认的不在插件中的配置项
-UE.Editor.defaultOptions = function(editor){
-
- var _url = editor.options.UEDITOR_HOME_URL;
- return {
- isShow: true,
- initialContent: '',
- initialStyle:'',
- autoClearinitialContent: false,
- iframeCssUrl: _url + 'themes/iframe.css',
- textarea: 'editorValue',
- focus: false,
- focusInEnd: true,
- autoClearEmptyNode: true,
- fullscreen: false,
- readonly: false,
- zIndex: 999,
- imagePopup: true,
- enterTag: 'p',
- customDomain: false,
- lang: 'zh-cn',
- langPath: _url + 'lang/',
- theme: 'default',
- themePath: _url + 'themes/',
- allHtmlEnabled: false,
- scaleEnabled: false,
- tableNativeEditInFF: false,
- autoSyncData : true,
- fileNameFormat: '{time}{rand:6}'
- }
-};
\ No newline at end of file
+UE.Editor.defaultOptions = function(editor) {
+ var _url = editor.options.UEDITOR_HOME_URL;
+ return {
+ isShow: true,
+ initialContent: "",
+ initialStyle: "",
+ autoClearinitialContent: false,
+ iframeCssUrl: _url + "themes/iframe.css",
+ textarea: "editorValue",
+ focus: false,
+ focusInEnd: true,
+ autoClearEmptyNode: true,
+ fullscreen: false,
+ readonly: false,
+ zIndex: 999,
+ imagePopup: true,
+ enterTag: "p",
+ customDomain: false,
+ lang: "zh-cn",
+ langPath: _url + "lang/",
+ theme: "default",
+ themePath: _url + "themes/",
+ allHtmlEnabled: false,
+ scaleEnabled: false,
+ tableNativeEditInFF: false,
+ autoSyncData: true,
+ fileNameFormat: "{time}{rand:6}"
+ };
+};
diff --git a/_src/core/Editor.js b/_src/core/Editor.js
index 1d4a0d77d..2a99d6013 100644
--- a/_src/core/Editor.js
+++ b/_src/core/Editor.js
@@ -1,1533 +1,1664 @@
-/**
- * 编辑器主类,包含编辑器提供的大部分公用接口
- * @file
- * @module UE
- * @class Editor
- * @since 1.2.6.1
- */
-
-/**
- * UEditor公用空间,UEditor所有的功能都挂载在该空间下
- * @unfile
- * @module UE
- */
-
-/**
- * UEditor的核心类,为用户提供与编辑器交互的接口。
- * @unfile
- * @module UE
- * @class Editor
- */
-
-(function () {
- var uid = 0, _selectionChangeTimer;
-
- /**
- * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面
- * @private
- * @method setValue
- * @param { UE.Editor } editor 编辑器事例
- */
- function setValue(form, editor) {
- var textarea;
- if (editor.options.textarea) {
- if (utils.isString(editor.options.textarea)) {
- for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, 'textarea'); ti = tis[i++];) {
- if (ti.id == 'ueditor_textarea_' + editor.options.textarea) {
- textarea = ti;
- break;
- }
- }
- } else {
- textarea = editor.textarea;
- }
- }
- if (!textarea) {
- form.appendChild(textarea = domUtils.createElement(document, 'textarea', {
- 'name': editor.options.textarea,
- 'id': 'ueditor_textarea_' + editor.options.textarea,
- 'style': "display:none"
- }));
- //不要产生多个textarea
- editor.textarea = textarea;
- }
- !textarea.getAttribute('name') && textarea.setAttribute('name', editor.options.textarea );
- textarea.value = editor.hasContents() ?
- (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) :
- ''
- }
- function loadPlugins(me){
- //初始化插件
- for (var pi in UE.plugins) {
- UE.plugins[pi].call(me);
- }
-
- }
- function checkCurLang(I18N){
- for(var lang in I18N){
- return lang
- }
- }
-
- function langReadied(me){
- me.langIsReady = true;
-
- me.fireEvent("langReady");
- }
-
- /**
- * 编辑器准备就绪后会触发该事件
- * @module UE
- * @class Editor
- * @event ready
- * @remind render方法执行完成之后,会触发该事件
- * @remind
- * @example
- * ```javascript
- * editor.addListener( 'ready', function( editor ) {
- * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点
- * } );
- * ```
- */
- /**
- * 执行destroy方法,会触发该事件
- * @module UE
- * @class Editor
- * @event destroy
- * @see UE.Editor:destroy()
- */
- /**
- * 执行reset方法,会触发该事件
- * @module UE
- * @class Editor
- * @event reset
- * @see UE.Editor:reset()
- */
- /**
- * 执行focus方法,会触发该事件
- * @module UE
- * @class Editor
- * @event focus
- * @see UE.Editor:focus(Boolean)
- */
- /**
- * 语言加载完成会触发该事件
- * @module UE
- * @class Editor
- * @event langReady
- */
- /**
- * 运行命令之后会触发该命令
- * @module UE
- * @class Editor
- * @event beforeExecCommand
- */
- /**
- * 运行命令之后会触发该命令
- * @module UE
- * @class Editor
- * @event afterExecCommand
- */
- /**
- * 运行命令之前会触发该命令
- * @module UE
- * @class Editor
- * @event firstBeforeExecCommand
- */
- /**
- * 在getContent方法执行之前会触发该事件
- * @module UE
- * @class Editor
- * @event beforeGetContent
- * @see UE.Editor:getContent()
- */
- /**
- * 在getContent方法执行之后会触发该事件
- * @module UE
- * @class Editor
- * @event afterGetContent
- * @see UE.Editor:getContent()
- */
- /**
- * 在getAllHtml方法执行时会触发该事件
- * @module UE
- * @class Editor
- * @event getAllHtml
- * @see UE.Editor:getAllHtml()
- */
- /**
- * 在setContent方法执行之前会触发该事件
- * @module UE
- * @class Editor
- * @event beforeSetContent
- * @see UE.Editor:setContent(String)
- */
- /**
- * 在setContent方法执行之后会触发该事件
- * @module UE
- * @class Editor
- * @event afterSetContent
- * @see UE.Editor:setContent(String)
- */
- /**
- * 每当编辑器内部选区发生改变时,将触发该事件
- * @event selectionchange
- * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理
- * @example
- * ```javascript
- * editor.addListener( 'selectionchange', function( editor ) {
- * console.log('选区发生改变');
- * }
- */
- /**
- * 在所有selectionchange的监听函数执行之前,会触发该事件
- * @module UE
- * @class Editor
- * @event beforeSelectionChange
- * @see UE.Editor:selectionchange
- */
- /**
- * 在所有selectionchange的监听函数执行完之后,会触发该事件
- * @module UE
- * @class Editor
- * @event afterSelectionChange
- * @see UE.Editor:selectionchange
- */
- /**
- * 编辑器内容发生改变时会触发该事件
- * @module UE
- * @class Editor
- * @event contentChange
- */
-
-
- /**
- * 以默认参数构建一个编辑器实例
- * @constructor
- * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面
- * @example
- * ```javascript
- * var editor = new UE.Editor();
- * editor.execCommand('blod');
- * ```
- * @see UE.Config
- */
-
- /**
- * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。
- * @constructor
- * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面
- * @param { Object } setting 创建编辑器的参数
- * @example
- * ```javascript
- * var editor = new UE.Editor();
- * editor.execCommand('blod');
- * ```
- * @see UE.Config
- */
- var Editor = UE.Editor = function (options) {
- var me = this;
- me.uid = uid++;
- EventBase.call(me);
- me.commands = {};
- me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);
- me.shortcutkeys = {};
- me.inputRules = [];
- me.outputRules = [];
- //设置默认的常用属性
- me.setOpt(Editor.defaultOptions(me));
-
- /* 尝试异步加载后台配置 */
- me.loadServerConfig();
-
- if(!utils.isEmptyObject(UE.I18N)){
- //修改默认的语言类型
- me.options.lang = checkCurLang(UE.I18N);
- UE.plugin.load(me);
- langReadied(me);
-
- }else{
- utils.loadFile(document, {
- src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js",
- tag: "script",
- type: "text/javascript",
- defer: "defer"
- }, function () {
- UE.plugin.load(me);
- langReadied(me);
- });
- }
-
- UE.instants['ueditorInstant' + me.uid] = me;
- };
- Editor.prototype = {
- registerCommand : function(name,obj){
- this.commands[name] = obj;
- },
- /**
- * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的
- * @method ready
- * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会
- * 立即触发该回调。
- * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入
- * @example
- * ```javascript
- * editor.ready( function( editor ) {
- * editor.setContent('初始化完毕');
- * } );
- * ```
- * @see UE.Editor.event:ready
- */
- ready: function (fn) {
- var me = this;
- if (fn) {
- me.isReady ? fn.apply(me) : me.addListener('ready', fn);
- }
- },
-
- /**
- * 该方法是提供给插件里面使用,设置配置项默认值
- * @method setOpt
- * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置
- * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。
- * @param { String } key 编辑器的可接受的选项名称
- * @param { * } val 该选项可接受的值
- * @example
- * ```javascript
- * editor.setOpt( 'initContent', '欢迎使用编辑器' );
- * ```
- */
-
- /**
- * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值
- * @method setOpt
- * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置
- * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。
- * @param { Object } options 将要设置的选项的键值对对象
- * @example
- * ```javascript
- * editor.setOpt( {
- * 'initContent': '欢迎使用编辑器'
- * } );
- * ```
- */
- setOpt: function (key, val) {
- var obj = {};
- if (utils.isString(key)) {
- obj[key] = val
- } else {
- obj = key;
- }
- utils.extend(this.options, obj, true);
- },
- getOpt:function(key){
- return this.options[key]
- },
- /**
- * 销毁编辑器实例,使用textarea代替
- * @method destroy
- * @example
- * ```javascript
- * editor.destroy();
- * ```
- */
- destroy: function () {
-
- var me = this;
- me.fireEvent('destroy');
- var container = me.container.parentNode;
- var textarea = me.textarea;
- if (!textarea) {
- textarea = document.createElement('textarea');
- container.parentNode.insertBefore(textarea, container);
- } else {
- textarea.style.display = ''
- }
-
- textarea.style.width = me.iframe.offsetWidth + 'px';
- textarea.style.height = me.iframe.offsetHeight + 'px';
- textarea.value = me.getContent();
- textarea.id = me.key;
- container.innerHTML = '';
- domUtils.remove(container);
- var key = me.key;
- //trace:2004
- for (var p in me) {
- if (me.hasOwnProperty(p)) {
- delete this[p];
- }
- }
- UE.delEditor(key);
- },
-
- /**
- * 渲染编辑器的DOM到指定容器
- * @method render
- * @param { String } containerId 指定一个容器ID
- * @remind 执行该方法,会触发ready事件
- * @warning 必须且只能调用一次
- */
-
- /**
- * 渲染编辑器的DOM到指定容器
- * @method render
- * @param { Element } containerDom 直接指定容器对象
- * @remind 执行该方法,会触发ready事件
- * @warning 必须且只能调用一次
- */
- render: function (container) {
- var me = this,
- options = me.options,
- getStyleValue=function(attr){
- return parseInt(domUtils.getComputedStyle(container,attr));
- };
- if (utils.isString(container)) {
- container = document.getElementById(container);
- }
- if (container) {
- if(options.initialFrameWidth){
- options.minFrameWidth = options.initialFrameWidth
- }else{
- options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;
- }
- if(options.initialFrameHeight){
- options.minFrameHeight = options.initialFrameHeight
- }else{
- options.initialFrameHeight = options.minFrameHeight = container.offsetHeight;
- }
-
- container.style.width = /%$/.test(options.initialFrameWidth) ? '100%' : options.initialFrameWidth-
- getStyleValue("padding-left")- getStyleValue("padding-right") +'px';
- container.style.height = /%$/.test(options.initialFrameHeight) ? '100%' : options.initialFrameHeight -
- getStyleValue("padding-top")- getStyleValue("padding-bottom") +'px';
-
- container.style.zIndex = options.zIndex;
-
- var html = ( ie && browser.version < 9 ? '' : '') +
- '' +
- '' +
- '' +
- (options.iframeCssUrl ? '' : '' ) +
- (options.initialStyle ? '' : '') +
- '' +
- '' +
- '' +
- (options.iframeJsUrl ? (''):'') +
- '';
-
- container.appendChild(domUtils.createElement(document, 'iframe', {
- id: 'ueditor_' + me.uid,
- width: "100%",
- height: "100%",
- frameborder: "0",
- //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条
-// scrolling :'no',
- src: 'javascript:void(function(){document.open();' + (options.customDomain && document.domain != location.hostname ? 'document.domain="' + document.domain + '";' : '') +
- 'document.write("' + html + '");document.close();}())'
- }));
- container.style.overflow = 'hidden';
- //解决如果是给定的百分比,会导致高度算不对的问题
- setTimeout(function(){
- if( /%$/.test(options.initialFrameWidth)){
- options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;
- //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化
-// container.style.width = options.initialFrameWidth + 'px';
- }
- if(/%$/.test(options.initialFrameHeight)){
- options.minFrameHeight = options.initialFrameHeight = container.offsetHeight;
- container.style.height = options.initialFrameHeight + 'px';
- }
- })
- }
- },
-
- /**
- * 编辑器初始化
- * @method _setup
- * @private
- * @param { Element } doc 编辑器Iframe中的文档对象
- */
- _setup: function (doc) {
-
- var me = this,
- options = me.options;
- if (ie) {
- doc.body.disabled = true;
- doc.body.contentEditable = true;
- doc.body.disabled = false;
- } else {
- doc.body.contentEditable = true;
- }
- doc.body.spellcheck = false;
- me.document = doc;
- me.window = doc.defaultView || doc.parentWindow;
- me.iframe = me.window.frameElement;
- me.body = doc.body;
- me.selection = new dom.Selection(doc);
- //gecko初始化就能得到range,无法判断isFocus了
- var geckoSel;
- if (browser.gecko && (geckoSel = this.selection.getNative())) {
- geckoSel.removeAllRanges();
- }
- this._initEvents();
- //为form提交提供一个隐藏的textarea
- for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) {
- if (form.tagName == 'FORM') {
- me.form = form;
- if(me.options.autoSyncData){
- domUtils.on(me.window,'blur',function(){
- setValue(form,me);
- });
- }else{
- domUtils.on(form, 'submit', function () {
- setValue(this, me);
- });
- }
- break;
- }
- }
- if (options.initialContent) {
- if (options.autoClearinitialContent) {
- var oldExecCommand = me.execCommand;
- me.execCommand = function () {
- me.fireEvent('firstBeforeExecCommand');
- return oldExecCommand.apply(me, arguments);
- };
- this._setDefaultContent(options.initialContent);
- } else
- this.setContent(options.initialContent, false, true);
- }
-
- //编辑器不能为空内容
-
- if (domUtils.isEmptyNode(me.body)) {
- me.body.innerHTML = '' + (browser.ie ? '' : ' ') + ' ';
- }
- //如果要求focus, 就把光标定位到内容开始
- if (options.focus) {
- setTimeout(function () {
- me.focus(me.options.focusInEnd);
- //如果自动清除开着,就不需要做selectionchange;
- !me.options.autoClearinitialContent && me._selectionChange();
- }, 0);
- }
- if (!me.container) {
- me.container = this.iframe.parentNode;
- }
- if (options.fullscreen && me.ui) {
- me.ui.setFullScreen(true);
- }
-
- try {
- me.document.execCommand('2D-position', false, false);
- } catch (e) {
- }
- try {
- me.document.execCommand('enableInlineTableEditing', false, false);
- } catch (e) {
- }
- try {
- me.document.execCommand('enableObjectResizing', false, false);
- } catch (e) {
- }
-
- //挂接快捷键
- me._bindshortcutKeys();
- me.isReady = 1;
- me.fireEvent('ready');
- options.onready && options.onready.call(me);
- if (!browser.ie9below) {
- domUtils.on(me.window, ['blur', 'focus'], function (e) {
- //chrome下会出现alt+tab切换时,导致选区位置不对
- if (e.type == 'blur') {
- me._bakRange = me.selection.getRange();
- try {
- me._bakNativeRange = me.selection.getNative().getRangeAt(0);
- me.selection.getNative().removeAllRanges();
- } catch (e) {
- me._bakNativeRange = null;
- }
-
- } else {
- try {
- me._bakRange && me._bakRange.select();
- } catch (e) {
- }
- }
- });
- }
- //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点
- if (browser.gecko && browser.version <= 10902) {
- //修复ff3.6初始化进来,不能点击获得焦点
- me.body.contentEditable = false;
- setTimeout(function () {
- me.body.contentEditable = true;
- }, 100);
- setInterval(function () {
- me.body.style.height = me.iframe.offsetHeight - 20 + 'px'
- }, 100)
- }
-
- !options.isShow && me.setHide();
- options.readonly && me.setDisabled();
- },
-
- /**
- * 同步数据到编辑器所在的form
- * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况
- * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项
- * @method sync
- * @example
- * ```javascript
- * editor.sync();
- * form.sumbit(); //form变量已经指向了form元素
- * ```
- */
-
- /**
- * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备
- * 后台取得数据的键值,该键值默认使用给定的编辑器容器的name属性,如果没有name属性则使用参数项里给定的“textarea”项
- * @method sync
- * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下
- */
- sync: function (formId) {
- var me = this,
- form = formId ? document.getElementById(formId) :
- domUtils.findParent(me.iframe.parentNode, function (node) {
- return node.tagName == 'FORM'
- }, true);
- form && setValue(form, me);
- },
-
- /**
- * 设置编辑器高度
- * @method setHeight
- * @remind 当配置项autoHeightEnabled为真时,该方法无效
- * @param { Number } number 设置的高度值,纯数值,不带单位
- * @example
- * ```javascript
- * editor.setHeight(number);
- * ```
- */
- setHeight: function (height,notSetHeight) {
- if (height !== parseInt(this.iframe.parentNode.style.height)) {
- this.iframe.parentNode.style.height = height + 'px';
- }
- !notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);
- this.body.style.height = height + 'px';
- !notSetHeight && this.trigger('setHeight')
- },
-
- /**
- * 为编辑器的编辑命令提供快捷键
- * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口
- * @method addshortcutkey
- * @param { Object } keyset 命令名和快捷键键值对对象,多个按钮的快捷键用“+”分隔
- * @example
- * ```javascript
- * editor.addshortcutkey({
- * "Bold" : "ctrl+66",//^B
- * "Italic" : "ctrl+73", //^I
- * });
- * ```
- */
- /**
- * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口
- * @method addshortcutkey
- * @param { String } cmd 触发快捷键时,响应的命令
- * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔
- * @example
- * ```javascript
- * editor.addshortcutkey("Underline", "ctrl+85"); //^U
- * ```
- */
- addshortcutkey: function (cmd, keys) {
- var obj = {};
- if (keys) {
- obj[cmd] = keys
- } else {
- obj = cmd;
- }
- utils.extend(this.shortcutkeys, obj)
- },
-
- /**
- * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令
- * @method _bindshortcutKeys
- * @private
- */
- _bindshortcutKeys: function () {
- var me = this, shortcutkeys = this.shortcutkeys;
- me.addListener('keydown', function (type, e) {
- var keyCode = e.keyCode || e.which;
- for (var i in shortcutkeys) {
- var tmp = shortcutkeys[i].split(',');
- for (var t = 0, ti; ti = tmp[t++];) {
- ti = ti.split(':');
- var key = ti[0], param = ti[1];
- if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) {
- if (( (RegExp.$1 == 'ctrl' ? (e.ctrlKey || e.metaKey) : 0)
- && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1)
- && keyCode == RegExp.$3
- ) ||
- keyCode == RegExp.$1
- ) {
- if (me.queryCommandState(i,param) != -1)
- me.execCommand(i, param);
- domUtils.preventDefault(e);
- }
- }
- }
-
- }
- });
- },
-
- /**
- * 获取编辑器的内容
- * @method getContent
- * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容
- * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串
- * @example
- * ```javascript
- * //编辑器html内容:123456
- * var content = editor.getContent(); //返回值:123456
- * ```
- */
-
- /**
- * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则
- * @method getContent
- * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值,
- * 代表当前编辑器的内容是否空,
- * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回
- * 经过内置过滤规则处理后的内容。
- * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。
- * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容
- * @return { String } 编辑器的内容字符串
- * @example
- * ```javascript
- * // editor 是一个编辑器的实例
- * var content = editor.getContent( function ( editor ) {
- * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串
- * } );
- * ```
- */
- getContent: function (cmd, fn,notSetCursor,ignoreBlank,formatter) {
- var me = this;
- if (cmd && utils.isFunction(cmd)) {
- fn = cmd;
- cmd = '';
- }
- if (fn ? !fn() : !this.hasContents()) {
- return '';
- }
- me.fireEvent('beforegetcontent');
- var root = UE.htmlparser(me.body.innerHTML,ignoreBlank);
- me.filterOutputRule(root);
- me.fireEvent('aftergetcontent', cmd,root);
- return root.toHtml(formatter);
- },
-
- /**
- * 取得完整的html代码,可以直接显示成完整的html文档
- * @method getAllHtml
- * @return { String } 编辑器的内容html文档字符串
- * @eaxmple
- * ```javascript
- * editor.getAllHtml(); //返回格式大致是: ......
- * ```
- */
- getAllHtml: function () {
- var me = this,
- headHtml = [],
- html = '';
- me.fireEvent('getAllHtml', headHtml);
- if (browser.ie && browser.version > 8) {
- var headHtmlForIE9 = '';
- utils.each(me.document.styleSheets, function (si) {
- headHtmlForIE9 += ( si.href ? '' : '');
- });
- utils.each(me.document.getElementsByTagName('script'), function (si) {
- headHtmlForIE9 += si.outerHTML;
- });
-
- }
- return '' + (me.options.charset ? '' : '')
- + (headHtmlForIE9 || me.document.getElementsByTagName('head')[0].innerHTML) + headHtml.join('\n') + ''
- + '' + me.getContent(null, null, true) + '';
- },
-
- /**
- * 得到编辑器的纯文本内容,但会保留段落格式
- * @method getPlainTxt
- * @return { String } 编辑器带段落格式的纯文本内容字符串
- * @example
- * ```javascript
- * //编辑器html内容:1 2
- * console.log(editor.getPlainTxt()); //输出:"1\n2\n
- * ```
- */
- getPlainTxt: function () {
- var reg = new RegExp(domUtils.fillChar, 'g'),
- html = this.body.innerHTML.replace(/[\n\r]/g, '');//ie要先去了\n在处理
- html = html.replace(/<(p|div)[^>]*>( | )<\/\1>/gi, '\n')
- .replace(/ /gi, '\n')
- .replace(/<[^>/]+>/g, '')
- .replace(/(\n)?<\/([^>]+)>/g, function (a, b, c) {
- return dtd.$block[c] ? '\n' : b ? b : '';
- });
- //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0
- return html.replace(reg, '').replace(/\u00a0/g, ' ').replace(/ /g, ' ');
- },
-
- /**
- * 获取编辑器中的纯文本内容,没有段落格式
- * @method getContentTxt
- * @return { String } 编辑器不带段落格式的纯文本内容字符串
- * @example
- * ```javascript
- * //编辑器html内容:1 2
- * console.log(editor.getPlainTxt()); //输出:"12
- * ```
- */
- getContentTxt: function () {
- var reg = new RegExp(domUtils.fillChar, 'g');
- //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0
- return this.body[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').replace(/\u00a0/g, ' ');
- },
-
- /**
- * 设置编辑器的内容,可修改编辑器当前的html内容
- * @method setContent
- * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容
- * @warning 该方法会触发selectionchange事件
- * @param { String } html 要插入的html内容
- * @example
- * ```javascript
- * editor.getContent('test ');
- * ```
- */
-
- /**
- * 设置编辑器的内容,可修改编辑器当前的html内容
- * @method setContent
- * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容
- * @warning 该方法会触发selectionchange事件
- * @param { String } html 要插入的html内容
- * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入
- * @example
- * ```javascript
- * //假设设置前的编辑器内容是 old text
- * editor.setContent('new text ', true); //插入的结果是old text new text
- * ```
- */
- setContent: function (html, isAppendTo, notFireSelectionchange) {
- var me = this;
-
- me.fireEvent('beforesetcontent', html);
- var root = UE.htmlparser(html);
- me.filterInputRule(root);
- html = root.toHtml();
-
- me.body.innerHTML = (isAppendTo ? me.body.innerHTML : '') + html;
-
-
- function isCdataDiv(node){
- return node.tagName == 'DIV' && node.getAttribute('cdata_tag');
- }
- //给文本或者inline节点套p标签
- if (me.options.enterTag == 'p') {
-
- var child = this.body.firstChild, tmpNode;
- if (!child || child.nodeType == 1 &&
- (dtd.$cdata[child.tagName] || isCdataDiv(child) ||
- domUtils.isCustomeNode(child)
- )
- && child === this.body.lastChild) {
- this.body.innerHTML = '' + (browser.ie ? ' ' : ' ') + ' ' + this.body.innerHTML;
-
- } else {
- var p = me.document.createElement('p');
- while (child) {
- while (child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName])) {
- tmpNode = child.nextSibling;
- p.appendChild(child);
- child = tmpNode;
- }
- if (p.firstChild) {
- if (!child) {
- me.body.appendChild(p);
- break;
- } else {
- child.parentNode.insertBefore(p, child);
- p = me.document.createElement('p');
- }
- }
- child = child.nextSibling;
- }
- }
- }
- me.fireEvent('aftersetcontent');
- me.fireEvent('contentchange');
-
- !notFireSelectionchange && me._selectionChange();
- //清除保存的选区
- me._bakRange = me._bakIERange = me._bakNativeRange = null;
- //trace:1742 setContent后gecko能得到焦点问题
- var geckoSel;
- if (browser.gecko && (geckoSel = this.selection.getNative())) {
- geckoSel.removeAllRanges();
- }
- if(me.options.autoSyncData){
- me.form && setValue(me.form,me);
- }
- },
-
- /**
- * 让编辑器获得焦点,默认focus到编辑器头部
- * @method focus
- * @example
- * ```javascript
- * editor.focus()
- * ```
- */
-
- /**
- * 让编辑器获得焦点,toEnd确定focus位置
- * @method focus
- * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部
- * @example
- * ```javascript
- * editor.focus(true)
- * ```
- */
- focus: function (toEnd) {
- try {
- var me = this,
- rng = me.selection.getRange();
- if (toEnd) {
- var node = me.body.lastChild;
- if(node && node.nodeType == 1 && !dtd.$empty[node.tagName]){
- if(domUtils.isEmptyBlock(node)){
- rng.setStartAtFirst(node)
- }else{
- rng.setStartAtLast(node)
- }
- rng.collapse(true);
- }
- rng.setCursor(true);
- } else {
- if(!rng.collapsed && domUtils.isBody(rng.startContainer) && rng.startOffset == 0){
-
- var node = me.body.firstChild;
- if(node && node.nodeType == 1 && !dtd.$empty[node.tagName]){
- rng.setStartAtFirst(node).collapse(true);
- }
- }
-
- rng.select(true);
-
- }
- this.fireEvent('focus selectionchange');
- } catch (e) {
- }
-
- },
- isFocus:function(){
- return this.selection.isFocus();
- },
- blur:function(){
- var sel = this.selection.getNative();
- if(sel.empty && browser.ie){
- var nativeRng = document.body.createTextRange();
- nativeRng.moveToElementText(document.body);
- nativeRng.collapse(true);
- nativeRng.select();
- sel.empty()
- }else{
- sel.removeAllRanges()
- }
-
- //this.fireEvent('blur selectionchange');
- },
- /**
- * 初始化UE事件及部分事件代理
- * @method _initEvents
- * @private
- */
- _initEvents: function () {
- var me = this,
- doc = me.document,
- win = me.window;
- me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
- domUtils.on(doc, ['click', 'contextmenu', 'mousedown', 'keydown', 'keyup', 'keypress', 'mouseup', 'mouseover', 'mouseout', 'selectstart'], me._proxyDomEvent);
- domUtils.on(win, ['focus', 'blur'], me._proxyDomEvent);
- domUtils.on(me.body,'drop',function(e){
- //阻止ff下默认的弹出新页面打开图片
- if(browser.gecko && e.stopPropagation) { e.stopPropagation(); }
- me.fireEvent('contentchange')
- });
- domUtils.on(doc, ['mouseup', 'keydown'], function (evt) {
- //特殊键不触发selectionchange
- if (evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
- return;
- }
- if (evt.button == 2)return;
- me._selectionChange(250, evt);
- });
- },
- /**
- * 触发事件代理
- * @method _proxyDomEvent
- * @private
- * @return { * } fireEvent的返回值
- * @see UE.EventBase:fireEvent(String)
- */
- _proxyDomEvent: function (evt) {
- if(this.fireEvent('before' + evt.type.replace(/^on/, '').toLowerCase()) === false){
- return false;
- }
- if(this.fireEvent(evt.type.replace(/^on/, ''), evt) === false){
- return false;
- }
- return this.fireEvent('after' + evt.type.replace(/^on/, '').toLowerCase())
- },
- /**
- * 变化选区
- * @method _selectionChange
- * @private
- */
- _selectionChange: function (delay, evt) {
- var me = this;
- //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1)
-// if ( !me.selection.isFocus() ){
-// return;
-// }
-
-
- var hackForMouseUp = false;
- var mouseX, mouseY;
- if (browser.ie && browser.version < 9 && evt && evt.type == 'mouseup') {
- var range = this.selection.getRange();
- if (!range.collapsed) {
- hackForMouseUp = true;
- mouseX = evt.clientX;
- mouseY = evt.clientY;
- }
- }
- clearTimeout(_selectionChangeTimer);
- _selectionChangeTimer = setTimeout(function () {
- if (!me.selection || !me.selection.getNative()) {
- return;
- }
- //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值.
- //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响
- var ieRange;
- if (hackForMouseUp && me.selection.getNative().type == 'None') {
- ieRange = me.document.body.createTextRange();
- try {
- ieRange.moveToPoint(mouseX, mouseY);
- } catch (ex) {
- ieRange = null;
- }
- }
- var bakGetIERange;
- if (ieRange) {
- bakGetIERange = me.selection.getIERange;
- me.selection.getIERange = function () {
- return ieRange;
- };
- }
- me.selection.cache();
- if (bakGetIERange) {
- me.selection.getIERange = bakGetIERange;
- }
- if (me.selection._cachedRange && me.selection._cachedStartElement) {
- me.fireEvent('beforeselectionchange');
- // 第二个参数causeByUi为true代表由用户交互造成的selectionchange.
- me.fireEvent('selectionchange', !!evt);
- me.fireEvent('afterselectionchange');
- me.selection.clear();
- }
- }, delay || 50);
- },
-
- /**
- * 执行编辑命令
- * @method _callCmdFn
- * @private
- * @param { String } fnName 函数名称
- * @param { * } args 传给命令函数的参数
- * @return { * } 返回命令函数运行的返回值
- */
- _callCmdFn: function (fnName, args) {
- var cmdName = args[0].toLowerCase(),
- cmd, cmdFn;
- cmd = this.commands[cmdName] || UE.commands[cmdName];
- cmdFn = cmd && cmd[fnName];
- //没有querycommandstate或者没有command的都默认返回0
- if ((!cmd || !cmdFn) && fnName == 'queryCommandState') {
- return 0;
- } else if (cmdFn) {
- return cmdFn.apply(this, args);
- }
- },
-
- /**
- * 执行编辑命令cmdName,完成富文本编辑效果
- * @method execCommand
- * @param { String } cmdName 需要执行的命令
- * @remind 具体命令的使用请参考命令列表
- * @return { * } 返回命令函数运行的返回值
- * @example
- * ```javascript
- * editor.execCommand(cmdName);
- * ```
- */
- execCommand: function (cmdName) {
- cmdName = cmdName.toLowerCase();
- var me = this,
- result,
- cmd = me.commands[cmdName] || UE.commands[cmdName];
- if (!cmd || !cmd.execCommand) {
- return null;
- }
- if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {
- me.__hasEnterExecCommand = true;
- if (me.queryCommandState.apply(me,arguments) != -1) {
- me.fireEvent('saveScene');
- me.fireEvent.apply(me, ['beforeexeccommand', cmdName].concat(arguments));
- result = this._callCmdFn('execCommand', arguments);
- //保存场景时,做了内容对比,再看是否进行contentchange触发,这里多触发了一次,去掉
-// (!cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange');
- me.fireEvent.apply(me, ['afterexeccommand', cmdName].concat(arguments));
- me.fireEvent('saveScene');
- }
- me.__hasEnterExecCommand = false;
- } else {
- result = this._callCmdFn('execCommand', arguments);
- (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange')
- }
- (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me._selectionChange();
- return result;
- },
-
- /**
- * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态
- * @method queryCommandState
- * @param { String } cmdName 需要查询的命令名称
- * @remind 具体命令的使用请参考命令列表
- * @return { Number } number 返回放前命令的状态,返回值三种情况:(-1|0|1)
- * @example
- * ```javascript
- * editor.queryCommandState(cmdName) => (-1|0|1)
- * ```
- * @see COMMAND.LIST
- */
- queryCommandState: function (cmdName) {
- return this._callCmdFn('queryCommandState', arguments);
- },
-
- /**
- * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值
- * @method queryCommandValue
- * @param { String } cmdName 需要查询的命令名称
- * @remind 具体命令的使用请参考命令列表
- * @remind 只有部分插件有此方法
- * @return { * } 返回每个命令特定的当前状态值
- * @grammar editor.queryCommandValue(cmdName) => {*}
- * @see COMMAND.LIST
- */
- queryCommandValue: function (cmdName) {
- return this._callCmdFn('queryCommandValue', arguments);
- },
-
- /**
- * 检查编辑区域中是否有内容
- * @method hasContents
- * @remind 默认有文本内容,或者有以下节点都不认为是空
- * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param
- * @return { Boolean } 检查有内容返回true,否则返回false
- * @example
- * ```javascript
- * editor.hasContents()
- * ```
- */
-
- /**
- * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true
- * @method hasContents
- * @param { Array } tags 传入数组判断时用到的节点类型
- * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false
- * @example
- * ```javascript
- * editor.hasContents(['span']);
- * ```
- */
- hasContents: function (tags) {
- if (tags) {
- for (var i = 0, ci; ci = tags[i++];) {
- if (this.document.getElementsByTagName(ci).length > 0) {
- return true;
- }
- }
- }
- if (!domUtils.isEmptyBlock(this.body)) {
- return true
- }
- //随时添加,定义的特殊标签如果存在,不能认为是空
- tags = ['div'];
- for (i = 0; ci = tags[i++];) {
- var nodes = domUtils.getElementsByTagName(this.document, ci);
- for (var n = 0, cn; cn = nodes[n++];) {
- if (domUtils.isCustomeNode(cn)) {
- return true;
- }
- }
- }
- return false;
- },
-
- /**
- * 重置编辑器,可用来做多个tab使用同一个编辑器实例
- * @method reset
- * @remind 此方法会清空编辑器内容,清空回退列表,会触发reset事件
- * @example
- * ```javascript
- * editor.reset()
- * ```
- */
- reset: function () {
- this.fireEvent('reset');
- },
-
- /**
- * 设置当前编辑区域可以编辑
- * @method setEnabled
- * @example
- * ```javascript
- * editor.setEnabled()
- * ```
- */
- setEnabled: function () {
- var me = this, range;
- if (me.body.contentEditable == 'false') {
- me.body.contentEditable = true;
- range = me.selection.getRange();
- //有可能内容丢失了
- try {
- range.moveToBookmark(me.lastBk);
- delete me.lastBk
- } catch (e) {
- range.setStartAtFirst(me.body).collapse(true)
- }
- range.select(true);
- if (me.bkqueryCommandState) {
- me.queryCommandState = me.bkqueryCommandState;
- delete me.bkqueryCommandState;
- }
- if (me.bkqueryCommandValue) {
- me.queryCommandValue = me.bkqueryCommandValue;
- delete me.bkqueryCommandValue;
- }
- me.fireEvent('selectionchange');
- }
- },
- enable: function () {
- return this.setEnabled();
- },
-
- /** 设置当前编辑区域不可编辑
- * @method setDisabled
- */
-
- /** 设置当前编辑区域不可编辑,except中的命令除外
- * @method setDisabled
- * @param { String } except 例外命令的字符串
- * @remind 即使设置了disable,此处配置的例外命令仍然可以执行
- * @example
- * ```javascript
- * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能
- * ```
- */
-
- /** 设置当前编辑区域不可编辑,except中的命令除外
- * @method setDisabled
- * @param { Array } except 例外命令的字符串数组,数组中的命令仍然可以执行
- * @remind 即使设置了disable,此处配置的例外命令仍然可以执行
- * @example
- * ```javascript
- * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能
- * ```
- */
- setDisabled: function (except) {
- var me = this;
- except = except ? utils.isArray(except) ? except : [except] : [];
- if (me.body.contentEditable == 'true') {
- if (!me.lastBk) {
- me.lastBk = me.selection.getRange().createBookmark(true);
- }
- me.body.contentEditable = false;
- me.bkqueryCommandState = me.queryCommandState;
- me.bkqueryCommandValue = me.queryCommandValue;
- me.queryCommandState = function (type) {
- if (utils.indexOf(except, type) != -1) {
- return me.bkqueryCommandState.apply(me, arguments);
- }
- return -1;
- };
- me.queryCommandValue = function (type) {
- if (utils.indexOf(except, type) != -1) {
- return me.bkqueryCommandValue.apply(me, arguments);
- }
- return null;
- };
- me.fireEvent('selectionchange');
- }
- },
- disable: function (except) {
- return this.setDisabled(except);
- },
-
- /**
- * 设置默认内容
- * @method _setDefaultContent
- * @private
- * @param { String } cont 要存入的内容
- */
- _setDefaultContent: function () {
- function clear() {
- var me = this;
- if (me.document.getElementById('initContent')) {
- me.body.innerHTML = '' + (ie ? '' : ' ') + ' ';
- me.removeListener('firstBeforeExecCommand focus', clear);
- setTimeout(function () {
- me.focus();
- me._selectionChange();
- }, 0)
- }
- }
-
- return function (cont) {
- var me = this;
- me.body.innerHTML = '' + cont + ' ';
-
- me.addListener('firstBeforeExecCommand focus', clear);
- }
- }(),
-
- /**
- * 显示编辑器
- * @method setShow
- * @example
- * ```javascript
- * editor.setShow()
- * ```
- */
- setShow: function () {
- var me = this, range = me.selection.getRange();
- if (me.container.style.display == 'none') {
- //有可能内容丢失了
- try {
- range.moveToBookmark(me.lastBk);
- delete me.lastBk
- } catch (e) {
- range.setStartAtFirst(me.body).collapse(true)
- }
- //ie下focus实效,所以做了个延迟
- setTimeout(function () {
- range.select(true);
- }, 100);
- me.container.style.display = '';
- }
-
- },
- show: function () {
- return this.setShow();
- },
- /**
- * 隐藏编辑器
- * @method setHide
- * @example
- * ```javascript
- * editor.setHide()
- * ```
- */
- setHide: function () {
- var me = this;
- if (!me.lastBk) {
- me.lastBk = me.selection.getRange().createBookmark(true);
- }
- me.container.style.display = 'none'
- },
- hide: function () {
- return this.setHide();
- },
-
- /**
- * 根据指定的路径,获取对应的语言资源
- * @method getLang
- * @param { String } path 路径根据的是lang目录下的语言文件的路径结构
- * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串
- * @example
- * ```javascript
- * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除'
- * ```
- */
- getLang: function (path) {
- var lang = UE.I18N[this.options.lang];
- if (!lang) {
- throw Error("not import language file");
- }
- path = (path || "").split(".");
- for (var i = 0, ci; ci = path[i++];) {
- lang = lang[ci];
- if (!lang)break;
- }
- return lang;
- },
-
- /**
- * 计算编辑器html内容字符串的长度
- * @method getContentLength
- * @return { Number } 返回计算的长度
- * @example
- * ```javascript
- * //编辑器html内容132
- * editor.getContentLength() //返回27
- * ```
- */
- /**
- * 计算编辑器当前纯文本内容的长度
- * @method getContentLength
- * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算
- * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1
- * @example
- * ```javascript
- * //编辑器html内容132
- * editor.getContentLength() //返回3
- * ```
- */
- getContentLength: function (ingoneHtml, tagNames) {
- var count = this.getContent(false,false,true).length;
- if (ingoneHtml) {
- tagNames = (tagNames || []).concat([ 'hr', 'img', 'iframe']);
- count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length;
- for (var i = 0, ci; ci = tagNames[i++];) {
- count += this.document.getElementsByTagName(ci).length;
- }
- }
- return count;
- },
-
- /**
- * 注册输入过滤规则
- * @method addInputRule
- * @param { Function } rule 要添加的过滤规则
- * @example
- * ```javascript
- * editor.addInputRule(function(root){
- * $.each(root.getNodesByTagName('div'),function(i,node){
- * node.tagName="p";
- * });
- * });
- * ```
- */
- addInputRule: function (rule) {
- this.inputRules.push(rule);
- },
-
- /**
- * 执行注册的过滤规则
- * @method filterInputRule
- * @param { UE.uNode } root 要过滤的uNode节点
- * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数
- * @example
- * ```javascript
- * editor.filterInputRule(editor.body);
- * ```
- * @see UE.Editor:addInputRule
- */
- filterInputRule: function (root) {
- for (var i = 0, ci; ci = this.inputRules[i++];) {
- ci.call(this, root)
- }
- },
-
- /**
- * 注册输出过滤规则
- * @method addOutputRule
- * @param { Function } rule 要添加的过滤规则
- * @example
- * ```javascript
- * editor.addOutputRule(function(root){
- * $.each(root.getNodesByTagName('p'),function(i,node){
- * node.tagName="div";
- * });
- * });
- * ```
- */
- addOutputRule: function (rule) {
- this.outputRules.push(rule)
- },
-
- /**
- * 根据输出过滤规则,过滤编辑器内容
- * @method filterOutputRule
- * @remind 执行editor.getContent方法的时候,会先运行该过滤函数
- * @param { UE.uNode } root 要过滤的uNode节点
- * @example
- * ```javascript
- * editor.filterOutputRule(editor.body);
- * ```
- * @see UE.Editor:addOutputRule
- */
- filterOutputRule: function (root) {
- for (var i = 0, ci; ci = this.outputRules[i++];) {
- ci.call(this, root)
- }
- },
-
- /**
- * 根据action名称获取请求的路径
- * @method getActionUrl
- * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径
- * @param { String } action action名称
- * @example
- * ```javascript
- * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config"
- * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage"
- * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl"
- * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage"
- * ```
- */
- getActionUrl: function(action){
- var actionName = this.getOpt(action) || action,
- imageUrl = this.getOpt('imageUrl'),
- serverUrl = this.getOpt('serverUrl');
-
- if(!serverUrl && imageUrl) {
- serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2');
- }
-
- if(serverUrl) {
- serverUrl = serverUrl + (serverUrl.indexOf('?') == -1 ? '?':'&') + 'action=' + (actionName || '');
- return utils.formatUrl(serverUrl);
- } else {
- return '';
- }
- }
- };
- utils.inherits(Editor, EventBase);
-})();
+/**
+ * 编辑器主类,包含编辑器提供的大部分公用接口
+ * @file
+ * @module UE
+ * @class Editor
+ * @since 1.2.6.1
+ */
+
+/**
+ * UEditor公用空间,UEditor所有的功能都挂载在该空间下
+ * @unfile
+ * @module UE
+ */
+
+/**
+ * UEditor的核心类,为用户提供与编辑器交互的接口。
+ * @unfile
+ * @module UE
+ * @class Editor
+ */
+
+(function() {
+ var uid = 0,
+ _selectionChangeTimer;
+
+ /**
+ * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面
+ * @private
+ * @method setValue
+ * @param { UE.Editor } editor 编辑器事例
+ */
+ function setValue(form, editor) {
+ var textarea;
+ if (editor.options.textarea) {
+ if (utils.isString(editor.options.textarea)) {
+ for (
+ var i = 0, ti, tis = domUtils.getElementsByTagName(form, "textarea");
+ (ti = tis[i++]);
+
+ ) {
+ if (ti.id == "ueditor_textarea_" + editor.options.textarea) {
+ textarea = ti;
+ break;
+ }
+ }
+ } else {
+ textarea = editor.textarea;
+ }
+ }
+ if (!textarea) {
+ form.appendChild(
+ (textarea = domUtils.createElement(document, "textarea", {
+ name: editor.options.textarea,
+ id: "ueditor_textarea_" + editor.options.textarea,
+ style: "display:none"
+ }))
+ );
+ //不要产生多个textarea
+ editor.textarea = textarea;
+ }
+ !textarea.getAttribute("name") &&
+ textarea.setAttribute("name", editor.options.textarea);
+ textarea.value = editor.hasContents()
+ ? editor.options.allHtmlEnabled
+ ? editor.getAllHtml()
+ : editor.getContent(null, null, true)
+ : "";
+ }
+ function loadPlugins(me) {
+ //初始化插件
+ for (var pi in UE.plugins) {
+ UE.plugins[pi].call(me);
+ }
+ }
+ function checkCurLang(I18N) {
+ for (var lang in I18N) {
+ return lang;
+ }
+ }
+
+ function langReadied(me) {
+ me.langIsReady = true;
+
+ me.fireEvent("langReady");
+ }
+
+ /**
+ * 编辑器准备就绪后会触发该事件
+ * @module UE
+ * @class Editor
+ * @event ready
+ * @remind render方法执行完成之后,会触发该事件
+ * @remind
+ * @example
+ * ```javascript
+ * editor.addListener( 'ready', function( editor ) {
+ * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点
+ * } );
+ * ```
+ */
+ /**
+ * 执行destroy方法,会触发该事件
+ * @module UE
+ * @class Editor
+ * @event destroy
+ * @see UE.Editor:destroy()
+ */
+ /**
+ * 执行reset方法,会触发该事件
+ * @module UE
+ * @class Editor
+ * @event reset
+ * @see UE.Editor:reset()
+ */
+ /**
+ * 执行focus方法,会触发该事件
+ * @module UE
+ * @class Editor
+ * @event focus
+ * @see UE.Editor:focus(Boolean)
+ */
+ /**
+ * 语言加载完成会触发该事件
+ * @module UE
+ * @class Editor
+ * @event langReady
+ */
+ /**
+ * 运行命令之后会触发该命令
+ * @module UE
+ * @class Editor
+ * @event beforeExecCommand
+ */
+ /**
+ * 运行命令之后会触发该命令
+ * @module UE
+ * @class Editor
+ * @event afterExecCommand
+ */
+ /**
+ * 运行命令之前会触发该命令
+ * @module UE
+ * @class Editor
+ * @event firstBeforeExecCommand
+ */
+ /**
+ * 在getContent方法执行之前会触发该事件
+ * @module UE
+ * @class Editor
+ * @event beforeGetContent
+ * @see UE.Editor:getContent()
+ */
+ /**
+ * 在getContent方法执行之后会触发该事件
+ * @module UE
+ * @class Editor
+ * @event afterGetContent
+ * @see UE.Editor:getContent()
+ */
+ /**
+ * 在getAllHtml方法执行时会触发该事件
+ * @module UE
+ * @class Editor
+ * @event getAllHtml
+ * @see UE.Editor:getAllHtml()
+ */
+ /**
+ * 在setContent方法执行之前会触发该事件
+ * @module UE
+ * @class Editor
+ * @event beforeSetContent
+ * @see UE.Editor:setContent(String)
+ */
+ /**
+ * 在setContent方法执行之后会触发该事件
+ * @module UE
+ * @class Editor
+ * @event afterSetContent
+ * @see UE.Editor:setContent(String)
+ */
+ /**
+ * 每当编辑器内部选区发生改变时,将触发该事件
+ * @event selectionchange
+ * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理
+ * @example
+ * ```javascript
+ * editor.addListener( 'selectionchange', function( editor ) {
+ * console.log('选区发生改变');
+ * }
+ */
+ /**
+ * 在所有selectionchange的监听函数执行之前,会触发该事件
+ * @module UE
+ * @class Editor
+ * @event beforeSelectionChange
+ * @see UE.Editor:selectionchange
+ */
+ /**
+ * 在所有selectionchange的监听函数执行完之后,会触发该事件
+ * @module UE
+ * @class Editor
+ * @event afterSelectionChange
+ * @see UE.Editor:selectionchange
+ */
+ /**
+ * 编辑器内容发生改变时会触发该事件
+ * @module UE
+ * @class Editor
+ * @event contentChange
+ */
+
+ /**
+ * 以默认参数构建一个编辑器实例
+ * @constructor
+ * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面
+ * @example
+ * ```javascript
+ * var editor = new UE.Editor();
+ * editor.execCommand('blod');
+ * ```
+ * @see UE.Config
+ */
+
+ /**
+ * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。
+ * @constructor
+ * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面
+ * @param { Object } setting 创建编辑器的参数
+ * @example
+ * ```javascript
+ * var editor = new UE.Editor();
+ * editor.execCommand('blod');
+ * ```
+ * @see UE.Config
+ */
+ var Editor = (UE.Editor = function(options) {
+ var me = this;
+ me.uid = uid++;
+ EventBase.call(me);
+ me.commands = {};
+ me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);
+ me.shortcutkeys = {};
+ me.inputRules = [];
+ me.outputRules = [];
+ //设置默认的常用属性
+ me.setOpt(Editor.defaultOptions(me));
+
+ /* 尝试异步加载后台配置 */
+ me.loadServerConfig();
+
+ if (!utils.isEmptyObject(UE.I18N)) {
+ //修改默认的语言类型
+ me.options.lang = checkCurLang(UE.I18N);
+ UE.plugin.load(me);
+ langReadied(me);
+ } else {
+ utils.loadFile(
+ document,
+ {
+ src:
+ me.options.langPath +
+ me.options.lang +
+ "/" +
+ me.options.lang +
+ ".js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ UE.plugin.load(me);
+ langReadied(me);
+ }
+ );
+ }
+
+ UE.instants["ueditorInstant" + me.uid] = me;
+ });
+ Editor.prototype = {
+ registerCommand: function(name, obj) {
+ this.commands[name] = obj;
+ },
+ /**
+ * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的
+ * @method ready
+ * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会
+ * 立即触发该回调。
+ * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入
+ * @example
+ * ```javascript
+ * editor.ready( function( editor ) {
+ * editor.setContent('初始化完毕');
+ * } );
+ * ```
+ * @see UE.Editor.event:ready
+ */
+ ready: function(fn) {
+ var me = this;
+ if (fn) {
+ me.isReady ? fn.apply(me) : me.addListener("ready", fn);
+ }
+ },
+
+ /**
+ * 该方法是提供给插件里面使用,设置配置项默认值
+ * @method setOpt
+ * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置
+ * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。
+ * @param { String } key 编辑器的可接受的选项名称
+ * @param { * } val 该选项可接受的值
+ * @example
+ * ```javascript
+ * editor.setOpt( 'initContent', '欢迎使用编辑器' );
+ * ```
+ */
+
+ /**
+ * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值
+ * @method setOpt
+ * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置
+ * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。
+ * @param { Object } options 将要设置的选项的键值对对象
+ * @example
+ * ```javascript
+ * editor.setOpt( {
+ * 'initContent': '欢迎使用编辑器'
+ * } );
+ * ```
+ */
+ setOpt: function(key, val) {
+ var obj = {};
+ if (utils.isString(key)) {
+ obj[key] = val;
+ } else {
+ obj = key;
+ }
+ utils.extend(this.options, obj, true);
+ },
+ getOpt: function(key) {
+ return this.options[key];
+ },
+ /**
+ * 销毁编辑器实例,使用textarea代替
+ * @method destroy
+ * @example
+ * ```javascript
+ * editor.destroy();
+ * ```
+ */
+ destroy: function() {
+ var me = this;
+ me.fireEvent("destroy");
+ var container = me.container.parentNode;
+ var textarea = me.textarea;
+ if (!textarea) {
+ textarea = document.createElement("textarea");
+ container.parentNode.insertBefore(textarea, container);
+ } else {
+ textarea.style.display = "";
+ }
+
+ textarea.style.width = me.iframe.offsetWidth + "px";
+ textarea.style.height = me.iframe.offsetHeight + "px";
+ textarea.value = me.getContent();
+ textarea.id = me.key;
+ container.innerHTML = "";
+ domUtils.remove(container);
+ var key = me.key;
+ //trace:2004
+ for (var p in me) {
+ if (me.hasOwnProperty(p)) {
+ delete this[p];
+ }
+ }
+ UE.delEditor(key);
+ },
+
+ /**
+ * 渲染编辑器的DOM到指定容器
+ * @method render
+ * @param { String } containerId 指定一个容器ID
+ * @remind 执行该方法,会触发ready事件
+ * @warning 必须且只能调用一次
+ */
+
+ /**
+ * 渲染编辑器的DOM到指定容器
+ * @method render
+ * @param { Element } containerDom 直接指定容器对象
+ * @remind 执行该方法,会触发ready事件
+ * @warning 必须且只能调用一次
+ */
+ render: function(container) {
+ var me = this,
+ options = me.options,
+ getStyleValue = function(attr) {
+ return parseInt(domUtils.getComputedStyle(container, attr));
+ };
+ if (utils.isString(container)) {
+ container = document.getElementById(container);
+ }
+ if (container) {
+ if (options.initialFrameWidth) {
+ options.minFrameWidth = options.initialFrameWidth;
+ } else {
+ options.minFrameWidth = options.initialFrameWidth =
+ container.offsetWidth;
+ }
+ if (options.initialFrameHeight) {
+ options.minFrameHeight = options.initialFrameHeight;
+ } else {
+ options.initialFrameHeight = options.minFrameHeight =
+ container.offsetHeight;
+ }
+
+ container.style.width = /%$/.test(options.initialFrameWidth)
+ ? "100%"
+ : options.initialFrameWidth -
+ getStyleValue("padding-left") -
+ getStyleValue("padding-right") +
+ "px";
+ container.style.height = /%$/.test(options.initialFrameHeight)
+ ? "100%"
+ : options.initialFrameHeight -
+ getStyleValue("padding-top") -
+ getStyleValue("padding-bottom") +
+ "px";
+
+ container.style.zIndex = options.zIndex;
+
+ var html =
+ (ie && browser.version < 9 ? "" : "") +
+ "" +
+ "" +
+ "" +
+ (options.iframeCssUrl
+ ? ""
+ : "") +
+ (options.initialStyle
+ ? ""
+ : "") +
+ "" +
+ "" +
+ "" +
+ (options.iframeJsUrl
+ ? ""
+ : "") +
+ "";
+
+ container.appendChild(
+ domUtils.createElement(document, "iframe", {
+ id: "ueditor_" + me.uid,
+ width: "100%",
+ height: "100%",
+ frameborder: "0",
+ //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条
+ // scrolling :'no',
+ src:
+ "javascript:void(function(){document.open();" +
+ (options.customDomain && document.domain != location.hostname
+ ? 'document.domain="' + document.domain + '";'
+ : "") +
+ 'document.write("' +
+ html +
+ '");document.close();}())'
+ })
+ );
+ container.style.overflow = "hidden";
+ //解决如果是给定的百分比,会导致高度算不对的问题
+ setTimeout(function() {
+ if (/%$/.test(options.initialFrameWidth)) {
+ options.minFrameWidth = options.initialFrameWidth =
+ container.offsetWidth;
+ //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化
+ // container.style.width = options.initialFrameWidth + 'px';
+ }
+ if (/%$/.test(options.initialFrameHeight)) {
+ options.minFrameHeight = options.initialFrameHeight =
+ container.offsetHeight;
+ container.style.height = options.initialFrameHeight + "px";
+ }
+ });
+ }
+ },
+
+ /**
+ * 编辑器初始化
+ * @method _setup
+ * @private
+ * @param { Element } doc 编辑器Iframe中的文档对象
+ */
+ _setup: function(doc) {
+ var me = this,
+ options = me.options;
+ if (ie) {
+ doc.body.disabled = true;
+ doc.body.contentEditable = true;
+ doc.body.disabled = false;
+ } else {
+ doc.body.contentEditable = true;
+ }
+ doc.body.spellcheck = false;
+ me.document = doc;
+ me.window = doc.defaultView || doc.parentWindow;
+ me.iframe = me.window.frameElement;
+ me.body = doc.body;
+ me.selection = new dom.Selection(doc);
+ //gecko初始化就能得到range,无法判断isFocus了
+ var geckoSel;
+ if (browser.gecko && (geckoSel = this.selection.getNative())) {
+ geckoSel.removeAllRanges();
+ }
+ this._initEvents();
+ //为form提交提供一个隐藏的textarea
+ for (
+ var form = this.iframe.parentNode;
+ !domUtils.isBody(form);
+ form = form.parentNode
+ ) {
+ if (form.tagName == "FORM") {
+ me.form = form;
+ if (me.options.autoSyncData) {
+ domUtils.on(me.window, "blur", function() {
+ setValue(form, me);
+ });
+ } else {
+ domUtils.on(form, "submit", function() {
+ setValue(this, me);
+ });
+ }
+ break;
+ }
+ }
+ if (options.initialContent) {
+ if (options.autoClearinitialContent) {
+ var oldExecCommand = me.execCommand;
+ me.execCommand = function() {
+ me.fireEvent("firstBeforeExecCommand");
+ return oldExecCommand.apply(me, arguments);
+ };
+ this._setDefaultContent(options.initialContent);
+ } else this.setContent(options.initialContent, false, true);
+ }
+
+ //编辑器不能为空内容
+
+ if (domUtils.isEmptyNode(me.body)) {
+ me.body.innerHTML = "" + (browser.ie ? "" : " ") + " ";
+ }
+ //如果要求focus, 就把光标定位到内容开始
+ if (options.focus) {
+ setTimeout(function() {
+ me.focus(me.options.focusInEnd);
+ //如果自动清除开着,就不需要做selectionchange;
+ !me.options.autoClearinitialContent && me._selectionChange();
+ }, 0);
+ }
+ if (!me.container) {
+ me.container = this.iframe.parentNode;
+ }
+ if (options.fullscreen && me.ui) {
+ me.ui.setFullScreen(true);
+ }
+
+ try {
+ me.document.execCommand("2D-position", false, false);
+ } catch (e) {}
+ try {
+ me.document.execCommand("enableInlineTableEditing", false, false);
+ } catch (e) {}
+ try {
+ me.document.execCommand("enableObjectResizing", false, false);
+ } catch (e) {}
+
+ //挂接快捷键
+ me._bindshortcutKeys();
+ me.isReady = 1;
+ me.fireEvent("ready");
+ options.onready && options.onready.call(me);
+ if (!browser.ie9below) {
+ domUtils.on(me.window, ["blur", "focus"], function(e) {
+ //chrome下会出现alt+tab切换时,导致选区位置不对
+ if (e.type == "blur") {
+ me._bakRange = me.selection.getRange();
+ try {
+ me._bakNativeRange = me.selection.getNative().getRangeAt(0);
+ me.selection.getNative().removeAllRanges();
+ } catch (e) {
+ me._bakNativeRange = null;
+ }
+ } else {
+ try {
+ me._bakRange && me._bakRange.select();
+ } catch (e) {}
+ }
+ });
+ }
+ //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点
+ if (browser.gecko && browser.version <= 10902) {
+ //修复ff3.6初始化进来,不能点击获得焦点
+ me.body.contentEditable = false;
+ setTimeout(function() {
+ me.body.contentEditable = true;
+ }, 100);
+ setInterval(function() {
+ me.body.style.height = me.iframe.offsetHeight - 20 + "px";
+ }, 100);
+ }
+
+ !options.isShow && me.setHide();
+ options.readonly && me.setDisabled();
+ },
+
+ /**
+ * 同步数据到编辑器所在的form
+ * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况
+ * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项
+ * @method sync
+ * @example
+ * ```javascript
+ * editor.sync();
+ * form.sumbit(); //form变量已经指向了form元素
+ * ```
+ */
+
+ /**
+ * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备
+ * 后台取得数据的键值,该键值默认使用给定的编辑器容器的name属性,如果没有name属性则使用参数项里给定的“textarea”项
+ * @method sync
+ * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下
+ */
+ sync: function(formId) {
+ var me = this,
+ form = formId
+ ? document.getElementById(formId)
+ : domUtils.findParent(
+ me.iframe.parentNode,
+ function(node) {
+ return node.tagName == "FORM";
+ },
+ true
+ );
+ form && setValue(form, me);
+ },
+
+ /**
+ * 设置编辑器高度
+ * @method setHeight
+ * @remind 当配置项autoHeightEnabled为真时,该方法无效
+ * @param { Number } number 设置的高度值,纯数值,不带单位
+ * @example
+ * ```javascript
+ * editor.setHeight(number);
+ * ```
+ */
+ setHeight: function(height, notSetHeight) {
+ if (height !== parseInt(this.iframe.parentNode.style.height)) {
+ this.iframe.parentNode.style.height = height + "px";
+ }
+ !notSetHeight &&
+ (this.options.minFrameHeight = this.options.initialFrameHeight = height);
+ this.body.style.height = height + "px";
+ !notSetHeight && this.trigger("setHeight");
+ },
+
+ /**
+ * 为编辑器的编辑命令提供快捷键
+ * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口
+ * @method addshortcutkey
+ * @param { Object } keyset 命令名和快捷键键值对对象,多个按钮的快捷键用“+”分隔
+ * @example
+ * ```javascript
+ * editor.addshortcutkey({
+ * "Bold" : "ctrl+66",//^B
+ * "Italic" : "ctrl+73", //^I
+ * });
+ * ```
+ */
+ /**
+ * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口
+ * @method addshortcutkey
+ * @param { String } cmd 触发快捷键时,响应的命令
+ * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔
+ * @example
+ * ```javascript
+ * editor.addshortcutkey("Underline", "ctrl+85"); //^U
+ * ```
+ */
+ addshortcutkey: function(cmd, keys) {
+ var obj = {};
+ if (keys) {
+ obj[cmd] = keys;
+ } else {
+ obj = cmd;
+ }
+ utils.extend(this.shortcutkeys, obj);
+ },
+
+ /**
+ * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令
+ * @method _bindshortcutKeys
+ * @private
+ */
+ _bindshortcutKeys: function() {
+ var me = this,
+ shortcutkeys = this.shortcutkeys;
+ me.addListener("keydown", function(type, e) {
+ var keyCode = e.keyCode || e.which;
+ for (var i in shortcutkeys) {
+ var tmp = shortcutkeys[i].split(",");
+ for (var t = 0, ti; (ti = tmp[t++]); ) {
+ ti = ti.split(":");
+ var key = ti[0],
+ param = ti[1];
+ if (
+ /^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) ||
+ /^(\d+)$/.test(key)
+ ) {
+ if (
+ ((RegExp.$1 == "ctrl" ? e.ctrlKey || e.metaKey : 0) &&
+ (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) &&
+ keyCode == RegExp.$3) ||
+ keyCode == RegExp.$1
+ ) {
+ if (me.queryCommandState(i, param) != -1)
+ me.execCommand(i, param);
+ domUtils.preventDefault(e);
+ }
+ }
+ }
+ }
+ });
+ },
+
+ /**
+ * 获取编辑器的内容
+ * @method getContent
+ * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容
+ * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串
+ * @example
+ * ```javascript
+ * //编辑器html内容:123456
+ * var content = editor.getContent(); //返回值:123456
+ * ```
+ */
+
+ /**
+ * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则
+ * @method getContent
+ * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值,
+ * 代表当前编辑器的内容是否空,
+ * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回
+ * 经过内置过滤规则处理后的内容。
+ * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。
+ * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容
+ * @return { String } 编辑器的内容字符串
+ * @example
+ * ```javascript
+ * // editor 是一个编辑器的实例
+ * var content = editor.getContent( function ( editor ) {
+ * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串
+ * } );
+ * ```
+ */
+ getContent: function(cmd, fn, notSetCursor, ignoreBlank, formatter) {
+ var me = this;
+ if (cmd && utils.isFunction(cmd)) {
+ fn = cmd;
+ cmd = "";
+ }
+ if (fn ? !fn() : !this.hasContents()) {
+ return "";
+ }
+ me.fireEvent("beforegetcontent");
+ var root = UE.htmlparser(me.body.innerHTML, ignoreBlank);
+ me.filterOutputRule(root);
+ me.fireEvent("aftergetcontent", cmd, root);
+ return root.toHtml(formatter);
+ },
+
+ /**
+ * 取得完整的html代码,可以直接显示成完整的html文档
+ * @method getAllHtml
+ * @return { String } 编辑器的内容html文档字符串
+ * @eaxmple
+ * ```javascript
+ * editor.getAllHtml(); //返回格式大致是: ......
+ * ```
+ */
+ getAllHtml: function() {
+ var me = this,
+ headHtml = [],
+ html = "";
+ me.fireEvent("getAllHtml", headHtml);
+ if (browser.ie && browser.version > 8) {
+ var headHtmlForIE9 = "";
+ utils.each(me.document.styleSheets, function(si) {
+ headHtmlForIE9 += si.href
+ ? ''
+ : "";
+ });
+ utils.each(me.document.getElementsByTagName("script"), function(si) {
+ headHtmlForIE9 += si.outerHTML;
+ });
+ }
+ return (
+ "" +
+ (me.options.charset
+ ? ''
+ : "") +
+ (headHtmlForIE9 ||
+ me.document.getElementsByTagName("head")[0].innerHTML) +
+ headHtml.join("\n") +
+ "" +
+ "" +
+ me.getContent(null, null, true) +
+ ""
+ );
+ },
+
+ /**
+ * 得到编辑器的纯文本内容,但会保留段落格式
+ * @method getPlainTxt
+ * @return { String } 编辑器带段落格式的纯文本内容字符串
+ * @example
+ * ```javascript
+ * //编辑器html内容:1 2
+ * console.log(editor.getPlainTxt()); //输出:"1\n2\n
+ * ```
+ */
+ getPlainTxt: function() {
+ var reg = new RegExp(domUtils.fillChar, "g"),
+ html = this.body.innerHTML.replace(/[\n\r]/g, ""); //ie要先去了\n在处理
+ html = html
+ .replace(/<(p|div)[^>]*>( | )<\/\1>/gi, "\n")
+ .replace(/ /gi, "\n")
+ .replace(/<[^>/]+>/g, "")
+ .replace(/(\n)?<\/([^>]+)>/g, function(a, b, c) {
+ return dtd.$block[c] ? "\n" : b ? b : "";
+ });
+ //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0
+ return html
+ .replace(reg, "")
+ .replace(/\u00a0/g, " ")
+ .replace(/ /g, " ");
+ },
+
+ /**
+ * 获取编辑器中的纯文本内容,没有段落格式
+ * @method getContentTxt
+ * @return { String } 编辑器不带段落格式的纯文本内容字符串
+ * @example
+ * ```javascript
+ * //编辑器html内容:1 2
+ * console.log(editor.getPlainTxt()); //输出:"12
+ * ```
+ */
+ getContentTxt: function() {
+ var reg = new RegExp(domUtils.fillChar, "g");
+ //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0
+ return this.body[browser.ie ? "innerText" : "textContent"]
+ .replace(reg, "")
+ .replace(/\u00a0/g, " ");
+ },
+
+ /**
+ * 设置编辑器的内容,可修改编辑器当前的html内容
+ * @method setContent
+ * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容
+ * @warning 该方法会触发selectionchange事件
+ * @param { String } html 要插入的html内容
+ * @example
+ * ```javascript
+ * editor.getContent('test ');
+ * ```
+ */
+
+ /**
+ * 设置编辑器的内容,可修改编辑器当前的html内容
+ * @method setContent
+ * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容
+ * @warning 该方法会触发selectionchange事件
+ * @param { String } html 要插入的html内容
+ * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入
+ * @example
+ * ```javascript
+ * //假设设置前的编辑器内容是 old text
+ * editor.setContent('new text ', true); //插入的结果是old text new text
+ * ```
+ */
+ setContent: function(html, isAppendTo, notFireSelectionchange) {
+ var me = this;
+
+ me.fireEvent("beforesetcontent", html);
+ var root = UE.htmlparser(html);
+ me.filterInputRule(root);
+ html = root.toHtml();
+
+ me.body.innerHTML = (isAppendTo ? me.body.innerHTML : "") + html;
+
+ function isCdataDiv(node) {
+ return node.tagName == "DIV" && node.getAttribute("cdata_tag");
+ }
+ //给文本或者inline节点套p标签
+ if (me.options.enterTag == "p") {
+ var child = this.body.firstChild,
+ tmpNode;
+ if (
+ !child ||
+ (child.nodeType == 1 &&
+ (dtd.$cdata[child.tagName] ||
+ isCdataDiv(child) ||
+ domUtils.isCustomeNode(child)) &&
+ child === this.body.lastChild)
+ ) {
+ this.body.innerHTML =
+ "" +
+ (browser.ie ? " " : " ") +
+ " " +
+ this.body.innerHTML;
+ } else {
+ var p = me.document.createElement("p");
+ while (child) {
+ while (
+ child &&
+ (child.nodeType == 3 ||
+ (child.nodeType == 1 &&
+ dtd.p[child.tagName] &&
+ !dtd.$cdata[child.tagName]))
+ ) {
+ tmpNode = child.nextSibling;
+ p.appendChild(child);
+ child = tmpNode;
+ }
+ if (p.firstChild) {
+ if (!child) {
+ me.body.appendChild(p);
+ break;
+ } else {
+ child.parentNode.insertBefore(p, child);
+ p = me.document.createElement("p");
+ }
+ }
+ child = child.nextSibling;
+ }
+ }
+ }
+ me.fireEvent("aftersetcontent");
+ me.fireEvent("contentchange");
+
+ !notFireSelectionchange && me._selectionChange();
+ //清除保存的选区
+ me._bakRange = me._bakIERange = me._bakNativeRange = null;
+ //trace:1742 setContent后gecko能得到焦点问题
+ var geckoSel;
+ if (browser.gecko && (geckoSel = this.selection.getNative())) {
+ geckoSel.removeAllRanges();
+ }
+ if (me.options.autoSyncData) {
+ me.form && setValue(me.form, me);
+ }
+ },
+
+ /**
+ * 让编辑器获得焦点,默认focus到编辑器头部
+ * @method focus
+ * @example
+ * ```javascript
+ * editor.focus()
+ * ```
+ */
+
+ /**
+ * 让编辑器获得焦点,toEnd确定focus位置
+ * @method focus
+ * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部
+ * @example
+ * ```javascript
+ * editor.focus(true)
+ * ```
+ */
+ focus: function(toEnd) {
+ try {
+ var me = this,
+ rng = me.selection.getRange();
+ if (toEnd) {
+ var node = me.body.lastChild;
+ if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
+ if (domUtils.isEmptyBlock(node)) {
+ rng.setStartAtFirst(node);
+ } else {
+ rng.setStartAtLast(node);
+ }
+ rng.collapse(true);
+ }
+ rng.setCursor(true);
+ } else {
+ if (
+ !rng.collapsed &&
+ domUtils.isBody(rng.startContainer) &&
+ rng.startOffset == 0
+ ) {
+ var node = me.body.firstChild;
+ if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
+ rng.setStartAtFirst(node).collapse(true);
+ }
+ }
+
+ rng.select(true);
+ }
+ this.fireEvent("focus selectionchange");
+ } catch (e) {}
+ },
+ isFocus: function() {
+ return this.selection.isFocus();
+ },
+ blur: function() {
+ var sel = this.selection.getNative();
+ if (sel.empty && browser.ie) {
+ var nativeRng = document.body.createTextRange();
+ nativeRng.moveToElementText(document.body);
+ nativeRng.collapse(true);
+ nativeRng.select();
+ sel.empty();
+ } else {
+ sel.removeAllRanges();
+ }
+
+ //this.fireEvent('blur selectionchange');
+ },
+ /**
+ * 初始化UE事件及部分事件代理
+ * @method _initEvents
+ * @private
+ */
+ _initEvents: function() {
+ var me = this,
+ doc = me.document,
+ win = me.window;
+ me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
+ domUtils.on(
+ doc,
+ [
+ "click",
+ "contextmenu",
+ "mousedown",
+ "keydown",
+ "keyup",
+ "keypress",
+ "mouseup",
+ "mouseover",
+ "mouseout",
+ "selectstart"
+ ],
+ me._proxyDomEvent
+ );
+ domUtils.on(win, ["focus", "blur"], me._proxyDomEvent);
+ domUtils.on(me.body, "drop", function(e) {
+ //阻止ff下默认的弹出新页面打开图片
+ if (browser.gecko && e.stopPropagation) {
+ e.stopPropagation();
+ }
+ me.fireEvent("contentchange");
+ });
+ domUtils.on(doc, ["mouseup", "keydown"], function(evt) {
+ //特殊键不触发selectionchange
+ if (
+ evt.type == "keydown" &&
+ (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)
+ ) {
+ return;
+ }
+ if (evt.button == 2) return;
+ me._selectionChange(250, evt);
+ });
+ },
+ /**
+ * 触发事件代理
+ * @method _proxyDomEvent
+ * @private
+ * @return { * } fireEvent的返回值
+ * @see UE.EventBase:fireEvent(String)
+ */
+ _proxyDomEvent: function(evt) {
+ if (
+ this.fireEvent("before" + evt.type.replace(/^on/, "").toLowerCase()) ===
+ false
+ ) {
+ return false;
+ }
+ if (this.fireEvent(evt.type.replace(/^on/, ""), evt) === false) {
+ return false;
+ }
+ return this.fireEvent(
+ "after" + evt.type.replace(/^on/, "").toLowerCase()
+ );
+ },
+ /**
+ * 变化选区
+ * @method _selectionChange
+ * @private
+ */
+ _selectionChange: function(delay, evt) {
+ var me = this;
+ //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1)
+ // if ( !me.selection.isFocus() ){
+ // return;
+ // }
+
+ var hackForMouseUp = false;
+ var mouseX, mouseY;
+ if (browser.ie && browser.version < 9 && evt && evt.type == "mouseup") {
+ var range = this.selection.getRange();
+ if (!range.collapsed) {
+ hackForMouseUp = true;
+ mouseX = evt.clientX;
+ mouseY = evt.clientY;
+ }
+ }
+ clearTimeout(_selectionChangeTimer);
+ _selectionChangeTimer = setTimeout(function() {
+ if (!me.selection || !me.selection.getNative()) {
+ return;
+ }
+ //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值.
+ //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响
+ var ieRange;
+ if (hackForMouseUp && me.selection.getNative().type == "None") {
+ ieRange = me.document.body.createTextRange();
+ try {
+ ieRange.moveToPoint(mouseX, mouseY);
+ } catch (ex) {
+ ieRange = null;
+ }
+ }
+ var bakGetIERange;
+ if (ieRange) {
+ bakGetIERange = me.selection.getIERange;
+ me.selection.getIERange = function() {
+ return ieRange;
+ };
+ }
+ me.selection.cache();
+ if (bakGetIERange) {
+ me.selection.getIERange = bakGetIERange;
+ }
+ if (me.selection._cachedRange && me.selection._cachedStartElement) {
+ me.fireEvent("beforeselectionchange");
+ // 第二个参数causeByUi为true代表由用户交互造成的selectionchange.
+ me.fireEvent("selectionchange", !!evt);
+ me.fireEvent("afterselectionchange");
+ me.selection.clear();
+ }
+ }, delay || 50);
+ },
+
+ /**
+ * 执行编辑命令
+ * @method _callCmdFn
+ * @private
+ * @param { String } fnName 函数名称
+ * @param { * } args 传给命令函数的参数
+ * @return { * } 返回命令函数运行的返回值
+ */
+ _callCmdFn: function(fnName, args) {
+ var cmdName = args[0].toLowerCase(),
+ cmd,
+ cmdFn;
+ cmd = this.commands[cmdName] || UE.commands[cmdName];
+ cmdFn = cmd && cmd[fnName];
+ //没有querycommandstate或者没有command的都默认返回0
+ if ((!cmd || !cmdFn) && fnName == "queryCommandState") {
+ return 0;
+ } else if (cmdFn) {
+ return cmdFn.apply(this, args);
+ }
+ },
+
+ /**
+ * 执行编辑命令cmdName,完成富文本编辑效果
+ * @method execCommand
+ * @param { String } cmdName 需要执行的命令
+ * @remind 具体命令的使用请参考命令列表
+ * @return { * } 返回命令函数运行的返回值
+ * @example
+ * ```javascript
+ * editor.execCommand(cmdName);
+ * ```
+ */
+ execCommand: function(cmdName) {
+ cmdName = cmdName.toLowerCase();
+ var me = this,
+ result,
+ cmd = me.commands[cmdName] || UE.commands[cmdName];
+ if (!cmd || !cmd.execCommand) {
+ return null;
+ }
+ if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {
+ me.__hasEnterExecCommand = true;
+ if (me.queryCommandState.apply(me, arguments) != -1) {
+ me.fireEvent("saveScene");
+ me.fireEvent.apply(
+ me,
+ ["beforeexeccommand", cmdName].concat(arguments)
+ );
+ result = this._callCmdFn("execCommand", arguments);
+ //保存场景时,做了内容对比,再看是否进行contentchange触发,这里多触发了一次,去掉
+ // (!cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange');
+ me.fireEvent.apply(
+ me,
+ ["afterexeccommand", cmdName].concat(arguments)
+ );
+ me.fireEvent("saveScene");
+ }
+ me.__hasEnterExecCommand = false;
+ } else {
+ result = this._callCmdFn("execCommand", arguments);
+ !me.__hasEnterExecCommand &&
+ !cmd.ignoreContentChange &&
+ !me._ignoreContentChange &&
+ me.fireEvent("contentchange");
+ }
+ !me.__hasEnterExecCommand &&
+ !cmd.ignoreContentChange &&
+ !me._ignoreContentChange &&
+ me._selectionChange();
+ return result;
+ },
+
+ /**
+ * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态
+ * @method queryCommandState
+ * @param { String } cmdName 需要查询的命令名称
+ * @remind 具体命令的使用请参考命令列表
+ * @return { Number } number 返回放前命令的状态,返回值三种情况:(-1|0|1)
+ * @example
+ * ```javascript
+ * editor.queryCommandState(cmdName) => (-1|0|1)
+ * ```
+ * @see COMMAND.LIST
+ */
+ queryCommandState: function(cmdName) {
+ return this._callCmdFn("queryCommandState", arguments);
+ },
+
+ /**
+ * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值
+ * @method queryCommandValue
+ * @param { String } cmdName 需要查询的命令名称
+ * @remind 具体命令的使用请参考命令列表
+ * @remind 只有部分插件有此方法
+ * @return { * } 返回每个命令特定的当前状态值
+ * @grammar editor.queryCommandValue(cmdName) => {*}
+ * @see COMMAND.LIST
+ */
+ queryCommandValue: function(cmdName) {
+ return this._callCmdFn("queryCommandValue", arguments);
+ },
+
+ /**
+ * 检查编辑区域中是否有内容
+ * @method hasContents
+ * @remind 默认有文本内容,或者有以下节点都不认为是空
+ * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param
+ * @return { Boolean } 检查有内容返回true,否则返回false
+ * @example
+ * ```javascript
+ * editor.hasContents()
+ * ```
+ */
+
+ /**
+ * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true
+ * @method hasContents
+ * @param { Array } tags 传入数组判断时用到的节点类型
+ * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false
+ * @example
+ * ```javascript
+ * editor.hasContents(['span']);
+ * ```
+ */
+ hasContents: function(tags) {
+ if (tags) {
+ for (var i = 0, ci; (ci = tags[i++]); ) {
+ if (this.document.getElementsByTagName(ci).length > 0) {
+ return true;
+ }
+ }
+ }
+ if (!domUtils.isEmptyBlock(this.body)) {
+ return true;
+ }
+ //随时添加,定义的特殊标签如果存在,不能认为是空
+ tags = ["div"];
+ for (i = 0; (ci = tags[i++]); ) {
+ var nodes = domUtils.getElementsByTagName(this.document, ci);
+ for (var n = 0, cn; (cn = nodes[n++]); ) {
+ if (domUtils.isCustomeNode(cn)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+
+ /**
+ * 重置编辑器,可用来做多个tab使用同一个编辑器实例
+ * @method reset
+ * @remind 此方法会清空编辑器内容,清空回退列表,会触发reset事件
+ * @example
+ * ```javascript
+ * editor.reset()
+ * ```
+ */
+ reset: function() {
+ this.fireEvent("reset");
+ },
+
+ /**
+ * 设置当前编辑区域可以编辑
+ * @method setEnabled
+ * @example
+ * ```javascript
+ * editor.setEnabled()
+ * ```
+ */
+ setEnabled: function() {
+ var me = this,
+ range;
+ if (me.body.contentEditable == "false") {
+ me.body.contentEditable = true;
+ range = me.selection.getRange();
+ //有可能内容丢失了
+ try {
+ range.moveToBookmark(me.lastBk);
+ delete me.lastBk;
+ } catch (e) {
+ range.setStartAtFirst(me.body).collapse(true);
+ }
+ range.select(true);
+ if (me.bkqueryCommandState) {
+ me.queryCommandState = me.bkqueryCommandState;
+ delete me.bkqueryCommandState;
+ }
+ if (me.bkqueryCommandValue) {
+ me.queryCommandValue = me.bkqueryCommandValue;
+ delete me.bkqueryCommandValue;
+ }
+ me.fireEvent("selectionchange");
+ }
+ },
+ enable: function() {
+ return this.setEnabled();
+ },
+
+ /** 设置当前编辑区域不可编辑
+ * @method setDisabled
+ */
+
+ /** 设置当前编辑区域不可编辑,except中的命令除外
+ * @method setDisabled
+ * @param { String } except 例外命令的字符串
+ * @remind 即使设置了disable,此处配置的例外命令仍然可以执行
+ * @example
+ * ```javascript
+ * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能
+ * ```
+ */
+
+ /** 设置当前编辑区域不可编辑,except中的命令除外
+ * @method setDisabled
+ * @param { Array } except 例外命令的字符串数组,数组中的命令仍然可以执行
+ * @remind 即使设置了disable,此处配置的例外命令仍然可以执行
+ * @example
+ * ```javascript
+ * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能
+ * ```
+ */
+ setDisabled: function(except) {
+ var me = this;
+ except = except ? (utils.isArray(except) ? except : [except]) : [];
+ if (me.body.contentEditable == "true") {
+ if (!me.lastBk) {
+ me.lastBk = me.selection.getRange().createBookmark(true);
+ }
+ me.body.contentEditable = false;
+ me.bkqueryCommandState = me.queryCommandState;
+ me.bkqueryCommandValue = me.queryCommandValue;
+ me.queryCommandState = function(type) {
+ if (utils.indexOf(except, type) != -1) {
+ return me.bkqueryCommandState.apply(me, arguments);
+ }
+ return -1;
+ };
+ me.queryCommandValue = function(type) {
+ if (utils.indexOf(except, type) != -1) {
+ return me.bkqueryCommandValue.apply(me, arguments);
+ }
+ return null;
+ };
+ me.fireEvent("selectionchange");
+ }
+ },
+ disable: function(except) {
+ return this.setDisabled(except);
+ },
+
+ /**
+ * 设置默认内容
+ * @method _setDefaultContent
+ * @private
+ * @param { String } cont 要存入的内容
+ */
+ _setDefaultContent: (function() {
+ function clear() {
+ var me = this;
+ if (me.document.getElementById("initContent")) {
+ me.body.innerHTML = "" + (ie ? "" : " ") + " ";
+ me.removeListener("firstBeforeExecCommand focus", clear);
+ setTimeout(function() {
+ me.focus();
+ me._selectionChange();
+ }, 0);
+ }
+ }
+
+ return function(cont) {
+ var me = this;
+ me.body.innerHTML = '' + cont + " ";
+
+ me.addListener("firstBeforeExecCommand focus", clear);
+ };
+ })(),
+
+ /**
+ * 显示编辑器
+ * @method setShow
+ * @example
+ * ```javascript
+ * editor.setShow()
+ * ```
+ */
+ setShow: function() {
+ var me = this,
+ range = me.selection.getRange();
+ if (me.container.style.display == "none") {
+ //有可能内容丢失了
+ try {
+ range.moveToBookmark(me.lastBk);
+ delete me.lastBk;
+ } catch (e) {
+ range.setStartAtFirst(me.body).collapse(true);
+ }
+ //ie下focus实效,所以做了个延迟
+ setTimeout(function() {
+ range.select(true);
+ }, 100);
+ me.container.style.display = "";
+ }
+ },
+ show: function() {
+ return this.setShow();
+ },
+ /**
+ * 隐藏编辑器
+ * @method setHide
+ * @example
+ * ```javascript
+ * editor.setHide()
+ * ```
+ */
+ setHide: function() {
+ var me = this;
+ if (!me.lastBk) {
+ me.lastBk = me.selection.getRange().createBookmark(true);
+ }
+ me.container.style.display = "none";
+ },
+ hide: function() {
+ return this.setHide();
+ },
+
+ /**
+ * 根据指定的路径,获取对应的语言资源
+ * @method getLang
+ * @param { String } path 路径根据的是lang目录下的语言文件的路径结构
+ * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串
+ * @example
+ * ```javascript
+ * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除'
+ * ```
+ */
+ getLang: function(path) {
+ var lang = UE.I18N[this.options.lang];
+ if (!lang) {
+ throw Error("not import language file");
+ }
+ path = (path || "").split(".");
+ for (var i = 0, ci; (ci = path[i++]); ) {
+ lang = lang[ci];
+ if (!lang) break;
+ }
+ return lang;
+ },
+
+ /**
+ * 计算编辑器html内容字符串的长度
+ * @method getContentLength
+ * @return { Number } 返回计算的长度
+ * @example
+ * ```javascript
+ * //编辑器html内容132
+ * editor.getContentLength() //返回27
+ * ```
+ */
+ /**
+ * 计算编辑器当前纯文本内容的长度
+ * @method getContentLength
+ * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算
+ * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1
+ * @example
+ * ```javascript
+ * //编辑器html内容132
+ * editor.getContentLength() //返回3
+ * ```
+ */
+ getContentLength: function(ingoneHtml, tagNames) {
+ var count = this.getContent(false, false, true).length;
+ if (ingoneHtml) {
+ tagNames = (tagNames || []).concat(["hr", "img", "iframe"]);
+ count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length;
+ for (var i = 0, ci; (ci = tagNames[i++]); ) {
+ count += this.document.getElementsByTagName(ci).length;
+ }
+ }
+ return count;
+ },
+
+ /**
+ * 注册输入过滤规则
+ * @method addInputRule
+ * @param { Function } rule 要添加的过滤规则
+ * @example
+ * ```javascript
+ * editor.addInputRule(function(root){
+ * $.each(root.getNodesByTagName('div'),function(i,node){
+ * node.tagName="p";
+ * });
+ * });
+ * ```
+ */
+ addInputRule: function(rule) {
+ this.inputRules.push(rule);
+ },
+
+ /**
+ * 执行注册的过滤规则
+ * @method filterInputRule
+ * @param { UE.uNode } root 要过滤的uNode节点
+ * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数
+ * @example
+ * ```javascript
+ * editor.filterInputRule(editor.body);
+ * ```
+ * @see UE.Editor:addInputRule
+ */
+ filterInputRule: function(root) {
+ for (var i = 0, ci; (ci = this.inputRules[i++]); ) {
+ ci.call(this, root);
+ }
+ },
+
+ /**
+ * 注册输出过滤规则
+ * @method addOutputRule
+ * @param { Function } rule 要添加的过滤规则
+ * @example
+ * ```javascript
+ * editor.addOutputRule(function(root){
+ * $.each(root.getNodesByTagName('p'),function(i,node){
+ * node.tagName="div";
+ * });
+ * });
+ * ```
+ */
+ addOutputRule: function(rule) {
+ this.outputRules.push(rule);
+ },
+
+ /**
+ * 根据输出过滤规则,过滤编辑器内容
+ * @method filterOutputRule
+ * @remind 执行editor.getContent方法的时候,会先运行该过滤函数
+ * @param { UE.uNode } root 要过滤的uNode节点
+ * @example
+ * ```javascript
+ * editor.filterOutputRule(editor.body);
+ * ```
+ * @see UE.Editor:addOutputRule
+ */
+ filterOutputRule: function(root) {
+ for (var i = 0, ci; (ci = this.outputRules[i++]); ) {
+ ci.call(this, root);
+ }
+ },
+
+ /**
+ * 根据action名称获取请求的路径
+ * @method getActionUrl
+ * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径
+ * @param { String } action action名称
+ * @example
+ * ```javascript
+ * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config"
+ * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage"
+ * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl"
+ * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage"
+ * ```
+ */
+ getActionUrl: function(action) {
+ var actionName = this.getOpt(action) || action,
+ imageUrl = this.getOpt("imageUrl"),
+ serverUrl = this.getOpt("serverUrl");
+
+ if (!serverUrl && imageUrl) {
+ serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2");
+ }
+
+ if (serverUrl) {
+ serverUrl =
+ serverUrl +
+ (serverUrl.indexOf("?") == -1 ? "?" : "&") +
+ "action=" +
+ (actionName || "");
+ return utils.formatUrl(serverUrl);
+ } else {
+ return "";
+ }
+ }
+ };
+ utils.inherits(Editor, EventBase);
+})();
diff --git a/_src/core/EventBase.js b/_src/core/EventBase.js
index 2e418f541..f65ddf898 100644
--- a/_src/core/EventBase.js
+++ b/_src/core/EventBase.js
@@ -1,167 +1,170 @@
-/**
- * UE采用的事件基类
- * @file
- * @module UE
- * @class EventBase
- * @since 1.2.6.1
- */
-
-/**
- * UEditor公用空间,UEditor所有的功能都挂载在该空间下
- * @unfile
- * @module UE
- */
-
-/**
- * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。
- * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。
- * @unfile
- * @module UE
- * @class EventBase
- */
-
-/**
- * 通过此构造器,子类可以继承EventBase获取事件监听的方法
- * @constructor
- * @example
- * ```javascript
- * UE.EventBase.call(editor);
- * ```
- */
-var EventBase = UE.EventBase = function () {};
-
-EventBase.prototype = {
-
- /**
- * 注册事件监听器
- * @method addListener
- * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔
- * @param { Function } fn 监听的事件被触发时,会执行该回调函数
- * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行
- * @example
- * ```javascript
- * editor.addListener('selectionchange',function(){
- * console.log("选区已经变化!");
- * })
- * editor.addListener('beforegetcontent aftergetcontent',function(type){
- * if(type == 'beforegetcontent'){
- * //do something
- * }else{
- * //do something
- * }
- * console.log(this.getContent) // this是注册的事件的编辑器实例
- * })
- * ```
- * @see UE.EventBase:fireEvent(String)
- */
- addListener:function (types, listener) {
- types = utils.trim(types).split(/\s+/);
- for (var i = 0, ti; ti = types[i++];) {
- getListener(this, ti, true).push(listener);
- }
- },
-
- on : function(types, listener){
- return this.addListener(types,listener);
- },
- off : function(types, listener){
- return this.removeListener(types, listener)
- },
- trigger:function(){
- return this.fireEvent.apply(this,arguments);
- },
- /**
- * 移除事件监听器
- * @method removeListener
- * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔
- * @param { Function } fn 移除监听事件的函数引用
- * @example
- * ```javascript
- * //changeCallback为方法体
- * editor.removeListener("selectionchange",changeCallback);
- * ```
- */
- removeListener:function (types, listener) {
- types = utils.trim(types).split(/\s+/);
- for (var i = 0, ti; ti = types[i++];) {
- utils.removeItem(getListener(this, ti) || [], listener);
- }
- },
-
- /**
- * 触发事件
- * @method fireEvent
- * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔
- * @remind 该方法会触发addListener
- * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值
- * @example
- * ```javascript
- * editor.fireEvent("selectionchange");
- * ```
- */
-
- /**
- * 触发事件
- * @method fireEvent
- * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔
- * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数
- * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值
- * @example
- * ```javascript
- *
- * editor.addListener( "selectionchange", function ( type, arg1, arg2 ) {
- *
- * console.log( arg1 + " " + arg2 );
- *
- * } );
- *
- * //触发selectionchange事件, 会执行上面的事件监听器
- * //output: Hello World
- * editor.fireEvent("selectionchange", "Hello", "World");
- * ```
- */
- fireEvent:function () {
- var types = arguments[0];
- types = utils.trim(types).split(' ');
- for (var i = 0, ti; ti = types[i++];) {
- var listeners = getListener(this, ti),
- r, t, k;
- if (listeners) {
- k = listeners.length;
- while (k--) {
- if(!listeners[k])continue;
- t = listeners[k].apply(this, arguments);
- if(t === true){
- return t;
- }
- if (t !== undefined) {
- r = t;
- }
- }
- }
- if (t = this['on' + ti.toLowerCase()]) {
- r = t.apply(this, arguments);
- }
- }
- return r;
- }
-};
-/**
- * 获得对象所拥有监听类型的所有监听器
- * @unfile
- * @module UE
- * @since 1.2.6.1
- * @method getListener
- * @public
- * @param { Object } obj 查询监听器的对象
- * @param { String } type 事件类型
- * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组
- * @return { Array } 监听器数组
- */
-function getListener(obj, type, force) {
- var allListeners;
- type = type.toLowerCase();
- return ( ( allListeners = ( obj.__allListeners || force && ( obj.__allListeners = {} ) ) )
- && ( allListeners[type] || force && ( allListeners[type] = [] ) ) );
-}
-
+/**
+ * UE采用的事件基类
+ * @file
+ * @module UE
+ * @class EventBase
+ * @since 1.2.6.1
+ */
+
+/**
+ * UEditor公用空间,UEditor所有的功能都挂载在该空间下
+ * @unfile
+ * @module UE
+ */
+
+/**
+ * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。
+ * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。
+ * @unfile
+ * @module UE
+ * @class EventBase
+ */
+
+/**
+ * 通过此构造器,子类可以继承EventBase获取事件监听的方法
+ * @constructor
+ * @example
+ * ```javascript
+ * UE.EventBase.call(editor);
+ * ```
+ */
+var EventBase = (UE.EventBase = function() {});
+
+EventBase.prototype = {
+ /**
+ * 注册事件监听器
+ * @method addListener
+ * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔
+ * @param { Function } fn 监听的事件被触发时,会执行该回调函数
+ * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行
+ * @example
+ * ```javascript
+ * editor.addListener('selectionchange',function(){
+ * console.log("选区已经变化!");
+ * })
+ * editor.addListener('beforegetcontent aftergetcontent',function(type){
+ * if(type == 'beforegetcontent'){
+ * //do something
+ * }else{
+ * //do something
+ * }
+ * console.log(this.getContent) // this是注册的事件的编辑器实例
+ * })
+ * ```
+ * @see UE.EventBase:fireEvent(String)
+ */
+ addListener: function(types, listener) {
+ types = utils.trim(types).split(/\s+/);
+ for (var i = 0, ti; (ti = types[i++]); ) {
+ getListener(this, ti, true).push(listener);
+ }
+ },
+
+ on: function(types, listener) {
+ return this.addListener(types, listener);
+ },
+ off: function(types, listener) {
+ return this.removeListener(types, listener);
+ },
+ trigger: function() {
+ return this.fireEvent.apply(this, arguments);
+ },
+ /**
+ * 移除事件监听器
+ * @method removeListener
+ * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔
+ * @param { Function } fn 移除监听事件的函数引用
+ * @example
+ * ```javascript
+ * //changeCallback为方法体
+ * editor.removeListener("selectionchange",changeCallback);
+ * ```
+ */
+ removeListener: function(types, listener) {
+ types = utils.trim(types).split(/\s+/);
+ for (var i = 0, ti; (ti = types[i++]); ) {
+ utils.removeItem(getListener(this, ti) || [], listener);
+ }
+ },
+
+ /**
+ * 触发事件
+ * @method fireEvent
+ * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔
+ * @remind 该方法会触发addListener
+ * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值
+ * @example
+ * ```javascript
+ * editor.fireEvent("selectionchange");
+ * ```
+ */
+
+ /**
+ * 触发事件
+ * @method fireEvent
+ * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔
+ * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数
+ * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值
+ * @example
+ * ```javascript
+ *
+ * editor.addListener( "selectionchange", function ( type, arg1, arg2 ) {
+ *
+ * console.log( arg1 + " " + arg2 );
+ *
+ * } );
+ *
+ * //触发selectionchange事件, 会执行上面的事件监听器
+ * //output: Hello World
+ * editor.fireEvent("selectionchange", "Hello", "World");
+ * ```
+ */
+ fireEvent: function() {
+ var types = arguments[0];
+ types = utils.trim(types).split(" ");
+ for (var i = 0, ti; (ti = types[i++]); ) {
+ var listeners = getListener(this, ti),
+ r,
+ t,
+ k;
+ if (listeners) {
+ k = listeners.length;
+ while (k--) {
+ if (!listeners[k]) continue;
+ t = listeners[k].apply(this, arguments);
+ if (t === true) {
+ return t;
+ }
+ if (t !== undefined) {
+ r = t;
+ }
+ }
+ }
+ if ((t = this["on" + ti.toLowerCase()])) {
+ r = t.apply(this, arguments);
+ }
+ }
+ return r;
+ }
+};
+/**
+ * 获得对象所拥有监听类型的所有监听器
+ * @unfile
+ * @module UE
+ * @since 1.2.6.1
+ * @method getListener
+ * @public
+ * @param { Object } obj 查询监听器的对象
+ * @param { String } type 事件类型
+ * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组
+ * @return { Array } 监听器数组
+ */
+function getListener(obj, type, force) {
+ var allListeners;
+ type = type.toLowerCase();
+ return (
+ (allListeners =
+ obj.__allListeners || (force && (obj.__allListeners = {}))) &&
+ (allListeners[type] || (force && (allListeners[type] = [])))
+ );
+}
diff --git a/_src/core/Range.js b/_src/core/Range.js
index 05835b423..e2d17b630 100644
--- a/_src/core/Range.js
+++ b/_src/core/Range.js
@@ -1,1851 +1,1982 @@
-/**
- * Range封装
- * @file
- * @module UE.dom
- * @class Range
- * @since 1.2.6.1
- */
-
-/**
- * dom操作封装
- * @unfile
- * @module UE.dom
- */
-
-/**
- * Range实现类,本类是UEditor底层核心类,封装不同浏览器之间的Range操作。
- * @unfile
- * @module UE.dom
- * @class Range
- */
-
-
-(function () {
- var guid = 0,
- fillChar = domUtils.fillChar,
- fillData;
-
- /**
- * 更新range的collapse状态
- * @param {Range} range range对象
- */
- function updateCollapse(range) {
- range.collapsed =
- range.startContainer && range.endContainer &&
- range.startContainer === range.endContainer &&
- range.startOffset == range.endOffset;
- }
-
- function selectOneNode(rng){
- return !rng.collapsed && rng.startContainer.nodeType == 1 && rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset == 1
- }
- function setEndPoint(toStart, node, offset, range) {
- //如果node是自闭合标签要处理
- if (node.nodeType == 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) {
- offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1);
- node = node.parentNode;
- }
- if (toStart) {
- range.startContainer = node;
- range.startOffset = offset;
- if (!range.endContainer) {
- range.collapse(true);
- }
- } else {
- range.endContainer = node;
- range.endOffset = offset;
- if (!range.startContainer) {
- range.collapse(false);
- }
- }
- updateCollapse(range);
- return range;
- }
-
- function execContentsAction(range, action) {
- //调整边界
- //range.includeBookmark();
- var start = range.startContainer,
- end = range.endContainer,
- startOffset = range.startOffset,
- endOffset = range.endOffset,
- doc = range.document,
- frag = doc.createDocumentFragment(),
- tmpStart, tmpEnd;
- if (start.nodeType == 1) {
- start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode('')));
- }
- if (end.nodeType == 1) {
- end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode('')));
- }
- if (start === end && start.nodeType == 3) {
- frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset)));
- //is not clone
- if (action) {
- start.deleteData(startOffset, endOffset - startOffset);
- range.collapse(true);
- }
- return frag;
- }
- var current, currentLevel, clone = frag,
- startParents = domUtils.findParents(start, true), endParents = domUtils.findParents(end, true);
- for (var i = 0; startParents[i] == endParents[i];) {
- i++;
- }
- for (var j = i, si; si = startParents[j]; j++) {
- current = si.nextSibling;
- if (si == start) {
- if (!tmpStart) {
- if (range.startContainer.nodeType == 3) {
- clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset)));
- //is not clone
- if (action) {
- start.deleteData(startOffset, start.nodeValue.length - startOffset);
- }
- } else {
- clone.appendChild(!action ? start.cloneNode(true) : start);
- }
- }
- } else {
- currentLevel = si.cloneNode(false);
- clone.appendChild(currentLevel);
- }
- while (current) {
- if (current === end || current === endParents[j]) {
- break;
- }
- si = current.nextSibling;
- clone.appendChild(!action ? current.cloneNode(true) : current);
- current = si;
- }
- clone = currentLevel;
- }
- clone = frag;
- if (!startParents[i]) {
- clone.appendChild(startParents[i - 1].cloneNode(false));
- clone = clone.firstChild;
- }
- for (var j = i, ei; ei = endParents[j]; j++) {
- current = ei.previousSibling;
- if (ei == end) {
- if (!tmpEnd && range.endContainer.nodeType == 3) {
- clone.appendChild(doc.createTextNode(end.substringData(0, endOffset)));
- //is not clone
- if (action) {
- end.deleteData(0, endOffset);
- }
- }
- } else {
- currentLevel = ei.cloneNode(false);
- clone.appendChild(currentLevel);
- }
- //如果两端同级,右边第一次已经被开始做了
- if (j != i || !startParents[i]) {
- while (current) {
- if (current === start) {
- break;
- }
- ei = current.previousSibling;
- clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild);
- current = ei;
- }
- }
- clone = currentLevel;
- }
- if (action) {
- range.setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i]).collapse(true);
- }
- tmpStart && domUtils.remove(tmpStart);
- tmpEnd && domUtils.remove(tmpEnd);
- return frag;
- }
-
- /**
- * 创建一个跟document绑定的空的Range实例
- * @constructor
- * @param { Document } document 新建的选区所属的文档对象
- */
-
- /**
- * @property { Node } startContainer 当前Range的开始边界的容器节点, 可以是一个元素节点或者是文本节点
- */
-
- /**
- * @property { Node } startOffset 当前Range的开始边界容器节点的偏移量, 如果是元素节点,
- * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符
- */
-
- /**
- * @property { Node } endContainer 当前Range的结束边界的容器节点, 可以是一个元素节点或者是文本节点
- */
-
- /**
- * @property { Node } endOffset 当前Range的结束边界容器节点的偏移量, 如果是元素节点,
- * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符
- */
-
- /**
- * @property { Boolean } collapsed 当前Range是否闭合
- * @default true
- * @remind Range是闭合的时候, startContainer === endContainer && startOffset === endOffset
- */
-
- /**
- * @property { Document } document 当前Range所属的Document对象
- * @remind 不同range的的document属性可以是不同的
- */
- var Range = dom.Range = function (document) {
- var me = this;
- me.startContainer =
- me.startOffset =
- me.endContainer =
- me.endOffset = null;
- me.document = document;
- me.collapsed = true;
- };
-
- /**
- * 删除fillData
- * @param doc
- * @param excludeNode
- */
- function removeFillData(doc, excludeNode) {
- try {
- if (fillData && domUtils.inDoc(fillData, doc)) {
- if (!fillData.nodeValue.replace(fillCharReg, '').length) {
- var tmpNode = fillData.parentNode;
- domUtils.remove(fillData);
- while (tmpNode && domUtils.isEmptyInlineElement(tmpNode) &&
- //safari的contains有bug
- (browser.safari ? !(domUtils.getPosition(tmpNode,excludeNode) & domUtils.POSITION_CONTAINS) : !tmpNode.contains(excludeNode))
- ) {
- fillData = tmpNode.parentNode;
- domUtils.remove(tmpNode);
- tmpNode = fillData;
- }
- } else {
- fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, '');
- }
- }
- } catch (e) {
- }
- }
-
- /**
- * @param node
- * @param dir
- */
- function mergeSibling(node, dir) {
- var tmpNode;
- node = node[dir];
- while (node && domUtils.isFillChar(node)) {
- tmpNode = node[dir];
- domUtils.remove(node);
- node = tmpNode;
- }
- }
-
- Range.prototype = {
-
- /**
- * 克隆选区的内容到一个DocumentFragment里
- * @method cloneContents
- * @return { DocumentFragment | NULL } 如果选区是闭合的将返回null, 否则, 返回包含所clone内容的DocumentFragment元素
- * @example
- * ```html
- *
- *
- * xx[xxx]x
- *
- *
- *
- * ```
- */
- cloneContents:function () {
- return this.collapsed ? null : execContentsAction(this, 0);
- },
-
- /**
- * 删除当前选区范围中的所有内容
- * @method deleteContents
- * @remind 执行完该操作后, 当前Range对象变成了闭合状态
- * @return { UE.dom.Range } 当前操作的Range对象
- * @example
- * ```html
- *
- *
- * xx[xxx]x
- *
- *
- *
- * ```
- */
- deleteContents:function () {
- var txt;
- if (!this.collapsed) {
- execContentsAction(this, 1);
- }
- if (browser.webkit) {
- txt = this.startContainer;
- if (txt.nodeType == 3 && !txt.nodeValue.length) {
- this.setStartBefore(txt).collapse(true);
- domUtils.remove(txt);
- }
- }
- return this;
- },
-
- /**
- * 将当前选区的内容提取到一个DocumentFragment里
- * @method extractContents
- * @remind 执行该操作后, 选区将变成闭合状态
- * @warning 执行该操作后, 原来选区所选中的内容将从dom树上剥离出来
- * @return { DocumentFragment } 返回包含所提取内容的DocumentFragment对象
- * @example
- * ```html
- *
- *
- * xx[xxx]x
- *
- *
- *
- */
- extractContents:function () {
- return this.collapsed ? null : execContentsAction(this, 2);
- },
-
- /**
- * 设置Range的开始容器节点和偏移量
- * @method setStart
- * @remind 如果给定的节点是元素节点,那么offset指的是其子元素中索引为offset的元素,
- * 如果是文本节点,那么offset指的是其文本内容的第offset个字符
- * @remind 如果提供的容器节点是一个不能包含子元素的节点, 则该选区的开始容器将被设置
- * 为该节点的父节点, 此时, 其距离开始容器的偏移量也变成了该节点在其父节点
- * 中的索引
- * @param { Node } node 将被设为当前选区开始边界容器的节点对象
- * @param { int } offset 选区的开始位置偏移量
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * xxxxxxxxxxxxx[xxx]
- *
- *
- * ```
- * @example
- * ```html
- *
- * xxx[xx]x
- *
- *
- * ```
- */
- setStart:function (node, offset) {
- return setEndPoint(true, node, offset, this);
- },
-
- /**
- * 设置Range的结束容器和偏移量
- * @method setEnd
- * @param { Node } node 作为当前选区结束边界容器的节点对象
- * @param { int } offset 结束边界的偏移量
- * @see UE.dom.Range:setStart(Node,int)
- * @return { UE.dom.Range } 当前range对象
- */
- setEnd:function (node, offset) {
- return setEndPoint(false, node, offset, this);
- },
-
- /**
- * 将Range开始位置设置到node节点之后
- * @method setStartAfter
- * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引+1
- * @param { Node } node 选区的开始边界将紧接着该节点之后
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * xxxxxxx[xxxx]
- *
- *
- * ```
- */
- setStartAfter:function (node) {
- return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1);
- },
-
- /**
- * 将Range开始位置设置到node节点之前
- * @method setStartBefore
- * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引
- * @param { Node } node 新的选区开始位置在该节点之前
- * @see UE.dom.Range:setStartAfter(Node)
- * @return { UE.dom.Range } 当前range对象
- */
- setStartBefore:function (node) {
- return this.setStart(node.parentNode, domUtils.getNodeIndex(node));
- },
-
- /**
- * 将Range结束位置设置到node节点之后
- * @method setEndAfter
- * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引+1
- * @param { Node } node 目标节点
- * @see UE.dom.Range:setStartAfter(Node)
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * [xxxxxxx]xxxx
- *
- *
- * ```
- */
- setEndAfter:function (node) {
- return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1);
- },
-
- /**
- * 将Range结束位置设置到node节点之前
- * @method setEndBefore
- * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引
- * @param { Node } node 目标节点
- * @see UE.dom.Range:setEndAfter(Node)
- * @return { UE.dom.Range } 当前range对象
- */
- setEndBefore:function (node) {
- return this.setEnd(node.parentNode, domUtils.getNodeIndex(node));
- },
-
- /**
- * 设置Range的开始位置到node节点内的第一个子节点之前
- * @method setStartAtFirst
- * @remind 选区的开始容器将变成给定的节点, 且偏移量为0
- * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。
- * @param { Node } node 目标节点
- * @see UE.dom.Range:setStartBefore(Node)
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * xxxxx[xx]xxxx
- *
- *
- * ```
- */
- setStartAtFirst:function (node) {
- return this.setStart(node, 0);
- },
-
- /**
- * 设置Range的开始位置到node节点内的最后一个节点之后
- * @method setStartAtLast
- * @remind 选区的开始容器将变成给定的节点, 且偏移量为该节点的子节点数
- * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。
- * @param { Node } node 目标节点
- * @see UE.dom.Range:setStartAtFirst(Node)
- * @return { UE.dom.Range } 当前range对象
- */
- setStartAtLast:function (node) {
- return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);
- },
-
- /**
- * 设置Range的结束位置到node节点内的第一个节点之前
- * @method setEndAtFirst
- * @param { Node } node 目标节点
- * @remind 选区的结束容器将变成给定的节点, 且偏移量为0
- * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。
- * @see UE.dom.Range:setStartAtFirst(Node)
- * @return { UE.dom.Range } 当前range对象
- */
- setEndAtFirst:function (node) {
- return this.setEnd(node, 0);
- },
-
- /**
- * 设置Range的结束位置到node节点内的最后一个节点之后
- * @method setEndAtLast
- * @param { Node } node 目标节点
- * @remind 选区的结束容器将变成给定的节点, 且偏移量为该节点的子节点数量
- * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。
- * @see UE.dom.Range:setStartAtFirst(Node)
- * @return { UE.dom.Range } 当前range对象
- */
- setEndAtLast:function (node) {
- return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);
- },
-
- /**
- * 选中给定节点
- * @method selectNode
- * @remind 此时, 选区的开始容器和结束容器都是该节点的父节点, 其startOffset是该节点在父节点中的位置索引,
- * 而endOffset为startOffset+1
- * @param { Node } node 需要选中的节点
- * @return { UE.dom.Range } 当前range对象,此时的range仅包含当前给定的节点对象
- * @example
- * ```html
- *
- * xxxxx[xx]xxxx
- *
- *
- * ```
- */
- selectNode:function (node) {
- return this.setStartBefore(node).setEndAfter(node);
- },
-
- /**
- * 选中给定节点内部的所有节点
- * @method selectNodeContents
- * @remind 此时, 选区的开始容器和结束容器都是该节点, 其startOffset为0,
- * 而endOffset是该节点的子节点数。
- * @param { Node } node 目标节点, 当前range将包含该节点内的所有节点
- * @return { UE.dom.Range } 当前range对象, 此时range仅包含给定节点的所有子节点
- * @example
- * ```html
- *
- * xxxxx[xx]xxxx
- *
- *
- * ```
- */
- selectNodeContents:function (node) {
- return this.setStart(node, 0).setEndAtLast(node);
- },
-
- /**
- * clone当前Range对象
- * @method cloneRange
- * @remind 返回的range是一个全新的range对象, 其内部所有属性与当前被clone的range相同。
- * @return { UE.dom.Range } 当前range对象的一个副本
- */
- cloneRange:function () {
- var me = this;
- return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset);
-
- },
-
- /**
- * 向当前选区的结束处闭合选区
- * @method collapse
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * xxxxx[xx]xxxx
- *
- *
- * ```
- */
-
- /**
- * 闭合当前选区,根据给定的toStart参数项决定是向当前选区开始处闭合还是向结束处闭合,
- * 如果toStart的值为true,则向开始位置闭合, 反之,向结束位置闭合。
- * @method collapse
- * @param { Boolean } toStart 是否向选区开始处闭合
- * @return { UE.dom.Range } 当前range对象,此时range对象处于闭合状态
- * @see UE.dom.Range:collapse()
- * @example
- * ```html
- *
- * xxxxx[xx]xxxx
- *
- *
- * ```
- */
- collapse:function (toStart) {
- var me = this;
- if (toStart) {
- me.endContainer = me.startContainer;
- me.endOffset = me.startOffset;
- } else {
- me.startContainer = me.endContainer;
- me.startOffset = me.endOffset;
- }
- me.collapsed = true;
- return me;
- },
-
- /**
- * 调整range的开始位置和结束位置,使其"收缩"到最小的位置
- * @method shrinkBoundary
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- * xxxx[xxxxx] => xxxx[xxxxx]
- * ```
- *
- * @example
- * ```html
- *
- * x[xx]xxx
- *
- *
- * ```
- *
- * @example
- * ```html
- * [xxxxxxxxxxx] => [xxxxxxxxxxx]
- * ```
- */
-
- /**
- * 调整range的开始位置和结束位置,使其"收缩"到最小的位置,
- * 如果ignoreEnd的值为true,则忽略对结束位置的调整
- * @method shrinkBoundary
- * @param { Boolean } ignoreEnd 是否忽略对结束位置的调整
- * @return { UE.dom.Range } 当前range对象
- * @see UE.dom.domUtils.Range:shrinkBoundary()
- */
- shrinkBoundary:function (ignoreEnd) {
- var me = this, child,
- collapsed = me.collapsed;
- function check(node){
- return node.nodeType == 1 && !domUtils.isBookmarkNode(node) && !dtd.$empty[node.tagName] && !dtd.$nonChild[node.tagName]
- }
- while (me.startContainer.nodeType == 1 //是element
- && (child = me.startContainer.childNodes[me.startOffset]) //子节点也是element
- && check(child)) {
- me.setStart(child, 0);
- }
- if (collapsed) {
- return me.collapse(true);
- }
- if (!ignoreEnd) {
- while (me.endContainer.nodeType == 1//是element
- && me.endOffset > 0 //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错
- && (child = me.endContainer.childNodes[me.endOffset - 1]) //子节点也是element
- && check(child)) {
- me.setEnd(child, child.childNodes.length);
- }
- }
- return me;
- },
-
- /**
- * 获取离当前选区内包含的所有节点最近的公共祖先节点,
- * @method getCommonAncestor
- * @remind 返回的公共祖先节点一定不是range自身的容器节点, 但有可能是一个文本节点
- * @return { Node } 当前range对象内所有节点的公共祖先节点
- * @example
- * ```html
- * //选区示例
- * xxxx[xxx]xxxxxx
- *
- * ```
- */
-
- /**
- * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到
- * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf
- * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点
- * @method getCommonAncestor
- * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点
- * @return { Node } 当前range对象内所有节点的公共祖先节点
- * @see UE.dom.Range:getCommonAncestor()
- * @example
- * ```html
- *
- *
- *
- * xxxxxxxxx[xxx]xxxxxxxx
- *
- *
- *
- *
- * ```
- */
-
- /**
- * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到
- * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf
- * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点; 同时可以根据
- * ignoreTextNode 参数的取值决定是否忽略类型为文本节点的祖先节点。
- * @method getCommonAncestor
- * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点
- * @param { Boolean } ignoreTextNode 获取祖先节点的过程中是否忽略类型为文本节点的祖先节点
- * @return { Node } 当前range对象内所有节点的公共祖先节点
- * @see UE.dom.Range:getCommonAncestor()
- * @see UE.dom.Range:getCommonAncestor(Boolean)
- * @example
- * ```html
- *
- *
- *
- * xxxxxxxx[x]xxxxxxxxxxx
- *
- *
- *
- *
- * ```
- */
- getCommonAncestor:function (includeSelf, ignoreTextNode) {
- var me = this,
- start = me.startContainer,
- end = me.endContainer;
- if (start === end) {
- if (includeSelf && selectOneNode(this)) {
- start = start.childNodes[me.startOffset];
- if(start.nodeType == 1)
- return start;
- }
- //只有在上来就相等的情况下才会出现是文本的情况
- return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start;
- }
- return domUtils.getCommonAncestor(start, end);
- },
-
- /**
- * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上
- * @method trimBoundary
- * @remind 该操作有可能会引起文本节点被切开
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * //选区示例
- * xxx[xxxxx]xxx
- *
- *
- * ```
- */
-
- /**
- * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上,
- * 可以根据 ignoreEnd 参数的值决定是否调整对结束边界的调整
- * @method trimBoundary
- * @param { Boolean } ignoreEnd 是否忽略对结束边界的调整
- * @return { UE.dom.Range } 当前range对象
- * @example
- * ```html
- *
- * //选区示例
- * xxx[xxxxx]xxx
- *
- *
- * ```
- */
- trimBoundary:function (ignoreEnd) {
- this.txtToElmBoundary();
- var start = this.startContainer,
- offset = this.startOffset,
- collapsed = this.collapsed,
- end = this.endContainer;
- if (start.nodeType == 3) {
- if (offset == 0) {
- this.setStartBefore(start);
- } else {
- if (offset >= start.nodeValue.length) {
- this.setStartAfter(start);
- } else {
- var textNode = domUtils.split(start, offset);
- //跟新结束边界
- if (start === end) {
- this.setEnd(textNode, this.endOffset - offset);
- } else if (start.parentNode === end) {
- this.endOffset += 1;
- }
- this.setStartBefore(textNode);
- }
- }
- if (collapsed) {
- return this.collapse(true);
- }
- }
- if (!ignoreEnd) {
- offset = this.endOffset;
- end = this.endContainer;
- if (end.nodeType == 3) {
- if (offset == 0) {
- this.setEndBefore(end);
- } else {
- offset < end.nodeValue.length && domUtils.split(end, offset);
- this.setEndAfter(end);
- }
- }
- }
- return this;
- },
-
- /**
- * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则什么也不做
- * @method txtToElmBoundary
- * @remind 该操作不会修改dom节点
- * @return { UE.dom.Range } 当前range对象
- */
-
- /**
- * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则根据参数项
- * ignoreCollapsed 的值决定是否执行该调整
- * @method txtToElmBoundary
- * @param { Boolean } ignoreCollapsed 是否忽略选区的闭合状态, 如果该参数取值为true, 则
- * 不论选区是否闭合, 都会执行该操作, 反之, 则不会对闭合的选区执行该操作
- * @return { UE.dom.Range } 当前range对象
- */
- txtToElmBoundary:function (ignoreCollapsed) {
- function adjust(r, c) {
- var container = r[c + 'Container'],
- offset = r[c + 'Offset'];
- if (container.nodeType == 3) {
- if (!offset) {
- r['set' + c.replace(/(\w)/, function (a) {
- return a.toUpperCase();
- }) + 'Before'](container);
- } else if (offset >= container.nodeValue.length) {
- r['set' + c.replace(/(\w)/, function (a) {
- return a.toUpperCase();
- }) + 'After' ](container);
- }
- }
- }
-
- if (ignoreCollapsed || !this.collapsed) {
- adjust(this, 'start');
- adjust(this, 'end');
- }
- return this;
- },
-
- /**
- * 在当前选区的开始位置前插入节点,新插入的节点会被该range包含
- * @method insertNode
- * @param { Node } node 需要插入的节点
- * @remind 插入的节点可以是一个DocumentFragment依次插入多个节点
- * @return { UE.dom.Range } 当前range对象
- */
- insertNode:function (node) {
- var first = node, length = 1;
- if (node.nodeType == 11) {
- first = node.firstChild;
- length = node.childNodes.length;
- }
- this.trimBoundary(true);
- var start = this.startContainer,
- offset = this.startOffset;
- var nextNode = start.childNodes[ offset ];
- if (nextNode) {
- start.insertBefore(node, nextNode);
- } else {
- start.appendChild(node);
- }
- if (first.parentNode === this.endContainer) {
- this.endOffset = this.endOffset + length;
- }
- return this.setStartBefore(first);
- },
-
- /**
- * 闭合选区到当前选区的开始位置, 并且定位光标到闭合后的位置
- * @method setCursor
- * @return { UE.dom.Range } 当前range对象
- * @see UE.dom.Range:collapse()
- */
-
- /**
- * 闭合选区,可以根据参数toEnd的值控制选区是向前闭合还是向后闭合, 并且定位光标到闭合后的位置。
- * @method setCursor
- * @param { Boolean } toEnd 是否向后闭合, 如果为true, 则闭合选区时, 将向结束容器方向闭合,
- * 反之,则向开始容器方向闭合
- * @return { UE.dom.Range } 当前range对象
- * @see UE.dom.Range:collapse(Boolean)
- */
- setCursor:function (toEnd, noFillData) {
- return this.collapse(!toEnd).select(noFillData);
- },
-
- /**
- * 创建当前range的一个书签,记录下当前range的位置,方便当dom树改变时,还能找回原来的选区位置
- * @method createBookmark
- * @param { Boolean } serialize 控制返回的标记位置是对当前位置的引用还是ID,如果该值为true,则
- * 返回标记位置的ID, 反之则返回标记位置节点的引用
- * @return { Object } 返回一个书签记录键值对, 其包含的key有: start => 开始标记的ID或者引用,
- * end => 结束标记的ID或引用, id => 当前标记的类型, 如果为true,则表示
- * 返回的记录的类型为ID, 反之则为引用
- */
- createBookmark:function (serialize, same) {
- var endNode,
- startNode = this.document.createElement('span');
- startNode.style.cssText = 'display:none;line-height:0px;';
- startNode.appendChild(this.document.createTextNode('\u200D'));
- startNode.id = '_baidu_bookmark_start_' + (same ? '' : guid++);
-
- if (!this.collapsed) {
- endNode = startNode.cloneNode(true);
- endNode.id = '_baidu_bookmark_end_' + (same ? '' : guid++);
- }
- this.insertNode(startNode);
- if (endNode) {
- this.collapse().insertNode(endNode).setEndBefore(endNode);
- }
- this.setStartAfter(startNode);
- return {
- start:serialize ? startNode.id : startNode,
- end:endNode ? serialize ? endNode.id : endNode : null,
- id:serialize
- }
- },
-
- /**
- * 调整当前range的边界到书签位置,并删除该书签对象所标记的位置内的节点
- * @method moveToBookmark
- * @param { BookMark } bookmark createBookmark所创建的标签对象
- * @return { UE.dom.Range } 当前range对象
- * @see UE.dom.Range:createBookmark(Boolean)
- */
- moveToBookmark:function (bookmark) {
- var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,
- end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
- this.setStartBefore(start);
- domUtils.remove(start);
- if (end) {
- this.setEndBefore(end);
- domUtils.remove(end);
- } else {
- this.collapse(true);
- }
- return this;
- },
-
- /**
- * 调整range的边界,使其"放大"到最近的父节点
- * @method enlarge
- * @remind 会引起选区的变化
- * @return { UE.dom.Range } 当前range对象
- */
-
- /**
- * 调整range的边界,使其"放大"到最近的父节点,根据参数 toBlock 的取值, 可以
- * 要求扩大之后的父节点是block节点
- * @method enlarge
- * @param { Boolean } toBlock 是否要求扩大之后的父节点必须是block节点
- * @return { UE.dom.Range } 当前range对象
- */
- enlarge:function (toBlock, stopFn) {
- var isBody = domUtils.isBody,
- pre, node, tmp = this.document.createTextNode('');
- if (toBlock) {
- node = this.startContainer;
- if (node.nodeType == 1) {
- if (node.childNodes[this.startOffset]) {
- pre = node = node.childNodes[this.startOffset]
- } else {
- node.appendChild(tmp);
- pre = node = tmp;
- }
- } else {
- pre = node;
- }
- while (1) {
- if (domUtils.isBlockElm(node)) {
- node = pre;
- while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) {
- node = pre;
- }
- this.setStartBefore(node);
- break;
- }
- pre = node;
- node = node.parentNode;
- }
- node = this.endContainer;
- if (node.nodeType == 1) {
- if (pre = node.childNodes[this.endOffset]) {
- node.insertBefore(tmp, pre);
- } else {
- node.appendChild(tmp);
- }
- pre = node = tmp;
- } else {
- pre = node;
- }
- while (1) {
- if (domUtils.isBlockElm(node)) {
- node = pre;
- while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) {
- node = pre;
- }
- this.setEndAfter(node);
- break;
- }
- pre = node;
- node = node.parentNode;
- }
- if (tmp.parentNode === this.endContainer) {
- this.endOffset--;
- }
- domUtils.remove(tmp);
- }
-
- // 扩展边界到最大
- if (!this.collapsed) {
- while (this.startOffset == 0) {
- if (stopFn && stopFn(this.startContainer)) {
- break;
- }
- if (isBody(this.startContainer)) {
- break;
- }
- this.setStartBefore(this.startContainer);
- }
- while (this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)) {
- if (stopFn && stopFn(this.endContainer)) {
- break;
- }
- if (isBody(this.endContainer)) {
- break;
- }
- this.setEndAfter(this.endContainer);
- }
- }
- return this;
- },
- enlargeToBlockElm:function(ignoreEnd){
- while(!domUtils.isBlockElm(this.startContainer)){
- this.setStartBefore(this.startContainer);
- }
- if(!ignoreEnd){
- while(!domUtils.isBlockElm(this.endContainer)){
- this.setEndAfter(this.endContainer);
- }
- }
- return this;
- },
- /**
- * 调整Range的边界,使其"缩小"到最合适的位置
- * @method adjustmentBoundary
- * @return { UE.dom.Range } 当前range对象
- * @see UE.dom.Range:shrinkBoundary()
- */
- adjustmentBoundary:function () {
- if (!this.collapsed) {
- while (!domUtils.isBody(this.startContainer) &&
- this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length &&
- this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
- ) {
-
- this.setStartAfter(this.startContainer);
- }
- while (!domUtils.isBody(this.endContainer) && !this.endOffset &&
- this.endContainer[this.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
- ) {
- this.setEndBefore(this.endContainer);
- }
- }
- return this;
- },
-
- /**
- * 给range选区中的内容添加给定的inline标签
- * @method applyInlineStyle
- * @param { String } tagName 需要添加的标签名
- * @example
- * ```html
- * xxxx[xxxx]x ==> range.applyInlineStyle("strong") ==> xxxx[xxxx]x
- * ```
- */
-
- /**
- * 给range选区中的内容添加给定的inline标签, 并且为标签附加上一些初始化属性。
- * @method applyInlineStyle
- * @param { String } tagName 需要添加的标签名
- * @param { Object } attrs 跟随新添加的标签的属性
- * @return { UE.dom.Range } 当前选区
- * @example
- * ```html
- * xxxx[xxxx]x
- *
- * ==>
- *
- *
- * range.applyInlineStyle("strong",{"style":"font-size:12px"})
- *
- * ==>
- *
- * xxxx[xxxx]x
- * ```
- */
- applyInlineStyle:function (tagName, attrs, list) {
- if (this.collapsed)return this;
- this.trimBoundary().enlarge(false,
- function (node) {
- return node.nodeType == 1 && domUtils.isBlockElm(node)
- }).adjustmentBoundary();
- var bookmark = this.createBookmark(),
- end = bookmark.end,
- filterFn = function (node) {
- return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);
- },
- current = domUtils.getNextDomNode(bookmark.start, false, filterFn),
- node,
- pre,
- range = this.cloneRange();
- while (current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) {
- if (current.nodeType == 3 || dtd[tagName][current.tagName]) {
- range.setStartBefore(current);
- node = current;
- while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) {
- pre = node;
- node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) {
- return dtd[tagName][parent.tagName];
- });
- }
- var frag = range.setEndAfter(pre).extractContents(), elm;
- if (list && list.length > 0) {
- var level, top;
- top = level = list[0].cloneNode(false);
- for (var i = 1, ci; ci = list[i++];) {
- level.appendChild(ci.cloneNode(false));
- level = level.firstChild;
- }
- elm = level;
- } else {
- elm = range.document.createElement(tagName);
- }
- if (attrs) {
- domUtils.setAttributes(elm, attrs);
- }
- elm.appendChild(frag);
- //针对嵌套span的全局样式指定,做容错处理
- if(elm.tagName == 'SPAN' && attrs && attrs.style){
- utils.each(elm.getElementsByTagName('span'),function(s){
- s.style.cssText = s.style.cssText + ';' + attrs.style;
- })
- }
- range.insertNode(list ? top : elm);
- //处理下滑线在a上的情况
- var aNode;
- if (tagName == 'span' && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, 'a', true))) {
- domUtils.setAttributes(aNode, attrs);
- domUtils.remove(elm, true);
- elm = aNode;
- } else {
- domUtils.mergeSibling(elm);
- domUtils.clearEmptySibling(elm);
- }
- //去除子节点相同的
- domUtils.mergeChild(elm, attrs);
- current = domUtils.getNextDomNode(elm, false, filterFn);
- domUtils.mergeToParent(elm);
- if (node === end) {
- break;
- }
- } else {
- current = domUtils.getNextDomNode(current, true, filterFn);
- }
- }
- return this.moveToBookmark(bookmark);
- },
-
- /**
- * 移除当前选区内指定的inline标签,但保留其中的内容
- * @method removeInlineStyle
- * @param { String } tagName 需要移除的标签名
- * @return { UE.dom.Range } 当前的range对象
- * @example
- * ```html
- * xx[xxxxyyyzz]z => range.removeInlineStyle(["em"]) => xx[xxxxyyyzz]z
- * ```
- */
-
- /**
- * 移除当前选区内指定的一组inline标签,但保留其中的内容
- * @method removeInlineStyle
- * @param { Array } tagNameArr 需要移除的标签名的数组
- * @return { UE.dom.Range } 当前的range对象
- * @see UE.dom.Range:removeInlineStyle(String)
- */
- removeInlineStyle:function (tagNames) {
- if (this.collapsed)return this;
- tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];
- this.shrinkBoundary().adjustmentBoundary();
- var start = this.startContainer, end = this.endContainer;
- while (1) {
- if (start.nodeType == 1) {
- if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) {
- break;
- }
- if (start.tagName.toLowerCase() == 'body') {
- start = null;
- break;
- }
- }
- start = start.parentNode;
- }
- while (1) {
- if (end.nodeType == 1) {
- if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) {
- break;
- }
- if (end.tagName.toLowerCase() == 'body') {
- end = null;
- break;
- }
- }
- end = end.parentNode;
- }
- var bookmark = this.createBookmark(),
- frag,
- tmpRange;
- if (start) {
- tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start);
- frag = tmpRange.extractContents();
- tmpRange.insertNode(frag);
- domUtils.clearEmptySibling(start, true);
- start.parentNode.insertBefore(bookmark.start, start);
- }
- if (end) {
- tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end);
- frag = tmpRange.extractContents();
- tmpRange.insertNode(frag);
- domUtils.clearEmptySibling(end, false, true);
- end.parentNode.insertBefore(bookmark.end, end.nextSibling);
- }
- var current = domUtils.getNextDomNode(bookmark.start, false, function (node) {
- return node.nodeType == 1;
- }), next;
- while (current && current !== bookmark.end) {
- next = domUtils.getNextDomNode(current, true, function (node) {
- return node.nodeType == 1;
- });
- if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) {
- domUtils.remove(current, true);
- }
- current = next;
- }
- return this.moveToBookmark(bookmark);
- },
-
- /**
- * 获取当前选中的自闭合的节点
- * @method getClosedNode
- * @return { Node | NULL } 如果当前选中的是自闭合节点, 则返回该节点, 否则返回NULL
- */
- getClosedNode:function () {
- var node;
- if (!this.collapsed) {
- var range = this.cloneRange().adjustmentBoundary().shrinkBoundary();
- if (selectOneNode(range)) {
- var child = range.startContainer.childNodes[range.startOffset];
- if (child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) {
- node = child;
- }
- }
- }
- return node;
- },
-
- /**
- * 在页面上高亮range所表示的选区
- * @method select
- * @return { UE.dom.Range } 返回当前Range对象
- */
- //这里不区分ie9以上,trace:3824
- select:browser.ie ? function (noFillData, textRange) {
- var nativeRange;
- if (!this.collapsed)
- this.shrinkBoundary();
- var node = this.getClosedNode();
- if (node && !textRange) {
- try {
- nativeRange = this.document.body.createControlRange();
- nativeRange.addElement(node);
- nativeRange.select();
- } catch (e) {}
- return this;
- }
- var bookmark = this.createBookmark(),
- start = bookmark.start,
- end;
- nativeRange = this.document.body.createTextRange();
- nativeRange.moveToElementText(start);
- nativeRange.moveStart('character', 1);
- if (!this.collapsed) {
- var nativeRangeEnd = this.document.body.createTextRange();
- end = bookmark.end;
- nativeRangeEnd.moveToElementText(end);
- nativeRange.setEndPoint('EndToEnd', nativeRangeEnd);
- } else {
- if (!noFillData && this.startContainer.nodeType != 3) {
- //使用|x固定住光标
- var tmpText = this.document.createTextNode(fillChar),
- tmp = this.document.createElement('span');
- tmp.appendChild(this.document.createTextNode(fillChar));
- start.parentNode.insertBefore(tmp, start);
- start.parentNode.insertBefore(tmpText, start);
- //当点b,i,u时,不能清除i上边的b
- removeFillData(this.document, tmpText);
- fillData = tmpText;
- mergeSibling(tmp, 'previousSibling');
- mergeSibling(start, 'nextSibling');
- nativeRange.moveStart('character', -1);
- nativeRange.collapse(true);
- }
- }
- this.moveToBookmark(bookmark);
- tmp && domUtils.remove(tmp);
- //IE在隐藏状态下不支持range操作,catch一下
- try {
- nativeRange.select();
- } catch (e) {
- }
- return this;
- } : function (notInsertFillData) {
- function checkOffset(rng){
-
- function check(node,offset,dir){
- if(node.nodeType == 3 && node.nodeValue.length < offset){
- rng[dir + 'Offset'] = node.nodeValue.length
- }
- }
- check(rng.startContainer,rng.startOffset,'start');
- check(rng.endContainer,rng.endOffset,'end');
- }
- var win = domUtils.getWindow(this.document),
- sel = win.getSelection(),
- txtNode;
- //FF下关闭自动长高时滚动条在关闭dialog时会跳
- //ff下如果不body.focus将不能定位闭合光标到编辑器内
- browser.gecko ? this.document.body.focus() : win.focus();
- if (sel) {
- sel.removeAllRanges();
- // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断
- // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR'
- if (this.collapsed && !notInsertFillData) {
-// //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点
-// if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) {
-// var tmp = this.document.createTextNode('');
-// this.insertNode(tmp).setStart(tmp, 0).collapse(true);
-// }
-//
- //处理光标落在文本节点的情况
- //处理以下的情况
- //|xxxx
- //xxxx|xxxx
- //xxxx|
- var start = this.startContainer,child = start;
- if(start.nodeType == 1){
- child = start.childNodes[this.startOffset];
-
- }
- if( !(start.nodeType == 3 && this.startOffset) &&
- (child ?
- (!child.previousSibling || child.previousSibling.nodeType != 3)
- :
- (!start.lastChild || start.lastChild.nodeType != 3)
- )
- ){
- txtNode = this.document.createTextNode(fillChar);
- //跟着前边走
- this.insertNode(txtNode);
- removeFillData(this.document, txtNode);
- mergeSibling(txtNode, 'previousSibling');
- mergeSibling(txtNode, 'nextSibling');
- fillData = txtNode;
- this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true);
- }
- }
- var nativeRange = this.document.createRange();
- if(this.collapsed && browser.opera && this.startContainer.nodeType == 1){
- var child = this.startContainer.childNodes[this.startOffset];
- if(!child){
- //往前靠拢
- child = this.startContainer.lastChild;
- if( child && domUtils.isBr(child)){
- this.setStartBefore(child).collapse(true);
- }
- }else{
- //向后靠拢
- while(child && domUtils.isBlockElm(child)){
- if(child.nodeType == 1 && child.childNodes[0]){
- child = child.childNodes[0]
- }else{
- break;
- }
- }
- child && this.setStartBefore(child).collapse(true)
- }
-
- }
- //是createAddress最后一位算的不准,现在这里进行微调
- checkOffset(this);
- nativeRange.setStart(this.startContainer, this.startOffset);
- nativeRange.setEnd(this.endContainer, this.endOffset);
- sel.addRange(nativeRange);
- }
- return this;
- },
-
- /**
- * 滚动到当前range开始的位置
- * @method scrollToView
- * @param { Window } win 当前range对象所属的window对象
- * @return { UE.dom.Range } 当前Range对象
- */
-
- /**
- * 滚动到距离当前range开始位置 offset 的位置处
- * @method scrollToView
- * @param { Window } win 当前range对象所属的window对象
- * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移
- * @return { UE.dom.Range } 当前Range对象
- */
- scrollToView:function (win, offset) {
- win = win ? window : domUtils.getWindow(this.document);
- var me = this,
- span = me.document.createElement('span');
- //trace:717
- span.innerHTML = ' ';
- me.cloneRange().insertNode(span);
- domUtils.scrollToView(span, win, offset);
- domUtils.remove(span);
- return me;
- },
-
- /**
- * 判断当前选区内容是否占位符
- * @private
- * @method inFillChar
- * @return { Boolean } 如果是占位符返回true,否则返回false
- */
- inFillChar : function(){
- var start = this.startContainer;
- if(this.collapsed && start.nodeType == 3
- && start.nodeValue.replace(new RegExp('^' + domUtils.fillChar),'').length + 1 == start.nodeValue.length
- ){
- return true;
- }
- return false;
- },
-
- /**
- * 保存
- * @method createAddress
- * @private
- * @return { Boolean } 返回开始和结束的位置
- * @example
- * ```html
- *
- *
- * aaaa
- *
- *
- * bbbb
- *
- *
- *
- *
- *
- *
- * ```
- */
- createAddress : function(ignoreEnd,ignoreTxt){
- var addr = {},me = this;
-
- function getAddress(isStart){
- var node = isStart ? me.startContainer : me.endContainer;
- var parents = domUtils.findParents(node,true,function(node){return !domUtils.isBody(node)}),
- addrs = [];
- for(var i = 0,ci;ci = parents[i++];){
- addrs.push(domUtils.getNodeIndex(ci,ignoreTxt));
- }
- var firstIndex = 0;
-
- if(ignoreTxt){
- if(node.nodeType == 3){
- var tmpNode = node.previousSibling;
- while(tmpNode && tmpNode.nodeType == 3){
- firstIndex += tmpNode.nodeValue.replace(fillCharReg,'').length;
- tmpNode = tmpNode.previousSibling;
- }
- firstIndex += (isStart ? me.startOffset : me.endOffset)// - (fillCharReg.test(node.nodeValue) ? 1 : 0 )
- }else{
- node = node.childNodes[ isStart ? me.startOffset : me.endOffset];
- if(node){
- firstIndex = domUtils.getNodeIndex(node,ignoreTxt);
- }else{
- node = isStart ? me.startContainer : me.endContainer;
- var first = node.firstChild;
- while(first){
- if(domUtils.isFillChar(first)){
- first = first.nextSibling;
- continue;
- }
- firstIndex++;
- if(first.nodeType == 3){
- while( first && first.nodeType == 3){
- first = first.nextSibling;
- }
- }else{
- first = first.nextSibling;
- }
- }
- }
- }
-
- }else{
- firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset
- }
- if(firstIndex < 0){
- firstIndex = 0;
- }
- addrs.push(firstIndex);
- return addrs;
- }
- addr.startAddress = getAddress(true);
- if(!ignoreEnd){
- addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress();
- }
- return addr;
- },
-
- /**
- * 保存
- * @method createAddress
- * @private
- * @return { Boolean } 返回开始和结束的位置
- * @example
- * ```html
- *
- *
- * aaaa
- *
- *
- * bbbb
- *
- *
- *
- *
- *
- *
- * ```
- */
- moveToAddress : function(addr,ignoreEnd){
- var me = this;
- function getNode(address,isStart){
- var tmpNode = me.document.body,
- parentNode,offset;
- for(var i= 0,ci,l=address.length;i
- *
- *
- *
- *
- *
- * |
- *
- *
- *
- *
- *
- *
+ *
+ * xx[xxx]x
+ *
+ *
+ *
+ *
+ * xx[xxx]x
+ *
+ *
+ *
+ *
+ * xx[xxx]x
+ *
+ *
+ *
+ *
+ *
+ * xxxxxxxxx[xxx]xxxxxxxx
+ *
+ *
+ *
+ *
+ *
+ *
+ * xxxxxxxx[x]xxxxxxxxxxx
+ *
+ *
+ *
+ *