diff --git a/app/admin/config/admin.php b/app/admin/config/admin.php index 8061372..f0cc989 100644 --- a/app/admin/config/admin.php +++ b/app/admin/config/admin.php @@ -33,4 +33,10 @@ return [ 'cos' => '腾讯云cos', 'qnoss' => '七牛云' ], + + // 默认编辑器 + 'editor_types' => [ + 'ueditor' => '百度编辑器', + 'ckeditor' => 'CK编辑器', + ], ]; \ No newline at end of file diff --git a/app/admin/controller/Ajax.php b/app/admin/controller/Ajax.php index 967265b..506d0e6 100644 --- a/app/admin/controller/Ajax.php +++ b/app/admin/controller/Ajax.php @@ -6,7 +6,6 @@ use app\admin\model\SystemUploadfile; use app\admin\service\UploadService; use app\common\controller\AdminController; use app\common\service\MenuService; -use app\admin\service\upload\Uploadfile; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; @@ -128,4 +127,68 @@ class Ajax extends AdminController return json($data); } + /** + * @desc 百度编辑器上传 + * @return Json + */ + public function uploadUEditor(): Json + { + $this->isDemo && $this->error('演示环境下不允许修改'); + $uploadConfig = sysconfig('upload'); + $upload_allow_size = $uploadConfig['upload_allow_size']; + $_upload_allow_ext = explode(',', $uploadConfig['upload_allow_ext']); + $upload_allow_ext = []; + array_map(function ($value) use (&$upload_allow_ext) { + $upload_allow_ext[] = '.' . $value; + }, $_upload_allow_ext); + $config = [ + // 上传图片配置项 + "imageActionName" => "image", + "imageFieldName" => "file", + "imageMaxSize" => $upload_allow_size, + "imageAllowFiles" => $upload_allow_ext, + "imageCompressEnable" => true, + "imageCompressBorder" => 5000, + "imageInsertAlign" => "none", + "imageUrlPrefix" => "", + // 列出图片 + "imageManagerActionName" => "listImage", + "imageManagerListSize" => 20, + "imageManagerUrlPrefix" => "", + "imageManagerInsertAlign" => "none", + "imageManagerAllowFiles" => $upload_allow_ext, + ]; + $action = $this->request->param('action/s', ''); + $file = $this->request->file('file'); + $upload_type = $uploadConfig['upload_type']; + switch ($action) { + case 'image': + try { + $upload = UploadService::instance()->setConfig($uploadConfig)->$upload_type($file); + $code = $upload['code'] ?? 0; + if ($code == 0) { + return json(['state' => $upload['data'] ?? '上传错误信息']); + } else { + return json(['state' => 'SUCCESS', 'url' => $upload['data']['url'] ?? '']); + } + } catch (\Exception $e) { + return $this->error($e->getMessage()); + } + case 'listImage': + $res = (new SystemUploadfile())->order($this->sort)->limit(100)->column('url'); + $list = []; + array_map(function ($value) use (&$list) { + $list[] = ['url' => $value,]; + }, $res); + $result = [ + "state" => "SUCCESS", + "list" => $list, + "total" => 0, + "start" => 0, + ]; + return json($result); + default: + return json($config); + } + } } \ No newline at end of file diff --git a/app/admin/controller/system/Config.php b/app/admin/controller/system/Config.php index d42103e..50fef70 100644 --- a/app/admin/controller/system/Config.php +++ b/app/admin/controller/system/Config.php @@ -22,6 +22,7 @@ class Config extends AdminController parent::__construct($app); $this->model = new SystemConfig(); $this->assign('upload_types', config('admin.upload_types')); + $this->assign('editor_types', config('admin.editor_types')); } /** diff --git a/app/admin/view/layout/default.html b/app/admin/view/layout/default.html index 3976eb1..96621b0 100644 --- a/app/admin/view/layout/default.html +++ b/app/admin/view/layout/default.html @@ -21,6 +21,7 @@ IS_SUPER_ADMIN: "{$isSuperAdmin|default='false'}", VERSION: "{$version|default='1.0.0'}", CSRF_TOKEN: "{:token()}", + EDITOR_TYPE: "{:sysconfig('site','editor_type')?:'ueditor'}", }; diff --git a/app/admin/view/system/config/site.html b/app/admin/view/system/config/site.html index 9ad46ba..4a0c437 100644 --- a/app/admin/view/system/config/site.html +++ b/app/admin/view/system/config/site.html @@ -9,7 +9,7 @@
- +
@@ -43,6 +43,18 @@
+ +
+ +
+ {foreach $editor_types as $key=>$val} + + {/foreach} +
+ 默认百度编辑器。 +
+
+
diff --git a/public/static/config-admin.js b/public/static/config-admin.js index 6fc24d8..628f022 100644 --- a/public/static/config-admin.js +++ b/public/static/config-admin.js @@ -22,6 +22,11 @@ require.config({ "autocomplete": ["plugs/lay-module/autocomplete/autocomplete"], "vue": ["plugs/vue-2.6.10/vue.min"], "ckeditor": ["plugs/ckeditor4/ckeditor"], + "ueditor.config": ["plugs/ueditor/ueditor.config"], + "ueditor": ["plugs/ueditor/ueditor.all"], + "ueditor.zh-cn": ["plugs/ueditor/lang/zh-cn/zh-cn"], + "codemirror": ["plugs/ueditor/third-party/codemirror"], + "ZeroClipboard": ["plugs/ueditor/third-party/zeroclipboard/zeroclipboard"], } }); @@ -38,4 +43,8 @@ if ("undefined" != typeof CONFIG.AUTOLOAD_JS && CONFIG.AUTOLOAD_JS) { eval('Controller.' + CONFIG.ACTION + '()'); } }); -} \ No newline at end of file +} + +require(['ZeroClipboard', 'ueditor.config', 'ueditor'], function (ZeroClipboard) { + window['ZeroClipboard'] = ZeroClipboard; +}) \ No newline at end of file diff --git a/public/static/plugs/easy-admin/easy-admin.js b/public/static/plugs/easy-admin/easy-admin.js index 8e7432c..304f644 100644 --- a/public/static/plugs/easy-admin/easy-admin.js +++ b/public/static/plugs/easy-admin/easy-admin.js @@ -1303,19 +1303,26 @@ define(["jquery", "tableSelect", "ckeditor"], function ($, tableSelect, undefine var dataField = data.field; // 富文本数据处理 - var editorList = document.querySelectorAll(".editor"); - if (editorList.length > 0) { + if (window.CONFIG.EDITOR_TYPE == 'ueditor') { + var editorList = document.querySelectorAll("textarea.layui-textarea.editor"); $.each(editorList, function (i, v) { var name = $(this).attr("name"); - dataField[name] = CKEDITOR.instances[name].getData(); + dataField[name] = UE.getEditor(name + i).getContent(); }); - } + } else { + var editorList = document.querySelectorAll(".editor"); + if (editorList.length > 0) { + $.each(editorList, function (i, v) { + var name = $(this).attr("name"); + dataField[name] = CKEDITOR.instances[name].getData(); + }); + } + } if (typeof preposeCallback === 'function') { dataField = preposeCallback(dataField); } admin.api.form(url, dataField, ok, no, ex, refresh); - return false; }); }); @@ -1467,16 +1474,32 @@ define(["jquery", "tableSelect", "ckeditor"], function ($, tableSelect, undefine }, editor: function () { CKEDITOR.tools.setCookie('ckCsrfToken', init.csrf_token); - var editorList = document.querySelectorAll(".editor"); if (editorList.length > 0) { $.each(editorList, function (i, v) { - CKEDITOR.replace( - $(this).attr("name"), - { - height: $(this).height(), - filebrowserImageUploadUrl: admin.url('ajax/upload?type=editor'), - }); + if (window.CONFIG.EDITOR_TYPE == 'ueditor') { + var name = $(this).attr("name"); + $(this).parent().find('textarea').attr('id', name + i) + setTimeout(function () { + try { + UE.getEditor(name + i, { + initialFrameHeight: 420, + toolbars: [ + ["fullscreen", "source", "|", "undo", "redo", "|", "bold", "italic", "underline", "fontborder", "strikethrough", "superscript", "subscript", "removeformat", "formatmatch", "autotypeset", "blockquote", "pasteplain", "|", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist", "selectall", "cleardoc", "|", "rowspacingtop", "rowspacingbottom", "lineheight", "|", "customstyle", "paragraph", "fontfamily", "fontsize", "|", "directionalityltr", "directionalityrtl", "indent", "|", "justifyleft", "justifycenter", "justifyright", "justifyjustify", "|", "touppercase", "tolowercase", "|", "link", "unlink", "anchor", "|", "imagenone", "imageleft", "imageright", "imagecenter", "|", "insertimage", "emotion", "insertframe", "insertcode", "pagebreak", "template", "background", "formula", "|", "horizontal", "date", "time", "spechars", "wordimage", "|", "inserttable", "deletetable", "insertparagraphbeforetable", "insertrow", "deleterow", "insertcol", "deletecol", "mergecells", "mergeright", "mergedown", "splittocells", "splittorows", "splittocols", "|", "print", "preview", "searchreplace", "help",] + ], + }); + } catch (e) { + location.reload() + } + }, 200) + } else { + CKEDITOR.replace( + $(this).attr("name"), + { + height: $(this).height(), + filebrowserImageUploadUrl: admin.url('ajax/upload?type=editor'), + }); + } }); } }, diff --git a/public/static/plugs/ueditor/dialogs/anchor/anchor.html b/public/static/plugs/ueditor/dialogs/anchor/anchor.html new file mode 100644 index 0000000..01fe929 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/anchor/anchor.html @@ -0,0 +1,40 @@ + + + + + + + + +
+ +
+ + + + diff --git a/public/static/plugs/ueditor/dialogs/attachment/attachment.css b/public/static/plugs/ueditor/dialogs/attachment/attachment.css new file mode 100644 index 0000000..9c61716 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/attachment/attachment.css @@ -0,0 +1,681 @@ +@charset "utf-8"; +/* dialog样式 */ +.wrapper { + zoom: 1; + width: 630px; + *width: 626px; + height: 380px; + margin: 0 auto; + padding: 10px; + position: relative; + font-family: sans-serif; +} + +/*tab样式框大小*/ +.tabhead { + float:left; +} +.tabbody { + width: 100%; + height: 346px; + position: relative; + clear: both; +} + +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} + +.tabbody .panel.focus { + width: 100%; + height: 346px; + display: block; +} + +/* 上传附件 */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} + +.tabbody #upload.panel.focus { + width: 100%; + height: 346px; + display: block; + clip: auto; +} + +#upload .queueList { + margin: 0; + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 172px; + padding-top: 150px; + text-align: center; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *top: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 300px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 9px 0 0 9px; + *margin: 6px 0 0 6px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} +#upload .filelist li p.imgWrap.notimage { + margin-top: 0; + width: 111px; + height: 111px; + border: 1px #eeeeee solid; +} +#upload .filelist li p.imgWrap.notimage i.file-preview { + margin-top: 15px; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background-image: url(./images/success.gif) \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + + +/* 图片管理样式 */ +#online { + width: 100%; + height: 336px; + padding: 10px 0 0 0; +} +#online #fileList{ + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + position: relative; +} +#online ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#online li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 0 0 9px 9px; + *margin: 0 0 6px 6px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#online li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#online li img { + cursor: pointer; +} +#online li div.file-wrapper { + cursor: pointer; + position: absolute; + display: block; + width: 111px; + height: 111px; + border: 1px solid #eee; + background: url("./images/bg.png") repeat; +} +#online li div span.file-title{ + display: block; + padding: 0 3px; + margin: 3px 0 0 0; + font-size: 12px; + height: 15px; + color: #555555; + text-align: center; + width: 107px; + white-space: nowrap; + word-break: break-all; + overflow: hidden; + text-overflow: ellipsis; +} +#online li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#online li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#online li.selected .icon { + background-image: url(images/success.png); + background-image: url(images/success.gif) \9; + background-position: 75px 75px; +} +#online li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} + + +/* 在线文件的文件预览图标 */ +i.file-preview { + display: block; + margin: 10px auto; + width: 70px; + height: 70px; + background-image: url("./images/file-icons.png"); + background-image: url("./images/file-icons.gif") \9; + background-position: -140px center; + background-repeat: no-repeat; +} +i.file-preview.file-type-dir{ + background-position: 0 center; +} +i.file-preview.file-type-file{ + background-position: -140px center; +} +i.file-preview.file-type-filelist{ + background-position: -210px center; +} +i.file-preview.file-type-zip, +i.file-preview.file-type-rar, +i.file-preview.file-type-7z, +i.file-preview.file-type-tar, +i.file-preview.file-type-gz, +i.file-preview.file-type-bz2{ + background-position: -280px center; +} +i.file-preview.file-type-xls, +i.file-preview.file-type-xlsx{ + background-position: -350px center; +} +i.file-preview.file-type-doc, +i.file-preview.file-type-docx{ + background-position: -420px center; +} +i.file-preview.file-type-ppt, +i.file-preview.file-type-pptx{ + background-position: -490px center; +} +i.file-preview.file-type-vsd{ + background-position: -560px center; +} +i.file-preview.file-type-pdf{ + background-position: -630px center; +} +i.file-preview.file-type-txt, +i.file-preview.file-type-md, +i.file-preview.file-type-json, +i.file-preview.file-type-htm, +i.file-preview.file-type-xml, +i.file-preview.file-type-html, +i.file-preview.file-type-js, +i.file-preview.file-type-css, +i.file-preview.file-type-php, +i.file-preview.file-type-jsp, +i.file-preview.file-type-asp{ + background-position: -700px center; +} +i.file-preview.file-type-apk{ + background-position: -770px center; +} +i.file-preview.file-type-exe{ + background-position: -840px center; +} +i.file-preview.file-type-ipa{ + background-position: -910px center; +} +i.file-preview.file-type-mp4, +i.file-preview.file-type-swf, +i.file-preview.file-type-mkv, +i.file-preview.file-type-avi, +i.file-preview.file-type-flv, +i.file-preview.file-type-mov, +i.file-preview.file-type-mpg, +i.file-preview.file-type-mpeg, +i.file-preview.file-type-ogv, +i.file-preview.file-type-webm, +i.file-preview.file-type-rm, +i.file-preview.file-type-rmvb{ + background-position: -980px center; +} +i.file-preview.file-type-ogg, +i.file-preview.file-type-wav, +i.file-preview.file-type-wmv, +i.file-preview.file-type-mid, +i.file-preview.file-type-mp3{ + background-position: -1050px center; +} +i.file-preview.file-type-jpg, +i.file-preview.file-type-jpeg, +i.file-preview.file-type-gif, +i.file-preview.file-type-bmp, +i.file-preview.file-type-png, +i.file-preview.file-type-psd{ + background-position: -140px center; +} diff --git a/public/static/plugs/ueditor/dialogs/attachment/attachment.html b/public/static/plugs/ueditor/dialogs/attachment/attachment.html new file mode 100644 index 0000000..fa7a7a6 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/attachment/attachment.html @@ -0,0 +1,60 @@ + + + + + ueditor图片对话框 + + + + + + + + + + + + + + +
+
+ + +
+
+ +
+
+
+
+ 0% + +
+
+
+
+
+
+
+
+
+
+
+
    +
  • +
+
+
+ + +
+
+
+ +
+
+ + + + diff --git a/public/static/plugs/ueditor/dialogs/attachment/attachment.js b/public/static/plugs/ueditor/dialogs/attachment/attachment.js new file mode 100644 index 0000000..23048e5 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/attachment/attachment.js @@ -0,0 +1,766 @@ +/** + * User: Jinqn + * Date: 14-04-08 + * Time: 下午16:34 + * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片 + */ + +(function () { + + var uploadFile, + onlineFile; + + window.onload = function () { + initTabs(); + initButtons(); + }; + + /* 初始化tab标签 */ + function initTabs() { + var tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + setTabFocus(target.getAttribute('data-content-id')); + }); + } + + setTabFocus('upload'); + } + + /* 初始化tabbody */ + function setTabFocus(id) { + if(!id) return; + var i, bodyId, tabs = $G('tabhead').children; + for (i = 0; i < tabs.length; i++) { + bodyId = tabs[i].getAttribute('data-content-id') + if (bodyId == id) { + domUtils.addClass(tabs[i], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + } else { + domUtils.removeClasses(tabs[i], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + switch (id) { + case 'upload': + uploadFile = uploadFile || new UploadFile('queueList'); + break; + case 'online': + onlineFile = onlineFile || new OnlineFile('fileList'); + break; + } + } + + /* 初始化onok事件 */ + function initButtons() { + + dialog.onok = function () { + var list = [], id, tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + if (domUtils.hasClass(tabs[i], 'focus')) { + id = tabs[i].getAttribute('data-content-id'); + break; + } + } + + switch (id) { + case 'upload': + list = uploadFile.getInsertList(); + var count = uploadFile.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } + break; + case 'online': + list = onlineFile.getInsertList(); + break; + } + + editor.execCommand('insertfile', list); + }; + } + + + /* 上传附件 */ + function UploadFile(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadFile.prototype = { + init: function () { + this.fileList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')), + fileMaxSize = editor.getOpt('fileMaxSize'), + acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');; + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('fileActionName')) { + $('#filePickerReady').after($('
').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('fileFieldName'), + duplicate: true, + fileSingleSizeLimit: fileMaxSize, + compress: false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
  • ' + + '

    ' + file.name + '

    ' + + '

    ' + + '

    ' + + '
  • '), + + $btns = $('
    ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
    ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

    ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) { + $wrap.empty().addClass('notimage').append('' + + '' + file.name + ''); + } else { + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= fileMaxSize) { + fileCount++; + fileSize += file.size; + } + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= fileMaxSize) { + fileCount--; + fileSize -= file.size; + } + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + if (actionUrl.toLowerCase().indexOf('jsp') != -1) { + header['X_Requested_With'] = 'XMLHttpRequest'; + } + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + _this.fileList.push(json); + $file.append(''); + // 触发上传附件事件 + editor.fireEvent("uploadsuccess", { + res: json, + type: 'file' + }); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + getInsertList: function () { + var i, link, data, list = [], + prefix = editor.getOpt('fileUrlPrefix'); + for (i = 0; i < this.fileList.length; i++) { + data = this.fileList[i]; + link = data.url; + list.push({ + title: data.original || link.substr(link.lastIndexOf('/') + 1), + url: prefix + link + }); + } + return list; + } + }; + + + /* 在线附件 */ + function OnlineFile(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineFile.prototype = { + init: function () { + this.initContainer(); + this.initEvents(); + this.initData(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('fileList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getFileData(); + } + }); + /* 选中图片 */ + domUtils.on(this.list, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode; + + if (li.tagName.toLowerCase() == 'li') { + if (domUtils.hasClass(li, 'selected')) { + domUtils.removeClasses(li, 'selected'); + } else { + domUtils.addClass(li, 'selected'); + } + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('fileManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getFileData(); + }, + /* 向后台拉取图片列表数据 */ + getFileData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), { + timeout: 100000, + data: utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + headers: editor.options.serverHeaders || {}, + method: 'get', + onsuccess: function (r) { + try { + var json = eval('(' + r.responseText + ')'); + if (json.state == 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + onerror: function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, filetype, preview, icon, _this = this, + urlPrefix = editor.getOpt('fileManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + icon = document.createElement('span'); + filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1); + + if ( "png|jpg|jpeg|gif|bmp".indexOf(filetype) != -1 ) { + preview = document.createElement('img'); + domUtils.on(preview, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + }; + })(preview)); + preview.width = 113; + preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + } else { + var ic = document.createElement('i'), + textSpan = document.createElement('span'); + textSpan.innerHTML = list[i].original || list[i].url.substr(list[i].url.lastIndexOf('/') + 1); + preview = document.createElement('div'); + preview.appendChild(ic); + preview.appendChild(textSpan); + domUtils.addClass(preview, 'file-wrapper'); + domUtils.addClass(textSpan, 'file-title'); + domUtils.addClass(ic, 'file-type-' + filetype); + domUtils.addClass(ic, 'file-preview'); + } + domUtils.addClass(icon, 'icon'); + item.setAttribute('data-url', urlPrefix + list[i].url); + if (list[i].original) { + item.setAttribute('data-title', list[i].original); + } + + item.appendChild(preview); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = []; + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var url = lis[i].getAttribute('data-url'); + var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1); + list.push({ + title: title, + url: url + }); + } + } + return list; + } + }; + + +})(); diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.gif b/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.gif new file mode 100644 index 0000000..005a5ac Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.gif differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.png b/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.png new file mode 100644 index 0000000..4b6c444 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/alignicon.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/bg.png b/public/static/plugs/ueditor/dialogs/attachment/images/bg.png new file mode 100644 index 0000000..580be0a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.gif b/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.gif new file mode 100644 index 0000000..d8c02c2 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.png b/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.png new file mode 100644 index 0000000..3ff82c8 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/file-icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/icons.gif b/public/static/plugs/ueditor/dialogs/attachment/images/icons.gif new file mode 100644 index 0000000..78459de Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/icons.png b/public/static/plugs/ueditor/dialogs/attachment/images/icons.png new file mode 100644 index 0000000..12e4700 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/image.png b/public/static/plugs/ueditor/dialogs/attachment/images/image.png new file mode 100644 index 0000000..19699f6 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/image.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/progress.png b/public/static/plugs/ueditor/dialogs/attachment/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/progress.png differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/success.gif b/public/static/plugs/ueditor/dialogs/attachment/images/success.gif new file mode 100644 index 0000000..8d4f311 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/success.gif differ diff --git a/public/static/plugs/ueditor/dialogs/attachment/images/success.png b/public/static/plugs/ueditor/dialogs/attachment/images/success.png new file mode 100644 index 0000000..94f968d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/attachment/images/success.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/audio.css b/public/static/plugs/ueditor/dialogs/audio/audio.css new file mode 100644 index 0000000..eb0f251 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/audio/audio.css @@ -0,0 +1,650 @@ +@charset "utf-8"; +.wrapper{ width: 570px;_width:575px;margin: 10px auto; zoom:1;position: relative} +.tabbody{height: 355px;} +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} +.tabbody .panel.focus { + width: 100%; + height: 355px; + display: block; +} + +.tabbody .panel table td{vertical-align: middle;} +#audioUrl { + width: 380px; + height: 26px; + line-height: 26px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; + outline: none; + border-radius:3px; + padding:0 5px; +} +#audioSelect{ + width: 100px; + display: inline-block; + background: #FFF; + border: 1px solid #EEE; + line-height: 26px; + text-align: center; + color: #333; + text-decoration: none; + border-radius: 3px; + vertical-align: middle; +} +#audioSearchTxt{margin-left:15px;background: #FFF;width:200px;height:21px;line-height:21px;border: 1px solid #d7d7d7;} +#searchList{width: 570px;overflow: auto;zoom:1;height: 270px;} +#searchList div{float: left;width: 120px;height: 135px;margin: 5px 15px;} +#searchList img{margin: 2px 8px;cursor: pointer;border: 2px solid #fff} /*不用缩略图*/ +#searchList p{margin-left: 10px;} +#audioType{ + width: 65px; + height: 23px; + line-height: 22px; + border: 1px solid #d7d7d7; +} +#audioSearchBtn,#audioSearchReset{ + /*width: 80px;*/ + height: 25px; + line-height: 25px; + background: #eee; + border: 1px solid #d7d7d7; + cursor: pointer; + padding: 0 5px; +} + + + +#preview{position: relative;width: 420px;padding:0;overflow: hidden; margin-left: 10px; _margin-left:5px; height: 280px;background-color: #ddd;float: left} +#preview .previewMsg {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;background-color: #666;} +#preview .previewMsg span{display:block;margin: 125px auto 0 auto;text-align:center;font-size:18px;color:#fff;} +#preview .previewaudio {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;} +.edui-audio-wrapper fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} + +#audioInfo {width: 120px;float: left;margin-left: 10px;_margin-left:7px;} +fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} +fieldset legend{font-weight: bold;} +fieldset p{line-height: 30px;} +fieldset input.txt{ + width: 65px; + height: 21px; + line-height: 21px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; +} +label.url{font-weight: bold;margin-left: 5px;} +#audioFloat div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#audioFloat .focus{opacity: 1;filter: alpha(opacity = 100)} +span.view{display: inline-block;width: 30px;float: right;cursor: pointer;color: blue} + + + + +/* upload audio */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} +.tabbody #upload.panel.focus { + width: 100%; + height: 335px; + display: block; + clip: auto; +} +#upload_alignment div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#upload_alignment .focus{opacity: 1;filter: alpha(opacity = 100)} +#upload_left { width:427px; float:left; } +#upload_left .controller { height: 30px; clear: both; } +#uploadaudioInfo{margin-top:10px;float:right;padding-right:8px;} + +#upload .queueList { + margin: 0; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + margin-right:0; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 161px; + padding-top: 150px; + text-align: center; + width: 97%; + float: left; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *margin-left: 0; + *left: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 285px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 15px 0 0 20px; + *margin: 15px 0 0 15px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} +#upload .filelist li p.imgWrap.notimage { + margin-top: 0; + width: 111px; + height: 111px; + border: 1px #eeeeee solid; +} +#upload .filelist li p.imgWrap.notimage i.file-preview { + margin-top: 15px; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background-image: url(./images/success.gif) \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + +/* 在线文件的文件预览图标 */ +i.file-preview { + display: block; + margin: 10px auto; + width: 70px; + height: 70px; + background-image: url("./images/file-icons.png"); + background-image: url("./images/file-icons.gif") \9; + background-position: -140px center; + background-repeat: no-repeat; +} +i.file-preview.file-type-dir{ + background-position: 0 center; +} +i.file-preview.file-type-file{ + background-position: -140px center; +} +i.file-preview.file-type-filelist{ + background-position: -210px center; +} +i.file-preview.file-type-zip, +i.file-preview.file-type-rar, +i.file-preview.file-type-7z, +i.file-preview.file-type-tar, +i.file-preview.file-type-gz, +i.file-preview.file-type-bz2{ + background-position: -280px center; +} +i.file-preview.file-type-xls, +i.file-preview.file-type-xlsx{ + background-position: -350px center; +} +i.file-preview.file-type-doc, +i.file-preview.file-type-docx{ + background-position: -420px center; +} +i.file-preview.file-type-ppt, +i.file-preview.file-type-pptx{ + background-position: -490px center; +} +i.file-preview.file-type-vsd{ + background-position: -560px center; +} +i.file-preview.file-type-pdf{ + background-position: -630px center; +} +i.file-preview.file-type-txt, +i.file-preview.file-type-md, +i.file-preview.file-type-json, +i.file-preview.file-type-htm, +i.file-preview.file-type-xml, +i.file-preview.file-type-html, +i.file-preview.file-type-js, +i.file-preview.file-type-css, +i.file-preview.file-type-php, +i.file-preview.file-type-jsp, +i.file-preview.file-type-asp{ + background-position: -700px center; +} +i.file-preview.file-type-apk{ + background-position: -770px center; +} +i.file-preview.file-type-exe{ + background-position: -840px center; +} +i.file-preview.file-type-ipa{ + background-position: -910px center; +} +i.file-preview.file-type-mp4, +i.file-preview.file-type-swf, +i.file-preview.file-type-mkv, +i.file-preview.file-type-avi, +i.file-preview.file-type-flv, +i.file-preview.file-type-mov, +i.file-preview.file-type-mpg, +i.file-preview.file-type-mpeg, +i.file-preview.file-type-ogv, +i.file-preview.file-type-webm, +i.file-preview.file-type-rm, +i.file-preview.file-type-rmvb{ + background-position: -980px center; +} +i.file-preview.file-type-ogg, +i.file-preview.file-type-wav, +i.file-preview.file-type-wmv, +i.file-preview.file-type-mid, +i.file-preview.file-type-mp3{ + background-position: -1050px center; +} +i.file-preview.file-type-jpg, +i.file-preview.file-type-jpeg, +i.file-preview.file-type-gif, +i.file-preview.file-type-bmp, +i.file-preview.file-type-png, +i.file-preview.file-type-psd{ + background-position: -140px center; +} diff --git a/public/static/plugs/ueditor/dialogs/audio/audio.html b/public/static/plugs/ueditor/dialogs/audio/audio.html new file mode 100644 index 0000000..1b67abd --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/audio/audio.html @@ -0,0 +1,75 @@ + + + + + + + + + +
    +
    +
    + + +
    +
    +
    +
    +
    + 外链音频支持MP3格式 +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + 0% + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
      +
    • +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/dialogs/audio/audio.js b/public/static/plugs/ueditor/dialogs/audio/audio.js new file mode 100644 index 0000000..372b9eb --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/audio/audio.js @@ -0,0 +1,781 @@ +/** + * Created by JetBrains PhpStorm. + * User: taoqili + * Date: 12-2-20 + * Time: 上午11:19 + * To change this template use File | Settings | File Templates. + */ + +(function () { + + var audio = {}, + uploadaudioList = [], + isModifyUploadaudio = false, + uploadFile; + var editorOpt = {}; + + window.onload = function () { + editorOpt = editor.getOpt('audioConfig'); + $focus($G("audioUrl")); + initTabs(); + initAudio(); + initUpload(); + }; + + /* 初始化tab标签 */ + function initTabs() { + var tabs = $G('tabHeads').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var j, bodyId, target = e.target || e.srcElement; + for (j = 0; j < tabs.length; j++) { + bodyId = tabs[j].getAttribute('data-content-id'); + if (tabs[j] == target) { + domUtils.addClass(tabs[j], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + } else { + domUtils.removeClasses(tabs[j], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + }); + } + if (!editorOpt.disableUpload) { + $G('tabHeads').querySelector('[data-content-id="upload"]').style.display = 'inline-block'; + } + if (!!editorOpt.selectCallback) { + $G('audioSelect').style.display = 'inline-block'; + domUtils.on($G('audioSelect'), "click", function (e) { + editorOpt.selectCallback(editor, function (info) { + if (info) { + $G('audioUrl').value = info.path; + createPreview(info.path); + } + }); + }); + } + } + + function initAudio() { + createAlignButton(["audioFloat", "upload_alignment"]); + addUrlChangeListener($G("audioUrl")); + addOkListener(); + + //编辑视频时初始化相关信息 + (function () { + var img = editor.selection.getRange().getClosedNode(), url; + if (img && img.className) { + var hasFakedClass = (img.className == "edui-faked-audio"), + hasUploadClass = img.className.indexOf("edui-upload-audio") != -1; + if (hasFakedClass || hasUploadClass) { + $G("audioUrl").value = url = img.getAttribute("_url"); + var align = domUtils.getComputedStyle(img, "float"), + parentAlign = domUtils.getComputedStyle(img.parentNode, "text-align"); + updateAlignButton(parentAlign === "center" ? "center" : align); + } + if (hasUploadClass) { + isModifyUploadaudio = true; + } + } + createPreview(url); + })(); + } + + /** + * 监听确认和取消两个按钮事件,用户执行插入或者清空正在播放的视频实例操作 + */ + function addOkListener() { + dialog.onok = function () { + $G("preview").innerHTML = ""; + var currentTab = findFocus("tabHeads", "tabSrc"); + switch (currentTab) { + case "audio": + return insertSingle(); + break; + // case "audioSearch": + // return insertSearch("searchList"); + // break; + case "upload": + return insertUpload(); + break; + } + }; + dialog.oncancel = function () { + $G("preview").innerHTML = ""; + }; + } + + /** + * 依据传入的align值更新按钮信息 + * @param align + */ + function updateAlignButton(align) { + var aligns = $G("audioFloat").children; + for (var i = 0, ci; ci = aligns[i++];) { + if (ci.getAttribute("name") == align) { + if (ci.className != "focus") { + ci.className = "focus"; + } + } else { + if (ci.className == "focus") { + ci.className = ""; + } + } + } + } + + /** + * 将单个视频信息插入编辑器中 + */ + function insertSingle() { + var url = $G('audioUrl').value, + align = findFocus("audioFloat", "name"); + if (!url) return false; + editor.execCommand('insertaudio', { + url: url, + }, isModifyUploadaudio ? 'upload' : null); + } + + /** + * 将元素id下的所有代表视频的图片插入编辑器中 + * @param id + */ + function insertSearch(id) { + var imgs = domUtils.getElementsByTagName($G(id), "img"), + audioObjs = []; + for (var i = 0, img; img = imgs[i++];) { + if (img.getAttribute("selected")) { + audioObjs.push({ + url: img.getAttribute("ue_audio_url"), + width: 420, + height: 280, + align: "none" + }); + } + } + editor.execCommand('insertaudio', audioObjs); + } + + /** + * 找到id下具有focus类的节点并返回该节点下的某个属性 + * @param id + * @param returnProperty + */ + function findFocus(id, returnProperty) { + var tabs = $G(id).children, + property; + for (var i = 0, ci; ci = tabs[i++];) { + if (ci.className == "focus") { + property = ci.getAttribute(returnProperty); + break; + } + } + return property; + } + + /** + * 数字判断 + * @param value + */ + function isNumber(value) { + return /(0|^[1-9]\d*$)/.test(value); + } + + /** + * 创建图片浮动选择按钮 + * @param ids + */ + function createAlignButton(ids) { + for (var i = 0, ci; ci = ids[i++];) { + var floatContainer = $G(ci), + nameMaps = { + "none": lang['default'], + "left": lang.floatLeft, + "right": lang.floatRight, + "center": lang.block + }; + for (var j in nameMaps) { + var div = document.createElement("div"); + div.setAttribute("name", j); + if (j == "none") div.className = "focus"; + div.style.cssText = "background:url(images/" + j + "_focus.jpg);"; + div.setAttribute("title", nameMaps[j]); + floatContainer.appendChild(div); + } + switchSelect(ci); + } + } + + /** + * 选择切换 + * @param selectParentId + */ + function switchSelect(selectParentId) { + var selects = $G(selectParentId).children; + for (var i = 0, ci; ci = selects[i++];) { + domUtils.on(ci, "click", function () { + for (var j = 0, cj; cj = selects[j++];) { + cj.className = ""; + cj.removeAttribute && cj.removeAttribute("class"); + } + this.className = "focus"; + }) + } + } + + /** + * 监听url改变事件 + * @param url + */ + function addUrlChangeListener(url) { + if (browser.ie) { + url.onpropertychange = function () { + createPreview(this.value); + } + } else { + url.addEventListener("input", function () { + createPreview(this.value); + }, false); + } + } + + function createAudioHtml(url, param) { + param = param || {}; + var str = [ + "', + '', + '', + ]; + return str.join(''); + } + + /** + * 根据url生成视频预览 + * @param url + */ + function createPreview(url) { + if (!url) { + return; + } + + $G("preview").innerHTML = '
    ' + lang.urlError + '
    ' + + '
    ' + + '
    ' + createAudioHtml(url) + '
    ' + + '
    '; + } + + + /* 插入上传视频 */ + function insertUpload() { + var audioObjs = [], + uploadDir = editor.getOpt('audioUrlPrefix'), + align = findFocus("upload_alignment", "name") || 'none'; + for (var key in uploadaudioList) { + var file = uploadaudioList[key]; + audioObjs.push({ + url: uploadDir + file.url, + align: align + }); + } + + var count = uploadFile.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } else { + editor.execCommand('insertaudio', audioObjs, 'upload'); + } + } + + /*初始化上传标签*/ + function initUpload() { + uploadFile = new UploadFile('queueList'); + } + + + /* 上传附件 */ + function UploadFile(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + + UploadFile.prototype = { + init: function () { + this.fileList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('audioActionName')), + fileMaxSize = editor.getOpt('audioMaxSize'), + acceptExtensions = (editor.getOpt('audioAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, ''); + ; + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
    ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('audioActionName')) { + $('#filePickerReady').after($('
    ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('audioFieldName'), + duplicate: true, + fileSingleSizeLimit: fileMaxSize, + compress: false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
  • ' + + '

    ' + file.name + '

    ' + + '

    ' + + '

    ' + + '
  • '), + + $btns = $('
    ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
    ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

    ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|' + file.ext.toLowerCase() + '|') == -1) { + $wrap.empty().addClass('notimage').append('' + + '' + file.name + ''); + } else { + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src || (/^data:/.test(src) && browser.ie && browser.version <= 7)) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + } + percentages[file.id] = [file.size, 0]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[file.id][1] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[file.id][1] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[file.id]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[0]; + loaded += v[0] * v[1]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); + $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); + $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); + $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); + $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); + $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); + $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)).replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + fileCount--; + fileSize -= file.size; + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?' : '&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + if (actionUrl.toLowerCase().indexOf('jsp') != -1) { + header['X_Requested_With'] = 'XMLHttpRequest'; + } + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[file.id][1] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + uploadaudioList.push({ + 'url': json.url, + 'type': json.type, + 'original': json.original + }); + $file.append(''); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++];) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + refresh: function () { + this.uploader.refresh(); + } + }; + +})(); diff --git a/public/static/plugs/ueditor/dialogs/audio/images/bg.png b/public/static/plugs/ueditor/dialogs/audio/images/bg.png new file mode 100644 index 0000000..580be0a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/center_focus.jpg b/public/static/plugs/ueditor/dialogs/audio/images/center_focus.jpg new file mode 100644 index 0000000..262b029 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/center_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/file-icons.gif b/public/static/plugs/ueditor/dialogs/audio/images/file-icons.gif new file mode 100644 index 0000000..d8c02c2 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/file-icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/file-icons.png b/public/static/plugs/ueditor/dialogs/audio/images/file-icons.png new file mode 100644 index 0000000..3ff82c8 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/file-icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/icons.gif b/public/static/plugs/ueditor/dialogs/audio/images/icons.gif new file mode 100644 index 0000000..78459de Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/icons.png b/public/static/plugs/ueditor/dialogs/audio/images/icons.png new file mode 100644 index 0000000..12e4700 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/image.png b/public/static/plugs/ueditor/dialogs/audio/images/image.png new file mode 100644 index 0000000..19699f6 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/image.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/left_focus.jpg b/public/static/plugs/ueditor/dialogs/audio/images/left_focus.jpg new file mode 100644 index 0000000..7886d27 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/left_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/none_focus.jpg b/public/static/plugs/ueditor/dialogs/audio/images/none_focus.jpg new file mode 100644 index 0000000..7c768dc Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/none_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/progress.png b/public/static/plugs/ueditor/dialogs/audio/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/progress.png differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/right_focus.jpg b/public/static/plugs/ueditor/dialogs/audio/images/right_focus.jpg new file mode 100644 index 0000000..173e10d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/right_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/success.gif b/public/static/plugs/ueditor/dialogs/audio/images/success.gif new file mode 100644 index 0000000..8d4f311 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/success.gif differ diff --git a/public/static/plugs/ueditor/dialogs/audio/images/success.png b/public/static/plugs/ueditor/dialogs/audio/images/success.png new file mode 100644 index 0000000..94f968d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/audio/images/success.png differ diff --git a/public/static/plugs/ueditor/dialogs/background/background.css b/public/static/plugs/ueditor/dialogs/background/background.css new file mode 100644 index 0000000..5c41fe9 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/background/background.css @@ -0,0 +1,94 @@ +.wrapper{ width: 424px;margin: 10px auto; zoom:1;position: relative} +.tabbody{height:225px;} +.tabbody .panel { position: absolute;width:100%; height:100%;background: #fff; display: none;} +.tabbody .focus { display: block;} + +body{font-size: 12px;color: #888;overflow: hidden;} +input,label{vertical-align:middle} +.clear{clear: both;} +.pl{padding-left: 18px;padding-left: 23px\9;} + +#imageList {width: 420px;height: 215px;margin-top: 10px;overflow: hidden;overflow-y: auto;} +#imageList div {float: left;width: 100px;height: 95px;margin: 5px 10px;} +#imageList img {cursor: pointer;border: 2px solid white;} + +.bgarea{margin: 10px;padding: 5px;height: 84%;border: 1px solid #A8A297;} +.content div{margin: 10px 0 10px 5px;} +.content .iptradio{margin: 0px 5px 5px 0px;} +.txt{width:280px;} + +.wrapcolor{height: 19px;} +div.color{float: left;margin: 0;} +#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;margin: 0;float: left;} +div.alignment,#custom{margin-left: 23px;margin-left: 28px\9;} +#custom input{height: 15px;min-height: 15px;width:20px;} +#repeatType{width:100px;} + + +/* 图片管理样式 */ +#imgManager { + width: 100%; + height: 225px; +} +#imgManager #imageList{ + width: 100%; + overflow-x: hidden; + overflow-y: auto; +} +#imgManager ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#imgManager li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 9px 0 0 19px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#imgManager li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#imgManager li img { + cursor: pointer; +} +#imgManager li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#imgManager li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#imgManager li.selected .icon { + background-image: url(images/success.png); + background-position: 75px 75px; +} +#imgManager li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/background/background.html b/public/static/plugs/ueditor/dialogs/background/background.html new file mode 100644 index 0000000..e31e4d6 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/background/background.html @@ -0,0 +1,52 @@ + + + + + + + + +
    +
    + +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    + : +
    +
    +
    +
    +
    + +
    +
    + : +
    +
    + :x:px  y:px +
    +
    +
    + +
    +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/background/background.js b/public/static/plugs/ueditor/dialogs/background/background.js new file mode 100644 index 0000000..4914158 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/background/background.js @@ -0,0 +1,369 @@ +(function () { + + var onlineImage, + backupStyle = editor.queryCommandValue('background'); + + window.onload = function () { + initTabs(); + initColorSelector(); + }; + + /* 初始化tab标签 */ + function initTabs(){ + var tabs = $G('tabHeads').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + for (var j = 0; j < tabs.length; j++) { + if(tabs[j] == target){ + tabs[j].className = "focus"; + var contentId = tabs[j].getAttribute('data-content-id'); + $G(contentId).style.display = "block"; + }else { + tabs[j].className = ""; + $G(tabs[j].getAttribute('data-content-id')).style.display = "none"; + } + } + }); + } + } + + /* 初始化颜色设置 */ + function initColorSelector () { + var obj = editor.queryCommandValue('background'); + if (obj) { + var color = obj['background-color'], + repeat = obj['background-repeat'] || 'repeat', + image = obj['background-image'] || '', + position = obj['background-position'] || 'center center', + pos = position.split(' '), + x = parseInt(pos[0]) || 0, + y = parseInt(pos[1]) || 0; + + if(repeat == 'no-repeat' && (x || y)) repeat = 'self'; + + image = image.match(/url[\s]*\(([^\)]*)\)/); + image = image ? image[1]:''; + updateFormState('colored', color, image, repeat, x, y); + } else { + updateFormState(); + } + + var updateHandler = function () { + updateFormState(); + updateBackground(); + } + domUtils.on($G('nocolorRadio'), 'click', updateBackground); + domUtils.on($G('coloredRadio'), 'click', updateHandler); + domUtils.on($G('url'), 'keyup', function(){ + if($G('url').value && $G('alignment').style.display == "none") { + utils.each($G('repeatType').children, function(item){ + item.selected = ('repeat' == item.getAttribute('value') ? 'selected':false); + }); + } + updateHandler(); + }); + domUtils.on($G('repeatType'), 'change', updateHandler); + domUtils.on($G('x'), 'keyup', updateBackground); + domUtils.on($G('y'), 'keyup', updateBackground); + + initColorPicker(); + } + + /* 初始化颜色选择器 */ + function initColorPicker() { + var me = editor, + cp = $G("colorPicker"); + + /* 生成颜色选择器ui对象 */ + var popup = new UE.ui.Popup({ + content: new UE.ui.ColorPicker({ + noColorText: me.getLang("clearColor"), + editor: me, + onpickcolor: function (t, color) { + updateFormState('colored', color); + updateBackground(); + UE.ui.Popup.postHide(); + }, + onpicknocolor: function (t, color) { + updateFormState('colored', 'transparent'); + updateBackground(); + UE.ui.Popup.postHide(); + } + }), + editor: me, + onhide: function () { + } + }); + + /* 设置颜色选择器 */ + domUtils.on(cp, "click", function () { + popup.showAnchor(this); + }); + domUtils.on(document, 'mousedown', function (evt) { + var el = evt.target || evt.srcElement; + UE.ui.Popup.postHide(el); + }); + domUtils.on(window, 'scroll', function () { + UE.ui.Popup.postHide(); + }); + } + + /* 更新背景色设置面板 */ + function updateFormState (radio, color, url, align, x, y) { + var nocolorRadio = $G('nocolorRadio'), + coloredRadio = $G('coloredRadio'); + + if(radio) { + nocolorRadio.checked = (radio == 'colored' ? false:'checked'); + coloredRadio.checked = (radio == 'colored' ? 'checked':false); + } + if(color) { + domUtils.setStyle($G("colorPicker"), "background-color", color); + } + + if(url && /^\//.test(url)) { + var a = document.createElement('a'); + a.href = url; + browser.ie && (a.href = a.href); + url = browser.ie ? a.href:(a.protocol + '//' + a.host + a.pathname + a.search + a.hash); + } + + if(url || url === '') { + $G('url').value = url; + } + if(align) { + utils.each($G('repeatType').children, function(item){ + item.selected = (align == item.getAttribute('value') ? 'selected':false); + }); + } + if(x || y) { + $G('x').value = parseInt(x) || 0; + $G('y').value = parseInt(y) || 0; + } + + $G('alignment').style.display = coloredRadio.checked && $G('url').value ? '':'none'; + $G('custom').style.display = coloredRadio.checked && $G('url').value && $G('repeatType').value == 'self' ? '':'none'; + } + + /* 更新背景颜色 */ + function updateBackground () { + if ($G('coloredRadio').checked) { + var color = domUtils.getStyle($G("colorPicker"), "background-color"), + bgimg = $G("url").value, + align = $G("repeatType").value, + backgroundObj = { + "background-repeat": "no-repeat", + "background-position": "center center" + }; + + if (color) backgroundObj["background-color"] = color; + if (bgimg) backgroundObj["background-image"] = 'url(' + bgimg + ')'; + if (align == 'self') { + backgroundObj["background-position"] = $G("x").value + "px " + $G("y").value + "px"; + } else if (align == 'repeat-x' || align == 'repeat-y' || align == 'repeat') { + backgroundObj["background-repeat"] = align; + } + + editor.execCommand('background', backgroundObj); + } else { + editor.execCommand('background', null); + } + } + + + /* 在线图片 */ + function OnlineImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineImage.prototype = { + init: function () { + this.reset(); + this.initEvents(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.id = 'imageListUl'; + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('imageList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getImageData(); + } + }); + /* 选中图片 */ + domUtils.on(this.container, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode, + nodes = $G('imageListUl').childNodes; + + if (li.tagName.toLowerCase() == 'li') { + updateFormState('nocolor', null, ''); + for (var i = 0, node; node = nodes[i++];) { + if (node == li && !domUtils.hasClass(node, 'selected')) { + domUtils.addClass(node, 'selected'); + updateFormState('colored', null, li.firstChild.getAttribute("_src"), 'repeat'); + } else { + domUtils.removeClasses(node, 'selected'); + } + } + updateBackground(); + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('imageManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getImageData(); + }, + /* 重置界面 */ + reset: function() { + this.initContainer(); + this.initData(); + }, + /* 向后台拉取图片列表数据 */ + getImageData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')), + isJsonp = utils.isCrossDomainUrl(url); + ajax.request(url, { + 'timeout': 100000, + 'dataType': isJsonp ? 'jsonp':'', + 'data': utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + 'headers': editor.options.serverHeaders || {}, + 'method': 'get', + 'onsuccess': function (r) { + try { + var json = isJsonp ? r:eval('(' + r.responseText + ')'); + if (json.state == 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + 'onerror': function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, icon, _this = this, + urlPrefix = editor.getOpt('imageManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + img = document.createElement('img'); + icon = document.createElement('span'); + + domUtils.on(img, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + } + })(img)); + img.width = 113; + img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + img.setAttribute('_src', urlPrefix + list[i].url); + domUtils.addClass(icon, 'icon'); + + item.appendChild(img); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = [], align = getAlign(); + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var img = lis[i].firstChild, + src = img.getAttribute('_src'); + list.push({ + src: src, + _src: src, + floatStyle: align + }); + } + + } + return list; + } + }; + + dialog.onok = function () { + updateBackground(); + editor.fireEvent('saveScene'); + }; + dialog.oncancel = function () { + editor.execCommand('background', backupStyle); + }; + +})(); diff --git a/public/static/plugs/ueditor/dialogs/background/images/bg.png b/public/static/plugs/ueditor/dialogs/background/images/bg.png new file mode 100644 index 0000000..580be0a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/background/images/bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/background/images/success.png b/public/static/plugs/ueditor/dialogs/background/images/success.png new file mode 100644 index 0000000..94f968d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/background/images/success.png differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/emotion.css b/public/static/plugs/ueditor/dialogs/emotion/emotion.css new file mode 100644 index 0000000..f801105 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/emotion/emotion.css @@ -0,0 +1,43 @@ +.jd img{ + background:transparent url(images/jxface2.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.pp img{ + background:transparent url(images/fface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:25px;height:25px;display:block; +} +.ldw img{ + background:transparent url(images/wface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.tsj img{ + background:transparent url(images/tface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.cat img{ + background:transparent url(images/cface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.bb img{ + background:transparent url(images/bface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} +.youa img{ + background:transparent url(images/yface.gif?v=1.1) no-repeat scroll left top; + cursor:pointer;width:35px;height:35px;display:block; +} + +.smileytable td {height: 37px;} +#tabPanel{margin-left:5px;overflow: hidden;} +#tabContent {float:left;background:#FFFFFF;} +#tabContent div{display: none;width:480px;overflow:hidden;} +#tabIconReview.show{left:17px;display:block;} +.menuFocus{background:#ACCD3C;} +.menuDefault{background:#FFFFFF;} +#tabIconReview{position:absolute;left:406px;left:398px \9;top:41px;z-index:65533;width:90px;height:76px;} +img.review{width:90px;height:76px;border:2px solid #9cb945;background:#FFFFFF;background-position:center;background-repeat:no-repeat;} + +.wrapper .tabbody{position:relative;float:left;clear:both;padding:10px;width: 95%;} +.tabbody table{width: 100%;} +.tabbody td{border:1px solid #BAC498;} +.tabbody td span{display: block;zoom:1;padding:0 4px;} \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/emotion/emotion.html b/public/static/plugs/ueditor/dialogs/emotion/emotion.html new file mode 100644 index 0000000..a33b8f3 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/emotion/emotion.html @@ -0,0 +1,54 @@ + + + + + + + + + + +
    +
    + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + + diff --git a/public/static/plugs/ueditor/dialogs/emotion/emotion.js b/public/static/plugs/ueditor/dialogs/emotion/emotion.js new file mode 100644 index 0000000..6e158a9 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/emotion/emotion.js @@ -0,0 +1,186 @@ +window.onload = function () { + editor.setOpt({ + emotionLocalization:false + }); + + emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "http://img.baidu.com/hi/"; + emotion.SmileyBox = createTabList( emotion.tabNum ); + emotion.tabExist = createArr( emotion.tabNum ); + + initImgName(); + initEvtHandler( "tabHeads" ); +}; + +function initImgName() { + for ( var pro in emotion.SmilmgName ) { + var tempName = emotion.SmilmgName[pro], + tempBox = emotion.SmileyBox[pro], + tempStr = ""; + + if ( tempBox.length ) return; + for ( var i = 1; i <= tempName[1]; i++ ) { + tempStr = tempName[0]; + if ( i < 10 ) tempStr = tempStr + '0'; + tempStr = tempStr + i + '.gif'; + tempBox.push( tempStr ); + } + } +} + +function initEvtHandler( conId ) { + var tabHeads = $G( conId ); + for ( var i = 0, j = 0; i < tabHeads.childNodes.length; i++ ) { + var tabObj = tabHeads.childNodes[i]; + if ( tabObj.nodeType == 1 ) { + domUtils.on( tabObj, "click", (function ( index ) { + return function () { + switchTab( index ); + }; + })( j ) ); + j++; + } + } + switchTab( 0 ); + $G( "tabIconReview" ).style.display = 'none'; +} + +function InsertSmiley( url, evt ) { + var obj = { + src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url + }; + obj._src = obj.src; + editor.execCommand( 'insertimage', obj ); + if ( !evt.ctrlKey ) { + dialog.popup.hide(); + } +} + +function switchTab( index ) { + + autoHeight( index ); + if ( emotion.tabExist[index] == 0 ) { + emotion.tabExist[index] = 1; + createTab( 'tab' + index ); + } + //获取呈现元素句柄数组 + var tabHeads = $G( "tabHeads" ).getElementsByTagName( "span" ), + tabBodys = $G( "tabBodys" ).getElementsByTagName( "div" ), + i = 0, L = tabHeads.length; + //隐藏所有呈现元素 + for ( ; i < L; i++ ) { + tabHeads[i].className = ""; + tabBodys[i].style.display = "none"; + } + //显示对应呈现元素 + tabHeads[index].className = "focus"; + tabBodys[index].style.display = "block"; +} + +function autoHeight( index ) { + var iframe = dialog.getDom( "iframe" ), + parent = iframe.parentNode.parentNode; + switch ( index ) { + case 0: + iframe.style.height = "380px"; + parent.style.height = "392px"; + break; + case 1: + iframe.style.height = "220px"; + parent.style.height = "232px"; + break; + case 2: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 3: + iframe.style.height = "300px"; + parent.style.height = "312px"; + break; + case 4: + iframe.style.height = "140px"; + parent.style.height = "152px"; + break; + case 5: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 6: + iframe.style.height = "230px"; + parent.style.height = "242px"; + break; + default: + + } +} + + +function createTab( tabName ) { + var faceVersion = "?v=1.1", //版本号 + tab = $G( tabName ), //获取将要生成的Div句柄 + imagePath = emotion.SmileyPath + emotion.imageFolders[tabName], //获取显示表情和预览表情的路径 + positionLine = 11 / 2, //中间数 + iWidth = iHeight = 35, //图片长宽 + iColWidth = 3, //表格剩余空间的显示比例 + tableCss = emotion.imageCss[tabName], + cssOffset = emotion.imageCssOffset[tabName], + textHTML = [''], + i = 0, imgNum = emotion.SmileyBox[tabName].length, imgColNum = 11, faceImage, + sUrl, realUrl, posflag, offset, infor; + + for ( ; i < imgNum; ) { + textHTML.push( '' ); + for ( var j = 0; j < imgColNum; j++, i++ ) { + faceImage = emotion.SmileyBox[tabName][i]; + if ( faceImage ) { + sUrl = imagePath + faceImage + faceVersion; + realUrl = imagePath + faceImage; + posflag = j < positionLine ? 0 : 1; + offset = cssOffset * i * (-1) - 1; + infor = emotion.SmileyInfor[tabName][i]; + + textHTML.push( '' ); + } + textHTML.push( '' ); + } + textHTML.push( '
    ' ); + textHTML.push( '' ); + textHTML.push( '' ); + textHTML.push( '' ); + } else { + textHTML.push( '' ); + } + textHTML.push( '
    ' ); + textHTML = textHTML.join( "" ); + tab.innerHTML = textHTML; +} + +function over( td, srcPath, posFlag ) { + td.style.backgroundColor = "#ACCD3C"; + $G( 'faceReview' ).style.backgroundImage = "url(" + srcPath + ")"; + if ( posFlag == 1 ) $G( "tabIconReview" ).className = "show"; + $G( "tabIconReview" ).style.display = 'block'; +} + +function out( td ) { + td.style.backgroundColor = "transparent"; + var tabIconRevew = $G( "tabIconReview" ); + tabIconRevew.className = ""; + tabIconRevew.style.display = 'none'; +} + +function createTabList( tabNum ) { + var obj = {}; + for ( var i = 0; i < tabNum; i++ ) { + obj["tab" + i] = []; + } + return obj; +} + +function createArr( tabNum ) { + var arr = []; + for ( var i = 0; i < tabNum; i++ ) { + arr[i] = 0; + } + return arr; +} + diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/0.gif b/public/static/plugs/ueditor/dialogs/emotion/images/0.gif new file mode 100644 index 0000000..6964168 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/0.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/bface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/bface.gif new file mode 100644 index 0000000..14fe618 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/bface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/cface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/cface.gif new file mode 100644 index 0000000..bff947f Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/cface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/fface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/fface.gif new file mode 100644 index 0000000..0d8a6af Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/fface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/jxface2.gif b/public/static/plugs/ueditor/dialogs/emotion/images/jxface2.gif new file mode 100644 index 0000000..a959c90 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/jxface2.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/neweditor-tab-bg.png b/public/static/plugs/ueditor/dialogs/emotion/images/neweditor-tab-bg.png new file mode 100644 index 0000000..8f398b0 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/neweditor-tab-bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/tface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/tface.gif new file mode 100644 index 0000000..1354f54 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/tface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/wface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/wface.gif new file mode 100644 index 0000000..5667160 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/wface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/emotion/images/yface.gif b/public/static/plugs/ueditor/dialogs/emotion/images/yface.gif new file mode 100644 index 0000000..51608be Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/emotion/images/yface.gif differ diff --git a/public/static/plugs/ueditor/dialogs/formula/formula.html b/public/static/plugs/ueditor/dialogs/formula/formula.html new file mode 100644 index 0000000..8eeff98 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/formula/formula.html @@ -0,0 +1,98 @@ + + + + + + + + + +
    + + + + + +
    + + + + + + diff --git a/public/static/plugs/ueditor/dialogs/formula/formula.js b/public/static/plugs/ueditor/dialogs/formula/formula.js new file mode 100644 index 0000000..6a2b40b --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/formula/formula.js @@ -0,0 +1,147 @@ +function preg_quote(str, delimiter) { + // Quote regular expression characters plus an optional character + // + // version: 1107.2516 + // discuss at: http://phpjs.org/functions/preg_quote + // + original by: booeyOH + // + improved by: Ates Goral (http://magnetiq.com) + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + improved by: Brett Zamir (http://brett-zamir.me) + // * example 1: preg_quote("$40"); + // * returns 1: '\$40' + // * example 2: preg_quote("*RRRING* Hello?"); + // * returns 2: '\*RRRING\* Hello\?' + // * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:"); + // * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:' + return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); +} + +function loadScript(url, cb) { + var script; + script = document.createElement('script'); + script.src = url; + script.onload = function(){ + cb && cb({isNew: true}) + }; + document.getElementsByTagName('head')[0].appendChild(script); +} + +var Formula = { + mode: 'plain', + latexeasy: null, + init: function () { + // console.log('Formula.init') + Formula.initMode(); + Formula.initEvent(); + Formula.initSubmit(); + }, + renderPlain: function () { + var $preview = $('#preview'); + var value = $('#editor').val(); + if (!value) { + $preview.hide(); + return; + } + value = encodeURIComponent(value); + var formulaConfig = editor.getOpt('formulaConfig'); + var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value); + $('#previewImage').attr('src', src); + $preview.show(); + }, + setValuePlain: function (value) { + $('#editor').val(value); + Formula.renderPlain(); + }, + setValueLive: function (value) { + if (!Formula.latexeasy) { + setTimeout(function () { + Formula.setValueLive(value); + }, 100); + return; + } + Formula.latexeasy.call('set.latex', {latex: value}); + }, + initMode: function () { + var formulaConfig = editor.getOpt('formulaConfig'); + if ('live' === formulaConfig.editorMode) { + $('#liveEditor').attr('src', formulaConfig.editorLiveServer+'/editor'); + $('#modeLive').show(); + Formula.mode = 'live'; + } else { + $('#modePlain').show(); + Formula.mode = 'plain'; + } + var img = editor.selection.getRange().getClosedNode(); + if (img && img.getAttribute('data-formula-image') !== null) { + var value = img.getAttribute('data-formula-image'); + if (value) { + Formula.setValue(decodeURIComponent(value)); + } + } + }, + setValue: function (value) { + switch (Formula.mode) { + case 'plain': + Formula.setValuePlain(value); + break; + case 'live': + Formula.setValueLive(value); + break; + } + }, + getValue: function (cb) { + switch (Formula.mode) { + case 'plain': + cb($.trim($('#editor').val())); + break; + case 'live': + Formula.latexeasy.call('get.latex', {}, function (data) { + cb(data.latex); + }); + break; + } + }, + initEvent: function () { + var changeTimer = null, le; + switch (Formula.mode) { + case 'plain': + // console.log('Formula.initEvent'); + $('#editor').on('change keypress', function () { + changeTimer && clearTimeout(changeTimer); + changeTimer = setTimeout(function () { + Formula.renderPlain(); + }, 1000); + }); + $('#inputDemo').on('click', function () { + $('#editor').val('f(a) = \\frac{1}{2\\pi i} \\oint\\frac{f(z)}{z-a}dz'); + Formula.renderPlain(); + }); + break; + case 'live': + var formulaConfig = editor.getOpt('formulaConfig'); + loadScript(formulaConfig.editorLiveServer+'/vendor/LatexEasyEditor/editor/sdk.js',function(){ + le = new window.LatexEasy(document.getElementById('liveEditor')); + le.on('ready', function () { + Formula.latexeasy = le; + }); + le.init(); + }); + break; + } + }, + initSubmit: function () { + dialog.onclose = function (t, ok) { + if (!ok) { + return true; + } + // console.log('onclose', t, ok); + Formula.getValue(function (value) { + editor.execCommand('formula', value); + editor.fireEvent('saveScene'); + dialog.close(false); + }); + return false; + }; + } +}; diff --git a/public/static/plugs/ueditor/dialogs/help/help.css b/public/static/plugs/ueditor/dialogs/help/help.css new file mode 100644 index 0000000..4478475 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/help/help.css @@ -0,0 +1,7 @@ +.wrapper{width: 370px;margin: 10px auto;zoom: 1;} +.tabbody{height: 360px;} +.tabbody .panel{width:100%;height: 360px;position: absolute;background: #fff;} +.tabbody .panel h1{font-size:26px;margin: 5px 0 0 5px;} +.tabbody .panel p{font-size:12px;margin: 5px 0 0 5px;} +.tabbody table{width:90%;line-height: 20px;margin: 5px 0 0 5px;;} +.tabbody table thead{font-weight: bold;line-height: 25px;} \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/help/help.html b/public/static/plugs/ueditor/dialogs/help/help.html new file mode 100644 index 0000000..2fffafd --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/help/help.html @@ -0,0 +1,82 @@ + + + + 帮助 + + + + + +
    +
    + + +
    +
    +
    +

    UEditor Plus

    +

    +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ctrl+b
    ctrl+c
    ctrl+x
    ctrl+v
    ctrl+y
    ctrl+z
    ctrl+i
    ctrl+u
    ctrl+a
    shift+enter
    alt+z
    +
    +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/help/help.js b/public/static/plugs/ueditor/dialogs/help/help.js new file mode 100644 index 0000000..9a2272e --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/help/help.js @@ -0,0 +1,56 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午1:06 + * To change this template use File | Settings | File Templates. + */ +/** + * tab点击处理事件 + * @param tabHeads + * @param tabBodys + * @param obj + */ +function clickHandler( tabHeads,tabBodys,obj ) { + //head样式更改 + for ( var k = 0, len = tabHeads.length; k < len; k++ ) { + tabHeads[k].className = ""; + } + obj.className = "focus"; + //body显隐 + var tabSrc = obj.getAttribute( "tabSrc" ); + for ( var j = 0, length = tabBodys.length; j < length; j++ ) { + var body = tabBodys[j], + id = body.getAttribute( "id" ); + body.onclick = function(){ + this.style.zoom = 1; + }; + if ( id != tabSrc ) { + body.style.zIndex = 1; + } else { + body.style.zIndex = 200; + } + } + +} + +/** + * TAB切换 + * @param tabParentId tab的父节点ID或者对象本身 + */ +function switchTab( tabParentId ) { + var tabElements = $G( tabParentId ).children, + tabHeads = tabElements[0].children, + tabBodys = tabElements[1].children; + + for ( var i = 0, length = tabHeads.length; i < length; i++ ) { + var head = tabHeads[i]; + if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head ); + head.onclick = function () { + clickHandler(tabHeads,tabBodys,this); + } + } +} +switchTab("helptab"); + +document.getElementById('version').innerHTML = parent.UE.version; \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/image/image.css b/public/static/plugs/ueditor/dialogs/image/image.css new file mode 100644 index 0000000..d494fec --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/image/image.css @@ -0,0 +1,718 @@ +@charset "utf-8"; +/* dialog样式 */ +.wrapper { + zoom: 1; + width: 630px; + *width: 626px; + height: 380px; + margin: 0 auto; + padding: 10px; + position: relative; + font-family: sans-serif; +} + +/*tab样式框大小*/ +.tabhead { + float:left; +} +.tabbody { + width: 100%; + height: 346px; + position: relative; + clear: both; +} + +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} + +.tabbody .panel.focus { + width: 100%; + height: 346px; + display: block; +} + +/* 图片对齐方式 */ +.alignBar{ + float:right; + margin-top: 5px; + position: relative; +} + +.alignBar .algnLabel{ + float:left; + height: 20px; + line-height: 20px; +} + +.alignBar #alignIcon{ + zoom:1; + _display: inline; + display: inline-block; + position: relative; +} +.alignBar #alignIcon span{ + float: left; + cursor: pointer; + display: block; + width: 19px; + height: 17px; + margin-right: 3px; + margin-left: 3px; + background-image: url(./images/alignicon.jpg); +} +.alignBar #alignIcon .none-align{ + background-position: 0 -18px; +} +.alignBar #alignIcon .left-align{ + background-position: -20px -18px; +} +.alignBar #alignIcon .right-align{ + background-position: -40px -18px; +} +.alignBar #alignIcon .center-align{ + background-position: -60px -18px; +} +.alignBar #alignIcon .none-align.focus{ + background-position: 0 0; +} +.alignBar #alignIcon .left-align.focus{ + background-position: -20px 0; +} +.alignBar #alignIcon .right-align.focus{ + background-position: -40px 0; +} +.alignBar #alignIcon .center-align.focus{ + background-position: -60px 0; +} + + + + +/* 远程图片样式 */ +#remote { + z-index: 200; +} + +#remote .top{ + width: 100%; + margin-top: 25px; +} +#remote .left{ + display: block; + float: left; + width: 300px; + height:10px; +} +#remote .right{ + display: block; + float: right; + width: 300px; + height:10px; +} +#remote .row{ + margin-left: 20px; + clear: both; + height: 40px; +} + +#remote .row label{ + text-align: center; + width: 50px; + zoom:1; + _display: inline; + display:inline-block; + vertical-align: middle; +} +#remote .row label.algnLabel{ + float: left; + +} + +#remote input.text{ + width: 150px; + padding: 3px 6px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +#remote input.text:focus { + outline: 0; +} +#remote #url{ + width: 400px; + margin-bottom: 2px; +} +#remote #imageSelect{ + width: 100px; + display: inline-block; + background: #FFF; + border: 1px solid #EEE; + line-height: 26px; + text-align: center; + color: #333; + text-decoration: none; + border-radius: 3px; + vertical-align: top; +} +#remote #width, +#remote #height{ + width: 30px; + margin-left: 2px; + margin-right: 2px; + text-align:center; +} +#remote #border, +#remote #vhSpace, +#remote #title{ + width: 180px; + margin-right: 5px; +} +#remote #lock{ + display:inline-block; + vertical-align: middle; +} +#remote #lockicon{ + zoom: 1; + _display:inline; + display: inline-block; + width: 20px; + height: 20px; + background: url("../../themes/default/images/lock.gif") -13px -13px no-repeat; + vertical-align: middle; +} +#remote #preview{ + clear: both; + width: 260px; + height: 240px; + z-index: 9999; + margin-top: 10px; + background-color: #eee; + overflow: hidden; +} + +/* 上传图片 */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} + +.tabbody #upload.panel.focus { + width: 100%; + height: 346px; + display: block; + clip: auto; +} + +#upload .queueList { + margin: 0; + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 172px; + padding-top: 150px; + text-align: center; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *top: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 300px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; + position: relative; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 9px 0 0 9px; + *margin: 6px 0 0 6px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background: url(./images/success.gif) no-repeat right bottom \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + + +/* 图片管理样式 */ +#online { + width: 100%; + height: 336px; + padding: 10px 0 0 0; +} +#online #imageList{ + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + position: relative; +} +#online ul { + display: block; + list-style: none; + margin: 0; + padding: 0; +} +#online li { + float: left; + display: block; + list-style: none; + padding: 0; + width: 113px; + height: 113px; + margin: 0 0 9px 9px; + *margin: 0 0 6px 6px; + background-color: #eee; + overflow: hidden; + cursor: pointer; + position: relative; +} +#online li.clearFloat { + float: none; + clear: both; + display: block; + width:0; + height:0; + margin: 0; + padding: 0; +} +#online li img { + cursor: pointer; +} +#online li .icon { + cursor: pointer; + width: 113px; + height: 113px; + position: absolute; + top: 0; + left: 0; + z-index: 2; + border: 0; + background-repeat: no-repeat; +} +#online li .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; +} +#online li.selected .icon { + background-image: url(images/success.png); + background-image: url(images/success.gif)\9; + background-position: 75px 75px; +} +#online li.selected .icon:hover { + width: 107px; + height: 107px; + border: 3px solid #1094fa; + background-position: 72px 72px; +} diff --git a/public/static/plugs/ueditor/dialogs/image/image.html b/public/static/plugs/ueditor/dialogs/image/image.html new file mode 100644 index 0000000..0492e58 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/image/image.html @@ -0,0 +1,119 @@ + + + + + ueditor图片对话框 + + + + + + + + + + + + + + +
    +
    + + + +
    +
    + + + + + + + + +
    +
    + + +
    +
    +
    + + + +
    +
    +
    +
    + +   px +   px + +
    +
    + + px +
    +
    + + px +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + 0% + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
      +
    • +
    +
    +
    + + +
    +
    +
    + + + + +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/image/image.js b/public/static/plugs/ueditor/dialogs/image/image.js new file mode 100644 index 0000000..1119171 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/image/image.js @@ -0,0 +1,1021 @@ +/** + * User: Jinqn + * Date: 14-04-08 + * Time: 下午16:34 + * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片 + */ +(function () { + + var remoteImage, + uploadImage, + onlineImage; + var editorOpt = {}; + + window.onload = function () { + editorOpt = editor.getOpt('imageConfig'); + initTabs(); + initAlign(); + initButtons(); + }; + + /* 初始化tab标签 */ + function initTabs() { + var tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var target = e.target || e.srcElement; + setTabFocus(target.getAttribute('data-content-id')); + }); + } + if(!editorOpt.disableUpload){ + $G('tabhead').querySelector('[data-content-id="upload"]').style.display = 'inline-block'; + } + if(!editorOpt.disableOnline){ + $G('tabhead').querySelector('[data-content-id="online"]').style.display = 'inline-block'; + } + if(!!editorOpt.selectCallback){ + $G('imageSelect').style.display = 'inline-block'; + domUtils.on($G('imageSelect'), "click", function (e) { + editorOpt.selectCallback(editor,function(info){ + if(info){ + $G('url').value = info.path; + $G('title').value = info.name; + var img = new Image(); + img.onload = function(){ + $G('width').value = img.width; + $G('height').value = img.height; + remoteImage.setPreview(); + }; + img.onerror = function(){ + remoteImage.setPreview(); + }; + img.src = info.path; + } + }); + }); + } + var img = editor.selection.getRange().getClosedNode(); + if (img && img.tagName && img.tagName.toLowerCase() == 'img') { + setTabFocus('remote'); + } else { + setTabFocus('remote'); + } + } + + /* 初始化tabbody */ + function setTabFocus(id) { + if(!id) return; + var i, bodyId, tabs = $G('tabhead').children; + for (i = 0; i < tabs.length; i++) { + bodyId = tabs[i].getAttribute('data-content-id'); + if (bodyId == id) { + domUtils.addClass(tabs[i], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + } else { + domUtils.removeClasses(tabs[i], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + switch (id) { + case 'remote': + remoteImage = remoteImage || new RemoteImage(); + break; + case 'upload': + setAlign(editor.getOpt('imageInsertAlign')); + uploadImage = uploadImage || new UploadImage('queueList'); + break; + case 'online': + setAlign(editor.getOpt('imageManagerInsertAlign')); + onlineImage = onlineImage || new OnlineImage('imageList'); + onlineImage.reset(); + break; + } + } + + /* 初始化onok事件 */ + function initButtons() { + + dialog.onok = function () { + var remote = false, list = [], id, tabs = $G('tabhead').children; + for (var i = 0; i < tabs.length; i++) { + if (domUtils.hasClass(tabs[i], 'focus')) { + id = tabs[i].getAttribute('data-content-id'); + break; + } + } + + switch (id) { + case 'remote': + list = remoteImage.getInsertList(); + break; + case 'upload': + list = uploadImage.getInsertList(); + var count = uploadImage.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } + break; + case 'online': + list = onlineImage.getInsertList(); + break; + } + + if(list) { + editor.execCommand('insertimage', list); + remote && editor.fireEvent("catchRemoteImage"); + } + }; + } + + + /* 初始化对其方式的点击事件 */ + function initAlign(){ + /* 点击align图标 */ + domUtils.on($G("alignIcon"), 'click', function(e){ + var target = e.target || e.srcElement; + if(target.className && target.className.indexOf('-align') != -1) { + setAlign(target.getAttribute('data-align')); + } + }); + } + + /* 设置对齐方式 */ + function setAlign(align){ + align = align || 'none'; + var aligns = $G("alignIcon").children; + for(i = 0; i < aligns.length; i++){ + if(aligns[i].getAttribute('data-align') == align) { + domUtils.addClass(aligns[i], 'focus'); + $G("align").value = aligns[i].getAttribute('data-align'); + } else { + domUtils.removeClasses(aligns[i], 'focus'); + } + } + } + /* 获取对齐方式 */ + function getAlign(){ + var align = $G("align").value || 'none'; + return align == 'none' ? '':align; + } + + + /* 在线图片 */ + function RemoteImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + RemoteImage.prototype = { + init: function () { + this.initContainer(); + this.initEvents(); + }, + initContainer: function () { + this.dom = { + 'url': $G('url'), + 'width': $G('width'), + 'height': $G('height'), + 'border': $G('border'), + 'vhSpace': $G('vhSpace'), + 'title': $G('title'), + 'align': $G('align') + }; + var img = editor.selection.getRange().getClosedNode(); + if (img) { + this.setImage(img); + } + }, + initEvents: function () { + var _this = this, + locker = $G('lock'); + + /* 改变url */ + domUtils.on($G("url"), 'keyup', updatePreview); + domUtils.on($G("border"), 'keyup', updatePreview); + domUtils.on($G("title"), 'keyup', updatePreview); + + domUtils.on($G("width"), 'keyup', function(){ + 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(){ + 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); + locker.setAttribute('data-proportion', proportion); + }); + + function updatePreview(){ + _this.setPreview(); + } + }, + updateLocker: function(){ + var width = $G('width').value, + height = $G('height').value, + locker = $G('lock'); + if(width && height && width == parseInt(width) && height == parseInt(height)) { + locker.disabled = false; + locker.title = ''; + } else { + locker.checked = false; + locker.disabled = 'disabled'; + locker.title = lang.remoteLockError; + } + }, + setImage: function(img){ + /* 不是正常的图片 */ + if (!img.tagName || img.tagName.toLowerCase() != 'img' && !img.getAttribute("src") || !img.src) return; + + var wordImgFlag = img.getAttribute("data-word-image"), + src = wordImgFlag ? wordImgFlag.replace("&", "&") : (img.getAttribute('_src') || img.getAttribute("src", 2).replace("&", "&")), + align = editor.queryCommandValue("imageFloat"); + + /* 防止onchange事件循环调用 */ + if (src !== $G("url").value) $G("url").value = src; + if(src) { + /* 设置表单内容 */ + $G("width").value = img.width || ''; + $G("height").value = img.height || ''; + $G("border").value = img.getAttribute("border") || '0'; + $G("vhSpace").value = img.getAttribute("vspace") || '0'; + $G("title").value = img.title || img.alt || ''; + setAlign(align); + this.setPreview(); + this.updateLocker(); + } + }, + getData: function(){ + var data = {}; + for(var k in this.dom){ + data[k] = this.dom[k].value; + } + return data; + }, + setPreview: function(){ + var url = $G('url').value, + ow = $G('width').value, + oh = $G('height').value, + border = $G('border').value, + title = $G('title').value, + preview = $G('preview'), + width, + height; + + width = ((!ow || !oh) ? preview.offsetWidth:Math.min(ow, preview.offsetWidth)); + width = width+(border*2) > preview.offsetWidth ? width:(preview.offsetWidth - (border*2)); + height = (!ow || !oh) ? '':width*oh/ow; + + if(url) { + preview.innerHTML = ''; + } + }, + getInsertList: function () { + var data = this.getData(); + if(data['url']) { + var img = { + src: data['url'], + _src: data['url'], + } + img._propertyDelete = [] + img.style = [] + if(data['width']){ + img.width = data['width']; + img.style.push('width:'+data['width']+'px'); + }else{ + img._propertyDelete.push('width'); + } + if(data['height']){ + img.height = data['height']; + img.style.push('height:'+data['height']+'px'); + }else{ + img._propertyDelete.push('height'); + } + if(data['border']){ + img.border = data['border']; + }else{ + img._propertyDelete.push('border'); + } + if(data['align']){ + img.floatStyle = data['align']; + }else{ + img._propertyDelete.push('floatStyle'); + } + if(data['vhSpace']){ + img.vspace = data['vhSpace']; + }else{ + img._propertyDelete.push('vspace'); + } + if(data['title']){ + img.alt = data['title']; + }else{ + img._propertyDelete.push('alt'); + } + if(img.style.length> 0){ + img.style = img.style.join(';'); + }else{ + img._propertyDelete.push('style'); + } + return [img]; + } else { + return []; + } + } + }; + + + + /* 上传图片 */ + function UploadImage(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadImage.prototype = { + init: function () { + this.imageList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('imageActionName')), + acceptExtensions = (editor.getOpt('imageAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, ''), + imageMaxSize = editor.getOpt('imageMaxSize'), + imageCompressBorder = editor.getOpt('imageCompressBorder'); + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
    ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('imageActionName')) { + $('#filePickerReady').after($('
    ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + accept: { + title: 'Images', + extensions: acceptExtensions, + mimeTypes: 'image/*' + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('imageFieldName'), + duplicate: true, + fileSingleSizeLimit: imageMaxSize, // 默认 2 M + threads: 1, + headers: editor.getOpt('serverHeaders') || {}, + compress: editor.getOpt('imageCompressEnable') ? { + enable:editor.getOpt('imageCompressEnable'), + maxWidthOrHeight: imageCompressBorder, + maxSize: imageMaxSize, + }:false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
  • ' + + '

    ' + file.name + '

    ' + + '

    ' + + '

    ' + + '
  • '), + + $btns = $('
    ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
    ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

    ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val !== state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase()) != -1 && file.size <= imageMaxSize) { + fileCount--; + fileSize -= file.size; + } + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + if (actionUrl.toLowerCase().indexOf('jsp') != -1) { + header['X-Requested-With'] = 'XMLHttpRequest'; + } + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + _this.imageList.push(json); + $file.append(''); + // 触发上传图片事件 + editor.fireEvent("uploadsuccess", { + res: json, + type: 'image' + }); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + destroy: function () { + this.$wrap.remove(); + }, + getInsertList: function () { + var i, data, list = [], + align = getAlign(), + prefix = editor.getOpt('imageUrlPrefix'); + for (i = 0; i < this.imageList.length; i++) { + data = this.imageList[i]; + list.push({ + src: prefix + data.url, + _src: prefix + data.url, + alt: data.original, + floatStyle: align + }); + } + return list; + } + }; + + + /* 在线图片 */ + function OnlineImage(target) { + this.container = utils.isString(target) ? document.getElementById(target) : target; + this.init(); + } + OnlineImage.prototype = { + init: function () { + this.reset(); + this.initEvents(); + }, + /* 初始化容器 */ + initContainer: function () { + this.container.innerHTML = ''; + this.list = document.createElement('ul'); + this.clearFloat = document.createElement('li'); + + domUtils.addClass(this.list, 'list'); + domUtils.addClass(this.clearFloat, 'clearFloat'); + + this.list.appendChild(this.clearFloat); + this.container.appendChild(this.list); + }, + /* 初始化滚动事件,滚动到地步自动拉取数据 */ + initEvents: function () { + var _this = this; + + /* 滚动拉取图片 */ + domUtils.on($G('imageList'), 'scroll', function(e){ + var panel = this; + if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) { + _this.getImageData(); + } + }); + /* 选中图片 */ + domUtils.on(this.container, 'click', function (e) { + var target = e.target || e.srcElement, + li = target.parentNode; + + if (li.tagName.toLowerCase() == 'li') { + if (domUtils.hasClass(li, 'selected')) { + domUtils.removeClasses(li, 'selected'); + } else { + domUtils.addClass(li, 'selected'); + } + } + }); + }, + /* 初始化第一次的数据 */ + initData: function () { + + /* 拉取数据需要使用的值 */ + this.state = 0; + this.listSize = editor.getOpt('imageManagerListSize'); + this.listIndex = 0; + this.listEnd = false; + + /* 第一次拉取数据 */ + this.getImageData(); + }, + /* 重置界面 */ + reset: function() { + this.initContainer(); + this.initData(); + }, + /* 向后台拉取图片列表数据 */ + getImageData: function () { + var _this = this; + + if(!_this.listEnd && !this.isLoadingData) { + this.isLoadingData = true; + var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')), + isJsonp = utils.isCrossDomainUrl(url); + ajax.request(url, { + 'timeout': 100000, + 'dataType': isJsonp ? 'jsonp':'', + 'headers': editor.options.serverHeaders || {}, + 'data': utils.extend({ + start: this.listIndex, + size: this.listSize + }, editor.queryCommandValue('serverparam')), + 'method': 'get', + 'onsuccess': function (r) { + try { + var json = isJsonp ? r:eval('(' + r.responseText + ')'); + if (json.state === 'SUCCESS') { + _this.pushData(json.list); + _this.listIndex = parseInt(json.start) + parseInt(json.list.length); + if(_this.listIndex >= json.total) { + _this.listEnd = true; + } + _this.isLoadingData = false; + } + } catch (e) { + if(r.responseText.indexOf('ue_separate_ue') != -1) { + var list = r.responseText.split(r.responseText); + _this.pushData(list); + _this.listIndex = parseInt(list.length); + _this.listEnd = true; + _this.isLoadingData = false; + } + } + }, + 'onerror': function () { + _this.isLoadingData = false; + } + }); + } + }, + /* 添加图片到列表界面上 */ + pushData: function (list) { + var i, item, img, icon, _this = this, + urlPrefix = editor.getOpt('imageManagerUrlPrefix'); + for (i = 0; i < list.length; i++) { + if(list[i] && list[i].url) { + item = document.createElement('li'); + img = document.createElement('img'); + icon = document.createElement('span'); + + domUtils.on(img, 'load', (function(image){ + return function(){ + _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight); + } + })(img)); + img.width = 113; + img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) ); + img.setAttribute('_src', urlPrefix + list[i].url); + domUtils.addClass(icon, 'icon'); + + item.appendChild(img); + item.appendChild(icon); + this.list.insertBefore(item, this.clearFloat); + } + } + }, + /* 改变图片大小 */ + scale: function (img, w, h, type) { + var ow = img.width, + oh = img.height; + + if (type == 'justify') { + if (ow >= oh) { + img.width = w; + img.height = h * oh / ow; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w * ow / oh; + img.height = h; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } else { + if (ow >= oh) { + img.width = w * ow / oh; + img.height = h; + img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px'; + } else { + img.width = w; + img.height = h * oh / ow; + img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px'; + } + } + }, + getInsertList: function () { + var i, lis = this.list.children, list = [], align = getAlign(); + for (i = 0; i < lis.length; i++) { + if (domUtils.hasClass(lis[i], 'selected')) { + var img = lis[i].firstChild, + src = img.getAttribute('_src'); + list.push({ + src: src, + _src: src, + alt: src.substr(src.lastIndexOf('/') + 1), + floatStyle: align + }); + } + + } + return list; + } + }; + +})(); diff --git a/public/static/plugs/ueditor/dialogs/image/images/alignicon.jpg b/public/static/plugs/ueditor/dialogs/image/images/alignicon.jpg new file mode 100644 index 0000000..754755b Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/alignicon.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/bg.png b/public/static/plugs/ueditor/dialogs/image/images/bg.png new file mode 100644 index 0000000..580be0a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/icons.gif b/public/static/plugs/ueditor/dialogs/image/images/icons.gif new file mode 100644 index 0000000..78459de Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/icons.png b/public/static/plugs/ueditor/dialogs/image/images/icons.png new file mode 100644 index 0000000..12e4700 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/image.png b/public/static/plugs/ueditor/dialogs/image/images/image.png new file mode 100644 index 0000000..19699f6 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/image.png differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/progress.png b/public/static/plugs/ueditor/dialogs/image/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/progress.png differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/success.gif b/public/static/plugs/ueditor/dialogs/image/images/success.gif new file mode 100644 index 0000000..8d4f311 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/success.gif differ diff --git a/public/static/plugs/ueditor/dialogs/image/images/success.png b/public/static/plugs/ueditor/dialogs/image/images/success.png new file mode 100644 index 0000000..94f968d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/image/images/success.png differ diff --git a/public/static/plugs/ueditor/dialogs/insertframe/insertframe.html b/public/static/plugs/ueditor/dialogs/insertframe/insertframe.html new file mode 100644 index 0000000..ebd1255 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/insertframe/insertframe.html @@ -0,0 +1,135 @@ + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + + +
    + px +
    px +
    + +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/internal.js b/public/static/plugs/ueditor/dialogs/internal.js new file mode 100644 index 0000000..44dc17f --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/internal.js @@ -0,0 +1,81 @@ +(function () { + var parent = window.parent; + //dialog对象 + dialog = parent.$EDITORUI[window.frameElement.id.replace( /_iframe$/, '' )]; + //当前打开dialog的编辑器实例 + editor = dialog.editor; + + UE = parent.UE; + + domUtils = UE.dom.domUtils; + + utils = UE.utils; + + browser = UE.browser; + + ajax = UE.ajax; + + $G = function ( id ) { + return document.getElementById( id ) + }; + //focus元素 + $focus = function ( node ) { + setTimeout( function () { + if ( browser.ie ) { + var r = node.createTextRange(); + r.collapse( false ); + r.select(); + } else { + node.focus() + } + }, 0 ) + }; + utils.loadFile(document,{ + href:editor.options.themePath + editor.options.theme + "/dialogbase.css?cache="+Math.random(), + tag:"link", + type:"text/css", + rel:"stylesheet" + }); + lang = editor.getLang(dialog.className.split( "-" )[2]); + if(lang){ + domUtils.on(window,'load',function () { + + var langImgPath = editor.options.langPath + editor.options.lang + "/images/"; + //针对静态资源 + for ( var i in lang["static"] ) { + var dom = $G( i ); + if(!dom) continue; + var tagName = dom.tagName, + content = lang["static"][i]; + if(content.src){ + //clone + content = utils.extend({},content,false); + content.src = langImgPath + content.src; + } + if(content.style){ + content = utils.extend({},content,false); + content.style = content.style.replace(/url\s*\(/g,"url(" + langImgPath) + } + switch ( tagName.toLowerCase() ) { + case "var": + dom.parentNode.replaceChild( document.createTextNode( content ), dom ); + break; + case "select": + var ops = dom.options; + for ( var j = 0, oj; oj = ops[j]; ) { + oj.innerHTML = content.options[j++]; + } + for ( var p in content ) { + p != "options" && dom.setAttribute( p, content[p] ); + } + break; + default : + domUtils.setAttributes( dom, content); + } + } + } ); + } + + +})(); + diff --git a/public/static/plugs/ueditor/dialogs/link/link.html b/public/static/plugs/ueditor/dialogs/link/link.html new file mode 100644 index 0000000..9c0a3d6 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/link/link.html @@ -0,0 +1,134 @@ + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/preview/preview.html b/public/static/plugs/ueditor/dialogs/preview/preview.html new file mode 100644 index 0000000..69d9a32 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/preview/preview.html @@ -0,0 +1,40 @@ + + + + + + + + + + +
    + +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/addimg.png b/public/static/plugs/ueditor/dialogs/scrawl/images/addimg.png new file mode 100644 index 0000000..03a8713 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/addimg.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/brush.png b/public/static/plugs/ueditor/dialogs/scrawl/images/brush.png new file mode 100644 index 0000000..efa6fdb Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/brush.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/delimg.png b/public/static/plugs/ueditor/dialogs/scrawl/images/delimg.png new file mode 100644 index 0000000..5a892e4 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/delimg.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/delimgH.png b/public/static/plugs/ueditor/dialogs/scrawl/images/delimgH.png new file mode 100644 index 0000000..2f0c5c9 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/delimgH.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/empty.png b/public/static/plugs/ueditor/dialogs/scrawl/images/empty.png new file mode 100644 index 0000000..0375196 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/empty.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/emptyH.png b/public/static/plugs/ueditor/dialogs/scrawl/images/emptyH.png new file mode 100644 index 0000000..838ca72 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/emptyH.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/eraser.png b/public/static/plugs/ueditor/dialogs/scrawl/images/eraser.png new file mode 100644 index 0000000..63e87ce Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/eraser.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/redo.png b/public/static/plugs/ueditor/dialogs/scrawl/images/redo.png new file mode 100644 index 0000000..12cd9bb Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/redo.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/redoH.png b/public/static/plugs/ueditor/dialogs/scrawl/images/redoH.png new file mode 100644 index 0000000..d9f33d3 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/redoH.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/scale.png b/public/static/plugs/ueditor/dialogs/scrawl/images/scale.png new file mode 100644 index 0000000..935a3f3 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/scale.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/scaleH.png b/public/static/plugs/ueditor/dialogs/scrawl/images/scaleH.png new file mode 100644 index 0000000..72e64a9 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/scaleH.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/size.png b/public/static/plugs/ueditor/dialogs/scrawl/images/size.png new file mode 100644 index 0000000..8366845 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/size.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/undo.png b/public/static/plugs/ueditor/dialogs/scrawl/images/undo.png new file mode 100644 index 0000000..084c7cc Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/undo.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/images/undoH.png b/public/static/plugs/ueditor/dialogs/scrawl/images/undoH.png new file mode 100644 index 0000000..fde7eb3 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/scrawl/images/undoH.png differ diff --git a/public/static/plugs/ueditor/dialogs/scrawl/scrawl.css b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.css new file mode 100644 index 0000000..b18430d --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.css @@ -0,0 +1,72 @@ +/*common +*/ +body{margin: 0;} +table{width:100%;} +table td{padding:2px 4px;vertical-align: middle;} +a{text-decoration: none;} +em{font-style: normal;} +.border_style1{border: 1px solid #ccc;border-radius: 5px;box-shadow:2px 2px 5px #d3d6da;} +/*module +*/ +.main{margin: 8px;overflow: hidden;} + +.hot{float:left;height:335px;} +.drawBoard{position: relative; cursor: crosshair;} +.brushBorad{position: absolute;left:0;top:0;z-index: 998;} +.picBoard{border: none;text-align: center;line-height: 300px;cursor: default;} +.operateBar{margin-top:10px;font-size:12px;text-align: center;} +.operateBar span{margin-left: 10px;} + +.drawToolbar{float:right;width:110px;height:300px;overflow: hidden;} +.colorBar{margin-top:10px;font-size: 12px;text-align: center;} +.colorBar a{display:block;width: 10px;height: 10px;border:1px solid #1006F1;border-radius: 3px; box-shadow:2px 2px 5px #d3d6da;opacity: 0.3} +.sectionBar{margin-top:15px;font-size: 12px;text-align: center;} +.sectionBar a{display:inline-block;width:10px;height:12px;color: #888;text-indent: -999px;opacity: 0.3} +.size1{background: url('images/size.png') 1px center no-repeat ;} +.size2{background: url('images/size.png') -10px center no-repeat;} +.size3{background: url('images/size.png') -22px center no-repeat;} +.size4{background: url('images/size.png') -35px center no-repeat;} + +.addImgH{position: relative;} +.addImgH_form{position: absolute;left: 18px;top: -1px;width: 75px;height: 21px;opacity: 0;cursor: pointer;} +.addImgH_form input{width: 100%;} +/*scrawl遮罩层 +*/ +.maskLayerNull{display: none;} +.maskLayer{position: absolute;top:0;left:0;width: 100%; height: 100%;opacity: 0.7; + background-color: #fff;text-align:center;font-weight:bold;line-height:300px;z-index: 1000;} +/*btn state +*/ +.previousStepH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/undoH.png');cursor: pointer;} +.previousStepH .text{color:#888;cursor:pointer;} +.previousStep .icon{display: inline-block;width:16px;height:16px;background-image: url('images/undo.png');cursor:default;} +.previousStep .text{color:#ccc;cursor:default;} + +.nextStepH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/redoH.png');cursor: pointer;} +.nextStepH .text{color:#888;cursor:pointer;} +.nextStep .icon{display: inline-block;width:16px;height:16px;background-image: url('images/redo.png');cursor:default;} +.nextStep .text{color:#ccc;cursor:default;} + +.clearBoardH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/emptyH.png');cursor: pointer;} +.clearBoardH .text{color:#888;cursor:pointer;} +.clearBoard .icon{display: inline-block;width:16px;height:16px;background-image: url('images/empty.png');cursor:default;} +.clearBoard .text{color:#ccc;cursor:default;} + +.scaleBoardH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/scaleH.png');cursor: pointer;} +.scaleBoardH .text{color:#888;cursor:pointer;} +.scaleBoard .icon{display: inline-block;width:16px;height:16px;background-image: url('images/scale.png');cursor:default;} +.scaleBoard .text{color:#ccc;cursor:default;} + +.removeImgH .icon{display: inline-block;width:16px;height:16px;background-image: url('images/delimgH.png');cursor: pointer;} +.removeImgH .text{color:#888;cursor:pointer;} +.removeImg .icon{display: inline-block;width:16px;height:16px;background-image: url('images/delimg.png');cursor:default;} +.removeImg .text{color:#ccc;cursor:default;} + +.addImgH .icon{vertical-align:top;display: inline-block;width:16px;height:16px;background-image: url('images/addimg.png')} +.addImgH .text{color:#888;cursor:pointer;} +/*icon +*/ +.brushIcon{display: inline-block;width:16px;height:16px;background-image: url('images/brush.png')} +.eraserIcon{display: inline-block;width:16px;height:16px;background-image: url('images/eraser.png')} + + diff --git a/public/static/plugs/ueditor/dialogs/scrawl/scrawl.html b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.html new file mode 100644 index 0000000..4f2551a --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.html @@ -0,0 +1,95 @@ + + + + + + + + + + +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    + + 1 + 3 + 5 + 7 +
    +
    + + 1 + 3 + 5 + 7 +
    +
    +
    + + +
    + +
    + +
    +
    +
    + + + + +
    +
    +
    +
    + + + + + diff --git a/public/static/plugs/ueditor/dialogs/scrawl/scrawl.js b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.js new file mode 100644 index 0000000..655ceb4 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/scrawl/scrawl.js @@ -0,0 +1,676 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-5-22 + * Time: 上午11:38 + * To change this template use File | Settings | File Templates. + */ +var scrawl = function (options) { + options && this.initOptions(options); +}; +(function () { + var canvas = $G("J_brushBoard"), + context = canvas.getContext('2d'), + drawStep = [], //undo redo存储 + drawStepIndex = 0; //undo redo指针 + + scrawl.prototype = { + isScrawl:false, //是否涂鸦 + brushWidth:-1, //画笔粗细 + brushColor:"", //画笔颜色 + + initOptions:function (options) { + var me = this; + me.originalState(options);//初始页面状态 + me._buildToolbarColor(options.colorList);//动态生成颜色选择集合 + + me._addBoardListener(options.saveNum);//添加画板处理 + me._addOPerateListener(options.saveNum);//添加undo redo clearBoard处理 + me._addColorBarListener();//添加颜色选择处理 + me._addBrushBarListener();//添加画笔大小处理 + me._addEraserBarListener();//添加橡皮大小处理 + me._addAddImgListener();//添加增添背景图片处理 + me._addRemoveImgListenter();//删除背景图片处理 + me._addScalePicListenter();//添加缩放处理 + me._addClearSelectionListenter();//添加清楚选中状态处理 + + me._originalColorSelect(options.drawBrushColor);//初始化颜色选中 + me._originalBrushSelect(options.drawBrushSize);//初始化画笔选中 + me._clearSelection();//清楚选中状态 + }, + + originalState:function (options) { + var me = this; + + me.brushWidth = options.drawBrushSize;//同步画笔粗细 + me.brushColor = options.drawBrushColor;//同步画笔颜色 + + context.lineWidth = me.brushWidth;//初始画笔大小 + context.strokeStyle = me.brushColor;//初始画笔颜色 + context.fillStyle = "transparent";//初始画布背景颜色 + context.lineCap = "round";//去除锯齿 + context.fill(); + }, + _buildToolbarColor:function (colorList) { + var tmp = null, arr = []; + arr.push(""); + for (var i = 0, color; color = colorList[i++];) { + if ((i - 1) % 5 == 0) { + if (i != 1) { + arr.push(""); + } + arr.push(""); + } + tmp = '#' + color; + arr.push(""); + } + arr.push("
    "); + $G("J_colorBar").innerHTML = arr.join(""); + }, + + _addBoardListener:function (saveNum) { + var me = this, + margin = 0, + startX = -1, + startY = -1, + isMouseDown = false, + isMouseMove = false, + isMouseUp = false, + buttonPress = 0, button, flag = ''; + + margin = parseInt(domUtils.getComputedStyle($G("J_wrap"), "margin-left")); + drawStep.push(context.getImageData(0, 0, context.canvas.width, context.canvas.height)); + drawStepIndex += 1; + + domUtils.on(canvas, ["mousedown", "mousemove", "mouseup", "mouseout"], function (e) { + button = browser.webkit ? e.which : buttonPress; + switch (e.type) { + case 'mousedown': + buttonPress = 1; + flag = 1; + isMouseDown = true; + isMouseUp = false; + isMouseMove = false; + me.isScrawl = true; + startX = e.clientX - margin;//10为外边距总和 + startY = e.clientY - margin; + context.beginPath(); + break; + case 'mousemove' : + if (!flag && button == 0) { + return; + } + if (!flag && button) { + startX = e.clientX - margin;//10为外边距总和 + startY = e.clientY - margin; + context.beginPath(); + flag = 1; + } + if (isMouseUp || !isMouseDown) { + return; + } + var endX = e.clientX - margin, + endY = e.clientY - margin; + + context.moveTo(startX, startY); + context.lineTo(endX, endY); + context.stroke(); + startX = endX; + startY = endY; + isMouseMove = true; + break; + case 'mouseup': + buttonPress = 0; + if (!isMouseDown)return; + if (!isMouseMove) { + context.arc(startX, startY, context.lineWidth, 0, Math.PI * 2, false); + context.fillStyle = context.strokeStyle; + context.fill(); + } + context.closePath(); + me._saveOPerate(saveNum); + isMouseDown = false; + isMouseMove = false; + isMouseUp = true; + startX = -1; + startY = -1; + break; + case 'mouseout': + flag = ''; + buttonPress = 0; + if (button == 1) return; + context.closePath(); + break; + } + }); + }, + _addOPerateListener:function (saveNum) { + var me = this; + domUtils.on($G("J_previousStep"), "click", function () { + if (drawStepIndex > 1) { + drawStepIndex -= 1; + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + context.putImageData(drawStep[drawStepIndex - 1], 0, 0); + me.btn2Highlight("J_nextStep"); + drawStepIndex == 1 && me.btn2disable("J_previousStep"); + } + }); + domUtils.on($G("J_nextStep"), "click", function () { + if (drawStepIndex > 0 && drawStepIndex < drawStep.length) { + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + context.putImageData(drawStep[drawStepIndex], 0, 0); + drawStepIndex += 1; + me.btn2Highlight("J_previousStep"); + drawStepIndex == drawStep.length && me.btn2disable("J_nextStep"); + } + }); + domUtils.on($G("J_clearBoard"), "click", function () { + context.clearRect(0, 0, context.canvas.width, context.canvas.height); + drawStep = []; + me._saveOPerate(saveNum); + drawStepIndex = 1; + me.isScrawl = false; + me.btn2disable("J_previousStep"); + me.btn2disable("J_nextStep"); + me.btn2disable("J_clearBoard"); + }); + }, + _addColorBarListener:function () { + var me = this; + domUtils.on($G("J_colorBar"), "click", function (e) { + var target = me.getTarget(e), + color = target.title; + if (!!color) { + me._addColorSelect(target); + + me.brushColor = color; + context.globalCompositeOperation = "source-over"; + context.lineWidth = me.brushWidth; + context.strokeStyle = color; + } + }); + }, + _addBrushBarListener:function () { + var me = this; + domUtils.on($G("J_brushBar"), "click", function (e) { + var target = me.getTarget(e), + size = browser.ie ? target.innerText : target.text; + if (!!size) { + me._addBESelect(target); + + context.globalCompositeOperation = "source-over"; + context.lineWidth = parseInt(size); + context.strokeStyle = me.brushColor; + me.brushWidth = context.lineWidth; + } + }); + }, + _addEraserBarListener:function () { + var me = this; + domUtils.on($G("J_eraserBar"), "click", function (e) { + var target = me.getTarget(e), + size = browser.ie ? target.innerText : target.text; + if (!!size) { + me._addBESelect(target); + + context.lineWidth = parseInt(size); + context.globalCompositeOperation = "destination-out"; + context.strokeStyle = "#FFF"; + } + }); + }, + _addAddImgListener:function () { + var file = $G("J_imgTxt"); + if (!window.FileReader) { + $G("J_addImg").style.display = 'none'; + $G("J_removeImg").style.display = 'none'; + $G("J_sacleBoard").style.display = 'none'; + } + domUtils.on(file, "change", function (e) { + var frm = file.parentNode; + addMaskLayer(lang.backgroundUploading); + + var target = e.target || e.srcElement, + reader = new FileReader(); + reader.onload = function(evt){ + var target = evt.target || evt.srcElement; + ue_callback(target.result, 'SUCCESS'); + }; + reader.readAsDataURL(target.files[0]); + frm.reset(); + }); + }, + _addRemoveImgListenter:function () { + var me = this; + domUtils.on($G("J_removeImg"), "click", function () { + $G("J_picBoard").innerHTML = ""; + me.btn2disable("J_removeImg"); + me.btn2disable("J_sacleBoard"); + }); + }, + _addScalePicListenter:function () { + domUtils.on($G("J_sacleBoard"), "click", function () { + var picBoard = $G("J_picBoard"), + scaleCon = $G("J_scaleCon"), + img = picBoard.children[0]; + + if (img) { + if (!scaleCon) { + picBoard.style.cssText = "position:relative;z-index:999;"+picBoard.style.cssText; + img.style.cssText = "position: absolute;top:" + (canvas.height - img.height) / 2 + "px;left:" + (canvas.width - img.width) / 2 + "px;"; + var scale = new ScaleBoy(); + picBoard.appendChild(scale.init()); + scale.startScale(img); + } else { + if (scaleCon.style.visibility == "visible") { + scaleCon.style.visibility = "hidden"; + picBoard.style.position = ""; + picBoard.style.zIndex = ""; + } else { + scaleCon.style.visibility = "visible"; + picBoard.style.cssText += "position:relative;z-index:999"; + } + } + } + }); + }, + _addClearSelectionListenter:function () { + var doc = document; + domUtils.on(doc, 'mousemove', function (e) { + if (browser.ie && browser.version < 11) + doc.selection.clear(); + else + window.getSelection().removeAllRanges(); + }); + }, + _clearSelection:function () { + var list = ["J_operateBar", "J_colorBar", "J_brushBar", "J_eraserBar", "J_picBoard"]; + for (var i = 0, group; group = list[i++];) { + domUtils.unSelectable($G(group)); + } + }, + + _saveOPerate:function (saveNum) { + var me = this; + if (drawStep.length <= saveNum) { + if(drawStepIndex"); + } + scale.innerHTML = arr.join(""); + return scale; + } + + var rect = [ + //[left, top, width, height] + [1, 1, -1, -1], + [0, 1, 0, -1], + [0, 1, 1, -1], + [1, 0, -1, 0], + [0, 0, 1, 0], + [1, 0, -1, 1], + [0, 0, 0, 1], + [0, 0, 1, 1] + ]; + ScaleBoy.prototype = { + init:function () { + _appendStyle(); + var me = this, + scale = me.dom = _getDom(); + + me.scaleMousemove.fp = me; + domUtils.on(scale, 'mousedown', function (e) { + var target = e.target || e.srcElement; + me.start = {x:e.clientX, y:e.clientY}; + if (target.className.indexOf('hand') != -1) { + me.dir = target.className.replace('hand', ''); + } + domUtils.on(document.body, 'mousemove', me.scaleMousemove); + e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; + }); + domUtils.on(document.body, 'mouseup', function (e) { + if (me.start) { + domUtils.un(document.body, 'mousemove', me.scaleMousemove); + if (me.moved) { + me.updateScaledElement({position:{x:scale.style.left, y:scale.style.top}, size:{w:scale.style.width, h:scale.style.height}}); + } + delete me.start; + delete me.moved; + delete me.dir; + } + }); + return scale; + }, + startScale:function (objElement) { + var me = this, Idom = me.dom; + + Idom.style.cssText = 'visibility:visible;top:' + objElement.style.top + ';left:' + objElement.style.left + ';width:' + objElement.offsetWidth + 'px;height:' + objElement.offsetHeight + 'px;'; + me.scalingElement = objElement; + }, + updateScaledElement:function (objStyle) { + var cur = this.scalingElement, + pos = objStyle.position, + size = objStyle.size; + if (pos) { + typeof pos.x != 'undefined' && (cur.style.left = pos.x); + typeof pos.y != 'undefined' && (cur.style.top = pos.y); + } + if (size) { + size.w && (cur.style.width = size.w); + size.h && (cur.style.height = size.h); + } + }, + updateStyleByDir:function (dir, offset) { + var me = this, + dom = me.dom, tmp; + + rect['def'] = [1, 1, 0, 0]; + if (rect[dir][0] != 0) { + tmp = parseInt(dom.style.left) + offset.x; + dom.style.left = me._validScaledProp('left', tmp) + 'px'; + } + if (rect[dir][1] != 0) { + tmp = parseInt(dom.style.top) + offset.y; + dom.style.top = me._validScaledProp('top', tmp) + 'px'; + } + if (rect[dir][2] != 0) { + tmp = dom.clientWidth + rect[dir][2] * offset.x; + dom.style.width = me._validScaledProp('width', tmp) + 'px'; + } + if (rect[dir][3] != 0) { + tmp = dom.clientHeight + rect[dir][3] * offset.y; + dom.style.height = me._validScaledProp('height', tmp) + 'px'; + } + if (dir === 'def') { + me.updateScaledElement({position:{x:dom.style.left, y:dom.style.top}}); + } + }, + scaleMousemove:function (e) { + var me = arguments.callee.fp, + start = me.start, + dir = me.dir || 'def', + offset = {x:e.clientX - start.x, y:e.clientY - start.y}; + + me.updateStyleByDir(dir, offset); + arguments.callee.fp.start = {x:e.clientX, y:e.clientY}; + arguments.callee.fp.moved = 1; + }, + _validScaledProp:function (prop, value) { + var ele = this.dom, + wrap = $G("J_picBoard"); + + value = isNaN(value) ? 0 : value; + switch (prop) { + case 'left': + return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value; + case 'top': + return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value; + case 'width': + return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value; + case 'height': + return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value; + } + } + }; +})(); + +//后台回调 +function ue_callback(url, state) { + var doc = document, + picBorard = $G("J_picBoard"), + img = doc.createElement("img"); + + //图片缩放 + function scale(img, max, oWidth, oHeight) { + var width = 0, height = 0, percent, ow = img.width || oWidth, oh = img.height || oHeight; + if (ow > max || oh > max) { + if (ow >= oh) { + if (width = ow - max) { + percent = (width / ow).toFixed(2); + img.height = oh - oh * percent; + img.width = max; + } + } else { + if (height = oh - max) { + percent = (height / oh).toFixed(2); + img.width = ow - ow * percent; + img.height = max; + } + } + } + } + + //移除遮罩层 + removeMaskLayer(); + //状态响应 + if (state == "SUCCESS") { + picBorard.innerHTML = ""; + img.onload = function () { + scale(this, 300); + picBorard.appendChild(img); + + var obj = new scrawl(); + obj.btn2Highlight("J_removeImg"); + //trace 2457 + obj.btn2Highlight("J_sacleBoard"); + }; + img.src = url; + } else { + alert(state); + } +} +//去掉遮罩层 +function removeMaskLayer() { + var maskLayer = $G("J_maskLayer"); + maskLayer.className = "maskLayerNull"; + maskLayer.innerHTML = ""; + dialog.buttons[0].setDisabled(false); +} +//添加遮罩层 +function addMaskLayer(html) { + var maskLayer = $G("J_maskLayer"); + dialog.buttons[0].setDisabled(true); + maskLayer.className = "maskLayer"; + maskLayer.innerHTML = html; +} +//执行确认按钮方法 +function exec(scrawlObj) { + if (scrawlObj.isScrawl) { + addMaskLayer(lang.scrawlUpLoading); + var base64 = scrawlObj.getCanvasData(); + if (!!base64) { + var options = { + timeout:100000, + headers: editor.options.serverHeaders || {}, + onsuccess:function (xhr) { + if (!scrawlObj.isCancelScrawl) { + var responseObj; + responseObj = eval("(" + xhr.responseText + ")"); + if (responseObj.state === "SUCCESS") { + var imgObj = {}, + url = editor.options.scrawlUrlPrefix + responseObj.url; + imgObj.src = url; + imgObj._src = url; + imgObj.alt = responseObj.original || ''; + editor.execCommand("insertImage", imgObj); + dialog.close(); + // 触发上传涂鸦事件 + editor.fireEvent("uploadsuccess", { + res: responseObj, + type: 'scrawl' + }); + } else { + alert(responseObj.state); + } + + } + }, + onerror:function () { + alert(lang.imageError); + dialog.close(); + } + }; + options[editor.getOpt('scrawlFieldName')] = base64; + + var actionUrl = editor.getActionUrl(editor.getOpt('scrawlActionName')), + params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + params); + ajax.request(url, options); + } + } else { + addMaskLayer(lang.noScarwl + "   "); + } +} + diff --git a/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.html b/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.html new file mode 100644 index 0000000..8efae07 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.html @@ -0,0 +1,117 @@ + + + + + + + + + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + +
    :
    + +
    + + +
    +   +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    :
    :
    + +
    + + + + +
    +   +
    + +
    +
    +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.js b/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.js new file mode 100644 index 0000000..02fa46c --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/searchreplace/searchreplace.js @@ -0,0 +1,170 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午12:29 + * To change this template use File | Settings | File Templates. + */ + +//清空上次查选的痕迹 +editor.firstForSR = 0; +editor.currentRangeForSR = null; +//给tab注册切换事件 +/** + * tab点击处理事件 + * @param tabHeads + * @param tabBodys + * @param obj + */ +function clickHandler( tabHeads,tabBodys,obj ) { + //head样式更改 + for ( var k = 0, len = tabHeads.length; k < len; k++ ) { + tabHeads[k].className = ""; + } + obj.className = "focus"; + //body显隐 + var tabSrc = obj.getAttribute( "tabSrc" ); + for ( var j = 0, length = tabBodys.length; j < length; j++ ) { + var body = tabBodys[j], + id = body.getAttribute( "id" ); + if ( id != tabSrc ) { + body.style.zIndex = 1; + } else { + body.style.zIndex = 200; + } + } + +} + +/** + * TAB切换 + * @param tabParentId tab的父节点ID或者对象本身 + */ +function switchTab( tabParentId ) { + var tabElements = $G( tabParentId ).children, + tabHeads = tabElements[0].children, + tabBodys = tabElements[1].children; + + for ( var i = 0, length = tabHeads.length; i < length; i++ ) { + var head = tabHeads[i]; + if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head ); + head.onclick = function () { + clickHandler(tabHeads,tabBodys,this); + } + } +} +$G('searchtab').onmousedown = function(){ + $G('search-msg').innerHTML = ''; + $G('replace-msg').innerHTML = '' +} +//是否区分大小写 +function getMatchCase(id) { + return $G(id).checked ? true : false; +} +//查找 +$G("nextFindBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase") + }; + if (!frCommond(obj)) { + var bk = editor.selection.getRange().createBookmark(); + $G('search-msg').innerHTML = lang.getEnd; + editor.selection.getRange().moveToBookmark(bk).select(); + + + } +}; +$G("nextReplaceBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt1").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase1") + }; + frCommond(obj); +}; +$G("preFindBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:-1, + casesensitive:getMatchCase("matchCase") + }; + if (!frCommond(obj)) { + $G('search-msg').innerHTML = lang.getStart; + } +}; +$G("preReplaceBtn").onclick = function (txt, dir, mcase) { + var findtxt = $G("findtxt1").value, obj; + if (!findtxt) { + return false; + } + obj = { + searchStr:findtxt, + dir:-1, + casesensitive:getMatchCase("matchCase1") + }; + frCommond(obj); +}; +//替换 +$G("repalceBtn").onclick = function () { + editor.trigger('clearLastSearchResult'); + var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj, + replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, ""); + if (!findtxt) { + return false; + } + if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) { + return false; + } + obj = { + searchStr:findtxt, + dir:1, + casesensitive:getMatchCase("matchCase1"), + replaceStr:replacetxt + }; + frCommond(obj); +}; +//全部替换 +$G("repalceAllBtn").onclick = function () { + var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj, + replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, ""); + if (!findtxt) { + return false; + } + if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) { + return false; + } + obj = { + searchStr:findtxt, + casesensitive:getMatchCase("matchCase1"), + replaceStr:replacetxt, + all:true + }; + var num = frCommond(obj); + if (num) { + $G('replace-msg').innerHTML = lang.countMsg.replace("{#count}", num); + } +}; +//执行 +var frCommond = function (obj) { + return editor.execCommand("searchreplace", obj); +}; +switchTab("searchtab"); + + +dialog.onclose = function(){ + editor.trigger('clearLastSearchResult') +}; \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/spechars/spechars.html b/public/static/plugs/ueditor/dialogs/spechars/spechars.html new file mode 100644 index 0000000..9eb952d --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/spechars/spechars.html @@ -0,0 +1,21 @@ + + + + + + + + + +
    +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/spechars/spechars.js b/public/static/plugs/ueditor/dialogs/spechars/spechars.js new file mode 100644 index 0000000..f4c155e --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/spechars/spechars.js @@ -0,0 +1,57 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午1:09 + * To change this template use File | Settings | File Templates. + */ +var charsContent = [ + { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")}, + { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")}, + { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")}, + { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")}, + { name:"xlzm", title:lang.xlzm, content:toArray("Α,Β,Γ,Δ,Ε,Ζ,Η,Θ,Ι,Κ,Λ,Μ,Ν,Ξ,Ο,Π,Ρ,Σ,Τ,Υ,Φ,Χ,Ψ,Ω,α,β,γ,δ,ε,ζ,η,θ,ι,κ,λ,μ,ν,ξ,ο,π,ρ,σ,τ,υ,φ,χ,ψ,ω")}, + { name:"ewzm", title:lang.ewzm, content:toArray("А,Б,В,Г,Д,Е,Ё,Ж,З,И,Й,К,Л,М,Н,О,П,Р,С,Т,У,Ф,Х,Ц,Ч,Ш,Щ,Ъ,Ы,Ь,Э,Ю,Я,а,б,в,г,д,е,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ъ,ы,ь,э,ю,я")}, + { name:"pyzm", title:lang.pyzm, content:toArray("ā,á,ǎ,à,ē,é,ě,è,ī,í,ǐ,ì,ō,ó,ǒ,ò,ū,ú,ǔ,ù,ǖ,ǘ,ǚ,ǜ,ü")}, + { name:"yyyb", title:lang.yyyb, content:toArray("i:,i,e,æ,ʌ,ə:,ə,u:,u,ɔ:,ɔ,a:,ei,ai,ɔi,əu,au,iə,εə,uə,p,t,k,b,d,g,f,s,ʃ,θ,h,v,z,ʒ,ð,tʃ,tr,ts,dʒ,dr,dz,m,n,ŋ,l,r,w,j,")}, + { name:"zyzf", title:lang.zyzf, content:toArray("ㄅ,ㄆ,ㄇ,ㄈ,ㄉ,ㄊ,ㄋ,ㄌ,ㄍ,ㄎ,ㄏ,ㄐ,ㄑ,ㄒ,ㄓ,ㄔ,ㄕ,ㄖ,ㄗ,ㄘ,ㄙ,ㄚ,ㄛ,ㄜ,ㄝ,ㄞ,ㄟ,ㄠ,ㄡ,ㄢ,ㄣ,ㄤ,ㄥ,ㄦ,ㄧ,ㄨ")} +]; +(function createTab(content) { + for (var i = 0, ci; ci = content[i++];) { + var span = document.createElement("span"); + span.setAttribute("tabSrc", ci.name); + span.innerHTML = ci.title; + if (i == 1)span.className = "focus"; + domUtils.on(span, "click", function () { + var tmps = $G("tabHeads").children; + for (var k = 0, sk; sk = tmps[k++];) { + sk.className = ""; + } + tmps = $G("tabBodys").children; + for (var k = 0, sk; sk = tmps[k++];) { + sk.style.display = "none"; + } + this.className = "focus"; + $G(this.getAttribute("tabSrc")).style.display = ""; + }); + $G("tabHeads").appendChild(span); + domUtils.insertAfter(span, document.createTextNode("\n")); + var div = document.createElement("div"); + div.id = ci.name; + div.style.display = (i == 1) ? "" : "none"; + var cons = ci.content; + for (var j = 0, con; con = cons[j++];) { + var charSpan = document.createElement("span"); + charSpan.innerHTML = con; + domUtils.on(charSpan, "click", function () { + editor.execCommand("insertHTML", this.innerHTML); + dialog.close(); + }); + div.appendChild(charSpan); + } + $G("tabBodys").appendChild(div); + } +})(charsContent); +function toArray(str) { + return str.split(","); +} diff --git a/public/static/plugs/ueditor/dialogs/table/dragicon.png b/public/static/plugs/ueditor/dialogs/table/dragicon.png new file mode 100644 index 0000000..f26203b Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/table/dragicon.png differ diff --git a/public/static/plugs/ueditor/dialogs/table/edittable.css b/public/static/plugs/ueditor/dialogs/table/edittable.css new file mode 100644 index 0000000..c6f9396 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/table/edittable.css @@ -0,0 +1,84 @@ +body{ + overflow: hidden; + width: 540px; +} +.wrapper { + margin: 10px auto 0; + font-size: 12px; + overflow: hidden; + width: 520px; + height: 315px; +} + +.clear { + clear: both; +} + +.wrapper .left { + float: left; + margin-left: 10px;; +} + +.wrapper .right { + float: right; + border-left: 2px dotted #EDEDED; + padding-left: 15px; +} + +.section { + margin-bottom: 15px; + width: 240px; + overflow: hidden; +} + +.section h3 { + font-weight: bold; + padding: 5px 0; + margin-bottom: 10px; + border-bottom: 1px solid #EDEDED; + font-size: 12px; +} + +.section ul { + list-style: none; + overflow: hidden; + clear: both; + +} + +.section li { + float: left; + width: 120px;; +} + +.section .tone { + width: 80px;; +} + +.section .preview { + width: 220px; +} + +.section .preview table { + text-align: center; + vertical-align: middle; + color: #666; +} + +.section .preview caption { + font-weight: bold; +} + +.section .preview td { + border-width: 1px; + border-style: solid; + height: 22px; +} + +.section .preview th { + border-style: solid; + border-color: #DDD; + border-width: 2px 1px 1px 1px; + height: 22px; + background-color: #F7F7F7; +} \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/table/edittable.html b/public/static/plugs/ueditor/dialogs/table/edittable.html new file mode 100644 index 0000000..6e596ce --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/table/edittable.html @@ -0,0 +1,64 @@ + + + + + + + + +
    +
    +
    +

    +
      +
    • + +
    • +
    • + +
    • +
    +
      +
    • + +
    • +
    • + +
    • +
    +
    +
    +
    +

    +
      +
    • + +
    • +
    • + +
    • +
    +
    +
    +
    +

    +
      +
    • + + +
    • +
    +
    +
    +
    +
    +
    +

    +
    +
    +
    +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/table/edittable.js b/public/static/plugs/ueditor/dialogs/table/edittable.js new file mode 100644 index 0000000..11dbee7 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/table/edittable.js @@ -0,0 +1,237 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-12-19 + * Time: 下午4:55 + * To change this template use File | Settings | File Templates. + */ +(function () { + var title = $G("J_title"), + titleCol = $G("J_titleCol"), + caption = $G("J_caption"), + sorttable = $G("J_sorttable"), + autoSizeContent = $G("J_autoSizeContent"), + autoSizePage = $G("J_autoSizePage"), + tone = $G("J_tone"), + me, + preview = $G("J_preview"); + + var editTable = function () { + me = this; + me.init(); + }; + editTable.prototype = { + init:function () { + var colorPiker = new UE.ui.ColorPicker({ + editor:editor + }), + colorPop = new UE.ui.Popup({ + editor:editor, + content:colorPiker + }); + + title.checked = editor.queryCommandState("inserttitle") == -1; + titleCol.checked = editor.queryCommandState("inserttitlecol") == -1; + caption.checked = editor.queryCommandState("insertcaption") == -1; + sorttable.checked = editor.queryCommandState("enablesort") == 1; + + var enablesortState = editor.queryCommandState("enablesort"), + disablesortState = editor.queryCommandState("disablesort"); + + sorttable.checked = !!(enablesortState < 0 && disablesortState >=0); + sorttable.disabled = !!(enablesortState < 0 && disablesortState < 0); + sorttable.title = enablesortState < 0 && disablesortState < 0 ? lang.errorMsg:''; + + me.createTable(title.checked, titleCol.checked, caption.checked); + me.setAutoSize(); + me.setColor(me.getColor()); + + domUtils.on(title, "click", me.titleHanler); + domUtils.on(titleCol, "click", me.titleColHanler); + domUtils.on(caption, "click", me.captionHanler); + domUtils.on(sorttable, "click", me.sorttableHanler); + domUtils.on(autoSizeContent, "click", me.autoSizeContentHanler); + domUtils.on(autoSizePage, "click", me.autoSizePageHanler); + + domUtils.on(tone, "click", function () { + colorPop.showAnchor(tone); + }); + domUtils.on(document, 'mousedown', function () { + colorPop.hide(); + }); + colorPiker.addListener("pickcolor", function () { + me.setColor(arguments[1]); + colorPop.hide(); + }); + colorPiker.addListener("picknocolor", function () { + me.setColor(""); + colorPop.hide(); + }); + }, + + createTable:function (hasTitle, hasTitleCol, hasCaption) { + var arr = [], + sortSpan = '^'; + arr.push(""); + if (hasCaption) { + arr.push("") + } + if (hasTitle) { + arr.push(""); + if(hasTitleCol) { arr.push(""); } + for (var j = 0; j < 5; j++) { + arr.push(""); + } + arr.push(""); + } + for (var i = 0; i < 6; i++) { + arr.push(""); + if(hasTitleCol) { arr.push("") } + for (var k = 0; k < 5; k++) { + arr.push("") + } + arr.push(""); + } + arr.push("
    " + lang.captionName + "
    " + lang.titleName + "" + lang.titleName + "
    " + lang.titleName + "" + lang.cellsName + "
    "); + preview.innerHTML = arr.join(""); + this.updateSortSpan(); + }, + titleHanler:function () { + var example = $G("J_example"), + frg=document.createDocumentFragment(), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colCount = example.rows[0].children.length; + + if (title.checked) { + example.insertRow(0); + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + frg.appendChild(node); + } + example.rows[0].appendChild(frg); + + } else { + domUtils.remove(example.rows[0]); + } + me.setColor(color); + me.updateSortSpan(); + }, + titleColHanler:function () { + var example = $G("J_example"), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colArr = example.rows, + colCount = colArr.length; + + if (titleCol.checked) { + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + colArr[i].insertBefore(node, colArr[i].children[0]); + } + } else { + for (var i = 0; i < colCount; i++) { + domUtils.remove(colArr[i].children[0]); + } + } + me.setColor(color); + me.updateSortSpan(); + }, + captionHanler:function () { + var example = $G("J_example"); + if (caption.checked) { + var row = document.createElement('caption'); + row.innerHTML = lang.captionName; + example.insertBefore(row, example.firstChild); + } else { + domUtils.remove(domUtils.getElementsByTagName(example, 'caption')[0]); + } + }, + sorttableHanler:function(){ + me.updateSortSpan(); + }, + autoSizeContentHanler:function () { + var example = $G("J_example"); + example.removeAttribute("width"); + }, + autoSizePageHanler:function () { + var example = $G("J_example"); + var tds = example.getElementsByTagName(example, "td"); + utils.each(tds, function (td) { + td.removeAttribute("width"); + }); + example.setAttribute('width', '100%'); + }, + updateSortSpan: function(){ + var example = $G("J_example"), + row = example.rows[0]; + + var spans = domUtils.getElementsByTagName(example,"span"); + utils.each(spans,function(span){ + span.parentNode.removeChild(span); + }); + if (sorttable.checked) { + utils.each(row.cells, function(cell, i){ + var span = document.createElement("span"); + span.innerHTML = "^"; + cell.appendChild(span); + }); + } + }, + getColor:function () { + var start = editor.selection.getStart(), color, + cell = domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + color = cell && domUtils.getComputedStyle(cell, "border-color"); + if (!color) color = "#DDDDDD"; + return color; + }, + setColor:function (color) { + var example = $G("J_example"), + arr = domUtils.getElementsByTagName(example, "td").concat( + domUtils.getElementsByTagName(example, "th"), + domUtils.getElementsByTagName(example, "caption") + ); + + tone.value = color; + utils.each(arr, function (node) { + node.style.borderColor = color; + }); + + }, + setAutoSize:function () { + var me = this; + autoSizePage.checked = true; + me.autoSizePageHanler(); + } + }; + + new editTable; + + dialog.onok = function () { + editor.__hasEnterExecCommand = true; + + var checks = { + title:"inserttitle deletetitle", + titleCol:"inserttitlecol deletetitlecol", + caption:"insertcaption deletecaption", + sorttable:"enablesort disablesort" + }; + editor.fireEvent('saveScene'); + for(var i in checks){ + var cmds = checks[i].split(" "), + input = $G("J_" + i); + if(input["checked"]){ + editor.queryCommandState(cmds[0])!=-1 &&editor.execCommand(cmds[0]); + }else{ + editor.queryCommandState(cmds[1])!=-1 &&editor.execCommand(cmds[1]); + } + } + + editor.execCommand("edittable", tone.value); + autoSizeContent.checked ?editor.execCommand('adaptbytext') : ""; + autoSizePage.checked ? editor.execCommand("adaptbywindow") : ""; + editor.fireEvent('saveScene'); + + editor.__hasEnterExecCommand = false; + }; +})(); \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/table/edittd.html b/public/static/plugs/ueditor/dialogs/table/edittd.html new file mode 100644 index 0000000..70a3807 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/table/edittd.html @@ -0,0 +1,61 @@ + + + + + + + + +
    + + +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/table/edittip.html b/public/static/plugs/ueditor/dialogs/table/edittip.html new file mode 100644 index 0000000..f9080bd --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/table/edittip.html @@ -0,0 +1,33 @@ + + + + 表格删除提示 + + + + +
    +
    + +
    +
    + +
    +
    + + + diff --git a/public/static/plugs/ueditor/dialogs/template/config.js b/public/static/plugs/ueditor/dialogs/template/config.js new file mode 100644 index 0000000..417b8f7 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/template/config.js @@ -0,0 +1,42 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-8-8 + * Time: 下午2:00 + * To change this template use File | Settings | File Templates. + */ +var templates = [ + { + "pre":"pre0.png", + 'title':lang.blank, + 'preHtml':'

     欢迎使用UEditor!

    ', + "html":'

    欢迎使用UEditor!

    ' + + }, + { + "pre":"pre1.png", + 'title':lang.blog, + 'preHtml':'

    深入理解Range

    UEditor二次开发

    什么是Range

    对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。


    Range能干什么

    在“开始”选项卡上,通过从快速样式库中为所选文本选择一种外观,您可以方便地更改文档中所选文本的格式。

    ', + "html":'

    [键入文档标题]

    [键入文档副标题]

    [标题 1]

    对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。 您可以使用这些库来插入表格、页眉、页脚、列表、封面以及其他文档构建基块。 您创建的图片、图表或关系图也将与当前的文档外观协调一致。

    [标题 2]

    在“开始”选项卡上,通过从快速样式库中为所选文本选择一种外观,您可以方便地更改文档中所选文本的格式。 您还可以使用“开始”选项卡上的其他控件来直接设置文本格式。大多数控件都允许您选择是使用当前主题外观,还是使用某种直接指定的格式。

    [标题 3]

    对于“插入”选项卡上的库,在设计时都充分考虑了其中的项与文档整体外观的协调性。 您可以使用这些库来插入表格、页眉、页脚、列表、封面以及其他文档构建基块。 您创建的图片、图表或关系图也将与当前的文档外观协调一致。


    ' + + }, + { + "pre":"pre2.png", + 'title':lang.resume, + 'preHtml':'

    WEB前端开发简历


    联系电话:[键入您的电话]

    电子邮件:[键入您的电子邮件地址]

    家庭住址:[键入您的地址]

    目标职位

    WEB前端研发工程师

    学历

    1. [起止时间] [学校名称] [所学专业] [所获学位]

    工作经验


    ', + "html":'

    [此处键入简历标题]


    【此处插入照片】


    联系电话:[键入您的电话]


    电子邮件:[键入您的电子邮件地址]


    家庭住址:[键入您的地址]


    目标职位

    [此处键入您的期望职位]

    学历

    1. [键入起止时间] [键入学校名称] [键入所学专业] [键入所获学位]

    2. [键入起止时间] [键入学校名称] [键入所学专业] [键入所获学位]

    工作经验

    1. [键入起止时间] [键入公司名称] [键入职位名称]

      1. [键入负责项目] [键入项目简介]

      2. [键入负责项目] [键入项目简介]

    2. [键入起止时间] [键入公司名称] [键入职位名称]

      1. [键入负责项目] [键入项目简介]

    掌握技能

     [这里可以键入您所掌握的技能]

    ' + + }, + { + "pre":"pre3.png", + 'title':lang.richText, + 'preHtml':'

    [此处键入文章标题]

    图文混排方法

    图片居左,文字围绕图片排版

    方法:在文字前面插入图片,设置居左对齐,然后即可在右边输入多行文


    还有没有什么其他的环绕方式呢?这里是居右环绕


    欢迎大家多多尝试,为UEditor提供更多高质量模板!

    ', + "html":'


    [此处键入文章标题]

    图文混排方法

    1. 图片居左,文字围绕图片排版

    方法:在文字前面插入图片,设置居左对齐,然后即可在右边输入多行文本


    2. 图片居右,文字围绕图片排版

    方法:在文字前面插入图片,设置居右对齐,然后即可在左边输入多行文本


    3. 图片居中环绕排版

    方法:亲,这个真心没有办法。。。



    还有没有什么其他的环绕方式呢?这里是居右环绕


    欢迎大家多多尝试,为UEditor提供更多高质量模板!


    占位


    占位


    占位


    占位


    占位



    ' + }, + { + "pre":"pre4.png", + 'title':lang.sciPapers, + 'preHtml':'

    [键入文章标题]

    摘要:这里可以输入很长很长很长很长很长很长很长很长很差的摘要

    标题 1

    这里可以输入很多内容,可以图文混排,可以有列表等。

    标题 2

    1. 列表 1

    2. 列表 2

      1. 多级列表 1

      2. 多级列表 2

    3. 列表 3

    标题 3

    来个文字图文混排的


    ', + 'html':'

    [键入文章标题]

    摘要:这里可以输入很长很长很长很长很长很长很长很长很差的摘要

    标题 1

    这里可以输入很多内容,可以图文混排,可以有列表等。

    标题 2

    来个列表瞅瞅:

    1. 列表 1

    2. 列表 2

      1. 多级列表 1

      2. 多级列表 2

    3. 列表 3

    标题 3

    来个文字图文混排的

    这里可以多行

    右边是图片

    绝对没有问题的,不信你也可以试试看


    ' + } +]; \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/template/images/bg.gif b/public/static/plugs/ueditor/dialogs/template/images/bg.gif new file mode 100644 index 0000000..8c1d10a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/bg.gif differ diff --git a/public/static/plugs/ueditor/dialogs/template/images/pre0.png b/public/static/plugs/ueditor/dialogs/template/images/pre0.png new file mode 100644 index 0000000..8f3c16a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/pre0.png differ diff --git a/public/static/plugs/ueditor/dialogs/template/images/pre1.png b/public/static/plugs/ueditor/dialogs/template/images/pre1.png new file mode 100644 index 0000000..5a03f96 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/pre1.png differ diff --git a/public/static/plugs/ueditor/dialogs/template/images/pre2.png b/public/static/plugs/ueditor/dialogs/template/images/pre2.png new file mode 100644 index 0000000..5a55672 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/pre2.png differ diff --git a/public/static/plugs/ueditor/dialogs/template/images/pre3.png b/public/static/plugs/ueditor/dialogs/template/images/pre3.png new file mode 100644 index 0000000..d852d29 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/pre3.png differ diff --git a/public/static/plugs/ueditor/dialogs/template/images/pre4.png b/public/static/plugs/ueditor/dialogs/template/images/pre4.png new file mode 100644 index 0000000..0d7bc72 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/template/images/pre4.png differ diff --git a/public/static/plugs/ueditor/dialogs/template/template.css b/public/static/plugs/ueditor/dialogs/template/template.css new file mode 100644 index 0000000..6c1608d --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/template/template.css @@ -0,0 +1,18 @@ +.wrap{ padding: 5px;font-size: 14px;} +.left{width:425px;float: left;} +.right{width:160px;border: 1px solid #ccc;float: right;padding: 5px;margin-right: 5px;} +.right .pre{height: 332px;overflow-y: auto;} +.right .preitem{border: white 1px solid;margin: 5px 0;padding: 2px 0;} +.right .preitem:hover{background-color: lemonChiffon;cursor: pointer;border: #ccc 1px solid;} +.right .preitem img{display: block;margin: 0 auto;width:100px;} +.clear{clear: both;} +.top{height:26px;line-height: 26px;padding: 5px;} +.bottom{height:320px;width:100%;margin: 0 auto;} +.transparent{ background: url("images/bg.gif") repeat;} +.bottom table tr td{border:1px dashed #ccc;} +#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;} +.border_style1{padding:2px;border: 1px solid #ccc;border-radius: 5px;box-shadow:2px 2px 5px #d3d6da;} +p{margin: 5px 0} +table{clear:both;margin-bottom:10px;border-collapse:collapse;word-break:break-all;} +li{clear:both} +ol{padding-left:40px; } \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/template/template.html b/public/static/plugs/ueditor/dialogs/template/template.html new file mode 100644 index 0000000..9684419 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/template/template.html @@ -0,0 +1,26 @@ + + + + + + + + + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + diff --git a/public/static/plugs/ueditor/dialogs/template/template.js b/public/static/plugs/ueditor/dialogs/template/template.js new file mode 100644 index 0000000..80a334b --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/template/template.js @@ -0,0 +1,53 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-8-8 + * Time: 下午2:09 + * To change this template use File | Settings | File Templates. + */ +(function () { + var me = editor, + preview = $G( "preview" ), + preitem = $G( "preitem" ), + tmps = templates, + currentTmp; + var initPre = function () { + var str = ""; + for ( var i = 0, tmp; tmp = tmps[i++]; ) { + str += '
    '; + } + preitem.innerHTML = str; + }; + var pre = function ( n ) { + var tmp = tmps[n - 1]; + currentTmp = tmp; + clearItem(); + domUtils.setStyles( preitem.childNodes[n - 1], { + "background-color":"lemonChiffon", + "border":"#ccc 1px solid" + } ); + preview.innerHTML = tmp.preHtml ? tmp.preHtml : ""; + }; + var clearItem = function () { + var items = preitem.children; + for ( var i = 0, item; item = items[i++]; ) { + domUtils.setStyles( item, { + "background-color":"", + "border":"white 1px solid" + } ); + } + }; + dialog.onok = function () { + if ( !$G( "issave" ).checked ){ + me.execCommand( "cleardoc" ); + } + var obj = { + html:currentTmp && currentTmp.html + }; + me.execCommand( "template", obj ); + }; + initPre(); + window.pre = pre; + pre(2) + +})(); \ No newline at end of file diff --git a/public/static/plugs/ueditor/dialogs/video/images/bg.png b/public/static/plugs/ueditor/dialogs/video/images/bg.png new file mode 100644 index 0000000..580be0a Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/bg.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/center_focus.jpg b/public/static/plugs/ueditor/dialogs/video/images/center_focus.jpg new file mode 100644 index 0000000..262b029 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/center_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/file-icons.gif b/public/static/plugs/ueditor/dialogs/video/images/file-icons.gif new file mode 100644 index 0000000..d8c02c2 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/file-icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/file-icons.png b/public/static/plugs/ueditor/dialogs/video/images/file-icons.png new file mode 100644 index 0000000..3ff82c8 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/file-icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/icons.gif b/public/static/plugs/ueditor/dialogs/video/images/icons.gif new file mode 100644 index 0000000..78459de Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/icons.gif differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/icons.png b/public/static/plugs/ueditor/dialogs/video/images/icons.png new file mode 100644 index 0000000..12e4700 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/icons.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/image.png b/public/static/plugs/ueditor/dialogs/video/images/image.png new file mode 100644 index 0000000..19699f6 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/image.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/left_focus.jpg b/public/static/plugs/ueditor/dialogs/video/images/left_focus.jpg new file mode 100644 index 0000000..7886d27 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/left_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/none_focus.jpg b/public/static/plugs/ueditor/dialogs/video/images/none_focus.jpg new file mode 100644 index 0000000..7c768dc Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/none_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/progress.png b/public/static/plugs/ueditor/dialogs/video/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/progress.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/right_focus.jpg b/public/static/plugs/ueditor/dialogs/video/images/right_focus.jpg new file mode 100644 index 0000000..173e10d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/right_focus.jpg differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/success.gif b/public/static/plugs/ueditor/dialogs/video/images/success.gif new file mode 100644 index 0000000..8d4f311 Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/success.gif differ diff --git a/public/static/plugs/ueditor/dialogs/video/images/success.png b/public/static/plugs/ueditor/dialogs/video/images/success.png new file mode 100644 index 0000000..94f968d Binary files /dev/null and b/public/static/plugs/ueditor/dialogs/video/images/success.png differ diff --git a/public/static/plugs/ueditor/dialogs/video/video.css b/public/static/plugs/ueditor/dialogs/video/video.css new file mode 100644 index 0000000..e61ee80 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/video/video.css @@ -0,0 +1,650 @@ +@charset "utf-8"; +.wrapper{ width: 570px;_width:575px;margin: 10px auto; zoom:1;position: relative} +.tabbody{height: 355px;} +.tabbody .panel { + position: absolute; + width: 0; + height: 0; + background: #fff; + overflow: hidden; + display: none; +} +.tabbody .panel.focus { + width: 100%; + height: 355px; + display: block; +} + +.tabbody .panel table td{vertical-align: middle;} +#videoUrl { + width: 380px; + height: 26px; + line-height: 26px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; + outline: none; + border-radius:3px; + padding:0 5px; +} +#videoSelect{ + width: 100px; + display: inline-block; + background: #FFF; + border: 1px solid #EEE; + line-height: 26px; + text-align: center; + color: #333; + text-decoration: none; + border-radius: 3px; + vertical-align: middle; +} +#videoSearchTxt{margin-left:15px;background: #FFF;width:200px;height:21px;line-height:21px;border: 1px solid #d7d7d7;} +#searchList{width: 570px;overflow: auto;zoom:1;height: 270px;} +#searchList div{float: left;width: 120px;height: 135px;margin: 5px 15px;} +#searchList img{margin: 2px 8px;cursor: pointer;border: 2px solid #fff} /*不用缩略图*/ +#searchList p{margin-left: 10px;} +#videoType{ + width: 65px; + height: 23px; + line-height: 22px; + border: 1px solid #d7d7d7; +} +#videoSearchBtn,#videoSearchReset{ + /*width: 80px;*/ + height: 25px; + line-height: 25px; + background: #eee; + border: 1px solid #d7d7d7; + cursor: pointer; + padding: 0 5px; +} + + + +#preview{position: relative;width: 420px;padding:0;overflow: hidden; margin-left: 10px; _margin-left:5px; height: 280px;background-color: #ddd;float: left} +#preview .previewMsg {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;background-color: #666;} +#preview .previewMsg span{display:block;margin: 125px auto 0 auto;text-align:center;font-size:18px;color:#fff;} +#preview .previewVideo {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;} +.edui-video-wrapper fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} + +#videoInfo {width: 120px;float: left;margin-left: 10px;_margin-left:7px;} +fieldset{ + border: 1px solid #ddd; + padding-left: 5px; + margin-bottom: 20px; + padding-bottom: 5px; + width: 115px; +} +fieldset legend{font-weight: bold;} +fieldset p{line-height: 30px;} +fieldset input.txt{ + width: 65px; + height: 21px; + line-height: 21px; + margin: 8px 5px; + background: #FFF; + border: 1px solid #d7d7d7; +} +label.url{font-weight: bold;margin-left: 5px;} +#videoFloat div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#videoFloat .focus{opacity: 1;filter: alpha(opacity = 100)} +span.view{display: inline-block;width: 30px;float: right;cursor: pointer;color: blue} + + + + +/* upload video */ +.tabbody #upload.panel { + width: 0; + height: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); + background: #fff; + display: block; +} +.tabbody #upload.panel.focus { + width: 100%; + height: 335px; + display: block; + clip: auto; +} +#upload_alignment div{cursor:pointer;opacity: 0.5;filter: alpha(opacity = 50);margin:9px;_margin:5px;width:38px;height:36px;float:left;} +#upload_alignment .focus{opacity: 1;filter: alpha(opacity = 100)} +#upload_left { width:427px; float:left; } +#upload_left .controller { height: 30px; clear: both; } +#uploadVideoInfo{margin-top:10px;float:right;padding-right:8px;} + +#upload .queueList { + margin: 0; +} + +#upload p { + margin: 0; +} + +.element-invisible { + width: 0 !important; + height: 0 !important; + border: 0; + padding: 0; + margin: 0; + overflow: hidden; + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} + +#upload .placeholder { + margin: 10px; + margin-right:0; + border: 2px dashed #e6e6e6; + *border: 0px dashed #e6e6e6; + height: 161px; + padding-top: 150px; + text-align: center; + width: 97%; + float: left; + background: url(./images/image.png) center 70px no-repeat; + color: #cccccc; + font-size: 18px; + position: relative; + top:0; + *margin-left: 0; + *left: 10px; +} + +#upload .placeholder .webuploader-pick { + font-size: 18px; + background: #00b7ee; + border-radius: 3px; + line-height: 44px; + padding: 0 30px; + *width: 120px; + color: #fff; + display: inline-block; + margin: 0 auto 20px auto; + cursor: pointer; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); +} + +#upload .placeholder .webuploader-pick-hover { + background: #00a2d4; +} + + +#filePickerContainer { + text-align: center; +} + +#upload .placeholder .flashTip { + color: #666666; + font-size: 12px; + position: absolute; + width: 100%; + text-align: center; + bottom: 20px; +} + +#upload .placeholder .flashTip a { + color: #0785d1; + text-decoration: none; +} + +#upload .placeholder .flashTip a:hover { + text-decoration: underline; +} + +#upload .placeholder.webuploader-dnd-over { + border-color: #999999; +} + +#upload .filelist { + list-style: none; + margin: 0; + padding: 0; + overflow-x: hidden; + overflow-y: auto; + position: relative; + height: 285px; +} + +#upload .filelist:after { + content: ''; + display: block; + width: 0; + height: 0; + overflow: hidden; + clear: both; +} + +#upload .filelist li { + width: 113px; + height: 113px; + background: url(./images/bg.png); + text-align: center; + margin: 15px 0 0 20px; + *margin: 15px 0 0 15px; + position: relative; + display: block; + float: left; + overflow: hidden; + font-size: 12px; +} + +#upload .filelist li p.log { + position: relative; + top: -45px; +} + +#upload .filelist li p.title { + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + top: 5px; + text-indent: 5px; + text-align: left; +} + +#upload .filelist li p.progress { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + height: 8px; + overflow: hidden; + z-index: 50; + margin: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: 0 0 0; +} + +#upload .filelist li p.progress span { + display: none; + overflow: hidden; + width: 0; + height: 100%; + background: #1483d8 url(./images/progress.png) repeat-x; + + -webit-transition: width 200ms linear; + -moz-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; + transition: width 200ms linear; + + -webkit-animation: progressmove 2s linear infinite; + -moz-animation: progressmove 2s linear infinite; + -o-animation: progressmove 2s linear infinite; + -ms-animation: progressmove 2s linear infinite; + animation: progressmove 2s linear infinite; + + -webkit-transform: translateZ(0); +} + +@-webkit-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@-moz-keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +@keyframes progressmove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 17px 0; + } +} + +#upload .filelist li p.imgWrap { + position: relative; + z-index: 2; + line-height: 113px; + vertical-align: middle; + overflow: hidden; + width: 113px; + height: 113px; + + -webkit-transform-origin: 50% 50%; + -moz-transform-origin: 50% 50%; + -o-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + + -webit-transition: 200ms ease-out; + -moz-transition: 200ms ease-out; + -o-transition: 200ms ease-out; + -ms-transition: 200ms ease-out; + transition: 200ms ease-out; +} +#upload .filelist li p.imgWrap.notimage { + margin-top: 0; + width: 111px; + height: 111px; + border: 1px #eeeeee solid; +} +#upload .filelist li p.imgWrap.notimage i.file-preview { + margin-top: 15px; +} + +#upload .filelist li img { + width: 100%; +} + +#upload .filelist li p.error { + background: #f43838; + color: #fff; + position: absolute; + bottom: 0; + left: 0; + height: 28px; + line-height: 28px; + width: 100%; + z-index: 100; + display:none; +} + +#upload .filelist li .success { + display: block; + position: absolute; + left: 0; + bottom: 0; + height: 40px; + width: 100%; + z-index: 200; + background: url(./images/success.png) no-repeat right bottom; + background-image: url(./images/success.gif) \9; +} + +#upload .filelist li.filePickerBlock { + width: 113px; + height: 113px; + background: url(./images/image.png) no-repeat center 12px; + border: 1px solid #eeeeee; + border-radius: 0; +} +#upload .filelist li.filePickerBlock div.webuploader-pick { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + opacity: 0; + background: none; + font-size: 0; +} + +#upload .filelist div.file-panel { + position: absolute; + height: 0; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0; + background: rgba(0, 0, 0, 0.5); + width: 100%; + top: 0; + left: 0; + overflow: hidden; + z-index: 300; +} + +#upload .filelist div.file-panel span { + width: 24px; + height: 24px; + display: inline; + float: right; + text-indent: -9999px; + overflow: hidden; + background: url(./images/icons.png) no-repeat; + background: url(./images/icons.gif) no-repeat \9; + margin: 5px 1px 1px; + cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +#upload .filelist div.file-panel span.rotateLeft { + display:none; + background-position: 0 -24px; +} + +#upload .filelist div.file-panel span.rotateLeft:hover { + background-position: 0 0; +} + +#upload .filelist div.file-panel span.rotateRight { + display:none; + background-position: -24px -24px; +} + +#upload .filelist div.file-panel span.rotateRight:hover { + background-position: -24px 0; +} + +#upload .filelist div.file-panel span.cancel { + background-position: -48px -24px; +} + +#upload .filelist div.file-panel span.cancel:hover { + background-position: -48px 0; +} + +#upload .statusBar { + height: 45px; + border-bottom: 1px solid #dadada; + margin: 0 10px; + padding: 0; + line-height: 45px; + vertical-align: middle; + position: relative; +} + +#upload .statusBar .progress { + border: 1px solid #1483d8; + width: 198px; + background: #fff; + height: 18px; + position: absolute; + top: 12px; + display: none; + text-align: center; + line-height: 18px; + color: #6dbfff; + margin: 0 10px 0 0; +} +#upload .statusBar .progress span.percentage { + width: 0; + height: 100%; + left: 0; + top: 0; + background: #1483d8; + position: absolute; +} +#upload .statusBar .progress span.text { + position: relative; + z-index: 10; +} + +#upload .statusBar .info { + display: inline-block; + font-size: 14px; + color: #666666; +} + +#upload .statusBar .btns { + position: absolute; + top: 7px; + right: 0; + line-height: 30px; +} + +#filePickerBtn { + display: inline-block; + float: left; +} +#upload .statusBar .btns .webuploader-pick, +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-uploading, +#upload .statusBar .btns .uploadBtn.state-paused { + background: #ffffff; + border: 1px solid #cfcfcf; + color: #565656; + padding: 0 18px; + display: inline-block; + border-radius: 3px; + margin-left: 10px; + cursor: pointer; + font-size: 14px; + float: left; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#upload .statusBar .btns .webuploader-pick-hover, +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-uploading:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover { + background: #f0f0f0; +} + +#upload .statusBar .btns .uploadBtn, +#upload .statusBar .btns .uploadBtn.state-paused{ + background: #00b7ee; + color: #fff; + border-color: transparent; +} +#upload .statusBar .btns .uploadBtn:hover, +#upload .statusBar .btns .uploadBtn.state-paused:hover{ + background: #00a2d4; +} + +#upload .statusBar .btns .uploadBtn.disabled { + pointer-events: none; + filter:alpha(opacity=60); + -moz-opacity:0.6; + -khtml-opacity: 0.6; + opacity: 0.6; +} + + +/* 在线文件的文件预览图标 */ +i.file-preview { + display: block; + margin: 10px auto; + width: 70px; + height: 70px; + background-image: url("./images/file-icons.png"); + background-image: url("./images/file-icons.gif") \9; + background-position: -140px center; + background-repeat: no-repeat; +} +i.file-preview.file-type-dir{ + background-position: 0 center; +} +i.file-preview.file-type-file{ + background-position: -140px center; +} +i.file-preview.file-type-filelist{ + background-position: -210px center; +} +i.file-preview.file-type-zip, +i.file-preview.file-type-rar, +i.file-preview.file-type-7z, +i.file-preview.file-type-tar, +i.file-preview.file-type-gz, +i.file-preview.file-type-bz2{ + background-position: -280px center; +} +i.file-preview.file-type-xls, +i.file-preview.file-type-xlsx{ + background-position: -350px center; +} +i.file-preview.file-type-doc, +i.file-preview.file-type-docx{ + background-position: -420px center; +} +i.file-preview.file-type-ppt, +i.file-preview.file-type-pptx{ + background-position: -490px center; +} +i.file-preview.file-type-vsd{ + background-position: -560px center; +} +i.file-preview.file-type-pdf{ + background-position: -630px center; +} +i.file-preview.file-type-txt, +i.file-preview.file-type-md, +i.file-preview.file-type-json, +i.file-preview.file-type-htm, +i.file-preview.file-type-xml, +i.file-preview.file-type-html, +i.file-preview.file-type-js, +i.file-preview.file-type-css, +i.file-preview.file-type-php, +i.file-preview.file-type-jsp, +i.file-preview.file-type-asp{ + background-position: -700px center; +} +i.file-preview.file-type-apk{ + background-position: -770px center; +} +i.file-preview.file-type-exe{ + background-position: -840px center; +} +i.file-preview.file-type-ipa{ + background-position: -910px center; +} +i.file-preview.file-type-mp4, +i.file-preview.file-type-swf, +i.file-preview.file-type-mkv, +i.file-preview.file-type-avi, +i.file-preview.file-type-flv, +i.file-preview.file-type-mov, +i.file-preview.file-type-mpg, +i.file-preview.file-type-mpeg, +i.file-preview.file-type-ogv, +i.file-preview.file-type-webm, +i.file-preview.file-type-rm, +i.file-preview.file-type-rmvb{ + background-position: -980px center; +} +i.file-preview.file-type-ogg, +i.file-preview.file-type-wav, +i.file-preview.file-type-wmv, +i.file-preview.file-type-mid, +i.file-preview.file-type-mp3{ + background-position: -1050px center; +} +i.file-preview.file-type-jpg, +i.file-preview.file-type-jpeg, +i.file-preview.file-type-gif, +i.file-preview.file-type-bmp, +i.file-preview.file-type-png, +i.file-preview.file-type-psd{ + background-position: -140px center; +} diff --git a/public/static/plugs/ueditor/dialogs/video/video.html b/public/static/plugs/ueditor/dialogs/video/video.html new file mode 100644 index 0000000..c9f0290 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/video/video.html @@ -0,0 +1,89 @@ + + + + + + + + + +
    +
    +
    + + +
    +
    +
    +
    +
    + 外链视频支持:优酷、腾讯视频、哔哩哔哩 +
    +
    +
    +
    + + + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + 0% + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
      +
    • +
    +
    +
    +
    +
    + + + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/dialogs/video/video.js b/public/static/plugs/ueditor/dialogs/video/video.js new file mode 100644 index 0000000..4b1b9f7 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/video/video.js @@ -0,0 +1,828 @@ +/** + * Created by JetBrains PhpStorm. + * User: taoqili + * Date: 12-2-20 + * Time: 上午11:19 + * To change this template use File | Settings | File Templates. + */ + +(function(){ + + var video = {}, + uploadVideoList = [], + isModifyUploadVideo = false, + uploadFile; + var editorOpt = {}; + + window.onload = function(){ + editorOpt = editor.getOpt('videoConfig'); + $focus($G("videoUrl")); + initTabs(); + initVideo(); + initUpload(); + }; + + /* 初始化tab标签 */ + function initTabs(){ + var tabs = $G('tabHeads').children; + for (var i = 0; i < tabs.length; i++) { + domUtils.on(tabs[i], "click", function (e) { + var j, bodyId, target = e.target || e.srcElement; + for (j = 0; j < tabs.length; j++) { + bodyId = tabs[j].getAttribute('data-content-id'); + if(tabs[j] == target){ + domUtils.addClass(tabs[j], 'focus'); + domUtils.addClass($G(bodyId), 'focus'); + }else { + domUtils.removeClasses(tabs[j], 'focus'); + domUtils.removeClasses($G(bodyId), 'focus'); + } + } + }); + } + if(!editorOpt.disableUpload){ + $G('tabHeads').querySelector('[data-content-id="upload"]').style.display = 'inline-block'; + } + if(!!editorOpt.selectCallback){ + $G('videoSelect').style.display = 'inline-block'; + domUtils.on($G('videoSelect'), "click", function (e) { + editorOpt.selectCallback(editor,function(info){ + if(info){ + $G('videoUrl').value = info.path; + createPreviewVideo(info.path); + } + }); + }); + } + } + + function initVideo(){ + createAlignButton( ["videoFloat", "upload_alignment"] ); + addUrlChangeListener($G("videoUrl")); + addOkListener(); + + //编辑视频时初始化相关信息 + (function(){ + var img = editor.selection.getRange().getClosedNode(),url; + if(img && img.className){ + var hasFakedClass = (img.className == "edui-faked-video"), + hasUploadClass = img.className.indexOf("edui-upload-video")!=-1; + if(hasFakedClass || hasUploadClass) { + $G("videoUrl").value = url = img.getAttribute("_url"); + $G("videoWidth").value = img.width; + $G("videoHeight").value = img.height; + var align = domUtils.getComputedStyle(img,"float"), + parentAlign = domUtils.getComputedStyle(img.parentNode,"text-align"); + updateAlignButton(parentAlign==="center"?"center":align); + } + if(hasUploadClass) { + isModifyUploadVideo = true; + } + } + createPreviewVideo(url); + })(); + } + + /** + * 监听确认和取消两个按钮事件,用户执行插入或者清空正在播放的视频实例操作 + */ + function addOkListener(){ + dialog.onok = function(){ + $G("preview").innerHTML = ""; + var currentTab = findFocus("tabHeads","tabSrc"); + switch(currentTab){ + case "video": + return insertSingle(); + break; + case "videoSearch": + return insertSearch("searchList"); + break; + case "upload": + return insertUpload(); + break; + } + }; + dialog.oncancel = function(){ + $G("preview").innerHTML = ""; + }; + } + + /** + * 依据传入的align值更新按钮信息 + * @param align + */ + function updateAlignButton( align ) { + var aligns = $G( "videoFloat" ).children; + for ( var i = 0, ci; ci = aligns[i++]; ) { + if ( ci.getAttribute( "name" ) == align ) { + if ( ci.className !="focus" ) { + ci.className = "focus"; + } + } else { + if ( ci.className =="focus" ) { + ci.className = ""; + } + } + } + } + + /** + * 将单个视频信息插入编辑器中 + */ + function insertSingle(){ + var width = $G("videoWidth"), + height = $G("videoHeight"), + url=$G('videoUrl').value, + align = findFocus("videoFloat","name"); + if(!url) return false; + if ( !checkNum( [width, height] ) ) return false; + editor.execCommand('insertvideo', { + url: convert_url(url), + width: width.value, + height: height.value, + align: align + }, isModifyUploadVideo ? 'upload':null); + } + + /** + * 将元素id下的所有代表视频的图片插入编辑器中 + * @param id + */ + function insertSearch(id){ + var imgs = domUtils.getElementsByTagName($G(id),"img"), + videoObjs=[]; + for(var i=0,img; img=imgs[i++];){ + if(img.getAttribute("selected")){ + videoObjs.push({ + url:img.getAttribute("ue_video_url"), + width:420, + height:280, + align:"none" + }); + } + } + editor.execCommand('insertvideo',videoObjs); + } + + /** + * 找到id下具有focus类的节点并返回该节点下的某个属性 + * @param id + * @param returnProperty + */ + function findFocus( id, returnProperty ) { + var tabs = $G( id ).children, + property; + for ( var i = 0, ci; ci = tabs[i++]; ) { + if ( ci.className=="focus" ) { + property = ci.getAttribute( returnProperty ); + break; + } + } + return property; + } + function convert_url(url){ + if (!url) return ''; + url = utils.trim(url) + .replace(/v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/i, 'player.youku.com/embed/$1') + // .replace(/(www\.)?youtube\.com\/watch\?v=([\w\-]+)/i, "www.youtube.com/v/$2") + // .replace(/youtu.be\/(\w+)$/i, "www.youtube.com/v/$1") + //.replace(/www\.iqiyi\.com\/v_(\w+)\.html/i, "www.youtube.com/v/$1") + // .replace(/v\.ku6\.com\/.+\/([\w\.]+)\.html.*$/i, "player.ku6.com/refer/$1/v.swf") + // .replace(/www\.56\.com\/u\d+\/v_([\w\-]+)\.html/i, "player.56.com/v_$1.swf") + // .replace(/www.56.com\/w\d+\/play_album\-aid\-\d+_vid\-([^.]+)\.html/i, "player.56.com/v_$1.swf") + // .replace(/v\.pps\.tv\/play_([\w]+)\.html.*$/i, "player.pps.tv/player/sid/$1/v.swf") + // .replace(/www\.letv\.com\/ptv\/vplay\/([\d]+)\.html.*$/i, "i7.imgs.letv.com/player/swfPlayer.swf?id=$1&autoplay=0") + // .replace(/www\.tudou\.com\/programs\/view\/([\w\-]+)\/?/i, "www.tudou.com/v/$1") + // https://v.qq.com/x/cover/wagzbx91asjomnu/w05337nxfof.html + // https://v.qq.com/iframe/player.html?vid=w05337nxfof&tiny=0&auto=0 + .replace(/v\.qq\.com\/x\/cover\/[\w]+\/([\w]+)\.html/i, "v.qq.com/iframe/player.html?vid=$1&tiny=0&auto=0") + .replace(/v\.qq\.com\/x\/page\/([\w]+)\.html/i, "v.qq.com/iframe/player.html?vid=$1&tiny=0&auto=0") + .replace(/www\.bilibili\.com\/video\/([a-zA-Z0-9]+)\/?.*$/i, "player.bilibili.com/player.html?bvid=$1") + // .replace(/v\.qq\.com\/cover\/[\w]+\/[\w]+\/([\w]+)\.html/i, "static.video.qq.com/TPout.swf?vid=$1") + // .replace(/v\.qq\.com\/.+[\?\&]vid=([^&]+).*$/i, "static.video.qq.com/TPout.swf?vid=$1") + // .replace(/my\.tv\.sohu\.com\/[\w]+\/[\d]+\/([\d]+)\.shtml.*$/i, "share.vrs.sohu.com/my/v.swf&id=$1") + ; + return url; + } + + /** + * 检测传入的所有input框中输入的长宽是否是正数 + * @param nodes input框集合, + */ + function checkNum( nodes ) { + for ( var i = 0, ci; ci = nodes[i++]; ) { + var value = ci.value; + if ( !isNumber( value ) && value) { + alert( lang.numError ); + ci.value = ""; + ci.focus(); + return false; + } + } + return true; + } + + /** + * 数字判断 + * @param value + */ + function isNumber( value ) { + return /(0|^[1-9]\d*$)/.test( value ); + } + + /** + * 创建图片浮动选择按钮 + * @param ids + */ + function createAlignButton( ids ) { + for ( var i = 0, ci; ci = ids[i++]; ) { + var floatContainer = $G( ci ), + nameMaps = {"none":lang['default'], "left":lang.floatLeft, "right":lang.floatRight, "center":lang.block}; + for ( var j in nameMaps ) { + var div = document.createElement( "div" ); + div.setAttribute( "name", j ); + if ( j == "none" ) div.className="focus"; + div.style.cssText = "background:url(images/" + j + "_focus.jpg);"; + div.setAttribute( "title", nameMaps[j] ); + floatContainer.appendChild( div ); + } + switchSelect( ci ); + } + } + + /** + * 选择切换 + * @param selectParentId + */ + function switchSelect( selectParentId ) { + var selects = $G( selectParentId ).children; + for ( var i = 0, ci; ci = selects[i++]; ) { + domUtils.on( ci, "click", function () { + for ( var j = 0, cj; cj = selects[j++]; ) { + cj.className = ""; + cj.removeAttribute && cj.removeAttribute( "class" ); + } + this.className = "focus"; + } ) + } + } + + /** + * 监听url改变事件 + * @param url + */ + function addUrlChangeListener(url){ + if (browser.ie) { + url.onpropertychange = function () { + createPreviewVideo( this.value ); + } + } else { + url.addEventListener( "input", function () { + createPreviewVideo( this.value ); + }, false ); + } + } + + /** + * 根据url生成视频预览 + * @param url + */ + function createPreviewVideo(url){ + if (!url)return; + + var conUrl = convert_url(url); + + conUrl = utils.unhtml(conUrl); + + // $G("preview").innerHTML = '
    '+lang.urlError+'
    '+ + // '' + + // ''; + + $G("preview").innerHTML = '
    ' + lang.urlError + '
    ' + + ''; + } + + + /* 插入上传视频 */ + function insertUpload(){ + var videoObjs=[], + uploadDir = editor.getOpt('videoUrlPrefix'), + width = $G('upload_width').value || 420, + height = $G('upload_height').value || 280, + align = findFocus("upload_alignment","name") || 'none'; + for(var key in uploadVideoList) { + var file = uploadVideoList[key]; + videoObjs.push({ + url: uploadDir + file.url, + width:width, + height:height, + align:align + }); + } + + var count = uploadFile.getQueueCount(); + if (count) { + $('.info', '#queueList').html('' + '还有2个未上传文件'.replace(/[\d]/, count) + ''); + return false; + } else { + editor.execCommand('insertvideo', videoObjs, 'upload'); + } + } + + /*初始化上传标签*/ + function initUpload(){ + uploadFile = new UploadFile('queueList'); + } + + + /* 上传附件 */ + function UploadFile(target) { + this.$wrap = target.constructor == String ? $('#' + target) : $(target); + this.init(); + } + UploadFile.prototype = { + init: function () { + this.fileList = []; + this.initContainer(); + this.initUploader(); + }, + initContainer: function () { + this.$queue = this.$wrap.find('.filelist'); + }, + /* 初始化容器 */ + initUploader: function () { + var _this = this, + $ = jQuery, // just in case. Make sure it's not an other libaray. + $wrap = _this.$wrap, + // 图片容器 + $queue = $wrap.find('.filelist'), + // 状态栏,包括进度和控制按钮 + $statusBar = $wrap.find('.statusBar'), + // 文件总体选择信息。 + $info = $statusBar.find('.info'), + // 上传按钮 + $upload = $wrap.find('.uploadBtn'), + // 上传按钮 + $filePickerBtn = $wrap.find('.filePickerBtn'), + // 上传按钮 + $filePickerBlock = $wrap.find('.filePickerBlock'), + // 没选择文件之前的内容。 + $placeHolder = $wrap.find('.placeholder'), + // 总体进度条 + $progress = $statusBar.find('.progress').hide(), + // 添加的文件数量 + fileCount = 0, + // 添加的文件总大小 + fileSize = 0, + // 优化retina, 在retina下这个值是2 + ratio = window.devicePixelRatio || 1, + // 缩略图大小 + thumbnailWidth = 113 * ratio, + thumbnailHeight = 113 * ratio, + // 可能有pedding, ready, uploading, confirm, done. + state = '', + // 所有文件的进度信息,key为file id + percentages = {}, + supportTransition = (function () { + var s = document.createElement('p').style, + r = 'transition' in s || + 'WebkitTransition' in s || + 'MozTransition' in s || + 'msTransition' in s || + 'OTransition' in s; + s = null; + return r; + })(), + // WebUploader实例 + uploader, + actionUrl = editor.getActionUrl(editor.getOpt('videoActionName')), + fileMaxSize = editor.getOpt('videoMaxSize'), + acceptExtensions = (editor.getOpt('videoAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');; + + if (!WebUploader.Uploader.support()) { + $('#filePickerReady').after($('
    ').html(lang.errorNotSupport)).hide(); + return; + } else if (!editor.getOpt('videoActionName')) { + $('#filePickerReady').after($('
    ').html(lang.errorLoadConfig)).hide(); + return; + } + + uploader = _this.uploader = WebUploader.create({ + pick: { + id: '#filePickerReady', + label: lang.uploadSelectFile + }, + swf: '../../third-party/webuploader/Uploader.swf', + server: actionUrl, + fileVal: editor.getOpt('videoFieldName'), + duplicate: true, + fileSingleSizeLimit: fileMaxSize, + compress: false + }); + uploader.addButton({ + id: '#filePickerBlock' + }); + uploader.addButton({ + id: '#filePickerBtn', + label: lang.uploadAddFile + }); + + setState('pedding'); + + // 当有文件添加进来时执行,负责view的创建 + function addFile(file) { + var $li = $('
  • ' + + '

    ' + file.name + '

    ' + + '

    ' + + '

    ' + + '
  • '), + + $btns = $('
    ' + + '' + lang.uploadDelete + '' + + '' + lang.uploadTurnRight + '' + + '' + lang.uploadTurnLeft + '
    ').appendTo($li), + $prgress = $li.find('p.progress span'), + $wrap = $li.find('p.imgWrap'), + $info = $('

    ').hide().appendTo($li), + + showError = function (code) { + switch (code) { + case 'exceed_size': + text = lang.errorExceedSize; + break; + case 'interrupt': + text = lang.errorInterrupt; + break; + case 'http': + text = lang.errorHttp; + break; + case 'not_allow_type': + text = lang.errorFileType; + break; + default: + text = lang.errorUploadRetry; + break; + } + $info.text(text).show(); + }; + + if (file.getStatus() === 'invalid') { + showError(file.statusText); + } else { + $wrap.text(lang.uploadPreview); + if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) { + $wrap.empty().addClass('notimage').append('' + + '' + file.name + ''); + } else { + if (browser.ie && browser.version <= 7) { + $wrap.text(lang.uploadNoPreview); + } else { + uploader.makeThumb(file, function (error, src) { + if (error || !src || (/^data:/.test(src) && browser.ie && browser.version <= 7)) { + $wrap.text(lang.uploadNoPreview); + } else { + var $img = $(''); + $wrap.empty().append($img); + $img.on('error', function () { + $wrap.text(lang.uploadNoPreview); + }); + } + }, thumbnailWidth, thumbnailHeight); + } + } + percentages[ file.id ] = [ file.size, 0 ]; + file.rotation = 0; + + /* 检查文件格式 */ + if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) { + showError('not_allow_type'); + uploader.removeFile(file); + } + } + + file.on('statuschange', function (cur, prev) { + if (prev === 'progress') { + $prgress.hide().width(0); + } else if (prev === 'queued') { + $li.off('mouseenter mouseleave'); + $btns.remove(); + } + // 成功 + if (cur === 'error' || cur === 'invalid') { + showError(file.statusText); + percentages[ file.id ][ 1 ] = 1; + } else if (cur === 'interrupt') { + showError('interrupt'); + } else if (cur === 'queued') { + percentages[ file.id ][ 1 ] = 0; + } else if (cur === 'progress') { + $info.hide(); + $prgress.css('display', 'block'); + } else if (cur === 'complete') { + } + + $li.removeClass('state-' + prev).addClass('state-' + cur); + }); + + $li.on('mouseenter', function () { + $btns.stop().animate({height: 30}); + }); + $li.on('mouseleave', function () { + $btns.stop().animate({height: 0}); + }); + + $btns.on('click', 'span', function () { + var index = $(this).index(), + deg; + + switch (index) { + case 0: + uploader.removeFile(file); + return; + case 1: + file.rotation += 90; + break; + case 2: + file.rotation -= 90; + break; + } + + if (supportTransition) { + deg = 'rotate(' + file.rotation + 'deg)'; + $wrap.css({ + '-webkit-transform': deg, + '-mos-transform': deg, + '-o-transform': deg, + 'transform': deg + }); + } else { + $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'); + } + + }); + + $li.insertBefore($filePickerBlock); + } + + // 负责view的销毁 + function removeFile(file) { + var $li = $('#' + file.id); + delete percentages[ file.id ]; + updateTotalProgress(); + $li.off().find('.file-panel').off().end().remove(); + } + + function updateTotalProgress() { + var loaded = 0, + total = 0, + spans = $progress.children(), + percent; + + $.each(percentages, function (k, v) { + total += v[ 0 ]; + loaded += v[ 0 ] * v[ 1 ]; + }); + + percent = total ? loaded / total : 0; + + spans.eq(0).text(Math.round(percent * 100) + '%'); + spans.eq(1).css('width', Math.round(percent * 100) + '%'); + updateStatus(); + } + + function setState(val, files) { + + if (val != state) { + + var stats = uploader.getStats(); + + $upload.removeClass('state-' + state); + $upload.addClass('state-' + val); + + switch (val) { + + /* 未选择文件 */ + case 'pedding': + $queue.addClass('element-invisible'); + $statusBar.addClass('element-invisible'); + $placeHolder.removeClass('element-invisible'); + $progress.hide(); $info.hide(); + uploader.refresh(); + break; + + /* 可以开始上传 */ + case 'ready': + $placeHolder.addClass('element-invisible'); + $queue.removeClass('element-invisible'); + $statusBar.removeClass('element-invisible'); + $progress.hide(); $info.show(); + $upload.text(lang.uploadStart); + uploader.refresh(); + break; + + /* 上传中 */ + case 'uploading': + $progress.show(); $info.hide(); + $upload.text(lang.uploadPause); + break; + + /* 暂停上传 */ + case 'paused': + $progress.show(); $info.hide(); + $upload.text(lang.uploadContinue); + break; + + case 'confirm': + $progress.show(); $info.hide(); + $upload.text(lang.uploadStart); + + stats = uploader.getStats(); + if (stats.successNum && !stats.uploadFailNum) { + setState('finish'); + return; + } + break; + + case 'finish': + $progress.hide(); $info.show(); + if (stats.uploadFailNum) { + $upload.text(lang.uploadRetry); + } else { + $upload.text(lang.uploadStart); + } + break; + } + + state = val; + updateStatus(); + + } + + if (!_this.getQueueCount()) { + $upload.addClass('disabled') + } else { + $upload.removeClass('disabled') + } + + } + + function updateStatus() { + var text = '', stats; + + if (state === 'ready') { + text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize)); + } else if (state === 'confirm') { + stats = uploader.getStats(); + if (stats.uploadFailNum) { + text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum); + } + } else { + stats = uploader.getStats(); + text = lang.updateStatusFinish.replace('_', fileCount). + replace('_KB', WebUploader.formatSize(fileSize)). + replace('_', stats.successNum); + + if (stats.uploadFailNum) { + text += lang.updateStatusError.replace('_', stats.uploadFailNum); + } + } + + $info.html(text); + } + + uploader.on('fileQueued', function (file) { + fileCount++; + fileSize += file.size; + + if (fileCount === 1) { + $placeHolder.addClass('element-invisible'); + $statusBar.show(); + } + + addFile(file); + }); + + uploader.on('fileDequeued', function (file) { + fileCount--; + fileSize -= file.size; + + removeFile(file); + updateTotalProgress(); + }); + + uploader.on('filesQueued', function (file) { + if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) { + setState('ready'); + } + updateTotalProgress(); + }); + + uploader.on('all', function (type, files) { + switch (type) { + case 'uploadFinished': + setState('confirm', files); + break; + case 'startUpload': + /* 添加额外的GET参数 */ + var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '', + url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params); + uploader.option('server', url); + setState('uploading', files); + break; + case 'stopUpload': + setState('paused', files); + break; + } + }); + + uploader.on('uploadBeforeSend', function (file, data, header) { + //这里可以通过data对象添加POST参数 + if (actionUrl.toLowerCase().indexOf('jsp') != -1) { + header['X_Requested_With'] = 'XMLHttpRequest'; + } + }); + + uploader.on('uploadProgress', function (file, percentage) { + var $li = $('#' + file.id), + $percent = $li.find('.progress span'); + + $percent.css('width', percentage * 100 + '%'); + percentages[ file.id ][ 1 ] = percentage; + updateTotalProgress(); + }); + + uploader.on('uploadSuccess', function (file, ret) { + var $file = $('#' + file.id); + try { + var responseText = (ret._raw || ret), + json = utils.str2json(responseText); + if (json.state == 'SUCCESS') { + uploadVideoList.push({ + 'url': json.url, + 'type': json.type, + 'original':json.original + }); + $file.append(''); + // 触发上传视频事件 + editor.fireEvent("uploadsuccess", { + res: json, + type: 'video' + }); + } else { + $file.find('.error').text(json.state).show(); + } + } catch (e) { + $file.find('.error').text(lang.errorServerUpload).show(); + } + }); + + uploader.on('uploadError', function (file, code) { + }); + uploader.on('error', function (code, file) { + if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') { + addFile(file); + } + }); + uploader.on('uploadComplete', function (file, ret) { + }); + + $upload.on('click', function () { + if ($(this).hasClass('disabled')) { + return false; + } + + if (state === 'ready') { + uploader.upload(); + } else if (state === 'paused') { + uploader.upload(); + } else if (state === 'uploading') { + uploader.stop(); + } + }); + + $upload.addClass('state-' + state); + updateTotalProgress(); + }, + getQueueCount: function () { + var file, i, status, readyFile = 0, files = this.uploader.getFiles(); + for (i = 0; file = files[i++]; ) { + status = file.getStatus(); + if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++; + } + return readyFile; + }, + refresh: function(){ + this.uploader.refresh(); + } + }; + +})(); diff --git a/public/static/plugs/ueditor/dialogs/wordimage/wordimage.html b/public/static/plugs/ueditor/dialogs/wordimage/wordimage.html new file mode 100644 index 0000000..913a23e --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/wordimage/wordimage.html @@ -0,0 +1,221 @@ + + + + + + + + + +
    +
    +
    + +
    +
    +
    复制路径
    +
    +
    +
    +
    本地选择保存
    + +
    +
    +
    +
    +
    +
    + Windows使用教程 +
    +
    +

    1、点击复制地址按钮

    +

    2、点击本地选择文件,粘贴剪切板的路径到文件选择路径

    +

    3、点击确定

    +
    +
    + Mac使用教程 +
    +
    +

    1、点击复制地址按钮

    +

    2、点击本地选择文件,按快捷 Command+Shift+G ,粘贴剪切板的路径到文件选择路径

    +

    3、点击确定

    +
    +
    +
    + + + + + + + + diff --git a/public/static/plugs/ueditor/dialogs/wordimage/wordimage.js b/public/static/plugs/ueditor/dialogs/wordimage/wordimage.js new file mode 100644 index 0000000..ef531d1 --- /dev/null +++ b/public/static/plugs/ueditor/dialogs/wordimage/wordimage.js @@ -0,0 +1,93 @@ +/** + * Created by JetBrains PhpStorm. + * User: taoqili + * Date: 12-1-30 + * Time: 下午12:50 + * To change this template use File | Settings | File Templates. + */ +var wordImage = {}; +var g = $G, flashObj, flashContainer; + +wordImage.init = function (opt, callbacks) { + showLocalPath("fileUrl"); + createCopyButton("copyButton", "fileUrl"); + addUploadButtonListener(); + addOkListener(); +}; + +function addUploadButtonListener() { + g('saveFile').addEventListener('change', function () { + $('.image-tip').html('正在转存,请稍后...'); + uploader.addFile(this.files); + uploader.upload(); + }); +} + + +function addOkListener() { + dialog.onok = function () { + //console.log('imageUrls',imageUrls); + if (!imageUrls.length) return; + var urlPrefix = editor.getOpt('imageUrlPrefix'), + images = domUtils.getElementsByTagName(editor.document, "img"); + editor.fireEvent('saveScene'); + // console.log('images',images,imageUrls); + for (var i = 0, img; img = images[i++];) { + var src = img.getAttribute("data-word-image"); + if (!src) continue; + for (var j = 0, url; url = imageUrls[j++];) { + // console.log('url',src, url); + if (src.indexOf(url.name.replace(" ", "")) != -1) { + img.src = urlPrefix + url.url; + img.setAttribute("_src", urlPrefix + url.url); //同时修改"_src"属性 + img.setAttribute("title", url.title); + domUtils.removeAttributes(img, ["data-word-image", "style", "width", "height"]); + editor.fireEvent("selectionchange"); + break; + } + } + } + editor.fireEvent('saveScene'); + // hideFlash(); + }; + dialog.oncancel = function () { + //hideFlash(); + }; +} + +function showLocalPath(id) { + //单张编辑 + var img = editor.selection.getRange().getClosedNode(); + var images = editor.execCommand('wordimage'); + if (images.length == 1 || img && img.tagName == 'IMG') { + g(id).value = images[0]; + return; + } + var path = images[0]; + var leftSlashIndex = path.lastIndexOf("/") || 0, //不同版本的doc和浏览器都可能影响到这个符号,故直接判断两种 + rightSlashIndex = path.lastIndexOf("\\") || 0, + separater = leftSlashIndex > rightSlashIndex ? "/" : "\\"; + + path = path.substring(0, path.lastIndexOf(separater) + 1); + g(id).value = path; + //增提醒用户选择哪些文件 + var names = []; + for (var i = 0, len = images.length; i < len; i++) { + var img = images[i]; + names.push(img.substring(img.lastIndexOf(separater) + 1, img.length)); + } + $('.image-tip').html('请选择:' + names.join("、") + "共" + images.length + '个文件'); +} + +function createCopyButton(id, dataFrom) { + var url = g(dataFrom).value; + if (url.startsWith("file:////")) { + url = url.substring(8); + } + url = decodeURI( url ); + g(id).setAttribute("data-clipboard-text", url); + var clipboard = new Clipboard('[data-clipboard-text]') + clipboard.on('success', function (e) { + g('copyButton').innerHTML = '复制成功'; + }); +} diff --git a/public/static/plugs/ueditor/index.html b/public/static/plugs/ueditor/index.html new file mode 100644 index 0000000..9beb870 --- /dev/null +++ b/public/static/plugs/ueditor/index.html @@ -0,0 +1,139 @@ + + + + UEditorPlus 完整演示 + + + + + + + + + + + + + +
    +

    完整示例

    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + + diff --git a/public/static/plugs/ueditor/lang/en/en.js b/public/static/plugs/ueditor/lang/en/en.js new file mode 100644 index 0000000..586faf0 --- /dev/null +++ b/public/static/plugs/ueditor/lang/en/en.js @@ -0,0 +1,613 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-6-12 + * Time: 下午6:57 + * To change this template use File | Settings | File Templates. + */ +UE.I18N['en'] = { + 'labelMap':{ + 'anchor':'Anchor', 'undo':'Undo', 'redo':'Redo', 'bold':'Bold', 'indent':'Indent', + 'italic':'Italic', 'underline':'Underline', 'strikethrough':'Strikethrough', 'subscript':'SubScript','fontborder':'text border', + 'superscript':'SuperScript', 'formatmatch':'Format Match', 'source':'Source', 'blockquote':'BlockQuote', + 'pasteplain':'PastePlain', 'selectall':'SelectAll', 'print':'Print', 'preview':'Preview', + 'horizontal':'Horizontal', 'removeformat':'RemoveFormat', 'time':'Time', 'date':'Date', + 'unlink':'Unlink', 'insertrow':'InsertRow', 'insertcol':'InsertCol', 'mergeright':'MergeRight', 'mergedown':'MergeDown', + 'deleterow':'DeleteRow', 'deletecol':'DeleteCol', 'splittorows':'SplitToRows','insertcode':'insert code', + 'splittocols':'SplitToCols', 'splittocells':'SplitToCells','deletecaption':'DeleteCaption','inserttitle':'InsertTitle', + 'mergecells':'MergeCells', 'deletetable':'DeleteTable', 'cleardoc':'Clear', 'insertparagraphbeforetable':"InsertParagraphBeforeTable", + 'fontfamily':'FontFamily', 'fontsize':'FontSize', 'paragraph':'Paragraph','simpleupload':'Single Image','insertimage':'Multi Image','edittable':'Edit Table', 'edittd':'Edit Td','link':'Link', + 'emotion':'Emotion', 'spechars':'Spechars', 'searchreplace':'SearchReplace', + 'insertvideo':'Video', 'help':'Help', 'justifyleft':'JustifyLeft', 'justifyright':'JustifyRight', 'justifycenter':'JustifyCenter', + 'justifyjustify':'Justify', 'forecolor':'FontColor', 'backcolor':'BackColor', 'insertorderedlist':'OL', + 'insertunorderedlist':'UL', 'fullscreen':'FullScreen', 'directionalityltr':'EnterFromLeft', 'directionalityrtl':'EnterFromRight', + 'rowspacingtop':'RowSpacingTop', 'rowspacingbottom':'RowSpacingBottom', 'pagebreak':'PageBreak', 'insertframe':'Iframe', 'imagenone':'Default', + 'imageleft':'ImageLeft', 'imageright':'ImageRight', 'attachment':'Attachment', 'imagecenter':'ImageCenter', 'wordimage':'WordImage', 'formula':'Formula', + 'lineheight':'LineHeight','edittip':'EditTip','customstyle':'CustomStyle', 'scrawl':'Scrawl', 'autotypeset':'AutoTypeset', + 'touppercase':'UpperCase', 'tolowercase':'LowerCase','template':'Template','background':'Background','inserttable':'InsertTable', + }, + 'autosave': { + 'autoRestoreTip': 'Has been recovered from draft' + }, + 'insertorderedlist':{ + 'num':'1,2,3...', + 'num1':'1),2),3)...', + 'num2':'(1),(2),(3)...', + 'cn':'一,二,三....', + 'cn1':'一),二),三)....', + 'cn2':'(一),(二),(三)....', + 'decimal':'1,2,3...', + 'lower-alpha':'a,b,c...', + 'lower-roman':'i,ii,iii...', + 'upper-alpha':'A,B,C...', + 'upper-roman':'I,II,III...' + }, + 'insertunorderedlist':{ + 'circle':'○ Circle', + 'disc':'● Circle dot', + 'square':'■ Rectangle ', + 'dash' :'- Dash', + 'dot' : '。dot' + }, + 'paragraph':{'p':'Paragraph', 'h1':'Title 1', 'h2':'Title 2', 'h3':'Title 3', 'h4':'Title 4', 'h5':'Title 5', 'h6':'Title 6'}, + 'fontfamily':{ + 'default':'Default', + 'songti':'Sim Sun', + 'kaiti':'Sim Kai', + 'heiti':'Sim Hei', + 'lishu':'Sim Li', + 'yahei': 'Microsoft YaHei', + // 'andaleMono':'Andale Mono', + 'arial': 'Arial', + // 'arialBlack':'Arial Black', + // 'comicSansMs':'Comic Sans MS', + // 'impact':'Impact', + 'timesNewRoman':'Times New Roman' + }, + 'customstyle':{ + 'tc':'Title center', + 'tl':'Title left', + 'im':'Important', + 'hi':'Highlight' + }, + 'autoupload': { + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'simpleupload':{ + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'elementPathTip':"Path", + 'wordCountTip':"Word Count", + 'wordCountMsg':'{#count} characters entered,{#leave} left. ', + 'wordOverFlowMsg':'The number of characters has exceeded allowable maximum values, the server may refuse to save!', + 'ok':"OK", + 'cancel':"Cancel", + 'closeDialog':"closeDialog", + 'tableDrag':"You must import the file uiUtils.js before drag! ", + 'autofloatMsg':"The plugin AutoFloat depends on EditorUI!", + 'loadconfigError': 'Get server config error.', + 'loadconfigFormatError': 'Server config format error.', + 'loadconfigHttpError': 'Get server config http error.', + 'insertcode':{ + 'as3':'ActionScript 3', + 'bash':'Bash/Shell', + 'cpp':'C/C++', + 'css':'CSS', + 'cf':'ColdFusion', + 'c#':'C#', + 'delphi':'Delphi', + 'diff':'Diff', + 'erlang':'Erlang', + 'groovy':'Groovy', + 'html':'HTML', + 'java':'Java', + 'jfx':'JavaFX', + 'js':'JavaScript', + 'pl':'Perl', + 'php':'PHP', + 'plain':'Plain Text', + 'ps':'PowerShell', + 'python':'Python', + 'ruby':'Ruby', + 'scala':'Scala', + 'sql':'SQL', + 'vb':'Visual Basic', + 'xml':'XML' + }, + 'confirmClear':"Do you confirm to clear the Document?", + 'contextMenu':{ + 'delete':"Delete", + 'selectall':"Select all", + 'deletecode':"Delete Code", + 'cleardoc':"Clear Document", + 'confirmclear':"Do you confirm to clear the Document?", + 'unlink':"Unlink", + 'paragraph':"Paragraph", + 'edittable':"Table property", + 'aligncell':'Align cell', + 'aligntable':'Table alignment', + 'tableleft':'Left float', + 'tablecenter':'Center', + 'tableright':'Right float', + 'aligntd':'Cell alignment', + 'edittd':"Cell property", + 'setbordervisible':'set table edge visible', + 'table':"Table", + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justifyjustify':'Default', + 'deletetable':"Delete table", + 'insertparagraphbefore':"InsertedBeforeLine", + 'insertparagraphafter':'InsertedAfterLine', + 'inserttable':'Insert table', + 'insertcaption':'Insert caption', + 'deletecaption':'Delete Caption', + 'inserttitle':'Insert Title', + 'deletetitle':'Delete Title', + 'inserttitlecol':'Insert Title Col', + 'deletetitlecol':'Delete Title Col', + 'averageDiseRow':'AverageDise Row', + 'averageDisCol':'AverageDis Col', + 'deleterow':"Delete row", + 'deletecol':"Delete col", + 'insertrow':"Insert row", + 'insertcol':"Insert col", + 'insertrownext':'Insert Row Next', + 'insertcolnext':'Insert Col Next', + 'mergeright':"Merge right", + 'mergeleft':"Merge left", + 'mergedown':"Merge down", + 'mergecells':"Merge cells", + 'splittocells':"Split to cells", + 'splittocols':"Split to Cols", + 'splittorows':"Split to Rows", + 'tablesort':'Table sorting', + 'enablesort':'Sorting Enable', + 'disablesort':'Sorting Disable', + 'reversecurrent':'Reverse current', + 'orderbyasc':'Order By ASCII', + 'reversebyasc':'Reverse By ASCII', + 'orderbynum':'Order By Num', + 'reversebynum':'Reverse By Num', + 'borderbk':'Border shading', + 'setcolor':'interlaced color', + 'unsetcolor':'Cancel interlacedcolor', + 'setbackground':'Background interlaced', + 'unsetbackground':'Cancel Bk interlaced', + 'redandblue':'Blue and red', + 'threecolorgradient':'Three-color gradient', + 'copy':"Copy(Ctrl + c)", + 'copymsg':"Browser does not support. Please use 'Ctrl + c' instead!", + 'paste':"Paste(Ctrl + v)", + 'pastemsg':"Browser does not support. Please use 'Ctrl + v' instead!" + }, + 'copymsg': "Browser does not support. Please use 'Ctrl + c' instead!", + 'pastemsg': "Browser does not support. Please use 'Ctrl + v' instead!", + 'anchorMsg':"Link", + 'clearColor':'Clear', + 'standardColor':'Standard color', + 'themeColor':'Theme color', + 'property':'Property', + 'default':'Default', + 'modify':'Modify', + 'save':'Save', + 'formulaedit':'FormulaEdit', + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justify':'Default', + 'clear':'Clear', + 'delete':'Delete', + 'clickToUpload':"Click to upload", + 'unset':'Language hasn\'t been set!', + 't_row':'row', + 't_col':'col', + 'pasteOpt':'Paste Option', + 'pasteSourceFormat':"Keep Source Formatting", + 'tagFormat':'Keep tag', + 'pasteTextFormat':'Keep Text only', + 'more':'More', + 'autoTypeSet':{ + 'mergeLine':"Merge empty line", + 'delLine':"Del empty line", + 'removeFormat':"Remove format", + 'indent':"Indent", + 'alignment':"Alignment", + 'imageFloat':"Image float", + 'removeFontsize':"Remove font size", + 'removeFontFamily':"Remove fontFamily", + 'removeHtml':"Remove redundant HTML code", + 'pasteFilter':"Paste filter", + 'run':"Done", + 'symbol':'Symbol Conversion', + 'bdc2sb':'Full-width to Half-width', + 'tobdc':'Half-width to Full-width' + }, + + 'background':{ + 'static':{ + 'lang_background_normal':'Normal', + 'lang_background_local':'Online', + 'lang_background_set':'Background Set', + 'lang_background_none':'No Background', + 'lang_background_colored':'Colored Background', + 'lang_background_color':'Color Set', + 'lang_background_netimg':'Net-Image', + 'lang_background_align':'Align Type', + 'lang_background_position':'Position', + 'repeatType':{'options':["Center", "Repeat-x", "Repeat-y", "Tile","Custom"]} + }, + 'noUploadImage':"No pictures has been uploaded!", + 'toggleSelect':'Change the active state by click!\n Image Size: ' + }, + //===============dialog i18N======================= + 'insertimage':{ + 'static':{ + 'lang_tab_remote':"Insert", + 'lang_tab_upload':"Local", + 'lang_tab_online':"Manager", + 'lang_tab_search':"Search", + 'lang_input_url':"Address:", + 'lang_input_size':"Size:", + 'lang_input_width':"Width", + 'lang_input_height':"Height", + 'lang_input_border':"Border:", + 'lang_input_vhspace':"Margins:", + 'lang_input_title':"Title:", + 'lang_input_align':'Image Float Style:', + 'lang_imgLoading':"Loading...", + 'lang_start_upload':"Start Upload", + 'lock':{'title':"Lock rate"}, + 'searchType':{'title':"ImageType", 'options':["News", "Wallpaper", "emotions", "photo"]}, + 'searchTxt':{'value':"Enter the search keyword!"}, + 'searchBtn':{'value':"Search"}, + 'searchReset':{'value':"Clear"}, + 'noneAlign':{'title':'None Float'}, + 'leftAlign':{'title':'Left Float'}, + 'rightAlign':{'title':'Right Float'}, + 'centerAlign':{'title':'Center In A Line'} + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'uploadNoPreview':'Can Not Preview', + 'updateStatusReady': 'Selected _ pictures, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ pictures (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.', + 'remoteLockError':"Cannot Lock the Proportion between width and height", + 'numError':"Please enter the correct Num. e.g 123,400", + 'imageUrlError':"The image format may be wrong!", + 'imageLoadError':"Error,please check the network or URL!", + 'searchRemind':"Enter the search keyword!", + 'searchLoading':"Image is loading,please wait...", + 'searchRetry':" Sorry,can't find the image,please try again!" + }, + 'attachment':{ + 'static':{ + 'lang_tab_upload': 'Upload', + 'lang_tab_online': 'Online', + 'lang_start_upload':"Start upload", + 'lang_drop_remind':"You can drop files here, a single maximum of 300 files" + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + + 'insertvideo':{ + 'static':{ + 'lang_tab_insertV':"Video", + 'lang_tab_searchV':"Search", + 'lang_tab_uploadV':"Upload", + 'lang_video_url':" URL ", + 'lang_video_size':"Video Size", + 'lang_videoW':"Width", + 'lang_videoH':"Height", + 'lang_alignment':"Alignment", + 'videoSearchTxt':{'value':"Enter the search keyword!"}, + 'videoType':{'options':["All", "Hot", "Entertainment", "Funny", "Sports", "Science", "variety"]}, + 'videoSearchBtn':{'value':"Search in Baidu"}, + 'videoSearchReset':{'value':"Clear result"}, + + 'lang_input_fileStatus':' No file uploaded!', + 'startUpload':{'style':"background:url(upload.png) no-repeat;"}, + + 'lang_upload_size':"Video Size", + 'lang_upload_width':"Width", + 'lang_upload_height':"Height", + 'lang_upload_alignment':"Alignment", + 'lang_format_advice':"Recommends mp4 format." + }, + 'numError':"Please enter the correct Num. e.g 123,400", + 'floatLeft':"Float left", + 'floatRight':"Float right", + 'default':"Default", + 'block':"Display in block", + 'urlError':"The video url format may be wrong!", + 'loading':"  The video is loading, please wait…", + 'clickToSelect':"Click to select", + 'goToSource':'Visit source video ', + 'noVideo':"    Sorry,can't find the video,please try again!", + + 'browseFiles':'Open files', + 'uploadSuccess':'Upload Successful!', + 'delSuccessFile':'Remove from the success of the queue', + 'delFailSaveFile':'Remove the save failed file', + 'statusPrompt':' file(s) uploaded! ', + 'flashVersionError':'The current Flash version is too low, please update FlashPlayer,then try again!', + 'flashLoadingError':'The Flash failed loading! Please check the path or network state', + 'fileUploadReady':'Wait for uploading...', + 'delUploadQueue':'Remove from the uploading queue ', + 'limitPrompt1':'Can not choose more than single', + 'limitPrompt2':'file(s)!Please choose again!', + 'delFailFile':'Remove failure file', + 'fileSizeLimit':'File size exceeds the limit!', + 'emptyFile':'Can not upload an empty file!', + 'fileTypeError':'File type error!', + 'unknownError':'Unknown error!', + 'fileUploading':'Uploading,please wait...', + 'cancelUpload':'Cancel upload', + 'netError':'Network error', + 'failUpload':'Upload failed', + 'serverIOError':'Server IO error!', + 'noAuthority':'No Permission!', + 'fileNumLimit':'Upload limit to the number', + 'failCheck':'Authentication fails, the upload is skipped!', + 'fileCanceling':'Cancel, please wait...', + 'stopUploading':'Upload has stopped...', + + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + 'template':{ + 'static':{ + 'lang_template_bkcolor':'Background Color', + 'lang_template_clear' : 'Keep Content', + 'lang_template_select':'Select Template' + }, + 'blank':"Blank", + 'blog':"Blog", + 'resume':"Resume", + 'richText':"Rich Text", + 'scrPapers':"Scientific Papers" + }, + scrawl:{ + 'static':{ + 'lang_input_previousStep':"Previous", + 'lang_input_nextsStep':"Next", + 'lang_input_clear':'Clear', + 'lang_input_addPic':'AddImage', + 'lang_input_ScalePic':'ScaleImage', + 'lang_input_removePic':'RemoveImage', + 'J_imgTxt':{title:'Add background image'} + }, + 'noScarwl':"No paint, a white paper...", + 'scrawlUpLoading':"Image is uploading, please wait...", + 'continueBtn':"Try again", + 'imageError':"Image failed to load!", + 'backgroundUploading':'Image is uploading,please wait...' + }, + anchor:{ + 'static':{ + 'lang_input_anchorName':'Anchor Name:' + } + }, + emotion:{ + 'static':{ + 'lang_input_choice':'Choice', + 'lang_input_Tuzki':'Tuzki', + 'lang_input_lvdouwa':'LvDouWa', + 'lang_input_BOBO':'BOBO', + 'lang_input_babyCat':'BabyCat', + 'lang_input_bubble':'Bubble', + 'lang_input_youa':'YouA' + } + }, + help:{ + 'static':{ + 'lang_input_about':'About UEditor Plus', + 'lang_input_shortcuts':'Shortcuts', + 'lang_input_introduction':"UEditor Plus is based on UEditor.", + 'lang_Txt_shortcuts':'Shortcuts', + 'lang_Txt_func':'Function', + 'lang_Txt_bold':'Bold', + 'lang_Txt_copy':'Copy', + 'lang_Txt_cut':'Cut', + 'lang_Txt_Paste':'Paste', + 'lang_Txt_undo':'Undo', + 'lang_Txt_redo':'Redo', + 'lang_Txt_italic':'Italic', + 'lang_Txt_underline':'Underline', + 'lang_Txt_selectAll':'Select All', + 'lang_Txt_visualEnter':'Submit', + 'lang_Txt_fullscreen':'Fullscreen' + } + }, + insertframe:{ + 'static':{ + 'lang_input_address':'Address:', + 'lang_input_width':'Width:', + 'lang_input_height':'height:', + 'lang_input_isScroll':'Enable scrollbars:', + 'lang_input_frameborder':'Show frame border:', + 'lang_input_alignMode':'Alignment:', + 'align':{title:"Alignment", options:["Default", "Left", "Right", "Center"]} + }, + 'enterAddress':'Please enter an address!' + }, + link:{ + 'static':{ + 'lang_input_text':'Text:', + 'lang_input_url':'URL:', + 'lang_input_title':'Title:', + 'lang_input_target':'open in new window:' + }, + 'validLink':'Supports only effective when a link is selected', + 'httpPrompt':'The hyperlink you enter should start with "http|https|ftp://"!' + }, + searchreplace:{ + 'static':{ + lang_tab_search:"Search", + lang_tab_replace:"Replace", + lang_search1:"Search", + lang_search2:"Search", + lang_replace:"Replace", + lang_searchReg:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_searchReg1:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_case_sensitive1:"Case sense", + lang_case_sensitive2:"Case sense", + nextFindBtn:{value:"Next"}, + preFindBtn:{value:"Preview"}, + nextReplaceBtn:{value:"Next"}, + preReplaceBtn:{value:"Preview"}, + repalceBtn:{value:"Replace"}, + repalceAllBtn:{value:"Replace all"} + }, + getEnd:"Has the search to the bottom!", + getStart:"Has the search to the top!", + countMsg:"Altogether replaced {#count} character(s)!" + }, + spechars:{ + 'static':{}, + tsfh:"Special", + lmsz:"Roman", + szfh:"Numeral", + rwfh:"Japanese", + xlzm:"The Greek", + ewzm:"Russian", + pyzm:"Phonetic", + yyyb:"English", + zyzf:"Others" + }, + 'edittable':{ + 'static':{ + 'lang_tableStyle':'Table style', + 'lang_insertCaption':'Add table header row', + 'lang_insertTitle':'Add table title row', + 'lang_insertTitleCol':'Add table title col', + 'lang_tableSize':'Automatically adjust table size', + 'lang_autoSizeContent':'Adaptive by form text', + 'lang_orderbycontent':"Table of contents sortable", + 'lang_autoSizePage':'Page width adaptive', + 'lang_example':'Example', + 'lang_borderStyle':'Table Border', + 'lang_color':'Color:' + }, + captionName:'Caption', + titleName:'Title', + cellsName:'text', + errorMsg:'There are merged cells, can not sort.' + }, + 'edittip':{ + 'static':{ + lang_delRow:'Delete entire row', + lang_delCol:'Delete entire col' + } + }, + 'edittd':{ + 'static':{ + lang_tdBkColor:'Background Color:' + } + }, + 'formula':{ + 'static':{ + } + }, + wordimage:{ + 'static':{ + lang_resave:"The re-save step", + uploadBtn:{src:"upload.png", alt:"Upload"}, + clipboard:{style:"background: url(copy.png) -153px -1px no-repeat;"}, + lang_step:" 1. Click top button to copy the url and then open the dialog to paste it. 2. Open after choose photos uploaded process." + }, + fileType:"Image", + flashError:"Flash initialization failed!", + netError:"Network error! Please try again!", + copySuccess:"URL has been copied!", + + 'flashI18n':{ + lang:encodeURI( '{"UploadingState":"totalNum: ${a},uploadComplete: ${b}", "BeforeUpload":"waitingNum: ${a}", "ExceedSize":"Size exceed${a}", "ErrorInPreview":"Preview failed", "DefaultDescription":"Description", "LoadingImage":"Loading..."}' ), + uploadingTF:encodeURI( '{"font":"Arial", "size":12, "color":"0x000", "bold":"true", "italic":"false", "underline":"false"}' ), + imageTF:encodeURI( '{"font":"Arial", "size":11, "color":"red", "bold":"false", "italic":"false", "underline":"false"}' ), + textEncoding:"utf-8", + addImageSkinURL:"addImage.png", + allDeleteBtnUpSkinURL:"allDeleteBtnUpSkin.png", + allDeleteBtnHoverSkinURL:"allDeleteBtnHoverSkin.png", + rotateLeftBtnEnableSkinURL:"rotateLeftEnable.png", + rotateLeftBtnDisableSkinURL:"rotateLeftDisable.png", + rotateRightBtnEnableSkinURL:"rotateRightEnable.png", + rotateRightBtnDisableSkinURL:"rotateRightDisable.png", + deleteBtnEnableSkinURL:"deleteEnable.png", + deleteBtnDisableSkinURL:"deleteDisable.png", + backgroundURL:'', + listBackgroundURL:'', + buttonURL:'button.png' + } + }, +}; diff --git a/public/static/plugs/ueditor/lang/en/images/addimage.png b/public/static/plugs/ueditor/lang/en/images/addimage.png new file mode 100644 index 0000000..3a2fd17 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/addimage.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/alldeletebtnhoverskin.png b/public/static/plugs/ueditor/lang/en/images/alldeletebtnhoverskin.png new file mode 100644 index 0000000..355eeab Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/alldeletebtnhoverskin.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/alldeletebtnupskin.png b/public/static/plugs/ueditor/lang/en/images/alldeletebtnupskin.png new file mode 100644 index 0000000..61658ce Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/alldeletebtnupskin.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/background.png b/public/static/plugs/ueditor/lang/en/images/background.png new file mode 100644 index 0000000..d5bf5fd Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/background.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/button.png b/public/static/plugs/ueditor/lang/en/images/button.png new file mode 100644 index 0000000..098874c Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/button.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/copy.png b/public/static/plugs/ueditor/lang/en/images/copy.png new file mode 100644 index 0000000..f982e8b Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/copy.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/deletedisable.png b/public/static/plugs/ueditor/lang/en/images/deletedisable.png new file mode 100644 index 0000000..c8ee750 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/deletedisable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/deleteenable.png b/public/static/plugs/ueditor/lang/en/images/deleteenable.png new file mode 100644 index 0000000..26acc88 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/deleteenable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/listbackground.png b/public/static/plugs/ueditor/lang/en/images/listbackground.png new file mode 100644 index 0000000..4f82ccd Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/listbackground.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/localimage.png b/public/static/plugs/ueditor/lang/en/images/localimage.png new file mode 100644 index 0000000..dcecad4 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/localimage.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/music.png b/public/static/plugs/ueditor/lang/en/images/music.png new file mode 100644 index 0000000..2f495fe Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/music.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/rotateleftdisable.png b/public/static/plugs/ueditor/lang/en/images/rotateleftdisable.png new file mode 100644 index 0000000..741526e Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/rotateleftdisable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/rotateleftenable.png b/public/static/plugs/ueditor/lang/en/images/rotateleftenable.png new file mode 100644 index 0000000..e164ddb Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/rotateleftenable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/rotaterightdisable.png b/public/static/plugs/ueditor/lang/en/images/rotaterightdisable.png new file mode 100644 index 0000000..5a78c26 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/rotaterightdisable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/rotaterightenable.png b/public/static/plugs/ueditor/lang/en/images/rotaterightenable.png new file mode 100644 index 0000000..d768531 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/rotaterightenable.png differ diff --git a/public/static/plugs/ueditor/lang/en/images/upload.png b/public/static/plugs/ueditor/lang/en/images/upload.png new file mode 100644 index 0000000..7bb15b3 Binary files /dev/null and b/public/static/plugs/ueditor/lang/en/images/upload.png differ diff --git a/public/static/plugs/ueditor/lang/zh-cn/images/copy.png b/public/static/plugs/ueditor/lang/zh-cn/images/copy.png new file mode 100644 index 0000000..b2536aa Binary files /dev/null and b/public/static/plugs/ueditor/lang/zh-cn/images/copy.png differ diff --git a/public/static/plugs/ueditor/lang/zh-cn/images/localimage.png b/public/static/plugs/ueditor/lang/zh-cn/images/localimage.png new file mode 100644 index 0000000..ba5f07a Binary files /dev/null and b/public/static/plugs/ueditor/lang/zh-cn/images/localimage.png differ diff --git a/public/static/plugs/ueditor/lang/zh-cn/images/music.png b/public/static/plugs/ueditor/lang/zh-cn/images/music.png new file mode 100644 index 0000000..354edeb Binary files /dev/null and b/public/static/plugs/ueditor/lang/zh-cn/images/music.png differ diff --git a/public/static/plugs/ueditor/lang/zh-cn/images/upload.png b/public/static/plugs/ueditor/lang/zh-cn/images/upload.png new file mode 100644 index 0000000..08d4d92 Binary files /dev/null and b/public/static/plugs/ueditor/lang/zh-cn/images/upload.png differ diff --git a/public/static/plugs/ueditor/lang/zh-cn/zh-cn.js b/public/static/plugs/ueditor/lang/zh-cn/zh-cn.js new file mode 100644 index 0000000..a4df4a4 --- /dev/null +++ b/public/static/plugs/ueditor/lang/zh-cn/zh-cn.js @@ -0,0 +1,748 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-6-12 + * Time: 下午5:02 + * To change this template use File | Settings | File Templates. + */ +UE.I18N['zh-cn'] = { + 'labelMap': { + 'anchor': '锚点', + 'undo': '撤销', + 'redo': '重做', + 'bold': '加粗', + 'indent': '首行缩进', + 'italic': '斜体', + 'underline': '下划线', + 'strikethrough': '删除线', + 'subscript': '下标', + 'fontborder': '字符边框', + 'superscript': '上标', + 'formatmatch': '格式刷', + 'source': '源代码', + 'blockquote': '引用', + 'pasteplain': '纯文本粘贴模式', + 'selectall': '全选', + 'print': '打印', + 'preview': '预览', + 'horizontal': '分隔线', + 'removeformat': '清除格式', + 'time': '时间', + 'date': '日期', + 'unlink': '取消链接', + 'insertrow': '前插入行', + 'insertcol': '前插入列', + 'mergeright': '右合并单元格', + 'mergedown': '下合并单元格', + 'deleterow': '删除行', + 'deletecol': '删除列', + 'splittorows': '拆分成行', + 'splittocols': '拆分成列', + 'splittocells': '完全拆分单元格', + 'deletecaption': '删除表格标题', + 'inserttitle': '插入标题', + 'mergecells': '合并多个单元格', + 'deletetable': '删除表格', + 'cleardoc': '清空文档', + 'insertparagraphbeforetable': "表格前插入行", + 'insertcode': '代码语言', + 'fontfamily': '字体', + 'fontsize': '字号', + 'paragraph': '段落格式', + 'simpleupload': '单图上传', + 'insertimage': '插入图片', + 'edittable': '表格属性', + 'edittd': '单元格属性', + 'link': '超链接', + 'emotion': '表情', + 'spechars': '特殊字符', + 'searchreplace': '查询替换', + 'insertvideo': '视频', + 'insertaudio': '音频', + 'help': '帮助', + 'justifyleft': '居左对齐', + 'justifyright': '居右对齐', + 'justifycenter': '居中对齐', + 'justifyjustify': '两端对齐', + 'forecolor': '字体颜色', + 'backcolor': '背景色', + 'insertorderedlist': '有序列表', + 'insertunorderedlist': '无序列表', + 'fullscreen': '全屏', + 'directionalityltr': '从左向右输入', + 'directionalityrtl': '从右向左输入', + 'rowspacingtop': '段前距', + 'rowspacingbottom': '段后距', + 'pagebreak': '分页', + 'insertframe': '插入Iframe', + 'imagenone': '默认', + 'imageleft': '左浮动', + 'imageright': '右浮动', + 'attachment': '附件', + 'imagecenter': '居中', + 'wordimage': '图片转存', + 'formula': '公式', + 'lineheight': '行间距', + 'edittip': '编辑提示', + 'customstyle': '自定义标题', + 'autotypeset': '自动排版', + 'touppercase': '字母大写', + 'tolowercase': '字母小写', + 'background': '背景', + 'template': '模板', + 'scrawl': '涂鸦', + 'inserttable': '插入表格', + }, + 'autosave': { + 'autoRestoreTip': '已自动从草稿箱恢复' + }, + 'insertorderedlist': { + 'num': '1,2,3...', + 'num1': '1),2),3)...', + 'num2': '(1),(2),(3)...', + 'cn': '一,二,三....', + 'cn1': '一),二),三)....', + 'cn2': '(一),(二),(三)....', + 'decimal': '1,2,3...', + 'lower-alpha': 'a,b,c...', + 'lower-roman': 'i,ii,iii...', + 'upper-alpha': 'A,B,C...', + 'upper-roman': 'I,II,III...' + }, + 'insertunorderedlist': { + 'circle': '○ 大圆圈', + 'disc': '● 小黑点', + 'square': '■ 小方块 ', + 'dash': '— 破折号', + 'dot': ' 。 小圆圈' + }, + 'paragraph': {'p': '段落', 'h1': '标题 1', 'h2': '标题 2', 'h3': '标题 3', 'h4': '标题 4', 'h5': '标题 5', 'h6': '标题 6'}, + 'fontfamily': { + 'default': '默认', + 'songti': '宋体', + 'kaiti': '楷体', + 'heiti': '黑体', + 'lishu': '隶书', + 'yahei': '微软雅黑', + // 'andaleMono':'andale mono', + 'arial': 'arial', + // 'arialBlack':'arial black', + // 'comicSansMs':'comic sans ms', + // 'impact':'impact', + 'timesNewRoman': 'times new roman' + }, + 'customstyle': { + 'tc': '标题居中', + 'tl': '标题居左', + 'im': '强调', + 'hi': '明显强调' + }, + 'autoupload': { + 'exceedSizeError': '文件大小超出限制', + 'exceedTypeError': '文件格式不允许', + 'jsonEncodeError': '服务器返回格式错误', + 'loading': "正在上传...", + 'loadError': "上传错误", + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!' + }, + 'simpleupload': { + 'exceedSizeError': '文件大小超出限制', + 'exceedTypeError': '文件格式不允许', + 'jsonEncodeError': '服务器返回格式错误', + 'loading': "正在上传...", + 'loadError': "上传错误", + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!' + }, + 'elementPathTip': "元素路径", + 'wordCountTip': "字数统计", + 'wordCountMsg': '{#count} / {#leave}', + 'wordOverFlowMsg': '字数超出最大允许值,服务器可能拒绝保存!', + 'ok': "确认", + 'cancel': "取消", + 'closeDialog': "关闭对话框", + 'tableDrag': "表格拖动必须引入uiUtils.js文件!", + 'autofloatMsg': "工具栏浮动依赖编辑器UI,您首先需要引入UI文件!", + 'loadconfigError': '获取后台配置项请求出错,上传功能将不能正常使用!', + 'loadconfigFormatError': '后台配置项返回格式出错,上传功能将不能正常使用!', + 'loadconfigHttpError': '请求后台配置项http错误,上传功能将不能正常使用!', + 'insertcode': { + 'as3': 'ActionScript 3', + 'bash': 'Bash/Shell', + 'cpp': 'C/C++', + 'css': 'CSS', + 'cf': 'ColdFusion', + 'c#': 'C#', + 'delphi': 'Delphi', + 'diff': 'Diff', + 'erlang': 'Erlang', + 'groovy': 'Groovy', + 'html': 'HTML', + 'java': 'Java', + 'jfx': 'JavaFX', + 'js': 'JavaScript', + 'pl': 'Perl', + 'php': 'PHP', + 'plain': 'Plain Text', + 'ps': 'PowerShell', + 'python': 'Python', + 'ruby': 'Ruby', + 'scala': 'Scala', + 'sql': 'SQL', + 'vb': 'Visual Basic', + 'xml': 'XML' + }, + 'confirmClear': "确定清空当前文档么?", + 'contextMenu': { + 'delete': "删除", + 'selectall': "全选", + 'deletecode': "删除代码", + 'cleardoc': "清空文档", + 'confirmclear': "确定清空当前文档么?", + 'unlink': "删除超链接", + 'paragraph': "段落格式", + 'edittable': "表格属性", + 'aligntd': "单元格对齐方式", + 'aligntable': '表格对齐方式', + 'tableleft': '左浮动', + 'tablecenter': '居中显示', + 'tableright': '右浮动', + 'edittd': "单元格属性", + 'setbordervisible': '设置表格边线可见', + 'justifyleft': '左对齐', + 'justifyright': '右对齐', + 'justifycenter': '居中对齐', + 'justifyjustify': '两端对齐', + 'table': "表格", + 'inserttable': '插入表格', + 'deletetable': "删除表格", + 'insertparagraphbefore': "前插入段落", + 'insertparagraphafter': '后插入段落', + 'deleterow': "删除当前行", + 'deletecol': "删除当前列", + 'insertrow': "前插入行", + 'insertcol': "左插入列", + 'insertrownext': '后插入行', + 'insertcolnext': '右插入列', + 'insertcaption': '插入表格名称', + 'deletecaption': '删除表格名称', + 'inserttitle': '插入表格标题行', + 'deletetitle': '删除表格标题行', + 'inserttitlecol': '插入表格标题列', + 'deletetitlecol': '删除表格标题列', + 'averageDiseRow': '平均分布各行', + 'averageDisCol': '平均分布各列', + 'mergeright': "向右合并", + 'mergeleft': "向左合并", + 'mergedown': "向下合并", + 'mergecells': "合并单元格", + 'splittocells': "完全拆分单元格", + 'splittocols': "拆分成列", + 'splittorows': "拆分成行", + 'tablesort': '表格排序', + 'enablesort': '设置表格可排序', + 'disablesort': '取消表格可排序', + 'reversecurrent': '逆序当前', + 'orderbyasc': '按ASCII字符升序', + 'reversebyasc': '按ASCII字符降序', + 'orderbynum': '按数值大小升序', + 'reversebynum': '按数值大小降序', + 'borderbk': '边框底纹', + 'setcolor': '表格隔行变色', + 'unsetcolor': '取消表格隔行变色', + 'setbackground': '选区背景隔行', + 'unsetbackground': '取消选区背景', + 'redandblue': '红蓝相间', + 'threecolorgradient': '三色渐变', + 'copy': "复制(Ctrl + c)", + 'copymsg': "浏览器不支持,请使用 'Ctrl + c'", + 'paste': "粘贴(Ctrl + v)", + 'pastemsg': "浏览器不支持,请使用 'Ctrl + v'" + }, + 'copymsg': "浏览器不支持,请使用 'Ctrl + c'", + 'pastemsg': "浏览器不支持,请使用 'Ctrl + v'", + 'anchorMsg': "链接", + 'clearColor': '清空颜色', + 'standardColor': '标准颜色', + 'themeColor': '主题颜色', + 'property': '属性', + 'default': '默认', + 'modify': '修改', + 'save': '保存', + 'formulaedit': '公式修改', + 'justifyleft': '左对齐', + 'justifyright': '右对齐', + 'justifycenter': '居中', + 'justify': '默认', + 'clear': '清除', + 'delete': '删除', + 'clickToUpload': "点击上传", + 'unset': '尚未设置语言文件', + 't_row': '行', + 't_col': '列', + 'more': '更多', + 'pasteOpt': '粘贴选项', + 'pasteSourceFormat': "保留源格式", + 'tagFormat': '只保留标签', + 'pasteTextFormat': '只保留文本', + 'autoTypeSet': { + 'mergeLine': "合并空行", + 'delLine': "清除空行", + 'removeFormat': "清除格式", + 'indent': "首行缩进", + 'alignment': "对齐方式", + 'imageFloat': "图片浮动", + 'removeFontsize': "清除字号", + 'removeFontFamily': "清除字体", + 'removeHtml': "清除冗余HTML代码", + 'pasteFilter': "粘贴过滤", + 'run': "执行", + 'symbol': '符号转换', + 'bdc2sb': '全角转半角', + 'tobdc': '半角转全角' + }, + + 'background': { + 'static': { + 'lang_background_normal': '背景设置', + 'lang_background_local': '在线图片', + 'lang_background_set': '选项', + 'lang_background_none': '无背景色', + 'lang_background_colored': '有背景色', + 'lang_background_color': '颜色设置', + 'lang_background_netimg': '网络图片', + 'lang_background_align': '对齐方式', + 'lang_background_position': '精确定位', + 'repeatType': {'options': ["居中", "横向重复", "纵向重复", "平铺", "自定义"]} + + }, + 'noUploadImage': "当前未上传过任何图片!", + 'toggleSelect': "单击可切换选中状态\n原图尺寸: " + }, + //===============dialog i18N======================= + 'insertimage': { + 'static': { + 'lang_tab_remote': "插入图片", //节点 + 'lang_tab_upload': "本地上传", + 'lang_tab_online': "在线管理", + 'lang_input_url': "地 址:", + 'lang_input_size': "大 小:", + 'lang_input_width': "宽度", + 'lang_input_height': "高度", + 'lang_input_border': "边 框:", + 'lang_input_vhspace': "边 距:", + 'lang_input_title': "描 述:", + 'lang_input_align': '图片浮动方式:', + 'lang_imgLoading': " 图片加载中……", + 'lang_start_upload': "开始上传", + 'lock': {'title': "锁定宽高比例"}, //属性 + 'searchType': {'title': "图片类型", 'options': ["新闻", "壁纸", "表情", "头像"]}, //select的option + 'searchTxt': {'value': "请输入搜索关键词"}, + 'searchBtn': {'value': "百度一下"}, + 'searchReset': {'value': "清空搜索"}, + 'noneAlign': {'title': '无浮动'}, + 'leftAlign': {'title': '左浮动'}, + 'rightAlign': {'title': '右浮动'}, + 'centerAlign': {'title': '居中独占一行'} + }, + 'uploadSelectFile': '点击选择图片', + 'uploadAddFile': '继续添加', + 'uploadStart': '开始上传', + 'uploadPause': '暂停上传', + 'uploadContinue': '继续上传', + 'uploadRetry': '重试上传', + 'uploadDelete': '删除', + 'uploadTurnLeft': '向左旋转', + 'uploadTurnRight': '向右旋转', + 'uploadPreview': '预览中', + 'uploadNoPreview': '不能预览', + 'updateStatusReady': '选中_张图片,共_KB。', + 'updateStatusConfirm': '已成功上传_张照片,_张照片上传失败', + 'updateStatusFinish': '共_张(_KB),_张上传成功', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize': '文件大小超出', + 'errorFileType': '文件格式不允许', + 'errorInterrupt': '文件传输中断', + 'errorUploadRetry': '上传失败,请重试', + 'errorHttp': 'http请求错误', + 'errorServerUpload': '服务器返回出错', + 'remoteLockError': "宽高不正确,不能所定比例", + 'numError': "请输入正确的长度或者宽度值!例如:123,400", + 'imageUrlError': "不允许的图片格式或者图片域!", + 'imageLoadError': "图片加载失败!请检查链接地址或网络状态!", + 'searchRemind': "请输入搜索关键词", + 'searchLoading': "图片加载中,请稍后……", + 'searchRetry': " :( ,抱歉,没有找到图片!请重试一次!" + }, + 'attachment': { + 'static': { + 'lang_tab_upload': '上传附件', + 'lang_tab_online': '在线附件', + 'lang_start_upload': "开始上传", + 'lang_drop_remind': "可以将文件拖到这里,单次最多可选100个文件" + }, + 'uploadSelectFile': '点击选择文件', + 'uploadAddFile': '继续添加', + 'uploadStart': '开始上传', + 'uploadPause': '暂停上传', + 'uploadContinue': '继续上传', + 'uploadRetry': '重试上传', + 'uploadDelete': '删除', + 'uploadTurnLeft': '向左旋转', + 'uploadTurnRight': '向右旋转', + 'uploadPreview': '预览中', + 'updateStatusReady': '选中_个文件,共_KB。', + 'updateStatusConfirm': '已成功上传_个文件,_个文件上传失败', + 'updateStatusFinish': '共_个(_KB),_个上传成功', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize': '文件大小超出', + 'errorFileType': '文件格式不允许', + 'errorInterrupt': '文件传输中断', + 'errorUploadRetry': '上传失败,请重试', + 'errorHttp': 'http请求错误', + 'errorServerUpload': '服务器返回出错' + }, + 'insertvideo': { + 'static': { + 'lang_tab_insertV': "插入视频", + 'lang_tab_searchV': "搜索视频", + 'lang_tab_uploadV': "上传视频", + 'lang_video_url': "视频网址", + 'lang_video_size': "视频尺寸", + 'lang_videoW': "宽度", + 'lang_videoH': "高度", + 'lang_alignment': "对齐方式", + 'videoSearchTxt': {'value': "请输入搜索关键字!"}, + 'videoType': {'options': ["全部", "热门", "娱乐", "搞笑", "体育", "科技", "综艺"]}, + 'videoSearchBtn': {'value': "百度一下"}, + 'videoSearchReset': {'value': "清空结果"}, + + 'lang_input_fileStatus': ' 当前未上传文件', + 'startUpload': {'style': "background:url(upload.png) no-repeat;"}, + + 'lang_upload_size': "视频尺寸", + 'lang_upload_width': "宽度", + 'lang_upload_height': "高度", + 'lang_upload_alignment': "对齐方式", + 'lang_format_advice': "建议使用mp4格式." + + }, + 'numError': "请输入正确的数值,如123,400", + 'floatLeft': "左浮动", + 'floatRight': "右浮动", + 'default': "默认", + 'block': "独占一行", + 'urlError': "输入的视频地址有误,请检查后再试!", + 'loading': "  视频加载中,请等待……", + 'clickToSelect': "点击选中", + 'goToSource': '访问源视频', + 'noVideo': "    抱歉,找不到对应的视频,请重试!", + + 'browseFiles': '浏览文件', + 'uploadSuccess': '上传成功!', + 'delSuccessFile': '从成功队列中移除', + 'delFailSaveFile': '移除保存失败文件', + 'statusPrompt': ' 个文件已上传! ', + 'flashVersionError': '当前Flash版本过低,请更新FlashPlayer后重试!', + 'flashLoadingError': 'Flash加载失败!请检查路径或网络状态', + 'fileUploadReady': '等待上传……', + 'delUploadQueue': '从上传队列中移除', + 'limitPrompt1': '单次不能选择超过', + 'limitPrompt2': '个文件!请重新选择!', + 'delFailFile': '移除失败文件', + 'fileSizeLimit': '文件大小超出限制!', + 'emptyFile': '空文件无法上传!', + 'fileTypeError': '文件类型不允许!', + 'unknownError': '未知错误!', + 'fileUploading': '上传中,请等待……', + 'cancelUpload': '取消上传', + 'netError': '网络错误', + 'failUpload': '上传失败!', + 'serverIOError': '服务器IO错误!', + 'noAuthority': '无权限!', + 'fileNumLimit': '上传个数限制', + 'failCheck': '验证失败,本次上传被跳过!', + 'fileCanceling': '取消中,请等待……', + 'stopUploading': '上传已停止……', + + 'uploadSelectFile': '点击选择文件', + 'uploadAddFile': '继续添加', + 'uploadStart': '开始上传', + 'uploadPause': '暂停上传', + 'uploadContinue': '继续上传', + 'uploadRetry': '重试上传', + 'uploadDelete': '删除', + 'uploadTurnLeft': '向左旋转', + 'uploadTurnRight': '向右旋转', + 'uploadPreview': '预览中', + 'updateStatusReady': '选中_个文件,共_KB。', + 'updateStatusConfirm': '成功上传_个,_个失败', + 'updateStatusFinish': '共_个(_KB),_个成功上传', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize': '文件大小超出', + 'errorFileType': '文件格式不允许', + 'errorInterrupt': '文件传输中断', + 'errorUploadRetry': '上传失败,请重试', + 'errorHttp': 'http请求错误', + 'errorServerUpload': '服务器返回出错' + }, + 'insertaudio': { + 'static': { + 'lang_tab_insertV': "插入音频", + 'lang_tab_searchV': "搜索音频", + 'lang_tab_uploadV': "上传音频", + 'lang_video_url': "音频网址", + 'lang_video_size': "音频尺寸", + 'lang_videoW': "宽度", + 'lang_videoH': "高度", + 'lang_alignment': "对齐方式", + 'videoSearchTxt': {'value': "请输入搜索关键字!"}, + 'videoType': {'options': ["全部", "热门", "娱乐", "搞笑", "体育", "科技", "综艺"]}, + 'videoSearchBtn': {'value': "百度一下"}, + 'videoSearchReset': {'value': "清空结果"}, + + 'lang_input_fileStatus': ' 当前未上传文件', + 'startUpload': {'style': "background:url(upload.png) no-repeat;"}, + + 'lang_upload_size': "音频尺寸", + 'lang_upload_width': "宽度", + 'lang_upload_height': "高度", + 'lang_upload_alignment': "对齐方式", + 'lang_format_advice': "建议使用mp4格式." + + }, + 'numError': "请输入正确的数值,如123,400", + 'floatLeft': "左浮动", + 'floatRight': "右浮动", + 'default': "默认", + 'block': "独占一行", + 'urlError': "输入的音频地址有误,请检查后再试!", + 'loading': "  音频加载中,请等待……", + 'clickToSelect': "点击选中", + 'goToSource': '访问源音频', + 'noVideo': "    抱歉,找不到对应的音频,请重试!", + + 'browseFiles': '浏览文件', + 'uploadSuccess': '上传成功!', + 'delSuccessFile': '从成功队列中移除', + 'delFailSaveFile': '移除保存失败文件', + 'statusPrompt': ' 个文件已上传! ', + 'flashVersionError': '当前Flash版本过低,请更新FlashPlayer后重试!', + 'flashLoadingError': 'Flash加载失败!请检查路径或网络状态', + 'fileUploadReady': '等待上传……', + 'delUploadQueue': '从上传队列中移除', + 'limitPrompt1': '单次不能选择超过', + 'limitPrompt2': '个文件!请重新选择!', + 'delFailFile': '移除失败文件', + 'fileSizeLimit': '文件大小超出限制!', + 'emptyFile': '空文件无法上传!', + 'fileTypeError': '文件类型不允许!', + 'unknownError': '未知错误!', + 'fileUploading': '上传中,请等待……', + 'cancelUpload': '取消上传', + 'netError': '网络错误', + 'failUpload': '上传失败!', + 'serverIOError': '服务器IO错误!', + 'noAuthority': '无权限!', + 'fileNumLimit': '上传个数限制', + 'failCheck': '验证失败,本次上传被跳过!', + 'fileCanceling': '取消中,请等待……', + 'stopUploading': '上传已停止……', + + 'uploadSelectFile': '点击选择文件', + 'uploadAddFile': '继续添加', + 'uploadStart': '开始上传', + 'uploadPause': '暂停上传', + 'uploadContinue': '继续上传', + 'uploadRetry': '重试上传', + 'uploadDelete': '删除', + 'uploadTurnLeft': '向左旋转', + 'uploadTurnRight': '向右旋转', + 'uploadPreview': '预览中', + 'updateStatusReady': '选中_个文件,共_KB。', + 'updateStatusConfirm': '成功上传_个,_个失败', + 'updateStatusFinish': '共_个(_KB),_个成功上传', + 'updateStatusError': ',_张上传失败。', + 'errorNotSupport': 'WebUploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器。', + 'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!', + 'errorExceedSize': '文件大小超出', + 'errorFileType': '文件格式不允许', + 'errorInterrupt': '文件传输中断', + 'errorUploadRetry': '上传失败,请重试', + 'errorHttp': 'http请求错误', + 'errorServerUpload': '服务器返回出错' + }, + 'template': { + 'static': { + 'lang_template_bkcolor': '背景颜色', + 'lang_template_clear': '保留原有内容', + 'lang_template_select': '选择模板' + }, + 'blank': "空白文档", + 'blog': "博客文章", + 'resume': "个人简历", + 'richText': "图文混排", + 'sciPapers': "科技论文" + + + }, + 'scrawl': { + 'static': { + 'lang_input_previousStep': "上一步", + 'lang_input_nextsStep': "下一步", + 'lang_input_clear': '清空', + 'lang_input_addPic': '添加背景', + 'lang_input_ScalePic': '缩放背景', + 'lang_input_removePic': '删除背景', + 'J_imgTxt': {title: '添加背景图片'} + }, + 'noScarwl': "尚未作画,白纸一张~", + 'scrawlUpLoading': "涂鸦上传中,别急哦~", + 'continueBtn': "继续", + 'imageError': "糟糕,图片读取失败了!", + 'backgroundUploading': '背景图片上传中,别急哦~' + }, + 'anchor': { + 'static': { + 'lang_input_anchorName': '锚点名字:' + } + }, + 'emotion': { + 'static': { + 'lang_input_choice': '精选', + 'lang_input_Tuzki': '兔斯基', + 'lang_input_BOBO': 'BOBO', + 'lang_input_lvdouwa': '绿豆蛙', + 'lang_input_babyCat': 'baby猫', + 'lang_input_bubble': '泡泡', + 'lang_input_youa': '有啊' + } + }, + 'help': { + 'static': { + 'lang_input_about': '关于 UEditor Plus', + 'lang_input_shortcuts': '快捷键', + 'lang_input_introduction': 'UEditor Plus 是基于百度UEditor二次开发的所见即所得富文本web编辑器,主要丰富也界面样式,注重用户体验等特点。基于Apache 2.0协议开源,允许自由使用和修改代码。', + 'lang_Txt_shortcuts': '快捷键', + 'lang_Txt_func': '功能', + 'lang_Txt_bold': '给选中字设置为加粗', + 'lang_Txt_copy': '复制选中内容', + 'lang_Txt_cut': '剪切选中内容', + 'lang_Txt_Paste': '粘贴', + 'lang_Txt_undo': '重新执行上次操作', + 'lang_Txt_redo': '撤销上一次操作', + 'lang_Txt_italic': '给选中字设置为斜体', + 'lang_Txt_underline': '给选中字加下划线', + 'lang_Txt_selectAll': '全部选中', + 'lang_Txt_visualEnter': '软回车', + 'lang_Txt_fullscreen': '全屏' + } + }, + 'insertframe': { + 'static': { + 'lang_input_address': '地址:', + 'lang_input_width': '宽度:', + 'lang_input_height': '高度:', + 'lang_input_isScroll': '允许滚动条:', + 'lang_input_frameborder': '显示框架边框:', + 'lang_input_alignMode': '对齐方式:', + 'align': {title: "对齐方式", options: ["默认", "左对齐", "右对齐", "居中"]} + }, + 'enterAddress': '请输入地址!' + }, + 'link': { + 'static': { + 'lang_input_text': '文本内容:', + 'lang_input_url': '链接地址:', + 'lang_input_title': '标题:', + 'lang_input_target': '是否在新窗口打开:' + }, + 'validLink': '只支持选中一个链接时生效', + 'httpPrompt': '您输入的超链接中不包含http等协议名称,默认将为您添加http://前缀' + }, + 'searchreplace': { + 'static': { + lang_tab_search: "查找", + lang_tab_replace: "替换", + lang_search1: "查找", + lang_search2: "查找", + lang_replace: "替换", + lang_searchReg: '支持正则表达式,添加前后斜杠标示为正则表达式,例如“/表达式/”', + lang_searchReg1: '支持正则表达式,添加前后斜杠标示为正则表达式,例如“/表达式/”', + lang_case_sensitive1: "区分大小写", + lang_case_sensitive2: "区分大小写", + nextFindBtn: {value: "下一个"}, + preFindBtn: {value: "上一个"}, + nextReplaceBtn: {value: "下一个"}, + preReplaceBtn: {value: "上一个"}, + repalceBtn: {value: "替换"}, + repalceAllBtn: {value: "全部替换"} + }, + getEnd: "已经搜索到文章末尾!", + getStart: "已经搜索到文章头部", + countMsg: "总共替换了{#count}处!" + }, + 'spechars': { + 'static': {}, + tsfh: "特殊字符", + lmsz: "罗马字符", + szfh: "数学字符", + rwfh: "日文字符", + xlzm: "希腊字母", + ewzm: "俄文字符", + pyzm: "拼音字母", + yyyb: "英语音标", + zyzf: "其他" + }, + 'edittable': { + 'static': { + 'lang_tableStyle': '表格样式', + 'lang_insertCaption': '添加表格名称行', + 'lang_insertTitle': '添加表格标题行', + 'lang_insertTitleCol': '添加表格标题列', + 'lang_orderbycontent': "使表格内容可排序", + 'lang_tableSize': '自动调整表格尺寸', + 'lang_autoSizeContent': '按表格文字自适应', + 'lang_autoSizePage': '按页面宽度自适应', + 'lang_example': '示例', + 'lang_borderStyle': '表格边框', + 'lang_color': '颜色:' + }, + captionName: '表格名称', + titleName: '标题', + cellsName: '内容', + errorMsg: '有合并单元格,不可排序' + }, + 'edittip': { + 'static': { + lang_delRow: '删除整行', + lang_delCol: '删除整列' + } + }, + 'edittd': { + 'static': { + lang_tdBkColor: '背景颜色:' + } + }, + 'formula': { + 'static': {} + }, + 'wordimage': { + 'static': { + lang_resave: "转存步骤", + uploadBtn: {src: "upload.png", alt: "上传"}, + clipboard: {style: "background: url(copy.png) -153px -1px no-repeat;"}, + lang_step: "1、点击顶部复制按钮,将地址复制到剪贴板;2、点击添加照片按钮,在弹出的对话框中使用Ctrl+V粘贴地址;3、点击打开后选择图片上传流程。" + }, + 'fileType': "图片", + 'flashError': "FLASH初始化失败,请检查FLASH插件是否正确安装!", + 'netError': "网络连接错误,请重试!", + 'copySuccess': "图片地址已经复制!", + 'flashI18n': {} //留空默认中文 + }, +}; diff --git a/public/static/plugs/ueditor/plugins/demo/demo.js b/public/static/plugs/ueditor/plugins/demo/demo.js new file mode 100644 index 0000000..addd6e0 --- /dev/null +++ b/public/static/plugs/ueditor/plugins/demo/demo.js @@ -0,0 +1,3 @@ +(function () { + +})(); diff --git a/public/static/plugs/ueditor/themes/default/css/ueditor.css b/public/static/plugs/ueditor/themes/default/css/ueditor.css new file mode 100644 index 0000000..80b359a --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/css/ueditor.css @@ -0,0 +1,2091 @@ +/*基础UI构建 +*/ +:root { + --edui-color-active-bg: rgba(200, 200, 200, 0.3); + --edui-color-border: #EEEEEE; + --edui-bg-toolbar: #FFFFFF; + --edui-color-muted: #CCCCCC; +} +@font-face { + font-family: "edui-iconfont"; + /* Project id 2897874 */ + src: url("data:application/octet-stream;base64,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") format('woff2'), url("data:application/octet-stream;base64,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") format('woff'), url("data:application/octet-stream;base64,AAEAAAALAIAAAwAwR1NVQiCLJXoAAAE4AAAAVE9TLzI8QFDMAAABjAAAAGBjbWFwoearHAAAA3QAAAguZ2x5ZoJvAGEAAAxsAABQeGhlYWQliGcsAAAA4AAAADZoaGVhB+UD+wAAALwAAAAkaG10eIgm//YAAAHsAAABiGxvY2HxZ91uAAALpAAAAMZtYXhwAX8A5gAAARgAAAAgbmFtZQlTMroAAFzkAAACo3Bvc3SGsMIgAABfiAAABQUAAQAAA4D/gABcBB3////7BAcAAQAAAAAAAAAAAAAAAAAAAGIAAQAAAAEAAOsAow9fDzz1AAsEAAAAAADhMZGpAAAAAOExkan///9VBAcDiAAAAAgAAgAAAAAAAAABAAAAYgDaABMAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKADAAPgACREZMVAAObGF0bgAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAQEAAGQAAUAAAKJAswAAACPAokCzAAAAesAMgEIAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAwOYA7fwDgP+AAAAD3ACrAAAAAQAAAAAAAAAAAAAAAAACBAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAP//BAD//wQA//8EAP//BAAAAAQA//8EAAAABAAAAAQA//8EAP//BAAAAAQA//8EAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABB0AAAQAAAAEAAAABAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAP//BAAAAAQAAAAEAAAABAAAAAQAAAAAAAAFAAAAAwAAACwAAAAEAAADhgABAAAAAAKAAAMAAQAAACwAAwAKAAADhgAEAlQAAABgAEAABQAg5iTmKOYq5i3mL+Y45j7mROZK5kzmVuZi5mXmaeZ15nrmgOaX5qfmrebA5tjm+ucE5wvnGuc15zfnUud754Lnree859Ln+Of86D7oQuh86JHpAekr6fDrCuts7Ont/P//AADmAOYo5irmLeYv5jbmPuZE5kjmTOZW5mLmZeZp5nXmeuaA5pfmp+at5sDm2Ob45wTnC+ca5zXnN+dS53vnguet57zn0efz5/zoPuhC6HvokekB6Svp8OsJ62zs6e37//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAYACoAKgAqACoAKgArACsAKwAsACwALAAsACwALAAsACwALAAsACwALAAsACwALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC2AMAAwADAAMAAwgDCAMIAwgDCAMQAxADEAAAAMgAzADQANQA2AFwANwA4AFMAOQA6ADsAPAA9AEwAPgAiACMAJAAfACAAIQBOAB4AGQAcAB0AGwAZABoAGAAUABUAFgAXAAcABgBhAF0ASwAuAFoAQQBKAFsACgBeADAAXwBgAA0AUQACABIARAAQABEACwBQAEYABQBCAEcASABJACwADwAxAEUAKQAOAAEAUgBAAAgAKgArAFUAKABWAFcAWABZAAQALwBDABMATQAMACUAVABPACYAJwAJAC0APwADAAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAASoAAAAAAAAAGIAAOYAAADmAAAAADIAAOYBAADmAQAAADMAAOYCAADmAgAAADQAAOYDAADmAwAAADUAAOYEAADmBAAAADYAAOYFAADmBQAAAFwAAOYGAADmBgAAADcAAOYHAADmBwAAADgAAOYIAADmCAAAAFMAAOYJAADmCQAAADkAAOYKAADmCgAAADoAAOYLAADmCwAAADsAAOYMAADmDAAAADwAAOYNAADmDQAAAD0AAOYOAADmDgAAAEwAAOYPAADmDwAAAD4AAOYQAADmEAAAACIAAOYRAADmEQAAACMAAOYSAADmEgAAACQAAOYTAADmEwAAAB8AAOYUAADmFAAAACAAAOYVAADmFQAAACEAAOYWAADmFgAAAE4AAOYXAADmFwAAAB4AAOYYAADmGAAAABkAAOYZAADmGQAAABwAAOYaAADmGgAAAB0AAOYbAADmGwAAABsAAOYcAADmHAAAABkAAOYdAADmHQAAABoAAOYeAADmHgAAABgAAOYfAADmHwAAABQAAOYgAADmIAAAABUAAOYhAADmIQAAABYAAOYiAADmIgAAABcAAOYjAADmIwAAAAcAAOYkAADmJAAAAAYAAOYoAADmKAAAAGEAAOYqAADmKgAAAF0AAOYtAADmLQAAAEsAAOYvAADmLwAAAC4AAOY2AADmNgAAAFoAAOY3AADmNwAAAEEAAOY4AADmOAAAAEoAAOY+AADmPgAAAFsAAOZEAADmRAAAAAoAAOZIAADmSAAAAF4AAOZJAADmSQAAADAAAOZKAADmSgAAAF8AAOZMAADmTAAAAGAAAOZWAADmVgAAAA0AAOZiAADmYgAAAFEAAOZlAADmZQAAAAIAAOZpAADmaQAAABIAAOZ1AADmdQAAAEQAAOZ6AADmegAAABAAAOaAAADmgAAAABEAAOaXAADmlwAAAAsAAOanAADmpwAAAFAAAOatAADmrQAAAEYAAObAAADmwAAAAAUAAObYAADm2AAAAEIAAOb4AADm+AAAAEcAAOb5AADm+QAAAEgAAOb6AADm+gAAAEkAAOcEAADnBAAAACwAAOcLAADnCwAAAA8AAOcaAADnGgAAADEAAOc1AADnNQAAAEUAAOc3AADnNwAAACkAAOdSAADnUgAAAA4AAOd7AADnewAAAAEAAOeCAADnggAAAFIAAOetAADnrQAAAEAAAOe8AADnvAAA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MQAuADAAZQBkAHUAaQAtAGkAYwBvAG4AZgBvAG4AdABHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYgECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8BQAFBAUIBQwFEAUUBRgFHAUgBSQFKAUsBTAFNAU4BTwFQAVEBUgFTAVQBVQFWAVcBWAFZAVoBWwFcAV0BXgFfAWABYQFiAWMABXNvdW5kBXJpZ2h0D2ljX2ltYWdlX3VwbG9hZAVjaGVjawZpZnJhbWUQQmFja2dyb3VuZEVmZmVjdANsdHIDcnRsC2ZpbmRyZXBsYWNlCWljcHJldmlldwVyaXFpMgtldXJvLXN5bWJvbAVtdXNpYwRoZWxwCWhhbmRfZHJhdwVwcmludAR0aW1lBWJhaWR1C0dvb2dsZS1NYXBzCmltYWdlLW5vbmUMaW1hZ2UtY2VudGVyCmltYWdlLWxlZnQLaW1hZ2UtcmlnaHQJY2xlYXItZG9jC3dvcmQtaW1hZ2UxCnBhZ2UtYnJlYWsGYXV0aG9yC3RvdXBwZXJjYXNlC3RvbG93ZXJjYXNlCmhvcml6b250YWwPbWVyZ2UtZG93bi1jZWxsC21lcmdlLWNlbGxzEG1lcmdlLXJpZ2h0LWNlbGwNc3BsaXQtdG8tcm93cw1zcGxpdC10by1jb2xzDnNwbGl0LXRvLWNlbGxzDmluc2VydHJvd2Fib3ZlGjI0Z2wtcGFyYWdyYXBoTWFyZ2luQm90dG9tFzI0Z2wtcGFyYWdyYXBoTWFyZ2luVG9wDXVub3JkZXJlZGxpc3QMbGlzdC1vcmRlcmVkFHNwbGl0LWNlbGxzLXZlcnRpY2FsFnNwbGl0LWNlbGxzLWhvcml6b250YWwKYXR0YWNobWVudAlzdWJzY3JpcHQJc2VsZWN0YWxsC3N1cGVyc2NyaXB0A21hcAliZy1jb2xvcnMNYWRkX2NvbF9hZnRlcg5hZGRfY29sX2JlZm9yZQ1hZGRfcm93X2FmdGVyDmFkZF9yb3dfYmVmb3JlCmRlbGV0ZV9jb2wNY29tYmluZV9jZWxscwJvbApkZWxldGVfcm93DGRlbGV0ZV90YWJsZQJ1bARyZWRvBXRhYmxlBHVuZG8FcGFzdGUGdXBsb2FkBWJydXNoCnRleHRfcXVvdGURaW5zZXJ0LXJvdy1ib3R0b20RZnVsbHNjcmVlbi1leHBhbmQOaW5zZXJ0LXJvdy10b3AIdGVtcGxhdGUSZm9ybWF0LWltYWdlLXJpZ2h0EWZvcm1hdC1pbWFnZS1sZWZ0E2Zvcm1hdC1pbWFnZS1jZW50ZXILbGluZS1oZWlnaHQXQWZ0ZXJjbGFzc1RleHQtT3V0bGluZWQFc21pbGUNYWxpZ24tanVzdGlmeQdmb3JtdWxhCmFuZ2xlLWRvd24FY2xvc2UKbWFnaWMtd2FuZAZlcmFzZXIEaHRtbAZ1bmxpbmsGaW5kZW50C2FsaWduLXJpZ2h0DGFsaWduLWNlbnRlcgphbGlnbi1sZWZ0C2ZvbnQtY29sb3JzBHBsYXkJdW5kZXJsaW5lBWltYWdlBml0YWxpYwRsaW5rBnN0cmlrZQRjb2RlBGJvbGQAAAAAAA==") format('truetype'); +} +.edui-default { + accent-color: #333; +} +/* common layer */ +.edui-default .edui-box { + border: none; + padding: 0; + margin: 0; + overflow: hidden; + line-height: 30px; +} +.edui-default a.edui-box { + display: block; + text-decoration: none; + color: black; +} +.edui-default a.edui-box:hover { + text-decoration: none; +} +.edui-default a.edui-box:active { + text-decoration: none; +} +.edui-default table.edui-box { + border-collapse: collapse; +} +.edui-default ul.edui-box { + list-style-type: none; +} +div.edui-box { + position: relative; + display: -moz-inline-box !important; + display: inline-block !important; + vertical-align: middle; +} +.edui-default .edui-clearfix { + zoom: 1; +} +.edui-default .edui-clearfix:after { + content: '\20'; + display: block; + clear: both; +} +* html div.edui-box { + display: inline !important; +} +*:first-child + html div.edui-box { + display: inline !important; +} +/* control layout */ +.edui-default .edui-button-body, +.edui-splitbutton-body, +.edui-menubutton-body, +.edui-combox-body { + position: relative; +} +.edui-default .edui-popup { + position: absolute; + -webkit-user-select: none; + -moz-user-select: none; +} +.edui-default .edui-popup .edui-shadow { + position: absolute; + z-index: -1; +} +.edui-default .edui-popup .edui-bordereraser { + position: absolute; + overflow: hidden; +} +.edui-default .edui-tablepicker .edui-canvas { + position: relative; +} +.edui-default .edui-tablepicker .edui-canvas .edui-overlay { + position: absolute; +} +.edui-default .edui-dialog-modalmask, +.edui-dialog-dragmask { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} +.edui-default .edui-toolbar { + position: relative; +} +/* + * default theme + */ +.edui-default .edui-label { + cursor: pointer; +} +.edui-default span.edui-clickable { + color: #666; + cursor: pointer; + text-decoration: none; +} +.edui-default span.edui-clickable:hover { + color: #333; +} +.edui-default span.edui-unclickable { + color: gray; + cursor: default; +} +.edui-default span.edui-popup-action-item { + margin-right: 5px; +} +.edui-default span.edui-popup-action-item:last-child { + margin-right: 0; +} + +/* 工具栏 */ +.edui-default .edui-toolbar { + cursor: default; + -webkit-user-select: none; + -moz-user-select: none; + padding: 1px; + overflow: hidden; /*全屏下单独一行不占位*/ + zoom: 1; + width:auto; + height:auto; +} + +.edui-default .edui-toolbar .edui-button, +.edui-default .edui-toolbar .edui-splitbutton, +.edui-default .edui-toolbar .edui-menubutton, +.edui-default .edui-toolbar .edui-combox { + margin: 1px; +} +/*UI工具栏、编辑区域、底部*/ +.edui-default .edui-editor { + border: 1px solid var(--edui-color-border); + background-color: white; + position: relative; + overflow: visible; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.edui-editor div{ + width:auto; + height:auto; +} +.edui-default .edui-editor-toolbarbox { + position: relative; + zoom: 1; + /*-webkit-box-shadow:0 1px 4px rgba(204, 204, 204, 0.6);*/ + /*-moz-box-shadow:0 1px 4px rgba(204, 204, 204, 0.6);*/ + /*box-shadow:0 1px 4px rgba(204, 204, 204, 0.6);*/ + border-top-left-radius:2px; + border-top-right-radius:2px; +} + +.edui-default .edui-editor-toolbarboxouter { + border-bottom: 1px solid var(--edui-color-border); + background-color: var(--edui-bg-toolbar); + /*background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);*/ + /*background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));*/ + /*background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);*/ + /*background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);*/ + /*background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);*/ + /*background-repeat: repeat-x;*/ + /*border: 1px solid #d4d4d4;*/ + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);*/ + /**zoom: 1;*/ + /*-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);*/ + /*-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);*/ + /*box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);*/ +} + +.edui-default .edui-editor-toolbarboxinner { + padding: 2px; +} + +.edui-default .edui-editor-iframeholder { + position: relative; + /*for fix ie6 toolbarmsg under iframe bug. relative -> static */ + /*_position: static !important;* +} + +.edui-default .edui-editor-iframeholder textarea { + font-family: consolas, "Courier New", "lucida console", monospace; + font-size: 12px; + line-height: 18px; +} + +.edui-default .edui-editor-bottombar { + /*border-top: 1px solid #ccc;*/ + /*height: 20px;*/ + /*width: 40%;*/ + /*float: left;*/ + /*overflow: hidden;*/ +} + +.edui-default .edui-editor-bottomContainer { + overflow: hidden; +} + +.edui-default .edui-editor-bottomContainer table { + width: 100%; + height: 0; + overflow: hidden; + border-spacing: 0; +} + +.edui-default .edui-editor-bottomContainer td { + white-space: nowrap; + border-top: 1px solid var(--edui-color-border); + line-height: 20px; + font-size: 12px; + font-family: Arial, Helvetica, Tahoma, Verdana, Sans-Serif; + padding:0 5px; + color:var(--edui-color-muted); +} + +.edui-default .edui-editor-wordcount { + text-align: right; + margin-right: 5px; + color: #aaa; +} +.edui-default .edui-editor-scale { + width: 12px; +} +.edui-default .edui-editor-scale .edui-editor-icon { + float: right; + width: 100%; + height: 12px; + margin-top: 10px; + background: url(../images/scale.png) no-repeat; + cursor: se-resize; +} +.edui-default .edui-editor-breadcrumb { + margin: 2px 0 0 3px; + color: var(--edui-color-muted); +} + +.edui-default .edui-editor-breadcrumb span { + cursor: pointer; + color: var(--edui-color-muted); + line-height: 16px; + display: inline-block; +} + +.edui-default .edui-toolbar .edui-for-fullscreen { + float: right; +} + +.edui-default .edui-bubble .edui-popup-content { + font-size: 13px; + box-shadow: 0 0 10px #0000001f; + transition: .25s; + color: #666; + background-color: #FFF; + padding: 10px; + border-radius: 5px; +} + +.edui-default .edui-bubble .edui-shadow { + /*box-shadow: 1px 1px 3px #818181;*/ + /*-webkit-box-shadow: 2px 2px 3px #818181;*/ + /*-moz-box-shadow: 2px 2px 3px #818181;*/ + /*filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius = '2', MakeShadow = 'true', ShadowOpacity = '0.5');*/ +} + +.edui-default .edui-editor-toolbarmsg { + background-color: #FFF6D9; + border-bottom: 1px solid #ccc; + position: absolute; + bottom: -25px; + left: 0; + z-index: 1009; + width: 99.9%; +} + +.edui-default .edui-editor-toolbarmsg-upload { + font-size: 14px; + color: blue; + width: 100px; + height: 16px; + line-height: 16px; + cursor: pointer; + position: absolute; + top: 5px; + left: 350px; +} + +.edui-default .edui-editor-toolbarmsg-label { + font-size: 12px; + line-height: 16px; + padding: 4px; +} + +.edui-default .edui-editor-toolbarmsg-close { + float: right; + width: 20px; + height: 16px; + line-height: 16px; + cursor: pointer; + color: red; +} + +/*可选中菜单按钮*/ +.edui-default .edui-list .edui-bordereraser { + display: none; +} + +.edui-default .edui-listitem { + padding: 1px; + white-space: nowrap; + cursor: pointer; +} + +.edui-default .edui-list .edui-state-hover { + position: relative; + background-color: #EEE; + border: 1px solid #EEE; + padding: 0; + border-radius: 3px; +} + +.edui-default .edui-for-fontfamily .edui-listitem-label { + min-width: 130px; + _width: 120px; + font-size: 12px; + height: 22px; + line-height: 22px; + padding-left: 5px; +} +.edui-default .edui-for-insertcode .edui-listitem-label { + min-width: 120px; + _width: 120px; + font-size: 12px; + height: 22px; + line-height: 22px; + padding-left: 5px; +} +.edui-default .edui-for-underline .edui-listitem-label { + min-width: 120px; + _width: 120px; + padding: 3px 5px; + font-size: 12px; +} + +.edui-default .edui-for-fontsize .edui-listitem-label { + min-width: 120px; + _width: 120px; + padding: 3px 5px; + cursor: pointer; +} + +.edui-default .edui-for-paragraph .edui-listitem-label { + min-width: 200px; + _width: 200px; + padding: 2px 5px; +} + +.edui-default .edui-for-rowspacingtop .edui-listitem-label, +.edui-default .edui-for-rowspacingbottom .edui-listitem-label { + min-width: 53px; + _width: 53px; + padding: 2px 5px; +} + +.edui-default .edui-for-lineheight .edui-listitem-label { + min-width: 53px; + _width: 53px; + padding: 2px 5px; +} + +.edui-default .edui-for-customstyle .edui-listitem-label { + min-width: 200px; + _width: 200px; + width: 200px !important; + padding: 2px 5px; +} + +/* 可选中按钮弹出菜单*/ +.edui-default .edui-menu { + z-index: 3000; +} + +.edui-default .edui-menu .edui-popup-content { + padding: 3px; +} + +.edui-default .edui-menu-body { + _width: 150px; + min-width: 170px; + background: url("../images/sparator_v.png") repeat-y 25px; +} + +.edui-default .edui-menuitem-body { +} + +.edui-default .edui-menuitem { + height: 24px; + line-height: 22px; + cursor: default; + vertical-align: top; +} + +.edui-default .edui-menuitem .edui-icon { + width: 20px !important; + height: 20px !important; + /*background: url(../images/icons.png) 0 -4000px;*/ + /*background: url(../images/icons.gif) 0 -4000px\9;*/ + font-family: 'edui-iconfont'; + font-size: 12px; + line-height: 20px; + text-align: center; +} + +.edui-default .edui-menuitem .edui-menuitem-body .edui-icon:before{ + display:none; +} + +.edui-default .edui-contextmenu .edui-popup-content .edui-menuitem-body .edui-icon:before{ + display: inline-block; +} + +.edui-default .edui-menuitem .edui-label { + font-size: 12px; + line-height: 20px; + height: 20px; + padding-left: 10px; +} + +.edui-default .edui-state-checked .edui-menuitem-body .edui-icon{ + line-height:20px; + text-align:center; +} +.edui-default .edui-state-checked .edui-menuitem-body .edui-icon:before{ + content: "\e7fc"; + font-size: 10px; + display:inline-block; +} + +.edui-default .edui-state-disabled .edui-menuitem-label { + color: gray; +} + + +/*不可选中菜单按钮 */ +.edui-default .edui-toolbar .edui-combox-body .edui-button-body { + width: 60px; + font-size: 12px; + height: 30px; + line-height: 30px; + padding-left: 5px; + white-space: nowrap; + margin: 0 3px 0 0; + cursor: pointer; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-arrow { + height: 30px; + width: 13px; + cursor: pointer; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-arrow:before{ + content: "\e9f0"; + font-family: "edui-iconfont"; + font-size: 8px; +} + +.edui-default .edui-toolbar .edui-combox .edui-combox-body { + border: 1px solid var(--edui-color-border); + background-color: white; + border-radius: 2px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; +} + +.edui-default .edui-toolbar .edui-combox .edui-combox-body > div { + vertical-align: top; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-splitborder { + display: none; +} + +.edui-default .edui-toolbar .edui-combox-body .edui-arrow { + border-left: 1px solid var(--edui-color-border); +} + +.edui-default .edui-toolbar .edui-state-hover .edui-combox-body { + /*background-color: #fff5d4;*/ + /*border: 1px solid #dcac6c;*/ +} + +.edui-default .edui-toolbar .edui-state-hover .edui-combox-body .edui-arrow { + /*border-left: 1px solid #dcac6c;*/ +} + +.edui-default .edui-toolbar .edui-state-checked .edui-combox-body { + background-color: #FFE69F; + border: 1px solid #DCAC6C; +} + +.edui-toolbar .edui-state-checked .edui-combox-body .edui-arrow { + border-left: 1px solid #DCAC6C; +} + +.edui-toolbar .edui-state-disabled .edui-combox-body { + background-color: #F0F0EE; + opacity: 0.3; +} + +.edui-toolbar .edui-state-opened .edui-combox-body { + background-color: white; + border: 1px solid gray; +} + +/*普通按钮样式及状态*/ +.edui-default .edui-toolbar .edui-button .edui-icon, +.edui-default .edui-toolbar .edui-menubutton .edui-icon, +.edui-default .edui-toolbar .edui-splitbutton .edui-icon { + height: 30px !important; + width: 30px !important; + /*background-image: url(../images/icons.png);*/ + /*background-image: url(../images/icons.gif) \9;*/ + background-position: center; + background-repeat: no-repeat; + font-family: "edui-iconfont"; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 16px; + text-align: center; + cursor: pointer; +} + +.edui-default .edui-toolbar .edui-button .edui-button-wrap { + padding: 1px; + position: relative; + border-radius: 3px; +} + +.edui-default .edui-toolbar .edui-button .edui-state-hover .edui-button-wrap { + background-color: #EEE; + border: 1px solid #EEE; + padding: 0; +} + +.edui-default .edui-toolbar .edui-button .edui-state-checked .edui-button-wrap { + background-color: #F0F0EE; + padding: 0; + border: 1px solid #EEE; + border-radius: 2px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; +} + +.edui-default .edui-toolbar .edui-button .edui-state-active .edui-button-wrap { + background-color: #F0F0EE; + padding: 0; + border: 1px solid var(--edui-color-border); +} +.edui-default .edui-toolbar .edui-state-disabled .edui-label { + color: #ccc; +} +.edui-default .edui-toolbar .edui-state-disabled .edui-icon { + opacity: 0.3; + filter: alpha(opacity = 30); +} + +.edui-default .edui-toolbar-button-custom{ + display: inline-block !important; + line-height: 30px; + vertical-align: middle; + padding: 0 10px; + border-radius: 3px; + margin: 0 5px; +} + +.edui-default .edui-toolbar-button-custom:hover{ + background: #EEE; +} + +/* toolbar icons */ +.edui-default .edui-for-undo .edui-icon:before { + content: "\e60f"; +} + +.edui-default .edui-for-redo .edui-icon:before { + content: "\e60c"; +} + +.edui-default .edui-for-bold .edui-icon:before { + content: "\e628"; +} + +.edui-default .edui-for-italic .edui-icon:before { + content: "\e62a"; +} + +.edui-default .edui-for-fontborder .edui-icon:before { + content: '\e62d'; +} +.edui-default .edui-for-underline .edui-icon:before { + content: "\e63e"; +} + +.edui-default .edui-for-strikethrough .edui-icon:before { + content: "\e64a"; +} + +.edui-default .edui-for-subscript .edui-icon:before { + content: "\ece9"; +} + +.edui-default .edui-for-superscript .edui-icon:before { + content: "\e83e"; +} + +.edui-default .edui-for-blockquote .edui-icon:before { + content: "\e6d8"; +} + +.edui-default .edui-for-forecolor .edui-icon:before { + content: "\e7f8"; +} + +.edui-default .edui-for-backcolor .edui-icon:before { + content: "\e71a"; +} + +.edui-default .edui-for-inserttable .edui-icon:before { + content: "\e60d"; +} + +.edui-default .edui-for-autotypeset .edui-icon:before { + content: "\e662"; +} + +.edui-default .edui-for-justifyleft .edui-icon:before { + content: "\e7f7"; +} + +.edui-default .edui-for-justifycenter .edui-icon:before { + content: "\e7f6"; +} + +.edui-default .edui-for-justifyright .edui-icon:before { + content: "\e7f5"; +} + +.edui-default .edui-for-justifyjustify .edui-icon:before { + content: "\e87c"; +} + +.edui-default .edui-for-insertorderedlist .edui-icon:before { + content: "\e737"; +} + +.edui-default .edui-for-insertunorderedlist .edui-icon:before { + content: "\e7f4"; +} + +.edui-default .edui-for-lineheight .edui-icon:before { + content: "\e638"; +} + +.edui-default .edui-for-rowspacingbottom .edui-icon:before { + content: '\eb09'; +} + +.edui-default .edui-for-rowspacingtop .edui-icon:before { + content: '\eb0a'; +} + +.edui-default .edui-for-horizontal .edui-icon:before { + content: "\e617"; +} + +.edui-default .edui-for-link .edui-icon:before { + content: "\e648"; +} + +.edui-default .edui-for-code .edui-icon:before { + background-position: -440px -40px; +} + +.edui-default .edui-for-insertimage .edui-icon:before { + content: "\e605"; +} + +.edui-default .edui-for-insertframe .edui-icon:before { + content: "\e6c0"; +} + +.edui-default .edui-for-emoticon .edui-icon:before { + content: "\e60e"; +} + +.edui-default .edui-for-spechars .edui-icon:before { + content: "\e891"; +} + +.edui-default .edui-for-help .edui-icon:before { + content: "\e752"; +} + +.edui-default .edui-for-print .edui-icon:before { + content: "\e67a"; +} + +.edui-default .edui-for-preview .edui-icon:before { + content: "\e644"; +} + +.edui-default .edui-for-selectall .edui-icon:before { + content: '\e62f'; +} + +.edui-default .edui-for-searchreplace .edui-icon:before { + content: "\eb6c"; +} + +.edui-default .edui-for-map .edui-icon:before { + content: "\e649"; +} + +.edui-default .edui-for-insertvideo .edui-icon:before { + content: "\e636"; +} + +.edui-default .edui-for-insertaudio .edui-icon:before { + content: "\e77b"; +} + +.edui-default .edui-for-time .edui-icon:before { + content: "\e680"; +} + +.edui-default .edui-for-date .edui-icon:before { + content: "\e697"; +} + +.edui-default .edui-for-cut .edui-icon:before { + background-position: -680px 0; +} + +.edui-default .edui-for-copy .edui-icon:before { + background-position: -700px 0; +} + +.edui-default .edui-for-paste .edui-icon:before { + background-position: -560px 0; +} + +.edui-default .edui-for-formatmatch .edui-icon:before { + content: "\e637"; +} + +.edui-default .edui-for-pasteplain .edui-icon:before { + content: '\edfb'; +} + +.edui-default .edui-for-directionalityltr .edui-icon:before { + content: "\e623"; +} + +.edui-default .edui-for-directionalityrtl .edui-icon:before { + content: "\e7bc"; +} + +.edui-default .edui-for-source .edui-icon:before { + content: "\e608"; +} + +.edui-default .edui-for-removeformat .edui-icon:before { + content: "\e782"; +} + +.edui-default .edui-for-unlink .edui-icon:before { + content: "\e92b"; +} + +.edui-default .edui-for-touppercase .edui-icon:before { + content: "\e619"; +} + +.edui-default .edui-for-tolowercase .edui-icon:before { + content: "\e61a"; +} + +.edui-default .edui-for-insertrow .edui-icon:before { + content: "\e603"; +} + +.edui-default .edui-for-insertrownext .edui-icon:before { + content: "\e602"; +} + +.edui-default .edui-for-insertcol .edui-icon:before { + content: "\e601"; +} + +.edui-default .edui-for-insertcolnext .edui-icon:before { + content: "\e600"; +} + +.edui-default .edui-for-mergeright .edui-icon:before { + content: "\e615"; +} + +.edui-default .edui-for-mergedown .edui-icon:before { + content: "\e613"; +} + +.edui-default .edui-for-splittorows .edui-icon:before { + content: "\e610"; +} + +.edui-default .edui-for-splittocols .edui-icon:before { + content: "\e611"; +} + +.edui-default .edui-for-insertparagraphbeforetable .edui-icon:before { + content: '\e901'; +} + +.edui-default .edui-for-deleterow .edui-icon:before { + content: "\e609"; +} + +.edui-default .edui-for-deletecol .edui-icon:before { + content: "\e604"; +} + +.edui-default .edui-for-splittocells .edui-icon:before { + content: "\e612"; +} + +.edui-default .edui-for-mergecells .edui-icon:before { + content: "\e606"; +} + +.edui-default .edui-for-deletetable .edui-icon:before { + content: "\e60a"; +} + +.edui-default .edui-for-cleardoc .edui-icon:before { + content: "\e61e"; +} + +.edui-default .edui-for-fullscreen .edui-icon:before { + content: "\e675"; +} + +.edui-default .edui-for-anchor .edui-icon:before { + content: "\e61b"; +} + +.edui-default .edui-for-pagebreak .edui-icon:before { + content: "\e61d"; +} + +.edui-default .edui-for-imagenone .edui-icon:before { + content: "\e61f"; +} + +.edui-default .edui-for-imageleft .edui-icon:before { + content: "\e621"; +} + +.edui-default .edui-for-wordimage .edui-icon:before { + content: "\e618"; +} + +.edui-default .edui-for-imageright .edui-icon:before { + content: "\e622"; +} + +.edui-default .edui-for-imagecenter .edui-icon:before { + content: "\e620"; +} + +.edui-default .edui-for-indent .edui-icon:before { + content: "\e7f3"; +} + +.edui-default .edui-for-outdent .edui-icon:before { + background-position: -540px 0; +} + +.edui-default .edui-for-table .edui-icon:before { + background-position: -580px -20px; +} + +.edui-default .edui-for-edittable .edui-icon:before { + background-position: -420px -40px; +} + +.edui-default .edui-for-template .edui-icon:before { + content: "\e6ad"; +} + +.edui-default .edui-for-delete .edui-icon:before { + background-position: -360px -40px; +} + +.edui-default .edui-for-attachment .edui-icon:before { + content: "\e704"; +} + +.edui-default .edui-for-edittd .edui-icon:before { + background-position: -700px -40px; +} + +.edui-default .edui-for-scrawl .edui-icon:before { + content: "\e70b"; +} + +.edui-default .edui-for-background .edui-icon:before { + content: "\e624"; +} + +.edui-default .edui-for-formula .edui-icon:before { + content: "\e616"; +} + +.edui-default .edui-for-aligntd .edui-icon:before { + background-position: -236px -76px; +} + +.edui-default .edui-for-insertparagraphtrue .edui-icon:before { + background-position: -625px -76px; +} + +.edui-default .edui-for-insertparagraph .edui-icon:before { + background-position: -602px -76px; +} + +.edui-default .edui-for-insertcaption .edui-icon:before { + background-position: -336px -76px; +} + +.edui-default .edui-for-deletecaption .edui-icon:before { + background-position: -362px -76px; +} + +.edui-default .edui-for-inserttitle .edui-icon:before { + background-position: -286px -76px; +} + +.edui-default .edui-for-deletetitle .edui-icon:before { + background-position: -311px -76px; +} + +.edui-default .edui-for-aligntable .edui-icon:before { + background-position: -440px 0; +} + +.edui-default .edui-for-tablealignment-left .edui-icon:before { + background-position: -460px 0; +} + +.edui-default .edui-for-tablealignment-center .edui-icon:before { + background-position: -420px 0; +} + +.edui-default .edui-for-tablealignment-right .edui-icon:before { + background-position: -480px 0; +} + +.edui-default .edui-for-inserttitlecol .edui-icon:before { + background-position: -673px -76px; +} + +.edui-default .edui-for-deletetitlecol .edui-icon:before { + background-position: -698px -76px; +} + +.edui-default .edui-for-simpleupload .edui-icon:before { + content: "\edfc"; +} + +/*splitbutton*/ +.edui-default .edui-toolbar .edui-splitbutton-body .edui-arrow, +.edui-default .edui-toolbar .edui-menubutton-body .edui-arrow { + height: 30px; + width: 13px; + cursor: pointer; +} +.edui-default .edui-toolbar .edui-splitbutton-body .edui-arrow:before, +.edui-default .edui-toolbar .edui-menubutton-body .edui-arrow:before { + content: "\e9f0"; + font-family: "edui-iconfont"; + font-size: 8px; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-menubutton-body { + padding: 1px; + border-radius: 3px; +} + +.edui-default .edui-toolbar .edui-splitborder { + /*width: 1px;*/ + width: 0px; + height: 30px; +} + +.edui-default .edui-toolbar .edui-state-hover .edui-splitborder { + /*width: 1px;*/ + border-left: 0px solid #dcac6c; +} + +.edui-default .edui-toolbar .edui-state-active .edui-splitborder { + width: 0; + /*border-left: 1px solid #EEE;*/ +} + +.edui-default .edui-toolbar .edui-state-opened .edui-splitborder { + /*width: 1px;*/ + border: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-hover .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-hover .edui-menubutton-body { + background-color: #EEE; + border: 1px solid #EEE; + padding: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-checked .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-checked .edui-menubutton-body { + background-color: #ffffff; + border: 1px solid #EEE; + padding: 0; +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-active .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-active .edui-menubutton-body { + background-color: #ffffff; + border: 1px solid #EEE; + padding: 0; +} + +.edui-default .edui-state-disabled .edui-arrow { + opacity: 0.3; + _filter: alpha(opacity = 30); +} + +.edui-default .edui-toolbar .edui-splitbutton .edui-state-opened .edui-splitbutton-body, +.edui-default .edui-toolbar .edui-menubutton .edui-state-opened .edui-menubutton-body { + background-color: white; + border: 1px solid #EEE; + padding: 0; +} + +.edui-default .edui-for-insertorderedlist .edui-bordereraser, +.edui-default .edui-for-lineheight .edui-bordereraser, +.edui-default .edui-for-rowspacingtop .edui-bordereraser, +.edui-default .edui-for-rowspacingbottom .edui-bordereraser, +.edui-default .edui-for-insertunorderedlist .edui-bordereraser { + background-color: white; +} + +/* 解决嵌套导致的图标问题 */ +.edui-default .edui-for-insertorderedlist .edui-popup-body .edui-icon, +.edui-default .edui-for-lineheight .edui-popup-body .edui-icon, +.edui-default .edui-for-rowspacingtop .edui-popup-body .edui-icon, +.edui-default .edui-for-rowspacingbottom .edui-popup-body .edui-icon, +.edui-default .edui-for-insertunorderedlist .edui-popup-body .edui-icon { + /*background-position: 0 -40px;*/ + background-image: none ; +} + +/* 弹出菜单 */ +.edui-default .edui-popup { + z-index: 3000; + background-color: #ffffff; + width:auto; + height:auto; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + margin-top:1px; +} + +.edui-default .edui-popup .edui-shadow { + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +.edui-default .edui-popup-content { + font-size: 13px; + box-shadow: 0 0 10px rgba(0,0,0,0.2); + transition: .25s; + color: #333; + background-color: #FFF; + padding: 10px; + border-radius: 5px; +} + +.edui-default .edui-popup .edui-bordereraser { + background-color: transparent; + height: 3px; +} + +.edui-default .edui-menu .edui-bordereraser { + height: 3px; +} + +.edui-default .edui-anchor-topleft .edui-bordereraser { + left: 1px; + top: -2px; +} + +.edui-default .edui-anchor-topright .edui-bordereraser { + right: 1px; + top: -2px; +} + +.edui-default .edui-anchor-bottomleft .edui-bordereraser { + left: 0; + bottom: -6px; + height: 7px; + border-left: 1px solid gray; + border-right: 1px solid gray; +} + +.edui-default .edui-anchor-bottomright .edui-bordereraser { + right: 0; + bottom: -6px; + height: 7px; + border-left: 1px solid gray; + border-right: 1px solid gray; +} + +.edui-popup div{ + width:auto; + height:auto; +} + +.edui-default .edui-editor-messageholder { + display: block; + width: 150px; + height: auto; + border: 0; + margin: 0; + padding: 0; + position: absolute; + top: 28px; + right: 3px; +} + +.edui-default .edui-message{ + min-height: 10px; + text-shadow: 0 1px 0 rgba(255,255,255,0.5); + padding: 0; + margin-bottom: 3px; + position: relative; +} +.edui-default .edui-message-body{ + border-radius: 3px; + padding: 8px 15px 8px 8px; + color: #c09853; + background-color: #fcf8e3; + border: 1px solid #fbeed5; +} +.edui-default .edui-message-type-info{ + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1 +} +.edui-default .edui-message-type-success{ + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6 +} +.edui-default .edui-message-type-danger, +.edui-default .edui-message-type-error{ + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7 +} +.edui-default .edui-message .edui-message-closer { + display: block; + width: 16px; + height: 16px; + line-height: 16px; + position: absolute; + top: 0; + right: 0; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + float: right; + font-size: 20px; + font-weight: bold; + color: #999; + text-shadow: 0 1px 0 #fff; + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; +} +.edui-default .edui-message .edui-message-content { + font-size: 10pt; + word-wrap: break-word; + word-break: normal; +} +/* 弹出对话框按钮和对话框大小 */ +.edui-default .edui-dialog { + z-index: 2000; + position: absolute; + +} + +.edui-dialog div { + width: auto; +} + +.edui-default .edui-dialog-wrap { + margin-right: 6px; + margin-bottom: 6px; +} + +.edui-default .edui-dialog-fullscreen-flag { + margin-right: 0; + margin-bottom: 0; +} + +.edui-default .edui-dialog-body { + position: relative; + /*padding:2px 0 0 2px;*/ + /*_zoom: 1;*/ +} + +.edui-default .edui-dialog-fullscreen-flag .edui-dialog-body { + padding: 0; +} + +.edui-default .edui-dialog-shadow { + position: absolute; + z-index: -1; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #ffffff; + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 3px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.edui-default .edui-dialog-foot { + background-color: white; + border-radius: 0 0 5px 5px; + height: 40px; +} + +.edui-default .edui-dialog-titlebar { + height: 30px; + background: #FFF; + position: relative; + cursor: move; + border-radius: 5px 5px 0 0; +} + +.edui-default .edui-dialog-caption { + font-weight: bold; + font-size: 14px; + line-height: 30px; + padding-left: 5px; +} + +.edui-default .edui-dialog-draghandle { + height: 30px; + padding: 5px; +} + +.edui-default .edui-dialog-closebutton { + position: absolute !important; + right: 10px; + top: 10px; +} + +.edui-default .edui-dialog-closebutton .edui-button-body { + height: 20px; + width: 20px; + cursor: pointer; +} + +.edui-default .edui-dialog-closebutton .edui-button-body .edui-icon { + width: 20px; + height: 20px; + font-family: 'edui-iconfont'; + line-height: 20px; + font-size: 20px; + text-align: center; + color: #999; + vertical-align: top; +} + +.edui-default .edui-dialog-closebutton .edui-button-body .edui-icon:before { + content: "\e6a7"; +} + +.edui-default .edui-dialog-closebutton .edui-state-hover .edui-button-body .edui-icon { + color: #333; +} + +.edui-default .edui-dialog-buttons { + position: absolute; + right: 0; +} + +.edui-default .edui-dialog-buttons .edui-button { + margin-right: 10px; +} + +.edui-default .edui-dialog-buttons .edui-button .edui-button-body .edui-icon { + display: none !important; +} + +.edui-default .edui-dialog-buttons .edui-button .edui-button-body { + height: 30px; + font-size: 12px; + line-height: 28px; + cursor: pointer; + border-radius: 4px; + text-align: center; + background-color: #F8F8F8; + border: 1px solid #EEE; + padding: 0 15px; +} + +.edui-default .edui-dialog-buttons .edui-button .edui-state-hover .edui-button-body { + +} + +.edui-default .edui-dialog iframe { + border: 0; + padding: 0; + margin: 0; + vertical-align: top; +} + +.edui-default .edui-dialog-modalmask { + opacity: 0.3; + filter: alpha(opacity=30); + background-color: #ccc; + position: absolute; + /*z-index: 1999;*/ +} + +.edui-default .edui-dialog-dragmask { + position: absolute; + /*z-index: 2001;*/ + background-color: transparent; + cursor: move; +} + +.edui-default .edui-dialog-content { + position: relative; +} + +.edui-default .dialogcontmask { + cursor: move; + visibility: hidden; + display: block; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + filter: alpha(opacity=0); +} + +/*link-dialog*/ +.edui-default .edui-for-link .edui-dialog-content { + width: 420px; + height: 200px; + overflow: hidden; +} + +/*background-dialog*/ +.edui-default .edui-for-background .edui-dialog-content { + width: 440px; + height: 280px; + overflow: hidden; +} + +/*template-dialog*/ +.edui-default .edui-for-template .edui-dialog-content { + width: 630px; + height: 390px; + overflow: hidden; +} + +/*scrawl-dialog*/ +.edui-default .edui-for-scrawl .edui-dialog-content { + width: 515px; + *width: 506px; + height: 360px; +} + +/*spechars-dialog*/ +.edui-default .edui-for-spechars .edui-dialog-content { + width: 620px; + height: 500px; + *width: 630px; + *height: 570px; +} + +/*image-dialog*/ +.edui-default .edui-for-insertimage .edui-dialog-content { + width: 650px; + height: 400px; + overflow: hidden; +} + +/*image-insertframe*/ +.edui-default .edui-for-insertframe .edui-dialog-content { + width: 350px; + height: 230px; + overflow: hidden; +} + +/*wordImage-dialog*/ +.edui-default .edui-for-wordimage .edui-dialog-content { + width: 620px; + height: 380px; + overflow: hidden; +} + +/*formula-dialog*/ +.edui-default .edui-for-formula .edui-dialog-content { + width: 800px; + height: 400px; + overflow: hidden; +} + +/*attachment-dialog*/ +.edui-default .edui-for-attachment .edui-dialog-content { + width: 650px; + height: 400px; + overflow: hidden; +} + + +/*map-dialog*/ +.edui-default .edui-for-map .edui-dialog-content { + width: 550px; + height: 400px; +} + +/*video-dialog*/ +.edui-default .edui-for-insertvideo .edui-dialog-content { + width: 590px; + height: 420px; +} + +/*audio-dialog*/ +.edui-default .edui-for-insertaudio .edui-dialog-content { + width: 590px; + height: 420px; +} + +/*anchor-dialog*/ +.edui-default .edui-for-anchor .edui-dialog-content { + width: 320px; + height: 60px; + overflow: hidden; +} + +/*searchreplace-dialog*/ +.edui-default .edui-for-searchreplace .edui-dialog-content { + width: 400px; + height: 220px; +} + +/*help-dialog*/ +.edui-default .edui-for-help .edui-dialog-content { + width: 400px; + height: 420px; +} + +/*edittable-dialog*/ +.edui-default .edui-for-edittable .edui-dialog-content { + width: 540px; + _width: 590px; + height: 335px; +} + +/*edittip-dialog*/ +.edui-default .edui-for-edittip .edui-dialog-content { + width: 225px; + height: 60px; +} + +/*edittd-dialog*/ +.edui-default .edui-for-edittd .edui-dialog-content { + width: 240px; + height: 50px; +} + +/*段落弹出菜单*/ +.edui-default .edui-for-paragraph .edui-listitem-label { + font-family: Tahoma, Verdana, Arial, Helvetica; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-p { + font-size: 22px; + line-height: 27px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h1 { + font-weight: bolder; + font-size: 32px; + line-height: 36px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h2 { + font-weight: bolder; + font-size: 27px; + line-height: 29px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h3 { + font-weight: bolder; + font-size: 19px; + line-height: 23px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h4 { + font-weight: bolder; + font-size: 16px; + line-height: 19px +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h5 { + font-weight: bolder; + font-size: 13px; + line-height: 16px; +} + +.edui-default .edui-for-paragraph .edui-listitem-label .edui-for-h6 { + font-weight: bolder; + font-size: 12px; + line-height: 14px; +} +/* 表格弹出菜单 */ +.edui-default .edui-for-inserttable .edui-splitborder { + display: none +} +.edui-default .edui-for-inserttable .edui-splitbutton-body .edui-arrow { + width: 0 +} +.edui-default .edui-toolbar .edui-for-inserttable .edui-state-active .edui-splitborder{ + border-left: 1px solid transparent; +} +.edui-default .edui-tablepicker .edui-infoarea { + height: 14px; + line-height: 14px; + font-size: 12px; + width: 220px; + margin-bottom: 3px; + clear: both; +} + +.edui-default .edui-tablepicker .edui-infoarea .edui-label { + float: left; +} + +.edui-default .edui-dialog-buttons .edui-label { + line-height: 30px; +} + +.edui-default .edui-tablepicker .edui-infoarea .edui-clickable { + float: right; +} + +.edui-default .edui-tablepicker .edui-pickarea { + background: url("../images/unhighlighted.gif") repeat; + height: 220px; + width: 220px; +} + +.edui-default .edui-tablepicker .edui-pickarea .edui-overlay { + background: url("../images/highlighted.gif") repeat; +} + +/* 颜色弹出菜单 */ +.edui-default .edui-colorpicker-topbar { + height: 27px; + width: 200px; + /*border-bottom: 1px gray dashed;*/ +} + +.edui-default .edui-colorpicker-preview { + height: 20px; + border: 1px inset black; + margin-left: 1px; + width: 128px; + float: left; + border-radius:3px; + position: relative; +} + +.edui-default .edui-colorpicker-preview input{ + padding: 0; + left: 0; + border: 0; + position: absolute; + top: 0; + width: 100%; + height: 100%; + border-radius: 3px; + opacity: 0; + cursor: pointer; +} + +.edui-default .edui-colorpicker-nocolor { + float: right; + margin-right: 1px; + font-size: 12px; + line-height: 20px; + height: 20px; + border: 1px solid #333; + padding: 0 5px; + cursor: pointer; + border-radius: 3px; + box-sizing: content-box; +} + +.edui-default .edui-colorpicker-tablefirstrow { + height: 30px; +} + +.edui-default .edui-colorpicker-colorcell { + width: 14px; + height: 14px; + display: block; + margin: 0; + cursor: pointer; + border-radius:2px; +} + +.edui-default .edui-colorpicker-colorcell:hover { + width: 14px; + height: 14px; + margin: 0; +} +.edui-default .edui-colorpicker-advbtn{ + display: block; + text-align: center; + cursor: pointer; + height:20px; +} +.arrow_down{ + background: white url('../images/arrow_down.png') no-repeat center; +} +.arrow_up{ + background: white url('../images/arrow_up.png') no-repeat center; +} +/*高级的样式*/ +.edui-colorpicker-adv{ + position: relative; + overflow: hidden; + height: 180px; + display: none; +} +.edui-colorpicker-plant, .edui-colorpicker-hue { + border: solid 1px #666; +} +.edui-colorpicker-pad { + width: 150px; + height: 150px; + left: 14px; + top: 13px; + position: absolute; + background: red; + overflow: hidden; + cursor: crosshair; +} +.edui-colorpicker-cover{ + position: absolute; + top: 0; + left: 0; + width: 150px; + height: 150px; + background: url("../images/tangram-colorpicker.png") -160px -200px; +} +.edui-colorpicker-padDot{ + position: absolute; + top: 0; + left: 0; + width: 11px; + height: 11px; + overflow: hidden; + background: url(../images/tangram-colorpicker.png) 0px -200px repeat-x; + z-index: 1000; + +} +.edui-colorpicker-sliderMain { + position: absolute; + left: 171px; + top: 13px; + width: 19px; + height: 152px; + background: url(../images/tangram-colorpicker.png) -179px -12px no-repeat; + +} +.edui-colorpicker-slider { + width: 100%; + height: 100%; + cursor: pointer; +} +.edui-colorpicker-thumb{ + position: absolute; + top: 0; + cursor: pointer; + height: 3px; + left: -1px; + right: -1px; + border: 1px solid black; + background: white; + opacity: .8; +} + +/*自动排版弹出菜单*/ +.edui-default .edui-autotypesetpicker .edui-autotypesetpicker-body { + font-size: 12px; + margin-bottom: 3px; + clear: both; +} + +.edui-default .edui-autotypesetpicker-body table { + border-collapse: separate; + border-spacing: 2px; +} + +.edui-default .edui-autotypesetpicker-body td { + font-size: 12px; + word-wrap: break-word; +} + +.edui-default .edui-autotypesetpicker-body td input { + margin: 3px 3px 3px 4px; + *margin: 1px 0 0 0; +} + +.edui-default .edui-autotypesetpicker-body td button { + border: none; + padding: 5px 10px; + font-size: 13px; + line-height: 1.5; + border-radius: 4rem; + -webkit-appearance: none; + cursor: pointer; + margin-bottom: 5px; + background-color: #EEE; +} + +/*自动排版弹出菜单*/ +.edui-default .edui-cellalignpicker .edui-cellalignpicker-body { + width: 70px; + font-size: 12px; + cursor: default; +} + +.edui-default .edui-cellalignpicker-body table { + border-collapse: separate; + border-spacing: 0; +} +.edui-default .edui-cellalignpicker-body td{ + padding: 1px; +} +.edui-default .edui-cellalignpicker-body .edui-icon{ + height: 20px; + width: 20px; + padding: 1px; + background-image: url(../images/table-cell-align.png); +} + +.edui-default .edui-cellalignpicker-body .edui-left{ + background-position: 0 0; +} + +.edui-default .edui-cellalignpicker-body .edui-center{ + background-position: -25px 0; +} +.edui-default .edui-cellalignpicker-body .edui-right{ + background-position: -51px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-left{ + background-position: -73px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-center{ + background-position: -98px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-state-hover .edui-right{ + background-position: -124px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-left { + background-position: -146px 0; + background-color: #f1f4f5; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-center { + background-position: -245px 0; +} + +.edui-default .edui-cellalignpicker-body td.edui-cellalign-selected .edui-right { + background-position: -271px 0; +} +/*分隔线*/ +.edui-default .edui-toolbar .edui-separator { + width: 1px; + height: 20px; + margin: 5px 5px; + background: var(--edui-color-border); +} + +/*颜色按钮 */ +.edui-default .edui-toolbar .edui-colorbutton .edui-colorlump { + position: absolute; + overflow: hidden; + bottom: 1px; + left: 5px; + width: 20px; + height: 4px; +} + +/*表情按钮及弹出菜单*/ +/*去除了表情的下拉箭头*/ +.edui-default .edui-for-emotion .edui-icon:before { + content: "\e60e"; +} +.edui-default .edui-for-emotion .edui-popup-content iframe +{ + width: 514px; + height: 380px; + overflow: hidden; +} +.edui-default .edui-for-emotion .edui-popup-content +{ + position: relative; + z-index: 555 +} + +.edui-default .edui-for-emotion .edui-splitborder { + display: none +} + +.edui-default .edui-for-emotion .edui-splitbutton-body .edui-arrow +{ + width: 0 +} +.edui-default .edui-toolbar .edui-for-emotion .edui-state-active .edui-splitborder +{ + border-left: 1px solid transparent; +} + +/*contextmenu*/ +.edui-default .edui-hassubmenu .edui-arrow { + height: 20px; + width: 20px; + float: right; + /*background: url("../images/icons-all.gif") no-repeat 10px -233px;*/ + font-family: 'edui-iconfont'; + font-size:12px; + line-height:20px; + text-align:center; +} + +.edui-default .edui-hassubmenu .edui-arrow:before{ + content: "\e665"; +} + +.edui-default .edui-menu-body .edui-menuitem { + padding: 1px; +} + +.edui-default .edui-menuseparator { + margin: 2px 0; + height: 1px; + overflow: hidden; +} + +.edui-default .edui-menuseparator-inner { + border-bottom: 1px solid #e2e3e3; + margin-left: 29px; + margin-right: 1px; +} + +.edui-default .edui-menu-body .edui-state-hover { + padding: 0 !important; + background-color: var(--edui-color-active-bg); + border-radius:3px; + border:1px solid var(--edui-color-active-bg); +} + +/*弹出菜单*/ +.edui-default .edui-shortcutmenu { + padding: 2px; + /*width: 300px;*/ + white-space: nowrap; + height: auto; + background-color: #fff; + /*border: 1px solid var(--edui-color-border);*/ + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); +} + +/*粘贴弹出菜单*/ +.edui-default .edui-wordpastepop .edui-popup-content{ + border: none; + padding: 0; + width: 54px; + height: 21px; +} +.edui-default .edui-pasteicon { + width: 100%; + height: 100%; + background-image: url('../images/wordpaste.png'); + background-position: 0 0; +} + +.edui-default .edui-pasteicon.edui-state-opened { + background-position: 0 -34px; +} + +.edui-default .edui-pastecontainer { + position: relative; + visibility: hidden; + width: 97px; + background: #fff; + border: 1px solid #ccc; +} + +.edui-default .edui-pastecontainer .edui-title { + font-weight: bold; + background: #F8F8FF; + height: 25px; + line-height: 25px; + font-size: 12px; + padding-left: 5px; +} + +.edui-default .edui-pastecontainer .edui-button { + overflow: hidden; + margin: 3px 0; +} + +.edui-default .edui-pastecontainer .edui-button .edui-richtxticon, +.edui-default .edui-pastecontainer .edui-button .edui-tagicon, +.edui-default .edui-pastecontainer .edui-button .edui-plaintxticon{ + float: left; + cursor: pointer; + width: 29px; + height: 29px; + margin-left: 5px; + background-image: url('../images/wordpaste.png'); + background-repeat: no-repeat; +} +.edui-default .edui-pastecontainer .edui-button .edui-richtxticon { + margin-left: 0; + background-position: -109px 0; +} +.edui-default .edui-pastecontainer .edui-button .edui-tagicon { + background-position: -148px 1px; +} + +.edui-default .edui-pastecontainer .edui-button .edui-plaintxticon { + background-position: -72px 0; +} + +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-richtxticon { + background-position: -109px -34px; +} +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-tagicon{ + background-position: -148px -34px; +} +.edui-default .edui-pastecontainer .edui-button .edui-state-hover .edui-plaintxticon{ + background-position: -72px -34px; +} +.edui-quick-operate { + position: relative; + margin: -10px; + /*width: 40px;*/ + height: 40px; + background: #FFF; + width: 50px !important; + border-radius: 4px; +} + +.edui-quick-operate:hover .edui-quick-operate-menu { + display: block; +} + +.edui-quick-operate-status { + display: flex; +} + +.edui-quick-operate-icon { + display: inline-block; + line-height: 30px !important; + width: 30px !important; + text-align: center; + cursor: pointer; + color: #2A57FE; +} + +.edui-quick-operate-icon:last-child { + width: 20px !important; + font-size: 0; + color: #999; +} + +.edui-quick-operate-icon:last-child svg { + vertical-align: middle; +} + +.edui-quick-operate-menu { + border: 1px solid #CCC; + border-radius: 5px; + box-shadow: 0 0 10px #CCC; + position: absolute; + left: 50px; + top: 0; + background: #FFF; + width: 100px !important; + display: none; +} + +.edui-quick-operate-menu .item { + height: 30px; + line-height: 30px; + padding: 0 10px; + cursor: pointer; +} + +.edui-quick-operate-menu .item:hover { + background: #F5F5F5; +} + +.edui-quick-operate-menu .item i { + display: inline-block; + width: 2em; +} + +.edui-quick-operate .icon { + font-family: "edui-iconfont"; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +.edui-quick-operate .icon.icon-image:before { + content: "\e605"; +} + +.edui-quick-operate .icon.icon-list:before { + content: "\e87c"; +} +.edui-quick-operate .icon.icon-trash:before { + content: "\e87c"; +} diff --git a/public/static/plugs/ueditor/themes/default/dialogbase.css b/public/static/plugs/ueditor/themes/default/dialogbase.css new file mode 100644 index 0000000..6b78254 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/dialogbase.css @@ -0,0 +1,101 @@ +/*弹出对话框页面样式组件 +*/ + +/*reset +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + outline: 0; + font-size: 100%; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +ins { + text-decoration: none; +} + +del { + text-decoration: line-through; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/*module +*/ +body { + background-color: #fff; + font: 12px/1.5 sans-serif, "宋体", "Arial Narrow", HELVETICA; + color: #646464; +} + +/*tab*/ +.tabhead { + position: relative; + z-index: 10; +} + +.tabhead span { + display: inline-block; + padding: 0 5px; + height: 30px; + border: 1px solid #ccc; + background: #EEE; + text-align: center; + line-height: 30px; + cursor: pointer; + *margin-right: 5px; + border-radius: 3px 3px 0 0; +} + +.tabhead span.focus { + height: 31px; + border-bottom: none; + background: #fff; +} + +.tabbody { + position: relative; + top: -1px; + margin: 0 auto; + border: 1px solid #ccc; +} + +/*button*/ +a.button { + display: block; + text-align: center; + line-height: 24px; + text-decoration: none; + height: 24px; + width: 95px; + border: 0; + color: #838383; + background: url(../../themes/default/images/icons-all.gif) no-repeat; +} + +a.button:hover { + background-position: 0 -30px; +} diff --git a/public/static/plugs/ueditor/themes/default/exts/doc.svg b/public/static/plugs/ueditor/themes/default/exts/doc.svg new file mode 100644 index 0000000..e659bcb --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/doc.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/docx.svg b/public/static/plugs/ueditor/themes/default/exts/docx.svg new file mode 100644 index 0000000..e659bcb --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/docx.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/gif.svg b/public/static/plugs/ueditor/themes/default/exts/gif.svg new file mode 100644 index 0000000..4ac397e --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/gif.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/jpeg.svg b/public/static/plugs/ueditor/themes/default/exts/jpeg.svg new file mode 100644 index 0000000..91c03d7 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/jpeg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/jpg.svg b/public/static/plugs/ueditor/themes/default/exts/jpg.svg new file mode 100644 index 0000000..c01dc2d --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/jpg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/mp3.svg b/public/static/plugs/ueditor/themes/default/exts/mp3.svg new file mode 100644 index 0000000..a707727 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/mp3.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/mp4.svg b/public/static/plugs/ueditor/themes/default/exts/mp4.svg new file mode 100644 index 0000000..9ea1542 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/mp4.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/pdf.svg b/public/static/plugs/ueditor/themes/default/exts/pdf.svg new file mode 100644 index 0000000..b6e9ac7 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/pdf.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/png.svg b/public/static/plugs/ueditor/themes/default/exts/png.svg new file mode 100644 index 0000000..88052f3 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/png.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/ppt.svg b/public/static/plugs/ueditor/themes/default/exts/ppt.svg new file mode 100644 index 0000000..91c8ad5 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/ppt.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/pptx.svg b/public/static/plugs/ueditor/themes/default/exts/pptx.svg new file mode 100644 index 0000000..91c8ad5 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/pptx.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/rar.svg b/public/static/plugs/ueditor/themes/default/exts/rar.svg new file mode 100644 index 0000000..aefca9d --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/rar.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/torrent.svg b/public/static/plugs/ueditor/themes/default/exts/torrent.svg new file mode 100644 index 0000000..5ac15bb --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/torrent.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/txt.svg b/public/static/plugs/ueditor/themes/default/exts/txt.svg new file mode 100644 index 0000000..2f28948 --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/txt.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/unknown.svg b/public/static/plugs/ueditor/themes/default/exts/unknown.svg new file mode 100644 index 0000000..1e9926b --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/unknown.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/xls.svg b/public/static/plugs/ueditor/themes/default/exts/xls.svg new file mode 100644 index 0000000..26d50ca --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/xls.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/xlsx.svg b/public/static/plugs/ueditor/themes/default/exts/xlsx.svg new file mode 100644 index 0000000..26d50ca --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/xlsx.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/exts/zip.svg b/public/static/plugs/ueditor/themes/default/exts/zip.svg new file mode 100644 index 0000000..aefca9d --- /dev/null +++ b/public/static/plugs/ueditor/themes/default/exts/zip.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/static/plugs/ueditor/themes/default/images/anchor.gif b/public/static/plugs/ueditor/themes/default/images/anchor.gif new file mode 100644 index 0000000..5aa797b Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/anchor.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/arrow.png b/public/static/plugs/ueditor/themes/default/images/arrow.png new file mode 100644 index 0000000..d900886 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/arrow.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/arrow_down.png b/public/static/plugs/ueditor/themes/default/images/arrow_down.png new file mode 100644 index 0000000..e9257e8 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/arrow_down.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/arrow_up.png b/public/static/plugs/ueditor/themes/default/images/arrow_up.png new file mode 100644 index 0000000..74277af Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/arrow_up.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/button-bg.gif b/public/static/plugs/ueditor/themes/default/images/button-bg.gif new file mode 100644 index 0000000..ec7fa2e Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/button-bg.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/cancelbutton.gif b/public/static/plugs/ueditor/themes/default/images/cancelbutton.gif new file mode 100644 index 0000000..df4bc2c Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/cancelbutton.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/charts.png b/public/static/plugs/ueditor/themes/default/images/charts.png new file mode 100644 index 0000000..713965c Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/charts.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/cursor_h.gif b/public/static/plugs/ueditor/themes/default/images/cursor_h.gif new file mode 100644 index 0000000..d7c3e7e Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/cursor_h.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/cursor_h.png b/public/static/plugs/ueditor/themes/default/images/cursor_h.png new file mode 100644 index 0000000..2088fc2 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/cursor_h.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/cursor_v.gif b/public/static/plugs/ueditor/themes/default/images/cursor_v.gif new file mode 100644 index 0000000..bb508db Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/cursor_v.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/cursor_v.png b/public/static/plugs/ueditor/themes/default/images/cursor_v.png new file mode 100644 index 0000000..6f39ca3 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/cursor_v.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/dialog-title-bg.png b/public/static/plugs/ueditor/themes/default/images/dialog-title-bg.png new file mode 100644 index 0000000..f744f26 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/dialog-title-bg.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/filescan.png b/public/static/plugs/ueditor/themes/default/images/filescan.png new file mode 100644 index 0000000..1d27158 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/filescan.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/highlighted.gif b/public/static/plugs/ueditor/themes/default/images/highlighted.gif new file mode 100644 index 0000000..9272b49 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/highlighted.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/icons-all.gif b/public/static/plugs/ueditor/themes/default/images/icons-all.gif new file mode 100644 index 0000000..21915e5 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/icons-all.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/icons.gif b/public/static/plugs/ueditor/themes/default/images/icons.gif new file mode 100644 index 0000000..7abd30a Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/icons.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/icons.png b/public/static/plugs/ueditor/themes/default/images/icons.png new file mode 100644 index 0000000..c015e3a Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/icons.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/img-cracked.png b/public/static/plugs/ueditor/themes/default/images/img-cracked.png new file mode 100644 index 0000000..3b1d389 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/img-cracked.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/loaderror.png b/public/static/plugs/ueditor/themes/default/images/loaderror.png new file mode 100644 index 0000000..35ff333 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/loaderror.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/loading.gif b/public/static/plugs/ueditor/themes/default/images/loading.gif new file mode 100644 index 0000000..b713e27 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/loading.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/lock.gif b/public/static/plugs/ueditor/themes/default/images/lock.gif new file mode 100644 index 0000000..b4e6d78 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/lock.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/neweditor-tab-bg.png b/public/static/plugs/ueditor/themes/default/images/neweditor-tab-bg.png new file mode 100644 index 0000000..8f398b0 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/neweditor-tab-bg.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/pagebreak.gif b/public/static/plugs/ueditor/themes/default/images/pagebreak.gif new file mode 100644 index 0000000..8d1cffd Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/pagebreak.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/scale.png b/public/static/plugs/ueditor/themes/default/images/scale.png new file mode 100644 index 0000000..f45adb5 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/scale.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/sortable.png b/public/static/plugs/ueditor/themes/default/images/sortable.png new file mode 100644 index 0000000..1bca649 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/sortable.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/spacer.gif b/public/static/plugs/ueditor/themes/default/images/spacer.gif new file mode 100644 index 0000000..5bfd67a Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/spacer.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/sparator_v.png b/public/static/plugs/ueditor/themes/default/images/sparator_v.png new file mode 100644 index 0000000..8cf5662 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/sparator_v.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/table-cell-align.png b/public/static/plugs/ueditor/themes/default/images/table-cell-align.png new file mode 100644 index 0000000..ddf4285 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/table-cell-align.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/tangram-colorpicker.png b/public/static/plugs/ueditor/themes/default/images/tangram-colorpicker.png new file mode 100644 index 0000000..738e500 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/tangram-colorpicker.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/toolbar_bg.png b/public/static/plugs/ueditor/themes/default/images/toolbar_bg.png new file mode 100644 index 0000000..7ab685f Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/toolbar_bg.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/unhighlighted.gif b/public/static/plugs/ueditor/themes/default/images/unhighlighted.gif new file mode 100644 index 0000000..7ad0b67 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/unhighlighted.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/upload.png b/public/static/plugs/ueditor/themes/default/images/upload.png new file mode 100644 index 0000000..08d4d92 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/upload.png differ diff --git a/public/static/plugs/ueditor/themes/default/images/videologo.gif b/public/static/plugs/ueditor/themes/default/images/videologo.gif new file mode 100644 index 0000000..555af74 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/videologo.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/word.gif b/public/static/plugs/ueditor/themes/default/images/word.gif new file mode 100644 index 0000000..9ef5d09 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/word.gif differ diff --git a/public/static/plugs/ueditor/themes/default/images/wordpaste.png b/public/static/plugs/ueditor/themes/default/images/wordpaste.png new file mode 100644 index 0000000..9367758 Binary files /dev/null and b/public/static/plugs/ueditor/themes/default/images/wordpaste.png differ diff --git a/public/static/plugs/ueditor/themes/iframe.css b/public/static/plugs/ueditor/themes/iframe.css new file mode 100644 index 0000000..0131ced --- /dev/null +++ b/public/static/plugs/ueditor/themes/iframe.css @@ -0,0 +1,63 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-size: 14px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +a { + color: #09f; + text-decoration: none; +} + +a:hover, +a:focus { + color: #09f; + text-decoration: none; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 18px; + border-left: 5px solid #EEE; +} + +img + br { + display: block; + padding: 4px 0; + content: ' '; +} + +body p { + margin-bottom: 1em; +} + +iframe { + border: none; +} + +img { + max-width: 100%; +} + +img[data-word-image] { + cursor: pointer; +} + +pre { + margin: .5em 0; + padding: .4em .6em; + border-radius: 8px; + background: #f8f8f8; + line-height: 1.5; +} + +/*交互操作*/ +img { + cursor: pointer; +} + +.edui-quick-operate-active { + background: #E6ECFF; +} diff --git a/public/static/plugs/ueditor/third-party/SyntaxHighlighter/shCore.js b/public/static/plugs/ueditor/third-party/SyntaxHighlighter/shCore.js new file mode 100644 index 0000000..3249184 --- /dev/null +++ b/public/static/plugs/ueditor/third-party/SyntaxHighlighter/shCore.js @@ -0,0 +1,3655 @@ +// XRegExp 1.5.1 +// (c) 2007-2012 Steven Levithan +// MIT License +// +// Provides an augmented, extensible, cross-browser implementation of regular expressions, +// including support for additional syntax, flags, and methods + +var XRegExp; + +if (XRegExp) { + // Avoid running twice, since that would break references to native globals + throw Error("can't load XRegExp twice in the same frame"); +} + +// Run within an anonymous function to protect variables and avoid new globals +(function (undefined) { + + //--------------------------------- + // Constructor + //--------------------------------- + + // Accepts a pattern and flags; returns a new, extended `RegExp` object. Differs from a native + // regular expression in that additional syntax and flags are supported and cross-browser + // syntax inconsistencies are ameliorated. `XRegExp(/regex/)` clones an existing regex and + // converts to type XRegExp + XRegExp = function (pattern, flags) { + var output = [], + currScope = XRegExp.OUTSIDE_CLASS, + pos = 0, + context, tokenResult, match, chr, regex; + + if (XRegExp.isRegExp(pattern)) { + if (flags !== undefined) + throw TypeError("can't supply flags when constructing one RegExp from another"); + return clone(pattern); + } + // Tokens become part of the regex construction process, so protect against infinite + // recursion when an XRegExp is constructed within a token handler or trigger + if (isInsideConstructor) + throw Error("can't call the XRegExp constructor within token definition functions"); + + flags = flags || ""; + context = { // `this` object for custom tokens + hasNamedCapture: false, + captureNames: [], + hasFlag: function (flag) {return flags.indexOf(flag) > -1;}, + setFlag: function (flag) {flags += flag;} + }; + + while (pos < pattern.length) { + // Check for custom tokens at the current position + tokenResult = runTokens(pattern, pos, currScope, context); + + if (tokenResult) { + output.push(tokenResult.output); + pos += (tokenResult.match[0].length || 1); + } else { + // Check for native multicharacter metasequences (excluding character classes) at + // the current position + if (match = nativ.exec.call(nativeTokens[currScope], pattern.slice(pos))) { + output.push(match[0]); + pos += match[0].length; + } else { + chr = pattern.charAt(pos); + if (chr === "[") + currScope = XRegExp.INSIDE_CLASS; + else if (chr === "]") + currScope = XRegExp.OUTSIDE_CLASS; + // Advance position one character + output.push(chr); + pos++; + } + } + } + + regex = RegExp(output.join(""), nativ.replace.call(flags, flagClip, "")); + regex._xregexp = { + source: pattern, + captureNames: context.hasNamedCapture ? context.captureNames : null + }; + return regex; + }; + + + //--------------------------------- + // Public properties + //--------------------------------- + + XRegExp.version = "1.5.1"; + + // Token scope bitflags + XRegExp.INSIDE_CLASS = 1; + XRegExp.OUTSIDE_CLASS = 2; + + + //--------------------------------- + // Private variables + //--------------------------------- + + var replacementToken = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g, + flagClip = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, // Nonnative and duplicate flags + quantifier = /^(?:[?*+]|{\d+(?:,\d*)?})\??/, + isInsideConstructor = false, + tokens = [], + // Copy native globals for reference ("native" is an ES3 reserved keyword) + nativ = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = nativ.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + nativ.test.call(x, ""); + return !x.lastIndex; + }(), + hasNativeY = RegExp.prototype.sticky !== undefined, + nativeTokens = {}; + + // `nativeTokens` match native multicharacter metasequences only (including deprecated octals, + // excluding character classes) + nativeTokens[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/; + nativeTokens[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/; + + + //--------------------------------- + // Public methods + //--------------------------------- + + // Lets you extend or change XRegExp syntax and create custom flags. This is used internally by + // the XRegExp library and can be used to create XRegExp plugins. This function is intended for + // users with advanced knowledge of JavaScript's regular expression syntax and behavior. It can + // be disabled by `XRegExp.freezeTokens` + XRegExp.addToken = function (regex, handler, scope, trigger) { + tokens.push({ + pattern: clone(regex, "g" + (hasNativeY ? "y" : "")), + handler: handler, + scope: scope || XRegExp.OUTSIDE_CLASS, + trigger: trigger || null + }); + }; + + // Accepts a pattern and flags; returns an extended `RegExp` object. If the pattern and flag + // combination has previously been cached, the cached copy is returned; otherwise the newly + // created regex is cached + XRegExp.cache = function (pattern, flags) { + var key = pattern + "/" + (flags || ""); + return XRegExp.cache[key] || (XRegExp.cache[key] = XRegExp(pattern, flags)); + }; + + // Accepts a `RegExp` instance; returns a copy with the `/g` flag set. The copy has a fresh + // `lastIndex` (set to zero). If you want to copy a regex without forcing the `global` + // property, use `XRegExp(regex)`. Do not use `RegExp(regex)` because it will not preserve + // special properties required for named capture + XRegExp.copyAsGlobal = function (regex) { + return clone(regex, "g"); + }; + + // Accepts a string; returns the string with regex metacharacters escaped. The returned string + // can safely be used at any point within a regex to match the provided literal string. Escaped + // characters are [ ] { } ( ) * + ? - . , \ ^ $ | # and whitespace + XRegExp.escape = function (str) { + return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }; + + // Accepts a string to search, regex to search with, position to start the search within the + // string (default: 0), and an optional Boolean indicating whether matches must start at-or- + // after the position or at the specified position only. This function ignores the `lastIndex` + // of the provided regex in its own handling, but updates the property for compatibility + XRegExp.execAt = function (str, regex, pos, anchored) { + var r2 = clone(regex, "g" + ((anchored && hasNativeY) ? "y" : "")), + match; + r2.lastIndex = pos = pos || 0; + match = r2.exec(str); // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (anchored && match && match.index !== pos) + match = null; + if (regex.global) + regex.lastIndex = match ? r2.lastIndex : 0; + return match; + }; + + // Breaks the unrestorable link to XRegExp's private list of tokens, thereby preventing + // syntax and flag changes. Should be run after XRegExp and any plugins are loaded + XRegExp.freezeTokens = function () { + XRegExp.addToken = function () { + throw Error("can't run addToken after freezeTokens"); + }; + }; + + // Accepts any value; returns a Boolean indicating whether the argument is a `RegExp` object. + // Note that this is also `true` for regex literals and regexes created by the `XRegExp` + // constructor. This works correctly for variables created in another frame, when `instanceof` + // and `constructor` checks would fail to work as intended + XRegExp.isRegExp = function (o) { + return Object.prototype.toString.call(o) === "[object RegExp]"; + }; + + // Executes `callback` once per match within `str`. Provides a simpler and cleaner way to + // iterate over regex matches compared to the traditional approaches of subverting + // `String.prototype.replace` or repeatedly calling `exec` within a `while` loop + XRegExp.iterate = function (str, regex, callback, context) { + var r2 = clone(regex, "g"), + i = -1, match; + while (match = r2.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (regex.global) + regex.lastIndex = r2.lastIndex; // Doing this to follow expectations if `lastIndex` is checked within `callback` + callback.call(context, match, ++i, str, regex); + if (r2.lastIndex === match.index) + r2.lastIndex++; + } + if (regex.global) + regex.lastIndex = 0; + }; + + // Accepts a string and an array of regexes; returns the result of using each successive regex + // to search within the matches of the previous regex. The array of regexes can also contain + // objects with `regex` and `backref` properties, in which case the named or numbered back- + // references specified are passed forward to the next regex or returned. E.g.: + // var xregexpImgFileNames = XRegExp.matchChain(html, [ + // {regex: /]+)>/i, backref: 1}, // tag attributes + // {regex: XRegExp('(?ix) \\s src=" (? [^"]+ )'), backref: "src"}, // src attribute values + // {regex: XRegExp("^http://xregexp\\.com(/[^#?]+)", "i"), backref: 1}, // xregexp.com paths + // /[^\/]+$/ // filenames (strip directory paths) + // ]); + XRegExp.matchChain = function (str, chain) { + return function recurseChain (values, level) { + var item = chain[level].regex ? chain[level] : {regex: chain[level]}, + regex = clone(item.regex, "g"), + matches = [], i; + for (i = 0; i < values.length; i++) { + XRegExp.iterate(values[i], regex, function (match) { + matches.push(item.backref ? (match[item.backref] || "") : match[0]); + }); + } + return ((level === chain.length - 1) || !matches.length) ? + matches : recurseChain(matches, level + 1); + }([str], 0); + }; + + + //--------------------------------- + // New RegExp prototype methods + //--------------------------------- + + // Accepts a context object and arguments array; returns the result of calling `exec` with the + // first value in the arguments array. the context is ignored but is accepted for congruity + // with `Function.prototype.apply` + RegExp.prototype.apply = function (context, args) { + return this.exec(args[0]); + }; + + // Accepts a context object and string; returns the result of calling `exec` with the provided + // string. the context is ignored but is accepted for congruity with `Function.prototype.call` + RegExp.prototype.call = function (context, str) { + return this.exec(str); + }; + + + //--------------------------------- + // Overriden native methods + //--------------------------------- + + // Adds named capture support (with backreferences returned as `result.name`), and fixes two + // cross-browser issues per ES3: + // - Captured values for nonparticipating capturing groups should be returned as `undefined`, + // rather than the empty string. + // - `lastIndex` should not be incremented after zero-length matches. + RegExp.prototype.exec = function (str) { + var match, name, r2, origLastIndex; + if (!this.global) + origLastIndex = this.lastIndex; + match = nativ.exec.apply(this, arguments); + if (match) { + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, nativ.replace.call(getNativeFlags(this), "g", "")); + // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed + // matching due to characters outside the match + nativ.replace.call((str + "").slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + // Attach named capture properties + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + // Fix browsers that increment `lastIndex` after zero-length matches + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + if (!this.global) + this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + return match; + }; + + // Fix browser bugs in native method + RegExp.prototype.test = function (str) { + // Use the native `exec` to skip some processing overhead, even though the altered + // `exec` would take care of the `lastIndex` fixes + var match, origLastIndex; + if (!this.global) + origLastIndex = this.lastIndex; + match = nativ.exec.call(this, str); + // Fix browsers that increment `lastIndex` after zero-length matches + if (match && !compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + if (!this.global) + this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + return !!match; + }; + + // Adds named capture support and fixes browser bugs in native method + String.prototype.match = function (regex) { + if (!XRegExp.isRegExp(regex)) + regex = RegExp(regex); // Native `RegExp` + if (regex.global) { + var result = nativ.match.apply(this, arguments); + regex.lastIndex = 0; // Fix IE bug + return result; + } + return regex.exec(this); // Run the altered `exec` + }; + + // Adds support for `${n}` tokens for named and numbered backreferences in replacement text, + // and provides named backreferences to replacement functions as `arguments[0].name`. Also + // fixes cross-browser differences in replacement text syntax when performing a replacement + // using a nonregex search value, and the value of replacement regexes' `lastIndex` property + // during replacement iterations. Note that this doesn't support SpiderMonkey's proprietary + // third (`flags`) parameter + String.prototype.replace = function (search, replacement) { + var isRegex = XRegExp.isRegExp(search), + captureNames, result, str, origLastIndex; + + // There are too many combinations of search/replacement types/values and browser bugs that + // preclude passing to native `replace`, so don't try + //if (...) + // return nativ.replace.apply(this, arguments); + + if (isRegex) { + if (search._xregexp) + captureNames = search._xregexp.captureNames; // Array or `null` + if (!search.global) + origLastIndex = search.lastIndex; + } else { + search = search + ""; // Type conversion + } + + if (Object.prototype.toString.call(replacement) === "[object Function]") { + result = nativ.replace.call(this + "", search, function () { + if (captureNames) { + // Change the `arguments[0]` string primitive to a String object which can store properties + arguments[0] = new String(arguments[0]); + // Store named backreferences on `arguments[0]` + for (var i = 0; i < captureNames.length; i++) { + if (captureNames[i]) + arguments[0][captureNames[i]] = arguments[i + 1]; + } + } + // Update `lastIndex` before calling `replacement` (fix browsers) + if (isRegex && search.global) + search.lastIndex = arguments[arguments.length - 2] + arguments[0].length; + return replacement.apply(null, arguments); + }); + } else { + str = this + ""; // Type conversion, so `args[args.length - 1]` will be a string (given nonstring `this`) + result = nativ.replace.call(str, search, function () { + var args = arguments; // Keep this function's `arguments` available through closure + return nativ.replace.call(replacement + "", replacementToken, function ($0, $1, $2) { + // Numbered backreference (without delimiters) or special variable + if ($1) { + switch ($1) { + case "$": return "$"; + case "&": return args[0]; + case "`": return args[args.length - 1].slice(0, args[args.length - 2]); + case "'": return args[args.length - 1].slice(args[args.length - 2] + args[0].length); + // Numbered backreference + default: + // What does "$10" mean? + // - Backreference 10, if 10 or more capturing groups exist + // - Backreference 1 followed by "0", if 1-9 capturing groups exist + // - Otherwise, it's the string "$10" + // Also note: + // - Backreferences cannot be more than two digits (enforced by `replacementToken`) + // - "$01" is equivalent to "$1" if a capturing group exists, otherwise it's the string "$01" + // - There is no "$0" token ("$&" is the entire match) + var literalNumbers = ""; + $1 = +$1; // Type conversion; drop leading zero + if (!$1) // `$1` was "0" or "00" + return $0; + while ($1 > args.length - 3) { + literalNumbers = String.prototype.slice.call($1, -1) + literalNumbers; + $1 = Math.floor($1 / 10); // Drop the last digit + } + return ($1 ? args[$1] || "" : "$") + literalNumbers; + } + // Named backreference or delimited numbered backreference + } else { + // What does "${n}" mean? + // - Backreference to numbered capture n. Two differences from "$n": + // - n can be more than two digits + // - Backreference 0 is allowed, and is the entire match + // - Backreference to named capture n, if it exists and is not a number overridden by numbered capture + // - Otherwise, it's the string "${n}" + var n = +$2; // Type conversion; drop leading zeros + if (n <= args.length - 3) + return args[n]; + n = captureNames ? indexOf(captureNames, $2) : -1; + return n > -1 ? args[n + 1] : $0; + } + }); + }); + } + + if (isRegex) { + if (search.global) + search.lastIndex = 0; // Fix IE, Safari bug (last tested IE 9.0.5, Safari 5.1.2 on Windows) + else + search.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows) + } + + return result; + }; + + // A consistent cross-browser, ES3 compliant `split` + String.prototype.split = function (s /* separator */, limit) { + // If separator `s` is not a regex, use the native `split` + if (!XRegExp.isRegExp(s)) + return nativ.split.apply(this, arguments); + + var str = this + "", // Type conversion + output = [], + lastLastIndex = 0, + match, lastLength; + + // Behavior for `limit`: if it's... + // - `undefined`: No limit + // - `NaN` or zero: Return an empty array + // - A positive number: Use `Math.floor(limit)` + // - A negative number: No limit + // - Other: Type-convert, then use the above rules + if (limit === undefined || +limit < 0) { + limit = Infinity; + } else { + limit = Math.floor(+limit); + if (!limit) + return []; + } + + // This is required if not `s.global`, and it avoids needing to set `s.lastIndex` to zero + // and restore it to its original value when we're done using the regex + s = XRegExp.copyAsGlobal(s); + + while (match = s.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.) + if (s.lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + + if (match.length > 1 && match.index < str.length) + Array.prototype.push.apply(output, match.slice(1)); + + lastLength = match[0].length; + lastLastIndex = s.lastIndex; + + if (output.length >= limit) + break; + } + + if (s.lastIndex === match.index) + s.lastIndex++; + } + + if (lastLastIndex === str.length) { + if (!nativ.test.call(s, "") || lastLength) + output.push(""); + } else { + output.push(str.slice(lastLastIndex)); + } + + return output.length > limit ? output.slice(0, limit) : output; + }; + + + //--------------------------------- + // Private helper functions + //--------------------------------- + + // Supporting function for `XRegExp`, `XRegExp.copyAsGlobal`, etc. Returns a copy of a `RegExp` + // instance with a fresh `lastIndex` (set to zero), preserving properties required for named + // capture. Also allows adding new flags in the process of copying the regex + function clone (regex, additionalFlags) { + if (!XRegExp.isRegExp(regex)) + throw TypeError("type RegExp expected"); + var x = regex._xregexp; + regex = XRegExp(regex.source, getNativeFlags(regex) + (additionalFlags || "")); + if (x) { + regex._xregexp = { + source: x.source, + captureNames: x.captureNames ? x.captureNames.slice(0) : null + }; + } + return regex; + } + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function runTokens (pattern, index, scope, context) { + var i = tokens.length, + result, match, t; + // Protect against constructing XRegExps within token handler and trigger functions + isInsideConstructor = true; + // Must reset `isInsideConstructor`, even if a `trigger` or `handler` throws + try { + while (i--) { // Run in reverse order + t = tokens[i]; + if ((scope & t.scope) && (!t.trigger || t.trigger.call(context))) { + t.pattern.lastIndex = index; + match = t.pattern.exec(pattern); // Running the altered `exec` here allows use of named backreferences, etc. + if (match && match.index === index) { + result = { + output: t.handler.call(context, match, scope), + match: match + }; + break; + } + } + } + } catch (err) { + throw err; + } finally { + isInsideConstructor = false; + } + return result; + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + + + //--------------------------------- + // Built-in tokens + //--------------------------------- + + // Augment XRegExp's regular expression syntax and flags. Note that when adding tokens, the + // third (`scope`) argument defaults to `XRegExp.OUTSIDE_CLASS` + + // Comment pattern: (?# ) + XRegExp.addToken( + /\(\?#[^)]*\)/, + function (match) { + // Keep tokens separated unless the following token is a quantifier + return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)"; + } + ); + + // Capturing group (match the opening parenthesis only). + // Required for support of named capturing groups + XRegExp.addToken( + /\((?!\?)/, + function () { + this.captureNames.push(null); + return "("; + } + ); + + // Named capturing group (match the opening delimiter only): (? + XRegExp.addToken( + /\(\?<([$\w]+)>/, + function (match) { + this.captureNames.push(match[1]); + this.hasNamedCapture = true; + return "("; + } + ); + + // Named backreference: \k + XRegExp.addToken( + /\\k<([\w$]+)>/, + function (match) { + var index = indexOf(this.captureNames, match[1]); + // Keep backreferences separate from subsequent literal numbers. Preserve back- + // references to named groups that are undefined at this point as literal strings + return index > -1 ? + "\\" + (index + 1) + (isNaN(match.input.charAt(match.index + match[0].length)) ? "" : "(?:)") : + match[0]; + } + ); + + // Empty character class: [] or [^] + XRegExp.addToken( + /\[\^?]/, + function (match) { + // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S]. + // (?!) should work like \b\B, but is unreliable in Firefox + return match[0] === "[]" ? "\\b\\B" : "[\\s\\S]"; + } + ); + + // Mode modifier at the start of the pattern only, with any combination of flags imsx: (?imsx) + // Does not support x(?i), (?-i), (?i-m), (?i: ), (?i)(?m), etc. + XRegExp.addToken( + /^\(\?([imsx]+)\)/, + function (match) { + this.setFlag(match[1]); + return ""; + } + ); + + // Whitespace and comments, in free-spacing (aka extended) mode only + XRegExp.addToken( + /(?:\s+|#.*)+/, + function (match) { + // Keep tokens separated unless the following token is a quantifier + return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)"; + }, + XRegExp.OUTSIDE_CLASS, + function () {return this.hasFlag("x");} + ); + + // Dot, in dotall (aka singleline) mode only + XRegExp.addToken( + /\./, + function () {return "[\\s\\S]";}, + XRegExp.OUTSIDE_CLASS, + function () {return this.hasFlag("s");} + ); + + + //--------------------------------- + // Backward compatibility + //--------------------------------- + + // Uncomment the following block for compatibility with XRegExp 1.0-1.2: + /* + XRegExp.matchWithinChain = XRegExp.matchChain; + RegExp.prototype.addFlags = function (s) {return clone(this, s);}; + RegExp.prototype.execAll = function (s) {var r = []; XRegExp.iterate(s, this, function (m) {r.push(m);}); return r;}; + RegExp.prototype.forEachExec = function (s, f, c) {return XRegExp.iterate(s, this, f, c);}; + RegExp.prototype.validate = function (s) {var r = RegExp("^(?:" + this.source + ")$(?!\\s)", getNativeFlags(this)); if (this.global) this.lastIndex = 0; return s.search(r) === 0;}; + */ + +})(); + +// +// Begin anonymous function. This is used to contain local scope variables without polutting global scope. +// +if (typeof(SyntaxHighlighter) == 'undefined') var SyntaxHighlighter = function() { + +// CommonJS + if (typeof(require) != 'undefined' && typeof(XRegExp) == 'undefined') + { + XRegExp = require('XRegExp').XRegExp; + } + +// Shortcut object which will be assigned to the SyntaxHighlighter variable. +// This is a shorthand for local reference in order to avoid long namespace +// references to SyntaxHighlighter.whatever... + var sh = { + defaults : { + /** Additional CSS class names to be added to highlighter elements. */ + 'class-name' : '', + + /** First line number. */ + 'first-line' : 1, + + /** + * Pads line numbers. Possible values are: + * + * false - don't pad line numbers. + * true - automaticaly pad numbers with minimum required number of leading zeroes. + * [int] - length up to which pad line numbers. + */ + 'pad-line-numbers' : false, + + /** Lines to highlight. */ + 'highlight' : false, + + /** Title to be displayed above the code block. */ + 'title' : null, + + /** Enables or disables smart tabs. */ + 'smart-tabs' : true, + + /** Gets or sets tab size. */ + 'tab-size' : 4, + + /** Enables or disables gutter. */ + 'gutter' : true, + + /** Enables or disables toolbar. */ + 'toolbar' : true, + + /** Enables quick code copy and paste from double click. */ + 'quick-code' : true, + + /** Forces code view to be collapsed. */ + 'collapse' : false, + + /** Enables or disables automatic links. */ + 'auto-links' : false, + + /** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */ + 'light' : false, + + 'unindent' : true, + + 'html-script' : false + }, + + config : { + space : ' ', + + /** Enables use of + * + * ``` + */ + findParent: function(node, filterFn, includeSelf) { + if (node && !domUtils.isBody(node)) { + node = includeSelf ? node : node.parentNode; + while (node) { + if (!filterFn || filterFn(node) || domUtils.isBody(node)) { + return filterFn && !filterFn(node) && domUtils.isBody(node) + ? null + : node; + } + node = node.parentNode; + } + } + return null; + }, + /** + * 查找node的节点名为tagName的第一个祖先节点, 查找的起点是node节点的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var node = UE.dom.domUtils.findParentByTagName( document.getElementsByTagName("div")[0], [ "BODY" ] ); + * //output: BODY + * console.log( node.tagName ); + * ``` + */ + + /** + * 查找node的节点名为tagName的祖先节点, 如果includeSelf的值为true,则查找的起点是给定的节点node, + * 否则, 起点是node的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @param { Boolean } includeSelf 查找过程是否包含node节点自身 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var queryTarget = document.getElementsByTagName("div")[0]; + * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ "DIV" ], true ); + * //output: true + * console.log( queryTarget === node ); + * ``` + */ + findParentByTagName: function(node, tagNames, includeSelf, excludeFn) { + tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]); + return domUtils.findParent( + node, + function(node) { + return tagNames[node.tagName] && !(excludeFn && excludeFn(node)); + }, + includeSelf + ); + }, + /** + * 查找节点node的祖先节点集合, 查找的起点是给定节点的父节点,结果集中不包含给定的节点。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + * @grammar UE.dom.domUtils.findParents(node) => Array //返回一个祖先节点数组集合,不包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf) => Array //返回一个祖先节点数组集合,includeSelf指定是否包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn) => Array //返回一个祖先节点数组集合,filterFn指定过滤条件,返回true的node将被选取 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn,closerFirst) => Array //返回一个祖先节点数组集合,closerFirst为true的话,node的直接父亲节点是数组的第0个 + */ + + /** + * 查找节点node的祖先节点集合, 如果includeSelf的值为true, + * 则返回的结果集中允许出现当前给定的节点, 否则, 该节点不会出现在其结果集中。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @param { Boolean } includeSelf 查找的结果中是否允许包含当前查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + */ + findParents: function(node, includeSelf, filterFn, closerFirst) { + var parents = includeSelf && ((filterFn && filterFn(node)) || !filterFn) + ? [node] + : []; + while ((node = domUtils.findParent(node, filterFn))) { + parents.push(node); + } + return closerFirst ? parents : parents.reverse(); + }, + + /** + * 在节点node后面插入新节点newNode + * @method insertAfter + * @param { Node } node 目标节点 + * @param { Node } newNode 新插入的节点, 该节点将置于目标节点之后 + * @return { Node } 新插入的节点 + */ + insertAfter: function(node, newNode) { + return node.nextSibling + ? node.parentNode.insertBefore(newNode, node.nextSibling) + : node.parentNode.appendChild(newNode); + }, + + /** + * 删除节点node及其下属的所有节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
    + *
    你好
    + *
    + * + * ``` + */ + + /** + * 删除节点node,并根据keepChildren的值决定是否保留子节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @param { Boolean } keepChildren 是否需要保留子节点 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
    + *
    你好
    + *
    + * + * ``` + */ + remove: function(node, keepChildren) { + var parent = node.parentNode, + child; + if (parent) { + if (keepChildren && node.hasChildNodes()) { + while ((child = node.firstChild)) { + parent.insertBefore(child, node); + } + } + parent.removeChild(node); + } + return node; + }, + + /** + * 取得node节点的下一个兄弟节点, 如果该节点其后没有兄弟节点, 则递归查找其父节点之后的第一个兄弟节点, + * 直到找到满足条件的节点或者递归到BODY节点之后才会结束。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```html + * + *
    + * + *
    + * xxx + * + * + * ``` + * @example + * ```html + * + *
    + * + * xxx + *
    + * xxx + * + * + * ``` + */ + + /** + * 取得node节点的下一个兄弟节点, 如果startFromChild的值为ture,则先获取其子节点, + * 如果有子节点则直接返回第一个子节点;如果没有子节点或者startFromChild的值为false, + * 则执行getNextDomNode(Node node)的查找过程。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @param { Boolean } startFromChild 查找过程是否从其子节点开始 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @see UE.dom.domUtils.getNextDomNode(Node) + */ + getNextDomNode: function(node, startFromChild, filterFn, guard) { + return getDomNode( + node, + "firstChild", + "nextSibling", + startFromChild, + filterFn, + guard + ); + }, + getPreDomNode: function(node, startFromChild, filterFn, guard) { + return getDomNode( + node, + "lastChild", + "previousSibling", + startFromChild, + filterFn, + guard + ); + }, + /** + * 检测节点node是否属是UEditor定义的bookmark节点 + * @method isBookmarkNode + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是bookmark节点 + * @example + * ```html + * + * + * ``` + */ + isBookmarkNode: function(node) { + return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id); + }, + /** + * 获取节点node所属的window对象 + * @method getWindow + * @param { Node } node 节点对象 + * @return { Window } 当前节点所属的window对象 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.getWindow( document.body ) === window ); + * ``` + */ + getWindow: function(node) { + var doc = node.ownerDocument || node; + return doc.defaultView || doc.parentWindow; + }, + /** + * 获取离nodeA与nodeB最近的公共的祖先节点 + * @method getCommonAncestor + * @param { Node } nodeA 第一个节点 + * @param { Node } nodeB 第二个节点 + * @remind 如果给定的两个节点是同一个节点, 将直接返回该节点。 + * @return { Node | NULL } 如果未找到公共节点, 返回NULL, 否则返回最近的公共祖先节点。 + * @example + * ```javascript + * var commonAncestor = UE.dom.domUtils.getCommonAncestor( document.body, document.body.firstChild ); + * //output: true + * console.log( commonAncestor.tagName.toLowerCase() === 'body' ); + * ``` + */ + getCommonAncestor: function(nodeA, nodeB) { + if (nodeA === nodeB) return nodeA; + var parentsA = [nodeA], + parentsB = [nodeB], + parent = nodeA, + i = -1; + while ((parent = parent.parentNode)) { + if (parent === nodeB) { + return parent; + } + parentsA.push(parent); + } + parent = nodeB; + while ((parent = parent.parentNode)) { + if (parent === nodeA) return parent; + parentsB.push(parent); + } + parentsA.reverse(); + parentsB.reverse(); + while ((i++, parentsA[i] === parentsB[i])) {} + return i == 0 ? null : parentsA[i - 1]; + }, + /** + * 清除node节点左右连续为空的兄弟inline节点 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * 则这些兄弟节点将被删除 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext) //ignoreNext指定是否忽略右边空节点 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext,ignorePre) //ignorePre指定是否忽略左边空节点 + * @example + * ```html + * + *
    + * + * + * + * xxx + * + * + * + * ``` + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作, 如果ignorePre的值为true,则忽略对左边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * @param { Boolean } ignorePre 是否忽略忽略对左边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + clearEmptySibling: function(node, ignoreNext, ignorePre) { + function clear(next, dir) { + var tmpNode; + while ( + next && + !domUtils.isBookmarkNode(next) && + (domUtils.isEmptyInlineElement(next) || + //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了 + !new RegExp("[^\t\n\r" + domUtils.fillChar + "]").test( + next.nodeValue + )) + ) { + tmpNode = next[dir]; + domUtils.remove(next); + next = tmpNode; + } + } + !ignoreNext && clear(node.nextSibling, "nextSibling"); + !ignorePre && clear(node.previousSibling, "previousSibling"); + }, + /** + * 将一个文本节点textNode拆分成两个文本节点,offset指定拆分位置 + * @method split + * @param { Node } textNode 需要拆分的文本节点对象 + * @param { int } offset 需要拆分的位置, 位置计算从0开始 + * @return { Node } 拆分后形成的新节点 + * @example + * ```html + *
    abcdef
    + * + * ``` + */ + split: function(node, offset) { + var doc = node.ownerDocument; + if (browser.ie && offset == node.nodeValue.length) { + var next = doc.createTextNode(""); + return domUtils.insertAfter(node, next); + } + var retval = node.splitText(offset); + //ie8下splitText不会跟新childNodes,我们手动触发他的更新 + if (browser.ie8) { + var tmpNode = doc.createTextNode(""); + domUtils.insertAfter(retval, tmpNode); + domUtils.remove(tmpNode); + } + return retval; + }, + + /** + * 检测文本节点textNode是否为空节点(包括空格、换行、占位符等字符) + * @method isWhitespace + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 检测的节点是否为空 + * @example + * ```html + *
    + * + *
    + * + * ``` + */ + isWhitespace: function(node) { + return !new RegExp("[^ \t\n\r" + domUtils.fillChar + "]").test( + node.nodeValue + ); + }, + /** + * 获取元素element相对于viewport的位置坐标 + * @method getXY + * @param { Node } element 需要计算位置的节点对象 + * @return { Object } 返回形如{x:left,y:top}的一个key-value映射对象, 其中键x代表水平偏移距离, + * y代表垂直偏移距离。 + * + * @example + * ```javascript + * var location = UE.dom.domUtils.getXY( document.getElementById("test") ); + * //output: test的坐标为: 12, 24 + * console.log( 'test的坐标为: ', location.x, ',', location.y ); + * ``` + */ + getXY: function(element) { + var x = 0, + y = 0; + while (element.offsetParent) { + y += element.offsetTop; + x += element.offsetLeft; + element = element.offsetParent; + } + return { x: x, y: y }; + }, + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param { String } type 绑定的事件类型 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,"click",function(e){ + * //e为事件对象,this为被点击元素对戏那个 + * }); + * ``` + */ + + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param {string} type 绑定的事件类型数组 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + on: function(element, type, handler) { + var types = utils.isArray(type) ? type : utils.trim(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; + }, + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { String } type 需要接触绑定的事件类型 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body,"click",function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { Array } type 需要接触绑定的事件类型数组 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body, ["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + un: function(element, type, handler) { + var types = utils.isArray(type) ? type : utils.trim(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]; + } + } + } + }, + + /** + * 比较节点nodeA与节点nodeB是否具有相同的标签名、属性名以及属性值 + * @method isSameElement + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的标签名、属性名以及属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameElement: function(nodeA, nodeB) { + if (nodeA.tagName != nodeB.tagName) { + return false; + } + var thisAttrs = nodeA.attributes, + otherAttrs = nodeB.attributes; + if (!ie && thisAttrs.length != otherAttrs.length) { + return false; + } + var attrA, + attrB, + al = 0, + bl = 0; + for (var i = 0; (attrA = thisAttrs[i++]); ) { + if (attrA.nodeName == "style") { + if (attrA.specified) { + al++; + } + if (domUtils.isSameStyle(nodeA, nodeB)) { + continue; + } else { + return false; + } + } + if (ie) { + if (attrA.specified) { + al++; + attrB = otherAttrs.getNamedItem(attrA.nodeName); + } else { + continue; + } + } else { + attrB = nodeB.attributes[attrA.nodeName]; + } + if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) { + return false; + } + } + // 有可能attrB的属性包含了attrA的属性之外还有自己的属性 + if (ie) { + for (i = 0; (attrB = otherAttrs[i++]); ) { + if (attrB.specified) { + bl++; + } + } + if (al != bl) { + return false; + } + } + return true; + }, + + /** + * 判断节点nodeA与节点nodeB的元素的style属性是否一致 + * @method isSameStyle + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的style属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameStyle: function(nodeA, nodeB) { + var styleA = nodeA.style.cssText + .replace(/( ?; ?)/g, ";") + .replace(/( ?: ?)/g, ":"), + styleB = nodeB.style.cssText + .replace(/( ?; ?)/g, ";") + .replace(/( ?: ?)/g, ":"); + if (browser.opera) { + styleA = nodeA.style; + styleB = nodeB.style; + if (styleA.length != styleB.length) return false; + for (var p in styleA) { + if (/^(\d+|csstext)$/i.test(p)) { + continue; + } + if (styleA[p] != styleB[p]) { + return false; + } + } + return true; + } + if (!styleA || !styleB) { + return styleA == styleB; + } + styleA = styleA.split(";"); + styleB = styleB.split(";"); + if (styleA.length != styleB.length) { + return false; + } + for (var i = 0, ci; (ci = styleA[i++]); ) { + if (utils.indexOf(styleB, ci) == -1) { + return false; + } + } + return true; + }, + /** + * 检查节点node是否为block元素 + * @method isBlockElm + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是block元素节点 + * @warning 该方法的判断规则如下: 如果该元素原本是block元素, 则不论该元素当前的css样式是什么都会返回true; + * 否则,检测该元素的css样式, 如果该元素当前是block元素, 则返回true。 其余情况下都返回false。 + * @example + * ```html + * + * + *
    + * + * + * ``` + */ + isBlockElm: function(node) { + return ( + node.nodeType == 1 && + (dtd.$block[node.tagName] || + styleBlock[domUtils.getComputedStyle(node, "display")]) && + !dtd.$nonChild[node.tagName] + ); + }, + /** + * 检测node节点是否为body节点 + * @method isBody + * @param { Element } node 需要检测的dom元素 + * @return { Boolean } 给定的元素是否是body元素 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.isBody( document.body ) ); + * ``` + */ + isBody: function(node) { + return node && node.nodeType == 1 && node.tagName.toLowerCase() == "body"; + }, + /** + * 以node节点为分界,将该节点的指定祖先节点parent拆分成两个独立的节点, + * 拆分形成的两个节点之间是node节点 + * @method breakParent + * @param { Node } node 作为分界的节点对象 + * @param { Node } parent 该节点必须是node节点的祖先节点, 且是block节点。 + * @return { Node } 给定的node分界节点 + * @example + * ```javascript + * + * var node = document.createElement("span"), + * wrapNode = document.createElement( "div" ), + * parent = document.createElement("p"); + * + * parent.appendChild( node ); + * wrapNode.appendChild( parent ); + * + * //拆分前 + * //output:

    + * console.log( wrapNode.innerHTML ); + * + * + * UE.dom.domUtils.breakParent( node, parent ); + * //拆分后 + * //output:

    + * console.log( wrapNode.innerHTML ); + * + * ``` + */ + breakParent: function(node, parent) { + var tmpNode, + parentClone = node, + clone = node, + leftNodes, + rightNodes; + do { + parentClone = parentClone.parentNode; + if (leftNodes) { + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(leftNodes); + leftNodes = tmpNode; + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(rightNodes); + rightNodes = tmpNode; + } else { + leftNodes = parentClone.cloneNode(false); + rightNodes = leftNodes.cloneNode(false); + } + while ((tmpNode = clone.previousSibling)) { + leftNodes.insertBefore(tmpNode, leftNodes.firstChild); + } + while ((tmpNode = clone.nextSibling)) { + rightNodes.appendChild(tmpNode); + } + clone = parentClone; + } while (parent !== parentClone); + tmpNode = parent.parentNode; + tmpNode.insertBefore(leftNodes, parent); + tmpNode.insertBefore(rightNodes, parent); + tmpNode.insertBefore(node, rightNodes); + domUtils.remove(parent); + return node; + }, + /** + * 检查节点node是否是空inline节点 + * @method isEmptyInlineElement + * @param { Node } node 需要检测的节点对象 + * @return { Number } 如果给定的节点是空的inline节点, 则返回1, 否则返回0。 + * @example + * ```html + * => 1 + * => 1 + * => 1 + * xx => 0 + * ``` + */ + isEmptyInlineElement: function(node) { + if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) { + return 0; + } + node = node.firstChild; + while (node) { + //如果是创建的bookmark就跳过 + if (domUtils.isBookmarkNode(node)) { + return 0; + } + if ( + (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node)) || + (node.nodeType == 3 && !domUtils.isWhitespace(node)) + ) { + return 0; + } + node = node.nextSibling; + } + return 1; + }, + + /** + * 删除node节点下首尾两端的空白文本子节点 + * @method trimWhiteTextNode + * @param { Element } node 需要执行删除操作的元素对象 + * @example + * ```javascript + * var node = document.createElement("div"); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * node.appendChild( document.createElement("div") ); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * //3 + * console.log( node.childNodes.length ); + * + * UE.dom.domUtils.trimWhiteTextNode( node ); + * + * //1 + * console.log( node.childNodes.length ); + * ``` + */ + trimWhiteTextNode: function(node) { + function remove(dir) { + var child; + while ( + (child = node[dir]) && + child.nodeType == 3 && + domUtils.isWhitespace(child) + ) { + node.removeChild(child); + } + } + remove("firstChild"); + remove("lastChild"); + }, + + /** + * 合并node节点下相同的子节点 + * @name mergeChild + * @desc + * UE.dom.domUtils.mergeChild(node,tagName) //tagName要合并的子节点的标签 + * @example + *

    xxaaxx

    + * ==> UE.dom.domUtils.mergeChild(node,'span') + *

    xxaaxx

    + */ + mergeChild: function(node, tagName, attrs) { + var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); + for (var i = 0, ci; (ci = list[i++]); ) { + if (!ci.parentNode || domUtils.isBookmarkNode(ci)) { + continue; + } + //span单独处理 + if (ci.tagName.toLowerCase() == "span") { + if (node === ci.parentNode) { + domUtils.trimWhiteTextNode(node); + if (node.childNodes.length == 1) { + node.style.cssText = ci.style.cssText + ";" + node.style.cssText; + domUtils.remove(ci, true); + continue; + } + } + ci.style.cssText = node.style.cssText + ";" + ci.style.cssText; + if (attrs) { + var style = attrs.style; + if (style) { + style = style.split(";"); + for (var j = 0, s; (s = style[j++]); ) { + ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split( + ":" + )[1]; + } + } + } + if (domUtils.isSameStyle(ci, node)) { + domUtils.remove(ci, true); + } + continue; + } + if (domUtils.isSameElement(node, ci)) { + domUtils.remove(ci, true); + } + } + }, + + /** + * 原生方法getElementsByTagName的封装 + * @method getElementsByTagName + * @param { Node } node 目标节点对象 + * @param { String } tagName 需要查找的节点的tagName, 多个tagName以空格分割 + * @return { Array } 符合条件的节点集合 + */ + getElementsByTagName: function(node, name, filter) { + if (filter && utils.isString(filter)) { + var className = filter; + filter = function(node) { + return domUtils.hasClass(node, className); + }; + } + name = utils.trim(name).replace(/[ ]{2,}/g, " ").split(" "); + var arr = []; + for (var n = 0, ni; (ni = name[n++]); ) { + var list = node.getElementsByTagName(ni); + for (var i = 0, ci; (ci = list[i++]); ) { + if (!filter || filter(ci)) arr.push(ci); + } + } + + return arr; + }, + /** + * 将节点node提取到父节点上 + * @method mergeToParent + * @param { Element } node 需要提取的元素对象 + * @example + * ```html + *
    + *
    + * + *
    + *
    + * + * + * ``` + */ + mergeToParent: function(node) { + var parent = node.parentNode; + while (parent && dtd.$removeEmpty[parent.tagName]) { + if (parent.tagName == node.tagName || parent.tagName == "A") { + //针对a标签单独处理 + domUtils.trimWhiteTextNode(parent); + //span需要特殊处理 不处理这样的情况 xxxxxxxxx + if ( + (parent.tagName == "SPAN" && !domUtils.isSameStyle(parent, node)) || + (parent.tagName == "A" && node.tagName == "SPAN") + ) { + if (parent.childNodes.length > 1 || parent !== node.parentNode) { + node.style.cssText = + parent.style.cssText + ";" + node.style.cssText; + parent = parent.parentNode; + continue; + } else { + parent.style.cssText += ";" + node.style.cssText; + //trace:952 a标签要保持下划线 + if (parent.tagName == "A") { + parent.style.textDecoration = "underline"; + } + } + } + if (parent.tagName != "A") { + parent === node.parentNode && domUtils.remove(node, true); + break; + } + } + parent = parent.parentNode; + } + }, + /** + * 合并节点node的左右兄弟节点 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点, 可以根据给定的条件选择是否忽略合并左节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点,可以根据给定的条件选择是否忽略合并左右节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @param { Boolean } ignoreNext 是否忽略合并右节点 + * @remind 如果同时忽略左右节点, 则该操作什么也不会做 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + mergeSibling: function(node, ignorePre, ignoreNext) { + function merge(rtl, start, node) { + var next; + if ( + (next = node[rtl]) && + !domUtils.isBookmarkNode(next) && + next.nodeType == 1 && + domUtils.isSameElement(node, next) + ) { + while (next.firstChild) { + if (start == "firstChild") { + node.insertBefore(next.lastChild, node.firstChild); + } else { + node.appendChild(next.firstChild); + } + } + domUtils.remove(next); + } + } + !ignorePre && merge("previousSibling", "firstChild", node); + !ignoreNext && merge("nextSibling", "lastChild", node); + }, + + /** + * 设置节点node及其子节点不会被选中 + * @method unSelectable + * @param { Element } node 需要执行操作的dom元素 + * @remind 执行该操作后的节点, 将不能被鼠标选中 + * @example + * ```javascript + * UE.dom.domUtils.unSelectable( document.body ); + * ``` + */ + unSelectable: (ie && browser.ie9below) || browser.opera + ? function(node) { + //for ie9 + node.onselectstart = function() { + return false; + }; + node.onclick = node.onkeyup = node.onkeydown = function() { + return false; + }; + node.unselectable = "on"; + node.setAttribute("unselectable", "on"); + for (var i = 0, ci; (ci = node.all[i++]); ) { + switch (ci.tagName.toLowerCase()) { + case "iframe": + case "textarea": + case "input": + case "select": + break; + default: + ci.unselectable = "on"; + node.setAttribute("unselectable", "on"); + } + } + } + : function(node) { + node.style.MozUserSelect = node.style.webkitUserSelect = node.style.msUserSelect = node.style.KhtmlUserSelect = + "none"; + }, + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { String } attrNames 可以是空格隔开的多个属性名称,该操作将会依次删除相应的属性 + * @example + * ```html + *
    + * xxxxx + *
    + * + * + * ``` + */ + + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { Array } attrNames 需要删除的属性名数组 + * @example + * ```html + *
    + * xxxxx + *
    + * + * + * ``` + */ + removeAttributes: function(node, attrNames) { + attrNames = utils.isArray(attrNames) + ? attrNames + : utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" "); + for (var i = 0, ci; (ci = attrNames[i++]); ) { + ci = attrFix[ci] || ci; + switch (ci) { + case "className": + node[ci] = ""; + break; + case "style": + node.style.cssText = ""; + var val = node.getAttributeNode("style"); + !browser.ie && val && node.removeAttributeNode(val); + } + node.removeAttribute(ci); + } + }, + /** + * 在doc下创建一个标签名为tag,属性为attrs的元素 + * @method createElement + * @param { DomDocument } doc 新创建的元素属于该document节点创建 + * @param { String } tagName 需要创建的元素的标签名 + * @param { Object } attrs 新创建的元素的属性key-value集合 + * @return { Element } 新创建的元素对象 + * @example + * ```javascript + * var ele = UE.dom.domUtils.createElement( document, 'div', { + * id: 'test' + * } ); + * + * //output: DIV + * console.log( ele.tagName ); + * + * //output: test + * console.log( ele.id ); + * + * ``` + */ + createElement: function(doc, tag, attrs) { + return domUtils.setAttributes(doc.createElement(tag), attrs); + }, + /** + * 为节点node添加属性attrs,attrs为属性键值对 + * @method setAttributes + * @param { Element } node 需要设置属性的元素对象 + * @param { Object } attrs 需要设置的属性名-值对 + * @return { Element } 设置属性的元素对象 + * @example + * ```html + * + * + * + * + */ + setAttributes: function(node, attrs) { + for (var attr in attrs) { + if('_propertyDelete'===attr){ + for(var j=0;j + * #test { + * font-size: 15px; + * } + * + * + * + * + * + * ``` + */ + getComputedStyle: function(element, styleName) { + //以下的属性单独处理 + var pros = "width height top left"; + + if (pros.indexOf(styleName) > -1) { + return ( + element[ + "offset" + + styleName.replace(/^\w/, function(s) { + return s.toUpperCase(); + }) + ] + "px" + ); + } + //忽略文本节点 + if (element.nodeType === 3) { + element = element.parentNode; + } + //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改. + if ( + browser.ie && + browser.version < 9 && + styleName === "font-size" && + !element.style.fontSize && + !dtd.$empty[element.tagName] && + !dtd.$nonChild[element.tagName] + ) { + var span = element.ownerDocument.createElement("span"); + span.style.cssText = "padding:0;border:0;font-family:simsun;"; + span.innerHTML = "."; + element.appendChild(span); + var result = span.offsetHeight; + element.removeChild(span); + span = null; + return result + "px"; + } + try { + var value = + domUtils.getStyle(element, styleName) || + (window.getComputedStyle + ? domUtils + .getWindow(element) + .getComputedStyle(element, "") + .getPropertyValue(styleName) + : (element.currentStyle || element.style)[ + utils.cssStyleToDomStyle(styleName) + ]); + } catch (e) { + return ""; + } + return utils.transUnitToPx(utils.fixColor(styleName, value)); + }, + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { String } classNames 需要删除的className, 多个className之间以空格分开 + * @example + * ```html + * xxx + * + * + * ``` + */ + + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { Array } classNames 需要删除的className数组 + * @example + * ```html + * xxx + * + * + * ``` + */ + removeClasses: function(elm, classNames) { + classNames = utils.isArray(classNames) + ? classNames + : utils.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 = utils.trim(cls).replace(/[ ]{2,}/g, " "); + if (cls) { + elm.className = cls; + } else { + domUtils.removeAttributes(elm, ["class"]); + } + }, + /** + * 给元素element添加className + * @method addClass + * @param { Node } ele 需要增加className的元素 + * @param { String } classNames 需要添加的className, 多个className之间以空格分割 + * @remind 相同的类名不会被重复添加 + * @example + * ```html + * + * + * + * ``` + */ + + /** + * 判断元素element是否包含给定的样式类名className + * @method hasClass + * @param { Node } ele 需要检测的元素 + * @param { Array } classNames 需要检测的className数组 + * @return { Boolean } 元素是否包含所有给定的className + * @example + * ```html + * + * + * + * ``` + */ + hasClass: function(element, className) { + if (utils.isRegExp(className)) { + return className.test(element.className); + } + className = utils.trim(className).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; + }, + + /** + * 阻止事件默认行为 + * @method preventDefault + * @param { Event } evt 需要阻止默认行为的事件对象 + * @example + * ```javascript + * UE.dom.domUtils.preventDefault( evt ); + * ``` + */ + preventDefault: function(evt) { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + }, + /** + * 删除元素element指定的样式 + * @method removeStyle + * @param { Element } element 需要删除样式的元素 + * @param { String } styleName 需要删除的样式名 + * @example + * ```html + * + * + * + * ``` + */ + removeStyle: function(element, name) { + if (browser.ie) { + //针对color先单独处理一下 + if (name == "color") { + name = "(^|;)" + name; + } + element.style.cssText = element.style.cssText.replace( + new RegExp(name + "[^:]*:[^;]+;?", "ig"), + "" + ); + } else { + if (element.style.removeProperty) { + element.style.removeProperty(name); + } else { + element.style.removeAttribute(utils.cssStyleToDomStyle(name)); + } + } + + if (!element.style.cssText) { + domUtils.removeAttributes(element, ["style"]); + } + }, + /** + * 获取元素element的style属性的指定值 + * @method getStyle + * @param { Element } element 需要获取属性值的元素 + * @param { String } styleName 需要获取的style的名称 + * @warning 该方法仅获取元素style属性中所标明的值 + * @return { String } 该元素包含指定的style属性值 + * @example + * ```html + *
    + * + * + * ``` + */ + getStyle: function(element, name) { + var value = element.style[utils.cssStyleToDomStyle(name)]; + return utils.fixColor(name, value); + }, + /** + * 为元素element设置样式属性值 + * @method setStyle + * @param { Element } element 需要设置样式的元素 + * @param { String } styleName 样式名 + * @param { String } styleValue 样式值 + * @example + * ```html + *
    + * + * + * ``` + */ + setStyle: function(element, name, value) { + element.style[utils.cssStyleToDomStyle(name)] = value; + if (!utils.trim(element.style.cssText)) { + this.removeAttributes(element, "style"); + } + }, + /** + * 为元素element设置多个样式属性值 + * @method setStyles + * @param { Element } element 需要设置样式的元素 + * @param { Object } styles 样式名值对 + * @example + * ```html + *
    + * + * + * ``` + */ + setStyles: function(element, styles) { + for (var name in styles) { + if (styles.hasOwnProperty(name)) { + domUtils.setStyle(element, name, styles[name]); + } + } + }, + /** + * 删除_moz_dirty属性 + * @private + * @method removeDirtyAttr + */ + removeDirtyAttr: function(node) { + for ( + var i = 0, ci, nodes = node.getElementsByTagName("*"); + (ci = nodes[i++]); + + ) { + ci.removeAttribute("_moz_dirty"); + } + node.removeAttribute("_moz_dirty"); + }, + /** + * 获取子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @return { Number } 给定的node元素的子节点数量 + * @example + * ```html + *
    + * + *
    + * + * + * ``` + */ + + /** + * 根据给定的过滤规则, 获取符合条件的子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @param { Function } fn 过滤器, 要求对符合条件的子节点返回true, 反之则要求返回false + * @return { Number } 符合过滤条件的node元素的子节点数量 + * @example + * ```html + *
    + * + *
    + * + * + * ``` + */ + getChildCount: function(node, fn) { + var count = 0, + first = node.firstChild; + fn = + fn || + function() { + return 1; + }; + while (first) { + if (fn(first)) { + count++; + } + first = first.nextSibling; + } + return count; + }, + + /** + * 判断给定节点是否为空节点 + * @method isEmptyNode + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否为空 + * @example + * ```javascript + * UE.dom.domUtils.isEmptyNode( document.body ); + * ``` + */ + isEmptyNode: function(node) { + return ( + !node.firstChild || + domUtils.getChildCount(node, function(node) { + return ( + !domUtils.isBr(node) && + !domUtils.isBookmarkNode(node) && + !domUtils.isWhitespace(node) + ); + }) == 0 + ); + }, + clearSelectedArr: function(nodes) { + var node; + while ((node = nodes.pop())) { + domUtils.removeAttributes(node, ["class"]); + } + }, + /** + * 将显示区域滚动到指定节点的位置 + * @method scrollToView + * @param {Node} node 节点 + * @param {window} win window对象 + * @param {Number} offsetTop 距离上方的偏移量 + */ + scrollToView: function(node, win, offsetTop) { + offsetTop = offsetTop || 0 + var getViewPaneSize = function() { + var doc = win.document, + mode = doc.compatMode == "CSS1Compat"; + return { + width: + (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0, + height: + (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0 + }; + }, + getScrollPosition = function(win) { + if ("pageXOffset" in win) { + return { + x: win.pageXOffset || 0, + y: win.pageYOffset || 0 + }; + } else { + var doc = win.document; + return { + x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, + y: doc.documentElement.scrollTop || doc.body.scrollTop || 0 + }; + } + }; + var winHeight = getViewPaneSize().height, + offset = winHeight * -1 + offsetTop; + offset += node.offsetHeight || 0; + var elementPosition = domUtils.getXY(node); + offset += elementPosition.y; + var currentScroll = getScrollPosition(win).y; + // console.log({currentScroll,winHeight,offset,y:elementPosition.y}); + // offset += 50; + if (offset > currentScroll || offset < currentScroll - winHeight) { + win.scrollTo({ + top:offset + (offset < 0 ? -20 : 20), + behavior: "smooth" + }); + } + }, + /** + * 判断给定节点是否为br + * @method isBr + * @param { Node } node 需要判断的节点对象 + * @return { Boolean } 给定的节点是否是br节点 + */ + isBr: function(node) { + return node.nodeType == 1 && node.tagName == "BR"; + }, + /** + * 判断给定的节点是否是一个“填充”节点 + * @private + * @method isFillChar + * @param { Node } node 需要判断的节点 + * @param { Boolean } isInStart 是否从节点内容的开始位置匹配 + * @returns { Boolean } 节点是否是填充节点 + */ + isFillChar: function(node, isInStart) { + if (node.nodeType != 3) return false; + var text = node.nodeValue; + if (isInStart) { + return new RegExp("^" + domUtils.fillChar).test(text); + } + return !text.replace(new RegExp(domUtils.fillChar, "g"), "").length; + }, + isStartInblock: function(range) { + var tmpRange = range.cloneRange(), + flag = 0, + start = tmpRange.startContainer, + tmp; + if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) { + start = start.childNodes[tmpRange.startOffset]; + var pre = start.previousSibling; + while (pre && domUtils.isFillChar(pre)) { + start = pre; + pre = pre.previousSibling; + } + } + if (this.isFillChar(start, true) && tmpRange.startOffset == 1) { + tmpRange.setStartBefore(start); + start = tmpRange.startContainer; + } + + while (start && domUtils.isFillChar(start)) { + tmp = start; + start = start.previousSibling; + } + if (tmp) { + tmpRange.setStartBefore(tmp); + start = tmpRange.startContainer; + } + if ( + start.nodeType == 1 && + domUtils.isEmptyNode(start) && + tmpRange.startOffset == 1 + ) { + tmpRange.setStart(start, 0).collapse(true); + } + while (!tmpRange.startOffset) { + start = tmpRange.startContainer; + if (domUtils.isBlockElm(start) || domUtils.isBody(start)) { + flag = 1; + break; + } + var pre = tmpRange.startContainer.previousSibling, + tmpNode; + if (!pre) { + tmpRange.setStartBefore(tmpRange.startContainer); + } else { + while (pre && domUtils.isFillChar(pre)) { + tmpNode = pre; + pre = pre.previousSibling; + } + if (tmpNode) { + tmpRange.setStartBefore(tmpNode); + } else { + tmpRange.setStartBefore(tmpRange.startContainer); + } + } + } + return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0; + }, + + /** + * 判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @return { Boolean } 是否是空元素 + * @example + * ```html + *
    + * + * + * ``` + */ + + /** + * 根据指定的判断规则判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @param { RegExp } reg 对内容执行判断的正则表达式对象 + * @return { Boolean } 是否是空元素 + */ + isEmptyBlock: function(node, reg) { + if (node.nodeType != 1) return 0; + reg = reg || new RegExp("[ \xa0\t\r\n" + domUtils.fillChar + "]", "g"); + + if ( + node[browser.ie ? "innerText" : "textContent"].replace(reg, "").length > 0 + ) { + return 0; + } + for (var n in dtd.$isNotEmpty) { + if (node.getElementsByTagName(n).length) { + return 0; + } + } + return 1; + }, + + /** + * 移动元素使得该元素的位置移动指定的偏移量的距离 + * @method setViewportOffset + * @param { Element } element 需要设置偏移量的元素 + * @param { Object } offset 偏移量, 形如{ left: 100, top: 50 }的一个键值对, 表示该元素将在 + * 现有的位置上向水平方向偏移offset.left的距离, 在竖直方向上偏移 + * offset.top的距离 + * @example + * ```html + *
    + * + * + * ``` + */ + setViewportOffset: function(element, offset) { + var left = parseInt(element.style.left) | 0; + var top = parseInt(element.style.top) | 0; + var rect = element.getBoundingClientRect(); + var offsetLeft = offset.left - rect.left; + var offsetTop = offset.top - rect.top; + if (offsetLeft) { + element.style.left = left + offsetLeft + "px"; + } + if (offsetTop) { + element.style.top = top + offsetTop + "px"; + } + }, + + /** + * 用“填充字符”填充节点 + * @method fillNode + * @private + * @param { DomDocument } doc 填充的节点所在的docment对象 + * @param { Node } node 需要填充的节点对象 + * @example + * ```html + *
    + * + * + * ``` + */ + fillNode: function(doc, node) { + var tmpNode = browser.ie + ? doc.createTextNode(domUtils.fillChar) + : doc.createElement("br"); + node.innerHTML = ""; + node.appendChild(tmpNode); + }, + + /** + * 把节点src的所有子节点追加到另一个节点tag上去 + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被追加到该节点下 + * @example + * ```html + *
    + * + *
    + *
    + *
    + *
    + * + * + * ``` + */ + + /** + * 把节点src的所有子节点移动到另一个节点tag上去, 可以通过dir参数控制附加的行为是“追加”还是“插入顶部” + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被附加到该节点下 + * @param { Boolean } dir 附加方式, 如果为true, 则附加进去的节点将被放到目标节点的顶部, 反之,则放到末尾 + * @example + * ```html + *
    + * + *
    + *
    + *
    + *
    + * + * + * ``` + */ + moveChild: function(src, tag, dir) { + while (src.firstChild) { + if (dir && tag.firstChild) { + tag.insertBefore(src.lastChild, tag.firstChild); + } else { + tag.appendChild(src.firstChild); + } + } + }, + + /** + * 判断节点的标签上是否不存在任何属性 + * @method hasNoAttributes + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否不包含任何属性 + * @example + * ```html + *
    xxxx
    + * + * + * ``` + */ + hasNoAttributes: function(node) { + return browser.ie + ? /^<\w+\s*?>/.test(node.outerHTML) + : node.attributes.length == 0; + }, + + /** + * 检测节点是否是UEditor所使用的辅助节点 + * @method isCustomeNode + * @private + * @param { Node } node 需要检测的节点 + * @remind 辅助节点是指编辑器要完成工作临时添加的节点, 在输出的时候将会从编辑器内移除, 不会影响最终的结果。 + * @return { Boolean } 给定的节点是否是一个辅助节点 + */ + isCustomeNode: function(node) { + return node.nodeType == 1 && node.getAttribute("_ue_custom_node_"); + }, + + /** + * 检测节点的标签是否是给定的标签 + * @method isTagNode + * @param { Node } node 需要检测的节点对象 + * @param { String } tagName 标签 + * @return { Boolean } 节点的标签是否是给定的标签 + * @example + * ```html + *
    + * + * + * ``` + */ + isTagNode: function(node, tagNames) { + return ( + node.nodeType == 1 && + new RegExp("\\b" + node.tagName + "\\b", "i").test(tagNames) + ); + }, + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 获取其中满足过滤条件的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @return { Node | NULL } 如果找到符合过滤条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() !== 'div'; + * } ) ); + * ``` + */ + + /** + * 给定一个节点数组nodeList和一组标签名tagNames, 获取其中能够匹配标签名的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { String } tagNames 需要匹配的标签名, 多个标签名之间用空格分割 + * @return { Node | NULL } 如果找到标签名匹配的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, 'a span' ) ); + * ``` + */ + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 如果参数forAll为true, 则会返回所有满足过滤 + * 条件的节点集合, 否则, 返回满足条件的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @param { Boolean } forAll 是否返回整个节点数组, 如果该参数为false, 则返回节点集合中的第一个节点 + * @return { Array | Node | NULL } 如果找到符合过滤条件的节点, 则根据参数forAll的值决定返回满足 + * 过滤条件的节点数组或第一个节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: 3(假定有3个div) + * console.log( divNodes.length ); + * + * var nodes = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, true ); + * + * //output: 3 + * console.log( nodes.length ); + * + * var node = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, false ); + * + * //output: div + * console.log( node.nodeName ); + * ``` + */ + filterNodeList: function(nodelist, filter, forAll) { + var results = []; + if (!utils.isFunction(filter)) { + var str = filter; + filter = function(n) { + return ( + utils.indexOf( + utils.isArray(str) ? str : str.split(" "), + n.tagName.toLowerCase() + ) != -1 + ); + }; + } + utils.each(nodelist, function(n) { + filter(n) && results.push(n); + }); + return results.length == 0 + ? null + : results.length == 1 || !forAll ? results[0] : results; + }, + + /** + * 查询给定的range选区是否在给定的node节点内,且在该节点的最末尾 + * @method isInNodeEndBoundary + * @param { UE.dom.Range } rng 需要判断的range对象, 该对象的startContainer不能为NULL + * @param node 需要检测的节点对象 + * @return { Number } 如果给定的选取range对象是在node内部的最末端, 则返回1, 否则返回0 + */ + isInNodeEndBoundary: function(rng, node) { + var start = rng.startContainer; + if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) { + return 0; + } + if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) { + return 0; + } + while (start !== node) { + if (start.nextSibling) { + return 0; + } + start = start.parentNode; + } + return 1; + }, + isBoundaryNode: function(node, dir) { + var tmp; + while (!domUtils.isBody(node)) { + tmp = node; + node = node.parentNode; + if (tmp !== node[dir]) { + return false; + } + } + return true; + }, + fillHtml: browser.ie11below ? " " : "
    ", + loadScript : function (url, cb) { + var script; + script = document.createElement('script'); + script.src = url; + script.onload = function(){ + cb && cb({isNew: true}) + }; + document.getElementsByTagName('head')[0].appendChild(script); + } +}); +var fillCharReg = new RegExp(domUtils.fillChar, "g"); + + +// core/Range.js +/** + * 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); + offset = offset || (win.innerHeight - 100); + // console.log('xxx',win, offset); + 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 < l; i++) { + ci = address[i]; + parentNode = tmpNode; + tmpNode = tmpNode.childNodes[ci]; + if (!tmpNode) { + offset = ci; + break; + } + } + if (isStart) { + if (tmpNode) { + me.setStartBefore(tmpNode); + } else { + me.setStart(parentNode, offset); + } + } else { + if (tmpNode) { + me.setEndBefore(tmpNode); + } else { + me.setEnd(parentNode, offset); + } + } + } + getNode(addr.startAddress, true); + !ignoreEnd && addr.endAddress && getNode(addr.endAddress); + return me; + }, + + /** + * 判断给定的Range对象是否和当前Range对象表示的是同一个选区 + * @method equals + * @param { UE.dom.Range } 需要判断的Range对象 + * @return { Boolean } 如果给定的Range对象与当前Range对象表示的是同一个选区, 则返回true, 否则返回false + */ + equals: function(rng) { + for (var p in this) { + if (this.hasOwnProperty(p)) { + if (this[p] !== rng[p]) return false; + } + } + return true; + }, + + /** + * 遍历range内的节点。每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 + * 作为其参数。 + * @method traversal + * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * + * + * + * + * + * + * + * + * + * ``` + */ + + /** + * 遍历range内的节点。 + * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 + * 作为其参数。 + * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触 + * 发doFn函数的执行 + * @method traversal + * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 + * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤 + * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不 + * 会触发doFn。 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:traversal(Function) + * @example + * ```html + * + * + * + * + * + * + * + * + * + * + * ``` + */ + traversal: function(doFn, filterFn) { + if (this.collapsed) return this; + var bookmark = this.createBookmark(), + end = bookmark.end, + current = domUtils.getNextDomNode(bookmark.start, false, filterFn); + while ( + current && + current !== end && + domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING + ) { + var tmpNode = domUtils.getNextDomNode(current, false, filterFn); + doFn(current); + current = tmpNode; + } + return this.moveToBookmark(bookmark); + } + }; +})(); + + +// core/Selection.js +/** + * 选集 + * @file + * @module UE.dom + * @class Selection + * @since 1.2.6.1 + */ + +/** + * 选区集合 + * @unfile + * @module UE.dom + * @class Selection + */ +(function() { + function getBoundaryInformation(range, start) { + var getIndex = domUtils.getNodeIndex; + range = range.duplicate(); + range.collapse(start); + var parent = range.parentElement(); + //如果节点里没有子节点,直接退出 + if (!parent.hasChildNodes()) { + return { container: parent, offset: 0 }; + } + var siblings = parent.children, + child, + testRange = range.duplicate(), + startIndex = 0, + endIndex = siblings.length - 1, + index = -1, + distance; + while (startIndex <= endIndex) { + index = Math.floor((startIndex + endIndex) / 2); + child = siblings[index]; + testRange.moveToElementText(child); + var position = testRange.compareEndPoints("StartToStart", range); + if (position > 0) { + endIndex = index - 1; + } else if (position < 0) { + startIndex = index + 1; + } else { + //trace:1043 + return { container: parent, offset: getIndex(child) }; + } + } + if (index == -1) { + testRange.moveToElementText(parent); + testRange.setEndPoint("StartToStart", range); + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + siblings = parent.childNodes; + if (!distance) { + child = siblings[siblings.length - 1]; + return { container: child, offset: child.nodeValue.length }; + } + + var i = siblings.length; + while (distance > 0) { + distance -= siblings[--i].nodeValue.length; + } + return { container: siblings[i], offset: -distance }; + } + testRange.collapse(position > 0); + testRange.setEndPoint(position > 0 ? "StartToStart" : "EndToStart", range); + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + if (!distance) { + return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] + ? { + container: parent, + offset: getIndex(child) + (position > 0 ? 0 : 1) + } + : { + container: child, + offset: position > 0 ? 0 : child.childNodes.length + }; + } + while (distance > 0) { + try { + var pre = child; + child = child[position > 0 ? "previousSibling" : "nextSibling"]; + distance -= child.nodeValue.length; + } catch (e) { + return { container: parent, offset: getIndex(pre) }; + } + } + return { + container: child, + offset: position > 0 ? -distance : child.nodeValue.length + distance + }; + } + + /** + * 将ieRange转换为Range对象 + * @param {Range} ieRange ieRange对象 + * @param {Range} range Range对象 + * @return {Range} range 返回转换后的Range对象 + */ + function transformIERangeToRange(ieRange, range) { + if (ieRange.item) { + range.selectNode(ieRange.item(0)); + } else { + var bi = getBoundaryInformation(ieRange, true); + range.setStart(bi.container, bi.offset); + if (ieRange.compareEndPoints("StartToEnd", ieRange) != 0) { + bi = getBoundaryInformation(ieRange, false); + range.setEnd(bi.container, bi.offset); + } + } + return range; + } + + /** + * 获得ieRange + * @param {Selection} sel Selection对象 + * @return {ieRange} 得到ieRange + */ + function _getIERange(sel) { + var ieRange; + //ie下有可能报错 + try { + ieRange = sel.getNative().createRange(); + } catch (e) { + return null; + } + var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); + if ((el.ownerDocument || el) === sel.document) { + return ieRange; + } + return null; + } + + var Selection = (dom.Selection = function(doc) { + var me = this, + iframe; + me.document = doc; + if (browser.ie9below) { + iframe = domUtils.getWindow(doc).frameElement; + domUtils.on(iframe, "beforedeactivate", function() { + me._bakIERange = me.getIERange(); + }); + domUtils.on(iframe, "activate", function() { + try { + if (!_getIERange(me) && me._bakIERange) { + me._bakIERange.select(); + } + } catch (ex) {} + me._bakIERange = null; + }); + } + iframe = doc = null; + }); + + Selection.prototype = { + rangeInBody: function(rng, txtRange) { + var node = browser.ie9below || txtRange + ? rng.item ? rng.item() : rng.parentElement() + : rng.startContainer; + + return node === this.document.body || domUtils.inDoc(node, this.document); + }, + + /** + * 获取原生seleciton对象 + * @method getNative + * @return { Object } 获得selection对象 + * @example + * ```javascript + * editor.selection.getNative(); + * ``` + */ + getNative: function() { + var doc = this.document; + try { + return !doc + ? null + : browser.ie9below + ? doc.selection + : domUtils.getWindow(doc).getSelection(); + } catch (e) { + return null; + } + }, + + /** + * 获得ieRange + * @method getIERange + * @return { Object } 返回ie原生的Range + * @example + * ```javascript + * editor.selection.getIERange(); + * ``` + */ + getIERange: function() { + var ieRange = _getIERange(this); + if (!ieRange) { + if (this._bakIERange) { + return this._bakIERange; + } + } + return ieRange; + }, + + /** + * 缓存当前选区的range和选区的开始节点 + * @method cache + */ + cache: function() { + this.clear(); + this._cachedRange = this.getRange(); + this._cachedStartElement = this.getStart(); + this._cachedStartElementPath = this.getStartElementPath(); + }, + + /** + * 获取选区开始位置的父节点到body + * @method getStartElementPath + * @return { Array } 返回父节点集合 + * @example + * ```javascript + * editor.selection.getStartElementPath(); + * ``` + */ + getStartElementPath: function() { + if (this._cachedStartElementPath) { + return this._cachedStartElementPath; + } + var start = this.getStart(); + if (start) { + return domUtils.findParents(start, true, null, true); + } + return []; + }, + + /** + * 清空缓存 + * @method clear + */ + clear: function() { + this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; + }, + + /** + * 编辑器是否得到了选区 + * @method isFocus + */ + isFocus: function() { + try { + if (browser.ie9below) { + var nativeRange = _getIERange(this); + return !!(nativeRange && this.rangeInBody(nativeRange)); + } else { + return !!this.getNative().rangeCount; + } + } catch (e) { + return false; + } + }, + + /** + * 获取选区对应的Range + * @method getRange + * @return { Object } 得到Range对象 + * @example + * ```javascript + * editor.selection.getRange(); + * ``` + */ + getRange: function() { + var me = this; + function optimze(range) { + var child = me.document.body.firstChild, + collapsed = range.collapsed; + while (child && child.firstChild) { + range.setStart(child, 0); + child = child.firstChild; + } + if (!range.startContainer) { + range.setStart(me.document.body, 0); + } + if (collapsed) { + range.collapse(true); + } + } + + if (me._cachedRange != null) { + return this._cachedRange; + } + var range = new baidu.editor.dom.Range(me.document); + + if (browser.ie9below) { + var nativeRange = me.getIERange(); + if (nativeRange) { + //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置 + try { + transformIERangeToRange(nativeRange, range); + } catch (e) { + optimze(range); + } + } else { + optimze(range); + } + } else { + var sel = me.getNative(); + if (sel && sel.rangeCount) { + var firstRange = sel.getRangeAt(0); + var lastRange = sel.getRangeAt(sel.rangeCount - 1); + range + .setStart(firstRange.startContainer, firstRange.startOffset) + .setEnd(lastRange.endContainer, lastRange.endOffset); + if ( + range.collapsed && + domUtils.isBody(range.startContainer) && + !range.startOffset + ) { + optimze(range); + } + } else { + //trace:1734 有可能已经不在dom树上了,标识的节点 + if ( + this._bakRange && + domUtils.inDoc(this._bakRange.startContainer, this.document) + ) { + return this._bakRange; + } + optimze(range); + } + } + return (this._bakRange = range); + }, + + /** + * 获取开始元素,用于状态反射 + * @method getStart + * @return { Element } 获得开始元素 + * @example + * ```javascript + * editor.selection.getStart(); + * ``` + */ + getStart: function() { + if (this._cachedStartElement) { + return this._cachedStartElement; + } + var range = browser.ie9below ? this.getIERange() : this.getRange(), + tmpRange, + start, + tmp, + parent; + if (browser.ie9below) { + if (!range) { + //todo 给第一个值可能会有问题 + return this.document.body.firstChild; + } + //control元素 + if (range.item) { + return range.item(0); + } + tmpRange = range.duplicate(); + //修正ie下x[xx] 闭合后 x|xx + tmpRange.text.length > 0 && tmpRange.moveStart("character", 1); + tmpRange.collapse(1); + start = tmpRange.parentElement(); + parent = tmp = range.parentElement(); + while ((tmp = tmp.parentNode)) { + if (tmp == start) { + start = parent; + break; + } + } + } else { + range.shrinkBoundary(); + start = range.startContainer; + if (start.nodeType == 1 && start.hasChildNodes()) { + start = + start.childNodes[ + Math.min(start.childNodes.length - 1, range.startOffset) + ]; + } + if (start.nodeType == 3) { + return start.parentNode; + } + } + return start; + }, + + /** + * 得到选区中的文本 + * @method getText + * @return { String } 选区中包含的文本 + * @example + * ```javascript + * editor.selection.getText(); + * ``` + */ + getText: function() { + var nativeSel, nativeRange; + if (this.isFocus() && (nativeSel = this.getNative())) { + nativeRange = browser.ie9below + ? nativeSel.createRange() + : nativeSel.getRangeAt(0); + return browser.ie9below ? nativeRange.text : nativeRange.toString(); + } + return ""; + }, + + /** + * 清除选区 + * @method clearRange + * @example + * ```javascript + * editor.selection.clearRange(); + * ``` + */ + clearRange: function() { + this.getNative()[browser.ie9below ? "empty" : "removeAllRanges"](); + } + }; +})(); + + +// core/Editor.js +/** + * 编辑器主类,包含编辑器提供的大部分公用接口 + * @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?20230921", + 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 additionCssHtml = []; + for(var i of options.iframeCssUrlsAddition){ + additionCssHtml.push("") + } + var html = + (ie && browser.version < 9 ? "" : "") + + "" + + "" + + "" + + (options.iframeCssUrl + ? "" + : "") + + (options.initialStyle + ? "" + : "") + + additionCssHtml.join("") + + "" + + "" + + "" + + (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); + }); + domUtils.on(form, "submit", function() { + me.fireEvent("beforesubmit"); + }); + } else { + domUtils.on(form, "submit", function() { + setValue(this, me); + me.fireEvent("beforesubmit"); + }); + } + 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); + }, + + /** + * 手动触发更新按钮栏状态 + */ + syncCommandState: function(){ + this.fireEvent("selectionchange"); + }, + + /** + * 设置编辑器宽度 + * @param width + */ + setWidth: function(width){ + if (width !== parseInt(this.iframe.parentNode.parentNode.style.width)) { + this.iframe.parentNode.parentNode.style.width = width + "px"; + } + }, + + /** + * 设置编辑器高度 + * @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"); + }); + // 当内容最末尾为非字符时,比较难以在最后插入字符,所以在点击时,自动添加一个空的p标签 + domUtils.on(me.body, "dblclick", function(e) { + try { + var node = me.body.lastChild; + if (!node) { + return; + } + var rect = node.getBoundingClientRect(); + if (e.clientY > rect.top + rect.height) { + var p = document.createElement('p'); + p.innerHTML = '
    '; + me.body.appendChild(p); + setTimeout(function () { + me.focus(true); + }, 100); + } + } catch (e) { + console.error('auto insert p at end', e); + } + }); + 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; + } + } + } + // 部分如媒体标签,不能认为为空 + tags = [ "video","iframe" ] + for (i = 0; (ci = tags[i++]); ) { + var nodes = domUtils.getElementsByTagName(this.document, ci); + for (var n = 0, cn; (cn = nodes[n++]); ) { + 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); +})(); + + +// core/Editor.defaultoptions.js +//维护编辑器一下默认的不在插件中的配置项 +UE.Editor.defaultOptions = function(editor) { + var _url = editor.options.UEDITOR_HOME_URL; + return { + isShow: true, + initialContent: "", + initialStyle: "", + autoClearinitialContent: false, + iframeCssUrl: _url + "themes/iframe.css?20221113", + iframeCssUrlsAddition: [], + 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}" + }; +}; + + +// core/loadconfig.js +(function () { + UE.Editor.prototype.loadServerConfig = function () { + var me = this; + setTimeout(function () { + try { + me.options.imageUrl && + me.setOpt( + "serverUrl", + me.options.imageUrl.replace( + /^(.*[\/]).+([\.].+)$/, + "$1controller$2" + ) + ); + + var configUrl = me.getActionUrl("config"), + isJsonp = utils.isCrossDomainUrl(configUrl); + + /* 发出ajax请求 */ + me._serverConfigLoaded = false; + + configUrl && + UE.ajax.request(configUrl, { + method: "GET", + dataType: isJsonp ? "jsonp" : "", + headers: me.options.serverHeaders || {}, + onsuccess: function (r) { + try { + var config = isJsonp ? r : eval("(" + r.responseText + ")"); + // console.log('me.options.before', me.options.audioConfig); + me.options = utils.merge(me.options, config); + // console.log('server.config', config.audioConfig); + // console.log('me.options.after', me.options.audioConfig); + me.fireEvent("serverConfigLoaded"); + me._serverConfigLoaded = true; + } catch (e) { + showErrorMsg(me.getLang("loadconfigFormatError")); + } + }, + onerror: function () { + showErrorMsg(me.getLang("loadconfigHttpError")); + } + }); + } catch (e) { + showErrorMsg(me.getLang("loadconfigError")); + } + }); + + function showErrorMsg(msg) { + console && console.error(msg); + //me.fireEvent('showMessage', { + // 'title': msg, + // 'type': 'error' + //}); + } + }; + + UE.Editor.prototype.isServerConfigLoaded = function () { + var me = this; + return me._serverConfigLoaded || false; + }; + + UE.Editor.prototype.afterConfigReady = function (handler) { + if (!handler || !utils.isFunction(handler)) return; + var me = this; + var readyHandler = function () { + handler.apply(me, arguments); + me.removeListener("serverConfigLoaded", readyHandler); + }; + + if (me.isServerConfigLoaded()) { + handler.call(me, "serverConfigLoaded"); + } else { + me.addListener("serverConfigLoaded", readyHandler); + } + }; +})(); + + +// core/ajax.js +/** + * @file + * @module UE.ajax + * @since 1.2.6.1 + */ + +/** + * 提供对ajax请求的支持 + * @module UE.ajax + */ +UE.ajax = (function() { + //创建一个ajaxRequest对象 + var fnStr = "XMLHttpRequest()"; + try { + new ActiveXObject("Msxml2.XMLHTTP"); + fnStr = "ActiveXObject('Msxml2.XMLHTTP')"; + } catch (e) { + try { + new ActiveXObject("Microsoft.XMLHTTP"); + fnStr = "ActiveXObject('Microsoft.XMLHTTP')"; + } catch (e) {} + } + var creatAjaxRequest = new Function("return new " + fnStr); + + /** + * 将json参数转化成适合ajax提交的参数列表 + * @param json + */ + function json2str(json) { + var strArr = []; + for (var i in json) { + //忽略默认的几个参数 + if ( + i == "method" || + i == "timeout" || + i == "async" || + i == "dataType" || + i == "callback" + ) + continue; + //忽略控制 + if (json[i] == undefined || json[i] == null) continue; + //传递过来的对象和函数不在提交之列 + if ( + !( + (typeof json[i]).toLowerCase() == "function" || + (typeof json[i]).toLowerCase() == "object" + ) + ) { + strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i])); + } else if (utils.isArray(json[i])) { + //支持传数组内容 + for (var j = 0; j < json[i].length; j++) { + strArr.push( + encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]) + ); + } + } + } + return strArr.join("&"); + } + + function doAjax(url, ajaxOptions) { + var xhr = creatAjaxRequest(), + //是否超时 + timeIsOut = false, + //默认参数 + defaultAjaxOptions = { + method: "POST", + timeout: 5000, + async: true, + headers: {}, + data: {}, //需要传递对象的话只能覆盖 + onsuccess: function() {}, + onerror: function() {} + }; + + if (typeof url === "object") { + ajaxOptions = url; + url = ajaxOptions.url; + } + if (!xhr || !url) return; + var ajaxOpts = ajaxOptions + ? utils.extend(defaultAjaxOptions, ajaxOptions) + : defaultAjaxOptions; + + // console.log('ajaxOpts',ajaxOpts); + + var submitStr = json2str(ajaxOpts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(ajaxOpts.data)) { + submitStr += (submitStr ? "&" : "") + json2str(ajaxOpts.data); + } + //超时检测 + var timerID = setTimeout(function() { + if (xhr.readyState !== 4) { + timeIsOut = true; + xhr.abort(); + clearTimeout(timerID); + } + }, ajaxOpts.timeout); + + var method = ajaxOpts.method.toUpperCase(); + var str = + url + + (url.indexOf("?") === -1 ? "?" : "&") + + (method === "POST" ? "" : submitStr + "&noCache=" + +new Date()); + xhr.open(method, str, ajaxOpts.async); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (!timeIsOut && xhr.status === 200) { + ajaxOpts.onsuccess(xhr); + } else { + ajaxOpts.onerror(xhr); + } + } + }; + if(ajaxOpts.headers){ + for(var key in ajaxOpts.headers){ + xhr.setRequestHeader(key,ajaxOpts.headers[key]); + } + } + if (method === "POST") { + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.send(submitStr); + } else { + xhr.send(null); + } + } + + function doJsonp(url, opts) { + var successhandler = opts.onsuccess || function() {}, + scr = document.createElement("SCRIPT"), + options = opts || {}, + charset = options["charset"], + callbackField = options["jsonp"] || "callback", + callbackFnName, + timeOut = options["timeOut"] || 0, + timer, + reg = new RegExp("(\\?|&)" + callbackField + "=([^&]*)"), + matches; + + if (utils.isFunction(successhandler)) { + callbackFnName = + "bd__editor__" + Math.floor(Math.random() * 2147483648).toString(36); + window[callbackFnName] = getCallBack(0); + } else if (utils.isString(successhandler)) { + callbackFnName = successhandler; + } else { + if ((matches = reg.exec(url))) { + callbackFnName = matches[2]; + } + } + + url = url.replace(reg, "\x241" + callbackField + "=" + callbackFnName); + + if (url.search(reg) < 0) { + url += + (url.indexOf("?") < 0 ? "?" : "&") + + callbackField + + "=" + + callbackFnName; + } + + var queryStr = json2str(opts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(opts.data)) { + queryStr += (queryStr ? "&" : "") + json2str(opts.data); + } + if (queryStr) { + url = url.replace(/\?/, "?" + queryStr + "&"); + } + + scr.onerror = getCallBack(1); + if (timeOut) { + timer = setTimeout(getCallBack(1), timeOut); + } + createScriptTag(scr, url, charset); + + function createScriptTag(scr, url, charset) { + scr.setAttribute("type", "text/javascript"); + scr.setAttribute("defer", "defer"); + charset && scr.setAttribute("charset", charset); + scr.setAttribute("src", url); + document.getElementsByTagName("head")[0].appendChild(scr); + } + + function getCallBack(onTimeOut) { + return function() { + try { + if (onTimeOut) { + options.onerror && options.onerror(); + } else { + try { + clearTimeout(timer); + successhandler.apply(window, arguments); + } catch (e) {} + } + } catch (exception) { + options.onerror && options.onerror.call(window, exception); + } finally { + options.oncomplete && options.oncomplete.apply(window, arguments); + scr.parentNode && scr.parentNode.removeChild(scr); + window[callbackFnName] = null; + try { + delete window[callbackFnName]; + } catch (e) {} + } + }; + } + } + + return { + /** + * 根据给定的参数项,向指定的url发起一个ajax请求。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调 + * @method request + * @param { URLString } url ajax请求的url地址 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * //向sayhello.php发起一个异步的Ajax GET请求, 请求超时时间为10s, 请求完成后执行相应的回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求方法。可选值: 'GET', 'POST',默认值是'POST' + * method: 'GET', + * + * //超时时间。 默认为5000, 单位是ms + * timeout: 10000, + * + * //是否是异步请求。 true为异步请求, false为同步请求 + * async: true, + * + * //请求携带的数据。如果请求为GET请求, data会经过stringify后附加到请求url之后。 + * data: { + * name: 'ueditor' + * }, + * + * //请求成功后的回调, 该回调接受当前的XMLHttpRequest对象作为参数。 + * onsuccess: function ( xhr ) { + * console.log( xhr.responseText ); + * }, + * + * //请求失败或者超时后的回调。 + * onerror: function ( xhr ) { + * alert( 'Ajax请求失败' ); + * } + * + * } ); + * ``` + */ + + /** + * 根据给定的参数项发起一个ajax请求, 参数项里必须包含一个url地址。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调。 + * @method request + * @warning 如果在参数项里未提供一个key为“url”的地址值,则该请求将直接退出。 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * + * //向sayhello.php发起一个异步的Ajax POST请求, 请求超时时间为5s, 请求完成后不执行任何回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求的地址, 该项是必须的。 + * url: 'sayhello.php' + * + * } ); + * ``` + */ + request: function(url, opts) { + if (opts && opts.dataType === "jsonp") { + doJsonp(url, opts); + } else { + doAjax(url, opts); + } + }, + getJSONP: function(url, data, fn) { + var opts = { + data: data, + oncomplete: fn + }; + doJsonp(url, opts); + } + }; +})(); + + +// core/api.js +UE.api = (function(){ + // axios import + var axios = null; + !function(e,t){axios=t()}(this,(function(){"use strict";function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=i.allOwnKeys,s=void 0!==a&&a;if(null!=t)if("object"!==e(t)&&(t=[t]),p(t))for(r=0,o=t.length;r0;)if(t===(n=r[o]).toLowerCase())return n;return null}var N="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,C=function(e){return!h(e)&&e!==N};var x,P=(x="undefined"!=typeof Uint8Array&&c(Uint8Array),function(e){return x&&e instanceof x}),k=l("HTMLFormElement"),U=function(e){var t=Object.prototype.hasOwnProperty;return function(e,n){return t.call(e,n)}}(),_=l("RegExp"),F=function(e,t){var n=Object.getOwnPropertyDescriptors(e),r={};T(n,(function(n,o){!1!==t(n,o,e)&&(r[o]=n)})),Object.defineProperties(e,r)},B="abcdefghijklmnopqrstuvwxyz",L="0123456789",D={DIGIT:L,ALPHA:B,ALPHA_DIGIT:B+B.toUpperCase()+L};var I=l("AsyncFunction"),q={isArray:p,isArrayBuffer:m,isBuffer:function(e){return null!==e&&!h(e)&&null!==e.constructor&&!h(e.constructor)&&v(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:function(e){var t;return e&&("function"==typeof FormData&&e instanceof FormData||v(e.append)&&("formdata"===(t=f(e))||"object"===t&&v(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&m(e.buffer)},isString:y,isNumber:b,isBoolean:function(e){return!0===e||!1===e},isObject:g,isPlainObject:w,isUndefined:h,isDate:E,isFile:O,isBlob:S,isRegExp:_,isFunction:v,isStream:function(e){return g(e)&&v(e.pipe)},isURLSearchParams:A,isTypedArray:P,isFileList:R,forEach:T,merge:function e(){for(var t=C(this)&&this||{},n=t.caseless,r={},o=function(t,o){var i=n&&j(r,o)||o;w(r[i])&&w(t)?r[i]=e(r[i],t):w(t)?r[i]=e({},t):p(t)?r[i]=t.slice():r[i]=t},i=0,a=arguments.length;i3&&void 0!==arguments[3]?arguments[3]:{},o=r.allOwnKeys;return T(t,(function(t,r){n&&v(t)?e[r]=a(t,n):e[r]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,n,r){e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},toFlatObject:function(e,t,n,r){var o,i,a,s={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],r&&!r(a,e,t)||s[a]||(t[a]=e[a],s[a]=!0);e=!1!==n&&c(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},kindOf:f,kindOfTest:l,endsWith:function(e,t,n){e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;var r=e.indexOf(t,n);return-1!==r&&r===n},toArray:function(e){if(!e)return null;if(p(e))return e;var t=e.length;if(!b(t))return null;for(var n=new Array(t);t-- >0;)n[t]=e[t];return n},forEachEntry:function(e,t){for(var n,r=(e&&e[Symbol.iterator]).call(e);(n=r.next())&&!n.done;){var o=n.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var n,r=[];null!==(n=e.exec(t));)r.push(n);return r},isHTMLForm:k,hasOwnProperty:U,hasOwnProp:U,reduceDescriptors:F,freezeMethods:function(e){F(e,(function(t,n){if(v(e)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;var r=e[n];v(r)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=function(){throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:function(e,t){var n={},r=function(e){e.forEach((function(e){n[e]=!0}))};return p(e)?r(e):r(String(e).split(t)),n},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))},noop:function(){},toFiniteNumber:function(e,t){return e=+e,Number.isFinite(e)?e:t},findKey:j,global:N,isContextDefined:C,ALPHABET:D,generateString:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:D.ALPHA_DIGIT,n="",r=t.length;e--;)n+=t[Math.random()*r|0];return n},isSpecCompliantForm:function(e){return!!(e&&v(e.append)&&"FormData"===e[Symbol.toStringTag]&&e[Symbol.iterator])},toJSONObject:function(e){var t=new Array(10);return function e(n,r){if(g(n)){if(t.indexOf(n)>=0)return;if(!("toJSON"in n)){t[r]=n;var o=p(n)?[]:{};return T(n,(function(t,n){var i=e(t,r+1);!h(i)&&(o[n]=i)})),t[r]=void 0,o}}return n}(e,0)},isAsyncFn:I,isThenable:function(e){return e&&(g(e)||v(e))&&v(e.then)&&v(e.catch)}};function M(e,t,n,r,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o)}q.inherits(M,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:q.toJSONObject(this.config),code:this.code,status:this.response&&this.response.status?this.response.status:null}}});var z=M.prototype,H={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((function(e){H[e]={value:e}})),Object.defineProperties(M,H),Object.defineProperty(z,"isAxiosError",{value:!0}),M.from=function(e,t,n,r,o,i){var a=Object.create(z);return q.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return"isAxiosError"!==e})),M.call(a,e.message,t,n,r,o),a.cause=e,a.name=e.name,i&&Object.assign(a,i),a};function J(e){return q.isPlainObject(e)||q.isArray(e)}function W(e){return q.endsWith(e,"[]")?e.slice(0,-2):e}function K(e,t,n){return e?e.concat(t).map((function(e,t){return e=W(e),!n&&t?"["+e+"]":e})).join(n?".":""):t}var V=q.toFlatObject(q,{},null,(function(e){return/^is[A-Z]/.test(e)}));function G(t,n,r){if(!q.isObject(t))throw new TypeError("target must be an object");n=n||new FormData;var o=(r=q.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!q.isUndefined(t[e])}))).metaTokens,i=r.visitor||f,a=r.dots,s=r.indexes,u=(r.Blob||"undefined"!=typeof Blob&&Blob)&&q.isSpecCompliantForm(n);if(!q.isFunction(i))throw new TypeError("visitor must be a function");function c(e){if(null===e)return"";if(q.isDate(e))return e.toISOString();if(!u&&q.isBlob(e))throw new M("Blob is not supported. Use a Buffer instead.");return q.isArrayBuffer(e)||q.isTypedArray(e)?u&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function f(t,r,i){var u=t;if(t&&!i&&"object"===e(t))if(q.endsWith(r,"{}"))r=o?r:r.slice(0,-2),t=JSON.stringify(t);else if(q.isArray(t)&&function(e){return q.isArray(e)&&!e.some(J)}(t)||(q.isFileList(t)||q.endsWith(r,"[]"))&&(u=q.toArray(t)))return r=W(r),u.forEach((function(e,t){!q.isUndefined(e)&&null!==e&&n.append(!0===s?K([r],t,a):null===s?r:r+"[]",c(e))})),!1;return!!J(t)||(n.append(K(i,r,a),c(t)),!1)}var l=[],d=Object.assign(V,{defaultVisitor:f,convertValue:c,isVisitable:J});if(!q.isObject(t))throw new TypeError("data must be an object");return function e(t,r){if(!q.isUndefined(t)){if(-1!==l.indexOf(t))throw Error("Circular reference detected in "+r.join("."));l.push(t),q.forEach(t,(function(t,o){!0===(!(q.isUndefined(t)||null===t)&&i.call(n,t,q.isString(o)?o.trim():o,r,d))&&e(t,r?r.concat(o):[o])})),l.pop()}}(t),n}function $(e){var t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function X(e,t){this._pairs=[],e&&G(e,this,t)}var Q=X.prototype;function Z(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function Y(e,t,n){if(!t)return e;var r,o=n&&n.encode||Z,i=n&&n.serialize;if(r=i?i(t,n):q.isURLSearchParams(t)?t.toString():new X(t,n).toString(o)){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+r}return e}Q.append=function(e,t){this._pairs.push([e,t])},Q.toString=function(e){var t=e?function(t){return e.call(this,t,$)}:$;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var ee,te=function(){function e(){t(this,e),this.handlers=[]}return r(e,[{key:"use",value:function(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}},{key:"eject",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:"clear",value:function(){this.handlers&&(this.handlers=[])}},{key:"forEach",value:function(e){q.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),ne={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},re={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:X,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},isStandardBrowserEnv:("undefined"==typeof navigator||"ReactNative"!==(ee=navigator.product)&&"NativeScript"!==ee&&"NS"!==ee)&&"undefined"!=typeof window&&"undefined"!=typeof document,isStandardBrowserWebWorkerEnv:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,protocols:["http","https","file","blob","url","data"]};function oe(e){function t(e,n,r,o){var i=e[o++],a=Number.isFinite(+i),s=o>=e.length;return i=!i&&q.isArray(r)?r.length:i,s?(q.hasOwnProp(r,i)?r[i]=[r[i],n]:r[i]=n,!a):(r[i]&&q.isObject(r[i])||(r[i]=[]),t(e,n,r[i],o)&&q.isArray(r[i])&&(r[i]=function(e){var t,n,r={},o=Object.keys(e),i=o.length;for(t=0;t-1,i=q.isObject(e);if(i&&q.isHTMLForm(e)&&(e=new FormData(e)),q.isFormData(e))return o&&o?JSON.stringify(oe(e)):e;if(q.isArrayBuffer(e)||q.isBuffer(e)||q.isStream(e)||q.isFile(e)||q.isBlob(e))return e;if(q.isArrayBufferView(e))return e.buffer;if(q.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();if(i){if(r.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return G(e,new re.classes.URLSearchParams,Object.assign({visitor:function(e,t,n,r){return re.isNode&&q.isBuffer(e)?(this.append(t,e.toString("base64")),!1):r.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((n=q.isFileList(e))||r.indexOf("multipart/form-data")>-1){var a=this.env&&this.env.FormData;return G(n?{"files[]":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType("application/json",!1),function(e,t,n){if(q.isString(e))try{return(t||JSON.parse)(e),q.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||ae.transitional,n=t&&t.forcedJSONParsing,r="json"===this.responseType;if(e&&q.isString(e)&&(n&&!this.responseType||r)){var o=!(t&&t.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(e){if(o){if("SyntaxError"===e.name)throw M.from(e,M.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:re.classes.FormData,Blob:re.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};q.forEach(["delete","get","head"],(function(e){ae.headers[e]={}})),q.forEach(["post","put","patch"],(function(e){ae.headers[e]=q.merge(ie)}));var se=ae,ue=q.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),ce=Symbol("internals");function fe(e){return e&&String(e).trim().toLowerCase()}function le(e){return!1===e||null==e?e:q.isArray(e)?e.map(le):String(e)}function de(e,t,n,r,o){return q.isFunction(r)?r.call(this,t,n):(o&&(t=n),q.isString(t)?q.isString(r)?-1!==t.indexOf(r):q.isRegExp(r)?r.test(t):void 0:void 0)}var pe=function(e,n){function i(e){t(this,i),e&&this.set(e)}return r(i,[{key:"set",value:function(e,t,n){var r=this;function o(e,t,n){var o=fe(t);if(!o)throw new Error("header name must be a non-empty string");var i=q.findKey(r,o);(!i||void 0===r[i]||!0===n||void 0===n&&!1!==r[i])&&(r[i||t]=le(e))}var i,a,s,u,c,f=function(e,t){return q.forEach(e,(function(e,n){return o(e,n,t)}))};return q.isPlainObject(e)||e instanceof this.constructor?f(e,t):q.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim())?f((c={},(i=e)&&i.split("\n").forEach((function(e){u=e.indexOf(":"),a=e.substring(0,u).trim().toLowerCase(),s=e.substring(u+1).trim(),!a||c[a]&&ue[a]||("set-cookie"===a?c[a]?c[a].push(s):c[a]=[s]:c[a]=c[a]?c[a]+", "+s:s)})),c),t):null!=e&&o(t,e,n),this}},{key:"get",value:function(e,t){if(e=fe(e)){var n=q.findKey(this,e);if(n){var r=this[n];if(!t)return r;if(!0===t)return function(e){for(var t,n=Object.create(null),r=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;t=r.exec(e);)n[t[1]]=t[2];return n}(r);if(q.isFunction(t))return t.call(this,r,n);if(q.isRegExp(t))return t.exec(r);throw new TypeError("parser must be boolean|regexp|function")}}}},{key:"has",value:function(e,t){if(e=fe(e)){var n=q.findKey(this,e);return!(!n||void 0===this[n]||t&&!de(0,this[n],n,t))}return!1}},{key:"delete",value:function(e,t){var n=this,r=!1;function o(e){if(e=fe(e)){var o=q.findKey(n,e);!o||t&&!de(0,n[o],o,t)||(delete n[o],r=!0)}}return q.isArray(e)?e.forEach(o):o(e),r}},{key:"clear",value:function(e){for(var t=Object.keys(this),n=t.length,r=!1;n--;){var o=t[n];e&&!de(0,this[o],o,e,!0)||(delete this[o],r=!0)}return r}},{key:"normalize",value:function(e){var t=this,n={};return q.forEach(this,(function(r,o){var i=q.findKey(n,o);if(i)return t[i]=le(r),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=le(r),n[a]=!0})),this}},{key:"concat",value:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r1?n-1:0),o=1;o0;){var a=o[i],s=n[a];if(s){var u=t[a],c=void 0===u||s(u,a,t);if(!0!==c)throw new M("option "+a+" must be "+c,M.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new M("Unknown option "+a,M.ERR_BAD_OPTION)}},validators:Ce},ke=Pe.validators,Ue=function(){function e(n){t(this,e),this.defaults=n,this.interceptors={request:new te,response:new te}}return r(e,[{key:"request",value:function(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{};var n,r=t=je(this.defaults,t),o=r.transitional,i=r.paramsSerializer,a=r.headers;void 0!==o&&Pe.assertOptions(o,{silentJSONParsing:ke.transitional(ke.boolean),forcedJSONParsing:ke.transitional(ke.boolean),clarifyTimeoutError:ke.transitional(ke.boolean)},!1),null!=i&&(q.isFunction(i)?t.paramsSerializer={serialize:i}:Pe.assertOptions(i,{encode:ke.function,serialize:ke.function},!0)),t.method=(t.method||this.defaults.method||"get").toLowerCase(),(n=a&&q.merge(a.common,a[t.method]))&&q.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete a[e]})),t.headers=he.concat(n,a);var s=[],u=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(u=u&&e.synchronous,s.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,d=0;if(!u){var p=[Ae.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,f),l=p.length,c=Promise.resolve(t);d0;)o._listeners[t](e);o._listeners=null}})),this.promise.then=function(e){var t,n=new Promise((function(e){o.subscribe(e),t=e})).then(e);return n.cancel=function(){o.unsubscribe(t)},n},n((function(e,t,n){o.reason||(o.reason=new ve(e,t,n),r(o.reason))}))}return r(e,[{key:"throwIfRequested",value:function(){if(this.reason)throw this.reason}},{key:"subscribe",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:"unsubscribe",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}}],[{key:"source",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}();var Be={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Be).forEach((function(e){var t=o(e,2),n=t[0],r=t[1];Be[r]=n}));var Le=Be;var De=function e(t){var n=new _e(t),r=a(_e.prototype.request,n);return q.extend(r,_e.prototype,n,{allOwnKeys:!0}),q.extend(r,n,null,{allOwnKeys:!0}),r.create=function(n){return e(je(t,n))},r}(se);return De.Axios=_e,De.CanceledError=ve,De.CancelToken=Fe,De.isCancel=ye,De.VERSION=Ne,De.toFormData=G,De.AxiosError=M,De.Cancel=De.CanceledError,De.all=function(e){return Promise.all(e)},De.spread=function(e){return function(t){return e.apply(null,t)}},De.isAxiosError=function(e){return q.isObject(e)&&!0===e.isAxiosError},De.mergeConfig=je,De.AxiosHeaders=he,De.formToJSON=function(e){return oe(q.isHTMLForm(e)?new FormData(e):e)},De.HttpStatusCode=Le,De.default=De,De})); + return { + requestAction: function (me, action, config) { + config.url = me.getOpt('serverUrl'); + config.method = 'post'; + config.params = config.params || {}; + config.params = Object.assign(config.params, me.getOpt('serverparam')); + config.params.action = action; + return this.request(me, config); + }, + request: function (me, config) { + config.headers = config.headers || {}; + var customHeaders = me.getOpt('serverHeaders'); + if (customHeaders) { + for (var key in customHeaders) { + config.headers[key] = customHeaders[key]; + } + } + return axios(config); + } + } +})(); + + +// core/image.js +UE.image = (function(){ + // import browser-image-compression + // https://www.npmjs.com/package/browser-image-compression + var imageCompression = null; + !function(e,t){imageCompression=t();}(this,(function(){"use strict";function _mergeNamespaces(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(r){if("default"!==r&&!(r in e)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}))})),Object.freeze(e)}function copyExifWithoutOrientation(e,t){return new Promise((function(r,i){let o;return getApp1Segment(e).then((function(e){try{return o=e,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:"image/jpeg"}))}catch(e){return i(e)}}),i)}))}const getApp1Segment=e=>new Promise(((t,r)=>{const i=new FileReader;i.addEventListener("load",(({target:{result:e}})=>{const i=new DataView(e);let o=0;if(65496!==i.getUint16(o))return r("not a valid JPEG");for(o+=2;;){const a=i.getUint16(o);if(65498===a)break;const s=i.getUint16(o+2);if(65505===a&&1165519206===i.getUint32(o+4)){const a=o+10;let f;switch(i.getUint16(a)){case 18761:f=!0;break;case 19789:f=!1;break;default:return r("TIFF header contains invalid endian")}if(42!==i.getUint16(a+2,f))return r("TIFF header contains invalid version");const l=i.getUint32(a+4,f),c=a+l+2+12*i.getUint16(a+l,f);for(let e=a+l+2;e>>24&255,i[r+1]=o>>>16&255,i[r+2]=o>>>8&255,i[r+3]=o>>>0&255,new Uint8Array(i.buffer,0,r+4)},UZIP.deflateRaw=function(e,t){null==t&&(t={level:6});var r=new Uint8Array(50+Math.floor(1.1*e.length)),i=UZIP.F.deflateRaw(e,r,i,t.level);return new Uint8Array(r.buffer,0,i)},UZIP.encode=function(e,t){null==t&&(t=!1);var r=0,i=UZIP.bin.writeUint,o=UZIP.bin.writeUshort,a={};for(var s in e){var f=!UZIP._noNeed(s)&&!t,l=e[s],c=UZIP.crc.crc(l,0,l.length);a[s]={cpr:f,usize:l.length,crc:c,file:f?UZIP.deflateRaw(l):l}}for(var s in a)r+=a[s].file.length+30+46+2*UZIP.bin.sizeUTF8(s);r+=22;var u=new Uint8Array(r),h=0,d=[];for(var s in a){var A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,0)}var g=0,p=h;for(var s in a){A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,1,d[g++])}var m=h-p;return i(u,h,101010256),h+=4,o(u,h+=4,g),o(u,h+=2,g),i(u,h+=2,m),i(u,h+=4,p),h+=4,h+=2,u.buffer},UZIP._noNeed=function(e){var t=e.split(".").pop().toLowerCase();return-1!="png,jpg,jpeg,zip".indexOf(t)},UZIP._writeHeader=function(e,t,r,i,o,a){var s=UZIP.bin.writeUint,f=UZIP.bin.writeUshort,l=i.file;return s(e,t,0==o?67324752:33639248),t+=4,1==o&&(t+=2),f(e,t,20),f(e,t+=2,0),f(e,t+=2,i.cpr?8:0),s(e,t+=2,0),s(e,t+=4,i.crc),s(e,t+=4,l.length),s(e,t+=4,i.usize),f(e,t+=4,UZIP.bin.sizeUTF8(r)),f(e,t+=2,0),t+=2,1==o&&(t+=2,t+=2,s(e,t+=6,a),t+=4),t+=UZIP.bin.writeUTF8(e,t,r),0==o&&(e.set(l,t),t+=l.length),t},UZIP.crc={table:function(){for(var e=new Uint32Array(256),t=0;t<256;t++){for(var r=t,i=0;i<8;i++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update:function(e,t,r,i){for(var o=0;o>>8;return e},crc:function(e,t,r){return 4294967295^UZIP.crc.update(4294967295,e,t,r)}},UZIP.adler=function(e,t,r){for(var i=1,o=0,a=t,s=t+r;a>8&255},readUint:function(e,t){return 16777216*e[t+3]+(e[t+2]<<16|e[t+1]<<8|e[t])},writeUint:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255,e[t+2]=r>>16&255,e[t+3]=r>>24&255},readASCII:function(e,t,r){for(var i="",o=0;o>6,e[t+o+1]=128|s>>0&63,o+=2;else if(0==(4294901760&s))e[t+o]=224|s>>12,e[t+o+1]=128|s>>6&63,e[t+o+2]=128|s>>0&63,o+=3;else{if(0!=(4292870144&s))throw"e";e[t+o]=240|s>>18,e[t+o+1]=128|s>>12&63,e[t+o+2]=128|s>>6&63,e[t+o+3]=128|s>>0&63,o+=4}}return o},sizeUTF8:function(e){for(var t=e.length,r=0,i=0;i>>3}var d=a.lits,A=a.strt,g=a.prev,p=0,m=0,w=0,v=0,b=0,y=0;for(h>2&&(A[y=UZIP.F._hash(e,0)]=0),l=0;l14e3||m>26697)&&h-l>100&&(u>>16,B=65535&F;if(0!=F){B=65535&F;var U=s(_=F>>>16,a.of0);a.lhst[257+U]++;var C=s(B,a.df0);a.dhst[C]++,v+=a.exb[U]+a.dxb[C],d[p]=_<<23|l-u,d[p+1]=B<<16|U<<8|C,p+=2,u=l+_}else a.lhst[e[l]]++;m++}}for(w==l&&0!=e.length||(u>>3},UZIP.F._bestMatch=function(e,t,r,i,o,a){var s=32767&t,f=r[s],l=s-f+32768&32767;if(f==s||i!=UZIP.F._hash(e,t-l))return 0;for(var c=0,u=0,h=Math.min(32767,t);l<=h&&0!=--a&&f!=s;){if(0==c||e[t+c]==e[t+c-l]){var d=UZIP.F._howLong(e,t,l);if(d>c){if(u=l,(c=d)>=o)break;l+2A&&(A=m,f=p)}}}l+=(s=f)-(f=r[s])+32768&32767}return c<<16|u},UZIP.F._howLong=function(e,t,r){if(e[t]!=e[t-r]||e[t+1]!=e[t+1-r]||e[t+2]!=e[t+2-r])return 0;var i=t,o=Math.min(e.length,t+258);for(t+=3;t>>23,R=M+(8388607&T);M>16,H=O>>8&255,L=255&O;y(f,l=UZIP.F._writeLit(257+H,C,f,l),S-v.of0[H]),l+=v.exb[H],b(f,l=UZIP.F._writeLit(L,I,f,l),P-v.df0[L]),l+=v.dxb[L],M+=S}}l=UZIP.F._writeLit(256,C,f,l)}return l},UZIP.F._copyExact=function(e,t,r,i,o){var a=o>>>3;return i[a]=r,i[a+1]=r>>>8,i[a+2]=255-i[a],i[a+3]=255-i[a+1],a+=4,i.set(new Uint8Array(e.buffer,t,r),a),o+(r+4<<3)},UZIP.F.getTrees=function(){for(var e=UZIP.F.U,t=UZIP.F._hufTree(e.lhst,e.ltree,15),r=UZIP.F._hufTree(e.dhst,e.dtree,15),i=[],o=UZIP.F._lenCodes(e.ltree,i),a=[],s=UZIP.F._lenCodes(e.dtree,a),f=0;f4&&0==e.itree[1+(e.ordr[c-1]<<1)];)c--;return[t,r,l,o,s,c,i,a]},UZIP.F.getSecond=function(e){for(var t=[],r=0;r>1)+",");return t},UZIP.F.contSize=function(e,t){for(var r=0,i=0;i15&&(UZIP.F._putsE(r,i,s,f),i+=f)}return i},UZIP.F._lenCodes=function(e,t){for(var r=e.length;2!=r&&0==e[r-1];)r-=2;for(var i=0;i>>1,138))<11?t.push(17,c-3):t.push(18,c-11),i+=2*c-2}else if(o==f&&a==o&&s==o){for(l=i+5;l+2>>1,6);t.push(16,c-3),i+=2*c-2}else t.push(o,0)}return r>>>1},UZIP.F._hufTree=function(e,t,r){var i=[],o=e.length,a=t.length,s=0;for(s=0;sr&&(UZIP.F.restrictDepth(l,r,p),p=r),s=0;st;i++){var s=e[i].d;e[i].d=t,a+=o-(1<>>=r-t;a>0;){(s=e[i].d)=0;i--)e[i].d==t&&a<0&&(e[i].d--,a++);0!=a&&console.log("debt left")},UZIP.F._goodIndex=function(e,t){var r=0;return t[16|r]<=e&&(r|=16),t[8|r]<=e&&(r|=8),t[4|r]<=e&&(r|=4),t[2|r]<=e&&(r|=2),t[1|r]<=e&&(r|=1),r},UZIP.F._writeLit=function(e,t,r,i){return UZIP.F._putsF(r,i,t[e<<1]),i+t[1+(e<<1)]},UZIP.F.inflate=function(e,t){var r=Uint8Array;if(3==e[0]&&0==e[1])return t||new r(0);var i=UZIP.F,o=i._bitsF,a=i._bitsE,s=i._decodeTiny,f=i.makeCodes,l=i.codes2map,c=i._get17,u=i.U,h=null==t;h&&(t=new r(e.length>>>2<<3));for(var d,A,g=0,p=0,m=0,w=0,v=0,b=0,y=0,E=0,F=0;0==g;)if(g=o(e,F,1),p=o(e,F+1,2),F+=3,0!=p){if(h&&(t=UZIP.F._check(t,E+(1<<17))),1==p&&(d=u.flmap,A=u.fdmap,b=511,y=31),2==p){m=a(e,F,5)+257,w=a(e,F+5,5)+1,v=a(e,F+10,4)+4,F+=14;for(var _=0;_<38;_+=2)u.itree[_]=0,u.itree[_+1]=0;var B=1;for(_=0;_B&&(B=U)}F+=3*v,f(u.itree,B),l(u.itree,B,u.imap),d=u.lmap,A=u.dmap,F=s(u.imap,(1<>>4;if(M>>>8==0)t[E++]=M;else{if(256==M)break;var x=E+M-254;if(M>264){var T=u.ldef[M-257];x=E+(T>>>3)+a(e,F,7&T),F+=7&T}var S=A[c(e,F)&y];F+=15&S;var R=S>>>4,O=u.ddef[R],P=(O>>>4)+o(e,F,15&O);for(F+=15&O,h&&(t=UZIP.F._check(t,E+(1<<17)));E>>3),L=e[H-4]|e[H-3]<<8;h&&(t=UZIP.F._check(t,E+L)),t.set(new r(e.buffer,e.byteOffset+H,L),E),F=H+L<<3,E+=L}return t.length==E?t:t.slice(0,E)},UZIP.F._check=function(e,t){var r=e.length;if(t<=r)return e;var i=new Uint8Array(Math.max(r<<1,t));return i.set(e,0),i},UZIP.F._decodeTiny=function(e,t,r,i,o,a){for(var s=UZIP.F._bitsE,f=UZIP.F._get17,l=0;l>>4;if(u<=15)a[l]=u,l++;else{var h=0,d=0;16==u?(d=3+s(i,o,2),o+=2,h=a[l-1]):17==u?(d=3+s(i,o,3),o+=3):18==u&&(d=11+s(i,o,7),o+=7);for(var A=l+d;l>>1;ao&&(o=f),a++}for(;a>1,f=e[a+1],l=s<<4|f,c=t-f,u=e[a]<>>15-t]=l,u++}},UZIP.F.revCodes=function(e,t){for(var r=UZIP.F.U.rev15,i=15-t,o=0;o>>i}},UZIP.F._putsE=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},UZIP.F._putsF=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},UZIP.F._bitsE=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},UZIP.F._get25=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},UZIP.F.U=(t=Uint16Array,r=Uint32Array,{next_code:new t(16),bl_count:new t(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new t(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new r(32),flmap:new t(512),fltree:[],fdmap:new t(32),fdtree:[],lmap:new t(32768),ltree:[],ttree:[],dmap:new t(32768),dtree:[],imap:new t(512),itree:[],rev15:new t(32768),lhst:new r(286),dhst:new r(30),ihst:new r(19),lits:new r(15e3),strt:new t(65536),prev:new t(32768)}),function(){for(var e=UZIP.F.U,t=0;t<32768;t++){var r=t;r=(4278255360&(r=(4042322160&(r=(3435973836&(r=(2863311530&r)>>>1|(1431655765&r)<<1))>>>2|(858993459&r)<<2))>>>4|(252645135&r)<<4))>>>8|(16711935&r)<<8,e.rev15[t]=(r>>>16|r<<16)>>>17}function pushV(e,t,r){for(;0!=t--;)e.push(0,r)}for(t=0;t<32;t++)e.ldef[t]=e.of0[t]<<3|e.exb[t],e.ddef[t]=e.df0[t]<<4|e.dxb[t];pushV(e.fltree,144,8),pushV(e.fltree,112,9),pushV(e.fltree,24,7),pushV(e.fltree,8,8),UZIP.F.makeCodes(e.fltree,9),UZIP.F.codes2map(e.fltree,9,e.flmap),UZIP.F.revCodes(e.fltree,9),pushV(e.fdtree,32,5),UZIP.F.makeCodes(e.fdtree,5),UZIP.F.codes2map(e.fdtree,5,e.fdmap),UZIP.F.revCodes(e.fdtree,5),pushV(e.itree,19,0),pushV(e.ltree,286,0),pushV(e.dtree,30,0),pushV(e.ttree,320,0)}()}({get exports(){return e},set exports(t){e=t}});var UZIP=_mergeNamespaces({__proto__:null,default:e},[e]);const UPNG=function(){var e={nextZero(e,t){for(;0!=e[t];)t++;return t},readUshort:(e,t)=>e[t]<<8|e[t+1],writeUshort(e,t,r){e[t]=r>>8&255,e[t+1]=255&r},readUint:(e,t)=>16777216*e[t]+(e[t+1]<<16|e[t+2]<<8|e[t+3]),writeUint(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r},readASCII(e,t,r){let i="";for(let o=0;oe.length<2?`0${e}`:e,readUTF8(t,r,i){let o,a="";for(let o=0;o>3)]>>7-((7&A)<<0)&1);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>2)]>>6-((3&A)<<1)&3);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>1)]>>4-((1&A)<<2)&15);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>>3)]>>>7-(7&B)&1))==255*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(2==h)for(B=0;B>>2)]>>>6-((3&B)<<1)&3))==85*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(4==h)for(B=0;B>>1)]>>>4-((1&B)<<2)&15))==17*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(8==h)for(B=0;B>3,s=Math.ceil(r*o/8),f=new Uint8Array(i*s);let l=0;const c=[0,0,4,0,2,0,1],u=[0,4,0,2,0,1,0],h=[8,8,8,4,4,2,2],d=[8,8,4,4,2,2,1];let A=0;for(;A<7;){const p=h[A],m=d[A];let w=0,v=0,b=c[A];for(;b>3])>>7-(7&i)&1,f[_*s+(t>>3)]|=g<<7-((7&t)<<0);if(2==o)g=(g=e[i>>3])>>6-(7&i)&3,f[_*s+(t>>2)]|=g<<6-((3&t)<<1);if(4==o)g=(g=e[i>>3])>>4-(7&i)&15,f[_*s+(t>>1)]|=g<<4-((1&t)<<2);if(o>=8){const r=_*s+t*a;for(let t=0;t>3)+t]}i+=o,t+=m}F++,_+=p}w*v!=0&&(l+=v*(1+E)),A+=1}return f}(r,e)),r}function _inflate(e,r){return t(new Uint8Array(e.buffer,2,e.length-6),r)}var t=function(){const e={H:{}};return e.H.N=function(t,r){const i=Uint8Array;let o,a,s=0,f=0,l=0,c=0,u=0,h=0,d=0,A=0,g=0;if(3==t[0]&&0==t[1])return r||new i(0);const p=e.H,m=p.b,w=p.e,v=p.R,b=p.n,y=p.A,E=p.Z,F=p.m,_=null==r;for(_&&(r=new i(t.length>>>2<<5));0==s;)if(s=m(t,g,1),f=m(t,g+1,2),g+=3,0!=f){if(_&&(r=e.H.W(r,A+(1<<17))),1==f&&(o=F.J,a=F.h,h=511,d=31),2==f){l=w(t,g,5)+257,c=w(t,g+5,5)+1,u=w(t,g+10,4)+4,g+=14;let e=1;for(var B=0;B<38;B+=2)F.Q[B]=0,F.Q[B+1]=0;for(B=0;Be&&(e=r)}g+=3*u,b(F.Q,e),y(F.Q,e,F.u),o=F.w,a=F.d,g=v(F.u,(1<>>4;if(i>>>8==0)r[A++]=i;else{if(256==i)break;{let e=A+i-254;if(i>264){const r=F.q[i-257];e=A+(r>>>3)+w(t,g,7&r),g+=7&r}const o=a[E(t,g)&d];g+=15&o;const s=o>>>4,f=F.c[s],l=(f>>>4)+m(t,g,15&f);for(g+=15&f;A>>3),a=t[o-4]|t[o-3]<<8;_&&(r=e.H.W(r,A+a)),r.set(new i(t.buffer,t.byteOffset+o,a),A),g=o+a<<3,A+=a}return r.length==A?r:r.slice(0,A)},e.H.W=function(e,t){const r=e.length;if(t<=r)return e;const i=new Uint8Array(r<<1);return i.set(e,0),i},e.H.R=function(t,r,i,o,a,s){const f=e.H.e,l=e.H.Z;let c=0;for(;c>>4;if(i<=15)s[c]=i,c++;else{let e=0,t=0;16==i?(t=3+f(o,a,2),a+=2,e=s[c-1]):17==i?(t=3+f(o,a,3),a+=3):18==i&&(t=11+f(o,a,7),a+=7);const r=c+t;for(;c>>1;for(;ao&&(o=r),a++}for(;a>1,s=t[e+1],f=o<<4|s,l=r-s;let c=t[e]<>>15-r]=f,c++}}},e.H.l=function(t,r){const i=e.H.m.r,o=15-r;for(let e=0;e>>o}},e.H.M=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},e.H.I=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},e.H.e=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},e.H.i=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},e.H.m=function(){const e=Uint16Array,t=Uint32Array;return{K:new e(16),j:new e(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new e(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new t(32),J:new e(512),_:[],h:new e(32),$:[],w:new e(32768),C:[],v:[],d:new e(32768),D:[],u:new e(512),Q:[],r:new e(32768),s:new t(286),Y:new t(30),a:new t(19),t:new t(15e3),k:new e(65536),g:new e(32768)}}(),function(){const t=e.H.m;for(var r=0;r<32768;r++){let e=r;e=(2863311530&e)>>>1|(1431655765&e)<<1,e=(3435973836&e)>>>2|(858993459&e)<<2,e=(4042322160&e)>>>4|(252645135&e)<<4,e=(4278255360&e)>>>8|(16711935&e)<<8,t.r[r]=(e>>>16|e<<16)>>>17}function n(e,t,r){for(;0!=t--;)e.push(0,r)}for(r=0;r<32;r++)t.q[r]=t.S[r]<<3|t.T[r],t.c[r]=t.p[r]<<4|t.z[r];n(t._,144,8),n(t._,112,9),n(t._,24,7),n(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),n(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),n(t.Q,19,0),n(t.C,286,0),n(t.D,30,0),n(t.v,320,0)}(),e.H.N}();function _getBPP(e){return[1,null,3,1,2,null,4][e.ctype]*e.depth}function _filterZero(e,t,r,i,o){let a=_getBPP(t);const s=Math.ceil(i*a/8);let f,l;a=Math.ceil(a/8);let c=e[r],u=0;if(c>1&&(e[r]=[0,0,1][c-2]),3==c)for(u=a;u>>1)&255;for(let t=0;t>>1);for(;u>>1)}else{for(;u=0&&f>=0?(h=r*t+a<<2,d=(f+r)*o+s+a<<2):(h=(-f+r)*t-s+a<<2,d=r*o+a<<2),0==l)i[d]=e[h],i[d+1]=e[h+1],i[d+2]=e[h+2],i[d+3]=e[h+3];else if(1==l){var A=e[h+3]*(1/255),g=e[h]*A,p=e[h+1]*A,m=e[h+2]*A,w=i[d+3]*(1/255),v=i[d]*w,b=i[d+1]*w,y=i[d+2]*w;const t=1-A,r=A+w*t,o=0==r?0:1/r;i[d+3]=255*r,i[d+0]=(g+v*t)*o,i[d+1]=(p+b*t)*o,i[d+2]=(m+y*t)*o}else if(2==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];A==w&&g==v&&p==b&&m==y?(i[d]=0,i[d+1]=0,i[d+2]=0,i[d+3]=0):(i[d]=g,i[d+1]=p,i[d+2]=m,i[d+3]=A)}else if(3==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];if(A==w&&g==v&&p==b&&m==y)continue;if(A<220&&w>20)return!1}return!0}return{decode:function decode(r){const i=new Uint8Array(r);let o=8;const a=e,s=a.readUshort,f=a.readUint,l={tabs:{},frames:[]},c=new Uint8Array(i.length);let u,h=0,d=0;const A=[137,80,78,71,13,10,26,10];for(var g=0;g<8;g++)if(i[g]!=A[g])throw"The input is not a PNG file!";for(;o>>1:r>>>=1;e[t]=r}return e}(),update(e,t,r,o){for(let a=0;a>>8;return e},crc:(e,t,r)=>4294967295^i.update(4294967295,e,t,r)};function addErr(e,t,r,i){t[r]+=e[0]*i>>4,t[r+1]+=e[1]*i>>4,t[r+2]+=e[2]*i>>4,t[r+3]+=e[3]*i>>4}function N(e){return Math.max(0,Math.min(255,e))}function D(e,t){const r=e[0]-t[0],i=e[1]-t[1],o=e[2]-t[2],a=e[3]-t[3];return r*r+i*i+o*o+a*a}function dither(e,t,r,i,o,a,s){null==s&&(s=1);const f=i.length,l=[];for(var c=0;c>>0&255,e>>>8&255,e>>>16&255,e>>>24&255])}for(c=0;c>2]=u,A[c>>2]=i[u]}}function _main(e,r,o,a,s){null==s&&(s={});const{crc:f}=i,l=t.writeUint,c=t.writeUshort,u=t.writeASCII;let h=8;const d=e.frames.length>1;let A,g=!1,p=33+(d?20:0);if(null!=s.sRGB&&(p+=13),null!=s.pHYs&&(p+=21),null!=s.iCCP&&(A=pako.deflate(s.iCCP),p+=21+A.length+4),3==e.ctype){for(var m=e.plte.length,w=0;w>>24!=255&&(g=!0);p+=8+3*m+4+(g?8+1*m+4:0)}for(var v=0;v>>8&255,a=r>>>16&255;b[h+t+0]=i,b[h+t+1]=o,b[h+t+2]=a}if(h+=3*m,l(b,h,f(b,h-3*m-4,3*m+4)),h+=4,g){l(b,h,m),h+=4,u(b,h,"tRNS"),h+=4;for(w=0;w>>24&255;h+=m,l(b,h,f(b,h-m-4,m+4)),h+=4}}let E=0;for(v=0;vc&&(c=t),eh&&(h=e))}-1==c&&(s=f=c=h=0),a&&(1==(1&s)&&s--,1==(1&f)&&f--);const v=(c-s+1)*(h-f+1);v>2,e>>2);F.push(_);const t=new Uint8Array(r.abuf,i,e);h&&dither(B.img,B.rect.width,B.rect.height,E,t,_),B.img.set(t),i+=e}}else for(p=0;pU&&t==e[w-U])_[w]=_[w-U];else{let e=y[t];if(null==e&&(y[t]=e=E.length,E.push(t),E.length>=300))break;_[w]=e}}}const C=E.length;C<=256&&0==u&&(A=C<=2?1:C<=4?2:C<=16?4:8,A=Math.max(A,c));for(p=0;p>1)]|=o[e+Q]<<4-4*(1&Q);else if(2==A)for(Q=0;Q>2)]|=o[e+Q]<<6-2*(3&Q);else if(1==A)for(Q=0;Q>3)]|=o[e+Q]<<7-1*(7&Q)}t=I,d=3,i=1}else if(0==v&&1==b.length){I=new Uint8Array(U*e*3);const o=U*e;for(w=0;ww&&(w=i),fv&&(v=f))}-1==w&&(p=m=w=v=0),f&&(1==(1&p)&&p--,1==(1&m)&&m--),s={x:p,y:m,width:w-p+1,height:v-m+1};const b=o[a];b.rect=s,b.blend=1,b.img=new Uint8Array(s.width*s.height*4),0==o[a-1].dispose?(e(u,r,i,b.img,s.width,s.height,-s.x,-s.y,0),_prepareDiff(A,r,i,b.img,s)):e(A,r,i,b.img,s.width,s.height,-s.x,-s.y,0)}function _prepareDiff(t,r,i,o,a){e(t,r,i,o,a.width,a.height,-a.x,-a.y,2)}function _filterZero(e,t,r,i,o,a,s){const f=[];let l,c=[0,1,2,3,4];-1!=a?c=[a]:(t*i>5e5||1==r)&&(c=[0]),s&&(l={level:0});const u=UZIP;for(var h=0;h>1)+256&255;if(4==s)for(c=a;c>1)&255;for(c=a;c>1)&255}if(4==s){for(c=0;c>2);let u;if(r.length<2e7)for(var h=0;h>2]=u.ind,o[h>>2]=u.est.rgba}else for(h=0;h>2]=u.ind,o[h>>2]=u.est.rgba}return{abuf:i.buffer,inds:c,plte:f}}function getKDtree(e,t,r){null==r&&(r=1e-4);const i=new Uint32Array(e.buffer),o={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};o.bst=stats(e,o.i0,o.i1),o.est=estats(o.bst);const a=[o];for(;a.lengtht&&(t=a[s].est.L,o=s);if(t=l||f.i1<=l){f.est.L=0;continue}const c={i0:f.i0,i1:l,bst:null,est:null,tdst:0,left:null,right:null};c.bst=stats(e,c.i0,c.i1),c.est=estats(c.bst);const u={i0:l,i1:f.i1,bst:null,est:null,tdst:0,left:null,right:null};u.bst={R:[],m:[],N:f.bst.N-c.bst.N};for(s=0;s<16;s++)u.bst.R[s]=f.bst.R[s]-c.bst.R[s];for(s=0;s<4;s++)u.bst.m[s]=f.bst.m[s]-c.bst.m[s];u.est=estats(u.bst),f.left=c,f.right=u,a[o]=c,a.push(u)}a.sort(((e,t)=>t.bst.N-e.bst.N));for(s=0;s0&&(s=e.right,f=e.left);const l=getNearest(s,t,r,i,o);if(l.tdst<=a*a)return l;const c=getNearest(f,t,r,i,o);return c.tdsta;)i-=4;if(r>=i)break;const s=t[r>>2];t[r>>2]=t[i>>2],t[i>>2]=s,r+=4,i-=4}for(;vecDot(e,r,o)>a;)r-=4;return r+4}function vecDot(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]}function stats(e,t,r){const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o=[0,0,0,0],a=r-t>>2;for(let a=t;a>>0}}var o={multVec:(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]],dot:(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],sml:(e,t)=>[e*t[0],e*t[1],e*t[2],e*t[3]]};UPNG.encode=function encode(e,t,r,i,o,a,s){null==i&&(i=0),null==s&&(s=!1);const f=compress(e,t,r,i,[!1,!1,!1,0,s,!1]);return compressPNG(f,-1),_main(f,t,r,o,a)},UPNG.encodeLL=function encodeLL(e,t,r,i,o,a,s,f){const l={ctype:0+(1==i?0:2)+(0==o?0:4),depth:a,frames:[]},c=(i+o)*a,u=c*t;for(let i=0;i>>0),set16(1),set16(32),set32(3),set32(c),set32(2835),set32(2835),seek(8),set32(16711680),set32(65280),set32(255),set32(4278190080),set32(1466527264),function convert(){for(;b0;){for(w=122+b*l,g=0;g>>24,d.setUint32(w+g,p<<8|m),g+=4;b++}E{t(new Blob([e],{type:"image/bmp"}))}))},_dly:9};var r={CHROME:"CHROME",FIREFOX:"FIREFOX",DESKTOP_SAFARI:"DESKTOP_SAFARI",IE:"IE",IOS:"IOS",ETC:"ETC"},i={[r.CHROME]:16384,[r.FIREFOX]:11180,[r.DESKTOP_SAFARI]:16384,[r.IE]:8192,[r.IOS]:4096,[r.ETC]:8192};const o="undefined"!=typeof window,a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,s=o&&window.cordova&&window.cordova.require&&window.cordova.require("cordova/modulemapper"),CustomFile=(o||a)&&(s&&s.getOriginalSymbol(window,"File")||"undefined"!=typeof File&&File),CustomFileReader=(o||a)&&(s&&s.getOriginalSymbol(window,"FileReader")||"undefined"!=typeof FileReader&&FileReader);function getFilefromDataUrl(e,t,r=Date.now()){return new Promise((i=>{const o=e.split(","),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let f=s.length;const l=new Uint8Array(f);for(;f--;)l[f]=s.charCodeAt(f);const c=new Blob([l],{type:a});c.name=t,c.lastModified=r,i(c)}))}function getDataUrlFromFile(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=()=>t(i.result),i.onerror=e=>r(e),i.readAsDataURL(e)}))}function loadImage(e){return new Promise(((t,r)=>{const i=new Image;i.onload=()=>t(i),i.onerror=e=>r(e),i.src=e}))}function getBrowserName(){if(void 0!==getBrowserName.cachedResult)return getBrowserName.cachedResult;let e=r.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=r.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=r.IOS:/Safari/i.test(t)?e=r.DESKTOP_SAFARI:/Firefox/i.test(t)?e=r.FIREFOX:(/MSIE/i.test(t)||!0==!!document.documentMode)&&(e=r.IE),getBrowserName.cachedResult=e,getBrowserName.cachedResult}function approximateBelowMaximumCanvasSizeOfBrowser(e,t){const r=getBrowserName(),o=i[r];let a=e,s=t,f=a*s;const l=a>s?s/a:a/s;for(;f>o*o;){const e=(o+a)/2,t=(o+s)/2;et.toBlob(e,r))).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_5.call(this)}catch(e){return f(e)}}.bind(this),f);{if("function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return e.convertToBlob({type:r,quality:a}).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f);{let d;return d=e.toDataURL(r,a),getFilefromDataUrl(d,i,o).then(function(e){try{return l=e,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f)}function $If_6(){return $If_5.call(this)}}function $If_5(){return $If_4.call(this)}}function $If_4(){return s(l)}}))}function cleanupCanvasMemory(e){e.width=0,e.height=0}function isAutoOrientationInBrowser(){return new Promise((function(e,t){let r,i,o,a,s;return void 0!==isAutoOrientationInBrowser.cachedResult?e(isAutoOrientationInBrowser.cachedResult):(r="data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==",getFilefromDataUrl("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==","test.jpg",Date.now()).then((function(r){try{return i=r,drawFileInCanvas(i).then((function(r){try{return o=r[1],canvasToFile(o,i.type,i.name,i.lastModified).then((function(r){try{return a=r,cleanupCanvasMemory(o),drawFileInCanvas(a).then((function(r){try{return s=r[0],isAutoOrientationInBrowser.cachedResult=1===s.width&&2===s.height,e(isAutoOrientationInBrowser.cachedResult)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t))}))}function getExifOrientation(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=e=>{const r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return t(-2);const i=r.byteLength;let o=2;for(;or(e),i.readAsArrayBuffer(e)}))}function handleMaxWidthOrHeight(e,t){const{width:r}=e,{height:i}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||i>o)&&([s,a]=getNewCanvasAndCtx(r,i),r>i?(s.width=o,s.height=i/r*o):(s.width=r/i*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),cleanupCanvasMemory(e)),s}function followExifOrientation(e,t){const{width:r}=e,{height:i}=e,[o,a]=getNewCanvasAndCtx(r,i);switch(t>4&&t<9?(o.width=i,o.height=r):(o.width=r,o.height=i),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,i);break;case 4:a.transform(1,0,0,-1,0,i);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,i,0);break;case 7:a.transform(0,-1,-1,0,i,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,i),cleanupCanvasMemory(e),o}function compress(e,t,r=0){return new Promise((function(i,o){let a,s,f,l,c,u,h,d,A,g,p,m,w,v,b,y,E,F,_,B;function incProgress(e=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=e,t.onProgress(Math.min(a,100))}function setProgress(e){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(e,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,f=1024*t.maxSizeMB*1024,incProgress(),drawFileInCanvas(e,t).then(function(r){try{return[,l]=r,incProgress(),c=handleMaxWidthOrHeight(l,t),incProgress(),new Promise((function(r,i){var o;if(!(o=t.exifOrientation))return getExifOrientation(e).then(function(e){try{return o=e,$If_2.call(this)}catch(e){return i(e)}}.bind(this),i);function $If_2(){return r(o)}return $If_2.call(this)})).then(function(r){try{return u=r,incProgress(),isAutoOrientationInBrowser().then(function(r){try{return h=r?c:followExifOrientation(c,u),incProgress(),d=t.initialQuality||1,A=t.fileType||e.type,canvasToFile(h,A,e.name,e.lastModified,d).then(function(r){try{{if(g=r,incProgress(),p=g.size>f,m=g.size>e.size,!p&&!m)return setProgress(100),i(g);var a;function $Loop_3(){if(s--&&(b>f||b>w)){let t,r;return t=B?.95*_.width:_.width,r=B?.95*_.height:_.height,[E,F]=getNewCanvasAndCtx(t,r),F.drawImage(_,0,0,t,r),d*="image/png"===A?.85:.95,canvasToFile(E,A,e.name,e.lastModified,d).then((function(e){try{return y=e,cleanupCanvasMemory(_),_=E,b=y.size,setProgress(Math.min(99,Math.floor((v-b)/(v-f)*100))),$Loop_3}catch(e){return o(e)}}),o)}return[1]}return w=e.size,v=g.size,b=v,_=h,B=!t.alwaysKeepResolution&&p,(a=function(e){for(;e;){if(e.then)return void e.then(a,o);try{if(e.pop){if(e.length)return e.pop()?$Loop_3_exit.call(this):e;e=$Loop_3}else e=e.call(this)}catch(e){return o(e)}}}.bind(this))($Loop_3);function $Loop_3_exit(){return cleanupCanvasMemory(_),cleanupCanvasMemory(E),cleanupCanvasMemory(c),cleanupCanvasMemory(h),cleanupCanvasMemory(l),setProgress(100),i(y)}}}catch(u){return o(u)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}))}const f="\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n options.onProgress = (progress) => self.postMessage({ progress, id })\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n self.importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message + '\\n' + e.stack, id })\n }\n})\n";let l;function compressOnWebWorker(e,t){return new Promise(((r,i)=>{l||(l=function createWorkerScriptURL(e){const t=[];return"function"==typeof e?t.push(`(${e})()`):t.push(e),URL.createObjectURL(new Blob(t))}(f));const o=new Worker(l);o.addEventListener("message",(function handler(e){if(t.signal&&t.signal.aborted)o.terminate();else if(void 0===e.data.progress){if(e.data.error)return i(new Error(e.data.error)),void o.terminate();r(e.data.file),o.terminate()}else t.onProgress(e.data.progress)})),o.addEventListener("error",i),t.signal&&t.signal.addEventListener("abort",(()=>{i(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function imageCompression(e,t){return new Promise((function(r,i){let o,a,s,f,l,c;if(o={...t},s=0,({onProgress:f}=o),o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,l="boolean"!=typeof o.useWebWorker||o.useWebWorker,delete o.useWebWorker,o.onProgress=e=>{s=e,"function"==typeof f&&f(s)},!(1||e instanceof Blob||e instanceof CustomFile))return i(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return i(new Error("The file given is not an image"));if(c="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!l||"function"!=typeof Worker||c)return compress(e,o).then(function(e){try{return a=e,$If_4.call(this)}catch(e){return i(e)}}.bind(this),i);var u=function(){try{return $If_4.call(this)}catch(e){return i(e)}}.bind(this),$Try_1_Catch=function(t){try{return compress(e,o).then((function(e){try{return a=e,u()}catch(e){return i(e)}}),i)}catch(e){return i(e)}};try{return o.libURL=o.libURL||"https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js",compressOnWebWorker(e,o).then((function(e){try{return a=e,u()}catch(e){return $Try_1_Catch()}}),$Try_1_Catch)}catch(e){$Try_1_Catch()}function $If_4(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}try{o.preserveExif&&"image/jpeg"===e.type&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=copyExifWithoutOrientation(e,a))}catch(e){}return r(a)}}))}return imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression.cleanupCanvasMemory=cleanupCanvasMemory,imageCompression.isAutoOrientationInBrowser=isAutoOrientationInBrowser,imageCompression.approximateBelowMaximumCanvasSizeOfBrowser=approximateBelowMaximumCanvasSizeOfBrowser,imageCompression.copyExifWithoutOrientation=copyExifWithoutOrientation,imageCompression.getBrowserName=getBrowserName,imageCompression.version="2.0.2",imageCompression})); + return { + // { + // maxSizeMB: number, // (default: Number.POSITIVE_INFINITY) + // maxWidthOrHeight: number, // compressedFile will scale down by ratio to a point that width or height is smaller than maxWidthOrHeight (default: undefined) + // // but, automatically reduce the size to smaller than the maximum Canvas size supported by each browser. + // // Please check the Caveat part for details. + // onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100) + // useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true) + // libURL: string, // optional, the libURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js) + // preserveExif: boolean, // optional, use preserve Exif metadata for JPEG image e.g., Camera model, Focal length, etc (default: false) + // + // signal: AbortSignal, // optional, to abort / cancel the compression + // + // // following options are for advanced users + // maxIteration: number, // optional, max number of iteration to compress the image (default: 10) + // exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024 + // fileType: string, // optional, fileType override e.g., 'image/jpeg', 'image/png' (default: file.type) + // initialQuality: number, // optional, initial quality value between 0 and 1 (default: 1) + // alwaysKeepResolution: boolean // optional, only reduce quality, always keep width and height (default: false) + // } + compress:function(file,option){ + return imageCompression(file,option); + } + }; +})(); + + +// core/dialog.js +UE.dialog = (function () { + return { + loadingPlaceholder: function (me) { + var loadingId = "loading_" + (+new Date()).toString(36); + me.focus(); + me.execCommand( + "inserthtml", + '' + ); + return loadingId; + }, + removeLoadingPlaceholder: function (me, loadingId) { + var loader = me.document.getElementById(loadingId); + if (loader) { + domUtils.remove(loader, false); + } + }, + tipError: function (me, title) { + me.fireEvent("showmessage", { + content: title, + type: "error", + timeout: 4000 + }); + } + } +})(); + + +// core/filterword.js +/** + * UE过滤word的静态方法 + * @file + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ + +/** + * 根据传入html字符串过滤word + * @module UE + * @since 1.2.6.1 + * @method filterWord + * @param { String } html html字符串 + * @return { String } 已过滤后的结果字符串 + * @example + * ```javascript + * UE.filterWord(html); + * ``` + */ +var filterWord = (UE.filterWord = (function() { + //是否是word过来的内容 + function isWordDocument(str) { + return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/gi.test( + str + ); + } + //去掉小数 + function transUnit(v) { + v = v.replace(/[\d.]+\w+/g, function(m) { + return utils.transUnitToPx(m); + }); + return v; + } + + function filterPasteWord(str) { + return ( + str + .replace(/[\t\r\n]+/g, " ") + .replace(//gi, "") + //转换图片 + .replace(/]*>[\s\S]*?.<\/v:shape>/gi, function(str) { + //opera能自己解析出image所这里直接返回空 + if (browser.opera) { + return ""; + } + try { + //有可能是bitmap占为图,无用,直接过滤掉,主要体现在粘贴excel表格中 + if (/Bitmap/i.test(str)) { + return ""; + } + var width = str.match(/width:([ \d.]*p[tx])/i)[1], + height = str.match(/height:([ \d.]*p[tx])/i)[1], + src = str.match(/src=\s*"([^"]*)"/i)[1]; + return ( + '' + ); + } catch (e) { + return ""; + } + }) + //针对wps添加的多余标签处理 + .replace(/<\/?div[^>]*>/g, "") + //去掉多余的属性 + .replace(/v:\w+=(["']?)[^'"]+\1/g, "") + .replace( + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, + "" + ) + .replace( + /

    ]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, + "

    $1

    " + ) + //去掉多余的属性 + .replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, function( + str, + name, + marks, + val + ) { + //保留list的标示 + return name == "class" && val == "MsoListParagraph" ? str : ""; + }) + //清除多余的font/span不能匹配 有可能是空格 + .replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function(a, b, c) { + return c.replace(/[\t\r\n ]+/g, " "); + }) + //处理style的问题 + .replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function( + str, + tag, + tmp, + style + ) { + var n = [], + s = style + .replace(/^\s+|\s+$/, "") + .replace(/'/g, "'") + .replace(/"/gi, "'") + .replace(/[\d.]+(cm|pt)/g, function(str) { + return utils.transUnitToPx(str); + }) + .split(/;\s*/g); + + for (var i = 0, v; (v = s[i]); i++) { + var name, + value, + parts = v.split(":"); + + if (parts.length == 2) { + name = parts[0].toLowerCase(); + value = parts[1].toLowerCase(); + if ( + (/^(background)\w*/.test(name) && + value.replace(/(initial|\s)/g, "").length == 0) || + (/^(margin)\w*/.test(name) && /^0\w+$/.test(value)) + ) { + continue; + } + + switch (name) { + case "mso-padding-alt": + case "mso-padding-top-alt": + case "mso-padding-right-alt": + case "mso-padding-bottom-alt": + case "mso-padding-left-alt": + case "mso-margin-alt": + case "mso-margin-top-alt": + case "mso-margin-right-alt": + case "mso-margin-bottom-alt": + case "mso-margin-left-alt": + //ie下会出现挤到一起的情况 + //case "mso-table-layout-alt": + case "mso-height": + case "mso-width": + case "mso-vertical-align-alt": + //trace:1819 ff下会解析出padding在table上 + if (!/]/.test(html)) { + return UE.htmlparser(html).children[0]; + } else { + return new uNode({ + type: "element", + children: [], + tagName: html + }); + } + }; + uNode.createText = function(data, noTrans) { + return new UE.uNode({ + type: "text", + data: noTrans ? data : utils.unhtml(data || "") + }); + }; + function nodeToHtml(node, arr, formatter, current) { + switch (node.type) { + case "root": + for (var i = 0, ci; (ci = node.children[i++]); ) { + //插入新行 + if ( + formatter && + ci.type == "element" && + !dtd.$inlineWithA[ci.tagName] && + i > 1 + ) { + insertLine(arr, current, true); + insertIndent(arr, current); + } + nodeToHtml(ci, arr, formatter, current); + } + break; + case "text": + isText(node, arr); + break; + case "element": + isElement(node, arr, formatter, current); + break; + case "comment": + isComment(node, arr, formatter); + } + return arr; + } + + function isText(node, arr) { + if (node.parentNode.tagName == "pre") { + //源码模式下输入html标签,不能做转换处理,直接输出 + arr.push(node.data); + } else { + arr.push( + notTransTagName[node.parentNode.tagName] + ? utils.html(node.data) + : node.data.replace(/[ ]{2}/g, "  ") + ); + } + } + + function isElement(node, arr, formatter, current) { + var attrhtml = ""; + if (node.attrs) { + attrhtml = []; + var attrs = node.attrs; + for (var a in attrs) { + //这里就针对 + //

    '

    + //这里边的\"做转换,要不用innerHTML直接被截断了,属性src + //有可能做的不够 + attrhtml.push( + a + + (attrs[a] !== undefined + ? '="' + + (notTransAttrs[a] + ? utils.html(attrs[a]).replace(/["]/g, function(a) { + return """; + }) + : utils.unhtml(attrs[a])) + + '"' + : "") + ); + } + attrhtml = attrhtml.join(" "); + } + arr.push( + "<" + + node.tagName + + (attrhtml ? " " + attrhtml : "") + + (dtd.$empty[node.tagName] ? "/" : "") + + ">" + ); + //插入新行 + if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") { + if (node.children && node.children.length) { + current = insertLine(arr, current, true); + insertIndent(arr, current); + } + } + if (node.children && node.children.length) { + for (var i = 0, ci; (ci = node.children[i++]); ) { + if ( + formatter && + ci.type == "element" && + !dtd.$inlineWithA[ci.tagName] && + i > 1 + ) { + insertLine(arr, current); + insertIndent(arr, current); + } + nodeToHtml(ci, arr, formatter, current); + } + } + if (!dtd.$empty[node.tagName]) { + if ( + formatter && + !dtd.$inlineWithA[node.tagName] && + node.tagName != "pre" + ) { + if (node.children && node.children.length) { + current = insertLine(arr, current); + insertIndent(arr, current); + } + } + arr.push(""); + } + } + + function isComment(node, arr) { + arr.push(""); + } + + function getNodeById(root, id) { + var node; + if (root.type == "element" && root.getAttr("id") == id) { + return root; + } + if (root.children && root.children.length) { + for (var i = 0, ci; (ci = root.children[i++]); ) { + if ((node = getNodeById(ci, id))) { + return node; + } + } + } + } + + function getNodesByTagName(node, tagName, arr) { + if (node.type == "element" && node.tagName == tagName) { + arr.push(node); + } + if (node.children && node.children.length) { + for (var i = 0, ci; (ci = node.children[i++]); ) { + getNodesByTagName(ci, tagName, arr); + } + } + } + function nodeTraversal(root, fn) { + if (root.children && root.children.length) { + for (var i = 0, ci; (ci = root.children[i]); ) { + nodeTraversal(ci, fn); + //ci被替换的情况,这里就不再走 fn了 + if (ci.parentNode) { + if (ci.children && ci.children.length) { + fn(ci); + } + if (ci.parentNode) i++; + } + } + } else { + fn(root); + } + } + uNode.prototype = { + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml(); + * ``` + */ + + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @param { Boolean } formatter 是否格式化返回值 + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml( true ); + * ``` + */ + toHtml: function(formatter) { + var arr = []; + nodeToHtml(this, arr, formatter, 0); + return arr.join(""); + }, + + /** + * 获取节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的html内容 + * @example + * ```javascript + * var htmlstr = node.innerHTML(); + * ``` + */ + + /** + * 设置节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } htmlstr 传入要设置的html内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerHTML('text'); + * ``` + */ + innerHTML: function(htmlstr) { + if (this.type != "element" || dtd.$empty[this.tagName]) { + return this; + } + if (utils.isString(htmlstr)) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i++]); ) { + ci.parentNode = null; + } + } + this.children = []; + var tmpRoot = UE.htmlparser(htmlstr); + for (var i = 0, ci; (ci = tmpRoot.children[i++]); ) { + this.children.push(ci); + ci.parentNode = this; + } + return this; + } else { + var tmpRoot = new UE.uNode({ + type: "root", + children: this.children + }); + return tmpRoot.toHtml(); + } + }, + + /** + * 获取节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的存文本内容 + * @example + * ```javascript + * var textStr = node.innerText(); + * ``` + */ + + /** + * 设置节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } textStr 传入要设置的文本内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerText('text'); + * ``` + */ + innerText: function(textStr, noTrans) { + if (this.type != "element" || dtd.$empty[this.tagName]) { + return this; + } + if (textStr) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i++]); ) { + ci.parentNode = null; + } + } + this.children = []; + this.appendChild(uNode.createText(textStr, noTrans)); + return this; + } else { + return this.toHtml().replace(/<[^>]+>/g, ""); + } + }, + + /** + * 获取当前对象的data属性 + * @method getData + * @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性 + * @example + * ```javascript + * node.getData(); + * ``` + */ + getData: function() { + if (this.type == "element") return ""; + return this.data; + }, + + /** + * 获取当前节点下的第一个子节点 + * @method firstChild + * @return { UE.uNode } 返回第一个子节点 + * @example + * ```javascript + * node.firstChild(); //返回第一个子节点 + * ``` + */ + firstChild: function() { + // if (this.type != 'element' || dtd.$empty[this.tagName]) { + // return this; + // } + return this.children ? this.children[0] : null; + }, + + /** + * 获取当前节点下的最后一个子节点 + * @method lastChild + * @return { UE.uNode } 返回最后一个子节点 + * @example + * ```javascript + * node.lastChild(); //返回最后一个子节点 + * ``` + */ + lastChild: function() { + // if (this.type != 'element' || dtd.$empty[this.tagName] ) { + // return this; + // } + return this.children ? this.children[this.children.length - 1] : null; + }, + + /** + * 获取和当前节点有相同父亲节点的前一个节点 + * @method previousSibling + * @return { UE.uNode } 返回前一个节点 + * @example + * ```javascript + * node.children[2].previousSibling(); //返回子节点node.children[1] + * ``` + */ + previousSibling: function() { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i]); i++) { + if (ci === this) { + return i == 0 ? null : parent.children[i - 1]; + } + } + }, + + /** + * 获取和当前节点有相同父亲节点的后一个节点 + * @method nextSibling + * @return { UE.uNode } 返回后一个节点,找不到返回null + * @example + * ```javascript + * node.children[2].nextSibling(); //如果有,返回子节点node.children[3] + * ``` + */ + nextSibling: function() { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i++]); ) { + if (ci === this) { + return parent.children[i]; + } + } + }, + + /** + * 用新的节点替换当前节点 + * @method replaceChild + * @param { UE.uNode } target 要替换成该节点参数 + * @param { UE.uNode } source 要被替换掉的节点 + * @return { UE.uNode } 返回替换之后的节点对象 + * @example + * ```javascript + * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点 + * ``` + */ + replaceChild: function(target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i, 1, target); + source.parentNode = null; + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 在节点的子节点列表最后位置插入一个节点 + * @method appendChild + * @param { UE.uNode } node 要插入的节点 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.appendChild( newNode ); //在node内插入子节点newNode + * ``` + */ + appendChild: function(node) { + if ( + this.type == "root" || + (this.type == "element" && !dtd.$empty[this.tagName]) + ) { + if (!this.children) { + this.children = []; + } + if (node.parentNode) { + node.parentNode.removeChild(node); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === node) { + this.children.splice(i, 1); + break; + } + } + this.children.push(node); + node.parentNode = this; + return node; + } + }, + + /** + * 在传入节点的前面插入一个节点 + * @method insertBefore + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点前面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertBefore: function(target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i, 0, target); + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 在传入节点的后面插入一个节点 + * @method insertAfter + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点后面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertAfter: function(target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i + 1, 0, target); + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 从当前节点的子节点列表中,移除节点 + * @method removeChild + * @param { UE.uNode } node 要移除的节点引用 + * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置 + * @return { * } 返回刚移除的子节点 + * @example + * ```javascript + * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置 + * ``` + */ + removeChild: function(node, keepChildren) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === node) { + this.children.splice(i, 1); + ci.parentNode = null; + if (keepChildren && ci.children && ci.children.length) { + for (var j = 0, cj; (cj = ci.children[j]); j++) { + this.children.splice(i + j, 0, cj); + cj.parentNode = this; + } + } + return ci; + } + } + } + }, + + /** + * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值 + * @method getAttr + * @param { String } attrName 要获取的属性名称 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.getAttr('title'); + * ``` + */ + getAttr: function(attrName) { + return this.attrs && this.attrs[attrName.toLowerCase()]; + }, + + /** + * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值 + * @method setAttr + * @param { String } attrName 要设置的属性名称 + * @param { * } attrVal 要设置的属性值,类型视设置的属性而定 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.setAttr('title','标题'); + * ``` + */ + setAttr: function(attrName, attrVal) { + if (!attrName) { + delete this.attrs; + return; + } + if (!this.attrs) { + this.attrs = {}; + } + if (utils.isObject(attrName)) { + for (var a in attrName) { + if (!attrName[a]) { + delete this.attrs[a]; + } else { + this.attrs[a.toLowerCase()] = attrName[a]; + } + } + } else { + if (!attrVal) { + delete this.attrs[attrName]; + } else { + this.attrs[attrName.toLowerCase()] = attrVal; + } + } + }, + + /** + * 获取当前节点在父节点下的位置索引 + * @method getIndex + * @return { Number } 返回索引数值,如果没有父节点,返回-1 + * @example + * ```javascript + * node.getIndex(); + * ``` + */ + getIndex: function() { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i]); i++) { + if (ci === this) { + return i; + } + } + return -1; + }, + + /** + * 在当前节点下,根据id查找节点 + * @method getNodeById + * @param { String } id 要查找的id + * @return { UE.uNode } 返回找到的节点 + * @example + * ```javascript + * node.getNodeById('textId'); + * ``` + */ + getNodeById: function(id) { + var node; + if (this.children && this.children.length) { + for (var i = 0, ci; (ci = this.children[i++]); ) { + if ((node = getNodeById(ci, id))) { + return node; + } + } + } + }, + + /** + * 在当前节点下,根据元素名称查找节点列表 + * @method getNodesByTagName + * @param { String } tagNames 要查找的元素名称 + * @return { Array } 返回找到的节点列表 + * @example + * ```javascript + * node.getNodesByTagName('span'); + * ``` + */ + getNodesByTagName: function(tagNames) { + tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" "); + var arr = [], + me = this; + utils.each(tagNames, function(tagName) { + if (me.children && me.children.length) { + for (var i = 0, ci; (ci = me.children[i++]); ) { + getNodesByTagName(ci, tagName, arr); + } + } + }); + return arr; + }, + + /** + * 根据样式名称,获取节点的样式值 + * @method getStyle + * @param { String } name 要获取的样式名称 + * @return { String } 返回样式值 + * @example + * ```javascript + * node.getStyle('font-size'); + * ``` + */ + getStyle: function(name) { + var cssStyle = this.getAttr("style"); + if (!cssStyle) { + return ""; + } + var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+)", "i"); + var match = cssStyle.match(reg); + if (match && match[0]) { + return match[2]; + } + return ""; + }, + + /** + * 给节点设置样式 + * @method setStyle + * @param { String } name 要设置的的样式名称 + * @param { String } val 要设置的的样值 + * @example + * ```javascript + * node.setStyle('font-size', '12px'); + * ``` + */ + setStyle: function(name, val) { + function exec(name, val) { + var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+;?)", "gi"); + cssStyle = cssStyle.replace(reg, "$1"); + if (val) { + cssStyle = name + ":" + utils.unhtml(val) + ";" + cssStyle; + } + } + + var cssStyle = this.getAttr("style"); + if (!cssStyle) { + cssStyle = ""; + } + if (utils.isObject(name)) { + for (var a in name) { + exec(a, name[a]); + } + } else { + exec(name, val); + } + this.setAttr("style", utils.trim(cssStyle)); + }, + + /** + * 传入一个函数,递归遍历当前节点下的所有节点 + * @method traversal + * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数 + * @example + * ```javascript + * traversal(node, function(){ + * console.log(node.type); + * }); + * ``` + */ + traversal: function(fn) { + if (this.children && this.children.length) { + nodeTraversal(this, fn); + } + return this; + } + }; +})(); + + +// core/htmlparser.js +/** + * html字符串转换成uNode节点 + * @file + * @module UE + * @since 1.2.6.1 + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ + +/** + * html字符串转换成uNode节点的静态方法 + * @method htmlparser + * @param { String } htmlstr 要转换的html代码 + * @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\n\r\t等空白字符 + * @return { uNode } 给定的html片段转换形成的uNode对象 + * @example + * ```javascript + * var root = UE.htmlparser('

    htmlparser

    ', true); + * ``` + */ + +var htmlparser = (UE.htmlparser = function(htmlstr, ignoreBlank) { + //todo 原来的方式 [^"'<>\/] 有\/就不能配对上 "); + + tmpl.push( + '' + ); + + tempIndex === 2 && tmpl.push(""); + } + + return ( + '
    ' + + '
    ' + + '
    这样的标签了 + //先去掉了,加上的原因忘了,这里先记录 + //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不能去除 + var allowEmptyTags = { + b: 1, + code: 1, + i: 1, + u: 1, + strike: 1, + s: 1, + tt: 1, + strong: 1, + q: 1, + samp: 1, + em: 1, + span: 1, + sub: 1, + img: 1, + sup: 1, + font: 1, + big: 1, + small: 1, + iframe: 1, + a: 1, + br: 1, + pre: 1 + }; + htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), ""); + if (!ignoreBlank) { + htmlstr = htmlstr.replace( + new RegExp( + "[\\r\\t\\n" + + (ignoreBlank ? "" : " ") + + "]*]*)>[\\r\\t\\n" + + (ignoreBlank ? "" : " ") + + "]*", + "g" + ), + function(a, b) { + //br暂时单独处理 + if (b && allowEmptyTags[b.toLowerCase()]) { + return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, ""); + } + return a + .replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "") + .replace( + new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"), + "" + ); + } + ); + } + + var notTransAttrs = { + href: 1, + src: 1 + }; + + var uNode = UE.uNode, + needParentNode = { + td: "tr", + tr: ["tbody", "thead", "tfoot"], + tbody: "table", + th: "tr", + thead: "table", + tfoot: "table", + caption: "table", + li: ["ul", "ol"], + dt: "dl", + dd: "dl", + option: "select" + }, + needChild = { + ol: "li", + ul: "li" + }; + + function text(parent, data) { + if (needChild[parent.tagName]) { + var tmpNode = uNode.createElement(needChild[parent.tagName]); + parent.appendChild(tmpNode); + tmpNode.appendChild(uNode.createText(data)); + parent = tmpNode; + } else { + parent.appendChild(uNode.createText(data)); + } + } + + function element(parent, tagName, htmlattr) { + var needParentTag; + if ((needParentTag = needParentNode[tagName])) { + var tmpParent = parent, + hasParent; + while (tmpParent.type != "root") { + if ( + utils.isArray(needParentTag) + ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 + : needParentTag == tmpParent.tagName + ) { + parent = tmpParent; + hasParent = true; + break; + } + tmpParent = tmpParent.parentNode; + } + if (!hasParent) { + parent = element( + parent, + utils.isArray(needParentTag) ? needParentTag[0] : needParentTag + ); + } + } + //按dtd处理嵌套 + // if(parent.type != 'root' && !dtd[parent.tagName][tagName]) + // parent = parent.parentNode; + var elm = new uNode({ + parentNode: parent, + type: "element", + tagName: tagName.toLowerCase(), + //是自闭合的处理一下 + children: dtd.$empty[tagName] ? null : [] + }); + //如果属性存在,处理属性 + if (htmlattr) { + var attrs = {}, + match; + while ((match = re_attr.exec(htmlattr))) { + attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] + ? match[2] || match[3] || match[4] + : utils.unhtml(match[2] || match[3] || match[4]); + } + elm.attrs = attrs; + } + //trace:3970 + // //如果parent下不能放elm + // if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){ + // parent = parent.parentNode; + // elm.parentNode = parent; + // } + parent.children.push(elm); + //如果是自闭合节点返回父亲节点 + return dtd.$empty[tagName] ? parent : elm; + } + + function comment(parent, data) { + parent.children.push( + new uNode({ + type: "comment", + data: data, + parentNode: parent + }) + ); + } + + var match, + currentIndex = 0, + nextIndex = 0; + //设置根节点 + var root = new uNode({ + type: "root", + children: [] + }); + var currentParent = root; + + while ((match = re_tag.exec(htmlstr))) { + currentIndex = match.index; + try { + if (currentIndex > nextIndex) { + //text node + text(currentParent, htmlstr.slice(nextIndex, currentIndex)); + } + if (match[3]) { + if (dtd.$cdata[currentParent.tagName]) { + text(currentParent, match[0]); + } else { + //start tag + currentParent = element( + currentParent, + match[3].toLowerCase(), + match[4] + ); + } + } else if (match[1]) { + if (currentParent.type != "root") { + if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) { + text(currentParent, match[0]); + } else { + var tmpParent = currentParent; + while ( + currentParent.type == "element" && + currentParent.tagName != match[1].toLowerCase() + ) { + currentParent = currentParent.parentNode; + if (currentParent.type == "root") { + currentParent = tmpParent; + throw "break"; + } + } + //end tag + currentParent = currentParent.parentNode; + } + } + } else if (match[2]) { + //comment + comment(currentParent, match[2]); + } + } catch (e) {} + + nextIndex = re_tag.lastIndex; + } + //如果结束是文本,就有可能丢掉,所以这里手动判断一下 + //例如
  • sdfsdfsdf
  • sdfsdfsdfsdf + if (nextIndex < htmlstr.length) { + text(currentParent, htmlstr.slice(nextIndex)); + } + return root; +}); + + +// core/filternode.js +/** + * UE过滤节点的静态方法 + * @file + */ + +/** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ + +/** + * 根据传入节点和过滤规则过滤相应节点 + * @module UE + * @since 1.2.6.1 + * @method filterNode + * @param { Object } root 指定root节点 + * @param { Object } rules 过滤规则json对象 + * @example + * ```javascript + * UE.filterNode(root,editor.options.filterRules); + * ``` + */ +var filterNode = (UE.filterNode = (function() { + function filterNode(node, rules) { + switch (node.type) { + case "text": + break; + case "element": + var val; + if ((val = rules[node.tagName])) { + if (val === "-") { + node.parentNode.removeChild(node); + } else if (utils.isFunction(val)) { + var parentNode = node.parentNode, + index = node.getIndex(); + val(node); + if (node.parentNode) { + if (node.children) { + for (var i = 0, ci; (ci = node.children[i]); ) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } else { + for (var i = index, ci; (ci = parentNode.children[i]); ) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } else { + var attrs = val["$"]; + if (attrs && node.attrs) { + var tmpAttrs = {}, + tmpVal; + for (var a in attrs) { + tmpVal = node.getAttr(a); + //todo 只先对style单独处理 + if (a == "style" && utils.isArray(attrs[a])) { + var tmpCssStyle = []; + utils.each(attrs[a], function(v) { + var tmp; + if ((tmp = node.getStyle(v))) { + tmpCssStyle.push(v + ":" + tmp); + } + }); + tmpVal = tmpCssStyle.join(";"); + } + if (tmpVal) { + tmpAttrs[a] = tmpVal; + } + } + node.attrs = tmpAttrs; + } + if (node.children) { + for (var i = 0, ci; (ci = node.children[i]); ) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } + } else { + //如果不在名单里扣出子节点并删除该节点,cdata除外 + if (dtd.$cdata[node.tagName]) { + node.parentNode.removeChild(node); + } else { + var parentNode = node.parentNode, + index = node.getIndex(); + node.parentNode.removeChild(node, true); + for (var i = index, ci; (ci = parentNode.children[i]); ) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } + break; + case "comment": + node.parentNode.removeChild(node); + } + } + return function(root, rules) { + if (utils.isEmptyObject(rules)) { + return root; + } + var val; + if ((val = rules["-"])) { + utils.each(val.split(" "), function(k) { + rules[k] = "-"; + }); + } + for (var i = 0, ci; (ci = root.children[i]); ) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + return root; + }; +})()); + + +// core/plugin.js +/** + * Created with JetBrains PhpStorm. + * User: campaign + * Date: 10/8/13 + * Time: 6:15 PM + * To change this template use File | Settings | File Templates. + */ +UE.plugin = (function() { + var _plugins = {}; + return { + register: function(pluginName, fn, oldOptionName, afterDisabled) { + if (oldOptionName && utils.isFunction(oldOptionName)) { + afterDisabled = oldOptionName; + oldOptionName = null; + } + _plugins[pluginName] = { + optionName: oldOptionName || pluginName, + execFn: fn, + //当插件被禁用时执行 + afterDisabled: afterDisabled + }; + }, + load: function(editor) { + utils.each(_plugins, function(plugin) { + var _export = plugin.execFn.call(editor); + if (editor.options[plugin.optionName] !== false) { + if (_export) { + //后边需要再做扩展 + utils.each(_export, function(v, k) { + switch (k.toLowerCase()) { + case "shortcutkey": + editor.addshortcutkey(v); + break; + case "bindevents": + utils.each(v, function(fn, eventName) { + editor.addListener(eventName, fn); + }); + break; + case "bindmultievents": + utils.each(utils.isArray(v) ? v : [v], function(event) { + var types = utils.trim(event.type).split(/\s+/); + utils.each(types, function(eventName) { + editor.addListener(eventName, event.handler); + }); + }); + break; + case "commands": + utils.each(v, function(execFn, execName) { + editor.commands[execName] = execFn; + }); + break; + case "outputrule": + editor.addOutputRule(v); + break; + case "inputrule": + editor.addInputRule(v); + break; + case "defaultoptions": + editor.setOpt(v); + } + }); + } + } else if (plugin.afterDisabled) { + plugin.afterDisabled.call(editor); + } + }); + //向下兼容 + utils.each(UE.plugins, function(plugin) { + plugin.call(editor); + }); + }, + run: function(pluginName, editor) { + var plugin = _plugins[pluginName]; + if (plugin) { + plugin.exeFn.call(editor); + } + } + }; +})(); + + +// core/keymap.js +var keymap = (UE.keymap = { + Backspace: 8, + Tab: 9, + Enter: 13, + + Shift: 16, + Control: 17, + Alt: 18, + CapsLock: 20, + + Esc: 27, + + Spacebar: 32, + + PageUp: 33, + PageDown: 34, + End: 35, + Home: 36, + + Left: 37, + Up: 38, + Right: 39, + Down: 40, + + Insert: 45, + + Del: 46, + + NumLock: 144, + + Cmd: 91, + + "=": 187, + "-": 189, + + b: 66, + i: 73, + //回退 + z: 90, + y: 89, + //粘贴 + v: 86, + x: 88, + + s: 83, + + n: 78 +}); + + +// core/localstorage.js +var LocalStorage = (UE.LocalStorage = (function () { + + var storage = window.localStorage + + return { + saveLocalData: function (key, data) { + // console.log('saveLocalData', key, data); + if (!storage) { + return false; + } + storage.setItem(key, data); + return true; + }, + getLocalData: function (key) { + // console.log('getLocalData', key); + if (!storage) { + return null; + } + return storage.getItem(key) || null; + }, + removeItem: function (key) { + // console.log('removeItem', key); + storage && storage.removeItem(key); + } + }; + +})()); + +(function () { + + var ROOT_KEY = "UEditorPlusPref"; + + UE.Editor.prototype.setPreferences = function (key, value) { + // console.log('setPreferences', key, value); + var obj = {}; + if (utils.isString(key)) { + obj[key] = value; + } else { + obj = key; + } + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + utils.extend(data, obj); + } else { + data = obj; + } + data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); + }; + + UE.Editor.prototype.getPreferences = function (key) { + // console.log('getPreferences', key); + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + return key ? data[key] : data; + } + return null; + }; + + UE.Editor.prototype.removePreferences = function (key) { + // console.log('removePreferences', key); + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + data[key] = undefined; + delete data[key]; + } + data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); + }; +})(); + + +// plugins/defaultfilter.js +///import core +///plugin 编辑器默认的过滤转换机制 + +UE.plugins["defaultfilter"] = function() { + var me = this; + me.setOpt({ + allowDivTransToP: true, + disabledTableInTable: true, + rgb2Hex: true + }); + //默认的过滤处理 + //进入编辑器的内容处理 + me.addInputRule(function(root) { + var allowDivTransToP = this.options.allowDivTransToP; + var val; + function tdParent(node) { + while (node && node.type == "element") { + if (node.tagName == "td") { + return true; + } + node = node.parentNode; + } + return false; + } + //进行默认的处理 + root.traversal(function(node) { + if (node.type == "element") { + if ( + !dtd.$cdata[node.tagName] && + me.options.autoClearEmptyNode && + dtd.$inline[node.tagName] && + !dtd.$empty[node.tagName] && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + if (!node.firstChild()) node.parentNode.removeChild(node); + else if ( + node.tagName == "span" && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + node.parentNode.removeChild(node, true); + } + return; + } + switch (node.tagName) { + case "style": + case "script": + node.setAttr({ + cdata_tag: node.tagName, + cdata_data: node.innerHTML() || "", + _ue_custom_node_: "true" + }); + node.tagName = "div"; + node.innerHTML(""); + break; + case "a": + if ((val = node.getAttr("href"))) { + node.setAttr("_href", val); + } + break; + case "img": + //todo base64暂时去掉,后边做远程图片上传后,干掉这个 + if ((val = node.getAttr("src"))) { + if (/^data:/.test(val)) { + node.parentNode.removeChild(node); + break; + } + } + node.setAttr("_src", node.getAttr("src")); + break; + case "span": + if (browser.webkit && (val = node.getStyle("white-space"))) { + if (/nowrap|normal/.test(val)) { + node.setStyle("white-space", ""); + if ( + me.options.autoClearEmptyNode && + utils.isEmptyObject(node.attrs) + ) { + node.parentNode.removeChild(node, true); + } + } + } + val = node.getAttr("id"); + if (val && /^_baidu_bookmark_/i.test(val)) { + node.parentNode.removeChild(node); + } + break; + case "p": + if ((val = node.getAttr("align"))) { + node.setAttr("align"); + node.setStyle("text-align", val); + } + //trace:3431 + // var cssStyle = node.getAttr('style'); + // if (cssStyle) { + // cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, ''); + // node.setAttr('style', cssStyle) + // + // } + //p标签不允许嵌套 + utils.each(node.children, function(n) { + if (n.type == "element" && n.tagName == "p") { + var next = n.nextSibling(); + node.parentNode.insertAfter(n, node); + var last = n; + while (next) { + var tmp = next.nextSibling(); + node.parentNode.insertAfter(next, last); + last = next; + next = tmp; + } + return false; + } + }); + if (!node.firstChild()) { + node.innerHTML(browser.ie ? " " : "
    "); + } + break; + case "div": + if (node.getAttr("cdata_tag")) { + break; + } + //针对代码这里不处理插入代码的div + val = node.getAttr("class"); + if (val && /^line number\d+/.test(val)) { + break; + } + if (!allowDivTransToP) { + break; + } + var tmpNode, + p = UE.uNode.createElement("p"); + while ((tmpNode = node.firstChild())) { + if ( + tmpNode.type == "text" || + !UE.dom.dtd.$block[tmpNode.tagName] + ) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement("p"); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + break; + case "dl": + node.tagName = "ul"; + break; + case "dt": + case "dd": + node.tagName = "li"; + break; + case "li": + var className = node.getAttr("class"); + if (!className || !/list\-/.test(className)) { + node.setAttr(); + } + var tmpNodes = node.getNodesByTagName("ol ul"); + UE.utils.each(tmpNodes, function(n) { + node.parentNode.insertAfter(n, node); + }); + break; + case "td": + case "th": + case "caption": + if (!node.children || !node.children.length) { + node.appendChild( + browser.ie11below + ? UE.uNode.createText(" ") + : UE.uNode.createElement("br") + ); + } + break; + case "table": + if (me.options.disabledTableInTable && tdParent(node)) { + node.parentNode.insertBefore( + UE.uNode.createText(node.innerText()), + node + ); + node.parentNode.removeChild(node); + } + } + } + // if(node.type == 'comment'){ + // node.parentNode.removeChild(node); + // } + }); + }); + + //从编辑器出去的内容处理 + me.addOutputRule(function(root) { + var val; + root.traversal(function(node) { + if (node.type == "element") { + if ( + me.options.autoClearEmptyNode && + dtd.$inline[node.tagName] && + !dtd.$empty[node.tagName] && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + if (!node.firstChild()) node.parentNode.removeChild(node); + else if ( + node.tagName == "span" && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + node.parentNode.removeChild(node, true); + } + return; + } + switch (node.tagName) { + case "div": + if ((val = node.getAttr("cdata_tag"))) { + node.tagName = val; + node.appendChild(UE.uNode.createText(node.getAttr("cdata_data"))); + node.setAttr({ + cdata_tag: "", + cdata_data: "", + _ue_custom_node_: "" + }); + } + break; + case "a": + if ((val = node.getAttr("_href"))) { + node.setAttr({ + href: utils.html(val), + _href: "" + }); + } + break; + break; + case "span": + val = node.getAttr("id"); + if (val && /^_baidu_bookmark_/i.test(val)) { + node.parentNode.removeChild(node); + } + //将color的rgb格式转换为#16进制格式 + if (me.getOpt("rgb2Hex")) { + var cssStyle = node.getAttr("style"); + if (cssStyle) { + node.setAttr( + "style", + cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function(a, value) { + var array = value.split(","); + if (array.length > 3) return ""; + value = "#"; + for (var i = 0, color; (color = array[i++]); ) { + color = parseInt( + color.replace(/[^\d]/gi, ""), + 10 + ).toString(16); + value += color.length == 1 ? "0" + color : color; + } + return value.toUpperCase(); + }) + ); + } + } + break; + case "img": + if ((val = node.getAttr("_src"))) { + node.setAttr({ + src: node.getAttr("_src"), + _src: "" + }); + } + } + } + }); + }); +}; + + +// plugins/inserthtml.js +/** + * 插入html字符串插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入html代码 + * @command inserthtml + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } html 插入的html字符串 + * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入 + * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。 + * @example + * ```javascript + * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本 + * //执行命令,插入CC + * //插入后的效果 xxxCCxxx + * //

    xx|xxx

    当前选区为闭合状态 + * //插入

    CC

    + * //结果

    xx

    CC

    xxx

    + * //

    xxxx

    |

    xxx

    当前选区在两个p标签之间 + * //插入 xxxx + * //结果

    xxxx

    xxxx

    xxx

    + * ``` + */ + +UE.commands["inserthtml"] = { + execCommand: function(command, html, notNeedFilter) { + var me = this, + range, + div; + if (!html) { + return; + } + if (me.fireEvent("beforeinserthtml", html) === true) { + return; + } + range = me.selection.getRange(); + div = range.document.createElement("div"); + div.style.display = "inline"; + + if (!notNeedFilter) { + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if (me.options.filterRules) { + UE.filterNode(root, me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + html = root.toHtml(); + } + div.innerHTML = utils.trim(html); + + if (!range.collapsed) { + var tmpNode = range.startContainer; + if (domUtils.isFillChar(tmpNode)) { + range.setStartBefore(tmpNode); + } + tmpNode = range.endContainer; + if (domUtils.isFillChar(tmpNode)) { + range.setEndAfter(tmpNode); + } + range.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if (range.endContainer && range.endContainer.nodeType == 1) { + tmpNode = range.endContainer.childNodes[range.endOffset]; + if (tmpNode && domUtils.isBr(tmpNode)) { + range.setEndAfter(tmpNode); + } + } + if (range.startOffset == 0) { + tmpNode = range.startContainer; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + tmpNode = range.endContainer; + if ( + range.endOffset == + (tmpNode.nodeType == 3 + ? tmpNode.nodeValue.length + : tmpNode.childNodes.length) && + domUtils.isBoundaryNode(tmpNode, "lastChild") + ) { + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + range.setStart(me.body.firstChild, 0).collapse(true); + } + } + } + !range.collapsed && range.deleteContents(); + if (range.startContainer.nodeType == 1) { + var child = range.startContainer.childNodes[range.startOffset], + pre; + if ( + child && + domUtils.isBlockElm(child) && + (pre = child.previousSibling) && + domUtils.isBlockElm(pre) + ) { + range.setEnd(pre, pre.childNodes.length).collapse(); + while (child.firstChild) { + pre.appendChild(child.firstChild); + } + domUtils.remove(child); + } + } + } + + var child, + parent, + pre, + tmp, + hadBreak = 0, + nextNode; + //如果当前位置选中了fillchar要干掉,要不会产生空行 + if (range.inFillChar()) { + child = range.startContainer; + if (domUtils.isFillChar(child)) { + range.setStartBefore(child).collapse(true); + domUtils.remove(child); + } else if (domUtils.isFillChar(child, true)) { + child.nodeValue = child.nodeValue.replace(fillCharReg, ""); + range.startOffset--; + range.collapsed && range.collapse(true); + } + } + //列表单独处理 + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li) { + var next, last; + while ((child = div.firstChild)) { + //针对hr单独处理一下先 + while ( + child && + (child.nodeType == 3 || + !domUtils.isBlockElm(child) || + child.tagName == "HR") + ) { + next = child.nextSibling; + range.insertNode(child).collapse(); + last = child; + child = next; + } + if (child) { + if (/^(ol|ul)$/i.test(child.tagName)) { + while (child.firstChild) { + last = child.firstChild; + domUtils.insertAfter(li, child.firstChild); + li = li.nextSibling; + } + domUtils.remove(child); + } else { + var tmpLi; + next = child.nextSibling; + tmpLi = me.document.createElement("li"); + domUtils.insertAfter(li, tmpLi); + tmpLi.appendChild(child); + last = child; + child = next; + li = tmpLi; + } + } + } + li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (domUtils.isEmptyBlock(li)) { + domUtils.remove(li); + } + if (last) { + range.setStartAfter(last).collapse(true).select(true); + } + } else { + while ((child = div.firstChild)) { + if (hadBreak) { + var p = me.document.createElement("p"); + while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) { + nextNode = child.nextSibling; + p.appendChild(child); + child = nextNode; + } + if (p.firstChild) { + child = p; + } + } + range.insertNode(child); + nextNode = child.nextSibling; + if ( + !hadBreak && + child.nodeType == domUtils.NODE_ELEMENT && + domUtils.isBlockElm(child) + ) { + parent = domUtils.findParent(child, function(node) { + return domUtils.isBlockElm(node); + }); + if ( + parent && + parent.tagName.toLowerCase() != "body" && + !( + dtd[parent.tagName][child.nodeName] && child.parentNode === parent + ) + ) { + if (!dtd[parent.tagName][child.nodeName]) { + pre = parent; + } else { + tmp = child.parentNode; + while (tmp !== parent) { + pre = tmp; + tmp = tmp.parentNode; + } + } + + domUtils.breakParent(child, pre || tmp); + //去掉break后前一个多余的节点

    |<[p> ==>

    |

    + var pre = child.previousSibling; + domUtils.trimWhiteTextNode(pre); + if (!pre.childNodes.length) { + domUtils.remove(pre); + } + //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位 + + if ( + !browser.ie && + (next = child.nextSibling) && + domUtils.isBlockElm(next) && + next.lastChild && + !domUtils.isBr(next.lastChild) + ) { + next.appendChild(me.document.createElement("br")); + } + hadBreak = 1; + } + } + var next = child.nextSibling; + if (!div.firstChild && next && domUtils.isBlockElm(next)) { + range.setStart(next, 0).collapse(true); + break; + } + range.setEndAfter(child).collapse(); + } + + child = range.startContainer; + + if (nextNode && domUtils.isBr(nextNode)) { + domUtils.remove(nextNode); + } + //用chrome可能有空白展位符 + if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) { + if ((nextNode = child.nextSibling)) { + domUtils.remove(child); + if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) { + range.setStart(nextNode, 0).collapse(true).shrinkBoundary(); + } + } else { + try { + child.innerHTML = browser.ie ? domUtils.fillChar : "
    "; + } catch (e) { + range.setStartBefore(child); + domUtils.remove(child); + } + } + } + //加上true因为在删除表情等时会删两次,第一次是删的fillData + try { + range.select(true); + } catch (e) {} + } + + setTimeout(function() { + range = me.selection.getRange(); + range.scrollToView( + me.autoHeightEnabled, + me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0 + ); + me.fireEvent("afterinserthtml", html); + }, 200); + } +}; + + +// plugins/autotypeset.js +/** + * 自动排版 + * @file + * @since 1.2.6.1 + */ + +/** + * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。 + * @command autotypeset + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autotypeset' ); + * ``` + */ + +UE.plugins["autotypeset"] = function() { + this.setOpt({ + // 自动排版参数 + autotypeset: { + // 合并空行 + mergeEmptyline: true, + // 去掉冗余的class + removeClass: true, + // 去掉空行 + removeEmptyline: false, + // 段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 + textAlign: "left", + // 图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 + imageBlockLine: "center", + // 根据规则过滤没事粘贴进来的内容 + pasteFilter: false, + // 去掉所有的内嵌字号,使用编辑器默认的字号 + clearFontSize: false, + // 去掉所有的内嵌字体,使用编辑器默认的字体 + clearFontFamily: false, + // 去掉空节点 + removeEmptyNode: false, + // 可以去掉的标签 + removeTagNames: utils.extend({ div: 1 }, dtd.$removeEmpty), + // 行首缩进 + indent: false, + // 行首缩进的大小 + indentValue: "2em", + // 全角转半角 + bdc2sb: false, + // 半角转全角 + tobdc: false + } + }); + + var me = this, + opt = me.options.autotypeset, + remainClass = { + selectTdClass: 1, + pagebreak: 1, + anchorclass: 1 + }, + remainTag = { + li: 1 + }, + tags = { + div: 1, + p: 1, + //trace:2183 这些也认为是行 + blockquote: 1, + center: 1, + h1: 1, + h2: 1, + h3: 1, + h4: 1, + h5: 1, + h6: 1, + span: 1 + }, + highlightCont; + //升级了版本,但配置项目里没有autotypeset + if (!opt) { + return; + } + + readLocalOpts(); + + function isLine(node, notEmpty) { + if (!node || node.nodeType == 3) return 0; + if (domUtils.isBr(node)) return 1; + if (node && node.parentNode && tags[node.tagName.toLowerCase()]) { + if ( + (highlightCont && highlightCont.contains(node)) || + node.getAttribute("pagebreak") + ) { + return 0; + } + + return notEmpty + ? !domUtils.isEmptyBlock(node) + : domUtils.isEmptyBlock( + node, + new RegExp("[\\s" + domUtils.fillChar + "]", "g") + ); + } + } + + function removeNotAttributeSpan(node) { + if (!node.style.cssText) { + domUtils.removeAttributes(node, ["style"]); + if ( + node.tagName.toLowerCase() == "span" && + domUtils.hasNoAttributes(node) + ) { + domUtils.remove(node, true); + } + } + } + function autotype(type, html) { + var me = this, + cont; + if (html) { + if (!opt.pasteFilter) { + return; + } + cont = me.document.createElement("div"); + cont.innerHTML = html.html; + } else { + cont = me.document.body; + } + var nodes = domUtils.getElementsByTagName(cont, "*"); + + // 行首缩进,段落方向,段间距,段内间距 + for (var i = 0, ci; (ci = nodes[i++]); ) { + if (me.fireEvent("excludeNodeinautotype", ci) === true) { + continue; + } + //font-size + if (opt.clearFontSize && ci.style.fontSize) { + domUtils.removeStyle(ci, "font-size"); + + removeNotAttributeSpan(ci); + } + //font-family + if (opt.clearFontFamily && ci.style.fontFamily) { + domUtils.removeStyle(ci, "font-family"); + removeNotAttributeSpan(ci); + } + + if (isLine(ci)) { + //合并空行 + if (opt.mergeEmptyline) { + var next = ci.nextSibling, + tmpNode, + isBr = domUtils.isBr(ci); + while (isLine(next)) { + tmpNode = next; + next = tmpNode.nextSibling; + if (isBr && (!next || (next && !domUtils.isBr(next)))) { + break; + } + domUtils.remove(tmpNode); + } + } + //去掉空行,保留占位的空行 + if ( + opt.removeEmptyline && + domUtils.inDoc(ci, cont) && + !remainTag[ci.parentNode.tagName.toLowerCase()] + ) { + if (domUtils.isBr(ci)) { + next = ci.nextSibling; + if (next && !domUtils.isBr(next)) { + continue; + } + } + domUtils.remove(ci); + continue; + } + } + if (isLine(ci, true) && ci.tagName != "SPAN") { + if (opt.indent) { + ci.style.textIndent = opt.indentValue; + } + if (opt.textAlign) { + ci.style.textAlign = opt.textAlign; + } + // if(opt.lineHeight) + // ci.style.lineHeight = opt.lineHeight + 'cm'; + } + + //去掉class,保留的class不去掉 + if ( + opt.removeClass && + ci.className && + !remainClass[ci.className.toLowerCase()] + ) { + if (highlightCont && highlightCont.contains(ci)) { + continue; + } + domUtils.removeAttributes(ci, ["class"]); + } + + //表情不处理 + if ( + opt.imageBlockLine && + ci.tagName.toLowerCase() == "img" && + !ci.getAttribute("emotion") + ) { + if (html) { + var img = ci; + switch (opt.imageBlockLine) { + case "left": + case "right": + case "none": + var pN = img.parentNode, + tmpNode, + pre, + next; + while (dtd.$inline[pN.tagName] || pN.tagName == "A") { + pN = pN.parentNode; + } + tmpNode = pN; + if ( + tmpNode.tagName == "P" && + domUtils.getStyle(tmpNode, "text-align") == "center" + ) { + if ( + !domUtils.isBody(tmpNode) && + domUtils.getChildCount(tmpNode, function(node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 + ) { + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if ( + pre && + next && + pre.nodeType == 1 && + next.nodeType == 1 && + pre.tagName == next.tagName && + domUtils.isBlockElm(pre) + ) { + pre.appendChild(tmpNode.firstChild); + while (next.firstChild) { + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + } else { + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + } + domUtils.setStyle(img, "float", opt.imageBlockLine); + break; + case "center": + if (me.queryCommandValue("imagefloat") != "center") { + pN = img.parentNode; + domUtils.setStyle(img, "float", "none"); + tmpNode = img; + while ( + pN && + domUtils.getChildCount(pN, function(node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 && + (dtd.$inline[pN.tagName] || pN.tagName == "A") + ) { + tmpNode = pN; + pN = pN.parentNode; + } + var pNode = me.document.createElement("p"); + domUtils.setAttributes(pNode, { + style: "text-align:center" + }); + tmpNode.parentNode.insertBefore(pNode, tmpNode); + pNode.appendChild(tmpNode); + domUtils.setStyle(tmpNode, "float", ""); + } + } + } else { + var range = me.selection.getRange(); + range.selectNode(ci).select(); + me.execCommand("imagefloat", opt.imageBlockLine); + } + } + + //去掉冗余的标签 + if (opt.removeEmptyNode) { + if ( + opt.removeTagNames[ci.tagName.toLowerCase()] && + domUtils.hasNoAttributes(ci) && + domUtils.isEmptyBlock(ci) + ) { + domUtils.remove(ci); + } + } + } + if (opt.tobdc) { + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function(node) { + if (node.type == "text") { + node.data = ToDBC(node.data); + } + }); + cont.innerHTML = root.toHtml(); + } + if (opt.bdc2sb) { + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function(node) { + if (node.type == "text") { + node.data = DBC2SB(node.data); + } + }); + cont.innerHTML = root.toHtml(); + } + if (html) { + html.html = cont.innerHTML; + } + } + if (opt.pasteFilter) { + me.addListener("beforepaste", autotype); + } + + function DBC2SB(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); //获取当前字符的unicode编码 + if (code >= 65281 && code <= 65373) { + //在这个unicode编码范围中的是所有的英文字母已经各种字符 + result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码 + } else if (code == 12288) { + //空格 + result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32); + } else { + result += str.charAt(i); + } + } + return result; + } + function ToDBC(txtstring) { + txtstring = utils.html(txtstring); + var tmp = ""; + var mark = ""; /*用于判断,如果是html尖括里的标记,则不进行全角的转换*/ + for (var i = 0; i < txtstring.length; i++) { + if (txtstring.charCodeAt(i) == 32) { + tmp = tmp + String.fromCharCode(12288); + } else if (txtstring.charCodeAt(i) < 127) { + tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248); + } else { + tmp += txtstring.charAt(i); + } + } + return tmp; + } + + function readLocalOpts() { + var cookieOpt = me.getPreferences("autotypeset"); + utils.extend(me.options.autotypeset, cookieOpt); + } + + me.commands["autotypeset"] = { + execCommand: function() { + me.removeListener("beforepaste", autotype); + if (opt.pasteFilter) { + me.addListener("beforepaste", autotype); + } + autotype.call(me); + } + }; +}; + + +// plugins/autosubmit.js +/** + * 快捷键提交 + * @file + * @since 1.2.6.1 + */ + +/** + * 提交表单 + * @command autosubmit + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autosubmit' ); + * ``` + */ + +UE.plugin.register("autosubmit", function() { + return { + shortcutkey: { + autosubmit: "ctrl+13" //手动提交 + }, + commands: { + autosubmit: { + execCommand: function() { + var me = this, + form = domUtils.findParentByTagName(me.iframe, "form", false); + if (form) { + if (me.fireEvent("beforesubmit") === false) { + return; + } + me.sync(); + form.submit(); + } + } + } + } + }; +}); + + +// plugins/background.js +/** + * 背景插件,为UEditor提供设置背景功能 + * @file + * @since 1.2.6.1 + */ +UE.plugin.register("background", function() { + var me = this, + cssRuleId = "editor_background", + isSetColored, + reg = new RegExp("body[\\s]*\\{(.+)\\}", "i"); + + function stringToObj(str) { + var obj = {}, + styles = str.split(";"); + utils.each(styles, function(v) { + var index = v.indexOf(":"), + key = utils.trim(v.substr(0, index)).toLowerCase(); + key && (obj[key] = utils.trim(v.substr(index + 1) || "")); + }); + return obj; + } + + function setBackground(obj) { + if (obj) { + var styles = []; + for (var name in obj) { + if (obj.hasOwnProperty(name)) { + styles.push(name + ":" + obj[name] + "; "); + } + } + utils.cssRule( + cssRuleId, + styles.length ? "body{" + styles.join("") + "}" : "", + me.document + ); + } else { + utils.cssRule(cssRuleId, "", me.document); + } + } + //重写editor.hasContent方法 + + var orgFn = me.hasContents; + me.hasContents = function() { + if (me.queryCommandValue("background")) { + return true; + } + return orgFn.apply(me, arguments); + }; + return { + bindEvents: { + getAllHtml: function(type, headHtml) { + var body = this.body, + su = domUtils.getComputedStyle(body, "background-image"), + url = ""; + if (su.indexOf(me.options.imagePath) > 0) { + url = su + .substring(su.indexOf(me.options.imagePath), su.length - 1) + .replace(/"|\(|\)/gi, ""); + } else { + url = su != "none" ? su.replace(/url\("?|"?\)/gi, "") : ""; + } + var html = ' "; + headHtml.push(html); + }, + aftersetcontent: function() { + if (isSetColored == false) setBackground(); + } + }, + inputRule: function(root) { + isSetColored = false; + utils.each(root.getNodesByTagName("p"), function(p) { + var styles = p.getAttr("data-background"); + if (styles) { + isSetColored = true; + setBackground(stringToObj(styles)); + p.parentNode.removeChild(p); + } + }); + }, + outputRule: function(root) { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || "") + .replace(/[\n\r]+/g, "") + .match(reg); + if (styles) { + root.appendChild( + UE.uNode.createElement( + '


    ' + ) + ); + } + }, + commands: { + background: { + execCommand: function(cmd, obj) { + setBackground(obj); + }, + queryCommandValue: function() { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || "") + .replace(/[\n\r]+/g, "") + .match(reg); + return styles ? stringToObj(styles[1]) : null; + }, + notNeedUndo: true + } + } + }; +}); + + +// plugins/image.js +/** + * 图片插入、排版插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 图片对齐方式 + * @command imagefloat + * @method execCommand + * @remind 值center为独占一行居中 + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式,可传left、right、none、center + * @remaind center表示图片独占一行 + * @example + * ```javascript + * editor.execCommand( 'imagefloat', 'center' ); + * ``` + */ + +/** + * 如果选区所在位置是图片区域 + * @command imagefloat + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回图片对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'imagefloat' ); + * ``` + */ + +UE.commands["imagefloat"] = { + execCommand: function(cmd, align) { + var me = this, + range = me.selection.getRange(); + if (!range.collapsed) { + var img = range.getClosedNode(); + if (img && img.tagName == "IMG") { + switch (align) { + case "left": + case "right": + case "none": + var pN = img.parentNode, + tmpNode, + pre, + next; + while (dtd.$inline[pN.tagName] || pN.tagName == "A") { + pN = pN.parentNode; + } + tmpNode = pN; + if ( + tmpNode.tagName == "P" && + domUtils.getStyle(tmpNode, "text-align") == "center" + ) { + if ( + !domUtils.isBody(tmpNode) && + domUtils.getChildCount(tmpNode, function(node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 + ) { + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if ( + pre && + next && + pre.nodeType == 1 && + next.nodeType == 1 && + pre.tagName == next.tagName && + domUtils.isBlockElm(pre) + ) { + pre.appendChild(tmpNode.firstChild); + while (next.firstChild) { + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + } else { + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + + range.selectNode(img).select(); + } + domUtils.setStyle(img, "float", align == "none" ? "" : align); + if (align == "none") { + domUtils.removeAttributes(img, "align"); + } + + break; + case "center": + if (me.queryCommandValue("imagefloat") != "center") { + pN = img.parentNode; + domUtils.setStyle(img, "float", ""); + domUtils.removeAttributes(img, "align"); + tmpNode = img; + while ( + pN && + domUtils.getChildCount(pN, function(node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 && + (dtd.$inline[pN.tagName] || pN.tagName == "A") + ) { + tmpNode = pN; + pN = pN.parentNode; + } + range.setStartBefore(tmpNode).setCursor(false); + pN = me.document.createElement("div"); + pN.appendChild(tmpNode); + domUtils.setStyle(tmpNode, "float", ""); + + me.execCommand( + "insertHtml", + '

    ' + + pN.innerHTML + + "

    " + ); + + tmpNode = me.document.getElementById("_img_parent_tmp"); + tmpNode.removeAttribute("id"); + tmpNode = tmpNode.firstChild; + range.selectNode(tmpNode).select(); + //去掉后边多余的元素 + next = tmpNode.parentNode.nextSibling; + if (next && domUtils.isEmptyNode(next)) { + domUtils.remove(next); + } + } + + break; + } + } + } + }, + queryCommandValue: function() { + var range = this.selection.getRange(), + startNode, + floatStyle; + if (range.collapsed) { + return "none"; + } + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") { + floatStyle = + domUtils.getComputedStyle(startNode, "float") || + startNode.getAttribute("align"); + + if (floatStyle == "none") { + floatStyle = domUtils.getComputedStyle( + startNode.parentNode, + "text-align" + ) == "center" + ? "center" + : floatStyle; + } + return { + left: 1, + right: 1, + center: 1 + }[floatStyle] + ? floatStyle + : "none"; + } + return "none"; + }, + queryCommandState: function() { + var range = this.selection.getRange(), + startNode; + + if (range.collapsed) return -1; + + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") { + return 0; + } + return -1; + } +}; + +/** + * 插入图片 + * @command insertimage + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片 + * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片, + * 此时数组的每一个元素都是一个Object类型的图片属性集合。 + * @example + * ```javascript + * editor.execCommand( 'insertimage', { + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * } ); + * ``` + * @example + * ```javascript + * editor.execCommand( 'insertimage', [{ + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * },{ + * src:'a/b/d.jpg', + * width:'100', + * height:'100' + * }] ); + * ``` + */ + +UE.commands["insertimage"] = { + execCommand: function(cmd, opt) { + opt = utils.isArray(opt) ? opt : [opt]; + if (!opt.length) { + return; + } + var me = this, + range = me.selection.getRange(), + img = range.getClosedNode(); + + if (me.fireEvent("beforeinsertimage", opt) === true) { + return; + } + + if ( + img && + /img/i.test(img.tagName) && + (img.className != "edui-faked-video" || + img.className.indexOf("edui-upload-video") != -1) && + !img.getAttribute("data-word-image") + ) { + var first = opt.shift(); + var floatStyle = first["floatStyle"]; + delete first["floatStyle"]; + //// img.style.border = (first.border||0) +"px solid #000"; + //// img.style.margin = (first.margin||0) +"px"; + // img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000"; + domUtils.setAttributes(img, first); + me.execCommand("imagefloat", floatStyle); + if (opt.length > 0) { + range.setStartAfter(img).setCursor(false, true); + me.execCommand("insertimage", opt); + } + } else { + var html = [], + str = "", + ci; + ci = opt[0]; + if (opt.length == 1) { + str = + '' + ci.alt + '"; + if (ci["floatStyle"] == "center") { + str = '

    ' + str + "

    "; + } + html.push(str); + } else { + for (var i = 0; (ci = opt[i++]); ) { + str = + "

    "; + html.push(str); + } + } + + me.execCommand("insertHtml", html.join("")); + } + + me.fireEvent("afterinsertimage", opt); + } +}; + + +// plugins/justify.js +/** + * 段落格式 + * @file + * @since 1.2.6.1 + */ + +/** + * 段落对齐方式 + * @command justify + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐 + * @example + * ```javascript + * editor.execCommand( 'justify', 'center' ); + * ``` + */ +/** + * 如果选区所在位置是段落区域,返回当前段落对齐方式 + * @command justify + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回段落对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'justify' ); + * ``` + */ + +UE.plugins["justify"] = function() { + var me = this, + block = domUtils.isBlockElm, + defaultValue = { + left: 1, + right: 1, + center: 1, + justify: 1 + }, + doJustify = function(range, style) { + var bookmark = range.createBookmark(), + filterFn = function(node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" && + !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }; + + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType == 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + var common = tmpRange.getCommonAncestor(); + if (!domUtils.isBody(common) && block(common)) { + domUtils.setStyles( + common, + utils.isString(style) ? { "text-align": style } : style + ); + current = common; + } else { + var p = range.document.createElement("p"); + domUtils.setStyles( + p, + utils.isString(style) ? { "text-align": style } : style + ); + var frag = tmpRange.extractContents(); + p.appendChild(frag); + tmpRange.insertNode(p); + current = p; + } + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + + UE.commands["justify"] = { + execCommand: function(cmdName, align) { + var range = this.selection.getRange(), + txt; + + //闭合时单独处理 + if (range.collapsed) { + txt = this.document.createTextNode("p"); + range.insertNode(txt); + } + doJustify(range, align); + if (txt) { + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + + return true; + }, + queryCommandValue: function() { + var startNode = this.selection.getStart(), + value = domUtils.getComputedStyle(startNode, "text-align"); + return defaultValue[value] ? value : "left"; + }, + queryCommandState: function() { + var start = this.selection.getStart(), + cell = + start && + domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + + return cell ? -1 : 0; + } + }; +}; + + +// plugins/font.js +/** + * 字体颜色,背景色,字号,字体,下划线,删除线 + * @file + * @since 1.2.6.1 + */ + +/** + * 字体颜色 + * @command forecolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'forecolor', '#000' ); + * ``` + */ +/** + * 返回选区字体颜色 + * @command forecolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'forecolor' ); + * ``` + */ + +/** + * 字体背景颜色 + * @command backcolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'backcolor', '#000' ); + * ``` + */ +/** + * 返回选区字体颜色 + * @command backcolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体背景颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'backcolor' ); + * ``` + */ + +/** + * 字体大小 + * @command fontsize + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体大小 + * @example + * ```javascript + * editor.execCommand( 'fontsize', '14px' ); + * ``` + */ +/** + * 返回选区字体大小 + * @command fontsize + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体大小 + * @example + * ```javascript + * editor.queryCommandValue( 'fontsize' ); + * ``` + */ + +/** + * 字体样式 + * @command fontfamily + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体样式 + * @example + * ```javascript + * editor.execCommand( 'fontfamily', '微软雅黑' ); + * ``` + */ +/** + * 返回选区字体样式 + * @command fontfamily + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体样式 + * @example + * ```javascript + * editor.queryCommandValue( 'fontfamily' ); + * ``` + */ + +/** + * 字体下划线,与删除线互斥 + * @command underline + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'underline' ); + * ``` + */ + +/** + * 字体删除线,与下划线互斥 + * @command strikethrough + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'strikethrough' ); + * ``` + */ + +/** + * 字体边框 + * @command fontborder + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'fontborder' ); + * ``` + */ + +UE.plugins["font"] = function() { + var me = this, + fonts = { + forecolor: "color", + backcolor: "background-color", + fontsize: "font-size", + fontfamily: "font-family", + underline: "text-decoration", + strikethrough: "text-decoration", + fontborder: "border" + }, + lang = me.getLang(), + needCmd = { underline: 1, strikethrough: 1, fontborder: 1 }, + needSetChild = { + forecolor: "color", + backcolor: "background-color", + fontsize: "font-size", + fontfamily: "font-family" + }; + me.setOpt({ + fontfamily: [ + { name: "default", val: "default" }, + { name: "songti", val: "宋体,SimSun" }, + { name: "yahei", val: "微软雅黑,Microsoft YaHei" }, + { name: "kaiti", val: "楷体,楷体_GB2312,SimKai" }, + { name: "heiti", val: "黑体,SimHei" }, + { name: "lishu", val: "隶书,SimLi" }, + // { name: "andaleMono", val: "andale mono" }, + { name: "arial", val: "arial,helvetica,sans-serif" }, + // { name: "arialBlack", val: "arial black,avant garde" }, + // { name: "comicSansMs", val: "comic sans ms" }, + // { name: "impact", val: "impact,chicago" }, + { name: "timesNewRoman", val: "times new roman" } + ], + fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36] + }); + + function mergeWithParent(node) { + var parent; + while ((parent = node.parentNode)) { + if ( + parent.tagName == "SPAN" && + domUtils.getChildCount(parent, function(child) { + return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child); + }) == 1 + ) { + parent.style.cssText += node.style.cssText; + domUtils.remove(node, true); + node = parent; + } else { + break; + } + } + } + function mergeChild(rng, cmdName, value) { + if (needSetChild[cmdName]) { + rng.adjustmentBoundary(); + if (!rng.collapsed && rng.startContainer.nodeType == 1) { + var start = rng.startContainer.childNodes[rng.startOffset]; + if (start && domUtils.isTagNode(start, "span")) { + var bk = rng.createBookmark(); + utils.each(domUtils.getElementsByTagName(start, "span"), function( + span + ) { + if (!span.parentNode || domUtils.isBookmarkNode(span)) return; + if ( + cmdName == "backcolor" && + domUtils + .getComputedStyle(span, "background-color") + .toLowerCase() === value + ) { + return; + } + domUtils.removeStyle(span, needSetChild[cmdName]); + if (span.style.cssText.replace(/^\s+$/, "").length == 0) { + domUtils.remove(span, true); + } + }); + rng.moveToBookmark(bk); + } + } + } + } + function mergesibling(rng, cmdName, value) { + var collapsed = rng.collapsed, + bk = rng.createBookmark(), + common; + if (collapsed) { + common = bk.start.parentNode; + while (dtd.$inline[common.tagName]) { + common = common.parentNode; + } + } else { + common = domUtils.getCommonAncestor(bk.start, bk.end); + } + utils.each(domUtils.getElementsByTagName(common, "span"), function(span) { + if (!span.parentNode || domUtils.isBookmarkNode(span)) return; + if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) { + if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) { + domUtils.remove(span, true); + } else { + domUtils.removeStyle(span, "border"); + } + return; + } + if ( + /border/i.test(span.style.cssText) && + span.parentNode.tagName == "SPAN" && + /border/i.test(span.parentNode.style.cssText) + ) { + span.style.cssText = span.style.cssText.replace( + /border[^:]*:[^;]+;?/gi, + "" + ); + } + if (!(cmdName == "fontborder" && value == "none")) { + var next = span.nextSibling; + while (next && next.nodeType == 1 && next.tagName == "SPAN") { + if (domUtils.isBookmarkNode(next) && cmdName == "fontborder") { + span.appendChild(next); + next = span.nextSibling; + continue; + } + if (next.style.cssText == span.style.cssText) { + domUtils.moveChild(next, span); + domUtils.remove(next); + } + if (span.nextSibling === next) break; + next = span.nextSibling; + } + } + + mergeWithParent(span); + if (browser.ie && browser.version > 8) { + //拷贝父亲们的特别的属性,这里只做背景颜色的处理 + var parent = domUtils.findParent(span, function(n) { + return ( + n.tagName == "SPAN" && /background-color/.test(n.style.cssText) + ); + }); + if (parent && !/background-color/.test(span.style.cssText)) { + span.style.backgroundColor = parent.style.backgroundColor; + } + } + }); + rng.moveToBookmark(bk); + mergeChild(rng, cmdName, value); + } + + me.addInputRule(function(root) { + utils.each(root.getNodesByTagName("u s del font strike"), function(node) { + if (node.tagName == "font") { + var cssStyle = []; + for (var p in node.attrs) { + switch (p) { + case "size": + cssStyle.push( + "font-size:" + + ({ + "1": "10", + "2": "12", + "3": "16", + "4": "18", + "5": "24", + "6": "32", + "7": "48" + }[node.attrs[p]] || node.attrs[p]) + + "px" + ); + break; + case "color": + cssStyle.push("color:" + node.attrs[p]); + break; + case "face": + cssStyle.push("font-family:" + node.attrs[p]); + break; + case "style": + cssStyle.push(node.attrs[p]); + } + } + node.attrs = { + style: cssStyle.join(";") + }; + } else { + var val = node.tagName == "u" ? "underline" : "line-through"; + node.attrs = { + style: (node.getAttr("style") || "") + "text-decoration:" + val + ";" + }; + } + node.tagName = "span"; + }); + // utils.each(root.getNodesByTagName('span'), function (node) { + // var val; + // if(val = node.getAttr('class')){ + // if(/fontstrikethrough/.test(val)){ + // node.setStyle('text-decoration','line-through'); + // if(node.attrs['class']){ + // node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,''); + // }else{ + // node.setAttr('class') + // } + // } + // if(/fontborder/.test(val)){ + // node.setStyle('border','1px solid #000'); + // if(node.attrs['class']){ + // node.attrs['class'] = node.attrs['class'].replace(/fontborder/,''); + // }else{ + // node.setAttr('class') + // } + // } + // } + // }); + }); + // me.addOutputRule(function(root){ + // utils.each(root.getNodesByTagName('span'), function (node) { + // var val; + // if(val = node.getStyle('text-decoration')){ + // if(/line-through/.test(val)){ + // if(node.attrs['class']){ + // node.attrs['class'] += ' fontstrikethrough'; + // }else{ + // node.setAttr('class','fontstrikethrough') + // } + // } + // + // node.setStyle('text-decoration') + // } + // if(val = node.getStyle('border')){ + // if(/1px/.test(val) && /solid/.test(val)){ + // if(node.attrs['class']){ + // node.attrs['class'] += ' fontborder'; + // + // }else{ + // node.setAttr('class','fontborder') + // } + // } + // node.setStyle('border') + // + // } + // }); + // }); + for (var p in fonts) { + (function(cmd, style) { + UE.commands[cmd] = { + execCommand: function(cmdName, value) { + value = + value || + (this.queryCommandState(cmdName) + ? "none" + : cmdName === "underline" + ? "underline" + : cmdName === "fontborder" ? "1px solid #000" : "line-through"); + var me = this, + range = this.selection.getRange(), + text; + + if (value === "default") { + if (range.collapsed) { + text = me.document.createTextNode("font"); + range.insertNode(text).select(); + } + me.execCommand("removeFormat", "span,a", style); + if (text) { + range.setStartBefore(text).collapse(true); + domUtils.remove(text); + } + mergesibling(range, cmdName, value); + range.select(); + } else { + if (!range.collapsed) { + if (needCmd[cmd] && me.queryCommandValue(cmd)) { + me.execCommand("removeFormat", "span,a", style); + } + range = me.selection.getRange(); + + range.applyInlineStyle("span", { style: style + ":" + value }); + mergesibling(range, cmdName, value); + range.select(); + } else { + var span = domUtils.findParentByTagName( + range.startContainer, + "span", + true + ); + text = me.document.createTextNode("font"); + if ( + span && + !span.children.length && + !span[browser.ie ? "innerText" : "textContent"].replace( + fillCharReg, + "" + ).length + ) { + //for ie hack when enter + range.insertNode(text); + if (needCmd[cmd]) { + range.selectNode(text).select(); + me.execCommand("removeFormat", "span,a", style, null); + + span = domUtils.findParentByTagName(text, "span", true); + range.setStartBefore(text); + } + span && (span.style.cssText += ";" + style + ":" + value); + range.collapse(true).select(); + } else { + range.insertNode(text); + range.selectNode(text).select(); + span = range.document.createElement("span"); + + if (needCmd[cmd]) { + //a标签内的不处理跳过 + if (domUtils.findParentByTagName(text, "a", true)) { + range.setStartBefore(text).setCursor(); + domUtils.remove(text); + return; + } + me.execCommand("removeFormat", "span,a", style); + } + + span.style.cssText = style + ":" + value; + + text.parentNode.insertBefore(span, text); + //修复,span套span 但样式不继承的问题 + if (!browser.ie || (browser.ie && browser.version == 9)) { + var spanParent = span.parentNode; + while (!domUtils.isBlockElm(spanParent)) { + if (spanParent.tagName == "SPAN") { + //opera合并style不会加入";" + span.style.cssText = + spanParent.style.cssText + ";" + span.style.cssText; + } + spanParent = spanParent.parentNode; + } + } + + if (opera) { + setTimeout(function() { + range.setStart(span, 0).collapse(true); + mergesibling(range, cmdName, value); + range.select(); + }); + } else { + range.setStart(span, 0).collapse(true); + mergesibling(range, cmdName, value); + range.select(); + } + + //trace:981 + //domUtils.mergeToParent(span) + } + domUtils.remove(text); + } + } + return true; + }, + queryCommandValue: function(cmdName) { + var startNode = this.selection.getStart(); + var styleVal; + + //trace:946 + if (cmdName === "underline" || cmdName === "strikethrough") { + var tmpNode = startNode, + value; + while ( + tmpNode && + !domUtils.isBlockElm(tmpNode) && + !domUtils.isBody(tmpNode) + ) { + if (tmpNode.nodeType == 1) { + value = domUtils.getComputedStyle(tmpNode, style); + if (value != "none") { + return value; + } + } + + tmpNode = tmpNode.parentNode; + } + return "none"; + } + + else if (cmdName === "fontborder") { + var tmp = startNode, + val; + while (tmp && dtd.$inline[tmp.tagName]) { + if ((val = domUtils.getComputedStyle(tmp, "border"))) { + if (/1px/.test(val) && /solid/.test(val)) { + return val; + } + } + tmp = tmp.parentNode; + } + return ""; + } + + else if (cmdName === "FontSize") { + styleVal = domUtils.getComputedStyle(startNode, style); + tmp = /^([\d\.]+)(\w+)$/.exec(styleVal); + + if (tmp) { + return Math.floor(tmp[1]) + tmp[2]; + } + + return styleVal; + } + + else if(cmdName === 'FontFamily'){ + styleVal = domUtils.getComputedStyle(startNode, style) + // 移除左右引号 + styleVal = styleVal.replace(/['"]/g, ''); + var fontFamily = lang.fontfamily.default; + var fontList = me.options["fontfamily"] || []; + for(var i=0;i]/g)); + opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g)); + opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g)); + doLink((range = this.selection.getRange()), opt, this); + //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题 + range.collapse().select(true); + }, + queryCommandValue: function() { + var range = this.selection.getRange(), + node; + if (range.collapsed) { + // node = this.selection.getStart(); + //在ie下getstart()取值偏上了 + node = range.startContainer; + node = node.nodeType == 1 ? node : node.parentNode; + + if ( + node && + (node = domUtils.findParentByTagName(node, "a", true)) && + !domUtils.isInNodeEndBoundary(range, node) + ) { + return node; + } + } else { + //trace:1111 如果是

    xx

    startContainer是p就会找不到a + range.shrinkBoundary(); + var start = range.startContainer.nodeType == 3 || + !range.startContainer.childNodes[range.startOffset] + ? range.startContainer + : range.startContainer.childNodes[range.startOffset], + end = range.endContainer.nodeType == 3 || range.endOffset == 0 + ? range.endContainer + : range.endContainer.childNodes[range.endOffset - 1], + common = range.getCommonAncestor(); + node = domUtils.findParentByTagName(common, "a", true); + if (!node && common.nodeType == 1) { + var as = common.getElementsByTagName("a"), + ps, + pe; + + for (var i = 0, ci; (ci = as[i++]); ) { + (ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition( + ci, + end + )); + if ( + (ps & domUtils.POSITION_FOLLOWING || + ps & domUtils.POSITION_CONTAINS) && + (pe & domUtils.POSITION_PRECEDING || + pe & domUtils.POSITION_CONTAINS) + ) { + node = ci; + break; + } + } + } + return node; + } + }, + queryCommandState: function() { + //判断如果是视频的话连接不可用 + //fix 853 + var img = this.selection.getRange().getClosedNode(), + flag = + img && + (img.className == "edui-faked-video" || + img.className.indexOf("edui-upload-video") != -1); + return flag ? -1 : 0; + } + }; +}; + + +// plugins/iframe.js +///import core +///import plugins\inserthtml.js +///commands 插入框架 +///commandsName InsertFrame +///commandsTitle 插入Iframe +///commandsDialog dialogs\insertframe + +UE.plugins["insertframe"] = function() { + var me = this; + function deleteIframe() { + me._iframe && delete me._iframe; + } + + me.addListener("selectionchange", function() { + deleteIframe(); + }); +}; + + +// plugins/scrawl.js +///import core +///commands 涂鸦 +///commandsName Scrawl +///commandsTitle 涂鸦 +///commandsDialog dialogs\scrawl +UE.commands["scrawl"] = { + queryCommandState: function() { + return browser.ie && browser.version <= 8 ? -1 : 0; + } +}; + + +// plugins/removeformat.js +/** + * 清除格式 + * @file + * @since 1.2.6.1 + */ + +/** + * 清除文字样式 + * @command removeformat + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} tags 以逗号隔开的标签。如:strong + * @param {String} style 样式如:color + * @param {String} attrs 属性如:width + * @example + * ```javascript + * editor.execCommand( 'removeformat', 'strong','color','width' ); + * ``` + */ + +UE.plugins["removeformat"] = function() { + var me = this; + me.setOpt({ + removeFormatTags: + "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var", + removeFormatAttributes: "class,style,lang,width,height,align,hspace,valign" + }); + me.commands["removeformat"] = { + execCommand: function(cmdName, tags, style, attrs, notIncludeA) { + var tagReg = new RegExp( + "^(?:" + + (tags || this.options.removeFormatTags).replace(/,/g, "|") + + ")$", + "i" + ), + removeFormatAttributes = style + ? [] + : (attrs || this.options.removeFormatAttributes).split(","), + range = new dom.Range(this.document), + bookmark, + node, + parent, + filter = function(node) { + return node.nodeType == 1; + }; + + function isRedundantSpan(node) { + if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") { + return 0; + } + if (browser.ie) { + //ie 下判断实效,所以只能简单用style来判断 + //return node.style.cssText == '' ? 1 : 0; + var attrs = node.attributes; + if (attrs.length) { + for (var i = 0, l = attrs.length; i < l; i++) { + if (attrs[i].specified) { + return 0; + } + } + return 1; + } + } + return !node.attributes.length; + } + function doRemove(range) { + var bookmark1 = range.createBookmark(); + if (range.collapsed) { + range.enlarge(true); + } + + //不能把a标签切了 + if (!notIncludeA) { + var aNode = domUtils.findParentByTagName( + range.startContainer, + "a", + true + ); + if (aNode) { + range.setStartBefore(aNode); + } + + aNode = domUtils.findParentByTagName(range.endContainer, "a", true); + if (aNode) { + range.setEndAfter(aNode); + } + } + + bookmark = range.createBookmark(); + + node = bookmark.start; + + //切开始 + while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { + domUtils.breakParent(node, parent); + + domUtils.clearEmptySibling(node); + } + if (bookmark.end) { + //切结束 + node = bookmark.end; + while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { + domUtils.breakParent(node, parent); + domUtils.clearEmptySibling(node); + } + + //开始去除样式 + var current = domUtils.getNextDomNode(bookmark.start, false, filter), + next; + while (current) { + if (current == bookmark.end) { + break; + } + + next = domUtils.getNextDomNode(current, true, filter); + + if ( + !dtd.$empty[current.tagName.toLowerCase()] && + !domUtils.isBookmarkNode(current) + ) { + if (tagReg.test(current.tagName)) { + if (style) { + domUtils.removeStyle(current, style); + if (isRedundantSpan(current) && style != "text-decoration") { + domUtils.remove(current, true); + } + } else { + domUtils.remove(current, true); + } + } else { + //trace:939 不能把list上的样式去掉 + // 清除格式时,默认移除Table、List上的样式 + if ( + true + // !dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName] + ) { + domUtils.removeAttributes(current, removeFormatAttributes); + if (isRedundantSpan(current)) { + domUtils.remove(current, true); + } + }else{ + // console.log('current.ignore',current); + } + } + } + current = next; + } + } + //trace:1035 + //trace:1096 不能把td上的样式去掉,比如边框 + var pN = bookmark.start.parentNode; + if ( + domUtils.isBlockElm(pN) && + !dtd.$tableContent[pN.tagName] && + !dtd.$list[pN.tagName] + ) { + domUtils.removeAttributes(pN, removeFormatAttributes); + } + pN = bookmark.end.parentNode; + if ( + bookmark.end && + domUtils.isBlockElm(pN) && + !dtd.$tableContent[pN.tagName] && + !dtd.$list[pN.tagName] + ) { + domUtils.removeAttributes(pN, removeFormatAttributes); + } + range.moveToBookmark(bookmark).moveToBookmark(bookmark1); + //清除冗余的代码 + var node = range.startContainer, + tmp, + collapsed = range.collapsed; + while ( + node.nodeType == 1 && + domUtils.isEmptyNode(node) && + dtd.$removeEmpty[node.tagName] + ) { + tmp = node.parentNode; + range.setStartBefore(node); + //trace:937 + //更新结束边界 + if (range.startContainer === range.endContainer) { + range.endOffset--; + } + domUtils.remove(node); + node = tmp; + } + + if (!collapsed) { + node = range.endContainer; + while ( + node.nodeType == 1 && + domUtils.isEmptyNode(node) && + dtd.$removeEmpty[node.tagName] + ) { + tmp = node.parentNode; + range.setEndBefore(node); + domUtils.remove(node); + + node = tmp; + } + } + } + + range = this.selection.getRange(); + doRemove(range); + range.select(); + } + }; +}; + + +// plugins/blockquote.js +/** + * 添加引用 + * @file + * @since 1.2.6.1 + */ + +/** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'blockquote' ); + * ``` + */ + +/** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } attrs 节点属性 + * @example + * ```javascript + * editor.execCommand( 'blockquote',{ + * style: "color: red;" + * } ); + * ``` + */ + +UE.plugins["blockquote"] = function() { + var me = this; + function getObj(editor) { + return domUtils.filterNodeList( + editor.selection.getStartElementPath(), + "blockquote" + ); + } + me.commands["blockquote"] = { + execCommand: function(cmdName, attrs) { + var range = this.selection.getRange(), + obj = getObj(this), + blockquote = dtd.blockquote, + bookmark = range.createBookmark(); + + if (obj) { + var start = range.startContainer, + startBlock = domUtils.isBlockElm(start) + ? start + : domUtils.findParent(start, function(node) { + return domUtils.isBlockElm(node); + }), + end = range.endContainer, + endBlock = domUtils.isBlockElm(end) + ? end + : domUtils.findParent(end, function(node) { + return domUtils.isBlockElm(node); + }); + + //处理一下li + startBlock = + domUtils.findParentByTagName(startBlock, "li", true) || startBlock; + endBlock = + domUtils.findParentByTagName(endBlock, "li", true) || endBlock; + + if ( + startBlock.tagName == "LI" || + startBlock.tagName == "TD" || + startBlock === obj || + domUtils.isBody(startBlock) + ) { + domUtils.remove(obj, true); + } else { + domUtils.breakParent(startBlock, obj); + } + + if (startBlock !== endBlock) { + obj = domUtils.findParentByTagName(endBlock, "blockquote"); + if (obj) { + if ( + endBlock.tagName == "LI" || + endBlock.tagName == "TD" || + domUtils.isBody(endBlock) + ) { + obj.parentNode && domUtils.remove(obj, true); + } else { + domUtils.breakParent(endBlock, obj); + } + } + } + + var blockquotes = domUtils.getElementsByTagName( + this.document, + "blockquote" + ); + for (var i = 0, bi; (bi = blockquotes[i++]); ) { + if (!bi.childNodes.length) { + domUtils.remove(bi); + } else if ( + domUtils.getPosition(bi, startBlock) & + domUtils.POSITION_FOLLOWING && + domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING + ) { + domUtils.remove(bi, true); + } + } + } else { + var tmpRange = range.cloneRange(), + node = tmpRange.startContainer.nodeType == 1 + ? tmpRange.startContainer + : tmpRange.startContainer.parentNode, + preNode = node, + doEnd = 1; + + //调整开始 + while (1) { + if (domUtils.isBody(node)) { + if (preNode !== node) { + if (range.collapsed) { + tmpRange.selectNode(preNode); + doEnd = 0; + } else { + tmpRange.setStartBefore(preNode); + } + } else { + tmpRange.setStart(node, 0); + } + + break; + } + if (!blockquote[node.tagName]) { + if (range.collapsed) { + tmpRange.selectNode(preNode); + } else { + tmpRange.setStartBefore(preNode); + } + break; + } + + preNode = node; + node = node.parentNode; + } + + //调整结束 + if (doEnd) { + preNode = node = node = tmpRange.endContainer.nodeType == 1 + ? tmpRange.endContainer + : tmpRange.endContainer.parentNode; + while (1) { + if (domUtils.isBody(node)) { + if (preNode !== node) { + tmpRange.setEndAfter(preNode); + } else { + tmpRange.setEnd(node, node.childNodes.length); + } + + break; + } + if (!blockquote[node.tagName]) { + tmpRange.setEndAfter(preNode); + break; + } + + preNode = node; + node = node.parentNode; + } + } + + node = range.document.createElement("blockquote"); + domUtils.setAttributes(node, attrs); + node.appendChild(tmpRange.extractContents()); + tmpRange.insertNode(node); + //去除重复的 + var childs = domUtils.getElementsByTagName(node, "blockquote"); + for (var i = 0, ci; (ci = childs[i++]); ) { + if (ci.parentNode) { + domUtils.remove(ci, true); + } + } + } + range.moveToBookmark(bookmark).select(); + }, + queryCommandState: function() { + return getObj(this) ? 1 : 0; + } + }; +}; + + +// plugins/convertcase.js +/** + * 大小写转换 + * @file + * @since 1.2.6.1 + */ + +/** + * 把选区内文本变大写,与“tolowercase”命令互斥 + * @command touppercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'touppercase' ); + * ``` + */ + +/** + * 把选区内文本变小写,与“touppercase”命令互斥 + * @command tolowercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'tolowercase' ); + * ``` + */ +UE.commands["touppercase"] = UE.commands["tolowercase"] = { + execCommand: function(cmd) { + var me = this; + var rng = me.selection.getRange(); + if (rng.collapsed) { + return rng; + } + var bk = rng.createBookmark(), + bkEnd = bk.end, + filterFn = function(node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }, + curNode = domUtils.getNextDomNode(bk.start, false, filterFn); + while ( + curNode && + domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING + ) { + if (curNode.nodeType == 3) { + curNode.nodeValue = curNode.nodeValue[ + cmd == "touppercase" ? "toUpperCase" : "toLowerCase" + ](); + } + curNode = domUtils.getNextDomNode(curNode, true, filterFn); + if (curNode === bkEnd) { + break; + } + } + rng.moveToBookmark(bk).select(); + } +}; + + +// plugins/indent.js +/** + * 首行缩进 + * @file + * @since 1.2.6.1 + */ + +/** + * 缩进 + * @command indent + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'indent' ); + * ``` + */ +UE.commands["indent"] = { + execCommand: function() { + var me = this, + value = me.queryCommandState("indent") + ? "0em" + : me.options.indentValue || "2em"; + me.execCommand("Paragraph", "p", { style: "text-indent:" + value }); + }, + queryCommandState: function() { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + "p h1 h2 h3 h4 h5 h6" + ); + return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0; + } +}; + + +// plugins/print.js +/** + * 打印 + * @file + * @since 1.2.6.1 + */ + +/** + * 打印 + * @command print + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'print' ); + * ``` + */ +UE.commands["print"] = { + execCommand: function() { + this.window.print(); + }, + notNeedUndo: 1 +}; + + +// plugins/preview.js +/** + * 预览 + * @file + * @since 1.2.6.1 + */ + +/** + * 预览 + * @command preview + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'preview' ); + * ``` + */ +UE.commands["preview"] = { + execCommand: function() { + var w = window.open("", "_blank", ""), + d = w.document; + d.open(); + d.write( + '
    " + + this.getContent(null, null, true) + + "
    " + ); + d.close(); + }, + notNeedUndo: 1 +}; + + +// plugins/selectall.js +/** + * 全选 + * @file + * @since 1.2.6.1 + */ + +/** + * 选中所有内容 + * @command selectall + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'selectall' ); + * ``` + */ +UE.plugins["selectall"] = function() { + var me = this; + me.commands["selectall"] = { + execCommand: function() { + //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 + var me = this, + body = me.body, + range = me.selection.getRange(); + range.selectNodeContents(body); + if (domUtils.isEmptyBlock(body)) { + //opera不能自动合并到元素的里边,要手动处理一下 + if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) { + range.setStartAtFirst(body.firstChild); + } + range.collapse(true); + } + range.select(true); + }, + notNeedUndo: 1 + }; + + //快捷键 + me.addshortcutkey({ + selectAll: "ctrl+65" + }); +}; + + +// plugins/paragraph.js +/** + * 段落样式 + * @file + * @since 1.2.6.1 + */ + +/** + * 段落格式 + * @command paragraph + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + * @param {Object} attrs 标签的属性 + * @example + * ```javascript + * editor.execCommand( 'Paragraph','h1','{ + * class:'test' + * }' ); + * ``` + */ + +/** + * 返回选区内节点标签名 + * @command paragraph + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 节点标签名 + * @example + * ```javascript + * editor.queryCommandValue( 'Paragraph' ); + * ``` + */ + +UE.plugins["paragraph"] = function() { + var me = this, + block = domUtils.isBlockElm, + notExchange = ["TD", "LI", "PRE"], + doParagraph = function(range, style, attrs, sourceCmdName) { + var bookmark = range.createBookmark(), + filterFn = function(node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" && + !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }, + para; + + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType === 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + + para = range.document.createElement(style); + if (attrs) { + domUtils.setAttributes(para, attrs); + if ( + sourceCmdName && + sourceCmdName === "customstyle" && + attrs.style + ) { + para.style.cssText = attrs.style; + } + } + para.appendChild(tmpRange.extractContents()); + //需要内容占位 + if (domUtils.isEmptyNode(para)) { + domUtils.fillChar(range.document, para); + } + + tmpRange.insertNode(para); + + var parent = para.parentNode; + //如果para上一级是一个block元素且不是body,td就删除它 + if ( + block(parent) && + !domUtils.isBody(para.parentNode) && + utils.indexOf(notExchange, parent.tagName) === -1 + ) { + //存储dir,style + if (!(sourceCmdName && sourceCmdName === "customstyle")) { + parent.getAttribute("dir") && + para.setAttribute("dir", parent.getAttribute("dir")); + //trace:1070 + parent.style.cssText && + (para.style.cssText = + parent.style.cssText + ";" + para.style.cssText); + //trace:1030 + parent.style.textAlign && + !para.style.textAlign && + (para.style.textAlign = parent.style.textAlign); + parent.style.textIndent && + !para.style.textIndent && + (para.style.textIndent = parent.style.textIndent); + parent.style.padding && + !para.style.padding && + (para.style.padding = parent.style.padding); + } + + //trace:1706 选择的就是h1-6要删除 + if ( + attrs && + /h\d/i.test(parent.tagName) && + !/h\d/i.test(para.tagName) + ) { + domUtils.setAttributes(parent, attrs); + if ( + sourceCmdName && + sourceCmdName === "customstyle" && + attrs.style + ) { + parent.style.cssText = attrs.style; + } + domUtils.remove(para.parentNode, true); + para = parent; + } else { + domUtils.remove(para.parentNode, true); + } + } + if (utils.indexOf(notExchange, parent.tagName) !== -1) { + current = parent; + } else { + current = para; + } + + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + me.setOpt("paragraph", { + p: "", + h1: "", + h2: "", + h3: "", + h4: "", + h5: "", + h6: "" + }); + me.commands["paragraph"] = { + execCommand: function(cmdName, style, attrs, sourceCmdName) { + var range = this.selection.getRange(); + //闭合时单独处理 + if (range.collapsed) { + var txt = this.document.createTextNode("p"); + range.insertNode(txt); + //去掉冗余的fillchar + if (browser.ie) { + var node = txt.previousSibling; + if (node && domUtils.isWhitespace(node)) { + domUtils.remove(node); + } + node = txt.nextSibling; + if (node && domUtils.isWhitespace(node)) { + domUtils.remove(node); + } + } + } + range = doParagraph(range, style, attrs, sourceCmdName); + if (txt) { + range.setStartBefore(txt).collapse(true); + pN = txt.parentNode; + + domUtils.remove(txt); + + if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) { + domUtils.fillNode(this.document, pN); + } + } + + if ( + browser.gecko && + range.collapsed && + range.startContainer.nodeType === 1 + ) { + var child = range.startContainer.childNodes[range.startOffset]; + if ( + child && + child.nodeType === 1 && + child.tagName.toLowerCase() === style + ) { + range.setStart(child, 0).collapse(true); + } + } + //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了 + range.select(); + + return true; + }, + queryCommandValue: function() { + var node = domUtils.filterNodeList( + this.selection.getStartElementPath(), + "p h1 h2 h3 h4 h5 h6" + ); + return node ? node.tagName.toLowerCase() : ""; + } + }; +}; + + +// plugins/directionality.js +/** + * 设置文字输入的方向的插件 + * @file + * @since 1.2.6.1 + */ +(function() { + var block = domUtils.isBlockElm, + getObj = function(editor) { + // var startNode = editor.selection.getStart(), + // parents; + // if ( startNode ) { + // //查找所有的是block的父亲节点 + // parents = domUtils.findParents( startNode, true, block, true ); + // for ( var i = 0,ci; ci = parents[i++]; ) { + // if ( ci.getAttribute( 'dir' ) ) { + // return ci; + // } + // } + // } + return domUtils.filterNodeList( + editor.selection.getStartElementPath(), + function(n) { + return n && n.nodeType == 1 && n.getAttribute("dir"); + } + ); + }, + doDirectionality = function(range, editor, forward) { + var bookmark, + filterFn = function(node) { + return node.nodeType == 1 + ? !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }, + obj = getObj(editor); + + if (obj && range.collapsed) { + obj.setAttribute("dir", forward); + return range; + } + bookmark = range.createBookmark(); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType == 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + var common = tmpRange.getCommonAncestor(); + if (!domUtils.isBody(common) && block(common)) { + //遍历到了block节点 + common.setAttribute("dir", forward); + current = common; + } else { + //没有遍历到,添加一个block节点 + var p = range.document.createElement("p"); + p.setAttribute("dir", forward); + var frag = tmpRange.extractContents(); + p.appendChild(frag); + tmpRange.insertNode(p); + current = p; + } + + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + + /** + * 文字输入方向 + * @command directionality + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.execCommand( 'directionality', 'ltr'); + * ``` + */ + + /** + * 查询当前选区的文字输入方向 + * @command directionality + * @method queryCommandValue + * @param { String } cmdName 命令字符串 + * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.queryCommandValue( 'directionality'); + * ``` + */ + UE.commands["directionality"] = { + execCommand: function(cmdName, forward) { + var range = this.selection.getRange(); + //闭合时单独处理 + if (range.collapsed) { + var txt = this.document.createTextNode("d"); + range.insertNode(txt); + } + doDirectionality(range, this, forward); + if (txt) { + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + return true; + }, + queryCommandValue: function() { + var node = getObj(this); + return node ? node.getAttribute("dir") : "ltr"; + } + }; +})(); + + +// plugins/horizontal.js +/** + * 插入分割线插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入分割线 + * @command horizontal + * @method execCommand + * @param { String } cmdName 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'horizontal' ); + * ``` + */ +UE.plugins["horizontal"] = function() { + var me = this; + me.commands["horizontal"] = { + execCommand: function(cmdName) { + var me = this; + if (me.queryCommandState(cmdName) !== -1) { + me.execCommand("insertHtml", "
    "); + var range = me.selection.getRange(), + start = range.startContainer; + if (start.nodeType == 1 && !start.childNodes[range.startOffset]) { + var tmp; + if ((tmp = start.childNodes[range.startOffset - 1])) { + if (tmp.nodeType == 1 && tmp.tagName == "HR") { + if (me.options.enterTag == "p") { + tmp = me.document.createElement("p"); + range.insertNode(tmp); + range.setStart(tmp, 0).setCursor(); + } else { + tmp = me.document.createElement("br"); + range.insertNode(tmp); + range.setStartBefore(tmp).setCursor(); + } + } + } + } + return true; + } + }, + //边界在table里不能加分隔线 + queryCommandState: function() { + return domUtils.filterNodeList( + this.selection.getStartElementPath(), + "table" + ) + ? -1 + : 0; + } + }; + // me.addListener('delkeyup',function(){ + // var rng = this.selection.getRange(); + // if(browser.ie && browser.version > 8){ + // rng.txtToElmBoundary(true); + // if(domUtils.isStartInblock(rng)){ + // var tmpNode = rng.startContainer; + // var pre = tmpNode.previousSibling; + // if(pre && domUtils.isTagNode(pre,'hr')){ + // domUtils.remove(pre); + // rng.select(); + // return; + // } + // } + // } + // if(domUtils.isBody(rng.startContainer)){ + // var hr = rng.startContainer.childNodes[rng.startOffset -1]; + // if(hr && hr.nodeName == 'HR'){ + // var next = hr.nextSibling; + // if(next){ + // rng.setStart(next,0) + // }else if(hr.previousSibling){ + // rng.setStartAtLast(hr.previousSibling) + // }else{ + // var p = this.document.createElement('p'); + // hr.parentNode.insertBefore(p,hr); + // domUtils.fillNode(this.document,p); + // rng.setStart(p,0); + // } + // domUtils.remove(hr); + // rng.setCursor(false,true); + // } + // } + // }) + me.addListener("delkeydown", function(name, evt) { + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + if (domUtils.isStartInblock(rng)) { + var tmpNode = rng.startContainer; + var pre = tmpNode.previousSibling; + if (pre && domUtils.isTagNode(pre, "hr")) { + domUtils.remove(pre); + rng.select(); + domUtils.preventDefault(evt); + return true; + } + } + }); +}; + + +// plugins/time.js +/** + * 插入时间和日期 + * @file + * @since 1.2.6.1 + */ + +/** + * 插入时间,默认格式:12:59:59 + * @command time + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'time'); + * ``` + */ + +/** + * 插入日期,默认格式:2013-08-30 + * @command date + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'date'); + * ``` + */ +UE.commands["time"] = UE.commands["date"] = { + execCommand: function(cmd, format) { + var date = new Date(); + + function formatTime(date, format) { + var hh = ("0" + date.getHours()).slice(-2), + ii = ("0" + date.getMinutes()).slice(-2), + ss = ("0" + date.getSeconds()).slice(-2); + format = format || "hh:ii:ss"; + return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss); + } + function formatDate(date, format) { + var yyyy = ("000" + date.getFullYear()).slice(-4), + yy = yyyy.slice(-2), + mm = ("0" + (date.getMonth() + 1)).slice(-2), + dd = ("0" + date.getDate()).slice(-2); + format = format || "yyyy-mm-dd"; + return format + .replace(/yyyy/gi, yyyy) + .replace(/yy/gi, yy) + .replace(/mm/gi, mm) + .replace(/dd/gi, dd); + } + + this.execCommand( + "insertHtml", + cmd == "time" ? formatTime(date, format) : formatDate(date, format) + ); + } +}; + + +// plugins/rowspacing.js +/** + * 段前段后间距插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 设置段间距 + * @command rowspacing + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 段间距的值,以px为单位 + * @param { String } dir 间距位置,top或bottom,分别表示段前和段后 + * @example + * ```javascript + * editor.execCommand( 'rowspacing', '10', 'top' ); + * ``` + */ + +UE.plugins["rowspacing"] = function() { + var me = this; + me.setOpt({ + rowspacingtop: ["5", "10", "15", "20", "25"], + rowspacingbottom: ["5", "10", "15", "20", "25"] + }); + me.commands["rowspacing"] = { + execCommand: function(cmdName, value, dir) { + this.execCommand("paragraph", "p", { + style: "margin-" + dir + ":" + value + "px" + }); + return true; + }, + queryCommandValue: function(cmdName, dir) { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + function(node) { + return domUtils.isBlockElm(node); + } + ), + value; + //trace:1026 + if (pN) { + value = domUtils + .getComputedStyle(pN, "margin-" + dir) + .replace(/[^\d]/g, ""); + return !value ? 0 : value; + } + return 0; + } + }; +}; + + +// plugins/lineheight.js +/** + * 设置行内间距 + * @file + * @since 1.2.6.1 + */ +UE.plugins["lineheight"] = function() { + var me = this; + me.setOpt({ lineheight: ["1", "1.5", "1.75", "2", "3", "4", "5"] }); + + /** + * 行距 + * @command lineheight + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75 + * @example + * ```javascript + * editor.execCommand( 'lineheight', 1.5); + * ``` + */ + /** + * 查询当前选区内容的行高大小 + * @command lineheight + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前行高大小 + * @example + * ```javascript + * editor.queryCommandValue( 'lineheight' ); + * ``` + */ + + me.commands["lineheight"] = { + execCommand: function(cmdName, value) { + this.execCommand("paragraph", "p", { + style: "line-height:" + (value == "1" ? "normal" : value + "em") + }); + return true; + }, + queryCommandValue: function() { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + function(node) { + return domUtils.isBlockElm(node); + } + ); + if (pN) { + var value = domUtils.getComputedStyle(pN, "line-height"); + return value == "normal" ? 1 : value.replace(/[^\d.]*/gi, ""); + } + } + }; +}; + + +// plugins/insertcode.js +/** + * 插入代码插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins["insertcode"] = function() { + var me = this; + me.setOpt("insertcode", { + as3: "ActionScript3", + bash: "Bash/Shell", + cpp: "C/C++", + css: "Css", + // cf: "CodeFunction", + "c#": "C#", + delphi: "Delphi", + // diff: "Diff", + erlang: "Erlang", + groovy: "Groovy", + html: "Html", + java: "Java", + // jfx: "JavaFx", + js: "Javascript", + pl: "Perl", + php: "PHP", + plain: "Text", + ps: "PowerShell", + python: "Python", + ruby: "Ruby", + scala: "Scala", + sql: "SQL", + vb: "VB", + xml: "XML", + mind: "Mind", + }); + + /** + * 插入代码 + * @command insertcode + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } lang 插入代码的语言 + * @example + * ```javascript + * editor.execCommand( 'insertcode', 'javascript' ); + * ``` + */ + + /** + * 如果选区所在位置是插入插入代码区域,返回代码的语言 + * @command insertcode + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回代码的语言 + * @example + * ```javascript + * editor.queryCommandValue( 'insertcode' ); + * ``` + */ + + me.commands["insertcode"] = { + execCommand: function(cmd, lang) { + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + pre.className = "brush:" + lang + ";toolbar:false;"; + } else { + var code = ""; + if (rng.collapsed) { + code = browser.ie && browser.ie11below + ? browser.version <= 8 ? " " : "" + : "
    "; + } else { + var frag = rng.extractContents(); + var div = me.document.createElement("div"); + div.appendChild(frag); + + utils.each( + UE.filterNode( + UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), + me.options.filterTxtRules + ).children, + function(node) { + if (browser.ie && browser.ie11below && browser.version > 8) { + if (node.type == "element") { + if (node.tagName == "br") { + code += "\n"; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function(cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + code += "\n"; + } else if (!dtd.$empty[node.tagName]) { + code += cn.innerText(); + } + } else { + code += cn.data; + } + }); + if (!/\n$/.test(code)) { + code += "\n"; + } + } + } else { + code += node.data + "\n"; + } + if (!node.nextSibling() && /\n$/.test(code)) { + code = code.replace(/\n$/, ""); + } + } else { + if (browser.ie && browser.ie11below) { + if (node.type == "element") { + if (node.tagName == "br") { + code += "
    "; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function(cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + code += "
    "; + } else if (!dtd.$empty[node.tagName]) { + code += cn.innerText(); + } + } else { + code += cn.data; + } + }); + if (!/br>$/.test(code)) { + code += "
    "; + } + } + } else { + code += node.data + "
    "; + } + if (!node.nextSibling() && /
    $/.test(code)) { + code = code.replace(/
    $/, ""); + } + } else { + code += node.type == "element" + ? dtd.$empty[node.tagName] ? "" : node.innerText() + : node.data; + if (!/br\/?\s*>$/.test(code)) { + if (!node.nextSibling()) return; + code += "
    "; + } + } + } + } + ); + } + me.execCommand( + "inserthtml", + '
    ' +
    +            code +
    +            "
    ", + true + ); + + pre = me.document.getElementById("coder"); + domUtils.removeAttributes(pre, "id"); + var tmpNode = pre.previousSibling; + + if ( + tmpNode && + ((tmpNode.nodeType == 3 && + tmpNode.nodeValue.length == 1 && + browser.ie && + browser.version == 6) || + domUtils.isEmptyBlock(tmpNode)) + ) { + domUtils.remove(tmpNode); + } + var rng = me.selection.getRange(); + if (domUtils.isEmptyBlock(pre)) { + rng.setStart(pre, 0).setCursor(false, true); + } else { + rng.selectNodeContents(pre).select(); + } + } + }, + queryCommandValue: function() { + var path = this.selection.getStartElementPath(); + var lang = ""; + utils.each(path, function(node) { + if (node.nodeName == "PRE") { + var match = node.className.match(/brush:([^;]+)/); + lang = match && match[1] ? match[1] : ""; + return false; + } + }); + return lang; + } + }; + + me.addInputRule(function(root) { + utils.each(root.getNodesByTagName("pre"), function(pre) { + var brs = pre.getNodesByTagName("br"); + if (brs.length) { + browser.ie && + browser.ie11below && + browser.version > 8 && + utils.each(brs, function(br) { + var txt = UE.uNode.createText("\n"); + br.parentNode.insertBefore(txt, br); + br.parentNode.removeChild(br); + }); + return; + } + if (browser.ie && browser.ie11below && browser.version > 8) return; + var code = pre.innerText().split(/\n/); + pre.innerHTML(""); + utils.each(code, function(c) { + if (c.length) { + pre.appendChild(UE.uNode.createText(c)); + } + pre.appendChild(UE.uNode.createElement("br")); + }); + }); + }); + me.addOutputRule(function(root) { + utils.each(root.getNodesByTagName("pre"), function(pre) { + var code = ""; + utils.each(pre.children, function(n) { + if (n.type == "text") { + //在ie下文本内容有可能末尾带有\n要去掉 + //trace:3396 + code += n.data.replace(/[ ]/g, " ").replace(/\n$/, ""); + } else { + if (n.tagName == "br") { + code += "\n"; + } else { + code += !dtd.$empty[n.tagName] ? "" : n.innerText(); + } + } + }); + + pre.innerText(code.replace(/( |\n)+$/, "")); + }); + }); + //不需要判断highlight的command列表 + me.notNeedCodeQuery = { + help: 1, + undo: 1, + redo: 1, + source: 1, + print: 1, + searchreplace: 1, + fullscreen: 1, + preview: 1, + insertparagraph: 1, + elementpath: 1, + insertcode: 1, + inserthtml: 1, + selectall: 1 + }; + //将queyCommamndState重置 + var orgQuery = me.queryCommandState; + me.queryCommandState = function(cmd) { + var me = this; + + if ( + !me.notNeedCodeQuery[cmd.toLowerCase()] && + me.selection && + me.queryCommandValue("insertcode") + ) { + return -1; + } + return UE.Editor.prototype.queryCommandState.apply(this, arguments); + }; + me.addListener("beforeenterkeydown", function() { + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + me.fireEvent("saveScene"); + if (!rng.collapsed) { + rng.deleteContents(); + } + if (!browser.ie || browser.ie9above) { + var tmpNode = me.document.createElement("br"), + pre; + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true); + var next = tmpNode.nextSibling; + if (!next && (!browser.ie || browser.version > 10)) { + rng.insertNode(tmpNode.cloneNode(false)); + } else { + rng.setStartAfter(tmpNode); + } + pre = tmpNode.previousSibling; + var tmp; + while (pre) { + tmp = pre; + pre = pre.previousSibling; + if (!pre || pre.nodeName == "BR") { + pre = tmp; + break; + } + } + if (pre) { + var str = ""; + while ( + pre && + pre.nodeName != "BR" && + new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue) + ) { + str += pre.nodeValue; + pre = pre.nextSibling; + } + if (pre.nodeName != "BR") { + var match = pre.nodeValue.match( + new RegExp("^([\\s" + domUtils.fillChar + "]+)") + ); + if (match && match[1]) { + str += match[1]; + } + } + if (str) { + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + } + rng.collapse(true).select(true); + } else { + if (browser.version > 8) { + var txt = me.document.createTextNode("\n"); + var start = rng.startContainer; + if (rng.startOffset == 0) { + var preNode = start.previousSibling; + if (preNode) { + rng.insertNode(txt); + var fillchar = me.document.createTextNode(" "); + rng + .setStartAfter(txt) + .insertNode(fillchar) + .setStart(fillchar, 0) + .collapse(true) + .select(true); + } + } else { + rng.insertNode(txt).setStartAfter(txt); + var fillchar = me.document.createTextNode(" "); + start = rng.startContainer.childNodes[rng.startOffset]; + if (start && !/^\n/.test(start.nodeValue)) { + rng.setStartBefore(txt); + } + rng + .insertNode(fillchar) + .setStart(fillchar, 0) + .collapse(true) + .select(true); + } + } else { + var tmpNode = me.document.createElement("br"); + rng.insertNode(tmpNode); + rng.insertNode(me.document.createTextNode(domUtils.fillChar)); + rng.setStartAfter(tmpNode); + pre = tmpNode.previousSibling; + var tmp; + while (pre) { + tmp = pre; + pre = pre.previousSibling; + if (!pre || pre.nodeName == "BR") { + pre = tmp; + break; + } + } + if (pre) { + var str = ""; + while ( + pre && + pre.nodeName != "BR" && + new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue) + ) { + str += pre.nodeValue; + pre = pre.nextSibling; + } + if (pre.nodeName != "BR") { + var match = pre.nodeValue.match( + new RegExp("^([ " + domUtils.fillChar + "]+)") + ); + if (match && match[1]) { + str += match[1]; + } + } + + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + rng.collapse(true).select(); + } + } + me.fireEvent("saveScene"); + return true; + } + }); + + me.addListener("tabkeydown", function(cmd, evt) { + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + me.fireEvent("saveScene"); + if (evt.shiftKey) { + } else { + if (!rng.collapsed) { + var bk = rng.createBookmark(); + var start = bk.start.previousSibling; + + while (start) { + if (pre.firstChild === start && !domUtils.isBr(start)) { + pre.insertBefore(me.document.createTextNode(" "), start); + + break; + } + if (domUtils.isBr(start)) { + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + + break; + } + start = start.previousSibling; + } + var end = bk.end; + start = bk.start.nextSibling; + if (pre.firstChild === bk.start) { + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + } + while (start && start !== end) { + if (domUtils.isBr(start) && start.nextSibling) { + if (start.nextSibling === end) { + break; + } + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + } + + start = start.nextSibling; + } + rng.moveToBookmark(bk).select(); + } else { + var tmpNode = me.document.createTextNode(" "); + rng + .insertNode(tmpNode) + .setStartAfter(tmpNode) + .collapse(true) + .select(true); + } + } + + me.fireEvent("saveScene"); + return true; + } + }); + + me.addListener("beforeinserthtml", function(evtName, html) { + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + if (!rng.collapsed) { + rng.deleteContents(); + } + var htmlstr = ""; + if (browser.ie && browser.version > 8) { + utils.each( + UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) + .children, + function(node) { + if (node.type == "element") { + if (node.tagName == "br") { + htmlstr += "\n"; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function(cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + htmlstr += "\n"; + } else if (!dtd.$empty[node.tagName]) { + htmlstr += cn.innerText(); + } + } else { + htmlstr += cn.data; + } + }); + if (!/\n$/.test(htmlstr)) { + htmlstr += "\n"; + } + } + } else { + htmlstr += node.data + "\n"; + } + if (!node.nextSibling() && /\n$/.test(htmlstr)) { + htmlstr = htmlstr.replace(/\n$/, ""); + } + } + ); + var tmpNode = me.document.createTextNode( + utils.html(htmlstr.replace(/ /g, " ")) + ); + rng.insertNode(tmpNode).selectNode(tmpNode).select(); + } else { + var frag = me.document.createDocumentFragment(); + + utils.each( + UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) + .children, + function(node) { + if (node.type == "element") { + if (node.tagName == "br") { + frag.appendChild(me.document.createElement("br")); + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function(cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + frag.appendChild(me.document.createElement("br")); + } else if (!dtd.$empty[node.tagName]) { + frag.appendChild( + me.document.createTextNode( + utils.html(cn.innerText().replace(/ /g, " ")) + ) + ); + } + } else { + frag.appendChild( + me.document.createTextNode( + utils.html(cn.data.replace(/ /g, " ")) + ) + ); + } + }); + if (frag.lastChild.nodeName != "BR") { + frag.appendChild(me.document.createElement("br")); + } + } + } else { + frag.appendChild( + me.document.createTextNode( + utils.html(node.data.replace(/ /g, " ")) + ) + ); + } + if (!node.nextSibling() && frag.lastChild.nodeName == "BR") { + frag.removeChild(frag.lastChild); + } + } + ); + rng.insertNode(frag).select(); + } + + return true; + } + }); + //方向键的处理 + me.addListener("keydown", function(cmd, evt) { + var me = this, + keyCode = evt.keyCode || evt.which; + if (keyCode == 40) { + var rng = me.selection.getRange(), + pre, + start = rng.startContainer; + if ( + rng.collapsed && + (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && + !pre.nextSibling + ) { + var last = pre.lastChild; + while (last && last.nodeName == "BR") { + last = last.previousSibling; + } + if ( + last === start || + (rng.startContainer === pre && + rng.startOffset == pre.childNodes.length) + ) { + me.execCommand("insertparagraph"); + domUtils.preventDefault(evt); + } + } + } + }); + //trace:3395 + me.addListener("delkeydown", function(type, evt) { + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + var start = rng.startContainer; + if ( + domUtils.isTagNode(start, "pre") && + rng.collapsed && + domUtils.isStartInblock(rng) + ) { + var p = me.document.createElement("p"); + domUtils.fillNode(me.document, p); + start.parentNode.insertBefore(p, start); + domUtils.remove(start); + rng.setStart(p, 0).setCursor(false, true); + domUtils.preventDefault(evt); + return true; + } + }); +}; + + +// plugins/cleardoc.js +/** + * 清空文档插件 + * @file + * @since 1.2.6.1 + */ + +/** + * 清空文档 + * @command cleardoc + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('cleardoc'); + * ``` + */ + +UE.commands["cleardoc"] = { + execCommand: function(cmdName) { + var me = this, + enterTag = me.options.enterTag, + range = me.selection.getRange(); + if (enterTag == "br") { + me.body.innerHTML = "
    "; + range.setStart(me.body, 0).setCursor(); + } else { + me.body.innerHTML = "

    " + (ie ? "" : "
    ") + "

    "; + range.setStart(me.body.firstChild, 0).setCursor(false, true); + } + setTimeout(function() { + me.fireEvent("clearDoc"); + }, 0); + } +}; + + +// plugins/anchor.js +/** + * 锚点插件,为UEditor提供插入锚点支持 + * @file + * @since 1.2.6.1 + */ +UE.plugin.register("anchor", function() { + return { + bindEvents: { + ready: function() { + utils.cssRule( + "anchor", + ".anchorclass{background: url('" + + this.options.themePath + + this.options.theme + + "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}", + this.document + ); + } + }, + outputRule: function(root) { + utils.each(root.getNodesByTagName("img"), function(a) { + var val; + if ((val = a.getAttr("anchorname"))) { + a.tagName = "a"; + a.setAttr({ + anchorname: "", + name: val, + class: "" + }); + } + }); + }, + inputRule: function(root) { + utils.each(root.getNodesByTagName("a"), function(a) { + var val; + if ((val = a.getAttr("name")) && !a.getAttr("href")) { + //过滤掉word冗余标签 + //_Toc\d+有可能勿命中 + if (/^\_Toc\d+$/.test(val)) { + a.parentNode.removeChild(a); + return; + } + a.tagName = "img"; + a.setAttr({ + anchorname: a.getAttr("name"), + class: "anchorclass" + }); + a.setAttr("name"); + } + }); + }, + commands: { + /** + * 插入锚点 + * @command anchor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } name 锚点名称字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('anchor', 'anchor1'); + * ``` + */ + anchor: { + execCommand: function(cmd, name) { + var range = this.selection.getRange(), + img = range.getClosedNode(); + if (img && img.getAttribute("anchorname")) { + if (name) { + img.setAttribute("anchorname", name); + } else { + range.setStartBefore(img).setCursor(); + domUtils.remove(img); + } + } else { + if (name) { + //只在选区的开始插入 + var anchor = this.document.createElement("img"); + range.collapse(true); + domUtils.setAttributes(anchor, { + anchorname: name, + class: "anchorclass" + }); + range + .insertNode(anchor) + .setStartAfter(anchor) + .setCursor(false, true); + } + } + } + } + } + }; +}); + + +// plugins/wordcount.js +///import core +///commands 字数统计 +///commandsName WordCount,wordCount +///commandsTitle 字数统计 +/* + * Created by JetBrains WebStorm. + * User: taoqili + * Date: 11-9-7 + * Time: 下午8:18 + * To change this template use File | Settings | File Templates. + */ + +UE.plugins["wordcount"] = function() { + var me = this; + me.setOpt("wordCount", true); + me.addListener("contentchange", function() { + me.fireEvent("wordcount"); + }); + var timer; + me.addListener("ready", function() { + var me = this; + domUtils.on(me.body, "keyup", function(evt) { + var code = evt.keyCode || evt.which, + //忽略的按键,ctr,alt,shift,方向键 + ignores = { + "16": 1, + "18": 1, + "20": 1, + "37": 1, + "38": 1, + "39": 1, + "40": 1 + }; + if (code in ignores) return; + clearTimeout(timer); + timer = setTimeout(function() { + me.fireEvent("wordcount"); + }, 200); + }); + }); +}; + + +// plugins/pagebreak.js +/** + * 分页功能插件 + * @file + * @since 1.2.6.1 + */ +UE.plugins["pagebreak"] = function() { + var me = this, + notBreakTags = ["td"]; + me.setOpt("pageBreakTag", "_ueditor_page_break_tag_"); + + function fillNode(node) { + if (domUtils.isEmptyBlock(node)) { + var firstChild = node.firstChild, + tmpNode; + + while ( + firstChild && + firstChild.nodeType == 1 && + domUtils.isEmptyBlock(firstChild) + ) { + tmpNode = firstChild; + firstChild = firstChild.firstChild; + } + !tmpNode && (tmpNode = node); + domUtils.fillNode(me.document, tmpNode); + } + } + //分页符样式添加 + + me.ready(function() { + utils.cssRule( + "pagebreak", + ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", + me.document + ); + }); + function isHr(node) { + return ( + node && + node.nodeType == 1 && + node.tagName == "HR" && + node.className == "pagebreak" + ); + } + me.addInputRule(function(root) { + root.traversal(function(node) { + if (node.type == "text" && node.data == me.options.pageBreakTag) { + var hr = UE.uNode.createElement( + '
    ' + ); + node.parentNode.insertBefore(hr, node); + node.parentNode.removeChild(node); + } + }); + }); + me.addOutputRule(function(node) { + utils.each(node.getNodesByTagName("hr"), function(n) { + if (n.getAttr("class") == "pagebreak") { + var txt = UE.uNode.createText(me.options.pageBreakTag); + n.parentNode.insertBefore(txt, n); + n.parentNode.removeChild(n); + } + }); + }); + + /** + * 插入分页符 + * @command pagebreak + * @method execCommand + * @param { String } cmd 命令字符串 + * @remind 在表格中插入分页符会把表格切分成两部分 + * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串, + * 以便于提交数据到服务器端后处理分页。 + * @example + * ```javascript + * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak + * ``` + */ + + me.commands["pagebreak"] = { + execCommand: function() { + var range = me.selection.getRange(), + hr = me.document.createElement("hr"); + domUtils.setAttributes(hr, { + class: "pagebreak", + noshade: "noshade", + size: "5" + }); + domUtils.unSelectable(hr); + //table单独处理 + var node = domUtils.findParentByTagName( + range.startContainer, + notBreakTags, + true + ), + parents = [], + pN; + if (node) { + switch (node.tagName) { + case "TD": + pN = node.parentNode; + if (!pN.previousSibling) { + var table = domUtils.findParentByTagName(pN, "table"); + // var tableWrapDiv = table.parentNode; + // if(tableWrapDiv && tableWrapDiv.nodeType == 1 + // && tableWrapDiv.tagName == 'DIV' + // && tableWrapDiv.getAttribute('dropdrag') + // ){ + // domUtils.remove(tableWrapDiv,true); + // } + table.parentNode.insertBefore(hr, table); + parents = domUtils.findParents(hr, true); + } else { + pN.parentNode.insertBefore(hr, pN); + parents = domUtils.findParents(hr); + } + pN = parents[1]; + if (hr !== pN) { + domUtils.breakParent(hr, pN); + } + //table要重写绑定一下拖拽 + me.fireEvent("afteradjusttable", me.document); + } + } else { + if (!range.collapsed) { + range.deleteContents(); + var start = range.startContainer; + while ( + !domUtils.isBody(start) && + domUtils.isBlockElm(start) && + domUtils.isEmptyNode(start) + ) { + range.setStartBefore(start).collapse(true); + domUtils.remove(start); + start = range.startContainer; + } + } + range.insertNode(hr); + + var pN = hr.parentNode, + nextNode; + while (!domUtils.isBody(pN)) { + domUtils.breakParent(hr, pN); + nextNode = hr.nextSibling; + if (nextNode && domUtils.isEmptyBlock(nextNode)) { + domUtils.remove(nextNode); + } + pN = hr.parentNode; + } + nextNode = hr.nextSibling; + var pre = hr.previousSibling; + if (isHr(pre)) { + domUtils.remove(pre); + } else { + pre && fillNode(pre); + } + + if (!nextNode) { + var p = me.document.createElement("p"); + + hr.parentNode.appendChild(p); + domUtils.fillNode(me.document, p); + range.setStart(p, 0).collapse(true); + } else { + if (isHr(nextNode)) { + domUtils.remove(nextNode); + } else { + fillNode(nextNode); + } + range.setEndAfter(hr).collapse(false); + } + + range.select(true); + } + } + }; +}; + + +// plugins/wordimage.js +///import core +///commands 本地图片引导上传 +///commandsName WordImage +///commandsTitle 本地图片引导上传 +///commandsDialog dialogs\wordimage + +UE.plugin.register("wordimage", function() { + var me = this, + images = []; + + this.addListener("click", function (type, evt) { + var el = evt.target || evt.srcElement; + if ('IMG' == el.tagName && el.getAttribute('data-word-image')) { + me.ui._dialogs.wordimageDialog && me.ui._dialogs.wordimageDialog.open(); + } + }); + + return { + commands: { + wordimage: { + execCommand: function() { + var images = domUtils.getElementsByTagName(me.body, "img"); + var urlList = []; + for (var i = 0, ci; (ci = images[i++]); ) { + var url = ci.getAttribute("data-word-image"); + url && urlList.push(url); + } + return urlList; + }, + queryCommandState: function() { + images = domUtils.getElementsByTagName(me.body, "img"); + for (var i = 0, ci; (ci = images[i++]); ) { + if (ci.getAttribute("data-word-image")) { + return 1; + } + } + return -1; + }, + notNeedUndo: true + } + }, + inputRule: function(root) { + utils.each(root.getNodesByTagName("img"), function(img) { + var attrs = img.attrs, + flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43, + opt = me.options, + src = opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif"; + if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) { + img.setAttr({ + width: attrs.width, + height: attrs.height, + alt: attrs.alt, + 'data-word-image': attrs.src, + src: src, + style: + "background:url(" + + (flag + ? opt.themePath + opt.theme + "/images/word.gif" + : opt.langPath + opt.lang + "/images/localimage.png") + + ") no-repeat center center;border:1px solid #ddd" + }); + } + }); + } + }; +}); + + +// plugins/autosave.js +UE.plugin.register("autosave", function () { + var me = this, saveKey = null; + + function save(editor) { + var saveData; + + if (!editor.hasContents()) { + //这里不能调用命令来删除, 会造成事件死循环 + saveKey && me.removePreferences(saveKey); + return; + } + + editor._autoSaveTimer = null; + + saveData = me.body.innerHTML; + + if ( + editor.fireEvent("beforeautosave", { + content: saveData + }) === false + ) { + return; + } + + // console.log('autosave', saveKey, saveData); + me.setPreferences(saveKey, saveData); + + editor.fireEvent("afterautosave", { + content: saveData + }); + } + + return { + defaultOptions: { + autoSaveEnable: true, + autoSaveRestore: false, + autoSaveKey: null, + }, + bindEvents: { + ready: function () { + saveKey = me.getOpt('autoSaveKey'); + if (!saveKey) { + var _suffix = "_DraftsData", key = null; + + if (me.key) { + key = me.key + _suffix; + } else { + key = (me.container.parentNode.id || "ue-common") + _suffix; + } + saveKey = (location.protocol + location.host + location.pathname).replace( + /[.:\/]/g, + "_" + ) + key; + } + if (me.getOpt('autoSaveRestore')) { + var data = me.getPreferences(saveKey); + // console.log('saveKey', saveKey, data); + if (data) { + me.body.innerHTML = data; + me.fireEvent('showmessage',{ + type:'info', + content:me.getLang('autosave').autoRestoreTip + }) + } + } + // console.log('saveKey', saveKey); + }, + beforesubmit: function(){ + if (!me.getOpt("autoSaveEnable") || !saveKey) { + return; + } + me.execCommand('clear_auto_save_content'); + }, + contentchange: function () { + if(!me.isReady){ + return; + } + if (!me.getOpt("autoSaveEnable") || !saveKey) { + return; + } + + if (me._autoSaveTimer) { + window.clearTimeout(me._autoSaveTimer); + } + + me._autoSaveTimer = window.setTimeout(function () { + save(me); + }, 1000); + } + }, + commands: { + clear_auto_save_content: { + execCommand: function (cmd, name) { + if (saveKey && me.getPreferences(saveKey)) { + me.removePreferences(saveKey); + } + }, + notNeedUndo: true, + ignoreContentChange: true + }, + + set_auto_save_content: { + execCommand: function (cmd, name) { + save(me); + }, + notNeedUndo: true, + ignoreContentChange: true + }, + + get_auto_save_content: { + execCommand: function (cmd, name) { + return me.getPreferences(saveKey) || ""; + }, + notNeedUndo: true, + ignoreContentChange: true + }, + + auto_save_restore: { + execCommand: function (cmd, name) { + if (saveKey) { + me.body.innerHTML = + me.getPreferences(saveKey) || "

    " + domUtils.fillHtml + "

    "; + me.focus(true); + } + }, + queryCommandState: function () { + return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1; + }, + notNeedUndo: true, + ignoreContentChange: true + } + } + }; +}); + + +// plugins/formula.js +UE.plugin.register("formula", function () { + var me = this, images = []; + + return { + commands: { + formula: { + execCommand: function (cmdName, value) { + var range = me.selection.getRange(), + img = range.getClosedNode(); + + value = encodeURIComponent(value); + var formulaConfig = me.getOpt('formulaConfig'); + var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value); + + if (img) { + img.setAttribute("src", src); + } else { + me.execCommand("insertHtml", ''); + } + }, + } + }, + }; +}); + + +// plugins/dragdrop.js +UE.plugins["dragdrop"] = function() { + var me = this; + me.ready(function() { + domUtils.on(this.body, "dragend", function() { + var rng = me.selection.getRange(); + var node = rng.getClosedNode() || me.selection.getStart(); + + if (node && node.tagName == "IMG") { + var pre = node.previousSibling, + next; + while ((next = node.nextSibling)) { + if ( + next.nodeType == 1 && + next.tagName == "SPAN" && + !next.firstChild + ) { + domUtils.remove(next); + } else { + break; + } + } + + if ( + ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre)) || !pre) && + (!next || (next && !domUtils.isEmptyBlock(next))) + ) { + if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) { + pre.appendChild(node); + domUtils.moveChild(next, pre); + domUtils.remove(next); + } else if ( + next && + next.tagName == "P" && + !domUtils.isEmptyBlock(next) + ) { + next.insertBefore(node, next.firstChild); + } + + if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) { + domUtils.remove(pre); + } + if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) { + domUtils.remove(next); + } + rng.selectNode(node).select(); + me.fireEvent("saveScene"); + } + } + }); + }); + me.addListener("keyup", function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var rng = me.selection.getRange(), + node; + if ( + (node = domUtils.findParentByTagName(rng.startContainer, "p", true)) + ) { + if (domUtils.getComputedStyle(node, "text-align") == "center") { + domUtils.removeStyle(node, "text-align"); + } + } + } + }); +}; + + +// plugins/undo.js +/** + * undo redo + * @file + * @since 1.2.6.1 + */ + +/** + * 撤销上一次执行的命令 + * @command undo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'undo' ); + * ``` + */ + +/** + * 重做上一次执行的命令 + * @command redo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'redo' ); + * ``` + */ + +UE.plugins["undo"] = function() { + var saveSceneTimer; + var me = this, + maxUndoCount = me.options.maxUndoCount || 20, + maxInputCount = me.options.maxInputCount || 20, + fillchar = new RegExp(domUtils.fillChar + "|", "gi"); // ie会产生多余的 + var noNeedFillCharTags = { + ol: 1, + ul: 1, + table: 1, + tbody: 1, + tr: 1, + body: 1 + }; + var orgState = me.options.autoClearEmptyNode; + function compareAddr(indexA, indexB) { + if (indexA.length != indexB.length) return 0; + for (var i = 0, l = indexA.length; i < l; i++) { + if (indexA[i] != indexB[i]) return 0; + } + return 1; + } + + function compareRangeAddress(rngAddrA, rngAddrB) { + if (rngAddrA.collapsed != rngAddrB.collapsed) { + return 0; + } + if ( + !compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || + !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress) + ) { + return 0; + } + return 1; + } + + function UndoManager() { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.undo = function() { + if (this.hasUndo) { + if (!this.list[this.index - 1] && this.list.length == 1) { + this.reset(); + return; + } + while ( + this.list[this.index].content == this.list[this.index - 1].content + ) { + this.index--; + if (this.index == 0) { + return this.restore(0); + } + } + this.restore(--this.index); + } + }; + this.redo = function() { + if (this.hasRedo) { + while ( + this.list[this.index].content == this.list[this.index + 1].content + ) { + this.index++; + if (this.index == this.list.length - 1) { + return this.restore(this.index); + } + } + this.restore(++this.index); + } + }; + + this.restore = function() { + var me = this.editor; + var scene = this.list[this.index]; + var root = UE.htmlparser(scene.content.replace(fillchar, "")); + me.options.autoClearEmptyNode = false; + me.filterInputRule(root); + me.options.autoClearEmptyNode = orgState; + //trace:873 + //去掉展位符 + me.document.body.innerHTML = root.toHtml(); + me.fireEvent("afterscencerestore"); + //处理undo后空格不展位的问题 + if (browser.ie) { + utils.each( + domUtils.getElementsByTagName(me.document, "td th caption p"), + function(node) { + if (domUtils.isEmptyNode(node)) { + domUtils.fillNode(me.document, node); + } + } + ); + } + + try { + var rng = new dom.Range(me.document).moveToAddress(scene.address); + rng.select( + noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()] + ); + } catch (e) {} + + this.update(); + this.clearKey(); + //不能把自己reset了 + me.fireEvent("reset", true); + }; + + this.getScene = function() { + var me = this.editor; + var rng = me.selection.getRange(), + rngAddress = rng.createAddress(false, true); + me.fireEvent("beforegetscene"); + var root = UE.htmlparser(me.body.innerHTML); + me.options.autoClearEmptyNode = false; + me.filterOutputRule(root); + me.options.autoClearEmptyNode = orgState; + var cont = root.toHtml(); + //trace:3461 + //这个会引起回退时导致空格丢失的情况 + // browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>')); + me.fireEvent("aftergetscene"); + + return { + address: rngAddress, + content: cont + }; + }; + this.save = function(notCompareRange, notSetCursor) { + + clearTimeout(saveSceneTimer); + var currentScene = this.getScene(notSetCursor), + lastScene = this.list[this.index]; + if (!lastScene || ( lastScene && lastScene.content != currentScene.content )) { + // 使用异步避免直接在事件中取值滞后一个字符 + setTimeout(function(){ + me.trigger("contentchange"); + },0); + } + //内容相同位置相同不存 + if ( + lastScene && + lastScene.content == currentScene.content && + (notCompareRange + ? 1 + : compareRangeAddress(lastScene.address, currentScene.address)) + ) { + return; + } + this.list = this.list.slice(0, this.index + 1); + this.list.push(currentScene); + //如果大于最大数量了,就把最前的剔除 + if (this.list.length > maxUndoCount) { + this.list.shift(); + } + this.index = this.list.length - 1; + this.clearKey(); + //跟新undo/redo状态 + this.update(); + }; + this.update = function() { + this.hasRedo = !!this.list[this.index + 1]; + this.hasUndo = !!this.list[this.index - 1]; + }; + this.reset = function() { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.clearKey(); + }; + this.clearKey = function() { + keycont = 0; + lastKeyCode = null; + }; + } + + me.undoManger = new UndoManager(); + me.undoManger.editor = me; + function saveScene() { + this.undoManger.save(); + } + + me.addListener("saveScene", function() { + var args = Array.prototype.splice.call(arguments, 1); + this.undoManger.save.apply(this.undoManger, args); + }); + + // me.addListener('beforeexeccommand', saveScene); + // me.addListener('afterexeccommand', saveScene); + + me.addListener("reset", function(type, exclude) { + if (!exclude) { + this.undoManger.reset(); + } + }); + me.commands["redo"] = me.commands["undo"] = { + execCommand: function(cmdName) { + this.undoManger[cmdName](); + }, + queryCommandState: function(cmdName) { + return this.undoManger[ + "has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo") + ] + ? 0 + : -1; + }, + notNeedUndo: 1 + }; + + var keys = { + // /*Backspace*/ 8:1, /*Delete*/ 46:1, + /*Shift*/ 16: 1, + /*Ctrl*/ 17: 1, + /*Alt*/ 18: 1, + 37: 1, + 38: 1, + 39: 1, + 40: 1 + }, + keycont = 0, + lastKeyCode; + //输入法状态下不计算字符数 + var inputType = false; + me.addListener("ready", function() { + domUtils.on(this.body, "compositionstart", function() { + inputType = true; + }); + domUtils.on(this.body, "compositionend", function() { + inputType = false; + }); + }); + //快捷键 + me.addshortcutkey({ + Undo: "ctrl+90", //undo + Redo: "ctrl+89" //redo + }); + var isCollapsed = true; + me.addListener("keydown", function(type, evt) { + var me = this; + var keyCode = evt.keyCode || evt.which; + if ( + !keys[keyCode] && + !evt.ctrlKey && + !evt.metaKey && + !evt.shiftKey && + !evt.altKey + ) { + if (inputType) return; + + if (!me.selection.getRange().collapsed) { + me.undoManger.save(false, true); + isCollapsed = false; + return; + } + if (me.undoManger.list.length === 0) { + me.undoManger.save(true); + } + clearTimeout(saveSceneTimer); + function save(cont) { + cont.undoManger.save(false, true); + cont.fireEvent("selectionchange"); + } + saveSceneTimer = setTimeout(function() { + if (inputType) { + var interalTimer = setInterval(function() { + if (!inputType) { + save(me); + clearInterval(interalTimer); + } + }, 300); + return; + } + save(me); + }, 200); + + lastKeyCode = keyCode; + keycont++; + if (keycont >= maxInputCount) { + save(me); + } + } + }); + me.addListener("keyup", function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if ( + !keys[keyCode] && + !evt.ctrlKey && + !evt.metaKey && + !evt.shiftKey && + !evt.altKey + ) { + if (inputType) return; + if (!isCollapsed) { + this.undoManger.save(false, true); + isCollapsed = true; + } + } + }); + //扩展实例,添加关闭和开启命令undo + me.stopCmdUndo = function() { + me.__hasEnterExecCommand = true; + }; + me.startCmdUndo = function() { + me.__hasEnterExecCommand = false; + }; +}; + + +// plugins/copy.js +UE.plugin.register("copy", function() { + var me = this; + + function initZeroClipboard() { + ZeroClipboard.config({ + debug: false, + swfPath: + me.options.UEDITOR_HOME_URL + + "third-party/zeroclipboard/ZeroClipboard.swf" + }); + + var client = (me.zeroclipboard = new ZeroClipboard()); + + // 复制内容 + client.on("copy", function(e) { + var client = e.client, + rng = me.selection.getRange(), + div = document.createElement("div"); + + div.appendChild(rng.cloneContents()); + client.setText(div.innerText || div.textContent); + client.setHtml(div.innerHTML); + rng.select(); + }); + // hover事件传递到target + client.on("mouseover mouseout", function(e) { + var target = e.target; + if (target) { + if (e.type == "mouseover") { + domUtils.addClass(target, "edui-state-hover"); + } else if (e.type == "mouseout") { + domUtils.removeClasses(target, "edui-state-hover"); + } + } + }); + // flash加载不成功 + client.on("wrongflash noflash", function() { + ZeroClipboard.destroy(); + }); + + // 触发事件 + me.fireEvent("zeroclipboardready", client); + } + + return { + bindEvents: { + ready: function() { + if (!browser.ie) { + if (window.ZeroClipboard) { + initZeroClipboard(); + } else { + utils.loadFile( + document, + { + src: + me.options.UEDITOR_HOME_URL + + "third-party/zeroclipboard/ZeroClipboard.js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, + function() { + initZeroClipboard(); + } + ); + } + } + } + }, + commands: { + copy: { + execCommand: function(cmd) { + if (!me.document.execCommand("copy")) { + alert(me.getLang("copymsg")); + } + } + } + } + }; +}); + + +// plugins/paste.js +///import core +///import plugins/inserthtml.js +///import plugins/undo.js +///import plugins/serialize.js +///commands 粘贴 +///commandsName PastePlain +///commandsTitle 纯文本粘贴模式 +/** + * @description 粘贴 + * @author zhanyi + */ +UE.plugins["paste"] = function() { + function getClipboardData(callback) { + var doc = this.document; + if (doc.getElementById("baidu_pastebin")) { + return; + } + var range = this.selection.getRange(), + bk = range.createBookmark(), + //创建剪贴的容器div + pastebin = doc.createElement("div"); + pastebin.id = "baidu_pastebin"; + // Safari 要求div必须有内容,才能粘贴内容进来 + browser.webkit && + pastebin.appendChild( + doc.createTextNode(domUtils.fillChar + domUtils.fillChar) + ); + doc.body.appendChild(pastebin); + //trace:717 隐藏的span不能得到top + //bk.start.innerHTML = ' '; + bk.start.style.display = ""; + pastebin.style.cssText = + "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + + //要在现在光标平行的位置加入,否则会出现跳动的问题 + domUtils.getXY(bk.start).y + + "px"; + + range.selectNodeContents(pastebin).select(true); + + setTimeout(function() { + if (browser.webkit) { + for ( + var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; + (pi = pastebins[i++]); + + ) { + if (domUtils.isEmptyNode(pi)) { + domUtils.remove(pi); + } else { + pastebin = pi; + break; + } + } + } + try { + pastebin.parentNode.removeChild(pastebin); + } catch (e) {} + range.moveToBookmark(bk).select(true); + callback(pastebin); + }, 0); + } + + var me = this; + + me.setOpt({ + retainOnlyLabelPasted: false + }); + + var txtContent, htmlContent, address; + + function getPureHtml(html) { + return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function( + a, + b, + tagName, + attrs + ) { + tagName = tagName.toLowerCase(); + if ({ img: 1 }[tagName]) { + return a; + } + attrs = attrs.replace( + /([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, + function(str, atr, val) { + if ( + { + src: 1, + href: 1, + name: 1 + }[atr.toLowerCase()] + ) { + return atr + "=" + val + " "; + } + return ""; + } + ); + if ( + { + span: 1, + div: 1 + }[tagName] + ) { + return ""; + } else { + return "<" + b + tagName + " " + utils.trim(attrs) + ">"; + } + }); + } + function filter(div) { + var html; + if (div.firstChild) { + //去掉cut中添加的边界值 + var nodes = domUtils.getElementsByTagName(div, "span"); + for (var i = 0, ni; (ni = nodes[i++]); ) { + if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") { + domUtils.remove(ni); + } + } + + if (browser.webkit) { + var brs = div.querySelectorAll("div br"); + for (var i = 0, bi; (bi = brs[i++]); ) { + var pN = bi.parentNode; + if (pN.tagName == "DIV" && pN.childNodes.length == 1) { + pN.innerHTML = "


    "; + domUtils.remove(pN); + } + } + var divs = div.querySelectorAll("#baidu_pastebin"); + for (var i = 0, di; (di = divs[i++]); ) { + var tmpP = me.document.createElement("p"); + di.parentNode.insertBefore(tmpP, di); + while (di.firstChild) { + tmpP.appendChild(di.firstChild); + } + domUtils.remove(di); + } + + var metas = div.querySelectorAll("meta"); + for (var i = 0, ci; (ci = metas[i++]); ) { + domUtils.remove(ci); + } + + var brs = div.querySelectorAll("br"); + for (i = 0; (ci = brs[i++]); ) { + if (/^apple-/i.test(ci.className)) { + domUtils.remove(ci); + } + } + } + if (browser.gecko) { + var dirtyNodes = div.querySelectorAll("[_moz_dirty]"); + for (i = 0; (ci = dirtyNodes[i++]); ) { + ci.removeAttribute("_moz_dirty"); + } + } + if (!browser.ie) { + var spans = div.querySelectorAll("span.Apple-style-span"); + for (var i = 0, ci; (ci = spans[i++]); ) { + domUtils.remove(ci, true); + } + } + + //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉 + html = div.innerHTML; //.replace(/>(?:(\s| )*?)<'); + + //过滤word粘贴过来的冗余属性 + html = UE.filterWord(html); + //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签 + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if (me.options.filterRules) { + UE.filterNode(root, me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + //针对chrome的处理 + if (browser.webkit) { + var br = root.lastChild(); + if (br && br.type == "element" && br.tagName == "br") { + root.removeChild(br); + } + utils.each(me.body.querySelectorAll("div"), function(node) { + if (domUtils.isEmptyBlock(node)) { + domUtils.remove(node, true); + } + }); + } + html = { html: root.toHtml() }; + me.fireEvent("beforepaste", html, root); + //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴 + if (!html.html) { + return; + } + root = UE.htmlparser(html.html, true); + //如果开启了纯文本模式 + if (me.queryCommandState("pasteplain") === 1) { + me.execCommand( + "insertHtml", + UE.filterNode(root, me.options.filterTxtRules).toHtml(), + true + ); + } else { + //文本模式 + UE.filterNode(root, me.options.filterTxtRules); + txtContent = root.toHtml(); + //完全模式 + htmlContent = html.html; + + address = me.selection.getRange().createAddress(true); + me.execCommand( + "insertHtml", + me.getOpt("retainOnlyLabelPasted") === true + ? getPureHtml(htmlContent) + : htmlContent, + true + ); + } + me.fireEvent("afterpaste", html); + } + } + + me.addListener("pasteTransfer", function(cmd, plainType) { + if (address && txtContent && htmlContent && txtContent != htmlContent) { + var range = me.selection.getRange(); + range.moveToAddress(address, true); + + if (!range.collapsed) { + while (!domUtils.isBody(range.startContainer)) { + var start = range.startContainer; + if (start.nodeType == 1) { + start = start.childNodes[range.startOffset]; + if (!start) { + range.setStartBefore(range.startContainer); + continue; + } + var pre = start.previousSibling; + + if ( + pre && + pre.nodeType == 3 && + new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test( + pre.nodeValue + ) + ) { + range.setStartBefore(pre); + } + } + if (range.startOffset == 0) { + range.setStartBefore(range.startContainer); + } else { + break; + } + } + while (!domUtils.isBody(range.endContainer)) { + var end = range.endContainer; + if (end.nodeType == 1) { + end = end.childNodes[range.endOffset]; + if (!end) { + range.setEndAfter(range.endContainer); + continue; + } + var next = end.nextSibling; + if ( + next && + next.nodeType == 3 && + new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test( + next.nodeValue + ) + ) { + range.setEndAfter(next); + } + } + if ( + range.endOffset == + range.endContainer[ + range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + range.setEndAfter(range.endContainer); + } else { + break; + } + } + } + + range.deleteContents(); + range.select(true); + me.__hasEnterExecCommand = true; + var html = htmlContent; + if (plainType === 2) { + html = getPureHtml(html); + } else if (plainType) { + html = txtContent; + } + me.execCommand("inserthtml", html, true); + me.__hasEnterExecCommand = false; + var rng = me.selection.getRange(); + while ( + !domUtils.isBody(rng.startContainer) && + !rng.startOffset && + rng.startContainer[ + rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + rng.setStartBefore(rng.startContainer); + } + var tmpAddress = rng.createAddress(true); + address.endAddress = tmpAddress.startAddress; + } + }); + + me.addListener("ready", function() { + domUtils.on(me.body, "cut", function() { + var range = me.selection.getRange(); + if (!range.collapsed && me.undoManger) { + me.undoManger.save(); + } + }); + + //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理 + domUtils.on( + me.body, + browser.ie || browser.opera ? "keydown" : "paste", + function(e) { + if ( + (browser.ie || browser.opera) && + ((!e.ctrlKey && !e.metaKey) || e.keyCode != "86") + ) { + return; + } + getClipboardData.call(me, function(div) { + filter(div); + }); + } + ); + }); + + me.commands["paste"] = { + execCommand: function(cmd) { + if (browser.ie) { + getClipboardData.call(me, function(div) { + filter(div); + }); + me.document.execCommand("paste"); + } else { + alert(me.getLang("pastemsg")); + } + } + }; +}; + + +// plugins/puretxtpaste.js +/** + * 纯文本粘贴插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins["pasteplain"] = function() { + var me = this; + me.setOpt({ + pasteplain: false, + filterTxtRules: (function() { + function transP(node) { + node.tagName = "p"; + node.setStyle(); + } + function removeNode(node) { + node.parentNode.removeChild(node, true); + } + return { + //直接删除及其字节点内容 + "-": "script style object iframe embed input select", + p: { $: {} }, + br: { $: {} }, + div: function(node) { + var tmpNode, + p = UE.uNode.createElement("p"); + while ((tmpNode = node.firstChild())) { + if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement("p"); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + }, + ol: removeNode, + ul: removeNode, + dl: removeNode, + dt: removeNode, + dd: removeNode, + li: removeNode, + caption: transP, + th: transP, + tr: transP, + h1: transP, + h2: transP, + h3: transP, + h4: transP, + h5: transP, + h6: transP, + td: function(node) { + //没有内容的td直接删掉 + var txt = !!node.innerText(); + if (txt) { + node.parentNode.insertAfter( + UE.uNode.createText("    "), + node + ); + } + node.parentNode.removeChild(node, node.innerText()); + } + }; + })() + }); + //暂时这里支持一下老版本的属性 + var pasteplain = me.options.pasteplain; + + /** + * 启用或取消纯文本粘贴模式 + * @command pasteplain + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.queryCommandState( 'pasteplain' ); + * ``` + */ + + /** + * 查询当前是否处于纯文本粘贴模式 + * @command pasteplain + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果处于纯文本模式,返回1,否则,返回0 + * @example + * ```javascript + * editor.queryCommandState( 'pasteplain' ); + * ``` + */ + me.commands["pasteplain"] = { + queryCommandState: function() { + return pasteplain ? 1 : 0; + }, + execCommand: function() { + pasteplain = !pasteplain | 0; + }, + notNeedUndo: 1 + }; +}; + + +// plugins/list.js +/** + * 有序列表,无序列表插件 + * @file + * @since 1.2.6.1 + */ + +UE.plugins["list"] = function() { + var me = this, + notExchange = { + TD: 1, + PRE: 1, + BLOCKQUOTE: 1 + }; + var customStyle = { + cn: "cn-1-", + cn1: "cn-2-", + cn2: "cn-3-", + num: "num-1-", + num1: "num-2-", + num2: "num-3-", + dash: "dash", + dot: "dot" + }; + + me.setOpt({ + autoTransWordToList: false, + insertorderedlist: { + num: "", + num1: "", + num2: "", + cn: "", + cn1: "", + cn2: "", + decimal: "", + "lower-alpha": "", + "lower-roman": "", + "upper-alpha": "", + "upper-roman": "" + }, + insertunorderedlist: { + circle: "", + disc: "", + square: "", + dash: "", + dot: "" + }, + listDefaultPaddingLeft: "30", + listiconpath: "http://bs.baidu.com/listicon/", + maxListLevel: -1, //-1不限制 + disablePInList: false + }); + function listToArray(list) { + var arr = []; + for (var p in list) { + arr.push(p); + } + return arr; + } + var listStyle = { + OL: listToArray(me.options.insertorderedlist), + UL: listToArray(me.options.insertunorderedlist) + }; + var liiconpath = me.options.listiconpath; + + //根据用户配置,调整customStyle + for (var s in customStyle) { + if ( + !me.options.insertorderedlist.hasOwnProperty(s) && + !me.options.insertunorderedlist.hasOwnProperty(s) + ) { + delete customStyle[s]; + } + } + + me.ready(function() { + var customCss = []; + for (var p in customStyle) { + if (p == "dash" || p == "dot") { + customCss.push( + "li.list-" + + customStyle[p] + + "{background-image:url(" + + liiconpath + + customStyle[p] + + ".gif)}" + ); + customCss.push( + "ul.custom_" + + p + + "{list-style:none;}ul.custom_" + + p + + " li{background-position:0 3px;background-repeat:no-repeat}" + ); + } else { + for (var i = 0; i < 99; i++) { + customCss.push( + "li.list-" + + customStyle[p] + + i + + "{background-image:url(" + + liiconpath + + "list-" + + customStyle[p] + + i + + ".gif)}" + ); + } + customCss.push( + "ol.custom_" + + p + + "{list-style:none;}ol.custom_" + + p + + " li{background-position:0 3px;background-repeat:no-repeat}" + ); + } + switch (p) { + case "cn": + customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); + customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); + break; + case "cn1": + customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}"); + customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); + break; + case "cn2": + customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}"); + customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}"); + customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}"); + break; + case "num": + case "num1": + customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); + break; + case "num2": + customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}"); + customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + break; + case "dash": + customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}"); + break; + case "dot": + customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}"); + } + } + customCss.push(".list-paddingleft-1{padding-left:0}"); + customCss.push( + ".list-paddingleft-2{padding-left:" + + me.options.listDefaultPaddingLeft + + "px}" + ); + customCss.push( + ".list-paddingleft-3{padding-left:" + + me.options.listDefaultPaddingLeft * 2 + + "px}" + ); + //如果不给宽度会在自定应样式里出现滚动条 + utils.cssRule( + "list", + "ol,ul{margin:0;pading:0;" + + (browser.ie ? "" : "width:95%") + + "}li{clear:both;}" + + customCss.join("\n"), + me.document + ); + }); + //单独处理剪切的问题 + me.ready(function() { + domUtils.on(me.body, "cut", function() { + setTimeout(function() { + var rng = me.selection.getRange(), + li; + //trace:3416 + if (!rng.collapsed) { + if ( + (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) + ) { + if (!li.nextSibling && domUtils.isEmptyBlock(li)) { + var pn = li.parentNode, + node; + if ((node = pn.previousSibling)) { + domUtils.remove(pn); + rng.setStartAtLast(node).collapse(true); + rng.select(true); + } else if ((node = pn.nextSibling)) { + domUtils.remove(pn); + rng.setStartAtFirst(node).collapse(true); + rng.select(true); + } else { + var tmpNode = me.document.createElement("p"); + domUtils.fillNode(me.document, tmpNode); + pn.parentNode.insertBefore(tmpNode, pn); + domUtils.remove(pn); + rng.setStart(tmpNode, 0).collapse(true); + rng.select(true); + } + } + } + } + }); + }); + }); + + function getStyle(node) { + var cls = node.className; + if (domUtils.hasClass(node, /custom_/)) { + return cls.match(/custom_(\w+)/)[1]; + } + return domUtils.getStyle(node, "list-style-type"); + } + + me.addListener("beforepaste", function(type, html) { + var me = this, + rng = me.selection.getRange(), + li; + var root = UE.htmlparser(html.html, true); + if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) { + var list = li.parentNode, + tagName = list.tagName === "OL" ? "ul" : "ol"; + utils.each(root.getNodesByTagName(tagName), function(n) { + n.tagName = list.tagName; + n.setAttr(); + if (n.parentNode === root) { + type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc"); + } else { + var className = n.parentNode.getAttr("class"); + if (className && /custom_/.test(className)) { + type = className.match(/custom_(\w+)/)[1]; + } else { + type = n.parentNode.getStyle("list-style-type"); + } + if (!type) { + type = list.tagName === "OL" ? "decimal" : "disc"; + } + } + var index = utils.indexOf(listStyle[list.tagName], type); + if (n.parentNode !== root) + index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + if (customStyle[currentStyle]) { + n.setAttr("class", "custom_" + currentStyle); + } else { + n.setStyle("list-style-type", currentStyle); + } + }); + } + + html.html = root.toHtml(); + }); + //导出时,去掉p标签 + me.getOpt("disablePInList") === true && + me.addOutputRule(function(root) { + utils.each(root.getNodesByTagName("li"), function(li) { + var newChildrens = [], + index = 0; + utils.each(li.children, function(n) { + if (n.tagName == "p") { + var tmpNode; + while ((tmpNode = n.children.pop())) { + newChildrens.splice(index, 0, tmpNode); + tmpNode.parentNode = li; + lastNode = tmpNode; + } + tmpNode = newChildrens[newChildrens.length - 1]; + if ( + !tmpNode || + tmpNode.type !== "element" || + tmpNode.tagName !== "br" + ) { + var br = UE.uNode.createElement("br"); + br.parentNode = li; + newChildrens.push(br); + } + + index = newChildrens.length; + } + }); + if (newChildrens.length) { + li.children = newChildrens; + } + }); + }); + //进入编辑器的li要套p标签 + me.addInputRule(function(root) { + utils.each(root.getNodesByTagName("li"), function(li) { + var tmpP = UE.uNode.createElement("p"); + for (var i = 0, ci; (ci = li.children[i]); ) { + if (ci.type === "text" || dtd.p[ci.tagName]) { + tmpP.appendChild(ci); + } else { + if (tmpP.firstChild()) { + li.insertBefore(tmpP, ci); + tmpP = UE.uNode.createElement("p"); + i = i + 2; + } else { + i++; + } + } + } + if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) { + li.appendChild(tmpP); + } + //trace:3357 + //p不能为空 + if (!tmpP.firstChild()) { + tmpP.innerHTML(browser.ie ? " " : "
    "); + } + //去掉末尾的空白 + var p = li.firstChild(); + var lastChild = p.lastChild(); + if ( + lastChild && + lastChild.type === "text" && + /^\s*$/.test(lastChild.data) + ) { + p.removeChild(lastChild); + } + }); + if (me.options.autoTransWordToList) { + var orderlisttype = { + num1: /^\d+\)/, + decimal: /^\d+\./, + "lower-alpha": /^[a-z]+\)/, + "upper-alpha": /^[A-Z]+\./, + cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/, + cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/ + }, + unorderlisttype = { + square: "n" + }; + function checkListType(content, container) { + var span = container.firstChild(); + if ( + span && + span.type === "element" && + span.tagName === "span" && + /Wingdings|Symbol/.test(span.getStyle("font-family")) + ) { + for (var p in unorderlisttype) { + if (unorderlisttype[p] == span.data) { + return p; + } + } + return "disc"; + } + for (var p in orderlisttype) { + if (orderlisttype[p].test(content)) { + return p; + } + } + } + utils.each(root.getNodesByTagName("p"), function(node) { + if (node.getAttr("class") !== "MsoListParagraph") { + return; + } + + //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视 + node.setStyle("margin", ""); + node.setStyle("margin-left", ""); + node.setAttr("class", ""); + + function appendLi(list, p, type) { + if (list.tagName === "ol") { + if (browser.ie) { + var first = p.firstChild(); + if ( + first.type === "element" && + first.tagName === "span" && + orderlisttype[type].test(first.innerText()) + ) { + p.removeChild(first); + } + } else { + p.innerHTML(p.innerHTML().replace(orderlisttype[type], "")); + } + } else { + p.removeChild(p.firstChild()); + } + + var li = UE.uNode.createElement("li"); + li.appendChild(p); + list.appendChild(li); + } + var tmp = node, + type, + cacheNode = node; + + if ( + node.parentNode.tagName !== "li" && + (type = checkListType(node.innerText(), node)) + ) { + var list = UE.uNode.createElement( + me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul" + ); + if (customStyle[type]) { + list.setAttr("class", "custom_" + type); + } else { + list.setStyle("list-style-type", type); + } + while ( + node && + node.parentNode.tagName !== "li" && + checkListType(node.innerText(), node) + ) { + tmp = node.nextSibling(); + if (!tmp) { + node.parentNode.insertBefore(list, node); + } + appendLi(list, node, type); + node = tmp; + } + if (!list.parentNode && node && node.parentNode) { + node.parentNode.insertBefore(list, node); + } + } + var span = cacheNode.firstChild(); + if ( + span && + span.type == "element" && + span.tagName == "span" && + /^\s*( )+\s*$/.test(span.innerText()) + ) { + span.parentNode.removeChild(span); + } + }); + } + }); + + //调整索引标签 + me.addListener("contentchange", function() { + adjustListStyle(me.document); + }); + + function adjustListStyle(doc, ignore) { + utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function(node) { + if (!domUtils.inDoc(node, doc)) return; + + var parent = node.parentNode; + if (parent.tagName === node.tagName) { + var nodeStyleType = + getStyle(node) || (node.tagName === "OL" ? "decimal" : "disc"), + parentStyleType = + getStyle(parent) || (parent.tagName === "OL" ? "decimal" : "disc"); + if (nodeStyleType === parentStyleType) { + var styleIndex = utils.indexOf( + listStyle[node.tagName], + nodeStyleType + ); + styleIndex = styleIndex + 1 === listStyle[node.tagName].length + ? 0 + : styleIndex + 1; + setListStyle(node, listStyle[node.tagName][styleIndex]); + } + } + var index = 0, + type = 2; + if (domUtils.hasClass(node, /custom_/)) { + if ( + !( + /[ou]l/i.test(parent.tagName) && + domUtils.hasClass(parent, /custom_/) + ) + ) { + type = 1; + } + } else { + if ( + /[ou]l/i.test(parent.tagName) && + domUtils.hasClass(parent, /custom_/) + ) { + type = 3; + } + } + + var style = domUtils.getStyle(node, "list-style-type"); + style && (node.style.cssText = "list-style-type:" + style); + node.className = + utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + + " list-paddingleft-" + + type; + utils.each(domUtils.getElementsByTagName(node, "li"), function(li) { + li.style.cssText && (li.style.cssText = ""); + if (!li.firstChild) { + domUtils.remove(li); + return; + } + if (li.parentNode !== node) { + return; + } + index++; + if (domUtils.hasClass(node, /custom_/)) { + var paddingLeft = 1, + currentStyle = getStyle(node); + if (node.tagName === "OL") { + if (currentStyle) { + switch (currentStyle) { + case "cn": + case "cn1": + case "cn2": + if ( + index > 10 && + (index % 10 === 0 || (index > 10 && index < 20)) + ) { + paddingLeft = 2; + } else if (index > 20) { + paddingLeft = 3; + } + break; + case "num2": + if (index > 9) { + paddingLeft = 2; + } + } + } + li.className = + "list-" + + customStyle[currentStyle] + + index + + " " + + "list-" + + currentStyle + + "-paddingleft-" + + paddingLeft; + } else { + li.className = + "list-" + + customStyle[currentStyle] + + " " + + "list-" + + currentStyle + + "-paddingleft"; + } + } else { + li.className = li.className.replace(/list-[\w\-]+/gi, ""); + } + var className = li.getAttribute("class"); + if (className !== null && !className.replace(/\s/g, "")) { + domUtils.removeAttributes(li, "class"); + } + }); + !ignore && + adjustList( + node, + node.tagName.toLowerCase(), + getStyle(node) || domUtils.getStyle(node, "list-style-type"), + true + ); + }); + } + function adjustList(list, tag, style, ignoreEmpty) { + var nextList = list.nextSibling; + if ( + nextList && + nextList.nodeType === 1 && + nextList.tagName.toLowerCase() === tag && + (getStyle(nextList) || + domUtils.getStyle(nextList, "list-style-type") || + (tag == "ol" ? "decimal" : "disc")) == style + ) { + domUtils.moveChild(nextList, list); + if (nextList.childNodes.length === 0) { + domUtils.remove(nextList); + } + } + if (nextList && domUtils.isFillChar(nextList)) { + domUtils.remove(nextList); + } + var preList = list.previousSibling; + if ( + preList && + preList.nodeType === 1 && + preList.tagName.toLowerCase() == tag && + (getStyle(preList) || + domUtils.getStyle(preList, "list-style-type") || + (tag == "ol" ? "decimal" : "disc")) === style + ) { + domUtils.moveChild(list, preList); + } + if (preList && domUtils.isFillChar(preList)) { + domUtils.remove(preList); + } + !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list); + if (getStyle(list)) { + adjustListStyle(list.ownerDocument, true); + } + } + + function setListStyle(list, style) { + if (customStyle[style]) { + list.className = "custom_" + style; + } + try { + domUtils.setStyle(list, "list-style-type", style); + } catch (e) {} + } + function clearEmptySibling(node) { + var tmpNode = node.previousSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + tmpNode = node.nextSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + } + + me.addListener("keydown", function(type, evt) { + function preventAndSave() { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + me.fireEvent("contentchange"); + me.undoManger && me.undoManger.save(); + } + function findList(node, filterFn) { + while (node && !domUtils.isBody(node)) { + if (filterFn(node)) { + return null; + } + if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) { + return node; + } + node = node.parentNode; + } + return null; + } + var keyCode = evt.keyCode || evt.which; + if (keyCode === 13 && !evt.shiftKey) { + //回车 + var rng = me.selection.getRange(), + parent = domUtils.findParent( + rng.startContainer, + function(node) { + return domUtils.isBlockElm(node); + }, + true + ), + li = domUtils.findParentByTagName(rng.startContainer, "li", true); + if (parent && parent.tagName !== "PRE" && !li) { + var html = parent.innerHTML.replace( + new RegExp(domUtils.fillChar, "g"), + "" + ); + if (/^\s*1\s*\.[^\d]/.test(html)) { + parent.innerHTML = html.replace(/^\s*1\s*\./, ""); + rng.setStartAtLast(parent).collapse(true).select(); + me.__hasEnterExecCommand = true; + me.execCommand("insertorderedlist"); + me.__hasEnterExecCommand = false; + } + } + var range = me.selection.getRange(), + start = findList(range.startContainer, function(node) { + return node.tagName === "TABLE"; + }), + end = range.collapsed + ? start + : findList(range.endContainer, function(node) { + return node.tagName === "TABLE"; + }); + + if (start && end && start === end) { + if (!range.collapsed) { + start = domUtils.findParentByTagName( + range.startContainer, + "li", + true + ); + end = domUtils.findParentByTagName(range.endContainer, "li", true); + if (start && end && start === end) { + range.deleteContents(); + li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li && domUtils.isEmptyBlock(li)) { + pre = li.previousSibling; + next = li.nextSibling; + p = me.document.createElement("p"); + + domUtils.fillNode(me.document, p); + parentList = li.parentNode; + if (pre && next) { + range.setStart(next, 0).collapse(true).select(true); + domUtils.remove(li); + } else { + if ((!pre && !next) || !pre) { + parentList.parentNode.insertBefore(p, parentList); + } else { + li.parentNode.parentNode.insertBefore( + p, + parentList.nextSibling + ); + } + domUtils.remove(li); + if (!parentList.firstChild) { + domUtils.remove(parentList); + } + range.setStart(p, 0).setCursor(); + } + preventAndSave(); + return; + } + } else { + var tmpRange = range.cloneRange(), + bk = tmpRange.collapse(false).createBookmark(); + + range.deleteContents(); + tmpRange.moveToBookmark(bk); + var li = domUtils.findParentByTagName( + tmpRange.startContainer, + "li", + true + ); + + clearEmptySibling(li); + tmpRange.select(); + preventAndSave(); + return; + } + } + + li = domUtils.findParentByTagName(range.startContainer, "li", true); + + if (li) { + if (domUtils.isEmptyBlock(li)) { + bk = range.createBookmark(); + var parentList = li.parentNode; + if (li !== parentList.lastChild) { + domUtils.breakParent(li, parentList); + clearEmptySibling(li); + } else { + parentList.parentNode.insertBefore(li, parentList.nextSibling); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } + //嵌套不处理 + if (!dtd.$list[li.parentNode.tagName]) { + if (!domUtils.isBlockElm(li.firstChild)) { + p = me.document.createElement("p"); + li.parentNode.insertBefore(p, li); + while (li.firstChild) { + p.appendChild(li.firstChild); + } + domUtils.remove(li); + } else { + domUtils.remove(li, true); + } + } + range.moveToBookmark(bk).select(); + } else { + var first = li.firstChild; + if (!first || !domUtils.isBlockElm(first)) { + var p = me.document.createElement("p"); + + !li.firstChild && domUtils.fillNode(me.document, p); + while (li.firstChild) { + p.appendChild(li.firstChild); + } + li.appendChild(p); + first = p; + } + + var span = me.document.createElement("span"); + + range.insertNode(span); + domUtils.breakParent(span, li); + + var nextLi = span.nextSibling; + first = nextLi.firstChild; + + if (!first) { + p = me.document.createElement("p"); + + domUtils.fillNode(me.document, p); + nextLi.appendChild(p); + first = p; + } + if (domUtils.isEmptyNode(first)) { + first.innerHTML = ""; + domUtils.fillNode(me.document, first); + } + + range.setStart(first, 0).collapse(true).shrinkBoundary().select(); + domUtils.remove(span); + var pre = nextLi.previousSibling; + if (pre && domUtils.isEmptyBlock(pre)) { + pre.innerHTML = "

    "; + domUtils.fillNode(me.document, pre.firstChild); + } + } + // } + preventAndSave(); + } + } + } + if (keyCode === 8) { + //修中ie中li下的问题 + range = me.selection.getRange(); + if (range.collapsed && domUtils.isStartInblock(range)) { + tmpRange = range.cloneRange().trimBoundary(); + li = domUtils.findParentByTagName(range.startContainer, "li", true); + //要在li的最左边,才能处理 + if (li && domUtils.isStartInblock(tmpRange)) { + start = domUtils.findParentByTagName(range.startContainer, "p", true); + if (start && start !== li.firstChild) { + var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]); + domUtils.breakParent(start, parentList); + clearEmptySibling(start); + me.fireEvent("contentchange"); + range.setStart(start, 0).setCursor(false, true); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + + if (li && (pre = li.previousSibling)) { + if (keyCode === 46 && li.childNodes.length) { + return; + } + //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li + if (dtd.$list[pre.tagName]) { + pre = pre.lastChild; + } + me.undoManger && me.undoManger.save(); + first = li.firstChild; + if (domUtils.isBlockElm(first)) { + if (domUtils.isEmptyNode(first)) { + // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + pre.appendChild(first); + range.setStart(first, 0).setCursor(false, true); + //first不是唯一的节点 + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } else { + span = me.document.createElement("span"); + range.insertNode(span); + //判断pre是否是空的节点,如果是


    类型的空节点,干掉p标签防止它占位 + if (domUtils.isEmptyBlock(pre)) { + pre.innerHTML = ""; + } + domUtils.moveChild(li, pre); + range.setStartBefore(span).collapse(true).select(true); + + domUtils.remove(span); + } + } else { + if (domUtils.isEmptyNode(li)) { + var p = me.document.createElement("p"); + pre.appendChild(p); + range.setStart(p, 0).setCursor(); + // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + } else { + range + .setEnd(pre, pre.childNodes.length) + .collapse() + .select(true); + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } + } + domUtils.remove(li); + me.fireEvent("contentchange"); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + //trace:980 + + if (li && !li.previousSibling) { + var parentList = li.parentNode; + var bk = range.createBookmark(); + if (domUtils.isTagNode(parentList.parentNode, "ol ul")) { + parentList.parentNode.insertBefore(li, parentList); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } else { + while (li.firstChild) { + parentList.parentNode.insertBefore(li.firstChild, parentList); + } + + domUtils.remove(li); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } + range.moveToBookmark(bk).setCursor(false, true); + me.fireEvent("contentchange"); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + } + } + } + }); + + me.addListener("keyup", function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 8) { + var rng = me.selection.getRange(), + list; + if ( + (list = domUtils.findParentByTagName( + rng.startContainer, + ["ol", "ul"], + true + )) + ) { + adjustList( + list, + list.tagName.toLowerCase(), + getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"), + true + ); + } + } + }); + //处理tab键 + me.addListener("tabkeydown", function() { + var range = me.selection.getRange(); + + //控制级数 + function checkLevel(li) { + if (me.options.maxListLevel != -1) { + var level = li.parentNode, + levelNum = 0; + while (/[ou]l/i.test(level.tagName)) { + levelNum++; + level = level.parentNode; + } + if (levelNum >= me.options.maxListLevel) { + return true; + } + } + } + //只以开始为准 + //todo 后续改进 + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li) { + var bk; + if (range.collapsed) { + if (checkLevel(li)) return true; + var parentLi = li.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf( + listStyle[list.tagName], + getStyle(parentLi) || + domUtils.getComputedStyle(parentLi, "list-style-type") + ); + index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + setListStyle(list, currentStyle); + if (domUtils.isStartInblock(range)) { + me.fireEvent("saveScene"); + bk = range.createBookmark(); + parentLi.insertBefore(list, li); + list.appendChild(li); + adjustList(list, list.tagName.toLowerCase(), currentStyle); + me.fireEvent("contentchange"); + range.moveToBookmark(bk).select(true); + return true; + } + } else { + me.fireEvent("saveScene"); + bk = range.createBookmark(); + for ( + var i = 0, closeList, parents = domUtils.findParents(li), ci; + (ci = parents[i++]); + + ) { + if (domUtils.isTagNode(ci, "ol ul")) { + closeList = ci; + break; + } + } + var current = li; + if (bk.end) { + while ( + current && + !( + domUtils.getPosition(current, bk.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (checkLevel(current)) { + current = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return node !== closeList; + }); + continue; + } + var parentLi = current.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf( + listStyle[list.tagName], + getStyle(parentLi) || + domUtils.getComputedStyle(parentLi, "list-style-type") + ); + var currentIndex = index + 1 == listStyle[list.tagName].length + ? 0 + : index + 1; + var currentStyle = listStyle[list.tagName][currentIndex]; + setListStyle(list, currentStyle); + parentLi.insertBefore(list, current); + while ( + current && + !( + domUtils.getPosition(current, bk.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + li = current.nextSibling; + list.appendChild(current); + if (!li || domUtils.isTagNode(li, "ol ul")) { + if (li) { + while ((li = li.firstChild)) { + if (li.tagName == "LI") { + break; + } + } + } else { + li = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return node !== closeList; + }); + } + break; + } + current = li; + } + adjustList(list, list.tagName.toLowerCase(), currentStyle); + current = li; + } + } + me.fireEvent("contentchange"); + range.moveToBookmark(bk).select(); + return true; + } + } + }); + function getLi(start) { + while (start && !domUtils.isBody(start)) { + if (start.nodeName == "TABLE") { + return null; + } + if (start.nodeName == "LI") { + return start; + } + start = start.parentNode; + } + } + + /** + * 有序列表,与“insertunorderedlist”命令互斥 + * @command insertorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.execCommand( 'insertorderedlist','decimal'); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前选区是有序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.queryCommandValue( 'insertorderedlist' ); + * ``` + */ + + /** + * 无序列表,与“insertorderedlist”命令互斥 + * @command insertunorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot + * @example + * ```javascript + * editor.execCommand( 'insertunorderedlist','circle'); + * ``` + */ + /** + * 查询当前是否有word文档粘贴进来的图片 + * @command insertunorderedlist + * @method insertunorderedlist + * @param { String } command 命令字符串 + * @return { int } 如果当前选区是无序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertunorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertunorderedlist + * @method queryCommandValue + * @param { String } command 命令字符串 + * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot + * @example + * ```javascript + * editor.queryCommandValue( 'insertunorderedlist' ); + * ``` + */ + + me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = { + execCommand: function(command, style) { + if (!style) { + style = command.toLowerCase() == "insertorderedlist" + ? "decimal" + : "disc"; + } + var me = this, + range = this.selection.getRange(), + filterFn = function(node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" + : !domUtils.isWhitespace(node); + }, + tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul", + frag = me.document.createDocumentFragment(); + //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置 + //range.shrinkBoundary();//.adjustmentBoundary(); + range.adjustmentBoundary().shrinkBoundary(); + var bko = range.createBookmark(true), + start = getLi(me.document.getElementById(bko.start)), + modifyStart = 0, + end = getLi(me.document.getElementById(bko.end)), + modifyEnd = 0, + startParent, + endParent, + list, + tmp; + + if (start || end) { + start && (startParent = start.parentNode); + if (!bko.end) { + end = start; + } + end && (endParent = end.parentNode); + + if (startParent === endParent) { + while (start !== end) { + tmp = start; + start = start.nextSibling; + if (!domUtils.isBlockElm(tmp.firstChild)) { + var p = me.document.createElement("p"); + while (tmp.firstChild) { + p.appendChild(tmp.firstChild); + } + tmp.appendChild(p); + } + frag.appendChild(tmp); + } + tmp = me.document.createElement("span"); + startParent.insertBefore(tmp, end); + if (!domUtils.isBlockElm(end.firstChild)) { + p = me.document.createElement("p"); + while (end.firstChild) { + p.appendChild(end.firstChild); + } + end.appendChild(p); + } + frag.appendChild(end); + domUtils.breakParent(tmp, startParent); + if (domUtils.isEmptyNode(tmp.previousSibling)) { + domUtils.remove(tmp.previousSibling); + } + if (domUtils.isEmptyNode(tmp.nextSibling)) { + domUtils.remove(tmp.nextSibling); + } + var nodeStyle = + getStyle(startParent) || + domUtils.getComputedStyle(startParent, "list-style-type") || + (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc"); + if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) { + for ( + var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); + (ci = frag.firstChild); + + ) { + if (domUtils.isTagNode(ci, "ol ul")) { + // 删除时,子列表不处理 + // utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){ + // while(li.firstChild){ + // tmpFrag.appendChild(li.firstChild); + // } + // + // }); + tmpFrag.appendChild(ci); + } else { + while (ci.firstChild) { + tmpFrag.appendChild(ci.firstChild); + domUtils.remove(ci); + } + } + } + tmp.parentNode.insertBefore(tmpFrag, tmp); + } else { + list = me.document.createElement(tag); + setListStyle(list, style); + list.appendChild(frag); + tmp.parentNode.insertBefore(list, tmp); + } + + domUtils.remove(tmp); + list && adjustList(list, tag, style); + range.moveToBookmark(bko).select(); + return; + } + //开始 + if (start) { + while (start) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, "ol ul")) { + frag.appendChild(start); + } else { + var tmpfrag = me.document.createDocumentFragment(), + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + var tmpP = me.document.createElement("p"); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + + start = tmp; + } + startParent.parentNode.insertBefore(frag, startParent.nextSibling); + if (domUtils.isEmptyNode(startParent)) { + range.setStartBefore(startParent); + domUtils.remove(startParent); + } else { + range.setStartAfter(startParent); + } + modifyStart = 1; + } + + if (end && domUtils.inDoc(endParent, me.document)) { + //结束 + start = endParent.firstChild; + while (start && start !== end) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, "ol ul")) { + frag.appendChild(start); + } else { + tmpfrag = me.document.createDocumentFragment(); + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + tmpP = me.document.createElement("p"); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + start = tmp; + } + var tmpDiv = domUtils.createElement(me.document, "div", { + tmpDiv: 1 + }); + domUtils.moveChild(end, tmpDiv); + + frag.appendChild(tmpDiv); + domUtils.remove(end); + endParent.parentNode.insertBefore(frag, endParent); + range.setEndBefore(endParent); + if (domUtils.isEmptyNode(endParent)) { + domUtils.remove(endParent); + } + + modifyEnd = 1; + } + } + + if (!modifyStart) { + range.setStartBefore(me.document.getElementById(bko.start)); + } + if (bko.end && !modifyEnd) { + range.setEndAfter(me.document.getElementById(bko.end)); + } + range.enlarge(true, function(node) { + return notExchange[node.tagName]; + }); + + frag = me.document.createDocumentFragment(); + + var bk = range.createBookmark(), + current = domUtils.getNextDomNode(bk.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode, + block = domUtils.isBlockElm; + + while ( + current && + current !== bk.end && + domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING + ) { + if (current.nodeType == 3 || dtd.li[current.tagName]) { + if (current.nodeType == 1 && dtd.$list[current.tagName]) { + while (current.firstChild) { + frag.appendChild(current.firstChild); + } + tmpNode = domUtils.getNextDomNode(current, false, filterFn); + domUtils.remove(current); + current = tmpNode; + continue; + } + tmpNode = current; + tmpRange.setStartBefore(current); + + while ( + current && + current !== bk.end && + (!block(current) || domUtils.isBookmarkNode(current)) + ) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function( + node + ) { + return !notExchange[node.tagName]; + }); + } + + if (current && block(current)) { + tmp = domUtils.getNextDomNode(tmpNode, false, filterFn); + if (tmp && domUtils.isBookmarkNode(tmp)) { + current = domUtils.getNextDomNode(tmp, false, filterFn); + tmpNode = tmp; + } + } + tmpRange.setEndAfter(tmpNode); + + current = domUtils.getNextDomNode(tmpNode, false, filterFn); + + var li = range.document.createElement("li"); + + li.appendChild(tmpRange.extractContents()); + if (domUtils.isEmptyNode(li)) { + var tmpNode = range.document.createElement("p"); + while (li.firstChild) { + tmpNode.appendChild(li.firstChild); + } + li.appendChild(tmpNode); + } + frag.appendChild(li); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + range.moveToBookmark(bk).collapse(true); + list = me.document.createElement(tag); + setListStyle(list, style); + list.appendChild(frag); + range.insertNode(list); + //当前list上下看能否合并 + adjustList(list, tag, style); + //去掉冗余的tmpDiv + for ( + var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); + (ci = tmpDivs[i++]); + + ) { + if (ci.getAttribute("tmpDiv")) { + domUtils.remove(ci, true); + } + } + range.moveToBookmark(bko).select(); + }, + queryCommandState: function(command) { + var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; + var path = this.selection.getStartElementPath(); + for (var i = 0, ci; (ci = path[i++]); ) { + if (ci.nodeName == "TABLE") { + return 0; + } + if (tag == ci.nodeName.toLowerCase()) { + return 1; + } + } + return 0; + }, + queryCommandValue: function(command) { + var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; + var path = this.selection.getStartElementPath(), + node; + for (var i = 0, ci; (ci = path[i++]); ) { + if (ci.nodeName == "TABLE") { + node = null; + break; + } + if (tag == ci.nodeName.toLowerCase()) { + node = ci; + break; + } + } + return node + ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type") + : null; + } + }; +}; + + +// plugins/source.js +/** + * 源码编辑插件 + * @file + * @since 1.2.6.1 + */ + +(function() { + var sourceEditors = { + textarea: function(editor, holder) { + var textarea = holder.ownerDocument.createElement("textarea"); + textarea.style.cssText = + "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;"; + // todo: IE下只有onresize属性可用... 很纠结 + if (browser.ie && browser.version < 8) { + textarea.style.width = holder.offsetWidth + "px"; + textarea.style.height = holder.offsetHeight + "px"; + holder.onresize = function() { + textarea.style.width = holder.offsetWidth + "px"; + textarea.style.height = holder.offsetHeight + "px"; + }; + } + holder.appendChild(textarea); + return { + setContent: function(content) { + textarea.value = content; + }, + getContent: function() { + return textarea.value; + }, + select: function() { + var range; + if (browser.ie) { + range = textarea.createTextRange(); + range.collapse(true); + range.select(); + } else { + //todo: chrome下无法设置焦点 + textarea.setSelectionRange(0, 0); + textarea.focus(); + } + }, + dispose: function() { + holder.removeChild(textarea); + // todo + holder.onresize = null; + textarea = null; + holder = null; + }, + focus: function (){ + textarea.focus(); + }, + blur: function (){ + textarea.blur(); + } + }; + }, + codemirror: function(editor, holder) { + var codeEditor = window.CodeMirror(holder, { + mode: "text/html", + tabMode: "indent", + lineNumbers: true, + lineWrapping: true, + onChange: function(v){ + editor.sync(); + editor.fireEvent("contentchange"); + // console.log('CodeMirror.onChange',v.getValue()); + } + }); + // console.log('sourceEditor',codeEditor); + var dom = codeEditor.getWrapperElement(); + dom.style.cssText = + 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;'; + codeEditor.getScrollerElement().style.cssText = + "position:absolute;left:0;top:0;width:100%;height:100%;"; + codeEditor.refresh(); + return { + getCodeMirror: function() { + return codeEditor; + }, + setContent: function(content) { + codeEditor.setValue(content); + }, + getContent: function() { + return codeEditor.getValue(); + }, + select: function() { + codeEditor.focus(); + }, + dispose: function() { + holder.removeChild(dom); + dom = null; + codeEditor = null; + }, + focus: function (){ + codeEditor.focus(); + }, + blur: function (){ + // codeEditor.blur(); + // since codemirror not support blur() + codeEditor.setOption('readOnly', true); + codeEditor.setOption('readOnly', false); + } + }; + } + }; + + UE.plugins["source"] = function() { + var me = this; + var opt = this.options; + var sourceMode = false; + var sourceEditor; + var orgSetContent; + var orgFocus; + var orgBlur; + opt.sourceEditor = browser.ie + ? "textarea" + : opt.sourceEditor || "codemirror"; + + me.setOpt({ + sourceEditorFirst: false + }); + function createSourceEditor(holder) { + return sourceEditors[ + opt.sourceEditor == "codemirror" && window.CodeMirror + ? "codemirror" + : "textarea" + ](me, holder); + } + + var bakCssText; + //解决在源码模式下getContent不能得到最新的内容问题 + var oldGetContent, bakAddress; + + /** + * 切换源码模式和编辑模式 + * @command source + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'source'); + * ``` + */ + + /** + * 查询当前编辑区域的状态是源码模式还是可视化模式 + * @command source + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前是源码编辑模式,返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'source' ); + * ``` + */ + + me.commands["source"] = { + execCommand: function() { + sourceMode = !sourceMode; + if (sourceMode) { + bakAddress = me.selection.getRange().createAddress(false, true); + me.undoManger && me.undoManger.save(true); + if (browser.gecko) { + me.body.contentEditable = false; + } + + bakCssText = me.iframe.style.cssText; + me.iframe.style.cssText += + "position:absolute;left:-32768px;top:-32768px;"; + + me.fireEvent("beforegetcontent"); + var root = UE.htmlparser(me.body.innerHTML); + me.filterOutputRule(root); + root.traversal(function(node) { + if (node.type == "element") { + switch (node.tagName) { + case "td": + case "th": + case "caption": + if (node.children && node.children.length == 1) { + if (node.firstChild().tagName == "br") { + node.removeChild(node.firstChild()); + } + } + break; + case "pre": + node.innerText(node.innerText().replace(/ /g, " ")); + } + } + }); + + me.fireEvent("aftergetcontent"); + + var content = root.toHtml(true); + + sourceEditor = createSourceEditor(me.iframe.parentNode); + + sourceEditor.setContent(content); + + orgSetContent = me.setContent; + + me.setContent = function(html) { + //这里暂时不触发事件,防止报错 + var root = UE.htmlparser(html); + me.filterInputRule(root); + html = root.toHtml(); + sourceEditor.setContent(html); + }; + + setTimeout(function() { + sourceEditor.select(); + me.addListener("fullscreenchanged", function() { + try { + sourceEditor.getCodeMirror().refresh(); + } catch (e) {} + }); + }); + + //重置getContent,源码模式下取值也能是最新的数据 + oldGetContent = me.getContent; + me.getContent = function() { + return ( + sourceEditor.getContent() || + "

    " + (browser.ie ? "" : "
    ") + "

    " + ); + }; + + orgFocus = me.focus; + orgBlur = me.blur; + + me.focus = function(){ + sourceEditor.focus(); + }; + + me.blur = function(){ + orgBlur.call(me); + sourceEditor.blur(); + }; + } else { + me.iframe.style.cssText = bakCssText; + var cont = + sourceEditor.getContent() || + "

    " + (browser.ie ? "" : "
    ") + "

    "; + //处理掉block节点前后的空格,有可能会误命中,暂时不考虑 + cont = cont.replace( + new RegExp("[\\r\\t\\n ]*]*)>", "g"), + function(a, b) { + if (b && !dtd.$inlineWithA[b.toLowerCase()]) { + return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, ""); + } + return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, ""); + } + ); + + me.setContent = orgSetContent; + + me.setContent(cont); + sourceEditor.dispose(); + sourceEditor = null; + //还原getContent方法 + me.getContent = oldGetContent; + + me.focus = orgFocus; + me.blur = orgBlur; + + var first = me.body.firstChild; + //trace:1106 都删除空了,下边会报错,所以补充一个p占位 + if (!first) { + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + first = me.body.firstChild; + } + + //要在ifm为显示时ff才能取到selection,否则报错 + //这里不能比较位置了 + me.undoManger && me.undoManger.save(true); + + if (browser.gecko) { + var input = document.createElement("input"); + input.style.cssText = "position:absolute;left:0;top:-32768px"; + + document.body.appendChild(input); + + me.body.contentEditable = false; + setTimeout(function() { + domUtils.setViewportOffset(input, { left: -32768, top: 0 }); + input.focus(); + setTimeout(function() { + me.body.contentEditable = true; + me.selection.getRange().moveToAddress(bakAddress).select(true); + domUtils.remove(input); + }); + }); + } else { + //ie下有可能报错,比如在代码顶头的情况 + try { + me.selection.getRange().moveToAddress(bakAddress).select(true); + } catch (e) {} + } + } + this.fireEvent("sourcemodechanged", sourceMode); + }, + queryCommandState: function() { + return sourceMode | 0; + }, + notNeedUndo: 1 + }; + var oldQueryCommandState = me.queryCommandState; + + me.queryCommandState = function(cmdName) { + cmdName = cmdName.toLowerCase(); + if (sourceMode) { + //源码模式下可以开启的命令 + return cmdName in + { + source: 1, + fullscreen: 1 + } + ? 1 + : -1; + } + return oldQueryCommandState.apply(this, arguments); + }; + + if (opt.sourceEditor == "codemirror") { + me.addListener("ready", function() { + utils.loadFile( + document, + { + src: + opt.codeMirrorJsUrl || + opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, + function() { + if (opt.sourceEditorFirst) { + setTimeout(function() { + me.execCommand("source"); + }, 0); + } + } + ); + utils.loadFile(document, { + tag: "link", + rel: "stylesheet", + type: "text/css", + href: + opt.codeMirrorCssUrl || + opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css?221123" + }); + }); + } + }; +})(); + + +// plugins/enterkey.js +///import core +///import plugins/undo.js +///commands 设置回车标签p或br +///commandsName EnterKey +///commandsTitle 设置回车标签p或br +/** + * @description 处理回车 + * @author zhanyi + */ +UE.plugins["enterkey"] = function() { + var hTag, + me = this, + tag = me.options.enterTag; + me.addListener("keyup", function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var range = me.selection.getRange(), + start = range.startContainer, + doSave; + + //修正在h1-h6里边回车后不能嵌套p的问题 + if (!browser.ie) { + if (/h\d/i.test(hTag)) { + if (browser.gecko) { + var h = domUtils.findParentByTagName( + start, + [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "caption", + "table" + ], + true + ); + if (!h) { + me.document.execCommand("formatBlock", false, "

    "); + doSave = 1; + } + } else { + //chrome remove div + if (start.nodeType == 1) { + var tmp = me.document.createTextNode(""), + div; + range.insertNode(tmp); + div = domUtils.findParentByTagName(tmp, "div", true); + if (div) { + var p = me.document.createElement("p"); + while (div.firstChild) { + p.appendChild(div.firstChild); + } + div.parentNode.insertBefore(p, div); + domUtils.remove(div); + range.setStartBefore(tmp).setCursor(); + doSave = 1; + } + domUtils.remove(tmp); + } + } + + if (me.undoManger && doSave) { + me.undoManger.save(); + } + } + //没有站位符,会出现多行的问题 + browser.opera && range.select(); + } else { + me.fireEvent("saveScene", true, true); + } + } + }); + + me.addListener("keydown", function(type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + //回车 + if (me.fireEvent("beforeenterkeydown")) { + domUtils.preventDefault(evt); + return; + } + me.fireEvent("saveScene", true, true); + hTag = ""; + + var range = me.selection.getRange(); + + if (!range.collapsed) { + //跨td不能删 + var start = range.startContainer, + end = range.endContainer, + startTd = domUtils.findParentByTagName(start, "td", true), + endTd = domUtils.findParentByTagName(end, "td", true); + if ( + (startTd && endTd && startTd !== endTd) || + (!startTd && endTd) || + (startTd && !endTd) + ) { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + return; + } + } + if (tag == "p") { + if (!browser.ie) { + start = domUtils.findParentByTagName( + range.startContainer, + [ + "ol", + "ul", + "p", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "caption" + ], + true + ); + + //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command + //trace:2431 + if (!start && !browser.opera) { + me.document.execCommand("formatBlock", false, "

    "); + + if (browser.gecko) { + range = me.selection.getRange(); + start = domUtils.findParentByTagName( + range.startContainer, + "p", + true + ); + start && domUtils.removeDirtyAttr(start); + } + } else { + hTag = start.tagName; + start.tagName.toLowerCase() == "p" && + browser.gecko && + domUtils.removeDirtyAttr(start); + } + } + } else { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + + if (!range.collapsed) { + range.deleteContents(); + start = range.startContainer; + if ( + start.nodeType == 1 && + (start = start.childNodes[range.startOffset]) + ) { + while (start.nodeType == 1) { + if (dtd.$empty[start.tagName]) { + range.setStartBefore(start).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + if (!start.firstChild) { + var br = range.document.createElement("br"); + start.appendChild(br); + range.setStart(start, 0).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + start = start.firstChild; + } + if (start === range.startContainer.childNodes[range.startOffset]) { + br = range.document.createElement("br"); + range.insertNode(br).setCursor(); + } else { + range.setStart(start, 0).setCursor(); + } + } else { + br = range.document.createElement("br"); + range.insertNode(br).setStartAfter(br).setCursor(); + } + } else { + br = range.document.createElement("br"); + range.insertNode(br); + var parent = br.parentNode; + if (parent.lastChild === br) { + br.parentNode.insertBefore(br.cloneNode(true), br); + range.setStartBefore(br); + } else { + range.setStartAfter(br); + } + range.setCursor(); + } + } + } + }); +}; + + +// plugins/keystrokes.js +/* 处理特殊键的兼容性问题 */ +UE.plugins["keystrokes"] = function() { + var me = this; + var collapsed = true; + me.addListener("keydown", function(type, evt) { + var keyCode = evt.keyCode || evt.which, + rng = me.selection.getRange(); + + //处理全选的情况 + if ( + !rng.collapsed && + !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && + ((keyCode >= 65 && keyCode <= 90) || + (keyCode >= 48 && keyCode <= 57) || + (keyCode >= 96 && keyCode <= 111) || + { + 13: 1, + 8: 1, + 46: 1 + }[keyCode]) + ) { + var tmpNode = rng.startContainer; + if (domUtils.isFillChar(tmpNode)) { + rng.setStartBefore(tmpNode); + } + tmpNode = rng.endContainer; + if (domUtils.isFillChar(tmpNode)) { + rng.setEndAfter(tmpNode); + } + rng.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if (rng.endContainer && rng.endContainer.nodeType == 1) { + tmpNode = rng.endContainer.childNodes[rng.endOffset]; + if (tmpNode && domUtils.isBr(tmpNode)) { + rng.setEndAfter(tmpNode); + } + } + if (rng.startOffset == 0) { + tmpNode = rng.startContainer; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + tmpNode = rng.endContainer; + if ( + rng.endOffset == + (tmpNode.nodeType == 3 + ? tmpNode.nodeValue.length + : tmpNode.childNodes.length) && + domUtils.isBoundaryNode(tmpNode, "lastChild") + ) { + me.fireEvent("saveScene"); + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + rng.setStart(me.body.firstChild, 0).setCursor(false, true); + me._selectionChange(); + return; + } + } + } + } + + //处理backspace + if (keyCode == keymap.Backspace) { + rng = me.selection.getRange(); + collapsed = rng.collapsed; + if (me.fireEvent("delkeydown", evt)) { + return; + } + var start, end; + //避免按两次删除才能生效的问题 + if (rng.collapsed && rng.inFillChar()) { + start = rng.startContainer; + + if (domUtils.isFillChar(start)) { + rng.setStartBefore(start).shrinkBoundary(true).collapse(true); + domUtils.remove(start); + } else { + start.nodeValue = start.nodeValue.replace( + new RegExp("^" + domUtils.fillChar), + "" + ); + rng.startOffset--; + rng.collapse(true).select(true); + } + } + + //解决选中control元素不能删除的问题 + if ((start = rng.getClosedNode())) { + me.fireEvent("saveScene"); + rng.setStartBefore(start); + domUtils.remove(start); + rng.setCursor(); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + //阻止在table上的删除 + if (!browser.ie) { + start = domUtils.findParentByTagName(rng.startContainer, "table", true); + end = domUtils.findParentByTagName(rng.endContainer, "table", true); + if ((start && !end) || (!start && end) || start !== end) { + evt.preventDefault(); + return; + } + } + } + //处理tab键的逻辑 + if (keyCode == keymap.Tab) { + //不处理以下标签 + var excludeTagNameForTabKey = { + ol: 1, + ul: 1, + table: 1 + }; + //处理组件里的tab按下事件 + if (me.fireEvent("tabkeydown", evt)) { + domUtils.preventDefault(evt); + return; + } + var range = me.selection.getRange(); + me.fireEvent("saveScene"); + for ( + var i = 0, + txt = "", + tabSize = me.options.tabSize || 4, + tabNode = me.options.tabNode || " "; + i < tabSize; + i++ + ) { + txt += tabNode; + } + var span = me.document.createElement("span"); + span.innerHTML = txt + domUtils.fillChar; + if (range.collapsed) { + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var filterFn = function(node) { + return ( + domUtils.isBlockElm(node) && + !excludeTagNameForTabKey[node.tagName.toLowerCase()] + ); + }; + //普通的情况 + start = domUtils.findParent(range.startContainer, filterFn, true); + end = domUtils.findParent(range.endContainer, filterFn, true); + if (start && end && start === end) { + range.deleteContents(); + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var bookmark = range.createBookmark(); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + current.insertBefore( + span.cloneNode(true).firstChild, + current.firstChild + ); + current = domUtils.getNextDomNode(current, false, filterFn); + } + range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); + } + } + domUtils.preventDefault(evt); + } + //trace:1634 + //ff的del键在容器空的时候,也会删除 + if (browser.gecko && keyCode == 46) { + range = me.selection.getRange(); + if (range.collapsed) { + start = range.startContainer; + if (domUtils.isEmptyBlock(start)) { + var parent = start.parentNode; + while ( + domUtils.getChildCount(parent) == 1 && + !domUtils.isBody(parent) + ) { + start = parent; + parent = parent.parentNode; + } + if (start === parent.lastChild) evt.preventDefault(); + return; + } + } + } + + /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */ + browser.chrome && + me.on("keydown", function(type, e) { + var keyCode = e.keyCode || e.which; + if ( + ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) && + keyCode == 73 + ) { + return true; + } + }); + }); + me.addListener("keyup", function(type, evt) { + var keyCode = evt.keyCode || evt.which, + rng, + me = this; + if (keyCode == keymap.Backspace) { + if (me.fireEvent("delkeyup")) { + return; + } + rng = me.selection.getRange(); + if (rng.collapsed) { + var tmpNode, + autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"]; + if ( + (tmpNode = domUtils.findParentByTagName( + rng.startContainer, + autoClearTagName, + true + )) + ) { + if (domUtils.isEmptyBlock(tmpNode)) { + var pre = tmpNode.previousSibling; + if (pre && pre.nodeName != "TABLE") { + domUtils.remove(tmpNode); + rng.setStartAtLast(pre).setCursor(false, true); + return; + } else { + var next = tmpNode.nextSibling; + if (next && next.nodeName != "TABLE") { + domUtils.remove(tmpNode); + rng.setStartAtFirst(next).setCursor(false, true); + return; + } + } + } + } + //处理当删除到body时,要重新给p标签展位 + if (domUtils.isBody(rng.startContainer)) { + var tmpNode = domUtils.createElement(me.document, "p", { + innerHTML: browser.ie ? domUtils.fillChar : "
    " + }); + rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true); + } + } + + //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了 + if ( + !collapsed && + (rng.startContainer.nodeType == 3 || + (rng.startContainer.nodeType == 1 && + domUtils.isEmptyBlock(rng.startContainer))) + ) { + if (browser.ie) { + var span = rng.document.createElement("span"); + rng.insertNode(span).setStartBefore(span).collapse(true); + rng.select(); + domUtils.remove(span); + } else { + rng.select(); + } + } + } + }); +}; + + +// plugins/fiximgclick.js +///import core +///commands 修复chrome下图片不能点击的问题,出现八个角可改变大小 +///commandsName FixImgClick +///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小 +//修复chrome下图片不能点击的问题,出现八个角可改变大小 + +UE.plugins["fiximgclick"] = (function() { + var elementUpdated = false; + function Scale() { + this.editor = null; + this.resizer = null; + this.cover = null; + this.doc = document; + this.prePos = { x: 0, y: 0 }; + this.startPos = { x: 0, y: 0 }; + } + + (function() { + var rect = [ + //[left, top, width, height] + [0, 0, -1, -1], + [0, 0, 0, -1], + [0, 0, 1, -1], + [0, 0, -1, 0], + [0, 0, 1, 0], + [0, 0, -1, 1], + [0, 0, 0, 1], + [0, 0, 1, 1] + ]; + + Scale.prototype = { + init: function(editor) { + var me = this; + me.editor = editor; + me.startPos = this.prePos = { x: 0, y: 0 }; + me.dragId = -1; + + var hands = [], + cover = (me.cover = document.createElement("div")), + resizer = (me.resizer = document.createElement("div")); + + cover.id = me.editor.ui.id + "_imagescale_cover"; + cover.style.cssText = + "position:absolute;display:none;z-index:" + + me.editor.options.zIndex + + ";filter:alpha(opacity=0); opacity:0;background:#CCC;"; + domUtils.on(cover, "mousedown click", function() { + me.hide(); + }); + + for (i = 0; i < 8; i++) { + hands.push( + '' + ); + } + resizer.id = me.editor.ui.id + "_imagescale"; + resizer.className = "edui-editor-imagescale"; + resizer.innerHTML = hands.join(""); + resizer.style.cssText += + ";display:none;border:1px solid #3b77ff;z-index:" + + me.editor.options.zIndex + + ";"; + + me.editor.ui.getDom().appendChild(cover); + me.editor.ui.getDom().appendChild(resizer); + + me.initStyle(); + me.initEvents(); + }, + initStyle: function() { + utils.cssRule( + "imagescale", + ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" + + ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}" + ); + }, + initEvents: function() { + var me = this; + + me.startPos.x = me.startPos.y = 0; + me.isDraging = false; + }, + _eventHandler: function(e) { + var me = this; + switch (e.type) { + case "mousedown": + var hand = e.target || e.srcElement, + hand; + if ( + hand.className.indexOf("edui-editor-imagescale-hand") != -1 && + me.dragId == -1 + ) { + me.dragId = hand.className.slice(-1); + me.startPos.x = me.prePos.x = e.clientX; + me.startPos.y = me.prePos.y = e.clientY; + domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me)); + } + break; + case "mousemove": + if (me.dragId != -1) { + me.updateContainerStyle(me.dragId, { + x: e.clientX - me.prePos.x, + y: e.clientY - me.prePos.y + }); + me.prePos.x = e.clientX; + me.prePos.y = e.clientY; + elementUpdated = true; + me.updateTargetElement(); + } + break; + case "mouseup": + if (me.dragId != -1) { + me.updateContainerStyle(me.dragId, { + x: e.clientX - me.prePos.x, + y: e.clientY - me.prePos.y + }); + me.updateTargetElement(); + if (me.target.parentNode) me.attachTo(me.target); + me.dragId = -1; + } + domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me)); + //修复只是点击挪动点,但没有改变大小,不应该触发contentchange + if (elementUpdated) { + elementUpdated = false; + me.editor.fireEvent("contentchange"); + } + + break; + default: + break; + } + }, + updateTargetElement: function() { + var me = this; + domUtils.setStyles(me.target, { + width: me.resizer.style.width, + height: me.resizer.style.height + }); + me.target.width = parseInt(me.resizer.style.width); + me.target.height = parseInt(me.resizer.style.height); + me.attachTo(me.target); + }, + updateContainerStyle: function(dir, offset) { + var me = this, + dom = me.resizer, + tmp; + + if (rect[dir][0] != 0) { + tmp = parseInt(dom.style.left) + offset.x; + dom.style.left = me._validScaledProp("left", tmp) + "px"; + } + if (rect[dir][1] != 0) { + tmp = parseInt(dom.style.top) + offset.y; + dom.style.top = me._validScaledProp("top", tmp) + "px"; + } + if (rect[dir][2] != 0) { + tmp = dom.clientWidth + rect[dir][2] * offset.x; + dom.style.width = me._validScaledProp("width", tmp) + "px"; + } + if (rect[dir][3] != 0) { + tmp = dom.clientHeight + rect[dir][3] * offset.y; + dom.style.height = me._validScaledProp("height", tmp) + "px"; + } + }, + _validScaledProp: function(prop, value) { + var ele = this.resizer, + wrap = document; + + value = isNaN(value) ? 0 : value; + switch (prop) { + case "left": + return value < 0 + ? 0 + : value + ele.clientWidth > wrap.clientWidth + ? wrap.clientWidth - ele.clientWidth + : value; + case "top": + return value < 0 + ? 0 + : value + ele.clientHeight > wrap.clientHeight + ? wrap.clientHeight - ele.clientHeight + : value; + case "width": + return value <= 0 + ? 1 + : value + ele.offsetLeft > wrap.clientWidth + ? wrap.clientWidth - ele.offsetLeft + : value; + case "height": + return value <= 0 + ? 1 + : value + ele.offsetTop > wrap.clientHeight + ? wrap.clientHeight - ele.offsetTop + : value; + } + }, + hideCover: function() { + this.cover.style.display = "none"; + }, + showCover: function() { + var me = this, + editorPos = domUtils.getXY(me.editor.ui.getDom()), + iframePos = domUtils.getXY(me.editor.iframe); + + domUtils.setStyles(me.cover, { + width: me.editor.iframe.offsetWidth + "px", + height: me.editor.iframe.offsetHeight + "px", + top: iframePos.y - editorPos.y + "px", + left: iframePos.x - editorPos.x + "px", + position: "absolute", + display: "" + }); + }, + show: function(targetObj) { + var me = this; + me.resizer.style.display = "block"; + if (targetObj) me.attachTo(targetObj); + + domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me)); + domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me)); + + me.showCover(); + me.editor.fireEvent("afterscaleshow", me); + me.editor.fireEvent("saveScene"); + }, + hide: function() { + var me = this; + me.hideCover(); + me.resizer.style.display = "none"; + + domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me)); + domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me)); + me.editor.fireEvent("afterscalehide", me); + }, + proxy: function(fn, context) { + return function(e) { + return fn.apply(context || this, arguments); + }; + }, + attachTo: function(targetObj) { + var me = this, + target = (me.target = targetObj), + resizer = this.resizer, + imgPos = domUtils.getXY(target), + iframePos = domUtils.getXY(me.editor.iframe), + editorPos = domUtils.getXY(resizer.parentNode); + + domUtils.setStyles(resizer, { + width: target.width + "px", + height: target.height + "px", + left: + iframePos.x + + imgPos.x - + me.editor.document.body.scrollLeft - + editorPos.x - + parseInt(resizer.style.borderLeftWidth) + + "px", + top: + iframePos.y + + imgPos.y - + me.editor.document.body.scrollTop - + editorPos.y - + parseInt(resizer.style.borderTopWidth) + + "px" + }); + } + }; + })(); + + return function() { + var me = this, + imageScale; + + me.setOpt("imageScaleEnabled", true); + + if (!browser.ie && me.options.imageScaleEnabled) { + me.addListener("click", function(type, e) { + var range = me.selection.getRange(), + img = range.getClosedNode(); + + if (img && img.tagName == "IMG" && me.body.contentEditable != "false") { + if ( + img.getAttribute("anchorname") || + domUtils.hasClass(img, "loadingclass") || + domUtils.hasClass(img, "loaderrorclass") + ) { + return; + } + + if (!imageScale) { + imageScale = new Scale(); + imageScale.init(me); + me.ui.getDom().appendChild(imageScale.resizer); + + var _keyDownHandler = function(e) { + imageScale.hide(); + if (imageScale.target) + me.selection.getRange().selectNode(imageScale.target).select(); + }, + _mouseDownHandler = function(e) { + var ele = e.target || e.srcElement; + if ( + ele && + (ele.className === undefined || + ele.className.indexOf("edui-editor-imagescale") == -1) + ) { + _keyDownHandler(e); + } + }, + timer; + + me.addListener("afterscaleshow", function(e) { + me.addListener("beforekeydown", _keyDownHandler); + me.addListener("beforemousedown", _mouseDownHandler); + domUtils.on(document, "keydown", _keyDownHandler); + domUtils.on(document, "mousedown", _mouseDownHandler); + me.selection.getNative().removeAllRanges(); + }); + me.addListener("afterscalehide", function(e) { + me.removeListener("beforekeydown", _keyDownHandler); + me.removeListener("beforemousedown", _mouseDownHandler); + domUtils.un(document, "keydown", _keyDownHandler); + domUtils.un(document, "mousedown", _mouseDownHandler); + var target = imageScale.target; + if (target.parentNode) { + me.selection.getRange().selectNode(target).select(); + } + }); + //TODO 有iframe的情况,mousedown不能往下传。。 + domUtils.on(imageScale.resizer, "mousedown", function(e) { + me.selection.getNative().removeAllRanges(); + var ele = e.target || e.srcElement; + if ( + ele && + ele.className.indexOf("edui-editor-imagescale-hand") == -1 + ) { + timer = setTimeout(function() { + imageScale.hide(); + if (imageScale.target) + me.selection.getRange().selectNode(ele).select(); + }, 200); + } + }); + domUtils.on(imageScale.resizer, "mouseup", function(e) { + var ele = e.target || e.srcElement; + if ( + ele && + ele.className.indexOf("edui-editor-imagescale-hand") == -1 + ) { + clearTimeout(timer); + } + }); + } + imageScale.show(img); + } else { + if (imageScale && imageScale.resizer.style.display != "none") + imageScale.hide(); + } + }); + } + + if (browser.webkit) { + me.addListener("click", function(type, e) { + if (e.target.tagName == "IMG" && me.body.contentEditable != "false") { + var range = new dom.Range(me.document); + range.selectNode(e.target).select(); + } + }); + } + }; +})(); + + +// plugins/autolink.js +///import core +///commands 为非ie浏览器自动添加a标签 +///commandsName AutoLink +///commandsTitle 自动增加链接 +/** + * @description 为非ie浏览器自动添加a标签 + * @author zhanyi + */ + +UE.plugin.register( + "autolink", + function() { + var cont = 0; + + return !browser.ie + ? { + bindEvents: { + reset: function() { + cont = 0; + }, + keydown: function(type, evt) { + var me = this; + var keyCode = evt.keyCode || evt.which; + + if (keyCode == 32 || keyCode == 13) { + var sel = me.selection.getNative(), + range = sel.getRangeAt(0).cloneRange(), + offset, + charCode; + + var start = range.startContainer; + while (start.nodeType == 1 && range.startOffset > 0) { + start = + range.startContainer.childNodes[range.startOffset - 1]; + if (!start) { + break; + } + range.setStart( + start, + start.nodeType == 1 + ? start.childNodes.length + : start.nodeValue.length + ); + range.collapse(true); + start = range.startContainer; + } + + do { + if (range.startOffset == 0) { + start = range.startContainer.previousSibling; + + while (start && start.nodeType == 1) { + start = start.lastChild; + } + if (!start || domUtils.isFillChar(start)) { + break; + } + offset = start.nodeValue.length; + } else { + start = range.startContainer; + offset = range.startOffset; + } + range.setStart(start, offset - 1); + charCode = range.toString().charCodeAt(0); + } while (charCode != 160 && charCode != 32); + + if ( + range + .toString() + .replace(new RegExp(domUtils.fillChar, "g"), "") + .match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i) + ) { + while (range.toString().length) { + if ( + /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test( + range.toString() + ) + ) { + break; + } + try { + range.setStart( + range.startContainer, + range.startOffset + 1 + ); + } catch (e) { + //trace:2121 + var start = range.startContainer; + while (!(next = start.nextSibling)) { + if (domUtils.isBody(start)) { + return; + } + start = start.parentNode; + } + range.setStart(next, 0); + } + } + //range的开始边界已经在a标签里的不再处理 + if ( + domUtils.findParentByTagName( + range.startContainer, + "a", + true + ) + ) { + return; + } + var a = me.document.createElement("a"), + text = me.document.createTextNode(" "), + href; + + me.undoManger && me.undoManger.save(); + a.appendChild(range.extractContents()); + a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, ""); + href = a + .getAttribute("href") + .replace(new RegExp(domUtils.fillChar, "g"), ""); + href = /^(?:https?:\/\/)/gi.test(href) + ? href + : "http://" + href; + a.setAttribute("_src", utils.html(href)); + a.href = utils.html(href); + + range.insertNode(a); + a.parentNode.insertBefore(text, a.nextSibling); + range.setStart(text, 0); + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + me.undoManger && me.undoManger.save(); + } + } + } + } + } + : {}; + }, + function() { + var keyCodes = { + 37: 1, + 38: 1, + 39: 1, + 40: 1, + 13: 1, + 32: 1 + }; + function checkIsCludeLink(node) { + if (node.nodeType == 3) { + return null; + } + if (node.nodeName == "A") { + return node; + } + var lastChild = node.lastChild; + + while (lastChild) { + if (lastChild.nodeName == "A") { + return lastChild; + } + if (lastChild.nodeType == 3) { + if (domUtils.isWhitespace(lastChild)) { + lastChild = lastChild.previousSibling; + continue; + } + return null; + } + lastChild = lastChild.lastChild; + } + } + browser.ie && + this.addListener("keyup", function(cmd, evt) { + var me = this, + keyCode = evt.keyCode; + if (keyCodes[keyCode]) { + var rng = me.selection.getRange(); + var start = rng.startContainer; + + if (keyCode == 13) { + while ( + start && + !domUtils.isBody(start) && + !domUtils.isBlockElm(start) + ) { + start = start.parentNode; + } + if (start && !domUtils.isBody(start) && start.nodeName == "P") { + var pre = start.previousSibling; + if (pre && pre.nodeType == 1) { + var pre = checkIsCludeLink(pre); + if (pre && !pre.getAttribute("_href")) { + domUtils.remove(pre, true); + } + } + } + } else if (keyCode == 32) { + if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) { + start = start.previousSibling; + if ( + start && + start.nodeName == "A" && + !start.getAttribute("_href") + ) { + domUtils.remove(start, true); + } + } + } else { + start = domUtils.findParentByTagName(start, "a", true); + if (start && !start.getAttribute("_href")) { + var bk = rng.createBookmark(); + + domUtils.remove(start, true); + rng.moveToBookmark(bk).select(true); + } + } + } + }); + } +); + + +// plugins/autoheight.js +///import core +///commands 当输入内容超过编辑器高度时,编辑器自动增高 +///commandsName AutoHeight,autoHeightEnabled +///commandsTitle 自动增高 +/** + * @description 自动伸展 + * @author zhanyi + */ +UE.plugins["autoheight"] = function() { + var me = this; + //提供开关,就算加载也可以关闭 + me.autoHeightEnabled = me.options.autoHeightEnabled !== false; + if (!me.autoHeightEnabled) { + return; + } + + var bakOverflow, + lastHeight = 0, + options = me.options, + currentHeight, + timer; + + function adjustHeight() { + var me = this; + clearTimeout(timer); + if (isFullscreen) return; + if ( + !me.queryCommandState || + (me.queryCommandState && me.queryCommandState("source") != 1) + ) { + timer = setTimeout(function() { + var node = me.body.lastChild; + while (node && node.nodeType != 1) { + node = node.previousSibling; + } + if (node && node.nodeType == 1) { + node.style.clear = "both"; + currentHeight = Math.max( + domUtils.getXY(node).y + node.offsetHeight + 25, + Math.max(options.minFrameHeight, options.initialFrameHeight) + ); + if (currentHeight !== lastHeight) { + me.iframe.parentNode.style.transition = 'width 0.3s, height 0.3s, easy-in-out'; + if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) { + me.iframe.parentNode.style.height = currentHeight + "px"; + } + me.body.style.height = currentHeight + "px"; + lastHeight = currentHeight; + } + domUtils.removeStyle(node, "clear"); + } + }, 50); + } + } + var isFullscreen; + me.addListener("fullscreenchanged", function(cmd, f) { + isFullscreen = f; + }); + me.addListener("destroy", function() { + domUtils.un(me.window, "scroll", fixedScrollTop); + me.removeListener( + "contentchange afterinserthtml keyup mouseup", + adjustHeight + ); + }); + me.enableAutoHeight = function() { + var me = this; + if (!me.autoHeightEnabled) { + return; + } + var doc = me.document; + me.autoHeightEnabled = true; + bakOverflow = doc.body.style.overflowY; + doc.body.style.overflowY = "hidden"; + me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight); + //ff不给事件算得不对 + + setTimeout(function() { + adjustHeight.call(me); + }, browser.gecko ? 100 : 0); + me.fireEvent("autoheightchanged", me.autoHeightEnabled); + }; + me.disableAutoHeight = function() { + me.body.style.overflowY = bakOverflow || ""; + + me.removeListener("contentchange", adjustHeight); + me.removeListener("keyup", adjustHeight); + me.removeListener("mouseup", adjustHeight); + me.autoHeightEnabled = false; + me.fireEvent("autoheightchanged", me.autoHeightEnabled); + }; + + me.on("setHeight", function() { + me.disableAutoHeight(); + }); + me.addListener("ready", function() { + me.enableAutoHeight(); + //trace:1764 + var timer; + domUtils.on( + browser.ie ? me.body : me.document, + browser.webkit ? "dragover" : "drop", + function() { + clearTimeout(timer); + timer = setTimeout(function() { + //trace:3681 + adjustHeight.call(me); + }, 100); + } + ); + //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题 + 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; + } + } +}; + + +// plugins/autofloat.js +///import core +///commands 悬浮工具栏 +///commandsName AutoFloat,autoFloatEnabled +///commandsTitle 悬浮工具栏 +/** + * modified by chengchao01 + * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! + */ +UE.plugins["autofloat"] = function() { + var me = this, + lang = me.getLang(); + me.setOpt({ + topOffset: 0 + }); + var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, + topOffset = me.options.topOffset; + + //如果不固定toolbar的位置,则直接退出 + if (!optsAutoFloatEnabled) { + return; + } + var uiUtils = UE.ui.uiUtils, + LteIE6 = browser.ie && browser.version <= 6, + quirks = browser.quirks; + + function checkHasUI() { + if (!UE.ui) { + alert(lang.autofloatMsg); + return 0; + } + return 1; + } + function fixIE6FixedPos() { + var docStyle = document.body.style; + docStyle.backgroundImage = 'url("about:blank")'; + docStyle.backgroundAttachment = "fixed"; + } + var bakCssText, + placeHolder = document.createElement("div"), + toolbarBox, + orgTop, + getPosition, + flag = true; //ie7模式下需要偏移 + function setFloating() { + var toobarBoxPos = domUtils.getXY(toolbarBox), + origalFloat = domUtils.getComputedStyle(toolbarBox, "position"), + origalLeft = domUtils.getComputedStyle(toolbarBox, "left"); + toolbarBox.style.width = toolbarBox.offsetWidth + "px"; + toolbarBox.style.zIndex = me.options.zIndex * 1 + 1; + toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); + if (LteIE6 || (quirks && browser.ie)) { + if (toolbarBox.style.position != "absolute") { + toolbarBox.style.position = "absolute"; + } + toolbarBox.style.top = + (document.body.scrollTop || document.documentElement.scrollTop) - + orgTop + + topOffset + + "px"; + } else { + if (browser.ie7Compat && flag) { + flag = false; + toolbarBox.style.left = + domUtils.getXY(toolbarBox).x - + document.documentElement.getBoundingClientRect().left + + 2 + + "px"; + } + if (toolbarBox.style.position != "fixed") { + toolbarBox.style.position = "fixed"; + toolbarBox.style.top = topOffset + "px"; + (origalFloat == "absolute" || origalFloat == "relative") && + parseFloat(origalLeft) && + (toolbarBox.style.left = toobarBoxPos.x + "px"); + } + } + } + function unsetFloating() { + flag = true; + if (placeHolder.parentNode) { + placeHolder.parentNode.removeChild(placeHolder); + } + + toolbarBox.style.cssText = bakCssText; + } + + me.unsetFloating = unsetFloating; + + function updateFloating() { + var rect3 = getPosition(me.container); + var offset = me.options.toolbarTopOffset || 0; + if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) { + setFloating(); + } else { + unsetFloating(); + } + } + var defer_updateFloating = utils.defer( + function() { + updateFloating(); + }, + browser.ie ? 200 : 100, + true + ); + + me.addListener("destroy", function() { + domUtils.un(window, ["scroll", "resize"], updateFloating); + me.removeListener("keydown", defer_updateFloating); + }); + + me.addListener("ready", function() { + if (checkHasUI(me)) { + //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断 + if (!me.ui) { + return; + } + getPosition = uiUtils.getClientRect; + toolbarBox = me.ui.getDom("toolbarbox"); + orgTop = getPosition(toolbarBox).top; + bakCssText = toolbarBox.style.cssText; + placeHolder.style.height = toolbarBox.offsetHeight + "px"; + if (LteIE6) { + fixIE6FixedPos(); + } + domUtils.on(window, ["scroll", "resize"], updateFloating); + me.addListener("keydown", defer_updateFloating); + + me.addListener("beforefullscreenchange", function(t, enabled) { + if (enabled) { + unsetFloating(); + } + }); + me.addListener("fullscreenchanged", function(t, enabled) { + if (!enabled) { + updateFloating(); + } + }); + me.addListener("sourcemodechanged", function(t, enabled) { + setTimeout(function() { + updateFloating(); + }, 0); + }); + me.addListener("clearDoc", function() { + setTimeout(function() { + updateFloating(); + }, 0); + }); + } + }); +}; + + +// plugins/video.js +/** + * video插件, 为UEditor提供视频插入支持 + * @file + * @since 1.2.6.1 + */ + +UE.plugins["video"] = function() { + var me = this; + + /** + * 创建插入视频字符窜 + * @param url 视频地址 + * @param width 视频宽度 + * @param height 视频高度 + * @param align 视频对齐 + * @param toEmbed 是否以flash代替显示 + * @param addParagraph 是否需要添加P 标签 + */ + function creatInsertStr(url, width, height, id, align, classname, type) { + var str; + switch (type) { + case 'iframe': + str = '' + + '
    ' + + '
    ' + + this.getContentHtmlTpl() + + "
    " + + " " + + "" + ); + }, + getContentHtmlTpl: function() { + if (this.content) { + if (typeof this.content == "string") { + return this.content; + } + return this.content.renderHtml(); + } else { + return ""; + } + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function() { + if (this.content instanceof UIBase) { + this.content.postRender(); + } + + //捕获鼠标滚轮 + if (this.captureWheel && !this.captured) { + this.captured = true; + + var winHeight = + (document.documentElement.clientHeight || + document.body.clientHeight) - 80, + _height = this.getDom().offsetHeight, + _top = uiUtils.getClientRect(this.combox.getDom()).top, + content = this.getDom("content"), + ifr = this.getDom("body").getElementsByTagName("iframe"), + me = this; + + ifr.length && (ifr = ifr[0]); + + while (_top + _height > winHeight) { + _height -= 30; + } + content.style.height = _height + "px"; + //同步更改iframe高度 + ifr && (ifr.style.height = _height + "px"); + + //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解 + domUtils.on( + content, + "onmousewheel" in document.body ? "mousewheel" : "DOMMouseScroll", + function(e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + + if (e.wheelDelta) { + content.scrollTop -= e.wheelDelta / 120 * 60; + } else { + content.scrollTop -= e.detail / -3 * 60; + } + } + ); + } + this.fireEvent("postRenderAfter"); + this.hide(true); + this._UIBase_postRender(); + }, + _doAutoRender: function() { + if (!this.getDom() && this.autoRender) { + this.render(); + } + }, + mesureSize: function() { + var box = this.getDom("content"); + return uiUtils.getClientRect(box); + }, + fitSize: function() { + // console.log('fitSize.popup') + if (this.captureWheel && this.sized) { + return this.__size; + } + this.sized = true; + var popBodyEl = this.getDom("body"); + popBodyEl.style.width = ""; + popBodyEl.style.height = ""; + var size = this.mesureSize(); + if (this.captureWheel) { + popBodyEl.style.width = -(-20 - size.width) + "px"; + var height = parseInt(this.getDom("content").style.height, 10); + !window.isNaN(height) && (size.height = height); + } else { + popBodyEl.style.width = size.width + "px"; + } + popBodyEl.style.height = size.height + "px"; + this.__size = size; + this.captureWheel && (this.getDom("content").style.overflow = "auto"); + return size; + }, + showAnchor: function(element, hoz) { + this.showAnchorRect(uiUtils.getClientRect(element), hoz); + }, + showAnchorRect: function(rect, hoz, adj) { + this._doAutoRender(); + var vpRect = uiUtils.getViewportRect(); + this.getDom().style.visibility = "hidden"; + this._show(); + var popSize = this.fitSize(); + + var sideLeft, sideUp, left, top; + if (hoz) { + sideLeft = + this.canSideLeft && + (rect.right + popSize.width > vpRect.right && + rect.left > popSize.width); + sideUp = + this.canSideUp && + (rect.top + popSize.height > vpRect.bottom && + rect.bottom > popSize.height); + left = sideLeft ? rect.left - popSize.width : rect.right; + top = sideUp ? rect.bottom - popSize.height : rect.top; + } else { + sideLeft = + this.canSideLeft && + (rect.right + popSize.width > vpRect.right && + rect.left > popSize.width); + sideUp = + this.canSideUp && + (rect.top + popSize.height > vpRect.bottom && + rect.bottom > popSize.height); + left = sideLeft ? rect.right - popSize.width : rect.left; + top = sideUp ? rect.top - popSize.height : rect.bottom; + } + if(!sideUp){ + if(top + popSize.height > vpRect.bottom){ + top = vpRect.bottom - popSize.height + } + } + // console.log('popup.showAnchorRect', vpRect, rect, hoz, sideUp, sideLeft, left, top); + + var popEl = this.getDom(); + uiUtils.setViewportOffset(popEl, { + left: left, + top: top + }); + domUtils.removeClasses(popEl, ANCHOR_CLASSES); + popEl.className += + " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)]; + if (this.editor) { + popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10; + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = + popEl.style.zIndex - 1; + } + this.getDom().style.visibility = "visible"; + }, + showAt: function(offset) { + var left = offset.left; + var top = offset.top; + var rect = { + left: left, + top: top, + right: left, + bottom: top, + height: 0, + width: 0 + }; + this.showAnchorRect(rect, false, true); + }, + _show: function() { + if (this._hidden) { + var box = this.getDom(); + box.style.display = ""; + this._hidden = false; + // if (box.setActive) { + // box.setActive(); + // } + this.fireEvent("show"); + } + }, + isHidden: function() { + return this._hidden; + }, + show: function() { + this._doAutoRender(); + this._show(); + }, + hide: function(notNofity) { + if (!this._hidden && this.getDom()) { + this.getDom().style.display = "none"; + this._hidden = true; + if (!notNofity) { + this.fireEvent("hide"); + } + } + }, + queryAutoHide: function(el) { + return !el || !uiUtils.contains(this.getDom(), el); + } + }; + utils.inherits(Popup, UIBase); + + domUtils.on(document, "mousedown", function(evt) { + var el = evt.target || evt.srcElement; + closeAllPopup(evt, el); + }); + domUtils.on(window, "scroll", function(evt, el) { + closeAllPopup(evt, el); + }); +})(); + + +// ui/colorpicker.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + ColorPicker = (baidu.editor.ui.ColorPicker = function(options) { + this.initOptions(options); + this.noColorText = this.noColorText || this.editor.getLang("clearColor"); + this.initUIBase(); + }); + + ColorPicker.prototype = { + getHtmlTpl: function() { + return genColorPicker(this.noColorText, this.editor); + }, + _onTableClick: function(evt) { + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute("data-color"); + if (color) { + this.fireEvent("pickcolor", color); + } + }, + _onTableOver: function(evt) { + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute("data-color"); + if (color) { + this.getDom("preview").style.backgroundColor = color; + } + }, + _onTableOut: function() { + this.getDom("preview").style.backgroundColor = ""; + }, + _onPickNoColor: function() { + this.fireEvent("picknocolor"); + }, + _onColorSelect: function(evt) { + var input = evt.target || evt.srcElement; + var color = input.value; + if (color) { + this.fireEvent("pickcolor", color); + } + } + }; + utils.inherits(ColorPicker, UIBase); + + var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," + + "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," + + "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," + + "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," + + "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," + + "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," + + "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split( + "," + ); + + function genColorPicker(noColorText, editor) { + var html = + '
    ' + + '
    ' + + // '
    ' + + '
    ' + + '
    ' + + noColorText + + "
    " + + "
    " + + '' + + '" + + ''; + for (var i = 0; i < COLORS.length; i++) { + if (i && i % 10 === 0) { + html += + "" + + (i == 60 + ? '" + : "") + + ""; + } + html += i < 70 + ? '" + : ""; + } + html += ""; + html += "
    ' + + editor.getLang("themeColor") + + "
    ' + + editor.getLang("standardColor") + + "
    "; + return html; + } +})(); + + +// ui/tablepicker.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; + + var TablePicker = (baidu.editor.ui.TablePicker = function(options) { + this.initOptions(options); + this.initTablePicker(); + }); + TablePicker.prototype = { + defaultNumRows: 10, + defaultNumCols: 10, + maxNumRows: 20, + maxNumCols: 20, + numRows: 10, + numCols: 10, + lengthOfCellSide: 22, + initTablePicker: function() { + this.initUIBase(); + }, + getHtmlTpl: function() { + var me = this; + return ( + '
    ' + + '
    ' + + '
    ' + + '' + + "
    " + + '
    " + + '
    ' + + "
    " + + "
    " + + "
    " + ); + }, + _UIBase_render: UIBase.prototype.render, + render: function(holder) { + this._UIBase_render(holder); + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_row") + + " x 0" + + this.editor.getLang("t_col"); + }, + _track: function(numCols, numRows) { + var style = this.getDom("overlay").style; + var sideLen = this.lengthOfCellSide; + style.width = numCols * sideLen + "px"; + style.height = numRows * sideLen + "px"; + var label = this.getDom("label"); + label.innerHTML = + numCols + + this.editor.getLang("t_col") + + " x " + + numRows + + this.editor.getLang("t_row"); + this.numCols = numCols; + this.numRows = numRows; + }, + _onMouseOver: function(evt, el) { + var rel = evt.relatedTarget || evt.fromElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_col") + + " x 0" + + this.editor.getLang("t_row"); + this.getDom("overlay").style.visibility = ""; + } + }, + _onMouseOut: function(evt, el) { + var rel = evt.relatedTarget || evt.toElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_col") + + " x 0" + + this.editor.getLang("t_row"); + this.getDom("overlay").style.visibility = "hidden"; + } + }, + _onMouseMove: function(evt, el) { + var style = this.getDom("overlay").style; + var offset = uiUtils.getEventOffset(evt); + var sideLen = this.lengthOfCellSide; + var numCols = Math.ceil(offset.left / sideLen); + var numRows = Math.ceil(offset.top / sideLen); + this._track(numCols, numRows); + }, + _onClick: function() { + this.fireEvent("picktable", this.numCols, this.numRows); + } + }; + utils.inherits(TablePicker, UIBase); +})(); + + +// ui/stateful.js +(function() { + var browser = baidu.editor.browser, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils; + + var TPL_STATEFUL = + 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + + (browser.ie + ? ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' + : ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + + ' onmouseout="$$.Stateful_onMouseOut(event, this);"'); + + baidu.editor.ui.Stateful = { + alwalysHoverable: false, + target: null, //目标元素和this指向dom不一样 + Stateful_init: function() { + this._Stateful_dGetHtmlTpl = this.getHtmlTpl; + this.getHtmlTpl = this.Stateful_getHtmlTpl; + }, + Stateful_getHtmlTpl: function() { + var tpl = this._Stateful_dGetHtmlTpl(); + // 使用function避免$转义 + return tpl.replace(/stateful/g, function() { + return TPL_STATEFUL; + }); + }, + Stateful_onMouseEnter: function(evt, el) { + this.target = el; + if (!this.isDisabled() || this.alwalysHoverable) { + this.addState("hover"); + this.fireEvent("over"); + } + }, + Stateful_onMouseLeave: function(evt, el) { + if (!this.isDisabled() || this.alwalysHoverable) { + this.removeState("hover"); + this.removeState("active"); + this.fireEvent("out"); + } + }, + Stateful_onMouseOver: function(evt, el) { + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseEnter(evt, el); + } + }, + Stateful_onMouseOut: function(evt, el) { + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseLeave(evt, el); + } + }, + Stateful_onMouseDown: function(evt, el) { + if (!this.isDisabled()) { + this.addState("active"); + } + }, + Stateful_onMouseUp: function(evt, el) { + if (!this.isDisabled()) { + this.removeState("active"); + } + }, + Stateful_postRender: function() { + if (this.disabled && !this.hasState("disabled")) { + this.addState("disabled"); + } + }, + hasState: function(state) { + return domUtils.hasClass(this.getStateDom(), "edui-state-" + state); + }, + addState: function(state) { + if (!this.hasState(state)) { + this.getStateDom().className += " edui-state-" + state; + } + }, + removeState: function(state) { + if (this.hasState(state)) { + domUtils.removeClasses(this.getStateDom(), ["edui-state-" + state]); + } + }, + getStateDom: function() { + return this.getDom("state"); + }, + isChecked: function() { + return this.hasState("checked"); + }, + setChecked: function(checked) { + if (!this.isDisabled() && checked) { + this.addState("checked"); + } else { + this.removeState("checked"); + } + }, + isDisabled: function() { + return this.hasState("disabled"); + }, + setDisabled: function(disabled) { + if (disabled) { + this.removeState("hover"); + this.removeState("checked"); + this.removeState("active"); + this.addState("disabled"); + } else { + this.removeState("disabled"); + } + } + }; +})(); + + +// ui/button.js +///import core +///import uicore +///import ui/stateful.js +(function() { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + Button = (baidu.editor.ui.Button = function(options) { + if (options.name) { + var btnName = options.name; + var cssRules = options.cssRules; + if (!options.className) { + options.className = "edui-for-" + btnName; + } + options.cssRules = + ".edui-" + + (options.theme || "default") + + " .edui-toolbar .edui-button.edui-for-" + + btnName + + " .edui-icon {" + + cssRules + + "}"; + } + this.initOptions(options); + this.initButton(); + }); + Button.prototype = { + uiName: "button", + label: "", + title: "", + showIcon: true, + showText: true, + cssRules: "", + initButton: function() { + this.initUIBase(); + this.Stateful_init(); + if (this.cssRules) { + utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); + } + }, + getHtmlTpl: function() { + return ( + '
    ' + + '
    ' + + '
    ' + + (this.showIcon ? '
    ' : "") + + (this.showText + ? '
    ' + this.label + "
    " + : "") + + "
    " + + "
    " + + "
    " + ); + }, + postRender: function() { + this.Stateful_postRender(); + this.setDisabled(this.disabled); + }, + _onMouseDown: function(e) { + var target = e.target || e.srcElement, + tagName = target && target.tagName && target.tagName.toLowerCase(); + if (tagName == "input" || tagName == "object" || tagName == "object") { + return false; + } + }, + _onClick: function() { + if (!this.isDisabled()) { + this.fireEvent("click"); + } + }, + setTitle: function(text) { + var label = this.getDom("label"); + label.innerHTML = text; + } + }; + utils.inherits(Button, UIBase); + utils.extend(Button.prototype, Stateful); +})(); + + +// ui/splitbutton.js +///import core +///import uicore +///import ui/stateful.js +(function() { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + SplitButton = (baidu.editor.ui.SplitButton = function(options) { + this.initOptions(options); + this.initSplitButton(); + }); + SplitButton.prototype = { + popup: null, + uiName: "splitbutton", + title: "", + initSplitButton: function() { + this.initUIBase(); + this.Stateful_init(); + var me = this; + if (this.popup != null) { + var popup = this.popup; + this.popup = null; + this.setPopup(popup); + } + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function() { + this.Stateful_postRender(); + this._UIBase_postRender(); + }, + setPopup: function(popup) { + if (this.popup === popup) return; + if (this.popup != null) { + this.popup.dispose(); + } + popup.addListener("show", utils.bind(this._onPopupShow, this)); + popup.addListener("hide", utils.bind(this._onPopupHide, this)); + popup.addListener( + "postrender", + utils.bind(function() { + popup + .getDom("body") + .appendChild( + uiUtils.createElementByHtml( + '
    ' + ) + ); + popup.getDom().className += " " + this.className; + }, this) + ); + this.popup = popup; + }, + _onPopupShow: function() { + this.addState("opened"); + }, + _onPopupHide: function() { + this.removeState("opened"); + }, + getHtmlTpl: function() { + return ( + '
    ' + + "
    ' + + '
    ' + + '
    ' + + "
    " + + '
    ' + + '
    ' + + "
    " + ); + }, + showPopup: function() { + // 当popup往上弹出的时候,做特殊处理 + var rect = uiUtils.getClientRect(this.getDom()); + rect.top -= this.popup.SHADOW_RADIUS; + rect.height += this.popup.SHADOW_RADIUS; + this.popup.showAnchorRect(rect); + }, + _onArrowClick: function(event, el) { + if (!this.isDisabled()) { + this.showPopup(); + } + }, + _onButtonClick: function() { + if (!this.isDisabled()) { + this.fireEvent("buttonclick"); + } + } + }; + utils.inherits(SplitButton, UIBase); + utils.extend(SplitButton.prototype, Stateful, true); +})(); + + +// ui/colorbutton.js +///import core +///import uicore +///import ui/colorpicker.js +///import ui/popup.js +///import ui/splitbutton.js +(function() { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + ColorPicker = baidu.editor.ui.ColorPicker, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + ColorButton = (baidu.editor.ui.ColorButton = function(options) { + this.initOptions(options); + this.initColorButton(); + }); + ColorButton.prototype = { + initColorButton: function() { + var me = this; + this.popup = new Popup({ + content: new ColorPicker({ + noColorText: me.editor.getLang("clearColor"), + editor: me.editor, + onpickcolor: function(t, color) { + me._onPickColor(color); + }, + onpicknocolor: function(t, color) { + me._onPickNoColor(color); + } + }), + editor: me.editor + }); + this.initSplitButton(); + }, + _SplitButton_postRender: SplitButton.prototype.postRender, + postRender: function() { + this._SplitButton_postRender(); + this.getDom("button_body").appendChild( + uiUtils.createElementByHtml( + '
    ' + ) + ); + this.getDom().className += " edui-colorbutton"; + }, + setColor: function(color) { + this.getDom("colorlump").style.backgroundColor = color; + this.color = color; + }, + _onPickColor: function(color) { + if (this.fireEvent("pickcolor", color) !== false) { + this.setColor(color); + this.popup.hide(); + } + }, + _onPickNoColor: function(color) { + if (this.fireEvent("picknocolor") !== false) { + this.popup.hide(); + } + } + }; + utils.inherits(ColorButton, SplitButton); +})(); + + +// ui/tablebutton.js +///import core +///import uicore +///import ui/popup.js +///import ui/tablepicker.js +///import ui/splitbutton.js +(function() { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + TablePicker = baidu.editor.ui.TablePicker, + SplitButton = baidu.editor.ui.SplitButton, + TableButton = (baidu.editor.ui.TableButton = function(options) { + this.initOptions(options); + this.initTableButton(); + }); + TableButton.prototype = { + initTableButton: function() { + var me = this; + this.popup = new Popup({ + content: new TablePicker({ + editor: me.editor, + onpicktable: function(t, numCols, numRows) { + me._onPickTable(numCols, numRows); + } + }), + editor: me.editor + }); + this.initSplitButton(); + }, + _onPickTable: function(numCols, numRows) { + if (this.fireEvent("picktable", numCols, numRows) !== false) { + this.popup.hide(); + } + } + }; + utils.inherits(TableButton, SplitButton); +})(); + + +// ui/autotypesetpicker.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase; + + var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = function( + options + ) { + this.initOptions(options); + this.initAutoTypeSetPicker(); + }); + AutoTypeSetPicker.prototype = { + initAutoTypeSetPicker: function() { + this.initUIBase(); + }, + getHtmlTpl: function() { + var me = this.editor, + opt = me.options.autotypeset, + lang = me.getLang("autoTypeSet"); + + var textAlignInputName = "textAlignValue" + me.uid, + imageBlockInputName = "imageBlockLineValue" + me.uid, + symbolConverInputName = "symbolConverValue" + me.uid; + + return ( + '
    ' + + '
    ' + + "" + + '" + + '" + + "" + + '" + + '" + + "" + + "" + + '" + + '" + + "" + + '" + + '" + + '" + + "" + + '" + + '" + + '" + + "" + + "
    " + + lang.mergeLine + + '" + + lang.delLine + + "
    " + + lang.removeFormat + + '" + + lang.indent + + "
    " + + lang.alignment + + "' + + '" + + me.getLang("justifyleft") + + '" + + me.getLang("justifycenter") + + '" + + me.getLang("justifyright") + + "
    " + + lang.imageFloat + + "' + + '" + + me.getLang("default") + + '" + + me.getLang("justifyleft") + + '" + + me.getLang("justifycenter") + + '" + + me.getLang("justifyright") + + "
    " + + lang.removeFontsize + + '" + + lang.removeFontFamily + + "
    " + + lang.removeHtml + + "
    " + + lang.pasteFilter + + "
    " + + lang.symbol + + "' + + '" + + lang.bdc2sb + + '" + + lang.tobdc + + "" + + "
    " + + "
    " + + "
    " + ); + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(AutoTypeSetPicker, UIBase); +})(); + + +// ui/autotypesetbutton.js +///import core +///import uicore +///import ui/popup.js +///import ui/autotypesetpicker.js +///import ui/splitbutton.js +(function() { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, + SplitButton = baidu.editor.ui.SplitButton, + AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = function(options) { + this.initOptions(options); + this.initAutoTypeSetButton(); + }); + function getPara(me) { + var opt = {}, + cont = me.getDom(), + editorId = me.editor.uid, + inputType = null, + attrName = null, + ipts = domUtils.getElementsByTagName(cont, "input"); + for (var i = ipts.length - 1, ipt; (ipt = ipts[i--]); ) { + inputType = ipt.getAttribute("type"); + if (inputType == "checkbox") { + attrName = ipt.getAttribute("name"); + opt[attrName] && delete opt[attrName]; + if (ipt.checked) { + var attrValue = document.getElementById( + attrName + "Value" + editorId + ); + if (attrValue) { + if (/input/gi.test(attrValue.tagName)) { + opt[attrName] = attrValue.value; + } else { + var iptChilds = attrValue.getElementsByTagName("input"); + for ( + var j = iptChilds.length - 1, iptchild; + (iptchild = iptChilds[j--]); + + ) { + if (iptchild.checked) { + opt[attrName] = iptchild.value; + break; + } + } + } + } else { + opt[attrName] = true; + } + } else { + opt[attrName] = false; + } + } else { + opt[ipt.getAttribute("value")] = ipt.checked; + } + } + + var selects = domUtils.getElementsByTagName(cont, "select"); + for (var i = 0, si; (si = selects[i++]); ) { + var attr = si.getAttribute("name"); + opt[attr] = opt[attr] ? si.value : ""; + } + + utils.extend(me.editor.options.autotypeset, opt); + + me.editor.setPreferences("autotypeset", opt); + } + + AutoTypeSetButton.prototype = { + initAutoTypeSetButton: function() { + var me = this; + this.popup = new Popup({ + //传入配置参数 + content: new AutoTypeSetPicker({ editor: me.editor }), + editor: me.editor, + hide: function() { + if (!this._hidden && this.getDom()) { + getPara(this); + this.getDom().style.display = "none"; + this._hidden = true; + this.fireEvent("hide"); + } + } + }); + var flag = 0; + this.popup.addListener("postRenderAfter", function() { + var popupUI = this; + if (flag) return; + var cont = this.getDom(), + btn = cont.getElementsByTagName("button")[0]; + + btn.onclick = function() { + getPara(popupUI); + me.editor.execCommand("autotypeset"); + popupUI.hide(); + }; + + domUtils.on(cont, "click", function(e) { + var target = e.target || e.srcElement, + editorId = me.editor.uid; + if (target && target.tagName == "INPUT") { + // 点击图片浮动的checkbox,去除对应的radio + if ( + target.name == "imageBlockLine" || + target.name == "textAlign" || + target.name == "symbolConver" + ) { + var checked = target.checked, + radioTd = document.getElementById( + target.name + "Value" + editorId + ), + radios = radioTd.getElementsByTagName("input"), + defalutSelect = { + imageBlockLine: "none", + textAlign: "left", + symbolConver: "tobdc" + }; + + for (var i = 0; i < radios.length; i++) { + if (checked) { + if (radios[i].value == defalutSelect[target.name]) { + radios[i].checked = "checked"; + } + } else { + radios[i].checked = false; + } + } + } + // 点击radio,选中对应的checkbox + if ( + target.name == "imageBlockLineValue" + editorId || + target.name == "textAlignValue" + editorId || + target.name == "bdc" + ) { + var checkboxs = target.parentNode.previousSibling.getElementsByTagName( + "input" + ); + checkboxs && (checkboxs[0].checked = true); + } + + getPara(popupUI); + } + }); + + flag = 1; + }); + this.initSplitButton(); + } + }; + utils.inherits(AutoTypeSetButton, SplitButton); +})(); + + +// ui/cellalignpicker.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + UIBase = baidu.editor.ui.UIBase; + + /** + * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始 + * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom' + * @update 2013/4/2 hancong03@baidu.com + */ + var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = function(options) { + this.initOptions(options); + this.initSelected(); + this.initCellAlignPicker(); + }); + CellAlignPicker.prototype = { + //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引 + initSelected: function() { + var status = { + valign: { + top: 0, + middle: 1, + bottom: 2 + }, + align: { + left: 0, + center: 1, + right: 2 + }, + count: 3 + }, + result = -1; + + if (this.selected) { + this.selectedIndex = + status.valign[this.selected.valign] * status.count + + status.align[this.selected.align]; + } + }, + initCellAlignPicker: function() { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl: function() { + var alignType = ["left", "center", "right"], + COUNT = 9, + tempClassName = null, + tempIndex = -1, + tmpl = []; + + for (var i = 0; i < COUNT; i++) { + tempClassName = this.selectedIndex === i + ? ' class="edui-cellalign-selected" ' + : ""; + tempIndex = i % 3; + + tempIndex === 0 && tmpl.push("
  • ' + + tmpl.join("") + + "
    " + + "
    " + + "
    " + ); + }, + getStateDom: function() { + return this.target; + }, + _onClick: function(evt) { + var target = evt.target || evt.srcElement; + if (/icon/.test(target.className)) { + this.items[target.parentNode.getAttribute("index")].onclick(); + Popup.postHide(evt); + } + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(CellAlignPicker, UIBase); + utils.extend(CellAlignPicker.prototype, Stateful, true); +})(); + + +// ui/pastepicker.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + Stateful = baidu.editor.ui.Stateful, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; + + var PastePicker = (baidu.editor.ui.PastePicker = function(options) { + this.initOptions(options); + this.initPastePicker(); + }); + PastePicker.prototype = { + initPastePicker: function() { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl: function() { + return ( + '
    ' + + '
    ' + + '
    ' + + this.editor.getLang("pasteOpt") + + "
    " + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + "
    " + + "
    " + + "
    " + ); + }, + getStateDom: function() { + return this.target; + }, + format: function(param) { + this.editor.ui._isTransfer = true; + this.editor.fireEvent("pasteTransfer", param); + }, + _onClick: function(cur) { + var node = domUtils.getNextDomNode(cur), + screenHt = uiUtils.getViewportRect().height, + subPop = uiUtils.getClientRect(node); + + if (subPop.top + subPop.height > screenHt) + node.style.top = -subPop.height - cur.offsetHeight + "px"; + else node.style.top = ""; + + if (/hidden/gi.test(domUtils.getComputedStyle(node, "visibility"))) { + node.style.visibility = "visible"; + domUtils.addClass(cur, "edui-state-opened"); + } else { + node.style.visibility = "hidden"; + domUtils.removeClasses(cur, "edui-state-opened"); + } + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(PastePicker, UIBase); + utils.extend(PastePicker.prototype, Stateful, true); +})(); + + +// ui/toolbar.js +(function() { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Toolbar = (baidu.editor.ui.Toolbar = function(options) { + this.initOptions(options); + this.initToolbar(); + }); + Toolbar.prototype = { + items: null, + initToolbar: function() { + this.items = this.items || []; + this.initUIBase(); + }, + add: function(item, index) { + if (index === undefined) { + this.items.push(item); + } else { + this.items.splice(index, 0, item); + } + }, + getHtmlTpl: function() { + var buff = []; + for (var i = 0; i < this.items.length; i++) { + buff[i] = this.items[i].renderHtml(); + } + return ( + '
    ' + + buff.join("") + + "
    " + ); + }, + postRender: function() { + var box = this.getDom(); + for (var i = 0; i < this.items.length; i++) { + this.items[i].postRender(); + } + uiUtils.makeUnselectable(box); + }, + _onMouseDown: function(e) { + var target = e.target || e.srcElement, + tagName = target && target.tagName && target.tagName.toLowerCase(); + if (tagName == "input" || tagName == "object" || tagName == "object") { + return false; + } + } + }; + utils.inherits(Toolbar, UIBase); +})(); + + +// ui/quick-operate.js +///import core +///import uicore +///import ui\popup.js +///import ui\stateful.js +(function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + CellAlignPicker = baidu.editor.ui.CellAlignPicker, + QuickOperate = (baidu.editor.ui.QuickOperate = function (options) { + this.initOptions(options); + // this.initMenu(); + }); + + // var menuSeparator = { + // renderHtml: function() { + // return '
    '; + // }, + // postRender: function() {}, + // queryAutoHide: function() { + // return true; + // } + // }; + QuickOperate.prototype = { + // items: null, + uiName: "quick-operate", + // initMenu: function() { + // this.items = this.items || []; + // this.initPopup(); + // this.initItems(); + // }, + // initItems: function() { + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // if (item == "-") { + // this.items[i] = this.getSeparator(); + // } else if (!(item instanceof MenuItem)) { + // item.editor = this.editor; + // item.theme = this.editor.options.theme; + // this.items[i] = this.createItem(item); + // } + // } + // }, + // getSeparator: function() { + // return menuSeparator; + // }, + // createItem: function(item) { + // //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + // item.menu = this; + // return new MenuItem(item); + // }, + _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, + getContentHtmlTpl: function () { + // if (this.items.length == 0) { + // return this._Popup_getContentHtmlTpl(); + // } + // var buff = []; + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // buff[i] = item.renderHtml(); + // } + // return '
    ' + buff.join("") + "
    "; + return [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    删除
    ', + '
    左对齐
    ', + '
    右对齐
    ', + '
    ', + '
    ', + ].join('') + }, + // _Popup_postRender: Popup.prototype.postRender, + // postRender: function() { + // var me = this; + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // item.ownerMenu = this; + // item.postRender(); + // } + // domUtils.on(this.getDom(), "mouseover", function(evt) { + // evt = evt || event; + // var rel = evt.relatedTarget || evt.fromElement; + // var el = me.getDom(); + // if (!uiUtils.contains(el, rel) && el !== rel) { + // me.fireEvent("over"); + // } + // }); + // this._Popup_postRender(); + // }, + // queryAutoHide: function(el) { + // if (el) { + // if (uiUtils.contains(this.getDom(), el)) { + // return false; + // } + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // if (item.queryAutoHide(el) === false) { + // return false; + // } + // } + // } + // }, + // clearItems: function() { + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // clearTimeout(item._showingTimer); + // clearTimeout(item._closingTimer); + // if (item.subMenu) { + // item.subMenu.destroy(); + // } + // } + // this.items = []; + // }, + destroy: function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + // this.clearItems(); + }, + dispose: function () { + this.destroy(); + } + }; + utils.inherits(QuickOperate, Popup); + // + // /** + // * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + // * @type {Function} + // */ + // var MenuItem = (baidu.editor.ui.MenuItem = function(options) { + // this.initOptions(options); + // this.initUIBase(); + // this.Stateful_init(); + // if (this.subMenu && !(this.subMenu instanceof QuickOperate)) { + // if (options.className && options.className.indexOf("aligntd") != -1) { + // var me = this; + // + // //获取单元格对齐初始状态 + // this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); + // + // this.subMenu = new Popup({ + // content: new CellAlignPicker(this.subMenu), + // parentMenu: me, + // editor: me.editor, + // destroy: function() { + // if (this.getDom()) { + // domUtils.remove(this.getDom()); + // } + // } + // }); + // this.subMenu.addListener("postRenderAfter", function() { + // domUtils.on(this.getDom(), "mouseover", function() { + // me.addState("opened"); + // }); + // }); + // } else { + // this.subMenu = new QuickOperate(this.subMenu); + // } + // } + // }); + // MenuItem.prototype = { + // label: "", + // subMenu: null, + // ownerMenu: null, + // uiName: "menuitem", + // alwalysHoverable: true, + // getHtmlTpl: function() { + // return ( + // '
    ' + + // '
    ' + + // this.renderLabelHtml() + + // "
    " + + // "
    " + // ); + // }, + // postRender: function() { + // var me = this; + // this.addListener("over", function() { + // me.ownerMenu.fireEvent("submenuover", me); + // if (me.subMenu) { + // me.delayShowSubMenu(); + // } + // }); + // if (this.subMenu) { + // this.getDom().className += " edui-hassubmenu"; + // this.subMenu.render(); + // this.addListener("out", function() { + // me.delayHideSubMenu(); + // }); + // this.subMenu.addListener("over", function() { + // clearTimeout(me._closingTimer); + // me._closingTimer = null; + // me.addState("opened"); + // }); + // this.ownerMenu.addListener("hide", function() { + // me.hideSubMenu(); + // }); + // this.ownerMenu.addListener("submenuover", function(t, subMenu) { + // if (subMenu !== me) { + // me.delayHideSubMenu(); + // } + // }); + // this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + // this.subMenu.queryAutoHide = function(el) { + // if (el && uiUtils.contains(me.getDom(), el)) { + // return false; + // } + // return this._bakQueryAutoHide(el); + // }; + // } + // this.getDom().style.tabIndex = "-1"; + // uiUtils.makeUnselectable(this.getDom()); + // this.Stateful_postRender(); + // }, + // delayShowSubMenu: function() { + // var me = this; + // if (!me.isDisabled()) { + // me.addState("opened"); + // clearTimeout(me._showingTimer); + // clearTimeout(me._closingTimer); + // me._closingTimer = null; + // me._showingTimer = setTimeout(function() { + // me.showSubMenu(); + // }, 250); + // } + // }, + // delayHideSubMenu: function() { + // var me = this; + // if (!me.isDisabled()) { + // me.removeState("opened"); + // clearTimeout(me._showingTimer); + // if (!me._closingTimer) { + // me._closingTimer = setTimeout(function() { + // if (!me.hasState("opened")) { + // me.hideSubMenu(); + // } + // me._closingTimer = null; + // }, 400); + // } + // } + // }, + // renderLabelHtml: function() { + // return ( + // '
    ' + + // '
    ' + + // '
    ' + + // (this.label || "") + + // "
    " + // ); + // }, + // getStateDom: function() { + // return this.getDom(); + // }, + // queryAutoHide: function(el) { + // if (this.subMenu && this.hasState("opened")) { + // return this.subMenu.queryAutoHide(el); + // } + // }, + // _onClick: function(event, this_) { + // if (this.hasState("disabled")) return; + // if (this.fireEvent("click", event, this_) !== false) { + // if (this.subMenu) { + // this.showSubMenu(); + // } else { + // Popup.postHide(event); + // } + // } + // }, + // showSubMenu: function() { + // var rect = uiUtils.getClientRect(this.getDom()); + // rect.right -= 5; + // rect.left += 2; + // rect.width -= 7; + // rect.top -= 4; + // rect.bottom += 4; + // rect.height += 8; + // this.subMenu.showAnchorRect(rect, true, true); + // }, + // hideSubMenu: function() { + // this.subMenu.hide(); + // } + // }; + // utils.inherits(MenuItem, UIBase); + // utils.extend(MenuItem.prototype, Stateful, true); +})(); + + +// ui/menu.js +///import core +///import uicore +///import ui\popup.js +///import ui\stateful.js +(function() { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + CellAlignPicker = baidu.editor.ui.CellAlignPicker, + Menu = (baidu.editor.ui.Menu = function(options) { + this.initOptions(options); + this.initMenu(); + }); + + var menuSeparator = { + renderHtml: function() { + return '
    '; + }, + postRender: function() {}, + queryAutoHide: function() { + return true; + } + }; + Menu.prototype = { + items: null, + uiName: "menu", + initMenu: function() { + this.items = this.items || []; + this.initPopup(); + this.initItems(); + }, + initItems: function() { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item == "-") { + this.items[i] = this.getSeparator(); + } else if (!(item instanceof MenuItem)) { + item.editor = this.editor; + item.theme = this.editor.options.theme; + this.items[i] = this.createItem(item); + } + } + }, + getSeparator: function() { + return menuSeparator; + }, + createItem: function(item) { + //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + item.menu = this; + return new MenuItem(item); + }, + _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, + getContentHtmlTpl: function() { + if (this.items.length == 0) { + return this._Popup_getContentHtmlTpl(); + } + var buff = []; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + buff[i] = item.renderHtml(); + } + return '
    ' + buff.join("") + "
    "; + }, + _Popup_postRender: Popup.prototype.postRender, + postRender: function() { + var me = this; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + item.ownerMenu = this; + item.postRender(); + } + domUtils.on(this.getDom(), "mouseover", function(evt) { + evt = evt || event; + var rel = evt.relatedTarget || evt.fromElement; + var el = me.getDom(); + if (!uiUtils.contains(el, rel) && el !== rel) { + me.fireEvent("over"); + } + }); + this._Popup_postRender(); + }, + queryAutoHide: function(el) { + if (el) { + if (uiUtils.contains(this.getDom(), el)) { + return false; + } + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item.queryAutoHide(el) === false) { + return false; + } + } + } + }, + clearItems: function() { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + clearTimeout(item._showingTimer); + clearTimeout(item._closingTimer); + if (item.subMenu) { + item.subMenu.destroy(); + } + } + this.items = []; + }, + destroy: function() { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + this.clearItems(); + }, + dispose: function() { + this.destroy(); + } + }; + utils.inherits(Menu, Popup); + + /** + * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + * @type {Function} + */ + var MenuItem = (baidu.editor.ui.MenuItem = function(options) { + this.initOptions(options); + this.initUIBase(); + this.Stateful_init(); + if (this.subMenu && !(this.subMenu instanceof Menu)) { + if (options.className && options.className.indexOf("aligntd") != -1) { + var me = this; + + //获取单元格对齐初始状态 + this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); + + this.subMenu = new Popup({ + content: new CellAlignPicker(this.subMenu), + parentMenu: me, + editor: me.editor, + destroy: function() { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + } + }); + this.subMenu.addListener("postRenderAfter", function() { + domUtils.on(this.getDom(), "mouseover", function() { + me.addState("opened"); + }); + }); + } else { + this.subMenu = new Menu(this.subMenu); + } + } + }); + MenuItem.prototype = { + label: "", + subMenu: null, + ownerMenu: null, + uiName: "menuitem", + alwalysHoverable: true, + getHtmlTpl: function() { + return ( + '
    ' + + '
    ' + + this.renderLabelHtml() + + "
    " + + "
    " + ); + }, + postRender: function() { + var me = this; + this.addListener("over", function() { + me.ownerMenu.fireEvent("submenuover", me); + if (me.subMenu) { + me.delayShowSubMenu(); + } + }); + if (this.subMenu) { + this.getDom().className += " edui-hassubmenu"; + this.subMenu.render(); + this.addListener("out", function() { + me.delayHideSubMenu(); + }); + this.subMenu.addListener("over", function() { + clearTimeout(me._closingTimer); + me._closingTimer = null; + me.addState("opened"); + }); + this.ownerMenu.addListener("hide", function() { + me.hideSubMenu(); + }); + this.ownerMenu.addListener("submenuover", function(t, subMenu) { + if (subMenu !== me) { + me.delayHideSubMenu(); + } + }); + this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + this.subMenu.queryAutoHide = function(el) { + if (el && uiUtils.contains(me.getDom(), el)) { + return false; + } + return this._bakQueryAutoHide(el); + }; + } + this.getDom().style.tabIndex = "-1"; + uiUtils.makeUnselectable(this.getDom()); + this.Stateful_postRender(); + }, + delayShowSubMenu: function() { + var me = this; + if (!me.isDisabled()) { + me.addState("opened"); + clearTimeout(me._showingTimer); + clearTimeout(me._closingTimer); + me._closingTimer = null; + me._showingTimer = setTimeout(function() { + me.showSubMenu(); + }, 250); + } + }, + delayHideSubMenu: function() { + var me = this; + if (!me.isDisabled()) { + me.removeState("opened"); + clearTimeout(me._showingTimer); + if (!me._closingTimer) { + me._closingTimer = setTimeout(function() { + if (!me.hasState("opened")) { + me.hideSubMenu(); + } + me._closingTimer = null; + }, 400); + } + } + }, + renderLabelHtml: function() { + return ( + '
    ' + + '
    ' + + '
    ' + + (this.label || "") + + "
    " + ); + }, + getStateDom: function() { + return this.getDom(); + }, + queryAutoHide: function(el) { + if (this.subMenu && this.hasState("opened")) { + return this.subMenu.queryAutoHide(el); + } + }, + _onClick: function(event, this_) { + if (this.hasState("disabled")) return; + if (this.fireEvent("click", event, this_) !== false) { + if (this.subMenu) { + this.showSubMenu(); + } else { + Popup.postHide(event); + } + } + }, + showSubMenu: function() { + var rect = uiUtils.getClientRect(this.getDom()); + rect.right -= 5; + rect.left += 2; + rect.width -= 7; + rect.top -= 4; + rect.bottom += 4; + rect.height += 8; + this.subMenu.showAnchorRect(rect, true, true); + }, + hideSubMenu: function() { + this.subMenu.hide(); + } + }; + utils.inherits(MenuItem, UIBase); + utils.extend(MenuItem.prototype, Stateful, true); +})(); + + +// ui/combox.js +///import core +///import uicore +///import ui/menu.js +///import ui/splitbutton.js +(function() { + // todo: menu和item提成通用list + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + Combox = (baidu.editor.ui.Combox = function(options) { + this.initOptions(options); + this.initCombox(); + }); + Combox.prototype = { + uiName: "combox", + onbuttonclick: function() { + this.showPopup(); + }, + initCombox: function() { + var me = this; + this.items = this.items || []; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + item.uiName = "listitem"; + item.index = i; + item.onclick = function() { + me.selectByIndex(this.index); + }; + } + this.popup = new Menu({ + items: this.items, + uiName: "list", + editor: this.editor, + captureWheel: true, + combox: this + }); + + this.initSplitButton(); + }, + _SplitButton_postRender: SplitButton.prototype.postRender, + postRender: function() { + this._SplitButton_postRender(); + this.setLabel(this.label || ""); + this.setValue(this.initValue || ""); + }, + showPopup: function() { + var rect = uiUtils.getClientRect(this.getDom()); + rect.top += 1; + rect.bottom -= 1; + rect.height -= 2; + this.popup.showAnchorRect(rect); + }, + getValue: function() { + return this.value; + }, + setValue: function(value) { + var index = this.indexByValue(value); + if (index != -1) { + this.selectedIndex = index; + this.setLabel(this.items[index].label); + this.value = this.items[index].value; + } else { + this.selectedIndex = -1; + this.setLabel(this.getLabelForUnknowValue(value)); + this.value = value; + } + }, + setLabel: function(label) { + this.getDom("button_body").innerHTML = label; + this.label = label; + }, + getLabelForUnknowValue: function(value) { + return value; + }, + indexByValue: function(value) { + for (var i = 0; i < this.items.length; i++) { + if (value == this.items[i].value) { + return i; + } + } + return -1; + }, + getItem: function(index) { + return this.items[index]; + }, + selectByIndex: function(index) { + if ( + index < this.items.length && + this.fireEvent("select", index) !== false + ) { + this.selectedIndex = index; + this.value = this.items[index].value; + this.setLabel(this.items[index].label); + } + } + }; + utils.inherits(Combox, SplitButton); +})(); + + +// ui/dialog.js +///import core +///import uicore +///import ui/mask.js +///import ui/button.js +(function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + Mask = baidu.editor.ui.Mask, + UIBase = baidu.editor.ui.UIBase, + Button = baidu.editor.ui.Button, + Dialog = (baidu.editor.ui.Dialog = function (options) { + if (options.name) { + var name = options.name; + var cssRules = options.cssRules; + if (!options.className) { + options.className = "edui-for-" + name; + } + if (cssRules) { + options.cssRules = + ".edui-for-" + name + " .edui-dialog-content {" + cssRules + "}"; + } + } + this.initOptions( + utils.extend( + { + autoReset: true, + draggable: true, + onok: function () { + }, + oncancel: function () { + }, + onclose: function (t, ok) { + return ok ? this.onok() : this.oncancel(); + }, + //是否控制dialog中的scroll事件, 默认为不阻止 + holdScroll: false + }, + options + ) + ); + this.initDialog(); + }); + var modalMask; + var dragMask; + var activeDialog; + Dialog.prototype = { + draggable: false, + uiName: "dialog", + initDialog: function () { + var me = this, + theme = this.editor.options.theme; + if (this.cssRules) { + this.cssRules = ".edui-" + theme + " " + this.cssRules; + utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); + } + this.initUIBase(); + this.modalMask = + modalMask || + (modalMask = new Mask({ + className: "edui-dialog-modalmask", + theme: theme, + onclick: function () { + activeDialog && activeDialog.close(false); + } + })); + this.dragMask = + dragMask || + (dragMask = new Mask({ + className: "edui-dialog-dragmask", + theme: theme + })); + this.closeButton = new Button({ + className: "edui-dialog-closebutton", + title: me.closeDialog, + theme: theme, + onclick: function () { + me.close(false); + } + }); + + this.fullscreen && this.initResizeEvent(); + + if (this.buttons) { + for (var i = 0; i < this.buttons.length; i++) { + if (!(this.buttons[i] instanceof Button)) { + this.buttons[i] = new Button( + utils.extend( + this.buttons[i], + { + editor: this.editor + }, + true + ) + ); + } + } + } + }, + initResizeEvent: function () { + var me = this; + + + domUtils.on(window, "resize", function () { + + if (me._hidden || me._hidden === undefined) { + return; + } + + if (me.__resizeTimer) { + window.clearTimeout(me.__resizeTimer); + } + + me.__resizeTimer = window.setTimeout(function () { + me.__resizeTimer = null; + + + var dialogWrapNode = me.getDom(), + contentNode = me.getDom("content"), + wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), + contentRect = UE.ui.uiUtils.getClientRect(contentNode), + vpRect = uiUtils.getViewportRect(); + + contentNode.style.width = + vpRect.width - wrapRect.width + contentRect.width + "px"; + contentNode.style.height = + vpRect.height - wrapRect.height + contentRect.height + "px"; + + dialogWrapNode.style.width = vpRect.width + "px"; + dialogWrapNode.style.height = vpRect.height + "px"; + + me.fireEvent("resize"); + }, 100); + }); + }, + fitSize: function () { + // console.log('fitSize.dialog') + var popBodyEl = this.getDom("body"); + var $foot = popBodyEl.querySelector('.edui-dialog-foot'); + var heightWithoutBody = 70; + if (!$foot) { + heightWithoutBody = 30; + } + var size = this.mesureSize(); + var winSize = uiUtils.getViewportRect(); + var width = size.width; + var height = size.height - heightWithoutBody; + var maxWidth = winSize.width - 2; + var maxHeight = winSize.height - heightWithoutBody - 2; + if (width > maxWidth) { + height = height * maxWidth / width; + width = maxWidth; + } + if (height > maxHeight) { + width = width * maxHeight / height; + height = maxHeight; + } + var scale = (width / size.width); + // console.log('size', {sizeWidth: size.width, sizeHeight: size.height, width, height, scale}); + // console.log('popBodyEl',popBodyEl, popBodyEl.querySelector('.edui-dialog-foot')); + // window._xxx = popBodyEl; + var $content = popBodyEl.querySelector('.edui-dialog-content'); + if (!$content.dataset.dialogScaled) { + $content.dataset.dialogScaled = true + $content.style.width = (width) + 'px'; + $content.style.height = (height) + 'px'; + var $iframe = popBodyEl.querySelector('.edui-dialog-content iframe'); + $iframe.style.width = (size.width) + 'px'; + $iframe.style.height = (size.height - heightWithoutBody) + 'px'; + $iframe.style.transformOrigin = '0 0'; + $iframe.style.transform = 'scale(' + scale + ')'; + size.width = width + size.height = height + heightWithoutBody + } + popBodyEl.style.width = size.width + "px"; + popBodyEl.style.height = size.height + "px"; + return size; + }, + safeSetOffset: function (offset) { + var me = this; + var el = me.getDom(); + var vpRect = uiUtils.getViewportRect(); + var rect = uiUtils.getClientRect(el); + var left = offset.left; + if (left + rect.width > vpRect.right) { + left = vpRect.right - rect.width; + } + var top = offset.top; + if (top + rect.height > vpRect.bottom) { + top = vpRect.bottom - rect.height; + } + el.style.left = Math.max(left, 0) + "px"; + el.style.top = Math.max(top, 0) + "px"; + }, + showAtCenter: function () { + var vpRect = uiUtils.getViewportRect(); + + if (!this.fullscreen) { + this.getDom().style.display = ""; + var popSize = this.fitSize(); + var titleHeight = this.getDom("titlebar").offsetHeight | 0; + var left = vpRect.width / 2 - popSize.width / 2; + var top = + vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight; + var popEl = this.getDom(); + this.safeSetOffset({ + left: Math.max(left | 0, 0), + top: Math.max(top | 0, 0) + }); + if (!domUtils.hasClass(popEl, "edui-state-centered")) { + popEl.className += " edui-state-centered"; + } + } else { + var dialogWrapNode = this.getDom(), + contentNode = this.getDom("content"); + + dialogWrapNode.style.display = "block"; + + var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), + contentRect = UE.ui.uiUtils.getClientRect(contentNode); + dialogWrapNode.style.left = "-100000px"; + + contentNode.style.width = + vpRect.width - wrapRect.width + contentRect.width + "px"; + contentNode.style.height = + vpRect.height - wrapRect.height + contentRect.height + "px"; + + dialogWrapNode.style.width = vpRect.width + "px"; + dialogWrapNode.style.height = vpRect.height + "px"; + dialogWrapNode.style.left = 0; + + //保存环境的overflow值 + this._originalContext = { + html: { + overflowX: document.documentElement.style.overflowX, + overflowY: document.documentElement.style.overflowY + }, + body: { + overflowX: document.body.style.overflowX, + overflowY: document.body.style.overflowY + } + }; + + document.documentElement.style.overflowX = "hidden"; + document.documentElement.style.overflowY = "hidden"; + document.body.style.overflowX = "hidden"; + document.body.style.overflowY = "hidden"; + } + + this._show(); + }, + getContentHtml: function () { + var contentHtml = ""; + if (typeof this.content == "string") { + contentHtml = this.content; + } else if (this.iframeUrl) { + contentHtml = + ''; + } + return contentHtml; + }, + getHtmlTpl: function () { + var footHtml = ""; + + if (this.buttons) { + var buff = []; + for (var i = 0; i < this.buttons.length; i++) { + buff[i] = this.buttons[i].renderHtml(); + } + footHtml = + '
    ' + + '
    ' + + buff.join("") + + "
    " + + "
    "; + } + + return ( + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + (this.title || "") + + "" + + "
    " + + this.closeButton.renderHtml() + + "
    " + + '
    ' + + (this.autoReset ? "" : this.getContentHtml()) + + "
    " + + footHtml + + "
    " + ); + }, + postRender: function () { + // todo: 保持居中/记住上次关闭位置选项 + if (!this.modalMask.getDom()) { + this.modalMask.render(); + this.modalMask.hide(); + } + if (!this.dragMask.getDom()) { + this.dragMask.render(); + this.dragMask.hide(); + } + var me = this; + this.addListener("show", function () { + me.modalMask.show(this.getDom().style.zIndex - 2); + }); + this.addListener("hide", function () { + me.modalMask.hide(); + }); + if (this.buttons) { + for (var i = 0; i < this.buttons.length; i++) { + this.buttons[i].postRender(); + } + } + domUtils.on(window, "resize", function () { + setTimeout(function () { + if (!me.isHidden()) { + me.safeSetOffset(uiUtils.getClientRect(me.getDom())); + } + }); + }); + + //hold住scroll事件,防止dialog的滚动影响页面 + // if( this.holdScroll ) { + // + // if( !me.iframeUrl ) { + // domUtils.on( document.getElementById( me.id + "_iframe"), !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } else { + // me.addListener('dialogafterreset', function(){ + // window.setTimeout(function(){ + // var iframeWindow = document.getElementById( me.id + "_iframe").contentWindow; + // + // if( browser.ie ) { + // + // var timer = window.setInterval(function(){ + // + // if( iframeWindow.document && iframeWindow.document.body ) { + // window.clearInterval( timer ); + // timer = null; + // domUtils.on( iframeWindow.document.body, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } + // + // }, 100); + // + // } else { + // domUtils.on( iframeWindow, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } + // + // }, 1); + // }); + // } + // + // } + this._hide(); + }, + mesureSize: function () { + var body = this.getDom("body"); + var width = uiUtils.getClientRect(this.getDom("content")).width; + var dialogBodyStyle = body.style; + dialogBodyStyle.width = width; + // console.log('getClientRect', body) + return uiUtils.getClientRect(body); + }, + _onTitlebarMouseDown: function (evt, el) { + if (this.draggable) { + var rect; + var vpRect = uiUtils.getViewportRect(); + var me = this; + uiUtils.startDrag(evt, { + ondragstart: function () { + rect = uiUtils.getClientRect(me.getDom()); + me.getDom("contmask").style.visibility = "visible"; + me.dragMask.show(me.getDom().style.zIndex - 1); + }, + ondragmove: function (x, y) { + var left = rect.left + x; + var top = rect.top + y; + me.safeSetOffset({ + left: left, + top: top + }); + }, + ondragstop: function () { + me.getDom("contmask").style.visibility = "hidden"; + domUtils.removeClasses(me.getDom(), ["edui-state-centered"]); + me.dragMask.hide(); + } + }); + } + }, + reset: function () { + this.getDom("content").innerHTML = this.getContentHtml(); + this.fireEvent("dialogafterreset"); + }, + _show: function () { + if (this._hidden) { + this.getDom().style.display = ""; + + //要高过编辑器的zindxe + this.editor.container.style.zIndex && + (this.getDom().style.zIndex = + this.editor.container.style.zIndex * 1 + 10); + this._hidden = false; + this.fireEvent("show"); + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = + this.getDom().style.zIndex - 4; + } + }, + isHidden: function () { + return this._hidden; + }, + _hide: function () { + if (!this._hidden) { + var wrapNode = this.getDom(); + wrapNode.style.display = "none"; + wrapNode.style.zIndex = ""; + wrapNode.style.width = ""; + wrapNode.style.height = ""; + this._hidden = true; + this.fireEvent("hide"); + } + }, + open: function () { + if (this.autoReset) { + //有可能还没有渲染 + try { + this.reset(); + } catch (e) { + this.render(); + this.open(); + } + } + this.showAtCenter(); + if (this.iframeUrl) { + try { + this.getDom("iframe").focus(); + } catch (ex) { + } + } + activeDialog = this; + }, + _onCloseButtonClick: function (evt, el) { + this.close(false); + }, + close: function (ok) { + if (this.fireEvent("close", ok) !== false) { + //还原环境 + if (this.fullscreen) { + document.documentElement.style.overflowX = this._originalContext.html.overflowX; + document.documentElement.style.overflowY = this._originalContext.html.overflowY; + document.body.style.overflowX = this._originalContext.body.overflowX; + document.body.style.overflowY = this._originalContext.body.overflowY; + delete this._originalContext; + } + this._hide(); + + //销毁content + var content = this.getDom("content"); + var iframe = this.getDom("iframe"); + if (content && iframe) { + var doc = iframe.contentDocument || iframe.contentWindow.document; + doc && (doc.body.innerHTML = ""); + domUtils.remove(content); + } + } + } + }; + utils.inherits(Dialog, UIBase); +})(); + + +// ui/menubutton.js +///import core +///import uicore +///import ui/menu.js +///import ui/splitbutton.js +(function() { + var utils = baidu.editor.utils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + MenuButton = (baidu.editor.ui.MenuButton = function(options) { + this.initOptions(options); + this.initMenuButton(); + }); + MenuButton.prototype = { + initMenuButton: function() { + var me = this; + this.uiName = "menubutton"; + this.popup = new Menu({ + items: me.items, + className: me.className, + editor: me.editor + }); + this.popup.addListener("show", function() { + var list = this; + for (var i = 0; i < list.items.length; i++) { + list.items[i].removeState("checked"); + if (list.items[i].value == me._value) { + list.items[i].addState("checked"); + this.value = me._value; + } + } + }); + this.initSplitButton(); + }, + setValue: function(value) { + this._value = value; + } + }; + utils.inherits(MenuButton, SplitButton); +})(); + + +// ui/multiMenu.js +///import core +///import uicore +///commands 表情 +(function() { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + MultiMenuPop = (baidu.editor.ui.MultiMenuPop = function(options) { + this.initOptions(options); + this.initMultiMenu(); + }); + + MultiMenuPop.prototype = { + initMultiMenu: function() { + var me = this; + this.popup = new Popup({ + content: "", + editor: me.editor, + iframe_rendered: false, + onshow: function() { + if (!this.iframe_rendered) { + this.iframe_rendered = true; + this.getDom("content").innerHTML = + ''; + me.editor.container.style.zIndex && + (this.getDom().style.zIndex = + me.editor.container.style.zIndex * 1 + 1); + } + } + // canSideUp:false, + // canSideLeft:false + }); + this.onbuttonclick = function() { + this.showPopup(); + }; + this.initSplitButton(); + } + }; + + utils.inherits(MultiMenuPop, SplitButton); +})(); + + +// ui/shortcutmenu.js +(function() { + var UI = baidu.editor.ui, + UIBase = UI.UIBase, + uiUtils = UI.uiUtils, + utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils; + + var allMenus = [], //存储所有快捷菜单 + timeID, + isSubMenuShow = false; //是否有子pop显示 + + var ShortCutMenu = (UI.ShortCutMenu = function(options) { + this.initOptions(options); + this.initShortCutMenu(); + }); + + ShortCutMenu.postHide = hideAllMenu; + + ShortCutMenu.prototype = { + isHidden: true, + SPACE: 5, + initShortCutMenu: function() { + this.items = this.items || []; + this.initUIBase(); + this.initItems(); + this.initEvent(); + allMenus.push(this); + }, + initEvent: function() { + var me = this, + doc = me.editor.document; + + /* + domUtils.on(doc, "mousemove", function(e) { + if (me.isHidden === false) { + //有pop显示就不隐藏快捷菜单 + if (me.getSubMenuMark() || me.eventType == "contextmenu") return; + + var flag = true, + el = me.getDom(), + wt = el.offsetWidth, + ht = el.offsetHeight, + distanceX = wt / 2 + me.SPACE, //距离中心X标准 + distanceY = ht / 2, //距离中心Y标准 + x = Math.abs(e.screenX - me.left), //离中心距离横坐标 + y = Math.abs(e.screenY - me.top); //离中心距离纵坐标 + + clearTimeout(timeID); + timeID = setTimeout(function() { + if (y > 0 && y < distanceY) { + me.setOpacity(el, "1"); + } else if (y > distanceY && y < distanceY + 70) { + me.setOpacity(el, "0.5"); + flag = false; + } else if (y > distanceY + 70 && y < distanceY + 140) { + me.hide(); + } + + if (flag && x > 0 && x < distanceX) { + me.setOpacity(el, "1"); + } else if (x > distanceX && x < distanceX + 70) { + me.setOpacity(el, "0.5"); + } else if (x > distanceX + 70 && x < distanceX + 140) { + console.log('hide') + me.hide(); + } + }); + } + }); + */ + //ie\ff下 mouseout不准 + /* + if (browser.chrome) { + domUtils.on(doc, "mouseout", function(e) { + var relatedTgt = e.relatedTarget || e.toElement; + + if (relatedTgt == null || relatedTgt.tagName == "HTML") { + me.hide(); + } + }); + } + */ + + me.editor.addListener("afterhidepop", function() { + if (!me.isHidden) { + isSubMenuShow = true; + } + }); + }, + initItems: function() { + if (utils.isArray(this.items)) { + for (var i = 0, len = this.items.length; i < len; i++) { + if('string' !== typeof this.items[i]){ + continue; + } + var item = this.items[i].toLowerCase(); + + if (UI[item]) { + this.items[i] = new UI[item](this.editor); + this.items[i].className += " edui-shortcutsubmenu "; + } + } + } + }, + setOpacity: function(el, value) { + if (browser.ie && browser.version < 9) { + el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"; + } else { + el.style.opacity = value; + } + }, + getSubMenuMark: function() { + isSubMenuShow = false; + var layerEle = uiUtils.getFixedLayer(); + var list = domUtils.getElementsByTagName(layerEle, "div", function(node) { + return domUtils.hasClass(node, "edui-shortcutsubmenu edui-popup"); + }); + + for (var i = 0, node; (node = list[i++]); ) { + if (node.style.display != "none") { + isSubMenuShow = true; + } + } + return isSubMenuShow; + }, + show: function(e, hasContextmenu) { + var me = this, + offset = {}, + el = this.getDom(), + fixedlayer = uiUtils.getFixedLayer(); + + function setPos(offset) { + if (offset.left < 0) { + offset.left = 0; + } + if (offset.top < 0) { + offset.top = 0; + } + el.style.cssText = + "position:absolute;left:" + + offset.left + + "px;top:" + + offset.top + + "px;"; + } + + function setPosByCxtMenu(menu) { + if (!menu.tagName) { + menu = menu.getDom(); + } + offset.left = parseInt(menu.style.left); + offset.top = parseInt(menu.style.top); + offset.top -= el.offsetHeight + 15; + setPos(offset); + } + + me.eventType = e.type; + el.style.cssText = "display:block;left:-9999px"; + + if (e.type == "contextmenu" && hasContextmenu) { + var menu = domUtils.getElementsByTagName( + fixedlayer, + "div", + "edui-contextmenu" + )[0]; + if (menu) { + setPosByCxtMenu(menu); + } else { + me.editor.addListener("aftershowcontextmenu", function(type, menu) { + setPosByCxtMenu(menu); + }); + } + } else { + offset = uiUtils.getViewportOffsetByEvent(e); + offset.top -= el.offsetHeight + me.SPACE; + offset.left += me.SPACE + 20; + setPos(offset); + me.setOpacity(el, 1); + } + + me.isHidden = false; + me.left = e.screenX + el.offsetWidth / 2 - me.SPACE; + me.top = e.screenY - el.offsetHeight / 2 - me.SPACE; + + if (me.editor) { + el.style.zIndex = me.editor.container.style.zIndex * 1 + 10; + fixedlayer.style.zIndex = el.style.zIndex - 1; + } + }, + hide: function() { + if (this.getDom()) { + this.getDom().style.display = "none"; + } + this.isHidden = true; + }, + postRender: function() { + if (utils.isArray(this.items)) { + for (var i = 0, item; (item = this.items[i++]); ) { + item.postRender(); + } + } + }, + getHtmlTpl: function() { + var buff; + if (utils.isArray(this.items)) { + buff = []; + for (var i = 0; i < this.items.length; i++) { + buff[i] = this.items[i].renderHtml(); + } + buff = buff.join(""); + } else { + buff = this.items; + } + + return ( + '
    ' + + buff + + "
    " + ); + } + }; + + utils.inherits(ShortCutMenu, UIBase); + + function hideAllMenu(e) { + var tgt = e.target || e.srcElement, + cur = domUtils.findParent( + tgt, + function(node) { + return ( + domUtils.hasClass(node, "edui-shortcutmenu") || + domUtils.hasClass(node, "edui-popup") + ); + }, + true + ); + + if (!cur) { + for (var i = 0, menu; (menu = allMenus[i++]); ) { + menu.hide(); + } + } + } + + domUtils.on(document, "mousedown", function(e) { + hideAllMenu(e); + }); + + domUtils.on(window, "scroll", function(e) { + hideAllMenu(e); + }); +})(); + + +// ui/breakline.js +(function() { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Breakline = (baidu.editor.ui.Breakline = function(options) { + this.initOptions(options); + this.initSeparator(); + }); + Breakline.prototype = { + uiName: "Breakline", + initSeparator: function() { + this.initUIBase(); + }, + getHtmlTpl: function() { + return "
    "; + } + }; + utils.inherits(Breakline, UIBase); +})(); + + +// ui/message.js +///import core +///import uicore +(function() { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Message = (baidu.editor.ui.Message = function(options) { + this.initOptions(options); + this.initMessage(); + }); + + Message.prototype = { + initMessage: function() { + this.initUIBase(); + }, + getHtmlTpl: function() { + return ( + '
    ' + + '
    ×
    ' + + '
    ' + + ' ' + + '
    ' + + '
    ' + + "
    " + + "
    " + + "
    " + ); + }, + reset: function(opt) { + var me = this; + if (!opt.keepshow) { + clearTimeout(this.timer); + me.timer = setTimeout(function() { + me.hide(); + }, opt.timeout || 4000); + } + + opt.content !== undefined && me.setContent(opt.content); + opt.type !== undefined && me.setType(opt.type); + + me.show(); + }, + postRender: function() { + var me = this, + closer = this.getDom("closer"); + closer && + domUtils.on(closer, "click", function() { + me.hide(); + }); + }, + setContent: function(content) { + this.getDom("content").innerHTML = content; + }, + setType: function(type) { + type = type || "info"; + var body = this.getDom("body"); + body.className = body.className.replace( + /edui-message-type-[\w-]+/, + "edui-message-type-" + type + ); + }, + getContent: function() { + return this.getDom("content").innerHTML; + }, + getType: function() { + var arr = this.getDom("body").match(/edui-message-type-([\w-]+)/); + return arr ? arr[1] : ""; + }, + show: function() { + this.getDom().style.display = "block"; + }, + hide: function() { + var dom = this.getDom(); + if (dom) { + dom.style.display = "none"; + dom.parentNode && dom.parentNode.removeChild(dom); + } + } + }; + + utils.inherits(Message, UIBase); +})(); + + +// adapter/editorui.js +//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?20220503", + insertimage: "~/dialogs/image/image.html?20220503", + link: "~/dialogs/link/link.html?20220503", + spechars: "~/dialogs/spechars/spechars.html?20220503", + searchreplace: "~/dialogs/searchreplace/searchreplace.html?20220503", + insertvideo: "~/dialogs/video/video.html?20220503", + insertaudio: "~/dialogs/audio/audio.html?20220503", + help: "~/dialogs/help/help.html?20220503", + preview: "~/dialogs/preview/preview.html?20220503", + emotion: "~/dialogs/emotion/emotion.html?20220503", + wordimage: "~/dialogs/wordimage/wordimage.html?20220902", + formula: "~/dialogs/formula/formula.html?20230822", + attachment: "~/dialogs/attachment/attachment.html?20220503", + insertframe: "~/dialogs/insertframe/insertframe.html?20220503", + edittip: "~/dialogs/table/edittip.html?20220503", + edittable: "~/dialogs/table/edittable.html?20220503", + edittd: "~/dialogs/table/edittd.html?20220503", + scrawl: "~/dialogs/scrawl/scrawl.html?20220503", + template: "~/dialogs/template/template.html?20220503", + background: "~/dialogs/background/background.html?20220503", + }; + //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起 + 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", + ]; + + 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); + // console.log('selectionchange',cmd,uiReady,state); + 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) { + 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); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function() { + ui.setDisabled(editor.queryCommandState(cmd) == -1); + }); + return ui; + }; + })(ci); + } + + var dialogBtns = { + noOk: ["searchreplace", "help", "spechars", "preview"], + ok: [ + "attachment", + "anchor", + "link", + "insertimage", + "insertframe", + "wordimage", + "insertvideo", + "insertaudio", + "insertframe", + "edittip", + "edittable", + "edittd", + "scrawl", + "template", + "formula", + "background", + ] + }; + + 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: /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(editor.options.toolbarCallback){ + if(true === editor.options.toolbarCallback(cmd,editor)){ + return; + } + } + 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) + }); + 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()); + } + })(p, dialogBtns[p]); + } + + 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; + } + } + + 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); + } + } + }); + 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); + } + 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); + } + } + }); + 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.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(); + } + }); + 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 + + "" + + "
    " + ); + } + }); + })(t); + } + + 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); + } + }); + } + 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[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); + } + //有序,无序列表 + 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); + } + + 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; + }; +})(); + + +// adapter/editor.js +///import core +///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" + ](); + } + }); + 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/gi.test(el.tagName) + ) { + var html = popup.formatHtml( + "" + + '' + + 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-audio") != -1 || + img.className.indexOf("edui-upload-audio") != -1 + ) { + dialogName = "insertaudioDialog"; + } + if (img.getAttribute("anchorname")) { + dialogName = "anchorDialog"; + html = popup.formatHtml( + "" + + '' + + editor.getLang("modify") + + "  " + + "" + + editor.getLang("delete") + + "" + ); + } + // if (img.getAttribute("data-word-image")) { + // //todo 放到dialog去做查询 + // editor['data-word-image'] = [img.getAttribute("data-word-image")]; + // dialogName = "wordimageDialog"; + // } + if ( + domUtils.hasClass(img, "loadingclass") || + domUtils.hasClass(img, "loaderrorclass") + ) { + dialogName = ""; + } + if (!dialogs[dialogName]) { + return; + } + + var actions = []; + actions.push(''); + actions.push('' + + editor.getLang("default") + + ""); + actions.push('' + + editor.getLang("justifyleft") + + ""); + actions.push('' + + editor.getLang("justifyright") + + ""); + actions.push('' + + editor.getLang("justifycenter") + + ""); + if (img.getAttribute('data-formula-image') !== null) { + actions.push("" + + editor.getLang("formulaedit") + ""); + } + if (img.getAttribute("data-word-image")) { + actions.push("" + + editor.getLang("save") + + ""); + } else { + actions.push("' + + editor.getLang("modify") + + ""); + } + actions.push(""); + + !html && (html = popup.formatHtml(actions.join(""))); + } + 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("anchorMsg") + + ': ' + + 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 || []; + if(toolbars[0]){ + toolbars[0].unshift( + 'message' + ); + } + 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; + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + (this.toolbars.length + ? '
    ' + + this.renderToolbarBoxHtml() + + "
    " + : "") + + '" + + '
    ' + + "
    " + + '
    ' + + "
    " + + //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); + } + + 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:var(--ueditor-top-offset," + + (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; + } + + 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_CORS_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?20230921", + 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) { + holder = document.getElementById(holder); + } + 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实例 + * @desc 提供一个全局的方法得到编辑器实例 + * + * * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回 + * * ''opt'' 编辑器的可选参数 + * @example + * UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例 + * this.setContent('hello') + * }}); + * 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 + }; + }); + }; +})(); + + +// adapter/message.js +UE.registerUI("message", function(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.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("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(); + }); + + 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/public/static/plugs/ueditor/ueditor.config.js b/public/static/plugs/ueditor/ueditor.config.js new file mode 100644 index 0000000..37af1ca --- /dev/null +++ b/public/static/plugs/ueditor/ueditor.config.js @@ -0,0 +1,655 @@ +/** + * ueditor plus 完整配置项 + * 可以在这里配置整个编辑器的特性 + */ +/**************************提示******************************** + * 所有被注释的配置项均为UEditor默认值。 + * 修改默认配置请首先确保已经完全明确该参数的真实用途。 + * 主要有两种修改方案,一种是取消此处注释,然后修改成对应参数;另一种是在实例化编辑器时传入对应参数。 + * 当升级编辑器时,可直接使用旧版配置文件替换新版配置文件,不用担心旧版配置文件中因缺少新功能所需的参数而导致脚本报错。 + **************************提示********************************/ + +(function () { + /** + * 编辑器资源文件根路径。它所表示的含义是:以编辑器实例化页面为当前路径,指向编辑器资源文件(即dialog等文件夹)的路径。 + * 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。 + * "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。 + * 如果站点中有多个不在同一层级的页面需要实例化编辑器,且引用了同一UEditor的时候,此处的URL可能不适用于每个页面的编辑器。 + * 因此,UEditor提供了针对不同页面的编辑器可单独配置的根路径,具体来说,在需要实例化编辑器的页面最顶部写上如下代码即可。当然,需要令此处的URL等于对应的配置。 + * window.UEDITOR_HOME_URL = "/xxxx/xxxx/"; + */ + window.UEDITOR_HOME_URL = "/static/plugs/ueditor/"; + var URL, CORS_URL; + if (window.UEDITOR_HOME_URL) { + URL = window.UEDITOR_HOME_URL; + } else if (window.__msCDN) { + URL = window.__msCDN + 'asset/vendor/ueditor/'; + } else if (window.__msRoot) { + URL = window.__msRoot + 'asset/vendor/ueditor/'; + } else { + URL = getUEBasePath(); + } + if (window.UEDITOR_CORS_URL) { + CORS_URL = window.UEDITOR_CORS_URL; + } else if (window.__msRoot) { + CORS_URL = window.__msRoot + 'asset/vendor/ueditor/'; + } else if (window.UEDITOR_HOME_URL) { + CORS_URL = window.UEDITOR_HOME_URL; + } else { + CORS_URL = getUEBasePath(); + } + + /** + * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。 + */ + window.UEDITOR_CONFIG = { + + // 为编辑器实例添加一个路径,这个不能被注释 + UEDITOR_HOME_URL: URL, + // 需要能跨域的静态资源请求,主要用户弹窗页面等静态资源 + UEDITOR_CORS_URL: CORS_URL, + + // 是否开启Debug模式 + debug: false, + + // 服务器统一请求接口路径 + serverUrl: "/admin/ajax/uploadUEditor", + // 服务器统一请求头信息,会在所有请求中带上该信息 + serverHeaders: { + // 'Authorization': 'Bearer xxx' + }, + + //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义 + toolbars: [ + [ + "fullscreen", // 全屏 + "source", // 源代码 + "|", + "undo", // 撤销 + "redo", // 重做 + "|", + "bold", // 加粗 + "italic", // 斜体 + "underline", // 下划线 + "fontborder", // 字符边框 + "strikethrough",// 删除线 + "superscript", // 上标 + "subscript", // 下标 + "removeformat", // 清除格式 + "formatmatch", // 格式刷 + "autotypeset", // 自动排版 + "blockquote", // 引用 + "pasteplain", // 纯文本粘贴模式 + "|", + "forecolor", // 字体颜色 + "backcolor", // 背景色 + "insertorderedlist", // 有序列表 + "insertunorderedlist", // 无序列表 + "selectall", // 全选 + "cleardoc", // 清空文档 + "|", + "rowspacingtop",// 段前距 + "rowspacingbottom", // 段后距 + "lineheight", // 行间距 + "|", + "customstyle", // 自定义标题 + "paragraph", // 段落格式 + "fontfamily", // 字体 + "fontsize", // 字号 + "|", + "directionalityltr", // 从左向右输入 + "directionalityrtl", // 从右向左输入 + "indent", // 首行缩进 + "|", + "justifyleft", // 居左对齐 + "justifycenter", // 居中对齐 + "justifyright", + "justifyjustify", // 两端对齐 + "|", + "touppercase", // 字母大写 + "tolowercase", // 字母小写 + "|", + "link", // 超链接 + "unlink", // 取消链接 + "anchor", // 锚点 + "|", + "imagenone", // 图片默认 + "imageleft", // 图片左浮动 + "imageright", // 图片右浮动 + "imagecenter", // 图片居中 + "|", + "simpleupload", // 单图上传 + "insertimage", // 多图上传 + "emotion", // 表情 + "scrawl", // 涂鸦 + "insertvideo", // 视频 + "insertaudio", // 音频 + "attachment", // 附件 + "insertframe", // 插入Iframe + "insertcode", // 插入代码 + "pagebreak", // 分页 + "template", // 模板 + "background", // 背景 + "formula", // 公式 + "|", + "horizontal", // 分隔线 + "date", // 日期 + "time", // 时间 + "spechars", // 特殊字符 + "wordimage", // Word图片转存 + "|", + "inserttable", // 插入表格 + "deletetable", // 删除表格 + "insertparagraphbeforetable", // 表格前插入行 + "insertrow", // 前插入行 + "deleterow", // 删除行 + "insertcol", // 前插入列 + "deletecol", // 删除列 + "mergecells", // 合并多个单元格 + "mergeright", // 右合并单元格 + "mergedown", // 下合并单元格 + "splittocells", // 完全拆分单元格 + "splittorows", // 拆分成行 + "splittocols", // 拆分成列 + "|", + "print", // 打印 + "preview", // 预览 + "searchreplace", // 查询替换 + "help", // 帮助 + ] + ] + + // 自定义工具栏按钮点击,返回 true 表示已经处理点击,会阻止默认事件 + , toolbarCallback: function (cmd, editor) { + // switch(cmd){ + // case 'insertimage': + // editor.execCommand('insertHtml', '

    '); + // console.log('toolbarCallback',cmd, editor) + // return true; + // case 'insertvideo': + // editor.execCommand('insertHtml', '