From 90e4d2318ad091035e47a78946e347e51ad79c8a Mon Sep 17 00:00:00 2001 From: zicla Date: Thu, 28 Dec 2017 13:25:50 +0800 Subject: [PATCH 01/22] Fix the InputUserSelection bug. --- src/backyard/matter/word/List.vue | 27 ----- .../user/widget/UserInputSelection.vue | 104 +++++++++--------- src/common/model/matter/Matter.js | 6 +- 3 files changed, 56 insertions(+), 81 deletions(-) delete mode 100644 src/backyard/matter/word/List.vue diff --git a/src/backyard/matter/word/List.vue b/src/backyard/matter/word/List.vue deleted file mode 100644 index 9c1fe8c..0000000 --- a/src/backyard/matter/word/List.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - \ No newline at end of file diff --git a/src/backyard/user/widget/UserInputSelection.vue b/src/backyard/user/widget/UserInputSelection.vue index 328eaa2..3d2f5e8 100644 --- a/src/backyard/user/widget/UserInputSelection.vue +++ b/src/backyard/user/widget/UserInputSelection.vue @@ -1,32 +1,35 @@ \ No newline at end of file + From 5aca8292b1ce7e3980277b9f483853c2c262b156 Mon Sep 17 00:00:00 2001 From: seaheart Date: Thu, 28 Dec 2017 15:09:04 +0800 Subject: [PATCH 05/22] complete folder move batch. --- src/assets/css/global/color.less | 429 ++++++++++++++---- src/backyard/matter/List.vue | 57 ++- src/backyard/matter/widget/FolderTree.vue | 100 ++++ src/backyard/matter/widget/MoveBatchPanel.vue | 38 ++ 4 files changed, 529 insertions(+), 95 deletions(-) create mode 100644 src/backyard/matter/widget/FolderTree.vue create mode 100644 src/backyard/matter/widget/MoveBatchPanel.vue diff --git a/src/assets/css/global/color.less b/src/assets/css/global/color.less index 894e30d..3a784ab 100644 --- a/src/assets/css/global/color.less +++ b/src/assets/css/global/color.less @@ -1,102 +1,359 @@ @import "../inspinia/variables.less"; @import "./variables.less"; -.bg-primary{ background-color: @brand-primary; color: white;} -.bg-success{ background-color: @brand-success; color: white; } -.bg-info{ background-color: @brand-info; color: white; } -.bg-warning{ background-color: @brand-warning; color: white; } -.bg-danger{ background-color: @brand-danger; color: white; } -.bg-gray{ background-color: @brand-gray; color: white; } -.bg-laxative{ background-color: @brand-laxative; color: white; } +.bg-primary { + background-color: @brand-primary; + color: white; +} +.bg-success { + background-color: @brand-success; + color: white; +} -.text-primary{ color:@brand-primary; } +.bg-info { + background-color: @brand-info; + color: white; +} -.bg-navy { background-color: #001F3F;} -.bg-blue { background-color: #0074D9;} -.bg-aqua { background-color: #7FDBFF;} -.bg-aliceblue { background-color: aliceblue;} -.bg-pink { background-color: pink;} -.bg-azure { background-color: azure;} -.bg-teal { background-color: #39CCCC;} -.bg-olive { background-color: #3D9970;} -.bg-green { background-color: #2ECC40;} -.bg-lime { background-color: #01FF70;} -.bg-yellow { background-color: #FFDC00;} -.bg-pink { color: pink; } -.bg-orange { background-color: #FF851B;} -.bg-red { background-color: #FF4136;} -.bg-fuchsia { background-color: #F012BE;} -.bg-purple { background-color: #B10DC9;} -.bg-maroon { background-color: #85144B;} -.bg-white { background-color: #FFFFFF;} -.bg-gray { background-color: #AAAAAA;} -.bg-silver { background-color: #DDDDDD;} -.bg-black { background-color: #111111;} +.bg-warning { + background-color: @brand-warning; + color: white; +} -.bg-111{ background-color:#111 } -.bg-222{ background-color:#222 } -.bg-333{ background-color:#333 } -.bg-444{ background-color:#444 } -.bg-555{ background-color:#555 } -.bg-666{ background-color:#666 } -.bg-777{ background-color:#777 } -.bg-888{ background-color:#888 } -.bg-999{ background-color:#999 } -.bg-aaa{ background-color:#aaa } -.bg-bbb{ background-color:#bbb } -.bg-ccc{ background-color:#ccc } -.bg-ddd{ background-color:#ddd } -.bg-eee{ background-color:#eee } +.bg-danger { + background-color: @brand-danger; + color: white; +} +.bg-gray { + background-color: @brand-gray; + color: white; +} + +.bg-laxative { + background-color: @brand-laxative; + color: white; +} + +.text-primary { + color: @brand-primary; +} + +.bg-navy { + background-color: #001F3F; +} + +.bg-blue { + background-color: #0074D9; +} + +.bg-aqua { + background-color: #7FDBFF; +} + +.bg-aliceblue { + background-color: aliceblue; +} + +.bg-pink { + background-color: pink; +} + +.bg-azure { + background-color: azure; +} + +.bg-teal { + background-color: #39CCCC; +} + +.bg-olive { + background-color: #3D9970; +} + +.bg-green { + background-color: #2ECC40; +} + +.bg-lime { + background-color: #01FF70; +} + +.bg-yellow { + background-color: #FFDC00; +} + +.bg-pink { + color: pink; +} + +.bg-orange { + background-color: #FF851B; +} + +.bg-red { + background-color: #FF4136; +} + +.bg-fuchsia { + background-color: #F012BE; +} + +.bg-purple { + background-color: #B10DC9; +} + +.bg-maroon { + background-color: #85144B; +} + +.bg-white { + background-color: #FFFFFF; +} + +.bg-gray { + background-color: #AAAAAA; +} + +.bg-silver { + background-color: #DDDDDD; +} + +.bg-silver-white { + background-color: #EEEEEE; +} + +.bg-black { + background-color: #111111; +} + +.bg-111 { + background-color: #111 +} + +.bg-222 { + background-color: #222 +} + +.bg-333 { + background-color: #333 +} + +.bg-444 { + background-color: #444 +} + +.bg-555 { + background-color: #555 +} + +.bg-666 { + background-color: #666 +} + +.bg-777 { + background-color: #777 +} + +.bg-888 { + background-color: #888 +} + +.bg-999 { + background-color: #999 +} + +.bg-aaa { + background-color: #aaa +} + +.bg-bbb { + background-color: #bbb +} + +.bg-ccc { + background-color: #ccc +} + +.bg-ddd { + background-color: #ddd +} + +.bg-eee { + background-color: #eee +} /* Colors */ -.navy { color: #001F3F;} -.blue { color: #0074D9;} -.aqua { color: #7FDBFF;} -.teal { color: #39CCCC;} -.olive { color: #3D9970;} -.green { color: #2ECC40;} -.lime { color: #01FF70;} -.yellow { color: #FFDC00;} -.pink { color: pink; } -.orange { color: #FF851B;} -.red { color: #FF4136;} -.fuchsia { color: #F012BE;} -.purple { color: #B10DC9;} -.maroon { color: #85144B;} -.white { color: #FFFFFF;} -.silver { color: #DDDDDD;} -.gray { color: #AAAAAA;} -.black { color: #111111;} +.navy { + color: #001F3F; +} +.blue { + color: #0074D9; +} -.color-111{color:#111} -.color-222{color:#222} -.color-333{color:#333} -.color-444{color:#444} -.color-555{color:#555} -.color-666{color:#666} -.color-777{color:#777} -.color-888{color:#888} -.color-999{color:#999} -.color-aaa{color:#aaa} -.color-bbb{color:#bbb} -.color-ccc{color:#ccc} -.color-ddd{color:#ddd} -.color-eee{color:#eee} +.aqua { + color: #7FDBFF; +} +.teal { + color: #39CCCC; +} -.color-text { color: #660E7A;} -.color-doc { color: #295496;} -.color-xls { color: #1E6C41;} -.color-ppt { color: #D04324;} -.color-pdf { color: #E40B0B;} -.color-audio { color: #5bc0de;} -.color-video { color: #5cb85c;} -.color-image { color: #0074D9;} -.color-archive { color: #4437f2;} +.olive { + color: #3D9970; +} -.color-light-active{ color: #ffc60c;} -.color-light-inactive{ color:#ccc;} +.green { + color: #2ECC40; +} + +.lime { + color: #01FF70; +} + +.yellow { + color: #FFDC00; +} + +.pink { + color: pink; +} + +.orange { + color: #FF851B; +} + +.red { + color: #FF4136; +} + +.fuchsia { + color: #F012BE; +} + +.purple { + color: #B10DC9; +} + +.maroon { + color: #85144B; +} + +.white { + color: #FFFFFF; +} + +.silver { + color: #DDDDDD; +} + +.gray { + color: #AAAAAA; +} + +.black { + color: #111111; +} + +.color-111 { + color: #111 +} + +.color-222 { + color: #222 +} + +.color-333 { + color: #333 +} + +.color-444 { + color: #444 +} + +.color-555 { + color: #555 +} + +.color-666 { + color: #666 +} + +.color-777 { + color: #777 +} + +.color-888 { + color: #888 +} + +.color-999 { + color: #999 +} + +.color-aaa { + color: #aaa +} + +.color-bbb { + color: #bbb +} + +.color-ccc { + color: #ccc +} + +.color-ddd { + color: #ddd +} + +.color-eee { + color: #eee +} + +.color-text { + color: #660E7A; +} + +.color-doc { + color: #295496; +} + +.color-xls { + color: #1E6C41; +} + +.color-ppt { + color: #D04324; +} + +.color-pdf { + color: #E40B0B; +} + +.color-audio { + color: #5bc0de; +} + +.color-video { + color: #5cb85c; +} + +.color-image { + color: #0074D9; +} + +.color-archive { + color: #4437f2; +} + +.color-light-active { + color: #ffc60c; +} + +.color-light-inactive { + color: #ccc; +} diff --git a/src/backyard/matter/List.vue b/src/backyard/matter/List.vue index 66503b4..1b85c28 100644 --- a/src/backyard/matter/List.vue +++ b/src/backyard/matter/List.vue @@ -7,11 +7,14 @@
- - @@ -19,6 +22,11 @@ 删除 + @@ -62,7 +70,7 @@ + + \ No newline at end of file diff --git a/src/backyard/matter/widget/MoveBatchPanel.vue b/src/backyard/matter/widget/MoveBatchPanel.vue new file mode 100644 index 0000000..a31330c --- /dev/null +++ b/src/backyard/matter/widget/MoveBatchPanel.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file From efcec8405abb1a67028667b1d920e84fd712d84c Mon Sep 17 00:00:00 2001 From: zicla Date: Thu, 28 Dec 2017 15:16:42 +0800 Subject: [PATCH 06/22] Add alien field and remove a lot of useless things. --- src/backyard/preference/Edit.vue | 15 - src/backyard/tag/Create.vue | 87 - src/backyard/tag/List.vue | 104 - src/backyard/user/Create.vue | 2 - src/backyard/wheel/Index.vue | 31 - .../fork/wangeditor/PluginAlignCenter.js | 108 - .../fork/wangeditor/PluginAlignJustify.js | 109 - src/common/fork/wangeditor/PluginAlignLeft.js | 108 - .../fork/wangeditor/PluginAlignRight.js | 108 - .../fork/wangeditor/PluginAttachment.js | 78 - src/common/fork/wangeditor/PluginHr.js | 49 - src/common/fork/wangeditor/PluginImage.js | 76 - src/common/fork/wangeditor/PluginIndent.js | 98 - src/common/fork/wangeditor/WEAttachment.vue | 86 - src/common/fork/wangeditor/WEImage.vue | 111 - src/common/fork/wangeditor/WangEditor.js | 8588 ----------------- .../fork/wangeditor/css/wangEditor.less | 810 -- src/common/fork/wangeditor/fonts/icomoon.eot | Bin 15648 -> 0 bytes src/common/fork/wangeditor/fonts/icomoon.svg | 76 - src/common/fork/wangeditor/fonts/icomoon.ttf | Bin 15484 -> 0 bytes src/common/fork/wangeditor/fonts/icomoon.woff | Bin 15560 -> 0 bytes src/common/model/matter/Matter.js | 10 +- src/common/model/preference/Preference.js | 6 - src/common/model/tag/Tag.js | 54 - src/common/widget/NbTags.vue | 186 - src/common/widget/NbTank.vue | 192 - src/common/widget/NbTanks.vue | 228 - static/img/file/alien.svg | 1 + 28 files changed, 9 insertions(+), 11312 deletions(-) delete mode 100644 src/backyard/tag/Create.vue delete mode 100644 src/backyard/tag/List.vue delete mode 100644 src/common/fork/wangeditor/PluginAlignCenter.js delete mode 100644 src/common/fork/wangeditor/PluginAlignJustify.js delete mode 100644 src/common/fork/wangeditor/PluginAlignLeft.js delete mode 100644 src/common/fork/wangeditor/PluginAlignRight.js delete mode 100644 src/common/fork/wangeditor/PluginAttachment.js delete mode 100644 src/common/fork/wangeditor/PluginHr.js delete mode 100644 src/common/fork/wangeditor/PluginImage.js delete mode 100644 src/common/fork/wangeditor/PluginIndent.js delete mode 100644 src/common/fork/wangeditor/WEAttachment.vue delete mode 100644 src/common/fork/wangeditor/WEImage.vue delete mode 100644 src/common/fork/wangeditor/WangEditor.js delete mode 100644 src/common/fork/wangeditor/css/wangEditor.less delete mode 100644 src/common/fork/wangeditor/fonts/icomoon.eot delete mode 100644 src/common/fork/wangeditor/fonts/icomoon.svg delete mode 100644 src/common/fork/wangeditor/fonts/icomoon.ttf delete mode 100644 src/common/fork/wangeditor/fonts/icomoon.woff delete mode 100644 src/common/model/tag/Tag.js delete mode 100644 src/common/widget/NbTags.vue delete mode 100644 src/common/widget/NbTank.vue delete mode 100644 src/common/widget/NbTanks.vue create mode 100644 static/img/file/alien.svg diff --git a/src/backyard/preference/Edit.vue b/src/backyard/preference/Edit.vue index 15e9f71..e287d1e 100644 --- a/src/backyard/preference/Edit.vue +++ b/src/backyard/preference/Edit.vue @@ -17,19 +17,6 @@
-
- -
- -
-
- -
- -
- -
-
@@ -44,7 +31,6 @@ - - \ No newline at end of file diff --git a/src/backyard/tag/List.vue b/src/backyard/tag/List.vue deleted file mode 100644 index 4b10345..0000000 --- a/src/backyard/tag/List.vue +++ /dev/null @@ -1,104 +0,0 @@ - - - - - diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index b74344a..ce9fefb 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -90,7 +90,6 @@ import { Notification } from 'element-ui' import { FeatureType } from '../../common/model/feature/FeatureType' import NbRadio from '../../common/widget/NbRadio.vue' - import NbTank from '../../common/widget/NbTank.vue' import CreateSaveButton from '../widget/CreateSaveButton' import User from '../../common/model/user/User' @@ -106,7 +105,6 @@ }, components: { NbRadio, - NbTank, CreateSaveButton }, methods: { diff --git a/src/backyard/wheel/Index.vue b/src/backyard/wheel/Index.vue index 5eb320c..558f420 100644 --- a/src/backyard/wheel/Index.vue +++ b/src/backyard/wheel/Index.vue @@ -9,53 +9,22 @@
-
-
-

- NbTank演示: -

-
-
-

- 1.私有文件演示: -

-
-
- -
- -
-

- 2.公有文件演示: -

-
-
- -
- - -
- - - - - - diff --git a/src/common/fork/wangeditor/WEImage.vue b/src/common/fork/wangeditor/WEImage.vue deleted file mode 100644 index 2c9c195..0000000 --- a/src/common/fork/wangeditor/WEImage.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - diff --git a/src/common/fork/wangeditor/WangEditor.js b/src/common/fork/wangeditor/WangEditor.js deleted file mode 100644 index 44f58aa..0000000 --- a/src/common/fork/wangeditor/WangEditor.js +++ /dev/null @@ -1,8588 +0,0 @@ -(function (factory) { - // 引用 css —— webapck - //require('wangeditor/dist/css/wangEditor.css'); - module.exports = factory( - // 传入 jquery ,支持使用 npm 方式或者自己定义jquery的路径 - require('jquery') - ); -})(function ($) { - - // 验证是否引用jquery - if (!$ || !$.fn || !$.fn.jquery) { - alert('在引用wangEditor.js之前,先引用jQuery,否则无法使用 wangEditor'); - return; - } - - let WangEditor = null; - // 定义扩展函数 - let _e = function (fn) { - if (WangEditor) { - // 执行传入的函数 - fn(WangEditor, $); - } - }; -// 定义构造函数 - (function (window, $) { - - // 编辑器(整体)构造函数 - let E = function (elem) { - // 支持 id 和 element 两种形式 - if (typeof elem === 'string') { - elem = '#' + elem; - } - - // ---------------获取基本节点------------------ - let $elem = $(elem); - if ($elem.length !== 1) { - return; - } - let nodeName = $elem[0].nodeName; - if (nodeName !== 'TEXTAREA' && nodeName !== 'DIV') { - // 只能是 textarea 和 div ,其他类型的元素不行 - return; - } - this.valueNodeName = nodeName.toLowerCase(); - this.$valueContainer = $elem; - - // 记录 elem 的 prev 和 parent(最后渲染 editor 要用到) - this.$prev = $elem.prev(); - this.$parent = $elem.parent(); - - // ------------------初始化------------------ - this.init(); - }; - - E.fn = E.prototype; - - E.$body = $('body'); - E.$document = $(document); - E.$window = $(window); - E.userAgent = navigator.userAgent; - E.getComputedStyle = window.getComputedStyle; - E.w3cRange = typeof document.createRange === 'function'; - E.hostname = location.hostname.toLowerCase(); - E.websiteHost = 'wangeditor.github.io|www.wangeditor.com|wangeditor.coding.me'; - E.isOnWebsite = E.websiteHost.indexOf(E.hostname) >= 0; - E.docsite = 'http://www.kancloud.cn/wangfupeng/wangeditor2/113961'; - - //二次开发全屏功能 - E.fullScreenClick = null; - E.fullScreenClickSelected = null; - - - // 暴露给全局对象 - WangEditor = E; - - // 注册 plugin 事件,用于用户自定义插件 - // 用户在引用 WangEditor.js 之后,还可以通过 E.plugin() 注入自定义函数, - // 该函数将会在 editor.create() 方法的最后一步执行 - E.plugin = function (fn) { - if (!E._plugins) { - E._plugins = []; - } - - if (typeof fn === 'function') { - E._plugins.push(fn); - } - }; - - })(window, $); -// editor 绑定事件 - _e(function (E, $) { - - E.fn.init = function () { - - // 初始化 editor 默认配置 - this.initDefaultConfig(); - - // 增加container - this.addEditorContainer(); - - // 增加编辑区域 - this.addTxt(); - - // 增加menuContainer - this.addMenuContainer(); - - // 初始化菜单集合 - this.menus = {}; - - // 初始化commandHooks - this.commandHooks(); - - }; - - }); -// editor api - _e(function (E, $) { - - // 预定义 ready 事件 - E.fn.ready = function (fn) { - - if (!this.readyFns) { - this.readyFns = []; - } - - this.readyFns.push(fn); - }; - - // 处理ready事件 - E.fn.readyHeadler = function () { - let fns = this.readyFns; - - while (fns.length) { - fns.shift().call(this); - } - }; - - // 更新内容到 $valueContainer - E.fn.updateValue = function () { - let editor = this; - let $valueContainer = editor.$valueContainer; - let $txt = editor.txt.$txt; - - if ($valueContainer === $txt) { - // 传入生成编辑器的div,即是编辑区域 - return; - } - - let value = $txt.html(); - $valueContainer.val(value); - }; - - // 获取初始化的内容 - E.fn.getInitValue = function () { - let editor = this; - let $valueContainer = editor.$valueContainer; - let currentValue = ''; - let nodeName = editor.valueNodeName; - if (nodeName === 'div') { - currentValue = $valueContainer.html(); - } else if (nodeName === 'textarea') { - currentValue = $valueContainer.val(); - } - - return currentValue; - }; - - // 触发菜单updatestyle - E.fn.updateMenuStyle = function () { - let menus = this.menus; - - $.each(menus, function (k, menu) { - menu.updateSelected(); - }); - }; - - // 除了传入的 menuIds,其他全部启用 - E.fn.enableMenusExcept = function (menuIds) { - if (this._disabled) { - // 编辑器处于禁用状态,则不执行改操作 - return; - } - // menuIds参数:支持数组和字符串 - menuIds = menuIds || []; - if (typeof menuIds === 'string') { - menuIds = [menuIds]; - } - - $.each(this.menus, function (k, menu) { - if (menuIds.indexOf(k) >= 0) { - return; - } - menu.disabled(false); - }); - }; - - // 除了传入的 menuIds,其他全部禁用 - E.fn.disableMenusExcept = function (menuIds) { - if (this._disabled) { - // 编辑器处于禁用状态,则不执行改操作 - return; - } - // menuIds参数:支持数组和字符串 - menuIds = menuIds || []; - if (typeof menuIds === 'string') { - menuIds = [menuIds]; - } - - $.each(this.menus, function (k, menu) { - if (menuIds.indexOf(k) >= 0) { - return; - } - menu.disabled(true); - }); - }; - - // 隐藏所有 dropPanel droplist modal - E.fn.hideDropPanelAndModal = function () { - let menus = this.menus; - - $.each(menus, function (k, menu) { - let m = menu.dropPanel || menu.dropList || menu.modal; - if (m && m.hide) { - m.hide(); - } - }); - }; - - }); -// selection range API - _e(function (E, $) { - - // 用到 w3c range 的函数,如果检测到浏览器不支持 w3c range,则赋值为空函数 - let ieRange = !E.w3cRange; - - function emptyFn() { - } - - // 设置或读取当前的range - E.fn.currentRange = function (cr) { - if (cr) { - this._rangeData = cr; - } else { - return this._rangeData; - } - }; - - // 将当前选区折叠 - E.fn.collapseRange = function (range, opt) { - // opt 参数说明:'start'-折叠到开始; 'end'-折叠到结束 - opt = opt || 'end'; - opt = opt === 'start' ? true : false; - - range = range || this.currentRange(); - - if (range) { - // 合并,保存 - range.collapse(opt); - this.currentRange(range); - } - }; - - // 获取选区的文字 - E.fn.getRangeText = ieRange ? emptyFn : function (range) { - range = range || this.currentRange(); - if (!range) { - return; - } - return range.toString(); - }; - - // 获取选区对应的DOM对象 - E.fn.getRangeElem = ieRange ? emptyFn : function (range) { - range = range || this.currentRange(); - let dom = range.commonAncestorContainer; - - if (dom.nodeType === 1) { - return dom; - } else { - return dom.parentNode; - } - }; - - // 选区内容是否为空? - E.fn.isRangeEmpty = ieRange ? emptyFn : function (range) { - range = range || this.currentRange(); - - if (range && range.startContainer) { - if (range.startContainer === range.endContainer) { - if (range.startOffset === range.endOffset) { - return true; - } - } - } - - return false; - }; - - // 保存选区数据 - E.fn.saveSelection = ieRange ? emptyFn : function (range) { - let self = this, - _parentElem, - selection, - txt = self.txt.$txt.get(0); - - if (range) { - _parentElem = range.commonAncestorContainer; - } else { - selection = document.getSelection(); - if (selection.getRangeAt && selection.rangeCount) { - range = document.getSelection().getRangeAt(0); - _parentElem = range.commonAncestorContainer; - } - } - // 确定父元素一定要包含在编辑器区域内 - if (_parentElem && ($.contains(txt, _parentElem) || txt === _parentElem)) { - // 保存选择区域 - self.currentRange(range); - } - }; - - // 恢复选中区域 - E.fn.restoreSelection = ieRange ? emptyFn : function (range) { - let selection; - - range = range || this.currentRange(); - - if (!range) { - return; - } - - // 使用 try catch 来防止 IE 某些情况报错 - try { - selection = document.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); - } catch (ex) { - E.error('执行 editor.restoreSelection 时,IE可能会有异常,不影响使用'); - } - }; - - // 根据elem恢复选区 - E.fn.restoreSelectionByElem = ieRange ? emptyFn : function (elem, opt) { - // opt参数说明:'start'-折叠到开始,'end'-折叠到结束,'all'-全部选中 - if (!elem) { - return; - } - opt = opt || 'end'; // 默认为折叠到结束 - - // 根据elem获取选区 - this.setRangeByElem(elem); - - // 根据 opt 折叠选区 - if (opt === 'start') { - this.collapseRange(this.currentRange(), 'start'); - } - if (opt === 'end') { - this.collapseRange(this.currentRange(), 'end'); - } - - // 恢复选区 - this.restoreSelection(); - }; - - // 初始化选区 - E.fn.initSelection = ieRange ? emptyFn : function () { - let editor = this; - if (editor.currentRange()) { - //如果currentRange有值,则不用再初始化 - return; - } - - let range; - let $txt = editor.txt.$txt; - let $firstChild = $txt.children().first(); - - if ($firstChild.length) { - editor.restoreSelectionByElem($firstChild.get(0)); - } - }; - - // 根据元素创建选区 - E.fn.setRangeByElem = ieRange ? emptyFn : function (elem) { - let editor = this; - let txtElem = editor.txt.$txt.get(0); - if (!elem || !$.contains(txtElem, elem)) { - return; - } - - // 找到elem的第一个 textNode 和 最后一个 textNode - let firstTextNode = elem.firstChild; - while (firstTextNode) { - if (firstTextNode.nodeType === 3) { - break; - } - // 继续向下 - firstTextNode = firstTextNode.firstChild; - } - let lastTextNode = elem.lastChild; - while (lastTextNode) { - if (lastTextNode.nodeType === 3) { - break; - } - // 继续向下 - lastTextNode = lastTextNode.lastChild; - } - - let range = document.createRange(); - if (firstTextNode && lastTextNode) { - // 说明 elem 有内容,能取到子元素 - range.setStart(firstTextNode, 0); - range.setEnd(lastTextNode, lastTextNode.textContent.length); - } else { - // 说明 elem 无内容 - range.setStart(elem, 0); - range.setEnd(elem, 0); - } - - // 保存选区 - editor.saveSelection(range); - }; - - }); -// selection range API - IE8及以下 - _e(function (E, $) { - - if (E.w3cRange) { - // 说明支持 W3C 的range方法 - return; - } - - // -----------------IE8时,需要重写以下方法------------------- - - // 获取选区的文字 - E.fn.getRangeText = function (range) { - range = range || this.currentRange(); - if (!range) { - return; - } - return range.text; - }; - - // 获取选区对应的DOM对象 - E.fn.getRangeElem = function (range) { - range = range || this.currentRange(); - if (!range) { - return; - } - let dom = range.parentElement(); - - if (dom.nodeType === 1) { - return dom; - } else { - return dom.parentNode; - } - }; - - // 选区内容是否为空? - E.fn.isRangeEmpty = function (range) { - range = range || this.currentRange(); - - if (range && range.text) { - return false; - } - - return true; - }; - - // 保存选区数据 - E.fn.saveSelection = function (range) { - let self = this, - _parentElem, - selection, - txt = self.txt.$txt.get(0); - - if (range) { - _parentElem = range.parentElement(); - } else { - range = document.selection.createRange(); - if (typeof range.parentElement === 'undefined') { - //IE6、7中,insertImage后会执行此处 - //由于找不到range.parentElement,所以干脆将_parentElem赋值为null - _parentElem = null; - } else { - _parentElem = range.parentElement(); - } - } - - // 确定父元素一定要包含在编辑器区域内 - if (_parentElem && ($.contains(txt, _parentElem) || txt === _parentElem)) { - // 保存选择区域 - self.currentRange(range); - } - }; - - // 恢复选中区域 - E.fn.restoreSelection = function (currentRange) { - let editor = this, - selection, - range; - - currentRange = currentRange || editor.currentRange(); - if (!currentRange) { - return; - } - - range = document.selection.createRange(); - try { - // 此处,plupload上传上传图片时,IE8-会报一个『参数无效』的错误 - range.setEndPoint('EndToEnd', currentRange); - } catch (ex) { - - } - - if (currentRange.text.length === 0) { - try { - // IE8 插入表情会报错 - range.collapse(false); - } catch (ex) { - - } - - } else { - range.setEndPoint('StartToStart', currentRange); - } - range.select(); - }; - - }); -// editor command hooks - _e(function (E, $) { - - E.fn.commandHooks = function () { - let editor = this; - let commandHooks = {}; - - // insertHtml - commandHooks.insertHtml = function (html) { - let $elem = $(html); - let rangeElem = editor.getRangeElem(); - let targetElem; - - targetElem = editor.getLegalTags(rangeElem); - if (!targetElem) { - return; - } - - $(targetElem).after($elem); - }; - - // 保存到对象 - editor.commandHooks = commandHooks; - }; - - }); -// editor command API - _e(function (E, $) { - - // 基本命令 - E.fn.command = function (e, commandName, commandValue, callback) { - let editor = this; - let hooks; - - function commandFn() { - if (!commandName) { - return; - } - if (editor.queryCommandSupported(commandName)) { - // 默认命令 - document.execCommand(commandName, false, commandValue); - } else { - // hooks 命令 - hooks = editor.commandHooks; - if (commandName in hooks) { - hooks[commandName](commandValue); - } - } - } - - this.customCommand(e, commandFn, callback); - }; - - // 针对一个elem对象执行基础命令 - E.fn.commandForElem = function (elemOpt, e, commandName, commandValue, callback) { - // 取得查询elem的查询条件和验证函数 - let selector; - let check; - if (typeof elemOpt === 'string') { - selector = elemOpt; - } else { - selector = elemOpt.selector; - check = elemOpt.check; - } - - // 查询elem - let rangeElem = this.getRangeElem(); - rangeElem = this.getSelfOrParentByName(rangeElem, selector, check); - - // 根据elem设置range - if (rangeElem) { - this.setRangeByElem(rangeElem); - } - - // 然后执行基础命令 - this.command(e, commandName, commandValue, callback); - }; - - // 自定义命令 - E.fn.customCommand = function (e, commandFn, callback) { - let editor = this; - let range = editor.currentRange(); - - if (!range) { - // 目前没有选区,则无法执行命令 - e && e.preventDefault(); - return; - } - // 记录内容,以便撤销(执行命令之前就要记录) - editor.undoRecord(); - - // 恢复选区(有 range 参数) - this.restoreSelection(range); - - // 执行命令事件 - commandFn.call(editor); - - // 保存选区(无参数,要从浏览器直接获取range信息) - this.saveSelection(); - // 重新恢复选区(无参数,要取得刚刚从浏览器得到的range信息) - this.restoreSelection(); - - // 执行 callback - if (callback && typeof callback === 'function') { - callback.call(editor); - } - - // 最后插入空行 - editor.txt.insertEmptyP(); - - // 包裹暴露的img和text - editor.txt.wrapImgAndText(); - - // 更新内容 - editor.updateValue(); - - // 更新菜单样式 - editor.updateMenuStyle(); - - // 隐藏 dropPanel dropList modal 设置 200ms 间隔 - function hidePanelAndModal() { - editor.hideDropPanelAndModal(); - } - - setTimeout(hidePanelAndModal, 200); - - if (e) { - e.preventDefault(); - } - }; - - // 封装 document.queryCommandValue 函数 - // IE8 直接执行偶尔会报错,因此直接用 try catch 封装一下 - E.fn.queryCommandValue = function (commandName) { - let result = ''; - try { - result = document.queryCommandValue(commandName); - } catch (ex) { - - } - return result; - }; - - // 封装 document.queryCommandState 函数 - // IE8 直接执行偶尔会报错,因此直接用 try catch 封装一下 - E.fn.queryCommandState = function (commandName) { - let result = false; - try { - result = document.queryCommandState(commandName); - } catch (ex) { - - } - return result; - }; - - // 封装 document.queryCommandSupported 函数 - E.fn.queryCommandSupported = function (commandName) { - let result = false; - try { - result = document.queryCommandSupported(commandName); - } catch (ex) { - - } - return result; - }; - - }); -// dom selector - _e(function (E, $) { - - let matchesSelector; - - // matchesSelector hook - function _matchesSelectorForIE(selector) { - let elem = this; - let $elems = $(selector); - let result = false; - - // 用jquery查找 selector 所有对象,如果其中有一个和传入 elem 相同,则证明 elem 符合 selector - $elems.each(function () { - if (this === elem) { - result = true; - return false; - } - }); - - return result; - } - - // 从当前的elem,往上去查找合法标签 如 p head table blockquote ul ol 等 - E.fn.getLegalTags = function (elem) { - let legalTags = this.config.legalTags; - if (!legalTags) { - E.error('配置项中缺少 legalTags 的配置'); - return; - } - return this.getSelfOrParentByName(elem, legalTags); - }; - - // 根据条件,查询自身或者父元素,符合即返回 - E.fn.getSelfOrParentByName = function (elem, selector, check) { - - if (!elem || !selector) { - return; - } - - if (!matchesSelector) { - // 定义 matchesSelector 函数 - matchesSelector = elem.webkitMatchesSelector || - elem.mozMatchesSelector || - elem.oMatchesSelector || - elem.matchesSelector; - } - if (!matchesSelector) { - // 如果浏览器本身不支持 matchesSelector 则使用自定义的hook - matchesSelector = _matchesSelectorForIE; - } - - let txt = this.txt.$txt.get(0); - - while (elem && txt !== elem && $.contains(txt, elem)) { - if (matchesSelector.call(elem, selector)) { - // 符合 selector 查询条件 - - if (!check) { - // 没有 check 验证函数,直接返回即可 - return elem; - } - - if (check(elem)) { - // 如果有 check 验证函数,还需 check 函数的确认 - return elem; - } - } - - // 如果上一步没经过验证,则将跳转到父元素 - elem = elem.parentNode; - } - - return; - }; - - }); -// undo redo - _e(function (E, $) { - - let length = 20; // 缓存的最大长度 - function _getRedoList(editor) { - if (editor._redoList == null) { - editor._redoList = []; - } - return editor._redoList; - } - - function _getUndoList(editor) { - if (editor._undoList == null) { - editor._undoList = []; - } - return editor._undoList; - } - - // 数据处理 - function _handle(editor, data, type) { - // let range = data.range; - // let range2 = range.cloneRange && range.cloneRange(); - let val = data.val; - let html = editor.txt.$txt.html(); - - if (val == null) { - return; - } - - if (val === html) { - if (type === 'redo') { - editor.redo(); - return; - } else if (type === 'undo') { - editor.undo(); - return; - } else { - return; - } - } - - // 保存数据 - editor.txt.$txt.html(val); - // 更新数据到textarea(有必要的话) - editor.updateValue(); - - // onchange 事件 - if (editor.onchange && typeof editor.onchange === 'function') { - editor.onchange.call(editor); - } - - // ????? - // 注释:$txt 被重新赋值之后,range会被重置,cloneRange() 也不好使 - // // 重置选区 - // if (range2) { - // editor.restoreSelection(range2); - // } - } - - // 记录 - E.fn.undoRecord = function () { - let editor = this; - let $txt = editor.txt.$txt; - let val = $txt.html(); - let undoList = _getUndoList(editor); - let redoList = _getRedoList(editor); - let currentVal = undoList.length ? undoList[0] : ''; - - if (val === currentVal.val) { - return; - } - - // 清空 redolist - if (redoList.length) { - redoList = []; - } - - // 添加数据到 undoList - undoList.unshift({ - range: editor.currentRange(), // 将当前的range也记录下 - val: val - }); - - // 限制 undoList 长度 - if (undoList.length > length) { - undoList.pop(); - } - }; - - // undo 操作 - E.fn.undo = function () { - let editor = this; - let undoList = _getUndoList(editor); - let redoList = _getRedoList(editor); - - if (!undoList.length) { - return; - } - - // 取出 undolist 第一个值,加入 redolist - let data = undoList.shift(); - redoList.unshift(data); - - // 并修改编辑器的内容 - _handle(this, data, 'undo'); - }; - - // redo 操作 - E.fn.redo = function () { - let editor = this; - let undoList = _getUndoList(editor); - let redoList = _getRedoList(editor); - if (!redoList.length) { - return; - } - - // 取出 redolist 第一个值,加入 undolist - let data = redoList.shift(); - undoList.unshift(data); - - // 并修改编辑器的内容 - _handle(this, data, 'redo'); - }; - }); -// 暴露给用户的 API - _e(function (E, $) { - - // 创建编辑器 - E.fn.create = function () { - let editor = this; - - // 检查 E.$body 是否有值 - // 如果在 body 之前引用了 js 文件,body 尚未加载,可能没有值 - if (!E.$body || E.$body.length === 0) { - E.$body = $('body'); - E.$document = $(document); - E.$window = $(window); - } - - // 执行 addMenus 之前: - // 1. 允许用户修改 editor.UI 自定义配置UI - // 2. 允许用户通过修改 editor.menus 来自定义配置菜单 - // 因此要在 create 时执行,而不是 init - editor.addMenus(); - - // 渲染 - editor.renderMenus(); - editor.renderMenuContainer(); - editor.renderTxt(); - editor.renderEditorContainer(); - - // 绑定事件 - editor.eventMenus(); - editor.eventMenuContainer(); - editor.eventTxt(); - - // 处理ready事件 - editor.readyHeadler(); - - // 初始化选区 - editor.initSelection(); - - // $txt 快捷方式 - editor.$txt = editor.txt.$txt; - - // 执行用户自定义事件,通过 E.ready() 添加 - let _plugins = E._plugins; - if (_plugins && _plugins.length) { - $.each(_plugins, function (k, val) { - val.call(editor); - }); - } - }; - - // 禁用编辑器 - E.fn.disable = function () { - this.txt.$txt.removeAttr('contenteditable'); - this.disableMenusExcept(); - - // 先禁用,再记录状态 - this._disabled = true; - }; - // 启用编辑器 - E.fn.enable = function () { - // 先解除状态记录,再启用 - this._disabled = false; - this.txt.$txt.attr('contenteditable', 'true'); - this.enableMenusExcept(); - }; - - // 销毁编辑器 - E.fn.destroy = function () { - let self = this; - let $valueContainer = self.$valueContainer; - let $editorContainer = self.$editorContainer; - let valueNodeName = self.valueNodeName; - - if (valueNodeName === 'div') { - // div 生成的编辑器 - $valueContainer.removeAttr('contenteditable'); - $editorContainer.after($valueContainer); - $editorContainer.hide(); - } else { - // textarea 生成的编辑器 - $valueContainer.show(); - $editorContainer.hide(); - } - }; - - // 撤销 销毁编辑器 - E.fn.undestroy = function () { - let self = this; - let $valueContainer = self.$valueContainer; - let $editorContainer = self.$editorContainer; - let $menuContainer = self.menuContainer.$menuContainer; - let valueNodeName = self.valueNodeName; - - if (valueNodeName === 'div') { - // div 生成的编辑器 - $valueContainer.attr('contenteditable', 'true'); - $menuContainer.after($valueContainer); - $editorContainer.show(); - } else { - // textarea 生成的编辑器 - $valueContainer.hide(); - $editorContainer.show(); - } - }; - - // 清空内容的快捷方式 - E.fn.clear = function () { - let editor = this; - let $txt = editor.txt.$txt; - $txt.html('


'); - editor.restoreSelectionByElem($txt.find('p').get(0)); - }; - - }); -// menuContainer 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let MenuContainer = function (editor) { - this.editor = editor; - this.init(); - }; - - MenuContainer.fn = MenuContainer.prototype; - - // 暴露给 E - E.MenuContainer = MenuContainer; - - }); -// MenuContainer.fn bind fn - _e(function (E, $) { - - let MenuContainer = E.MenuContainer; - - // 初始化 - MenuContainer.fn.init = function () { - let self = this; - let $menuContainer = $('
'); - - self.$menuContainer = $menuContainer; - - // change shadow - self.changeShadow(); - }; - - // 编辑区域滚动时,增加shadow - MenuContainer.fn.changeShadow = function () { - let $menuContainer = this.$menuContainer; - let editor = this.editor; - let $txt = editor.txt.$txt; - - $txt.on('scroll', function () { - if ($txt.scrollTop() > 10) { - $menuContainer.addClass('wangEditor-menu-shadow'); - } else { - $menuContainer.removeClass('wangEditor-menu-shadow'); - } - }); - }; - - }); -// MenuContainer.fn API - _e(function (E, $) { - - let MenuContainer = E.MenuContainer; - - MenuContainer.fn.render = function () { - let $menuContainer = this.$menuContainer; - let $editorContainer = this.editor.$editorContainer; - - $editorContainer.append($menuContainer); - }; - - // 获取菜单栏的高度 - MenuContainer.fn.height = function () { - let $menuContainer = this.$menuContainer; - return $menuContainer.height(); - }; - - // 添加菜单 - MenuContainer.fn.appendMenu = function (groupIdx, menu) { - // 判断是否需要新增一个菜单组 - this._addGroup(groupIdx); - // 增加菜单(返回 $menuItem) - return this._addOneMenu(menu); - }; - MenuContainer.fn._addGroup = function (groupIdx) { - let $menuContainer = this.$menuContainer; - let $menuGroup; - if (!this.$currentGroup || this.currentGroupIdx !== groupIdx) { - $menuGroup = $(''); - $menuContainer.append($menuGroup); - - this.$currentGroup = $menuGroup; - this.currentGroupIdx = groupIdx; - } - }; - MenuContainer.fn._addOneMenu = function (menu) { - let $menuNormal = menu.$domNormal; - let $menuSelected = menu.$domSelected; - - let $menuGroup = this.$currentGroup; - let $item = $(''); - $menuSelected.hide(); - $item.append($menuNormal).append($menuSelected); - $menuGroup.append($item); - - return $item; - }; - - }); -// menu 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let Menu = function (opt) { - this.editor = opt.editor; - this.id = opt.id; - this.title = opt.title; - this.$domNormal = opt.$domNormal; - this.$domSelected = opt.$domSelected || opt.$domNormal; - - // document.execCommand 的参数 - this.commandName = opt.commandName; - this.commandValue = opt.commandValue; - this.commandNameSelected = opt.commandNameSelected || opt.commandName; - this.commandValueSelected = opt.commandValueSelected || opt.commandValue; - }; - - Menu.fn = Menu.prototype; - - // 暴露给 E - E.Menu = Menu; - }); -// Menu.fn 初始化绑定的事件 - _e(function (E, $) { - - let Menu = E.Menu; - - // 初始化UI - Menu.fn.initUI = function () { - let editor = this.editor; - let uiConfig = editor.UI.menus; - let menuId = this.id; - let menuUI = uiConfig[menuId]; - - if (this.$domNormal && this.$domSelected) { - // 自定义的菜单中,已经传入了 $dom 无需从配置文件中查找生成 - return; - } - - if (menuUI == null) { - E.warn('editor.UI配置中,没有菜单 "' + menuId + '" 的UI配置,只能取默认值'); - - // 必须写成 uiConfig['default']; - // 写成 uiConfig.default IE8会报错 - menuUI = uiConfig['default']; - } - - // 正常状态 - this.$domNormal = $(menuUI.normal); - - // 选中状态 - if (/^\./.test(menuUI.selected)) { - // 增加一个样式 - this.$domSelected = this.$domNormal.clone().addClass(menuUI.selected.slice(1)); - } else { - // 一个新的dom对象 - this.$domSelected = $(menuUI.selected); - } - }; - - }); -// Menu.fn API - _e(function (E, $) { - - let Menu = E.Menu; - - // 渲染菜单 - Menu.fn.render = function (groupIdx) { - // 渲染UI - this.initUI(); - - let editor = this.editor; - let menuContainer = editor.menuContainer; - let $menuItem = menuContainer.appendMenu(groupIdx, this); - let onRender = this.onRender; - - // 渲染tip - this._renderTip($menuItem); - - // 执行 onRender 函数 - if (onRender && typeof onRender === 'function') { - onRender.call(this); - } - }; - Menu.fn._renderTip = function ($menuItem) { - let self = this; - let editor = self.editor; - let title = self.title; - let $tip = $(''); - // let $triangle = $(''); // 小三角 - - // 计算 tip 宽度 - let $tempDiv; - if (!self.tipWidth) { - // 设置一个纯透明的 p(absolute;top:-10000px;不会显示在内容区域) - // 内容赋值为 title ,为了计算tip宽度 - $tempDiv = $('

' + title + '

'); - // 先添加到body,计算完再 remove - E.$body.append($tempDiv); - editor.ready(function () { - let editor = this; - let titleWidth = $tempDiv.outerWidth() + 5; // 多出 5px 的冗余 - let currentWidth = $tip.outerWidth(); - let currentMarginLeft = parseFloat($tip.css('margin-left'), 10); - // 计算完,拿到数据,则弃用 - $tempDiv.remove(); - $tempDiv = null; - - // 重新设置样式 - $tip.css({ - width: titleWidth, - 'margin-left': currentMarginLeft + (currentWidth - titleWidth) / 2 - }); - - // 存储 - self.tipWidth = titleWidth; - }); - } - - // $tip.append($triangle); - $tip.append(title); - $menuItem.append($tip); - - function show() { - $tip.show(); - } - - function hide() { - $tip.hide(); - } - - let timeoutId; - $menuItem.find('a').on('mouseenter', function (e) { - if (!self.active() && !self.disabled()) { - timeoutId = setTimeout(show, 200); - } - }).on('mouseleave', function (e) { - timeoutId && clearTimeout(timeoutId); - hide(); - }).on('click', hide); - }; - - // 绑定事件 - Menu.fn.bindEvent = function () { - let self = this; - - let $domNormal = self.$domNormal; - let $domSelected = self.$domSelected; - - // 试图获取该菜单定义的事件(未selected),没有则自己定义 - let clickEvent = self.clickEvent; - if (!clickEvent) { - clickEvent = function (e) { - // -----------dropPanel dropList modal----------- - let dropObj = self.dropPanel || self.dropList || self.modal; - if (dropObj && dropObj.show) { - if (dropObj.isShowing) { - dropObj.hide(); - } else { - dropObj.show(); - } - return; - } - - // -----------command----------- - let editor = self.editor; - let commandName; - let commandValue; - - let selected = self.selected; - if (selected) { - commandName = self.commandNameSelected; - commandValue = self.commandValueSelected; - } else { - commandName = self.commandName; - commandValue = self.commandValue; - } - - if (commandName) { - // 执行命令 - editor.command(e, commandName, commandValue); - } else { - // 提示 - E.warn('菜单 "' + self.id + '" 未定义click事件'); - e.preventDefault(); - } - }; - } - // 获取菜单定义的selected情况下的点击事件 - let clickEventSelected = self.clickEventSelected || clickEvent; - - // 将事件绑定到菜单dom上 - $domNormal.click(function (e) { - if (!self.disabled()) { - clickEvent.call(self, e); - self.updateSelected(); - } - e.preventDefault(); - }); - $domSelected.click(function (e) { - if (!self.disabled()) { - clickEventSelected.call(self, e); - self.updateSelected(); - } - e.preventDefault(); - }); - }; - - // 更新选中状态 - Menu.fn.updateSelected = function () { - let self = this; - let editor = self.editor; - - // 试图获取用户自定义的判断事件 - let updateSelectedEvent = self.updateSelectedEvent; - if (!updateSelectedEvent) { - // 用户未自定义,则设置默认值 - updateSelectedEvent = function () { - let self = this; - let editor = self.editor; - let commandName = self.commandName; - let commandValue = self.commandValue; - - if (commandValue) { - if (editor.queryCommandValue(commandName).toLowerCase() === commandValue.toLowerCase()) { - return true; - } - } else if (editor.queryCommandState(commandName)) { - return true; - } - - return false; - }; - } - - // 获取结果 - let result = updateSelectedEvent.call(self); - result = !!result; - - // 存储结果、显示效果 - self.changeSelectedState(result); - }; - - // 切换选中状态、显示效果 - Menu.fn.changeSelectedState = function (state) { - let self = this; - let selected = self.selected; - - if (state != null && typeof state === 'boolean') { - if (selected === state) { - // 计算结果和当前的状态一样 - return; - } - // 存储结果 - self.selected = state; - - // 切换菜单的显示 - if (state) { - // 选中 - self.$domNormal.hide(); - self.$domSelected.show(); - } else { - // 未选中 - self.$domNormal.show(); - self.$domSelected.hide(); - } - } // if - }; - - // 点击菜单,显示了 dropPanel modal 时,菜单的状态 - Menu.fn.active = function (active) { - if (active == null) { - return this._activeState; - } - this._activeState = active; - }; - Menu.fn.activeStyle = function (active) { - let selected = this.selected; - let $dom = this.$domNormal; - let $domSelected = this.$domSelected; - - if (active) { - $dom.addClass('active'); - $domSelected.addClass('active'); - } else { - $dom.removeClass('active'); - $domSelected.removeClass('active'); - } - - // 记录状态 ( menu hover 时会取状态用 ) - this.active(active); - }; - - // 菜单的启用和禁用 - Menu.fn.disabled = function (opt) { - // 参数为空,取值 - if (opt == null) { - return !!this._disabled; - } - - if (this._disabled === opt) { - // 要设置的参数值和当前参数只一样,无需再次设置 - return; - } - - let $dom = this.$domNormal; - let $domSelected = this.$domSelected; - - // 设置样式 - if (opt) { - $dom.addClass('disable'); - $domSelected.addClass('disable'); - } else { - $dom.removeClass('disable'); - $domSelected.removeClass('disable'); - } - - // 存储 - this._disabled = opt; - }; - - }); -// dropList 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let DropList = function (editor, menu, opt) { - this.editor = editor; - this.menu = menu; - - // list 的数据源,格式 {'commandValue': 'title', ...} - this.data = opt.data; - // 要为每个item自定义的模板 - this.tpl = opt.tpl; - // 为了执行 editor.commandForElem 而传入的elem查询方式 - this.selectorForELemCommand = opt.selectorForELemCommand; - - // 执行事件前后的钩子 - this.beforeEvent = opt.beforeEvent; - this.afterEvent = opt.afterEvent; - - // 初始化 - this.init(); - }; - - DropList.fn = DropList.prototype; - - // 暴露给 E - E.DropList = DropList; - }); -// dropList fn bind - _e(function (E, $) { - - let DropList = E.DropList; - - // init - DropList.fn.init = function () { - let self = this; - - // 生成dom对象 - self.initDOM(); - - // 绑定command事件 - self.bindEvent(); - - // 声明隐藏的事件 - self.initHideEvent(); - }; - - // 初始化dom结构 - DropList.fn.initDOM = function () { - let self = this; - let data = self.data; - let tpl = self.tpl || '{#title}'; - let $list = $('
'); - - let itemContent; - let $item; - $.each(data, function (commandValue, title) { - itemContent = tpl.replace(/{#commandValue}/ig, commandValue).replace(/{#title}/ig, title); - $item = $(''); - $item.append(itemContent); - $list.append($item); - }); - - self.$list = $list; - }; - - // 绑定事件 - DropList.fn.bindEvent = function () { - let self = this; - let editor = self.editor; - let menu = self.menu; - let commandName = menu.commandName; - let selectorForELemCommand = self.selectorForELemCommand; - let $list = self.$list; - - // 执行事件前后的钩子函数 - let beforeEvent = self.beforeEvent; - let afterEvent = self.afterEvent; - - $list.on('click', 'a[commandValue]', function (e) { - // 正式命令执行之前 - if (beforeEvent && typeof beforeEvent === 'function') { - beforeEvent.call(e); - } - - // 执行命令 - let commandValue = $(e.currentTarget).attr('commandValue'); - if (menu.selected && editor.isRangeEmpty() && selectorForELemCommand) { - // 当前处于选中状态,并且选中内容为空 - editor.commandForElem(selectorForELemCommand, e, commandName, commandValue); - } else { - // 当前未处于选中状态,或者有选中内容。则执行默认命令 - editor.command(e, commandName, commandValue); - } - - // 正式命令之后的钩子 - if (afterEvent && typeof afterEvent === 'function') { - afterEvent.call(e); - } - }); - }; - - // 点击其他地方,立即隐藏 droplist - DropList.fn.initHideEvent = function () { - let self = this; - - // 获取 list elem - let thisList = self.$list.get(0); - - E.$body.on('click', function (e) { - if (!self.isShowing) { - return; - } - let trigger = e.target; - - // 获取菜单elem - let menu = self.menu; - let menuDom; - if (menu.selected) { - menuDom = menu.$domSelected.get(0); - } else { - menuDom = menu.$domNormal.get(0); - } - - if (menuDom === trigger || $.contains(menuDom, trigger)) { - // 说明由本菜单点击触发的 - return; - } - - if (thisList === trigger || $.contains(thisList, trigger)) { - // 说明由本list点击触发的 - return; - } - - // 其他情况,隐藏 list - self.hide(); - }); - - E.$window.scroll(function () { - self.hide(); - }); - - E.$window.on('resize', function () { - self.hide(); - }); - }; - - }); -// dropListfn api - _e(function (E, $) { - - let DropList = E.DropList; - - // 渲染 - DropList.fn._render = function () { - let self = this; - let editor = self.editor; - let $list = self.$list; - - // 渲染到页面 - editor.$editorContainer.append($list); - - // 记录状态 - self.rendered = true; - }; - - // 定位 - DropList.fn._position = function () { - let self = this; - let $list = self.$list; - let editor = self.editor; - let menu = self.menu; - let $menuContainer = editor.menuContainer.$menuContainer; - let $menuDom = menu.selected ? menu.$domSelected : menu.$domNormal; - // 注意这里的 offsetParent() 要返回 .menu-item 的 position - // 因为 .menu-item 是 position:relative - let menuPosition = $menuDom.offsetParent().position(); - - // 取得 menu 的位置、尺寸属性 - let menuTop = menuPosition.top; - let menuLeft = menuPosition.left; - let menuHeight = $menuDom.offsetParent().height(); - let menuWidth = $menuDom.offsetParent().width(); - - // 取得 list 的尺寸属性 - let listWidth = $list.outerWidth(); - // let listHeight = $list.outerHeight(); - - // 取得 $txt 的尺寸 - let txtWidth = editor.txt.$txt.outerWidth(); - - // ------------开始计算------------- - - // 初步计算 list 位置属性 - let top = menuTop + menuHeight; - let left = menuLeft + menuWidth / 2; - let marginLeft = 0 - menuWidth / 2; - - // 如果超出了有边界,则要左移(且和右侧有间隙) - let valWithTxt = (left + listWidth) - txtWidth; - if (valWithTxt > -10) { - marginLeft = marginLeft - valWithTxt - 10; - } - // 设置样式 - $list.css({ - top: top, - left: left, - 'margin-left': marginLeft - }); - - // 如果因为向下滚动而导致菜单fixed,则再加一步处理 - if (editor._isMenufixed) { - top = top + (($menuContainer.offset().top + $menuContainer.outerHeight()) - $list.offset().top); - - // 重新设置top - $list.css({ - top: top - }); - } - }; - - // 显示 - DropList.fn.show = function () { - let self = this; - let menu = self.menu; - if (!self.rendered) { - // 第一次show之前,先渲染 - self._render(); - } - - if (self.isShowing) { - return; - } - - let $list = self.$list; - $list.show(); - - // 定位 - self._position(); - - // 记录状态 - self.isShowing = true; - - // 菜单状态 - menu.activeStyle(true); - }; - - // 隐藏 - DropList.fn.hide = function () { - let self = this; - let menu = self.menu; - if (!self.isShowing) { - return; - } - - let $list = self.$list; - $list.hide(); - - // 记录状态 - self.isShowing = false; - - // 菜单状态 - menu.activeStyle(false); - }; - }); -// dropPanel 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let DropPanel = function (editor, menu, opt) { - this.editor = editor; - this.menu = menu; - this.$content = opt.$content; - this.width = opt.width || 200; - this.height = opt.height; - this.onRender = opt.onRender; - - // init - this.init(); - }; - - DropPanel.fn = DropPanel.prototype; - - // 暴露给 E - E.DropPanel = DropPanel; - }); -// dropPanel fn bind - _e(function (E, $) { - - let DropPanel = E.DropPanel; - - // init - DropPanel.fn.init = function () { - let self = this; - - // 生成dom对象 - self.initDOM(); - - // 声明隐藏的事件 - self.initHideEvent(); - }; - - // init DOM - DropPanel.fn.initDOM = function () { - let self = this; - let $content = self.$content; - let width = self.width; - let height = self.height; - let $panel = $('
'); - let $triangle = $('
'); - - $panel.css({ - width: width, - height: height ? height : 'auto' - }); - $panel.append($triangle); - $panel.append($content); - - // 添加对象数据 - self.$panel = $panel; - self.$triangle = $triangle; - }; - - // 点击其他地方,立即隐藏 dropPanel - DropPanel.fn.initHideEvent = function () { - let self = this; - - // 获取 panel elem - let thisPanle = self.$panel.get(0); - - E.$body.on('click', function (e) { - if (!self.isShowing) { - return; - } - let trigger = e.target; - - // 获取菜单elem - let menu = self.menu; - let menuDom; - if (menu.selected) { - menuDom = menu.$domSelected.get(0); - } else { - menuDom = menu.$domNormal.get(0); - } - - if (menuDom === trigger || $.contains(menuDom, trigger)) { - // 说明由本菜单点击触发的 - return; - } - - if (thisPanle === trigger || $.contains(thisPanle, trigger)) { - // 说明由本panel点击触发的 - return; - } - - // 其他情况,隐藏 panel - self.hide(); - }); - - E.$window.scroll(function (e) { - self.hide(); - }); - - E.$window.on('resize', function () { - self.hide(); - }); - }; - - }); -// dropPanel fn api - _e(function (E, $) { - - let DropPanel = E.DropPanel; - - // 渲染 - DropPanel.fn._render = function () { - let self = this; - let onRender = self.onRender; - let editor = self.editor; - let $panel = self.$panel; - - // 渲染到页面 - editor.$editorContainer.append($panel); - - // 渲染后的回调事件 - onRender && onRender.call(self); - - // 记录状态 - self.rendered = true; - }; - - // 定位 - DropPanel.fn._position = function () { - let self = this; - let $panel = self.$panel; - let $triangle = self.$triangle; - let editor = self.editor; - let $menuContainer = editor.menuContainer.$menuContainer; - let menu = self.menu; - let $menuDom = menu.selected ? menu.$domSelected : menu.$domNormal; - // 注意这里的 offsetParent() 要返回 .menu-item 的 position - // 因为 .menu-item 是 position:relative - let menuPosition = $menuDom.offsetParent().position(); - - // 取得 menu 的位置、尺寸属性 - let menuTop = menuPosition.top; - let menuLeft = menuPosition.left; - let menuHeight = $menuDom.offsetParent().height(); - let menuWidth = $menuDom.offsetParent().width(); - - // 取得 panel 的尺寸属性 - let panelWidth = $panel.outerWidth(); - // let panelHeight = $panel.outerHeight(); - - // 取得 $txt 的尺寸 - let txtWidth = editor.txt.$txt.outerWidth(); - - // ------------开始计算------------- - - // 初步计算 panel 位置属性 - let top = menuTop + menuHeight; - let left = menuLeft + menuWidth / 2; - let marginLeft = 0 - panelWidth / 2; - let marginLeft2 = marginLeft; // 下文用于和 marginLeft 比较,来设置三角形tip的位置 - - // 如果超出了左边界,则移动回来(要和左侧有10px间隙) - if ((0 - marginLeft) > (left - 10)) { - marginLeft = 0 - (left - 10); - } - - // 如果超出了有边界,则要左移(且和右侧有10px间隙) - let valWithTxt = (left + panelWidth + marginLeft) - txtWidth; - if (valWithTxt > -10) { - marginLeft = marginLeft - valWithTxt - 10; - } - - // 设置样式 - $panel.css({ - top: top, - left: left, - 'margin-left': marginLeft - }); - - // 如果因为向下滚动而导致菜单fixed,则再加一步处理 - if (editor._isMenufixed) { - top = top + (($menuContainer.offset().top + $menuContainer.outerHeight()) - $panel.offset().top); - - // 重新设置top - $panel.css({ - top: top - }); - } - - // 设置三角形 tip 的位置 - $triangle.css({ - 'margin-left': marginLeft2 - marginLeft - 5 - }); - }; - - // focus 第一个 input - DropPanel.fn.focusFirstInput = function () { - let self = this; - let $panel = self.$panel; - $panel.find('input[type=text],textarea').each(function () { - let $input = $(this); - if ($input.attr('disabled') == null) { - $input.focus(); - return false; - } - }); - }; - - // 显示 - DropPanel.fn.show = function () { - let self = this; - let menu = self.menu; - if (!self.rendered) { - // 第一次show之前,先渲染 - self._render(); - } - - if (self.isShowing) { - return; - } - - let $panel = self.$panel; - $panel.show(); - - // 定位 - self._position(); - - // 记录状态 - self.isShowing = true; - - // 菜单状态 - menu.activeStyle(true); - - if (E.w3cRange) { - // 高级浏览器 - self.focusFirstInput(); - } else { - // 兼容 IE8 input placeholder - E.placeholderForIE8($panel); - } - }; - - // 隐藏 - DropPanel.fn.hide = function () { - let self = this; - let menu = self.menu; - if (!self.isShowing) { - return; - } - - let $panel = self.$panel; - $panel.hide(); - - // 记录状态 - self.isShowing = false; - - // 菜单状态 - menu.activeStyle(false); - }; - - }); -// modal 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let Modal = function (editor, menu, opt) { - this.editor = editor; - this.menu = menu; - this.$content = opt.$content; - - this.init(); - }; - - Modal.fn = Modal.prototype; - - // 暴露给 E - E.Modal = Modal; - }); -// modal fn bind - _e(function (E, $) { - - let Modal = E.Modal; - - Modal.fn.init = function () { - let self = this; - - // 初始化dom - self.initDom(); - - // 初始化隐藏事件 - self.initHideEvent(); - }; - - // 初始化dom - Modal.fn.initDom = function () { - let self = this; - let $content = self.$content; - let $modal = $('
'); - let $close = $('
'); - - $modal.append($close); - $modal.append($content); - - // 记录数据 - self.$modal = $modal; - self.$close = $close; - }; - - // 初始化隐藏事件 - Modal.fn.initHideEvent = function () { - let self = this; - let $close = self.$close; - let modal = self.$modal.get(0); - - // 点击 $close 按钮,隐藏 - $close.click(function () { - self.hide(); - }); - - // 点击其他部分,隐藏 - E.$body.on('click', function (e) { - if (!self.isShowing) { - return; - } - let trigger = e.target; - - // 获取菜单elem - let menu = self.menu; - let menuDom; - if (menu) { - if (menu.selected) { - menuDom = menu.$domSelected.get(0); - } else { - menuDom = menu.$domNormal.get(0); - } - - if (menuDom === trigger || $.contains(menuDom, trigger)) { - // 说明由本菜单点击触发的 - return; - } - } - - if (modal === trigger || $.contains(modal, trigger)) { - // 说明由本panel点击触发的 - return; - } - - // 其他情况,隐藏 panel - self.hide(); - }); - }; - }); -// modal fn api - _e(function (E, $) { - - let Modal = E.Modal; - - // 渲染 - Modal.fn._render = function () { - let self = this; - let editor = self.editor; - let $modal = self.$modal; - - // $modal的z-index,在配置的z-index基础上再 +10 - $modal.css('z-index', editor.config.zindex + 10 + ''); - - // 渲染到body最后面 - E.$body.append($modal); - - // 记录状态 - self.rendered = true; - }; - - // 定位 - Modal.fn._position = function () { - let self = this; - let $modal = self.$modal; - let top = $modal.offset().top; - let width = $modal.outerWidth(); - let height = $modal.outerHeight(); - let marginLeft = 0 - (width / 2); - let marginTop = 0 - (height / 2); - let sTop = E.$window.scrollTop(); - - // 保证modal最顶部,不超过浏览器上边框 - if ((height / 2) > top) { - marginTop = 0 - top; - } - - $modal.css({ - 'margin-left': marginLeft + 'px', - 'margin-top': (marginTop + sTop) + 'px' - }); - }; - - // 显示 - Modal.fn.show = function () { - let self = this; - let menu = self.menu; - if (!self.rendered) { - // 第一次show之前,先渲染 - self._render(); - } - - if (self.isShowing) { - return; - } - // 记录状态 - self.isShowing = true; - - let $modal = self.$modal; - $modal.show(); - - // 定位 - self._position(); - - // 激活菜单状态 - menu && menu.activeStyle(true); - }; - - // 隐藏 - Modal.fn.hide = function () { - let self = this; - let menu = self.menu; - if (!self.isShowing) { - return; - } - // 记录状态 - self.isShowing = false; - - // 隐藏 - let $modal = self.$modal; - $modal.hide(); - - // 菜单状态 - menu && menu.activeStyle(false); - }; - }); -// txt 构造函数 - _e(function (E, $) { - - // 定义构造函数 - let Txt = function (editor) { - this.editor = editor; - - // 初始化 - this.init(); - }; - - Txt.fn = Txt.prototype; - - // 暴露给 E - E.Txt = Txt; - }); -// Txt.fn bind fn - _e(function (E, $) { - - let Txt = E.Txt; - - // 初始化 - Txt.fn.init = function () { - let self = this; - let editor = self.editor; - let $valueContainer = editor.$valueContainer; - let currentValue = editor.getInitValue(); - let $txt; - - if ($valueContainer.get(0).nodeName === 'DIV') { - // 如果传入生成编辑器的元素就是div,则直接使用 - $txt = $valueContainer; - $txt.addClass("wangEditor-txt"); - $txt.attr('contentEditable', 'true'); - } else { - // 如果不是div(是textarea),则创建一个div - $txt = $( - '
' + - currentValue + - '
' - ); - } - - // 试图最后插入一个空行,ready之后才行 - editor.ready(function () { - self.insertEmptyP(); - }); - - self.$txt = $txt; - - // 删除时,如果没有内容了,就添加一个


- self.contentEmptyHandle(); - - // enter时,不能使用 div 换行 - self.bindEnterForDiv(); - - // enter时,用 p 包裹 text - self.bindEnterForText(); - - // tab 插入4个空格 - self.bindTabEvent(); - - // 处理粘贴内容 - self.bindPasteFilter(); - - // $txt.formatText() 方法 - self.bindFormatText(); - - // 定义 $txt.html() 方法 - self.bindHtml(); - }; - - // 删除时,如果没有内容了,就添加一个


- Txt.fn.contentEmptyHandle = function () { - let self = this; - let editor = self.editor; - let $txt = self.$txt; - let $p; - - $txt.on('keydown', function (e) { - if (e.keyCode !== 8) { - return; - } - let txtHtml = $.trim($txt.html().toLowerCase()); - if (txtHtml === '


') { - // 如果最后还剩余一个空行,就不再继续删除了 - e.preventDefault(); - return; - } - }); - - $txt.on('keyup', function (e) { - if (e.keyCode !== 8) { - return; - } - let txtHtml = $.trim($txt.html().toLowerCase()); - // ff时用 txtHtml === '
' 判断,其他用 !txtHtml 判断 - if (!txtHtml || txtHtml === '
') { - // 内容空了 - $p = $('


'); - $txt.html(''); // 一定要先清空,否则在 ff 下有问题 - $txt.append($p); - editor.restoreSelectionByElem($p.get(0)); - } - }); - }; - - // enter时,不能使用 div 换行 - Txt.fn.bindEnterForDiv = function () { - let tags = E.config.legalTags; // 配置中编辑器要求的合法标签,如 p head table blockquote ul ol 等 - let self = this; - let editor = self.editor; - let $txt = self.$txt; - - let $keydownDivElem; - - function divHandler() { - if (!$keydownDivElem) { - return; - } - - let $pElem = $('

' + $keydownDivElem.html() + '

'); - $keydownDivElem.after($pElem); - $keydownDivElem.remove(); - } - - $txt.on('keydown keyup', function (e) { - if (e.keyCode !== 13) { - return; - } - // 查找合法标签 - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getLegalTags(rangeElem); - let $targetElem; - let $pElem; - - if (!targetElem) { - // 没找到合法标签,就去查找 div - targetElem = editor.getSelfOrParentByName(rangeElem, 'div'); - if (!targetElem) { - return; - } - $targetElem = $(targetElem); - - if (e.type === 'keydown') { - // 异步执行(同步执行会出现问题) - $keydownDivElem = $targetElem; - setTimeout(divHandler, 0); - } - - if (e.type === 'keyup') { - // 将 div 的内容移动到 p 里面,并移除 div - $pElem = $('

' + $targetElem.html() + '

'); - $targetElem.after($pElem); - $targetElem.remove(); - - // 如果是回车结束,将选区定位到行首 - editor.restoreSelectionByElem($pElem.get(0), 'start'); - } - } - }); - }; - - // enter时,用 p 包裹 text - Txt.fn.bindEnterForText = function () { - let self = this; - let $txt = self.$txt; - let handle; - $txt.on('keyup', function (e) { - if (e.keyCode !== 13) { - return; - } - if (!handle) { - handle = function () { - self.wrapImgAndText(); - }; - } - setTimeout(handle); - }); - }; - - // tab 时,插入4个空格 - Txt.fn.bindTabEvent = function () { - let self = this; - let editor = self.editor; - let $txt = self.$txt; - - $txt.on('keydown', function (e) { - if (e.keyCode !== 9) { - // 只监听 tab 按钮 - return; - } - // 如果浏览器支持 insertHtml 则插入4个空格。如果不支持,就不管了 - if (editor.queryCommandSupported('insertHtml')) { - editor.command(e, 'insertHtml', '    '); - } - }); - }; - - // 处理粘贴内容 - Txt.fn.bindPasteFilter = function () { - let self = this; - let editor = self.editor; - let resultHtml = ''; //存储最终的结果 - let $txt = self.$txt; - let legalTags = editor.config.legalTags; - let legalTagArr = legalTags.split(','); - - $txt.on('paste', function (e) { - if (!editor.config.pasteFilter) { - // 配置中取消了粘贴过滤 - return; - } - - let currentNodeName = editor.getRangeElem().nodeName; - if (currentNodeName === 'TD' || currentNodeName === 'TH') { - // 在表格的单元格中粘贴,忽略所有内容。否则会出现异常情况 - return; - } - - resultHtml = ''; // 先清空 resultHtml - - let pasteHtml, $paste; - let data = e.clipboardData || e.originalEvent.clipboardData; - let ieData = window.clipboardData; - - if (editor.config.pasteText) { - // 只粘贴纯文本 - - if (data && data.getData) { - // w3c - pasteHtml = data.getData('text/plain'); - } else if (ieData && ieData.getData) { - // IE - pasteHtml = ieData.getData('text'); - } else { - // 其他情况 - return; - } - - // 拼接为

标签 - if (pasteHtml) { - resultHtml = '

' + pasteHtml + '

'; - } - - } else { - // 粘贴过滤了样式的、只有标签的 html - - if (data && data.getData) { - // w3c - - // 获取粘贴过来的html - pasteHtml = data.getData('text/html'); - if (pasteHtml) { - // 创建dom - $paste = $('
' + pasteHtml + '
'); - // 处理,并将结果存储到 resultHtml 『全局』变量 - handle($paste.get(0)); - } else { - // 得不到html,试图获取text - pasteHtml = data.getData('text/plain'); - if (pasteHtml) { - // 替换特殊字符 - pasteHtml = pasteHtml.replace(/[ ]/g, ' ') - .replace(//g, '>') - .replace(/\n/g, '

'); - // 拼接 - resultHtml = '

' + pasteHtml + '

'; - - // 查询链接 - resultHtml = resultHtml.replace(/

(https?:\/\/.*?)<\/p>/ig, function (match, link) { - return '

' + link + '

'; - }); - } - } - - } else if (ieData && ieData.getData) { - // IE 直接从剪切板中取出纯文本格式 - resultHtml = ieData.getData('text'); - if (!resultHtml) { - return; - } - // 拼接为

标签 - resultHtml = '

' + resultHtml + '

'; - resultHtml = resultHtml.replace(new RegExp('\n', 'g'), '

'); - } else { - // 其他情况 - return; - } - } - - // 执行命令 - if (resultHtml) { - editor.command(e, 'insertHtml', resultHtml); - - // 删除内容为空的 p 和嵌套的 p - self.clearEmptyOrNestP(); - } - }); - - // 处理粘贴的内容 - function handle(elem) { - if (!elem || !elem.nodeType || !elem.nodeName) { - return; - } - let $elem; - let nodeName = elem.nodeName.toLowerCase(); - let nodeType = elem.nodeType; - let childNodesClone; - - // 只处理文本和普通node标签 - if (nodeType !== 3 && nodeType !== 1) { - return; - } - - $elem = $(elem); - - // 如果是容器,则继续深度遍历 - if (nodeName === 'div') { - childNodesClone = []; - $.each(elem.childNodes, function (index, item) { - // elem.childNodes 可获取TEXT节点,而 $elem.children() 就获取不到 - // 先将 elem.childNodes 拷贝一份,一面在循环递归过程中 elem 发生变化 - childNodesClone.push(item); - }); - // 遍历子元素,执行操作 - $.each(childNodesClone, function () { - handle(this); - }); - return; - } - - if (legalTagArr.indexOf(nodeName) >= 0) { - // 如果是合法标签之内的,则根据元素类型,获取值 - resultHtml += getResult(elem); - } else if (nodeType === 3) { - // 如果是文本,则直接插入 p 标签 - resultHtml += '

' + elem.textContent + '

'; - } else if (nodeName === 'br') { - //
保留 - resultHtml += '
'; - } - else { - // 忽略的标签 - if (['meta', 'style', 'script', 'object', 'form', 'iframe', 'hr'].indexOf(nodeName) >= 0) { - return; - } - // 其他标签,移除属性,插入 p 标签 - $elem = $(removeAttrs(elem)); - // 注意,这里的 clone() 是必须的,否则会出错 - resultHtml += $('
').append($elem.clone()).html(); - } - } - - // 获取元素的结果 - function getResult(elem) { - let nodeName = elem.nodeName.toLowerCase(); - let $elem; - let htmlForP = ''; - let htmlForLi = ''; - - if (['blockquote'].indexOf(nodeName) >= 0) { - - // 直接取出元素text即可 - $elem = $(elem); - return '<' + nodeName + '>' + $elem.text() + ''; - - } else if (['p', 'h1', 'h2', 'h3', 'h4', 'h5'].indexOf(nodeName) >= 0) { - - //p head 取出 text 和链接 - elem = removeAttrs(elem); - $elem = $(elem); - htmlForP = $elem.html(); - - // 剔除 a img 之外的元素 - htmlForP = htmlForP.replace(/<.*?>/ig, function (tag) { - if (tag === '' || tag.indexOf('' + htmlForP + ''; - - } else if (['ul', 'ol'].indexOf(nodeName) >= 0) { - - // ul ol元素,获取子元素(li元素)的text link img,再拼接 - $elem = $(elem); - $elem.children().each(function () { - let $li = $(removeAttrs(this)); - let html = $li.html(); - - html = html.replace(/<.*?>/ig, function (tag) { - if (tag === '' || tag.indexOf(''; - }); - return '<' + nodeName + '>' + htmlForLi + ''; - - } else { - - // 其他元素,移除元素属性 - $elem = $(removeAttrs(elem)); - return $('
').append($elem).html(); - } - } - - // 移除一个元素(子元素)的attr - function removeAttrs(elem) { - let attrs = elem.attributes || []; - let attrNames = []; - let exception = ['href', 'target', 'src', 'alt', 'rowspan', 'colspan']; //例外情况 - - // 先存储下elem中所有 attr 的名称 - $.each(attrs, function (key, attr) { - if (attr && attr.nodeType === 2) { - attrNames.push(attr.nodeName); - } - }); - // 再根据名称删除所有attr - $.each(attrNames, function (key, attr) { - if (exception.indexOf(attr) < 0) { - // 除了 exception 规定的例外情况,删除其他属性 - elem.removeAttribute(attr); - } - }); - - - // 递归子节点 - let children = elem.childNodes; - if (children.length) { - $.each(children, function (key, value) { - removeAttrs(value); - }); - } - - return elem; - } - }; - - // 绑定 $txt.formatText() 方法 - Txt.fn.bindFormatText = function () { - let self = this; - let editor = self.editor; - let $txt = self.$txt; - let legalTags = E.config.legalTags; - let legalTagArr = legalTags.split(','); - let length = legalTagArr.length; - let regArr = []; - - // 将 E.config.legalTags 配置的有效字符,生成正则表达式 - $.each(legalTagArr, function (k, tag) { - let reg = '\>\\s*\<(' + tag + ')\>'; - regArr.push(new RegExp(reg, 'ig')); - }); - - // 增加 li - regArr.push(new RegExp('\>\\s*\<(li)\>', 'ig')); - - // 增加 tr - regArr.push(new RegExp('\>\\s*\<(tr)\>', 'ig')); - - // 增加 code - regArr.push(new RegExp('\>\\s*\<(code)\>', 'ig')); - - // 生成 formatText 方法 - $txt.formatText = function () { - let $temp = $('
'); - let html = $txt.html(); - - // 去除空格 - html = html.replace(/\s*\n<' + tag + '>'; - }); - }); - - $temp.html(html); - return $temp.text(); - }; - }; - - // 定制 $txt.html 方法 - Txt.fn.bindHtml = function () { - let self = this; - let editor = self.editor; - let $txt = self.$txt; - let $valueContainer = editor.$valueContainer; - let valueNodeName = editor.valueNodeName; - - $txt.html = function (html) { - let result; - - if (valueNodeName === 'div') { - // div 生成的编辑器,取值、赋值,都直接触发jquery的html方法 - result = $.fn.html.call($txt, html); - } - - // textarea 生成的编辑器,则需要考虑赋值时,也给textarea赋值 - - if (html === undefined) { - // 取值,直接触发jquery原生html方法 - result = $.fn.html.call($txt); - - // 替换 html 中,src和href属性中的 & 字符。 - // 因为 .html() 或者 .innerHTML 会把所有的 & 字符都改成 & 但是 src 和 href 中的要保持 & - result = result.replace(/(href|src)\=\"(.*)\"/igm, function (a, b, c) { - return b + '="' + c.replace('&', '&') + '"'; - }); - } else { - // 赋值,需要同时给 textarea 赋值 - result = $.fn.html.call($txt, html); - $valueContainer.val(html); - } - - if (html === undefined) { - return result; - } else { - // 手动触发 change 事件,因为 $txt 监控了 change 事件来判断是否需要执行 editor.onchange - $txt.change(); - } - }; - }; - }); -// Txt.fn api - _e(function (E, $) { - - let Txt = E.Txt; - - let txtChangeEventNames = 'propertychange change click keyup input paste'; - - // 渲染 - Txt.fn.render = function () { - let $txt = this.$txt; - let $editorContainer = this.editor.$editorContainer; - $editorContainer.append($txt); - }; - - // 计算高度 - Txt.fn.initHeight = function () { - let editor = this.editor; - let $txt = this.$txt; - let valueContainerHeight = editor.$valueContainer.height(); - let menuHeight = editor.menuContainer.height(); - let txtHeight = valueContainerHeight - menuHeight; - - // 限制最小为 50px - txtHeight = txtHeight < 50 ? 50 : txtHeight; - - $txt.height(txtHeight); - - // 记录原始高度 - editor.valueContainerHeight = valueContainerHeight; - - // 设置 max-height - this.initMaxHeight(txtHeight, menuHeight); - }; - - // 计算最大高度 - Txt.fn.initMaxHeight = function (txtHeight, menuHeight) { - let editor = this.editor; - let $menuContainer = editor.menuContainer.$menuContainer; - let $txt = this.$txt; - let $wrap = $('
'); - - // 需要浏览器支持 max-height,否则不管 - if (window.getComputedStyle && 'max-height' in window.getComputedStyle($txt.get(0))) { - // 获取 max-height 并判断是否有值 - let maxHeight = parseInt(editor.$valueContainer.css('max-height')); - if (isNaN(maxHeight)) { - return; - } - - // max-height 和『全屏』暂时有冲突 - if (editor.menus.fullscreen) { - E.warn('max-height和『全屏』菜单一起使用时,会有一些问题尚未解决,请暂时不要两个同时使用'); - return; - } - - // 标记 - editor.useMaxHeight = true; - - // 设置maxheight - $wrap.css({ - 'max-height': (maxHeight - menuHeight) + 'px', - 'overflow-y': 'auto' - }); - $txt.css({ - 'height': 'auto', - 'overflow-y': 'visible', - 'min-height': txtHeight + 'px' - }); - - // 滚动式,菜单阴影 - $wrap.on('scroll', function () { - if ($txt.parent().scrollTop() > 10) { - $menuContainer.addClass('wangEditor-menu-shadow'); - } else { - $menuContainer.removeClass('wangEditor-menu-shadow'); - } - }); - - // 需在编辑器区域外面再包裹一层 - $txt.wrap($wrap); - } - }; - - // 保存选区 - Txt.fn.saveSelectionEvent = function () { - let $txt = this.$txt; - let editor = this.editor; - let timeoutId; - let dt = Date.now(); - - function save() { - editor.saveSelection(); - } - - // 同步保存选区 - function saveSync() { - // 100ms之内,不重复保存 - if (Date.now() - dt < 100) { - return; - } - - dt = Date.now(); - save(); - } - - // 异步保存选区 - function saveAync() { - // 节流,防止高频率重复操作 - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(save, 300); - } - - // txt change 、focus、blur 时随时保存选区 - $txt.on(txtChangeEventNames + ' focus blur', function (e) { - // 先同步保存选区,为了让接下来就马上要执行 editor.getRangeElem() 的程序 - // 能够获取到正确的 rangeElem - saveSync(); - - // 再异步保存选区,为了确定更加准确的选区,为后续的操作做准备 - saveAync(); - }); - - // 鼠标拖拽选择时,可能会拖拽到编辑器区域外面再松手,此时 $txt 就监听不到 click事件了 - $txt.on('mousedown', function () { - $txt.on('mouseleave.saveSelection', function (e) { - // 先同步后异步,如上述注释 - saveSync(); - saveAync(); - - // 顺道吧菜单状态也更新了 - editor.updateMenuStyle(); - }); - }).on('mouseup', function () { - $txt.off('mouseleave.saveSelection'); - }); - - }; - - // 随时更新 value - Txt.fn.updateValueEvent = function () { - let $txt = this.$txt; - let editor = this.editor; - let timeoutId, oldValue; - - // 触发 onchange 事件 - function doOnchange() { - let val = $txt.html(); - if (oldValue === val) { - // 无变化 - return; - } - - // 触发 onchange 事件 - if (editor.onchange && typeof editor.onchange === 'function') { - editor.onchange.call(editor); - } - - // 更新内容 - editor.updateValue(); - - // 记录最新内容 - oldValue = val; - } - - // txt change 时随时更新内容 - $txt.on(txtChangeEventNames, function (e) { - // 初始化 - if (oldValue == null) { - oldValue = $txt.html(); - } - - // 监控内容变化(停止操作 100ms 之后立即执行) - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(doOnchange, 100); - }); - }; - - // 随时更新 menustyle - Txt.fn.updateMenuStyleEvent = function () { - let $txt = this.$txt; - let editor = this.editor; - - // txt change 时随时更新内容 - $txt.on(txtChangeEventNames, function (e) { - editor.updateMenuStyle(); - }); - }; - - // 最后插入试图插入


- Txt.fn.insertEmptyP = function () { - let $txt = this.$txt; - let $children = $txt.children(); - - if ($children.length === 0) { - $txt.append($('


')); - return; - } - - if ($.trim($children.last().html()).toLowerCase() !== '
') { - $txt.append($('


')); - } - }; - - // 将编辑器暴露出来的文字和图片,都用 p 来包裹 - Txt.fn.wrapImgAndText = function () { - let $txt = this.$txt; - let $imgs = $txt.children('img'); - let txt = $txt[0]; - let childNodes = txt.childNodes; - let childrenLength = childNodes.length; - let i, childNode, p; - - // 处理图片 - $imgs.length && $imgs.each(function () { - $(this).wrap('

'); - }); - - // 处理文字 - for (i = 0; i < childrenLength; i++) { - childNode = childNodes[i]; - if (childNode.nodeType === 3 && childNode.textContent && $.trim(childNode.textContent)) { - $(childNode).wrap('

'); - } - } - }; - - // 清空内容为空的

,以及重复包裹的

(在windows下的chrome粘贴文字之后,会出现上述情况) - Txt.fn.clearEmptyOrNestP = function () { - let $txt = this.$txt; - let $pList = $txt.find('p'); - - $pList.each(function () { - let $p = $(this); - let $children = $p.children(); - let childrenLength = $children.length; - let $firstChild; - let content = $.trim($p.html()); - - // 内容为空的p - if (!content) { - $p.remove(); - return; - } - - // 嵌套的p - if (childrenLength === 1) { - $firstChild = $children.first(); - if ($firstChild.get(0) && $firstChild.get(0).nodeName === 'P') { - $p.html($firstChild.html()); - } - } - }); - }; - - // 获取 scrollTop - Txt.fn.scrollTop = function (val) { - let self = this; - let editor = self.editor; - let $txt = self.$txt; - - if (editor.useMaxHeight) { - return $txt.parent().scrollTop(val); - } else { - return $txt.scrollTop(val); - } - }; - - // 鼠标hover时候,显示p、head的高度 - Txt.fn.showHeightOnHover = function () { - let editor = this.editor; - let $editorContainer = editor.$editorContainer; - let menuContainer = editor.menuContainer; - let $txt = this.$txt; - let $tip = $(''); - let isTipInTxt = false; - - function addAndShowTip($target) { - if (!isTipInTxt) { - $editorContainer.append($tip); - isTipInTxt = true; - } - - let txtTop = $txt.position().top; - let txtHeight = $txt.outerHeight(); - - let height = $target.height(); - let top = $target.position().top; - let marginTop = parseInt($target.css('margin-top'), 10); - let paddingTop = parseInt($target.css('padding-top'), 10); - let marginBottom = parseInt($target.css('margin-bottom'), 10); - let paddingBottom = parseInt($target.css('padding-bottom'), 10); - - // 计算初步的结果 - let resultHeight = height + paddingTop + marginTop + paddingBottom + marginBottom; - let resultTop = top + menuContainer.height(); - - // let spaceValue; - - // // 判断是否超出下边界 - // spaceValue = (resultTop + resultHeight) - (txtTop + txtHeight); - // if (spaceValue > 0) { - // resultHeight = resultHeight - spaceValue; - // } - - // // 判断是否超出了下边界 - // spaceValue = txtTop > resultTop; - // if (spaceValue) { - // resultHeight = resultHeight - spaceValue; - // top = top + spaceValue; - // } - - // 按照最终结果渲染 - $tip.css({ - height: height + paddingTop + marginTop + paddingBottom + marginBottom, - top: top + menuContainer.height() - }); - } - - function removeTip() { - if (!isTipInTxt) { - return; - } - $tip.remove(); - isTipInTxt = false; - } - - $txt.on('mouseenter', 'ul,ol,blockquote,p,h1,h2,h3,h4,h5,table,pre', function (e) { - addAndShowTip($(e.currentTarget)); - }).on('mouseleave', function () { - removeTip(); - }); - }; - - }); -// 工具函数 - _e(function (E, $) { - - // IE8 [].indexOf() - if (!Array.prototype.indexOf) { - //IE低版本不支持 arr.indexOf - Array.prototype.indexOf = function (elem) { - let i = 0, - length = this.length; - for (; i < length; i++) { - if (this[i] === elem) { - return i; - } - } - return -1; - }; - //IE低版本不支持 arr.lastIndexOf - Array.prototype.lastIndexOf = function (elem) { - let length = this.length; - for (length = length - 1; length >= 0; length--) { - if (this[length] === elem) { - return length; - } - } - return -1; - }; - } - - // IE8 Date.now() - if (!Date.now) { - Date.now = function () { - return new Date().valueOf(); - }; - } - - // console.knock && console.warn && console.error - let console = window.console; - let emptyFn = function () { - }; - $.each(['info', 'log', 'warn', 'error'], function (key, value) { - if (console == null) { - E[value] = emptyFn; - } else { - E[value] = function (info) { - // 通过配置来控制打印输出 - if (E.config && E.config.printLog) { - console[value]('wangEditor提示: ' + info); - } - }; - } - }); - - // 获取随机数 - E.random = function () { - return Math.random().toString().slice(2); - }; - - // 浏览器是否支持 placeholder - E.placeholder = 'placeholder' in document.createElement('input'); - - // 兼容IE8的 input placeholder - E.placeholderForIE8 = function ($container) { - if (E.placeholder) { - return; - } - $container.find('input[placeholder]').each(function () { - let $input = $(this); - let placeholder = $input.attr('placeholder'); - - if ($input.val() === '') { - $input.css('color', '#666'); - $input.val(placeholder); - - $input.on('focus.placeholder click.placeholder', function () { - $input.val(''); - $input.css('color', '#333'); - $input.off('focus.placeholder click.placeholder'); - }); - } - }); - }; - }); -// 语言包 - _e(function (E, $) { - E.langs = {}; - - // 中文 - E.langs['zh-cn'] = { - bold: '粗体', - underline: '下划线', - italic: '斜体', - forecolor: '文字颜色', - bgcolor: '背景色', - strikethrough: '删除线', - eraser: '清空格式', - source: '源码', - quote: '引用', - fontfamily: '字体', - fontsize: '字号', - head: '标题', - orderlist: '有序列表', - unorderlist: '无序列表', - alignleft: '左对齐', - aligncenter: '居中', - alignright: '右对齐', - link: '链接', - text: '文本', - submit: '提交', - cancel: '取消', - unlink: '取消链接', - table: '表格', - emotion: '表情', - img: '图片', - video: '视频', - 'width': '宽', - 'height': '高', - location: '位置', - loading: '加载中', - searchlocation: '搜索位置', - dynamicMap: '动态地图', - clearLocation: '清除位置', - langDynamicOneLocation: '动态地图只能显示一个位置', - insertcode: '插入代码', - undo: '撤销', - redo: '重复', - fullscreen: '全屏', - openLink: '打开链接' - }; - - // 英文 - E.langs.en = { - bold: 'Bold', - underline: 'Underline', - italic: 'Italic', - forecolor: 'Color', - bgcolor: 'Backcolor', - strikethrough: 'Strikethrough', - eraser: 'Eraser', - source: 'Codeview', - quote: 'Quote', - fontfamily: 'Font family', - fontsize: 'Font size', - head: 'Head', - orderlist: 'Ordered list', - unorderlist: 'Unordered list', - alignleft: 'Align left', - aligncenter: 'Align center', - alignright: 'Align right', - link: 'Insert link', - text: 'Text', - submit: 'Submit', - cancel: 'Cancel', - unlink: 'Unlink', - table: 'Table', - emotion: 'Emotions', - img: 'Image', - video: 'Video', - 'width': 'width', - 'height': 'height', - location: 'Location', - loading: 'Loading', - searchlocation: 'search', - dynamicMap: 'Dynamic', - clearLocation: 'Clear', - langDynamicOneLocation: 'Only one location in dynamic map', - insertcode: 'Insert Code', - undo: 'Undo', - redo: 'Redo', - fullscreen: 'Full screnn', - openLink: 'open link' - }; - }); -// 全局配置 - _e(function (E, $) { - - E.config = {}; - - // 全屏时的 z-index - E.config.zindex = 10000; - - // 是否打印log - E.config.printLog = true; - - // 菜单吸顶:false - 不吸顶;number - 吸顶,值为top值 - E.config.menuFixed = 0; - - // 编辑源码时,过滤 javascript - E.config.jsFilter = true; - - // 编辑器允许的标签 - E.config.legalTags = 'p,h1,h2,h3,h4,h5,h6,blockquote,table,ul,ol,pre'; - - // 语言包 - E.config.lang = E.langs['zh-cn']; - - // 菜单配置 - E.config.menus = [ - 'source', - '|', - 'bold', - 'underline', - 'italic', - 'strikethrough', - 'eraser', - 'forecolor', - 'bgcolor', - '|', - 'quote', - 'fontfamily', - 'fontsize', - 'head', - 'unorderlist', - 'orderlist', - 'alignleft', - 'aligncenter', - 'alignright', - '|', - 'link', - 'unlink', - 'table', - 'emotion', - '|', - 'img', - 'video', - 'location', - 'insertcode', - '|', - 'undo', - 'redo', - 'fullscreen' - ]; - - // 颜色配置 - E.config.colors = { - // 'value': 'title' - '#880000': '暗红色', - '#800080': '紫色', - '#ff0000': '红色', - '#ff00ff': '鲜粉色', - '#000080': '深蓝色', - '#0000ff': '蓝色', - '#00ffff': '湖蓝色', - '#008080': '蓝绿色', - '#008000': '绿色', - '#808000': '橄榄色', - '#00ff00': '浅绿色', - '#ffcc00': '橙黄色', - '#808080': '灰色', - '#c0c0c0': '银色', - '#000000': '黑色', - '#ffffff': '白色' - }; - - // 字体 - E.config.familys = [ - '宋体', '黑体', '楷体', '微软雅黑', - 'Arial', 'Verdana', 'Georgia', - 'Times New Roman', 'Microsoft JhengHei', - 'Trebuchet MS', 'Courier New', 'Impact', 'Comic Sans MS', 'Consolas' - ]; - - // 字号 - E.config.fontsizes = { - // 格式:'value': 'title' - 1: '12px', - 2: '13px', - 3: '16px', - 4: '18px', - 5: '24px', - 6: '32px', - 7: '48px' - }; - - // 表情包 - E.config.emotionsShow = 'icon'; // 显示项,默认为'icon',也可以配置成'value' - E.config.emotions = { - // 'default': { - // title: '默认', - // data: './emotions.data' - // }, - 'weibo': { - title: '微博表情', - data: [ - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/7a/shenshou_thumb.gif', - value: '[草泥马]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/60/horse2_thumb.gif', - value: '[神马]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/fuyun_thumb.gif', - value: '[浮云]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c9/geili_thumb.gif', - value: '[给力]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/f2/wg_thumb.gif', - value: '[围观]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/70/vw_thumb.gif', - value: '[威武]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/6e/panda_thumb.gif', - value: '[熊猫]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/81/rabbit_thumb.gif', - value: '[兔子]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/otm_thumb.gif', - value: '[奥特曼]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/15/j_thumb.gif', - value: '[囧]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/89/hufen_thumb.gif', - value: '[互粉]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c4/liwu_thumb.gif', - value: '[礼物]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/ac/smilea_thumb.gif', - value: '[呵呵]' - }, - { - icon: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/0b/tootha_thumb.gif', - value: '[哈哈]' - } - ] - } - }; - - // 百度地图的key - E.config.mapAk = 'TVhjYjq1ICT2qqL5LdS8mwas'; - - // 上传图片的配置 - // server地址 - E.config.uploadImgUrl = ''; - // 超时时间 - E.config.uploadTimeout = 20 * 1000; - // 用于存储上传回调事件 - E.config.uploadImgFns = {}; - // 自定义上传图片的filename - // E.config.uploadImgFileName = 'customFileName'; - - // 自定义上传,设置为 true 之后,显示上传图标 - E.config.customUpload = false; - // 自定义上传的init事件 - // E.config.customUploadInit = function () {....}; - - // 自定义上传时传递的参数(如 token) - E.config.uploadParams = { - /* token: 'abcdef12345' */ - }; - - // 自定义上传是的header参数 - E.config.uploadHeaders = { - /* 'Accept' : 'text/x-json' */ - }; - - // 隐藏网络图片,默认为 false - E.config.hideLinkImg = false; - - // 是否过滤粘贴内容 - E.config.pasteFilter = true; - - // 是否粘贴纯文本,当 editor.config.pasteFilter === false 时候,此配置将失效 - E.config.pasteText = false; - - // 插入代码时,默认的语言 - E.config.codeDefaultLang = 'javascript'; - - }); -// 全局UI - _e(function (E, $) { - - E.UI = {}; - - // 为菜单自定义配置的UI - E.UI.menus = { - // 这个 default 不加引号,在 IE8 会报错 - 'default': { - normal: '', - selected: '.selected' - }, - bold: { - normal: '', - selected: '.selected' - }, - underline: { - normal: '', - selected: '.selected' - }, - italic: { - normal: '', - selected: '.selected' - }, - forecolor: { - normal: '', - selected: '.selected' - }, - bgcolor: { - normal: '', - selected: '.selected' - }, - strikethrough: { - normal: '', - selected: '.selected' - }, - eraser: { - normal: '', - selected: '.selected' - }, - quote: { - normal: '', - selected: '.selected' - }, - source: { - normal: '', - selected: '.selected' - }, - fontfamily: { - normal: '', - selected: '.selected' - }, - fontsize: { - normal: '', - selected: '.selected' - }, - head: { - normal: '', - selected: '.selected' - }, - orderlist: { - normal: '', - selected: '.selected' - }, - unorderlist: { - normal: '', - selected: '.selected' - }, - alignleft: { - normal: '', - selected: '.selected' - }, - aligncenter: { - normal: '', - selected: '.selected' - }, - alignright: { - normal: '', - selected: '.selected' - }, - link: { - normal: '', - selected: '.selected' - }, - unlink: { - normal: '', - selected: '.selected' - }, - table: { - normal: '', - selected: '.selected' - }, - emotion: { - normal: '', - selected: '.selected' - }, - img: { - normal: '', - selected: '.selected' - }, - video: { - normal: '', - selected: '.selected' - }, - location: { - normal: '', - selected: '.selected' - }, - insertcode: { - normal: '', - selected: '.selected' - }, - undo: { - normal: '', - selected: '.selected' - }, - redo: { - normal: '', - selected: '.selected' - }, - fullscreen: { - normal: '', - selected: '' - } - }; - - }); -// 对象配置 - _e(function (E, $) { - - E.fn.initDefaultConfig = function () { - let editor = this; - editor.config = $.extend({}, E.config); - editor.UI = $.extend({}, E.UI); - }; - - }); -// 增加 container - _e(function (E, $) { - - E.fn.addEditorContainer = function () { - this.$editorContainer = $('

'); - }; - - }); -// 增加编辑区域对象 - _e(function (E, $) { - - E.fn.addTxt = function () { - let editor = this; - let txt = new E.Txt(editor); - - editor.txt = txt; - }; - - }); -// 增加menuContainer对象 - _e(function (E, $) { - - E.fn.addMenuContainer = function () { - let editor = this; - editor.menuContainer = new E.MenuContainer(editor); - }; - - }); -// 增加menus - _e(function (E, $) { - - // 存储创建菜单的函数 - E.createMenuFns = []; - E.createMenu = function (fn) { - E.createMenuFns.push(fn); - }; - - // 创建所有菜单 - E.fn.addMenus = function () { - let editor = this; - let menuIds = editor.config.menus; - - // 检验 menuId 是否在配置中存在 - function check(menuId) { - if (menuIds.indexOf(menuId) >= 0) { - return true; - } - return false; - } - - // 遍历所有的菜单创建函数,并执行 - $.each(E.createMenuFns, function (k, createMenuFn) { - createMenuFn.call(editor, check); - }); - }; - - }); -// bold菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'bold'; - if (!check(menuId)) { - return; - } - - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.bold, - commandName: 'Bold' - }); - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 如果选区有内容,则执行基础命令 - editor.command(e, 'Bold'); - } else { - // 如果选区没有内容 - editor.commandForElem('b,strong,h1,h2,h3,h4,h5', e, 'Bold'); - } - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// underline菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'underline'; - if (!check(menuId)) { - return; - } - - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.underline, - commandName: 'Underline' - }); - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 如果选区有内容,则执行基础命令 - editor.command(e, 'Underline'); - } else { - // 如果选区没有内容 - editor.commandForElem('u,a', e, 'Underline'); - } - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// italic 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'italic'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.italic, - commandName: 'Italic' - }); - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 如果选区有内容,则执行基础命令 - editor.command(e, 'Italic'); - } else { - // 如果选区没有内容 - editor.commandForElem('i', e, 'Italic'); - } - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// forecolor 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'forecolor'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let configColors = editor.config.colors; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.forecolor - }); - - // 创建 dropPanel - let $content = $('
'); - $.each(configColors, function (k, v) { - $content.append( - [ - '' - ].join('') - ); - }); - $content.on('click', 'a[commandValue]', function (e) { - // 执行命令 - let $elem = $(this); - let commandValue = $elem.attr('commandValue'); - - if (menu.selected && editor.isRangeEmpty()) { - // 当前处于选中状态,并且选中内容为空 - editor.commandForElem('font[color]', e, 'forecolor', commandValue); - } else { - // 当前未处于选中状态,或者有选中内容。则执行默认命令 - editor.command(e, 'forecolor', commandValue); - } - }); - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 125 - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'font[color]'); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// bgcolor 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'bgcolor'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let configColors = editor.config.colors; - - // 检查元素是否有 background-color: 内联样式 - function checkElemFn(elem) { - let cssText; - if (elem && elem.style && elem.style.cssText != null) { - cssText = elem.style.cssText; - if (cssText && cssText.indexOf('background-color:') >= 0) { - return true; - } - } - return false; - } - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.bgcolor - }); - - // 创建 dropPanel - let $content = $('
'); - $.each(configColors, function (k, v) { - $content.append( - [ - '' - ].join('') - ); - }); - $content.on('click', 'a[commandValue]', function (e) { - // 执行命令 - - let $elem = $(this); - let commandValue = $elem.attr('commandValue'); - - if (menu.selected && editor.isRangeEmpty()) { - // 当前处于选中状态,并且选中内容为空。使用 commandForElem 执行命令 - editor.commandForElem({ - selector: 'span,font', - check: checkElemFn - }, e, 'BackColor', commandValue); - } else { - // 当前未处于选中状态,或者有选中内容。则执行默认命令 - editor.command(e, 'BackColor', commandValue); - } - }); - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 125 - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'span,font', checkElemFn); - - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// strikethrough 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'strikethrough'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.strikethrough, - commandName: 'StrikeThrough' - }); - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 如果选区有内容,则执行基础命令 - editor.command(e, 'StrikeThrough'); - } else { - // 如果选区没有内容 - editor.commandForElem('strike', e, 'StrikeThrough'); - } - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// eraser 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'eraser'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.eraser, - commandName: 'RemoveFormat' - }); - - // 定义点击事件 - menu.clickEvent = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - - if (!isRangeEmpty) { - // 选区不是空的,则执行默认命令 - editor.command(e, 'RemoveFormat'); - return; - } - - let $clearElem; - - // 自定义的命令函数 - function commandFn() { - let editor = this; - let rangeElem; - let pElem, $pElem; - let quoteElem, $quoteElem; - let listElem, $listElem; - - // 获取选区 elem - rangeElem = editor.getRangeElem(); - // 第一步,获取 quote 父元素 - quoteElem = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - if (quoteElem) { - $quoteElem = $(quoteElem); - $clearElem = $('

' + $quoteElem.text() + '

'); - $quoteElem.after($clearElem).remove(); - } - // 第二步,获取 p h 父元素 - pElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5'); - if (pElem) { - $pElem = $(pElem); - $clearElem = $('

' + $pElem.text() + '

'); - $pElem.after($clearElem).remove(); - } - // 第三步,获取list - listElem = editor.getSelfOrParentByName(rangeElem, 'ul,ol'); - if (listElem) { - $listElem = $(listElem); - $clearElem = $('

' + $listElem.text() + '

'); - $listElem.after($clearElem).remove(); - } - } - - // 自定义 callback 事件 - function callback() { - // callback中,设置range为clearElem - let editor = this; - if ($clearElem) { - editor.restoreSelectionByElem($clearElem.get(0)); - } - } - - // 执行自定义命令 - editor.customCommand(e, commandFn, callback); - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// source 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'source'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let txtHtml; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.source - }); - - menu.isShowCode = false; - - // 更新内容 - function updateValue() { - let $code = menu.$codeTextarea; - let $txt = editor.txt.$txt; - let value = $.trim($code.val()); // 取值 - - if (!value) { - value = '


'; - } - - // 过滤js代码 - if (editor.config.jsFilter) { - - value = value.replace(//ig, ''); - } - // 赋值 - try { - $txt.html(value); - } catch (ex) { - // 更新 html 源码出错,一般都是取消了 js 过滤之后,js报错导致的 - } - } - - // 定义click事件 - menu.clickEvent = function (e) { - let self = this; - let editor = self.editor; - let $txt = editor.txt.$txt; - let txtOuterHeight = $txt.outerHeight(); - let txtHeight = $txt.height(); - - if (!self.$codeTextarea) { - self.$codeTextarea = $(''); - } - let $code = self.$codeTextarea; - $code.css({ - height: txtHeight, - 'margin-top': txtOuterHeight - txtHeight - }); - - // 赋值 - $code.val($txt.html()); - - // 监控变化 - $code.on('change', function (e) { - updateValue(); - }); - - // 渲染 - $txt.after($code).hide(); - $code.show(); - - // 更新状态 - menu.isShowCode = true; - - // 执行 updateSelected 事件 - this.updateSelected(); - - // 禁用其他菜单 - editor.disableMenusExcept('source'); - - // 记录当前html值 - txtHtml = $txt.html(); - }; - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let self = this; - let editor = self.editor; - let $txt = editor.txt.$txt; - let $code = self.$codeTextarea; - let value; - - if (!$code) { - return; - } - - // 更新内容 - updateValue(); - - // 渲染 - $code.after($txt).hide(); - $txt.show(); - - // 更新状态 - menu.isShowCode = false; - - // 执行 updateSelected 事件 - this.updateSelected(); - - // 启用其他菜单 - editor.enableMenusExcept('source'); - - // 判断是否执行 onchange 事件 - if ($txt.html() !== txtHtml) { - if (editor.onchange && typeof editor.onchange === 'function') { - editor.onchange.call(editor); - } - } - }; - - // 定义切换选中状态事件 - menu.updateSelectedEvent = function () { - return this.isShowCode; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// quote 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'quote'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.quote, - commandName: 'formatBlock', - commandValue: 'blockquote' - }); - - // 定义click事件 - menu.clickEvent = function (e) { - let rangeElem = editor.getRangeElem(); - let $rangeElem; - if (!rangeElem) { - e.preventDefault(); - return; - } - let currentQuote = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - let $quote; - - if (currentQuote) { - // 说明当前在quote之内,不做任何处理 - e.preventDefault(); - return; - } - - rangeElem = editor.getLegalTags(rangeElem); - $rangeElem = $(rangeElem); - - // 无文字,则不允许执行引用 - if (!$rangeElem.text()) { - return; - } - - - if (!rangeElem) { - // 执行默认命令 - // IE8 下执行此处(不过,经测试代码无效,也不报错) - editor.command(e, 'formatBlock', 'blockquote'); - return; - } - - // 自定义command事件 - function commandFn() { - $quote = $('

' + $rangeElem.text() + '

'); - $rangeElem.after($quote).remove(); - $quote.wrap('
'); - } - - // 自定义 callback 事件 - function callback() { - // callback中,设置range为quote - let editor = this; - if ($quote) { - editor.restoreSelectionByElem($quote.get(0)); - } - } - - // 执行自定义命令 - editor.customCommand(e, commandFn, callback); - }; - - // 定义选中状态下的click事件 - menu.clickEventSelected = function (e) { - let rangeElem; - let quoteElem; - let $lastChild; - - // 获取当前选区的elem,并试图往上找 quote 元素 - rangeElem = editor.getRangeElem(); - quoteElem = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - if (!quoteElem) { - // 没找到,则返回 - e.preventDefault(); - return; - } - - // 自定义的command事件 - function commandFn() { - let $quoteElem; - let $children; - - $quoteElem = $(quoteElem); - $children = $quoteElem.children(); - if ($children.length) { - $children.each(function (k) { - let $item = $(this); - if ($item.get(0).nodeName === 'P') { - $quoteElem.after($item); - } else { - $quoteElem.after('

' + $item.text() + '

'); - } - $lastChild = $item; // 记录最后一个子元素,用于callback中的range定位 - }); - $quoteElem.remove(); - return; - } - } - - // 自定义的callback函数 - function callback() { - // callback中,设置range为lastChild - let editor = this; - if ($lastChild) { - editor.restoreSelectionByElem($lastChild.get(0)); - } - } - - // 执行自定义命令 - editor.customCommand(e, commandFn, callback); - }; - - // 定义更新选中状态的事件 - menu.updateSelectedEvent = function () { - let self = this; //菜单对象 - let editor = self.editor; - let rangeElem; - - rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - - if (rangeElem) { - return true; - } - - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - - // --------------- 两次点击 enter 跳出引用 --------------- - editor.ready(function () { - let editor = this; - let $txt = editor.txt.$txt; - let isPrevEnter = false; // 是不是刚刚在quote中按了 enter 键 - $txt.on('keydown', function (e) { - if (e.keyCode !== 13) { - // 不是 enter 键 - isPrevEnter = false; - return; - } - - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - if (!rangeElem) { - // 选区不是 quote - isPrevEnter = false; - return; - } - - if (!isPrevEnter) { - // 最近没有在qote中按enter键 - isPrevEnter = true; - return; - } - - let currentRangeElem = editor.getRangeElem(); - let $currentRangeElem = $(currentRangeElem); - if ($currentRangeElem.length) { - $currentRangeElem.parent().after($currentRangeElem); - } - - // 设置选区 - editor.restoreSelectionByElem(currentRangeElem, 'start'); - - isPrevEnter = false; - // 阻止默认行文 - e.preventDefault(); - - }); - }); // editor.ready( - - // --------------- 处理quote中无内容时不能删除的问题 --------------- - editor.ready(function () { - let editor = this; - let $txt = editor.txt.$txt; - let $rangeElem; - - function commandFn() { - $rangeElem && $rangeElem.remove(); - } - - function callback() { - if (!$rangeElem) { - return; - } - let $prev = $rangeElem.prev(); - if ($prev.length) { - // 有 prev 则定位到 prev 最后 - editor.restoreSelectionByElem($prev.get(0)); - } else { - // 无 prev 则初始化选区 - editor.initSelection(); - } - } - - $txt.on('keydown', function (e) { - if (e.keyCode !== 8) { - // 不是 backspace 键 - return; - } - - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'blockquote'); - if (!rangeElem) { - // 选区不是 quote - return; - } - $rangeElem = $(rangeElem); - - let text = $rangeElem.text(); - if (text) { - // quote 中还有内容 - return; - } - editor.customCommand(e, commandFn, callback); - - }); // $txt.on - }); // editor.ready( - }); - - }); -// 字体 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'fontfamily'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let configFamilys = editor.config.familys; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.fontfamily, - commandName: 'fontName' - }); - - // 初始化数据 - let data = {}; - /* - data 需要的结构 - { - 'commandValue': 'title' - ... - } - */ - $.each(configFamilys, function (k, v) { - // configFamilys 是数组,data 是对象 - data[v] = v; - }); - - // 创建droplist - let tpl = '{#title}'; - menu.dropList = new E.DropList(editor, menu, { - data: data, - tpl: tpl, - selectorForELemCommand: 'font[face]' // 为了执行 editor.commandForElem 而传入的elem查询方式 - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'font[face]'); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - }); -// 字号 菜单 - _e(function (E, $) { - E.createMenu(function (check) { - let menuId = 'fontsize'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let configSize = editor.config.fontsizes; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.fontsize, - commandName: 'fontSize' - }); - - // 初始化数据 - let data = configSize; - /* - data 需要的结构 - { - 'commandValue': 'title' - ... - } - */ - - // 创建droplist - let tpl = '{#title}'; - menu.dropList = new E.DropList(editor, menu, { - data: data, - tpl: tpl, - selectorForELemCommand: 'font[size]' // 为了执行 editor.commandForElem 而传入的elem查询方式 - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'font[size]'); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - }); -// head 菜单 - _e(function (E, $) { - E.createMenu(function (check) { - let menuId = 'head'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.head, - commandName: 'formatBlock' - }); - - // 初始化数据 - let data = { - '

': '标题1', - '

': '标题2', - '

': '标题3', - '

': '标题4', - '

': '标题5' - }; - /* - data 需要的结构 - { - 'commandValue': 'title' - ... - } - */ - - let isOrderedList; - - function beforeEvent(e) { - if (editor.queryCommandState('InsertOrderedList')) { - isOrderedList = true; - - // 先取消有序列表 - editor.command(e, 'InsertOrderedList'); - } else { - isOrderedList = false; - } - } - - function afterEvent(e) { - if (isOrderedList) { - // 再设置有序列表 - editor.command(e, 'InsertOrderedList'); - } - } - - // 创建droplist - let tpl = '{#commandValue}{#title}'; - menu.dropList = new E.DropList(editor, menu, { - data: data, - tpl: tpl, - // 对 ol 直接设置 head,会出现每个 li 的 index 都变成 1 的问题,因此要先取消 ol,然后设置 head,最后再增加上 ol - beforeEvent: beforeEvent, - afterEvent: afterEvent - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'h1,h2,h3,h4,h5'); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - }); -// unorderlist 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'unorderlist'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.unorderlist, - commandName: 'InsertUnorderedList' - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// orderlist 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'orderlist'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.orderlist, - commandName: 'InsertOrderedList' - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// alignleft 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'alignleft'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.alignleft, - commandName: 'JustifyLeft' - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) { - let cssText; - if (elem && elem.style && elem.style.cssText != null) { - cssText = elem.style.cssText; - if (cssText && /text-align:\s*left;/.test(cssText)) { - return true; - } - } - if ($(elem).attr('align') === 'left') { - // ff 中,设置align-left之后,会是

xxx

- return true; - } - return false; - }); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// aligncenter 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'aligncenter'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.aligncenter, - commandName: 'JustifyCenter' - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) { - let cssText; - if (elem && elem.style && elem.style.cssText != null) { - cssText = elem.style.cssText; - if (cssText && /text-align:\s*center;/.test(cssText)) { - return true; - } - } - if ($(elem).attr('align') === 'center') { - // ff 中,设置align-center之后,会是

xxx

- return true; - } - return false; - }); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// alignright 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'alignright'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.alignright, - commandName: 'JustifyRight' - }); - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) { - let cssText; - if (elem && elem.style && elem.style.cssText != null) { - cssText = elem.style.cssText; - if (cssText && /text-align:\s*right;/.test(cssText)) { - return true; - } - } - if ($(elem).attr('align') === 'right') { - // ff 中,设置align-right之后,会是

xxx

- return true; - } - return false; - }); - if (rangeElem) { - return true; - } - return false; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// link 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'link'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.link - }); - - // 创建 dropPanel - let $content = $('
'); - let $div1 = $('
'); - let $div2 = $div1.clone(); - let $div3 = $div1.clone().css('margin', '0 10px'); - let $textInput = $(''); - let $urlInput = $(''); - let $btnSubmit = $(''); - let $btnCancel = $(''); - - $div1.append($textInput); - $div2.append($urlInput); - $div3.append($btnSubmit).append($btnCancel); - $content.append($div1).append($div2).append($div3); - - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 300 - }); - - // 定义click事件 - menu.clickEvent = function (e) { - let menu = this; - let dropPanel = menu.dropPanel; - - // -------------隐藏---------------- - if (dropPanel.isShowing) { - dropPanel.hide(); - return; - } - - // -------------显示---------------- - - // 重置 input - $textInput.val(''); - $urlInput.val('http://'); - - // 获取url - let url = ''; - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'a'); - if (rangeElem) { - url = rangeElem.href || ''; - } - - // 获取 text - let text = ''; - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 选区不是空 - text = editor.getRangeText() || ''; - } else if (rangeElem) { - // 如果选区空,并且在 a 标签之内 - text = rangeElem.textContent || rangeElem.innerHTML; - } - - // 设置 url 和 text - url && $urlInput.val(url); - text && $textInput.val(text); - - // 如果有选区内容,textinput 不能修改 - if (!isRangeEmpty) { - $textInput.attr('disabled', true); - } else { - $textInput.removeAttr('disabled'); - } - - // 显示(要设置好了所有input的值和属性之后再显示) - dropPanel.show(); - }; - - // 定义 update selected 事件 - menu.updateSelectedEvent = function () { - let rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'a'); - if (rangeElem) { - return true; - } - return false; - }; - - // 『取消』 按钮 - $btnCancel.click(function (e) { - e.preventDefault(); - menu.dropPanel.hide(); - }); - - // 『确定』按钮 - $btnSubmit.click(function (e) { - e.preventDefault(); - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getSelfOrParentByName(rangeElem, 'a'); - let isRangeEmpty = editor.isRangeEmpty(); - - let $linkElem, linkHtml; - let commandFn, callback; - let $txt = editor.txt.$txt; - let $oldLinks, $newLinks; - let uniqId = 'link' + E.random(); - - // 获取数据 - let url = $.trim($urlInput.val()); - let text = $.trim($textInput.val()); - - if (!url) { - menu.dropPanel.focusFirstInput(); - return; - } - if (!text) { - text = url; - } - - if (!isRangeEmpty) { - // 选中区域有内容,则执行默认命令 - - // 获取目前 txt 内所有链接,并为当前链接做一个标记 - $oldLinks = $txt.find('a'); - $oldLinks.attr(uniqId, '1'); - - // 执行命令 - editor.command(e, 'createLink', url); - - // 去的没有标记的链接,即刚刚插入的链接 - $newLinks = $txt.find('a').not('[' + uniqId + ']'); - $newLinks.attr('target', '_blank'); // 增加 _blank - - // 去掉之前做的标记 - $oldLinks.removeAttr(uniqId); - - } else if (targetElem) { - // 无选中区域,在 a 标签之内,修改该 a 标签的内容和链接 - $linkElem = $(targetElem); - commandFn = function () { - $linkElem.attr('href', url); - $linkElem.text(text); - }; - callback = function () { - let editor = this; - editor.restoreSelectionByElem(targetElem); - }; - // 执行命令 - editor.customCommand(e, commandFn, callback); - } else { - // 无选中区域,不在 a 标签之内,插入新的链接 - - linkHtml = '' + text + ''; - if (E.userAgent.indexOf('Firefox') > 0) { - linkHtml += ' '; - } - editor.command(e, 'insertHtml', linkHtml); - } - - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// unlink 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'unlink'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.unlink, - commandName: 'unLink' - }); - - // click 事件 - menu.clickEvent = function (e) { - let isRangeEmpty = editor.isRangeEmpty(); - if (!isRangeEmpty) { - // 有选中区域,或者IE8,执行默认命令 - editor.command(e, 'unLink'); - return; - } - - // 无选中区域... - - let rangeElem = editor.getRangeElem(); - let aElem = editor.getSelfOrParentByName(rangeElem, 'a'); - if (!aElem) { - // 不在 a 之内,返回 - e.preventDefault(); - return; - } - - // 在 a 之内 - let $a = $(aElem); - let $span = $('' + $a.text() + ''); - - function commandFn() { - $a.after($span).remove(); - } - - function callback() { - editor.restoreSelectionByElem($span.get(0)); - } - - editor.customCommand(e, commandFn, callback); - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// table 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'table'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.table - }); - - // dropPanel 内容 - let $content = $('
'); - let $table = $(''); - let $row = $('0'); - let $rowspan = $(''); - let $col = $('0'); - let $colspan = $(''); - let $tr; - let i, j; - - // 创建一个n行n列的表格 - for (i = 0; i < 15; i++) { - $tr = $(''); - for (j = 0; j < 20; j++) { - $tr.append($('
')); - } - $table.append($tr); - } - $content.append($table); - $content.append($row).append($rowspan).append($col).append($colspan); - - // 定义table事件 - $table.on('mouseenter', 'td', function (e) { - let $currentTd = $(e.currentTarget); - let currentTdIndex = $currentTd.attr('index'); - let $currentTr = $currentTd.parent(); - let currentTrIndex = $currentTr.attr('index'); - - // 显示 - $row.text(currentTrIndex); - $col.text(currentTdIndex); - - // 遍历设置背景颜色 - $table.find('tr').each(function () { - let $tr = $(this); - let trIndex = $tr.attr('index'); - if (parseInt(trIndex, 10) <= parseInt(currentTrIndex, 10)) { - // 该行需要可能需要设置背景色 - $tr.find('td').each(function () { - let $td = $(this); - let tdIndex = $td.attr('index'); - if (parseInt(tdIndex, 10) <= parseInt(currentTdIndex, 10)) { - // 需要设置背景色 - $td.addClass('active'); - } else { - // 需要移除背景色 - $td.removeClass('active'); - } - }); - } else { - // 改行不需要设置背景色 - $tr.find('td').removeClass('active'); - } - }); - }).on('mouseleave', function (e) { - // mouseleave 删除背景色 - $table.find('td').removeClass('active'); - - $row.text(0); - $col.text(0); - }); - - // 插入表格 - $table.on('click', 'td', function (e) { - let $currentTd = $(e.currentTarget); - let currentTdIndex = $currentTd.attr('index'); - let $currentTr = $currentTd.parent(); - let currentTrIndex = $currentTr.attr('index'); - - let rownum = parseInt(currentTrIndex, 10); - let colnum = parseInt(currentTdIndex, 10); - - // -------- 拼接tabel html -------- - - let i, j; - let tableHtml = ''; - for (i = 0; i < rownum; i++) { - tableHtml += ''; - - for (j = 0; j < colnum; j++) { - tableHtml += ''; - } - tableHtml += ''; - } - tableHtml += '
 
'; - - // -------- 执行命令 -------- - editor.command(e, 'insertHtml', tableHtml); - }); - - // 创建 panel - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 262 - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// emotion 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'emotion'; - if (!check(menuId)) { - return; - } - let editor = this; - let config = editor.config; - let lang = config.lang; - let configEmotions = config.emotions; - let emotionsShow = config.emotionsShow; - - // 记录每一个表情图片的地址 - editor.emotionUrls = []; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.emotion - }); - - // 添加表情图片的函数 - function insertEmotionImgs(data, $tabContent) { - // 添加表情图片 - $.each(data, function (k, emotion) { - let src = emotion.icon || emotion.url; - let value = emotion.value || emotion.title; - // 通过配置 editor.config.emotionsShow 的值来修改插入到编辑器的内容(图片/value) - let commandValue = emotionsShow === 'icon' ? src : value; - let $command = $(''); - let $img = $(''); - $img.attr('_src', src); // 先将 src 复制到 '_src' 属性,先不加载 - - $command.append($img); - $tabContent.append($command); - - // 记录下每一个表情图片的地址 - editor.emotionUrls.push(src); - }); - } - - // 拼接 dropPanel 内容 - let $panelContent = $('
'); - let $tabContainer = $('
'); - let $contentContainer = $('
'); - $.each(configEmotions, function (k, emotion) { - let title = emotion.title; - let data = emotion.data; - - E.log('正在处理 ' + title + ' 表情的数据...'); - - // 增加该组表情的tab和content - let $tab = $('' + title + ' '); - $tabContainer.append($tab); - let $tabContent = $('
'); - $contentContainer.append($tabContent); - - // tab 切换事件 - $tab.click(function (e) { - $tabContainer.children().removeClass('selected'); - $contentContainer.children().removeClass('selected'); - $tabContent.addClass('selected'); - $tab.addClass('selected'); - e.preventDefault(); - }); - - // 处理data - if (typeof data === 'string') { - // url 形式,需要通过ajax从该url获取数据 - E.log('将通过 ' + data + ' 地址ajax下载表情包'); - $.get(data, function (result) { - result = $.parseJSON(result); - E.log('下载完毕,得到 ' + result.length + ' 个表情'); - insertEmotionImgs(result, $tabContent); - }); - - } else if (Object.prototype.toString.call(data).toLowerCase().indexOf('array') > 0) { - // 数组,即 data 直接就是表情包数据 - insertEmotionImgs(data, $tabContent); - } else { - // 其他情况,data格式不对 - E.error('data 数据格式错误,请修改为正确格式,参考文档:' + E.docsite); - return; - } - }); - $panelContent.append($tabContainer).append($contentContainer); - - // 默认显示第一个tab - $tabContainer.children().first().addClass('selected'); - $contentContainer.children().first().addClass('selected'); - - // 插入表情command事件 - $contentContainer.on('click', 'a[commandValue]', function (e) { - let $a = $(e.currentTarget); - let commandValue = $a.attr('commandValue'); - let img; - - // commandValue 有可能是图片url,也有可能是表情的 value,需要区别对待 - - if (emotionsShow === 'icon') { - // 插入图片 - editor.command(e, 'InsertImage', commandValue); - } else { - // 插入value - editor.command(e, 'insertHtml', '' + commandValue + ''); - } - - e.preventDefault(); - }); - - // 添加panel - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $panelContent, - width: 350 - }); - - // 定义click事件(异步加载表情图片) - menu.clickEvent = function (e) { - let menu = this; - let dropPanel = menu.dropPanel; - - // -------------隐藏------------- - if (dropPanel.isShowing) { - dropPanel.hide(); - return; - } - - // -------------显示------------- - dropPanel.show(); - - // 异步加载图片 - if (menu.imgLoaded) { - return; - } - $contentContainer.find('img').each(function () { - let $img = $(this); - let _src = $img.attr('_src'); - $img.on('error', function () { - E.error('加载不出表情图片 ' + _src); - }); - $img.attr('src', _src); - $img.removeAttr('_src'); - }); - menu.imgLoaded = true; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// img 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'img'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.img - }); - - // 创建 panel content - let $panelContent = $('
'); - let $tabContainer = $('
'); - let $contentContainer = $('
'); - $panelContent.append($tabContainer).append($contentContainer); - - // tab - let $uploadTab = $('上传图片'); - let $linkTab = $('网络图片'); - $tabContainer.append($uploadTab).append($linkTab); - - // 上传图片 content - let $uploadContent = $('
'); - $contentContainer.append($uploadContent); - - // 网络图片 content - let $linkContent = $('
'); - $contentContainer.append($linkContent); - linkContentHandler(editor, menu, $linkContent); - - // 添加panel - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $panelContent, - width: 400, - onRender: function () { - // 渲染后的回调事件,用于执行自定义上传的init - // 因为渲染之后,上传面板的dom才会被渲染到页面,才能让第三方空间获取到 - let init = editor.config.customUploadInit; - init && init.call(editor); - } - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - - // tab 切换事件 - function tabToggle() { - $uploadTab.click(function (e) { - $tabContainer.children().removeClass('selected'); - $contentContainer.children().removeClass('selected'); - $uploadContent.addClass('selected'); - $uploadTab.addClass('selected'); - e.preventDefault(); - }); - $linkTab.click(function (e) { - $tabContainer.children().removeClass('selected'); - $contentContainer.children().removeClass('selected'); - $linkContent.addClass('selected'); - $linkTab.addClass('selected'); - e.preventDefault(); - - // focus input - if (E.placeholder) { - $linkContent.find('input[type=text]').focus(); - } - }); - - // 默认情况 - // $uploadTab.addClass('selected'); - // $uploadContent.addClass('selected'); - $uploadTab.click(); - } - - // 隐藏上传图片 - function hideUploadImg() { - $tabContainer.remove(); - $uploadContent.remove(); - $linkContent.addClass('selected'); - } - - // 隐藏网络图片 - function hideLinkImg() { - $tabContainer.remove(); - $linkContent.remove(); - $uploadContent.addClass('selected'); - } - - // 判断用户是否配置了上传图片 - editor.ready(function () { - let editor = this; - let config = editor.config; - let uploadImgUrl = config.uploadImgUrl; - let customUpload = config.customUpload; - let linkImg = config.hideLinkImg; - let $uploadImgPanel; - - if (uploadImgUrl || customUpload) { - // 第一,暴露出 $uploadContent 以便用户自定义 !!!重要 - editor.$uploadContent = $uploadContent; - - // 第二,绑定tab切换事件 - tabToggle(); - - if (linkImg) { - // 隐藏网络图片 - hideLinkImg(); - } - } else { - // 未配置上传图片功能 - hideUploadImg(); - } - - // 点击 $uploadContent 立即隐藏 dropPanel - // 为了兼容IE8、9的上传,因为IE8、9使用 modal 上传 - // 这里使用异步,为了不妨碍高级浏览器通过点击 $uploadContent 选择文件 - function hidePanel() { - menu.dropPanel.hide(); - } - - $uploadContent.click(function () { - setTimeout(hidePanel); - }); - }); - }); - - // --------------- 处理网络图片content --------------- - function linkContentHandler(editor, menu, $linkContent) { - let lang = editor.config.lang; - let $urlContainer = $('
'); - let $urlInput = $(''); - $urlContainer.append($urlInput); - let $btnSubmit = $(''); - let $btnCancel = $(''); - - $linkContent.append($urlContainer).append($btnSubmit).append($btnCancel); - - // 取消 - $btnCancel.click(function (e) { - e.preventDefault(); - menu.dropPanel.hide(); - }); - - // callback - function callback() { - $urlInput.val(''); - } - - // 确定 - $btnSubmit.click(function (e) { - e.preventDefault(); - let url = $.trim($urlInput.val()); - if (!url) { - // 无内容 - $urlInput.focus(); - return; - } - - let imgHtml = ''; - editor.command(e, 'insertHtml', imgHtml, callback); - }); - } - - }); -// video 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'video'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - let reg = /^<(iframe)|(embed)/i; // '); - let $linkInputContainer = $('
'); - let $linkInput = $('\'/>'); - $linkInputContainer.append($linkInput); - let $sizeContainer = $('
'); - let $widthInput = $(''); - let $heightInput = $(''); - $sizeContainer.append(' ' + lang.width + ' ') - .append($widthInput) - .append(' px    ') - .append(' ' + lang.height + ' ') - .append($heightInput) - .append(' px '); - let $btnContainer = $('
'); - let $howToCopy = $('如何复制视频链接?'); - let $btnSubmit = $(''); - let $btnCancel = $(''); - $btnContainer.append($howToCopy).append($btnSubmit).append($btnCancel); - $content.append($linkInputContainer).append($sizeContainer).append($btnContainer); - - // 取消按钮 - $btnCancel.click(function (e) { - e.preventDefault(); - $linkInput.val(''); - menu.dropPanel.hide(); - }); - - // 确定按钮 - $btnSubmit.click(function (e) { - e.preventDefault(); - let link = $.trim($linkInput.val()); - let $link; - let width = parseInt($widthInput.val()); - let height = parseInt($heightInput.val()); - let $div = $('
'); - let html = '

{content}

'; - - // 验证数据 - if (!link) { - menu.dropPanel.focusFirstInput(); - return; - } - - if (!reg.test(link)) { - alert('视频链接格式错误!'); - menu.dropPanel.focusFirstInput(); - return; - } - - if (isNaN(width) || isNaN(height)) { - alert('宽度或高度不是数字!'); - return; - } - - $link = $(link); - - // 设置高度和宽度 - $link.attr('width', width) - .attr('height', height); - - // 拼接字符串 - html = html.replace('{content}', $div.append($link).html()); - - // 执行命令 - editor.command(e, 'insertHtml', html); - $linkInput.val(''); - }); - - // 创建panel - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 400 - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// location 菜单 - _e(function (E, $) { - - // 判断浏览器的 input 是否支持 keyup - let inputKeyup = (function (input) { - return 'onkeyup' in input; - })(document.createElement('input')); - - // 百度地图的key - E.baiduMapAk = 'TVhjYjq1ICT2qqL5LdS8mwas'; - - // 一个页面中,如果有多个编辑器,地图会出现问题。这个参数记录一下,如果超过 1 就提示 - E.numberOfLocation = 0; - - E.createMenu(function (check) { - let menuId = 'location'; - if (!check(menuId)) { - return; - } - - if (++E.numberOfLocation > 1) { - E.error('目前不支持在一个页面多个编辑器上同时使用地图,可通过自定义菜单配置去掉地图菜单'); - return; - } - - let editor = this; - let config = editor.config; - let lang = config.lang; - let ak = config.mapAk; - - // 地图的变量存储到这个地方 - editor.mapData = {}; - let mapData = editor.mapData; - - // ---------- 地图事件 ---------- - mapData.markers = []; - mapData.mapContainerId = 'map' + E.random(); - - mapData.clearLocations = function () { - let map = mapData.map; - if (!map) { - return; - } - map.clearOverlays(); - - //同时,清空marker数组 - mapData.markers = []; - }; - - mapData.searchMap = function () { - let map = mapData.map; - if (!map) { - return; - } - - let BMap = window.BMap; - let cityName = $cityInput.val(); - let locationName = $searchInput.val(); - let myGeo, marker; - - if (cityName !== '') { - if (!locationName || locationName === '') { - map.centerAndZoom(cityName, 11); - } - - //地址解析 - if (locationName && locationName !== '') { - myGeo = new BMap.Geocoder(); - // 将地址解析结果显示在地图上,并调整地图视野 - myGeo.getPoint(locationName, function (point) { - if (point) { - map.centerAndZoom(point, 13); - marker = new BMap.Marker(point); - map.addOverlay(marker); - marker.enableDragging(); //允许拖拽 - mapData.markers.push(marker); //将marker加入到数组中 - } else { - // alert('未找到'); - map.centerAndZoom(cityName, 11); //找不到则重新定位到城市 - } - }, cityName); - } - } // if(cityName !== '') - }; - - // load script 之后的 callback - let hasCallback = false; - window.baiduMapCallBack = function () { - // 避免重复加载 - if (hasCallback) { - return; - } else { - hasCallback = true; - } - - let BMap = window.BMap; - if (!mapData.map) { - // 创建Map实例 - mapData.map = new BMap.Map(mapData.mapContainerId); - } - let map = mapData.map; - - map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地图,设置中心点坐标和地图级别 - map.addControl(new BMap.MapTypeControl()); //添加地图类型控件 - map.setCurrentCity("北京"); // 设置地图显示的城市 此项是必须设置的 - map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 - - //根据IP定位 - function locationFun(result) { - let cityName = result.name; - map.setCenter(cityName); - - // 设置城市名称 - $cityInput.val(cityName); - if (E.placeholder) { - $searchInput.focus(); - } - let timeoutId, searchFn; - if (inputKeyup) { - // 并绑定搜索事件 - input 支持 keyup - searchFn = function (e) { - if (e.type === 'keyup' && e.keyCode === 13) { - e.preventDefault(); - } - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(mapData.searchMap, 500); - }; - $cityInput.on('keyup change paste', searchFn); - $searchInput.on('keyup change paste', searchFn); - } else { - // 并绑定搜索事件 - input 不支持 keyup - searchFn = function () { - if (!$content.is(':visible')) { - // panel 不显示了,就不用再监控了 - clearTimeout(timeoutId); - return; - } - - let currentCity = ''; - let currentSearch = ''; - let city = $cityInput.val(); - let search = $searchInput.val(); - - if (city !== currentCity || search !== currentSearch) { - // 刚获取的数据和之前的数据不一致,执行查询 - mapData.searchMap(); - // 更新数据 - currentCity = city; - currentSearch = search; - } - - // 继续监控 - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(searchFn, 1000); - }; - // 开始监控 - timeoutId = setTimeout(searchFn, 1000); - } - } - - let myCity = new BMap.LocalCity(); - myCity.get(locationFun); - - //鼠标点击,创建位置 - map.addEventListener("click", function (e) { - let marker = new BMap.Marker(new BMap.Point(e.point.lng, e.point.lat)); - map.addOverlay(marker); - marker.enableDragging(); - mapData.markers.push(marker); //加入到数组中 - }, false); - }; - - mapData.loadMapScript = function () { - let script = document.createElement("script"); - script.type = "text/javascript"; - script.src = "https://api.map.baidu.com/api?v=2.0&ak=" + ak + "&s=1&callback=baiduMapCallBack"; // baiduMapCallBack是一个本地函数 - try { - // IE10- 报错 - document.body.appendChild(script); - } catch (ex) { - E.error('加载地图过程中发生错误'); - } - }; - - // 初始化地图 - mapData.initMap = function () { - if (window.BMap) { - // 不是第一次,直接处理地图即可 - window.baiduMapCallBack(); - } else { - // 第一次,先加载地图 script,再处理地图(script加载完自动执行处理) - mapData.loadMapScript(); - } - }; - - // ---------- 创建 menu 对象 ---------- - - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.location - }); - - editor.menus[menuId] = menu; - - // ---------- 构建UI ---------- - - // panel content - let $content = $('
'); - - // 搜索框 - let $inputContainer = $('
'); - let $cityInput = $(''); - $cityInput.css({ - width: '80px', - 'text-align': 'center' - }); - let $searchInput = $(''); - $searchInput.css({ - width: '300px', - 'margin-left': '10px' - }).attr('placeholder', lang.searchlocation); - let $clearBtn = $(''); - $inputContainer.append($clearBtn) - .append($cityInput) - .append($searchInput); - $content.append($inputContainer); - - // 清除位置按钮 - $clearBtn.click(function (e) { - $searchInput.val(''); - $searchInput.focus(); - mapData.clearLocations(); - e.preventDefault(); - }); - - // 地图 - let $map = $('
'); - $map.css({ - height: '260px', - width: '100%', - position: 'relative', - 'margin-top': '10px', - border: '1px solid #f1f1f1' - }); - let $mapLoading = $('' + lang.loading + ''); - $mapLoading.css({ - position: 'absolute', - width: '100px', - 'text-align': 'center', - top: '45%', - left: '50%', - 'margin-left': '-50px' - }); - $map.append($mapLoading); - $content.append($map); - - // 按钮 - let $btnContainer = $('
'); - let $btnSubmit = $(''); - let $btnCancel = $(''); - let $checkLabel = $(''); - let $check = $(''); - $checkLabel.append($check).append(' ' + lang.dynamicMap + ''); - $btnContainer.append($checkLabel) - .append($btnSubmit) - .append($btnCancel); - $content.append($btnContainer); - - function callback() { - $searchInput.val(''); - } - - // 『取消』按钮事件 - $btnCancel.click(function (e) { - e.preventDefault(); - callback(); - menu.dropPanel.hide(); - }); - - // 『确定』按钮事件 - $btnSubmit.click(function (e) { - e.preventDefault(); - let map = mapData.map, - isDynamic = $check.is(':checked'), - markers = mapData.markers, - - center = map.getCenter(), - centerLng = center.lng, - centerLat = center.lat, - - zoom = map.getZoom(), - - size = map.getSize(), - sizeWidth = size.width, - sizeHeight = size.height, - - position, - src, - iframe; - - if (isDynamic) { - //动态地址 - src = 'http://ueditor.baidu.com/ueditor/dialogs/map/show.html#'; - } else { - //静态地址 - src = 'http://api.map.baidu.com/staticimage?'; - } - - //src参数 - src = src + 'center=' + centerLng + ',' + centerLat + - '&zoom=' + zoom + - '&width=' + sizeWidth + - '&height=' + sizeHeight; - if (markers.length > 0) { - src = src + '&markers='; - - //添加所有的marker - $.each(markers, function (key, value) { - position = value.getPosition(); - if (key > 0) { - src = src + '|'; - } - src = src + position.lng + ',' + position.lat; - }); - } - - if (isDynamic) { - if (markers.length > 1) { - alert(lang.langDynamicOneLocation); - return; - } - - src += '&markerStyles=l,A'; - - //插入iframe - iframe = ''; - iframe = iframe.replace('{src}', src); - editor.command(e, 'insertHtml', iframe, callback); - } else { - //插入图片 - editor.command(e, 'insertHtml', '', callback); - } - }); - - // 根据 UI 创建菜单 panel - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 500 - }); - - // ---------- 事件 ---------- - - // render 时执行事件 - menu.onRender = function () { - if (ak === E.baiduMapAk) { - E.warn('建议在配置中自定义百度地图的mapAk,否则可能影响地图功能,文档:' + E.docsite); - } - }; - - // click 事件 - menu.clickEvent = function (e) { - let menu = this; - let dropPanel = menu.dropPanel; - let firstTime = false; - - // -------------隐藏------------- - if (dropPanel.isShowing) { - dropPanel.hide(); - return; - } - - // -------------显示------------- - if (!mapData.map) { - // 第一次,先加载地图 - firstTime = true; - } - - dropPanel.show(); - mapData.initMap(); - - if (!firstTime) { - $searchInput.focus(); - } - }; - - }); - - }); -// insertcode 菜单 - _e(function (E, $) { - - // 加载 highlightjs 代码 - function loadHljs() { - if (E.userAgent.indexOf('MSIE 8') > 0) { - // 不支持 IE8 - return; - } - if (window.hljs) { - // 不要重复加载 - return; - } - let script = document.createElement("script"); - script.type = "text/javascript"; - script.src = "//cdn.bootcss.com/highlight.js/9.2.0/highlight.min.js"; - document.body.appendChild(script); - } - - - E.createMenu(function (check) { - let menuId = 'insertcode'; - if (!check(menuId)) { - return; - } - - // 加载 highlightjs 代码 - setTimeout(loadHljs, 0); - - let editor = this; - let config = editor.config; - let lang = config.lang; - let $txt = editor.txt.$txt; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.insertcode - }); - - // click 事件 - menu.clickEvent = function (e) { - let menu = this; - let dropPanel = menu.dropPanel; - - // 隐藏 - if (dropPanel.isShowing) { - dropPanel.hide(); - return; - } - - // 显示 - $textarea.val(''); - dropPanel.show(); - - // highlightjs 语言列表 - let hljs = window.hljs; - if (hljs && hljs.listLanguages) { - if ($langSelect.children().length !== 0) { - return; - } - $langSelect.css({ - 'margin-top': '9px', - 'margin-left': '5px' - }); - $.each(hljs.listLanguages(), function (key, lang) { - if (lang === 'xml') { - lang = 'html'; - } - if (lang === config.codeDefaultLang) { - $langSelect.append(''); - } else { - $langSelect.append(''); - } - }); - } else { - $langSelect.hide(); - } - }; - - // 选中状态下的 click 事件 - menu.clickEventSelected = function (e) { - let menu = this; - let dropPanel = menu.dropPanel; - - // 隐藏 - if (dropPanel.isShowing) { - dropPanel.hide(); - return; - } - - // 显示 - dropPanel.show(); - - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getSelfOrParentByName(rangeElem, 'pre'); - let $targetElem; - let className; - if (targetElem) { - // 确定找到 pre 之后,再找 code - targetElem = editor.getSelfOrParentByName(rangeElem, 'code'); - } - if (!targetElem) { - return; - } - $targetElem = $(targetElem); - - // 赋值内容 - $textarea.val($targetElem.text()); - if ($langSelect) { - // 赋值语言 - className = $targetElem.attr('class'); - if (className) { - $langSelect.val(className.split(' ')[0]); - } - } - }; - - // 定义更新选中状态的事件 - menu.updateSelectedEvent = function () { - let self = this; //菜单对象 - let editor = self.editor; - let rangeElem; - - rangeElem = editor.getRangeElem(); - rangeElem = editor.getSelfOrParentByName(rangeElem, 'pre'); - - if (rangeElem) { - return true; - } - - return false; - }; - - // 创建 panel - let $content = $('
'); - let $textarea = $(''); - let $langSelect = $(''); - contentHandle($content); - menu.dropPanel = new E.DropPanel(editor, menu, { - $content: $content, - width: 500 - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - - // ------ 增加 content 内容 ------ - function contentHandle($content) { - // textarea 区域 - let $textareaContainer = $('
'); - $textareaContainer.css({ - margin: '15px 5px 5px 5px', - height: '160px', - 'text-align': 'center' - }); - $textarea.css({ - width: '100%', - height: '100%', - padding: '10px' - }); - $textarea.on('keydown', function (e) { - // 取消 tab 键默认行为 - if (e.keyCode === 9) { - e.preventDefault(); - } - }); - $textareaContainer.append($textarea); - $content.append($textareaContainer); - - // 按钮区域 - let $btnContainer = $('
'); - let $btnSubmit = $(''); - let $btnCancel = $(''); - - $btnContainer.append($btnSubmit).append($btnCancel).append($langSelect); - $content.append($btnContainer); - - // 取消按钮 - $btnCancel.click(function (e) { - e.preventDefault(); - menu.dropPanel.hide(); - }); - - // 确定按钮 - let codeTpl = '
{#content}
'; - $btnSubmit.click(function (e) { - e.preventDefault(); - let val = $textarea.val(); - if (!val) { - // 无内容 - $textarea.focus(); - return; - } - - let rangeElem = editor.getRangeElem(); - if ($.trim($(rangeElem).text()) && codeTpl.indexOf('


') !== 0) { - codeTpl = '


' + codeTpl; - } - - let lang = $langSelect ? $langSelect.val() : ''; // 获取高亮语言 - let langClass = ''; - let doHightlight = function () { - $txt.find('pre code').each(function (i, block) { - let $block = $(block); - if ($block.attr('codemark')) { - // 有 codemark 标记的代码块,就不再重新格式化了 - return; - } else if (window.hljs) { - // 新代码块,格式化之后,立即标记 codemark - window.hljs.highlightBlock(block); - $block.attr('codemark', '1'); - } - }); - }; - - // 语言高亮样式 - if (lang) { - langClass = ' class="' + lang + ' hljs"'; - } - - // 替换标签 - val = val.replace(/&/gm, '&') - .replace(//gm, '>'); - - // ---- menu 未选中状态 ---- - if (!menu.selected) { - // 拼接html - let html = codeTpl.replace('{#langClass}', langClass).replace('{#content}', val); - editor.command(e, 'insertHtml', html, doHightlight); - return; - } - - // ---- menu 选中状态 ---- - let targetElem = editor.getSelfOrParentByName(rangeElem, 'pre'); - let $targetElem; - if (targetElem) { - // 确定找到 pre 之后,再找 code - targetElem = editor.getSelfOrParentByName(rangeElem, 'code'); - } - if (!targetElem) { - return; - } - $targetElem = $(targetElem); - - function commandFn() { - let className; - if (lang) { - className = $targetElem.attr('class'); - if (className !== lang + ' hljs') { - $targetElem.attr('class', lang + ' hljs'); - } - } - $targetElem.html(val); - } - - function callback() { - editor.restoreSelectionByElem(targetElem); - doHightlight(); - } - - editor.customCommand(e, commandFn, callback); - }); - } - - // ------ enter 时,不另起标签,只换行 ------ - $txt.on('keydown', function (e) { - if (e.keyCode !== 13) { - return; - } - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getSelfOrParentByName(rangeElem, 'code'); - if (!targetElem) { - return; - } - - editor.command(e, 'insertHtml', '\n'); - }); - - // ------ 点击时,禁用其他标签 ------ - function updateMenu() { - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getSelfOrParentByName(rangeElem, 'code'); - if (targetElem) { - // 在 code 之内,禁用其他菜单 - editor.disableMenusExcept('insertcode'); - } else { - // 不是在 code 之内,启用其他菜单 - editor.enableMenusExcept('insertcode'); - } - } - - $txt.on('keydown click', function (e) { - // 此处必须使用 setTimeout 异步处理,否则不对 - setTimeout(updateMenu); - }); - }); - - }); -// undo 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'undo'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.undo - }); - - // click 事件 - menu.clickEvent = function (e) { - editor.undo(); - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - - - // ------------ 初始化时、enter 时、打字中断时,做记录 ------------ - // ------------ ctrl + z 是调用记录撤销,而不是使用浏览器默认的撤销 ------------ - editor.ready(function () { - let editor = this; - let $txt = editor.txt.$txt; - let timeoutId; - - // 执行undo记录 - function undo() { - editor.undoRecord(); - } - - $txt.on('keydown', function (e) { - let keyCode = e.keyCode; - - // 撤销 ctrl + z - if (e.ctrlKey && keyCode === 90) { - editor.undo(); - return; - } - - if (keyCode === 13) { - // enter 做记录 - undo(); - } else { - // keyup 之后 1s 之内不操作,则做一次记录 - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(undo, 1000); - } - }); - - // 初始化做记录 - editor.undoRecord(); - }); - }); - - }); -// redo 菜单 - _e(function (E, $) { - - E.createMenu(function (check) { - let menuId = 'redo'; - if (!check(menuId)) { - return; - } - let editor = this; - let lang = editor.config.lang; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.redo - }); - - // click 事件 - menu.clickEvent = function (e) { - editor.redo(); - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// 全屏 菜单 - _e(function (E, $) { - - // 记录全屏时的scrollTop - let scrollTopWhenFullScreen; - - E.createMenu(function (check) { - let menuId = 'fullscreen'; - if (!check(menuId)) { - return; - } - let editor = this; - let $txt = editor.txt.$txt; - let config = editor.config; - let zIndexConfig = config.zindex || 10000; - let lang = config.lang; - - let isSelected = false; - let zIndex; - - let maxHeight; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, - id: menuId, - title: lang.fullscreen - }); - - // 定义click事件 - menu.clickEvent = function (e) { - - if (typeof editor.fullScreenClick === "function") { - editor.fullScreenClick(); - } - - // 增加样式 - let $editorContainer = editor.$editorContainer; - $editorContainer.addClass('wangEditor-fullscreen'); - - // (先保存当前的)再设置z-index - zIndex = $editorContainer.css('z-index'); - $editorContainer.css('z-index', zIndexConfig); - - let $wrapper; - let txtHeight = $txt.height(); - let txtOuterHeight = $txt.outerHeight(); - - if (editor.useMaxHeight) { - // 记录 max-height,并暂时去掉maxheight - maxHeight = $txt.css('max-height'); - $txt.css('max-height', 'none'); - - // 如果使用了maxHeight, 将$txt从它的父元素中移出来 - $wrapper = $txt.parent(); - $wrapper.after($txt); - $wrapper.remove(); - $txt.css('overflow-y', 'auto'); - } - - // 设置高度到全屏 - let menuContainer = editor.menuContainer; - $txt.height( - E.$window.height() - - menuContainer.height() - - (txtOuterHeight - txtHeight) // 去掉内边距和外边距 - ); - - // 取消menuContainer的内联样式(menu吸顶时,会为 menuContainer 设置一些内联样式) - editor.menuContainer.$menuContainer.attr('style', ''); - - // 保存状态 - isSelected = true; - - // 记录编辑器是否全屏 - editor.isFullScreen = true; - - // 记录设置全屏时的高度 - scrollTopWhenFullScreen = E.$window.scrollTop(); - }; - - // 定义选中状态的 click 事件 - menu.clickEventSelected = function (e) { - - if (typeof editor.fullScreenClickSelected === "function") { - editor.fullScreenClickSelected(); - } - - // 取消样式 - let $editorContainer = editor.$editorContainer; - $editorContainer.removeClass('wangEditor-fullscreen'); - $editorContainer.css('z-index', zIndex); - - // 还原height - if (editor.useMaxHeight) { - $txt.css('max-height', maxHeight); - } else { - // editor.valueContainerHeight 在 editor.txt.initHeight() 中事先保存了 - editor.$valueContainer.css('height', editor.valueContainerHeight); - } - - // 重新计算高度 - editor.txt.initHeight(); - - // 保存状态 - isSelected = false; - - // 记录编辑器是否全屏 - editor.isFullScreen = false; - - // 还原scrollTop - if (scrollTopWhenFullScreen != null) { - E.$window.scrollTop(scrollTopWhenFullScreen); - } - }; - - // 定义选中事件 - menu.updateSelectedEvent = function (e) { - return isSelected; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// 渲染menus - _e(function (E, $) { - - E.fn.renderMenus = function () { - - let editor = this; - let menus = editor.menus; - let menuIds = editor.config.menus; - let menuContainer = editor.menuContainer; - - let menu; - let groupIdx = 0; - $.each(menuIds, function (k, v) { - if (v === '|') { - groupIdx++; - return; - } - - menu = menus[v]; - if (menu) { - menu.render(groupIdx); - } - }); - }; - - }); -// 渲染menus - _e(function (E, $) { - - E.fn.renderMenuContainer = function () { - - let editor = this; - let menuContainer = editor.menuContainer; - let $editorContainer = editor.$editorContainer; - - menuContainer.render(); - - }; - - }); -// 渲染 txt - _e(function (E, $) { - - E.fn.renderTxt = function () { - - let editor = this; - let txt = editor.txt; - - txt.render(); - - // ready 时候,计算txt的高度 - editor.ready(function () { - txt.initHeight(); - }); - }; - - }); -// 渲染 container - _e(function (E, $) { - - E.fn.renderEditorContainer = function () { - - let editor = this; - let $valueContainer = editor.$valueContainer; - let $editorContainer = editor.$editorContainer; - let $txt = editor.txt.$txt; - let $prev, $parent; - - // 将编辑器渲染到页面中 - if ($valueContainer === $txt) { - $prev = editor.$prev; - $parent = editor.$parent; - - if ($prev && $prev.length) { - // 有前置节点,就插入到前置节点的后面 - $prev.after($editorContainer); - } else { - // 没有前置节点,就直接插入到父元素 - $parent.prepend($editorContainer); - } - - } else { - $valueContainer.after($editorContainer); - $valueContainer.hide(); - } - - // 设置宽度(这样设置宽度有问题) - // $editorContainer.css('width', $valueContainer.css('width')); - }; - - }); -// 菜单事件 - _e(function (E, $) { - - // 绑定每个菜单的click事件 - E.fn.eventMenus = function () { - - let menus = this.menus; - - // 绑定菜单的点击事件 - $.each(menus, function (k, v) { - v.bindEvent(); - }); - - }; - - }); -// 菜单container事件 - _e(function (E, $) { - - E.fn.eventMenuContainer = function () { - - }; - - }); -// 编辑区域事件 - _e(function (E, $) { - - E.fn.eventTxt = function () { - - let txt = this.txt; - - // txt内容变化时,保存选区 - txt.saveSelectionEvent(); - - // txt内容变化时,随时更新 value - txt.updateValueEvent(); - - // txt内容变化时,随时更新 menu style - txt.updateMenuStyleEvent(); - - // // 鼠标hover时,显示 p head 高度(暂时关闭这个功能) - // if (!/ie/i.test(E.userAgent)) { - // // 暂时不支持IE - // txt.showHeightOnHover(); - // } - }; - - }); -// 上传图片事件 - _e(function (E, $) { - - E.plugin(function () { - let editor = this; - let fns = editor.config.uploadImgFns; // editor.config.uploadImgFns = {} 在config文件中定义了 - - // -------- 定义load函数 -------- - fns.onload || (fns.onload = function (resultText, xhr) { - E.log('上传结束,返回结果为 ' + resultText); - - let editor = this; - let originalName = editor.uploadImgOriginalName || ''; // 上传图片时,已经将图片的名字存在 editor.uploadImgOriginalName - let img; - if (resultText.indexOf('error|') === 0) { - // 提示错误 - E.warn('上传失败:' + resultText.split('|')[1]); - alert(resultText.split('|')[1]); - } else { - E.log('上传成功,即将插入编辑区域,结果为:' + resultText); - - // 将结果插入编辑器 - img = document.createElement('img'); - img.onload = function () { - let html = '' + originalName + ''; - editor.command(null, 'insertHtml', html); - - E.log('已插入图片,地址 ' + resultText); - img = null; - }; - img.onerror = function () { - E.error('使用返回的结果获取图片,发生错误。请确认以下结果是否正确:' + resultText); - img = null; - }; - img.src = resultText; - } - - }); - - // -------- 定义tiemout函数 -------- - fns.ontimeout || (fns.ontimeout = function (xhr) { - E.error('上传图片超时'); - alert('上传图片超时'); - }); - - // -------- 定义error函数 -------- - fns.onerror || (fns.onerror = function (xhr) { - E.error('上传上图片发生错误'); - alert('上传上图片发生错误'); - }); - - }); - }); -// xhr 上传图片 - _e(function (E, $) { - - if (!window.FileReader || !window.FormData) { - // 如果不支持html5的文档操作,直接返回 - return; - } - - E.plugin(function () { - - let editor = this; - let config = editor.config; - let uploadImgUrl = config.uploadImgUrl; - let uploadTimeout = config.uploadTimeout; - - // 获取配置中的上传事件 - let uploadImgFns = config.uploadImgFns; - let onload = uploadImgFns.onload; - let ontimeout = uploadImgFns.ontimeout; - let onerror = uploadImgFns.onerror; - - if (!uploadImgUrl) { - return; - } - - // -------- 将以base64的图片url数据转换为Blob -------- - function convertBase64UrlToBlob(urlData, filetype) { - //去掉url的头,并转换为byte - let bytes = window.atob(urlData.split(',')[1]); - - //处理异常,将ascii码小于0的转换为大于0 - let ab = new ArrayBuffer(bytes.length); - let ia = new Uint8Array(ab); - let i; - for (i = 0; i < bytes.length; i++) { - ia[i] = bytes.charCodeAt(i); - } - - return new Blob([ab], {type: filetype}); - } - - // -------- 插入图片的方法 -------- - function insertImg(src, event) { - let img = document.createElement('img'); - img.onload = function () { - let html = ''; - editor.command(event, 'insertHtml', html); - - E.log('已插入图片,地址 ' + src); - img = null; - }; - img.onerror = function () { - E.error('使用返回的结果获取图片,发生错误。请确认以下结果是否正确:' + src); - img = null; - }; - img.src = src; - } - - // -------- onprogress 事件 -------- - function updateProgress(e) { - if (e.lengthComputable) { - let percentComplete = e.loaded / e.total; - editor.showUploadProgress(percentComplete * 100); - } - } - - // -------- xhr 上传图片 -------- - editor.xhrUploadImg = function (opt) { - // opt 数据 - let event = opt.event; - let fileName = opt.filename || ''; - let base64 = opt.base64; - let fileType = opt.fileType || 'image/png'; // 无扩展名则默认使用 png - let name = opt.name || 'wangEditor_upload_file'; - let loadfn = opt.loadfn || onload; - let errorfn = opt.errorfn || onerror; - let timeoutfn = opt.timeoutfn || ontimeout; - - // 上传参数(如 token) - let params = editor.config.uploadParams || {}; - - // headers - let headers = editor.config.uploadHeaders || {}; - - // 获取文件扩展名 - let fileExt = 'png'; // 默认为 png - if (fileName.indexOf('.') > 0) { - // 原来的文件名有扩展名 - fileExt = fileName.slice(fileName.lastIndexOf('.') - fileName.length + 1); - } else if (fileType.indexOf('/') > 0 && fileType.split('/')[1]) { - // 文件名没有扩展名,通过类型获取,如从 'image/png' 取 'png' - fileExt = fileType.split('/')[1]; - } - - // ------------ begin 预览模拟上传 ------------ - if (E.isOnWebsite) { - E.log('预览模拟上传'); - insertImg(base64, event); - return; - } - // ------------ end 预览模拟上传 ------------ - - // 变量声明 - let xhr = new XMLHttpRequest(); - let timeoutId; - let src; - let formData = new FormData(); - - // 超时处理 - function timeoutCallback() { - if (timeoutId) { - clearTimeout(timeoutId); - } - if (xhr && xhr.abort) { - xhr.abort(); - } - - // 超时了就阻止默认行为 - event.preventDefault(); - - // 执行回调函数,提示什么内容,都应该在回调函数中定义 - timeoutfn && timeoutfn.call(editor, xhr); - - // 隐藏进度条 - editor.hideUploadProgress(); - } - - xhr.onload = function () { - if (timeoutId) { - clearTimeout(timeoutId); - } - - // 记录文件名到 editor.uploadImgOriginalName ,插入图片时,可做 alt 属性用 - editor.uploadImgOriginalName = fileName; - if (fileName.indexOf('.') > 0) { - editor.uploadImgOriginalName = fileName.split('.')[0]; - } - - // 执行load函数,任何操作,都应该在load函数中定义 - loadfn && loadfn.call(editor, xhr.responseText, xhr); - - // 隐藏进度条 - editor.hideUploadProgress(); - }; - xhr.onerror = function () { - if (timeoutId) { - clearTimeout(timeoutId); - } - - // 超时了就阻止默认行为 - event.preventDefault(); - - // 执行error函数,错误提示,应该在error函数中定义 - errorfn && errorfn.call(editor, xhr); - - // 隐藏进度条 - editor.hideUploadProgress(); - }; - // xhr.onprogress = updateProgress; - xhr.upload.onprogress = updateProgress; - - // 填充数据 - formData.append(name, convertBase64UrlToBlob(base64, fileType), E.random() + '.' + fileExt); - - // 添加参数 - $.each(params, function (key, value) { - formData.append(key, value); - }); - - // 开始上传 - xhr.open('POST', uploadImgUrl, true); - // xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 将参数解析成传统form的方式上传 - - // 修改自定义配置的headers - $.each(headers, function (key, value) { - xhr.setRequestHeader(key, value); - }); - - // 跨域上传时,传cookie - xhr.withCredentials = true; - - // 发送数据 - xhr.send(formData); - timeoutId = setTimeout(timeoutCallback, uploadTimeout); - - E.log('开始上传...并开始超时计算'); - }; - }); - }); -// 进度条 - _e(function (E, $) { - - E.plugin(function () { - - let editor = this; - let menuContainer = editor.menuContainer; - let menuHeight = menuContainer.height(); - let $editorContainer = editor.$editorContainer; - let width = $editorContainer.width(); - let $progress = $('
'); - - // 渲染事件 - let isRender = false; - - function render() { - if (isRender) { - return; - } - isRender = true; - - $progress.css({ - top: menuHeight + 'px' - }); - $editorContainer.append($progress); - } - - // ------ 显示进度 ------ - editor.showUploadProgress = function (progress) { - if (timeoutId) { - clearTimeout(timeoutId); - } - - // 显示之前,先判断是否渲染 - render(); - - $progress.show(); - $progress.width(progress * width / 100); - }; - - // ------ 隐藏进度条 ------ - let timeoutId; - - function hideProgress() { - $progress.hide(); - timeoutId = null; - } - - editor.hideUploadProgress = function (time) { - if (timeoutId) { - clearTimeout(timeoutId); - } - time = time || 750; - timeoutId = setTimeout(hideProgress, time); - }; - }); - }); -// upload img 插件 - _e(function (E, $) { - - E.plugin(function () { - let editor = this; - let config = editor.config; - let uploadImgUrl = config.uploadImgUrl; - let uploadTimeout = config.uploadTimeout; - let event; - - if (!uploadImgUrl) { - return; - } - - // 获取editor的上传dom - let $uploadContent = editor.$uploadContent; - if (!$uploadContent) { - return; - } - - // 自定义UI,并添加到上传dom节点上 - let $uploadIcon = $('
'); - $uploadContent.append($uploadIcon); - - // ---------- 构建上传对象 ---------- - let upfile = new E.UploadFile({ - editor: editor, - uploadUrl: uploadImgUrl, - timeout: uploadTimeout, - fileAccept: 'image/jpg,image/jpeg,image/png,image/gif,image/bmp' // 只允许选择图片 - }); - - // 选择本地文件,上传 - $uploadIcon.click(function (e) { - event = e; - upfile.selectFiles(); - }); - }); - }); -// h5 方式上传图片 - _e(function (E, $) { - - if (!window.FileReader || !window.FormData) { - // 如果不支持html5的文档操作,直接返回 - return; - } - - // 构造函数 - let UploadFile = function (opt) { - this.editor = opt.editor; - this.uploadUrl = opt.uploadUrl; - this.timeout = opt.timeout; - this.fileAccept = opt.fileAccept; - this.multiple = true; - }; - - UploadFile.fn = UploadFile.prototype; - - // clear - UploadFile.fn.clear = function () { - this.$input.val(''); - E.log('input value 已清空'); - }; - - // 渲染 - UploadFile.fn.render = function () { - let self = this; - if (self._hasRender) { - // 不要重复渲染 - return; - } - - E.log('渲染dom'); - - let fileAccept = self.fileAccept; - let acceptTpl = fileAccept ? 'accept="' + fileAccept + '"' : ''; - let multiple = self.multiple; - let multipleTpl = multiple ? 'multiple="multiple"' : ''; - let $input = $(''); - let $container = $('
'); - - $container.append($input); - E.$body.append($container); - - // onchange 事件 - $input.on('change', function (e) { - self.selected(e, $input.get(0)); - }); - - // 记录对象数据 - self.$input = $input; - - // 记录 - self._hasRender = true; - }; - - // 选择 - UploadFile.fn.selectFiles = function () { - let self = this; - - E.log('使用 html5 方式上传'); - - // 先渲染 - self.render(); - - // 选择 - E.log('选择文件'); - self.$input.click(); - }; - - // 选中文件之后 - UploadFile.fn.selected = function (e, input) { - let self = this; - let files = input.files || []; - if (files.length === 0) { - return; - } - - E.log('选中 ' + files.length + ' 个文件'); - - // 遍历选中的文件,预览、上传 - $.each(files, function (key, value) { - self.upload(value); - }); - }; - - // 上传单个文件 - UploadFile.fn.upload = function (file) { - let self = this; - let editor = self.editor; - let filename = file.name || ''; - let fileType = file.type || ''; - let uploadImgFns = editor.config.uploadImgFns; - let uploadFileName = editor.config.uploadImgFileName || 'wangEditorH5File'; - let onload = uploadImgFns.onload; - let ontimeout = uploadImgFns.ontimeout; - let onerror = uploadImgFns.onerror; - let reader = new FileReader(); - - if (!onload || !ontimeout || !onerror) { - E.error('请为编辑器配置上传图片的 onload ontimeout onerror 回调事件'); - return; - } - - - E.log('开始执行 ' + filename + ' 文件的上传'); - - // 清空 input 数据 - function clearInput() { - self.clear(); - } - - // onload事件 - reader.onload = function (e) { - E.log('已读取' + filename + '文件'); - - let base64 = e.target.result || this.result; - editor.xhrUploadImg({ - event: e, - filename: filename, - base64: base64, - fileType: fileType, - name: uploadFileName, - loadfn: function (resultText, xhr) { - clearInput(); - // 执行配置中的方法 - let editor = this; - onload.call(editor, resultText, xhr); - }, - errorfn: function (xhr) { - clearInput(); - if (E.isOnWebsite) { - alert('wangEditor官网暂时没有服务端,因此报错。实际项目中不会发生'); - } - // 执行配置中的方法 - let editor = this; - onerror.call(editor, xhr); - }, - timeoutfn: function (xhr) { - clearInput(); - if (E.isOnWebsite) { - alert('wangEditor官网暂时没有服务端,因此超时。实际项目中不会发生'); - } - // 执行配置中的方法 - let editor = this; - ontimeout(editor, xhr); - } - }); - }; - - // 开始取文件 - reader.readAsDataURL(file); - }; - - // 暴露给 E - E.UploadFile = UploadFile; - - }); -// form方式上传图片 - _e(function (E, $) { - - if (window.FileReader && window.FormData) { - // 如果支持 html5 上传,则返回 - return; - } - - // 构造函数 - let UploadFile = function (opt) { - this.editor = opt.editor; - this.uploadUrl = opt.uploadUrl; - this.timeout = opt.timeout; - this.fileAccept = opt.fileAccept; - this.multiple = false; - }; - - UploadFile.fn = UploadFile.prototype; - - // clear - UploadFile.fn.clear = function () { - this.$input.val(''); - E.log('input value 已清空'); - }; - - // 隐藏modal - UploadFile.fn.hideModal = function () { - this.modal.hide(); - }; - - // 渲染 - UploadFile.fn.render = function () { - let self = this; - let editor = self.editor; - let uploadFileName = editor.config.uploadImgFileName || 'wangEditorFormFile'; - if (self._hasRender) { - // 不要重复渲染 - return; - } - - // 服务器端路径 - let uploadUrl = self.uploadUrl; - - E.log('渲染dom'); - - // 创建 form 和 iframe - let iframeId = 'iframe' + E.random(); - let $iframe = $(''); - let multiple = self.multiple; - let multipleTpl = multiple ? 'multiple="multiple"' : ''; - let $p = $('

选择图片并上传

'); - let $input = $(''); - let $btn = $(''); - let $form = $('
'); - let $container = $('
'); - - $form.append($p).append($input).append($btn); - - // 增加用户配置的参数,如 token - $.each(editor.config.uploadParams, function (key, value) { - $form.append($('')); - }); - - $container.append($form); - $container.append($iframe); - - self.$input = $input; - self.$iframe = $iframe; - - // 生成 modal - let modal = new E.Modal(editor, undefined, { - $content: $container - }); - self.modal = modal; - - // 记录 - self._hasRender = true; - }; - - // 绑定 iframe load 事件 - UploadFile.fn.bindLoadEvent = function () { - let self = this; - if (self._hasBindLoad) { - // 不要重复绑定 - return; - } - - let editor = self.editor; - let $iframe = self.$iframe; - let iframe = $iframe.get(0); - let iframeWindow = iframe.contentWindow; - let onload = editor.config.uploadImgFns.onload; - - // 定义load事件 - function onloadFn() { - let resultText = $.trim(iframeWindow.document.body.innerHTML); - if (!resultText) { - return; - } - - // 获取文件名 - let fileFullName = self.$input.val(); // 结果如 C:\folder\abc.png 格式 - let fileOriginalName = fileFullName; - if (fileFullName.lastIndexOf('\\') >= 0) { - // 获取 abc.png 格式 - fileOriginalName = fileFullName.slice(fileFullName.lastIndexOf('\\') + 1); - if (fileOriginalName.indexOf('.') > 0) { - // 获取 abc (即不带扩展名的文件名) - fileOriginalName = fileOriginalName.split('.')[0]; - } - } - - // 将文件名暂存到 editor.uploadImgOriginalName ,插入图片时,可作为 alt 属性来用 - editor.uploadImgOriginalName = fileOriginalName; - - // 执行load函数,插入图片的操作,应该在load函数中执行 - onload.call(editor, resultText); - - // 清空 input 数据 - self.clear(); - - // 隐藏modal - self.hideModal(); - } - - // 绑定 load 事件 - if (iframe.attachEvent) { - iframe.attachEvent('onload', onloadFn); - } else { - iframe.onload = onloadFn; - } - - // 记录 - self._hasBindLoad = true; - }; - - UploadFile.fn.show = function () { - let self = this; - let modal = self.modal; - - function show() { - modal.show(); - self.bindLoadEvent(); - } - - setTimeout(show); - }; - - // 选择 - UploadFile.fn.selectFiles = function () { - let self = this; - - E.log('使用 form 方式上传'); - - // 先渲染 - self.render(); - - // 先清空 - self.clear(); - - // 显示 - self.show(); - }; - - // 暴露给 E - E.UploadFile = UploadFile; - - }); -// upload img 插件 粘贴图片 - _e(function (E, $) { - - E.plugin(function () { - let editor = this; - let txt = editor.txt; - let $txt = txt.$txt; - let config = editor.config; - let uploadImgUrl = config.uploadImgUrl; - let uploadFileName = config.uploadImgFileName || 'wangEditorPasteFile'; - let pasteEvent; - let $imgsBeforePaste; - - // 未配置上传图片url,则忽略 - if (!uploadImgUrl) { - return; - } - - // -------- 非 chrome 下,通过查找粘贴的图片的方式上传 -------- - function findPasteImgAndUpload() { - let reg = /^data:(image\/\w+);base64/; - let $imgs = $txt.find('img'); - - E.log('粘贴后,检查到编辑器有' + $imgs.length + '个图片。开始遍历图片,试图找到刚刚粘贴过来的图片'); - - $.each($imgs, function () { - let img = this; - let $img = $(img); - let flag; - let base64 = $img.attr('src'); - let type; - - // 判断当前图片是否是粘贴之前的 - $imgsBeforePaste.each(function () { - if (img === this) { - // 当前图片是粘贴之前的 - flag = true; - return false; - } - }); - - // 当前图片是粘贴之前的,则忽略 - if (flag) { - return; - } - - E.log('找到一个粘贴过来的图片'); - - if (reg.test(base64)) { - // 得到的粘贴的图片是 base64 格式,符合要求 - E.log('src 是 base64 格式,可以上传'); - type = base64.match(reg)[1]; - editor.xhrUploadImg({ - event: pasteEvent, - base64: base64, - fileType: type, - name: uploadFileName - }); - } else { - E.log('src 为 ' + base64 + ' ,不是 base64 格式,暂时不支持上传'); - } - - // 最终移除原图片 - $img.remove(); - }); - - E.log('遍历结束'); - } - - // 开始监控粘贴事件 - $txt.on('paste', function (e) { - pasteEvent = e; - let data = pasteEvent.clipboardData || pasteEvent.originalEvent.clipboardData; - let text; - let items; - - // -------- 试图获取剪切板中的文字,有文字的情况下,就不处理图片粘贴 -------- - if (data == null) { - text = window.clipboardData && window.clipboardData.getData('text'); - } else { - text = data.getData('text/plain') || data.getData('text/html'); - } - if (text) { - return; - } - - items = data && data.items; - if (items) { - // -------- chrome 可以用 data.items 取出图片 ----- - E.log('通过 data.items 得到了数据'); - - $.each(items, function (key, value) { - let fileType = value.type || ''; - if (fileType.indexOf('image') < 0) { - // 不是图片 - return; - } - - let file = value.getAsFile(); - let reader = new FileReader(); - - E.log('得到一个粘贴图片'); - - reader.onload = function (e) { - E.log('读取到粘贴的图片'); - - // 执行上传 - let base64 = e.target.result || this.result; - editor.xhrUploadImg({ - event: pasteEvent, - base64: base64, - fileType: fileType, - name: uploadFileName - }); - }; - - //读取粘贴的文件 - reader.readAsDataURL(file); - }); - } else { - // -------- 非 chrome 不能用 data.items 取图片 ----- - - E.log('未从 data.items 得到数据,使用检测粘贴图片的方式'); - - // 获取 - $imgsBeforePaste = $txt.find('img'); - E.log('粘贴前,检查到编辑器有' + $imgsBeforePaste.length + '个图片'); - - // 异步上传找到的图片 - setTimeout(findPasteImgAndUpload, 0); - } - }); - - }); - }); -// 拖拽上传图片 插件 - _e(function (E, $) { - - E.plugin(function () { - - let editor = this; - let txt = editor.txt; - let $txt = txt.$txt; - let config = editor.config; - let uploadImgUrl = config.uploadImgUrl; - let uploadFileName = config.uploadImgFileName || 'wangEditorDragFile'; - - // 未配置上传图片url,则忽略 - if (!uploadImgUrl) { - return; - } - - // 阻止浏览器默认行为 - E.$document.on('dragleave drop dragenter dragover', function (e) { - e.preventDefault(); - }); - - // 监控 $txt drop 事件 - $txt.on('drop', function (dragEvent) { - dragEvent.preventDefault(); - - let originalEvent = dragEvent.originalEvent; - let files = originalEvent.dataTransfer && originalEvent.dataTransfer.files; - - if (!files || !files.length) { - return; - } - - $.each(files, function (k, file) { - let type = file.type; - let name = file.name; - - if (type.indexOf('image/') < 0) { - // 只接收图片 - return; - } - - E.log('得到图片 ' + name); - - let reader = new FileReader(); - reader.onload = function (e) { - E.log('读取到图片 ' + name); - - // 执行上传 - let base64 = e.target.result || this.result; - editor.xhrUploadImg({ - event: dragEvent, - base64: base64, - fileType: type, - name: uploadFileName - }); - }; - - //读取粘贴的文件 - reader.readAsDataURL(file); - - }); - }); - }); - - }); -// 编辑器区域 table toolbar - _e(function (E, $) { - - E.plugin(function () { - let editor = this; - let txt = editor.txt; - let $txt = txt.$txt; - let html = ''; - // 说明:设置了 max-height 之后,$txt.parent() 负责滚动处理 - let $currentTxt = editor.useMaxHeight ? $txt.parent() : $txt; - let $currentTable; - - // 用到的dom节点 - let isRendered = false; - let $toolbar = $('
'); - let $triangle = $('
'); - let $delete = $(''); - let $zoomSmall = $(''); - let $zoomBig = $(''); - - // 渲染到页面 - function render() { - if (isRendered) { - return; - } - - // 绑定事件 - bindEvent(); - - // 拼接 渲染到页面上 - $toolbar.append($triangle) - .append($delete) - .append($zoomSmall) - .append($zoomBig); - editor.$editorContainer.append($toolbar); - isRendered = true; - } - - // 绑定事件 - function bindEvent() { - // 统一执行命令的方法 - let commandFn; - - function command(e, callback) { - // 执行命令之前,先存储html内容 - html = $txt.html(); - // 监控内容变化 - let cb = function () { - if (callback) { - callback(); - } - if (html !== $txt.html()) { - $txt.change(); - } - }; - // 执行命令 - if (commandFn) { - editor.customCommand(e, commandFn, cb); - } - } - - // 删除 - $delete.click(function (e) { - commandFn = function () { - $currentTable.remove(); - }; - command(e, function () { - setTimeout(hide, 100); - }); - }); - - // 放大 - $zoomBig.click(function (e) { - commandFn = function () { - $currentTable.css({ - width: '100%' - }); - }; - command(e, function () { - setTimeout(show); - }); - }); - - // 缩小 - $zoomSmall.click(function (e) { - commandFn = function () { - $currentTable.css({ - width: 'auto' - }); - }; - command(e, function () { - setTimeout(show); - }); - }); - } - - // 显示 toolbar - function show() { - if (editor._disabled) { - // 编辑器已经被禁用,则不让显示 - return; - } - if ($currentTable == null) { - return; - } - $currentTable.addClass('clicked'); - let tablePosition = $currentTable.position(); - let tableTop = tablePosition.top; - let tableLeft = tablePosition.left; - let tableHeight = $currentTable.outerHeight(); - let tableWidth = $currentTable.outerWidth(); - - // --- 定位 toolbar --- - - // 计算初步结果 - let top = tableTop + tableHeight; - let left = tableLeft; - let marginLeft = 0; - - let txtTop = $currentTxt.position().top; - let txtHeight = $currentTxt.outerHeight(); - if (top > (txtTop + txtHeight)) { - // top 不得超出编辑范围 - top = txtTop + txtHeight; - } - - // 显示(方便计算 margin) - $toolbar.show(); - - // 计算 margin - let width = $toolbar.outerWidth(); - marginLeft = tableWidth / 2 - width / 2; - - // 定位 - $toolbar.css({ - top: top + 5, - left: left, - 'margin-left': marginLeft - }); - // 如果定位太靠左了 - if (marginLeft < 0) { - // 得到三角形的margin-left - $toolbar.css('margin-left', '0'); - $triangle.hide(); - } else { - $triangle.show(); - } - } - - // 隐藏 toolbar - function hide() { - if ($currentTable == null) { - return; - } - $currentTable.removeClass('clicked'); - $currentTable = null; - $toolbar.hide(); - } - - // click table 事件 - $currentTxt.on('click', 'table', function (e) { - let $table = $(e.currentTarget); - - // 渲染 - render(); - - if ($currentTable && ($currentTable.get(0) === $table.get(0))) { - setTimeout(hide, 100); - return; - } - - // 显示 toolbar - $currentTable = $table; - show(); - - // 阻止冒泡 - e.preventDefault(); - e.stopPropagation(); - - }).on('click keydown scroll', function (e) { - setTimeout(hide, 100); - }); - E.$body.on('click keydown scroll', function (e) { - setTimeout(hide, 100); - }); - }); - - }); -// 编辑器区域 img toolbar - _e(function (E, $) { - - if (E.userAgent.indexOf('MSIE 8') > 0) { - return; - } - - E.plugin(function () { - let editor = this; - let lang = editor.config.lang; - let txt = editor.txt; - let $txt = txt.$txt; - let html = ''; - // 说明:设置了 max-height 之后,$txt.parent() 负责滚动处理 - let $currentTxt = editor.useMaxHeight ? $txt.parent() : $txt; - let $editorContainer = editor.$editorContainer; - let $currentImg; - let currentLink = ''; - - // 用到的dom节点 - let isRendered = false; - let $dragPoint = $('
'); - - let $toolbar = $('
'); - let $triangle = $('
'); - - let $menuContainer = $('
'); - let $delete = $(''); - let $zoomSmall = $(''); - let $zoomBig = $(''); - // let $floatLeft = $(''); - // let $noFloat = $(''); - // let $floatRight = $(''); - let $alignLeft = $(''); - let $alignCenter = $(''); - let $alignRight = $(''); - let $link = $(''); - let $unLink = $(''); - - let $linkInputContainer = $('
'); - let $linkInput = $(''); - let $linkBtnSubmit = $(''); - let $linkBtnCancel = $(''); - - // 记录是否正在拖拽 - let isOnDrag = false; - - // 获取 / 设置 链接 - function imgLink(e, url) { - if (!$currentImg) { - return; - } - let commandFn; - let callback = function () { - // 及时保存currentLink - if (url != null) { - currentLink = url; - } - if (html !== $txt.html()) { - $txt.change(); - } - }; - let $link; - let inLink = false; - let $parent = $currentImg.parent(); - if ($parent.get(0).nodeName.toLowerCase() === 'a') { - // 父元素就是图片链接 - $link = $parent; - inLink = true; - } else { - // 父元素不是图片链接,则重新创建一个链接 - $link = $(''); - } - - if (url == null) { - // url 无值,是获取链接 - return $link.attr('href') || ''; - } else if (url === '') { - // url 是空字符串,是取消链接 - if (inLink) { - commandFn = function () { - $currentImg.unwrap(); - }; - } - } else { - // url 有值,是设置链接 - if (url === currentLink) { - return; - } - commandFn = function () { - $link.attr('href', url); - - if (!inLink) { - // 当前图片未包含在链接中,则包含进来 - $currentImg.wrap($link); - } - }; - } - - // 执行命令 - if (commandFn) { - // 记录下执行命令之前的html内容 - html = $txt.html(); - // 执行命令 - editor.customCommand(e, commandFn, callback); - } - } - - // 渲染到页面 - function render() { - if (isRendered) { - return; - } - - // 绑定事件 - bindToolbarEvent(); - bindDragEvent(); - - // 菜单放入 container - $menuContainer.append($delete) - .append($zoomSmall) - .append($zoomBig) - // .append($floatLeft) - // .append($noFloat) - // .append($floatRight); - .append($alignLeft) - .append($alignCenter) - .append($alignRight) - .append($link) - .append($unLink); - - // 链接input放入container - $linkInputContainer.append($linkInput) - .append($linkBtnCancel) - .append($linkBtnSubmit); - - // 拼接 渲染到页面上 - $toolbar.append($triangle) - .append($menuContainer) - .append($linkInputContainer); - - editor.$editorContainer.append($toolbar).append($dragPoint); - isRendered = true; - } - - // 绑定toolbar事件 - function bindToolbarEvent() { - // 统一执行命令的方法 - let commandFn; - - function customCommand(e, callback) { - let cb; - // 记录下执行命令之前的html内容 - html = $txt.html(); - cb = function () { - if (callback) { - callback(); - } - if (html !== $txt.html()) { - $txt.change(); - } - }; - // 执行命令 - if (commandFn) { - editor.customCommand(e, commandFn, cb); - } - } - - // 删除 - $delete.click(function (e) { - // 删除之前先unlink - imgLink(e, ''); - - // 删除图片 - commandFn = function () { - $currentImg.remove(); - }; - customCommand(e, function () { - setTimeout(hide, 100); - }); - }); - - // 放大 - $zoomBig.click(function (e) { - commandFn = function () { - let img = $currentImg.get(0); - let width = img.width; - let height = img.height; - width = width * 1.1; - height = height * 1.1; - - $currentImg.css({ - width: width + 'px', - height: height + 'px' - }); - }; - customCommand(e, function () { - setTimeout(show); - }); - }); - - // 缩小 - $zoomSmall.click(function (e) { - commandFn = function () { - let img = $currentImg.get(0); - let width = img.width; - let height = img.height; - width = width * 0.9; - height = height * 0.9; - - $currentImg.css({ - width: width + 'px', - height: height + 'px' - }); - }; - customCommand(e, function () { - setTimeout(show); - }); - }); - - // // 左浮动 - // $floatLeft.click(function (e) { - // commandFn = function () { - // $currentImg.css({ - // float: 'left' - // }); - // }; - // customCommand(e, function () { - // setTimeout(hide, 100); - // }); - // }); - - // alignLeft - $alignLeft.click(function (e) { - commandFn = function () { - // 如果 img 增加了链接,那么 img.parent() 就是 a 标签,设置 align 没用的,因此必须找到 P 父节点来设置 align - $currentImg.parents('p').css({ - 'text-align': 'left' - }).attr('align', 'left'); - console.log("Here."); - }; - customCommand(e, function () { - setTimeout(hide, 100); - }); - }); - - // // 右浮动 - // $floatRight.click(function (e) { - // commandFn = function () { - // $currentImg.css({ - // float: 'right' - // }); - // }; - // customCommand(e, function () { - // setTimeout(hide, 100); - // }); - // }); - - // alignRight - $alignRight.click(function (e) { - commandFn = function () { - // 如果 img 增加了链接,那么 img.parent() 就是 a 标签,设置 align 没用的,因此必须找到 P 父节点来设置 align - $currentImg.parents('p').css({ - 'text-align': 'right' - }).attr('align', 'right'); - }; - customCommand(e, function () { - setTimeout(hide, 100); - }); - }); - - // // 无浮动 - // $noFloat.click(function (e) { - // commandFn = function () { - // $currentImg.css({ - // float: 'none' - // }); - // }; - // customCommand(e, function () { - // setTimeout(hide, 100); - // }); - // }); - - // alignCenter - $alignCenter.click(function (e) { - commandFn = function () { - // 如果 img 增加了链接,那么 img.parent() 就是 a 标签,设置 align 没用的,因此必须找到 P 父节点来设置 align - $currentImg.parents('p').css({ - 'text-align': 'center' - }).attr('align', 'center'); - }; - customCommand(e, function () { - setTimeout(hide, 100); - }); - }); - - // link - // 显示链接input - $link.click(function (e) { - e.preventDefault(); - - // 获取当前链接,并显示 - currentLink = imgLink(e); - $linkInput.val(currentLink); - - $menuContainer.hide(); - $linkInputContainer.show(); - }); - // 设置链接 - $linkBtnSubmit.click(function (e) { - e.preventDefault(); - - let url = $.trim($linkInput.val()); - if (url) { - // 设置链接,同时会自动更新 currentLink 的值 - imgLink(e, url); - } - - // 隐藏 toolbar - setTimeout(hide); - }); - // 取消设置链接 - $linkBtnCancel.click(function (e) { - e.preventDefault(); - - // 重置链接 input - $linkInput.val(currentLink); - - $menuContainer.show(); - $linkInputContainer.hide(); - }); - - // unlink - $unLink.click(function (e) { - e.preventDefault(); - - // 执行 unlink - imgLink(e, ''); - - // 隐藏 toolbar - setTimeout(hide); - }); - } - - // 绑定drag事件 - function bindDragEvent() { - let _x, _y; - let dragMarginLeft, dragMarginTop; - let imgWidth, imgHeight; - - function mousemove(e) { - let diffX, diffY; - - // 计算差额 - diffX = e.pageX - _x; - diffY = e.pageY - _y; - - // --------- 计算拖拽点的位置 --------- - let currentDragMarginLeft = dragMarginLeft + diffX; - let currentDragMarginTop = dragMarginTop + diffY; - $dragPoint.css({ - 'margin-left': currentDragMarginLeft, - 'margin-top': currentDragMarginTop - }); - - // --------- 计算图片的大小 --------- - let currentImgWidth = imgWidth + diffX; - let currentImggHeight = imgHeight + diffY; - $currentImg && $currentImg.css({ - width: currentImgWidth, - height: currentImggHeight - }); - } - - $dragPoint.on('mousedown', function (e) { - if (!$currentImg) { - return; - } - // 当前鼠标位置 - _x = e.pageX; - _y = e.pageY; - - // 当前拖拽点的位置 - dragMarginLeft = parseFloat($dragPoint.css('margin-left'), 10); - dragMarginTop = parseFloat($dragPoint.css('margin-top'), 10); - - // 当前图片的大小 - imgWidth = $currentImg.width(); - imgHeight = $currentImg.height(); - - // 隐藏 $toolbar - $toolbar.hide(); - - // 绑定计算事件 - E.$document.on('mousemove._dragResizeImg', mousemove); - E.$document.on('mouseup._dragResizeImg', function (e) { - // 取消绑定 - E.$document.off('mousemove._dragResizeImg'); - E.$document.off('mouseup._dragResizeImg'); - - // 隐藏,并还原拖拽点的位置 - hide(); - $dragPoint.css({ - 'margin-left': dragMarginLeft, - 'margin-top': dragMarginTop - }); - - // 记录 - isOnDrag = false; - }); - - // 记录 - isOnDrag = true; - }); - } - - // 显示 toolbar - function show() { - if (editor._disabled) { - // 编辑器已经被禁用,则不让显示 - return; - } - if ($currentImg == null) { - return; - } - $currentImg.addClass('clicked'); - let imgPosition = $currentImg.position(); - let imgTop = imgPosition.top; - let imgLeft = imgPosition.left; - let imgHeight = $currentImg.outerHeight(); - let imgWidth = $currentImg.outerWidth(); - - - // --- 定位 dragpoint --- - $dragPoint.css({ - top: imgTop + imgHeight, - left: imgLeft + imgWidth - }); - - // --- 定位 toolbar --- - - // 计算初步结果 - let top = imgTop + imgHeight; - let left = imgLeft; - let marginLeft = 0; - - let txtTop = $currentTxt.position().top; - let txtHeight = $currentTxt.outerHeight(); - if (top > (txtTop + txtHeight)) { - // top 不得超出编辑范围 - top = txtTop + txtHeight; - } else { - // top 超出编辑范围,dragPoint就不显示了 - $dragPoint.show(); - } - - // 显示(方便计算 margin) - $toolbar.show(); - - // 计算 margin - let width = $toolbar.outerWidth(); - marginLeft = imgWidth / 2 - width / 2; - - // 定位 - $toolbar.css({ - top: top + 5, - left: left, - 'margin-left': marginLeft - }); - // 如果定位太靠左了 - if (marginLeft < 0) { - // 得到三角形的margin-left - $toolbar.css('margin-left', '0'); - $triangle.hide(); - } else { - $triangle.show(); - } - - // disable 菜单 - editor.disableMenusExcept(); - } - - // 隐藏 toolbar - function hide() { - if ($currentImg == null) { - return; - } - $currentImg.removeClass('clicked'); - $currentImg = null; - - $toolbar.hide(); - $dragPoint.hide(); - - // enable 菜单 - editor.enableMenusExcept(); - } - - // 判断img是否是一个表情 - function isEmotion(imgSrc) { - let result = false; - if (!editor.emotionUrls) { - return result; - } - $.each(editor.emotionUrls, function (index, url) { - let flag = false; - if (imgSrc === url) { - result = true; - flag = true; - } - if (flag) { - return false; // break 循环 - } - }); - return result; - } - - // click img 事件 - $currentTxt.on('mousedown', 'img', function (e) { - e.preventDefault(); - }).on('click', 'img', function (e) { - let $img = $(e.currentTarget); - let src = $img.attr('src'); - - if (!src || isEmotion(src)) { - // 是一个表情图标 - return; - } - - // ---------- 不是表情图标 ---------- - - // 渲染 - render(); - - if ($currentImg && ($currentImg.get(0) === $img.get(0))) { - setTimeout(hide, 100); - return; - } - - // 显示 toolbar - $currentImg = $img; - show(); - - // 默认显示menuContainer,其他默认隐藏 - $menuContainer.show(); - $linkInputContainer.hide(); - - // 阻止冒泡 - e.preventDefault(); - e.stopPropagation(); - - }).on('click keydown scroll', function (e) { - if (!isOnDrag) { - setTimeout(hide, 100); - } - }); - - }); - - }); -// 编辑区域 link toolbar - _e(function (E, $) { - E.plugin(function () { - let editor = this; - let lang = editor.config.lang; - let $txt = editor.txt.$txt; - - // 当前命中的链接 - let $currentLink; - - let $toolbar = $('
'); - let $triangle = $('
'); - let $triggerLink = $(' ' + lang.openLink + ''); - let isRendered; - - // 记录当前的显示/隐藏状态 - let isShow = false; - - let showTimeoutId, hideTimeoutId; - let showTimeoutIdByToolbar, hideTimeoutIdByToolbar; - - // 渲染 dom - function render() { - if (isRendered) { - return; - } - - $toolbar.append($triangle) - .append($triggerLink); - - editor.$editorContainer.append($toolbar); - - isRendered = true; - } - - // 定位 - function setPosition() { - if (!$currentLink) { - return; - } - - let position = $currentLink.position(); - let left = position.left; - let top = position.top; - let height = $currentLink.height(); - - // 初步计算top值 - let topResult = top + height + 5; - - // 判断 toolbar 是否超过了编辑器区域的下边界 - let menuHeight = editor.menuContainer.height(); - let txtHeight = editor.txt.$txt.outerHeight(); - if (topResult > menuHeight + txtHeight) { - topResult = menuHeight + txtHeight + 5; - } - - // 最终设置 - $toolbar.css({ - top: topResult, - left: left - }); - } - - // 显示 toolbar - function show() { - if (isShow) { - return; - } - - if (!$currentLink) { - return; - } - - render(); - - $toolbar.show(); - - // 设置链接 - let href = $currentLink.attr('href'); - $triggerLink.attr('href', href); - - // 定位 - setPosition(); - - isShow = true; - } - - // 隐藏 toolbar - function hide() { - if (!isShow) { - return; - } - - if (!$currentLink) { - return; - } - - $toolbar.hide(); - isShow = false; - } - - // $txt 绑定事件 - $txt.on('mouseenter', 'a', function (e) { - // 延时 500ms 显示toolbar - if (showTimeoutId) { - clearTimeout(showTimeoutId); - } - showTimeoutId = setTimeout(function () { - let a = e.currentTarget; - let $a = $(a); - $currentLink = $a; - - let $img = $a.children('img'); - if ($img.length) { - // 该链接下包含一个图片 - - // 图片点击时,隐藏toolbar - $img.click(function (e) { - hide(); - }); - - if ($img.hasClass('clicked')) { - // 图片还处于clicked状态,则不显示toolbar - return; - } - } - - // 显示toolbar - show(); - }, 500); - }).on('mouseleave', 'a', function (e) { - // 延时 500ms 隐藏toolbar - if (hideTimeoutId) { - clearTimeout(hideTimeoutId); - } - hideTimeoutId = setTimeout(hide, 500); - }).on('click keydown scroll', function (e) { - setTimeout(hide, 100); - }); - // $toolbar 绑定事件 - $toolbar.on('mouseenter', function (e) { - // 先中断掉 $txt.mouseleave 导致的隐藏 - if (hideTimeoutId) { - clearTimeout(hideTimeoutId); - } - }).on('mouseleave', function (e) { - // 延时 500ms 显示toolbar - if (showTimeoutIdByToolbar) { - clearTimeout(showTimeoutIdByToolbar); - } - showTimeoutIdByToolbar = setTimeout(hide, 500); - }); - }); - }); -// menu吸顶 - _e(function (E, $) { - - E.plugin(function () { - let editor = this; - let menuFixed = editor.config.menuFixed; - if (menuFixed === false || typeof menuFixed !== 'number') { - // 没有配置菜单吸顶 - return; - } - let bodyMarginTop = parseFloat(E.$body.css('margin-top'), 10); - if (isNaN(bodyMarginTop)) { - bodyMarginTop = 0; - } - - let $editorContainer = editor.$editorContainer; - let editorTop = $editorContainer.offset().top; - let editorHeight = $editorContainer.outerHeight(); - - let $menuContainer = editor.menuContainer.$menuContainer; - let menuCssPosition = $menuContainer.css('position'); - let menuCssTop = $menuContainer.css('top'); - let menuTop = $menuContainer.offset().top; - let menuHeight = $menuContainer.outerHeight(); - - let $txt = editor.txt.$txt; - - E.$window.scroll(function () { - //全屏模式不支持 - if (editor.isFullScreen) { - return; - } - - let sTop = E.$window.scrollTop(); - - // 需要重新计算宽度,因为浏览器可能此时出现滚动条 - let menuWidth = $menuContainer.width(); - - // 如果 menuTop === 0 说明此前编辑器一直隐藏,后来显示出来了,要重新计算相关数据 - if (menuTop === 0) { - menuTop = $menuContainer.offset().top; - editorTop = $editorContainer.offset().top; - editorHeight = $editorContainer.outerHeight(); - menuHeight = $menuContainer.outerHeight(); - } - - if (sTop >= menuTop && sTop + menuFixed + menuHeight + 30 < editorTop + editorHeight) { - // 吸顶 - $menuContainer.css({ - position: 'fixed', - top: menuFixed - }); - - // 固定宽度 - $menuContainer.width(menuWidth); - - // 增加body margin-top - E.$body.css({ - 'margin-top': bodyMarginTop + menuHeight - }); - - // 记录 - if (!editor._isMenufixed) { - editor._isMenufixed = true; - } - } else { - // 取消吸顶 - $menuContainer.css({ - position: menuCssPosition, - top: menuCssTop - }); - - // 取消宽度固定 - $menuContainer.css('width', '100%'); - - // 还原 body margin-top - E.$body.css({ - 'margin-top': bodyMarginTop - }); - - // 撤销记录 - if (editor._isMenufixed) { - editor._isMenufixed = false; - } - } - }); - }); - - }); -// 缩进 菜单插件 - _e(function (E, $) { - - // 用 createMenu 方法创建菜单 - E.createMenu(function (check) { - - // 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看 - let menuId = 'indent'; - - // check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。 - if (!check(menuId)) { - return; - } - - // this 指向 editor 对象自身 - let editor = this; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, // 编辑器对象 - id: menuId, // 菜单id - title: '缩进', // 菜单标题 - - // 正常状态和选中装下的dom对象,样式需要自定义 - $domNormal: $(''), - $domSelected: $('') - }); - - // 菜单正常状态下,点击将触发该事件 - menu.clickEvent = function (e) { - let elem = editor.getRangeElem(); - let p = editor.getSelfOrParentByName(elem, 'p'); - let $p; - - if (!p) { - // 未找到 p 元素,则忽略 - return e.preventDefault(); - } - $p = $(p); - - // 使用自定义命令 - function commandFn() { - $p.css('text-indent', '2em'); - } - - editor.customCommand(e, commandFn); - }; - - // 菜单选中状态下,点击将触发该事件 - menu.clickEventSelected = function (e) { - let elem = editor.getRangeElem(); - let p = editor.getSelfOrParentByName(elem, 'p'); - let $p; - - if (!p) { - // 未找到 p 元素,则忽略 - return e.preventDefault(); - } - $p = $(p); - - // 使用自定义命令 - function commandFn() { - $p.css('text-indent', '0'); - } - - editor.customCommand(e, commandFn); - }; - - // 根据当前选区,自定义更新菜单的选中状态或者正常状态 - menu.updateSelectedEvent = function () { - // 获取当前选区所在的父元素 - let elem = editor.getRangeElem(); - let p = editor.getSelfOrParentByName(elem, 'p'); - let $p; - let indent; - - if (!p) { - // 未找到 p 元素,则标记为未处于选中状态 - return false; - } - $p = $(p); - indent = $p.css('text-indent'); - - if (!indent || indent === '0px') { - // 得到的p,text-indent 属性是 0,则标记为未处于选中状态 - return false; - } - - // 找到 p 元素,并且 text-indent 不是 0,则标记为选中状态 - return true; - }; - - // 增加到editor对象中 - editor.menus[menuId] = menu; - }); - - }); -// 行高 菜单插件 - _e(function (E, $) { - - // 用 createMenu 方法创建菜单 - E.createMenu(function (check) { - - // 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看 - let menuId = 'lineheight'; - - // check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。 - if (!check(menuId)) { - return; - } - - // this 指向 editor 对象自身 - let editor = this; - - // 由于浏览器自身不支持 lineHeight 命令,因此要做一个hook - editor.commandHooks.lineHeight = function (value) { - let rangeElem = editor.getRangeElem(); - let targetElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,pre'); - if (!targetElem) { - return; - } - $(targetElem).css('line-height', value + ''); - }; - - // 创建 menu 对象 - let menu = new E.Menu({ - editor: editor, // 编辑器对象 - id: menuId, // 菜单id - title: '行高', // 菜单标题 - commandName: 'lineHeight', // 命令名称 - - // 正常状态和选中装下的dom对象,样式需要自定义 - $domNormal: $(''), - $domSelected: $('') - }); - - // 数据源 - let data = { - // 格式: 'value' : 'title' - '1.0': '1.0倍', - '1.5': '1.5倍', - '1.8': '1.8倍', - '2.0': '2.0倍', - '2.5': '2.5倍', - '3.0': '3.0倍' - }; - - // 为menu创建droplist对象 - let tpl = '{#title}'; - menu.dropList = new E.DropList(editor, menu, { - data: data, // 传入数据源 - tpl: tpl // 传入模板 - }); - - // 增加到editor对象中 - editor.menus[menuId] = menu; - - }); - - }); -// 自定义上传 - _e(function (E, $) { - - E.plugin(function () { - - let editor = this; - let customUpload = editor.config.customUpload; - if (!customUpload) { - return; - } else if (editor.config.uploadImgUrl) { - alert('自定义上传无效,详看浏览器日志console.log'); - E.error('已经配置了 uploadImgUrl ,就不能再配置 customUpload ,两者冲突。将导致自定义上传无效。'); - return; - } - - let $uploadContent = editor.$uploadContent; - if (!$uploadContent) { - E.error('自定义上传,无法获取 editor.$uploadContent'); - } - - // UI - let $uploadIcon = $('
'); - $uploadContent.append($uploadIcon); - - // 设置id,并暴露 - let btnId = 'upload' + E.random(); - let containerId = 'upload' + E.random(); - $uploadIcon.attr('id', btnId); - $uploadContent.attr('id', containerId); - - editor.customUploadBtnId = btnId; - editor.customUploadContainerId = containerId; - }); - - }); -// 版权提示 - _e(function (E, $) { - //E.info('本页面富文本编辑器由 WangEditor 提供 http://wangeditor.github.io/ '); - }); - - // 最终返回WangEditor构造函数 - return WangEditor; -}); diff --git a/src/common/fork/wangeditor/css/wangEditor.less b/src/common/fork/wangeditor/css/wangEditor.less deleted file mode 100644 index 6ee6acf..0000000 --- a/src/common/fork/wangeditor/css/wangEditor.less +++ /dev/null @@ -1,810 +0,0 @@ - -// ---------- begin 全局颜色配置 ------------ - -/* 编辑器边框颜色 */ -@border-color: #ccc; - -/* 菜单颜色、上边框颜色 */ -@fore-color: #666; - -/* 菜单选中状态的颜色 */ -@selected-color: #1e88e5; - -/* input focus 时的颜色 */ -@focus-input-color: #1e88e5; - -/* 按钮颜色 */ -@button-color: #1e88e5; - -/* tab selected 状态下的颜色 */ -@selected-tab-color: #1e88e5; - -// ---------- end 全局颜色配置 ------------ - - -.wangEditor-container { - position: relative; - background-color: #fff; - border: 1px solid @border-color; - z-index: 1; - width: 100%; - - a:focus, - button:focus{ - outline:none; - } - - //&,* { - // margin: 0; - // padding: 0; - // box-sizing: border-box; - // line-height: 1; - //} - - img { - border: none; - } - - .clearfix:after { - content: ''; - display: table; - clear: both; - } - .clearfix { - *zoom: 1; - } - - textarea { - border: none; - &:focus{ - outline: none; - } - } - - // 显示p head 高度的 tip - .height-tip { - position: absolute; - width: 3px; - background-color: #ccc; - left: 0; - transition: top .2s; - } - - // 设置 img table 的 toolbar - .txt-toolbar { - position: absolute; - background-color: #fff; - padding: 3px 5px; - border-top: 2px solid @fore-color; - box-shadow: 1px 3px 3px #999; - - // for IE8 - border-left: 1px\9 solid\9 #ccc\9; - border-bottom: 1px\9 solid\9 #999\9; - border-right: 1px\9 solid\9 #999\9; - - // 小三角 - .tip-triangle { - display: block; - position: absolute; - width: 0; - height: 0; - border: 5px solid; - border-color: transparent transparent @fore-color transparent; - top: -12px; - left: 50%; - margin-left: -5px; - } - - a { - color: @fore-color; - display: inline-block; - margin: 0 3px; - padding: 5px; - text-decoration: none; - border-radius: 3px; - - &:hover { - background-color: #f1f1f1; - } - } - } - // 图品拖拽大小 - .img-drag-point { - display: block; - position: absolute; - width: 12px; - height: 12px; - border-radius: 50%; - cursor: se-resize; - background-color: @fore-color; - margin-left: -6px; - margin-top: -6px; - box-shadow: 1px 1px 5px #999; - } - - // 进度条 - .wangEditor-upload-progress { - position: absolute; - height: 1px; - background: #1e88e5; - width: 0; - display: none; - -webkit-transition: width .5s; - -o-transition: width .5s; - transition: width .5s; - } -} -.wangEditor-fullscreen { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; -} -.wangEditor-container { - .code-textarea { - resize: none; - width: 100%; - font-size: 14px; - line-height: 1.5; - font-family: 'Verdana'; - color: #333; - padding: 0 15px 0 15px; - } -} -.wangEditor-menu-container { - - width: 100%; - border-bottom: 1px solid #f1f1f1; - background-color: #fff; - - a { - text-decoration: none; - } - - // 菜单组 - .menu-group { - float: left; - padding: 0 8px; - border-right: 1px solid #f1f1f1; - } - - // 单个菜单容器 - .menu-item { - float: left; - position: relative; - text-align: center; - height: 31px; - width: 35px; - - &:hover { - background-color: #f1f1f1; - } - - // 菜单 - a { - display: block; - text-align: center; - color: @fore-color; - width: 100%; - padding: 8px 0; - font-size: 0.9em; - } - - // 菜单选中状态 - .selected { - color: @selected-color; - } - - // 激活状态 - .active { - background-color: #f1f1f1; - } - - // 禁用状态 - .disable { - opacity: 0.5; - filter: Alpha(opacity=50); - } - } - - // tip提示 - .menu-tip { - display: block; - position: absolute; - z-index: 20; - width: 60px; - text-align: center; - background-color: @fore-color; - color: #fff; - padding: 7px 0; - font-size: 12px; - top: 100%; - left: 50%; - margin-left: -30px; - border-radius: 2px; - box-shadow: 1px 1px 5px #999; - - display: none; - - /*// 小三角 - .tip-triangle { - display: block; - position: absolute; - width: 0; - height: 0; - border:5px solid; - border-color: transparent transparent @fore-color transparent; - top: -10px; - left: 50%; - margin-left: -5px; - }*/ - } - .menu-tip-40 { - width: 40px; - margin-left: -20px; - } - .menu-tip-50 { - width: 50px; - margin-left: -25px; - } -} -.wangEditor-menu-shadow { - /*border-bottom-width: 0;*/ - border-bottom: 1px\9 solid\9 #f1f1f1\9; - box-shadow: 0 1px 3px #999; -} -.wangEditor-container { - .wangEditor-txt{ - width: 100%; - text-align: left; - padding: 15px; - padding-top: 0; - margin-top: 5px; - overflow-y: auto; - - p,h1,h2,h3,h4,h5 { - margin: 10px 0; - line-height: 1.8; - - * { - line-height: 1.8; - } - } - - ul, ol { - padding-left: 20px; - } - - img { - cursor: pointer; - } - img.clicked { - box-shadow: 1px 1px 10px #999; - } - - table.clicked { - box-shadow: 1px 1px 10px #999; - } - - pre code { - line-height: 1.5; - } - - &:focus{ - outline: none; - } - } -} -.wangEditor-container { - .wangEditor-txt { - blockquote { - display: block; - border-left: 8px solid #d0e5f2; - padding: 5px 10px; - margin: 10px 0; - line-height: 1.4; - font-size: 100%; - background-color: #f1f1f1; - } - table { - border: none; - border-collapse: collapse; - } - table td, - table th { - border: 1px solid #999; - padding: 3px 5px; - min-width: 50px; - height: 20px; - } - pre { - border: 1px solid #ccc; - background-color: #f8f8f8; - padding: 10px; - margin: 5px 0px; - font-size: 0.8em; - border-radius: 3px; - } - } -} -.wangEditor-drop-list { - display: none; - position: absolute; - background-color: #fff; - overflow: hidden; - z-index: 10; - - transition: height .7s; - - border-top: 1px solid #f1f1f1; - box-shadow: 1px 3px 3px #999; - - // for IE8 - border-left: 1px\9 solid\9 #ccc\9; - border-bottom: 1px\9 solid\9 #999\9; - border-right: 1px\9 solid\9 #999\9; - - a { - text-decoration: none; - display: block; - color: @fore-color; - padding: 3px 5px; - - &:hover { - background-color: #f1f1f1; - } - } -} -.wangEditor-drop-panel, -.txt-toolbar { - display: none; - position: absolute; - padding: 10px; - font-size: 14px; - /*border: 1px\9 solid\9 #cccccc\9;*/ - - background-color: #fff; - z-index: 10; - - border-top: 2px solid @fore-color; - box-shadow: 1px 3px 3px #999; - - // for IE8 - border-left: 1px\9 solid\9 #ccc\9; - border-bottom: 1px\9 solid\9 #999\9; - border-right: 1px\9 solid\9 #999\9; - - // 小三角 - .tip-triangle { - display: block; - position: absolute; - width: 0; - height: 0; - border: 5px solid; - border-color: transparent transparent @fore-color transparent; - top: -12px; - left: 50%; - margin-left: -5px; - } - - a { - text-decoration: none; - } - - // 输入框 - input[type=text] { - border: none; - border-bottom: 1px solid #ccc; - font-size: 14px; - height: 20px; - color: #333; - padding: 3px 0; - - &:focus{ - outline: none; - border-bottom: 2px solid @focus-input-color; - } - } - input[type=text].block { - display: block; - width: 100%; - } - textarea { - border: 1px solid #ccc; - &:focus { - outline: none; - border-color: @focus-input-color; - } - } - - // 按钮 - button { - font-size: 14px; - color: @button-color; - border: none; - padding: 10px; - background-color: #fff; - cursor: pointer; - border-radius: 3px; - - &:hover { - background-color: #f1f1f1; - } - &:focus{ - outline: none; - } - } - button.right { - float: right; - margin-left: 10px; - } - button.gray { - color: #999; - } - button.link { - padding: 5px 10px; - &:hover { - background-color: #fff; - text-decoration: underline; - } - } - - // 颜色块 - .color-item { - display: block; - float: left; - width: 25px; - height: 25px; - text-align: center; - padding: 2px; - border-radius: 2px; - text-decoration: underline; - - &:hover { - background-color: #f1f1f1; - } - } - - // 列表 - .list-menu-item { - display: block; - float: left; - color: #333; - padding: 5px 5px; - border-radius: 2px; - - &:hover { - background-color: #f1f1f1; - } - } - - // 表格 - table.choose-table { - border: none; - border-collapse: collapse; - - td { - border: 1px solid #ccc; - width: 16px; - height: 12px; - } - td.active { - background-color: #ccc; - opacity: .5; - filter: Alpha(opacity=50); - } - } - - // tab - .panel-tab { - .tab-container { - margin-bottom: 5px; - - a { - display: inline-block; - color: #999; - text-align: center; - margin: 0 5px; - padding: 5px 5px; - } - - a.selected { - color: @selected-tab-color; - border-bottom: 2px solid @selected-tab-color; - } - } - .content-container { - .content { - display: none; - - a { - display: inline-block; - margin: 2px; - padding: 2px; - border-radius: 2px; - - &:hover { - background-color: #f1f1f1; - } - } - } - .selected { - display: block; - } - } - .emotion-content-container { - height: 200px; - overflow-y: auto; - } - } - - // 上传图片 - .upload-icon-container { - color: #ccc; - text-align: center; - margin: 20px 20px 15px 20px !important; - padding: 5px !important; - font-size: 65px; - cursor: pointer; - border: 2px dotted #f1f1f1; - display: block !important; - - &:hover { - color: #666; - border-color: #ccc; - } - } -} -.wangEditor-modal { - position: absolute; - top: 50%; - left: 50%; - background-color: #fff; - - border-top: 1px solid #f1f1f1; - box-shadow: 1px 3px 3px #999; - - // for IE8 - border-top: 1px\9 solid\9 #ccc\9; - border-left: 1px\9 solid\9 #ccc\9; - border-bottom: 1px\9 solid\9 #999\9; - border-right: 1px\9 solid\9 #999\9; - - // 关闭按钮 - .wangEditor-modal-close { - position: absolute; - top: 0; - right: 0; - margin-top: -25px; - margin-right: -25px; - font-size: 1.5em; - color: #666; - cursor: pointer; - } - -} -@font-face { - font-family: 'icomoon'; - src:url('../fonts/icomoon.eot?-qdfu1s'); - src:url('../fonts/icomoon.eot?#iefix-qdfu1s') format('embedded-opentype'), - url('../fonts/icomoon.ttf?-qdfu1s') format('truetype'), - url('../fonts/icomoon.woff?-qdfu1s') format('woff'), - url('../fonts/icomoon.svg?-qdfu1s#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="wangeditor-menu-img-"], [class*=" wangeditor-menu-img-"] { - font-family: 'icomoon'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.wangeditor-menu-img-link:before {content: "\e800";} -.wangeditor-menu-img-unlink:before {content: "\e801";} -.wangeditor-menu-img-code:before {content: "\e802";} -.wangeditor-menu-img-cancel:before {content: "\e803";} -.wangeditor-menu-img-terminal:before {content: "\e804";} -.wangeditor-menu-img-angle-down:before {content: "\e805";} -.wangeditor-menu-img-font:before {content: "\e806";} -.wangeditor-menu-img-bold:before {content: "\e807";} -.wangeditor-menu-img-italic:before {content: "\e808";} -.wangeditor-menu-img-header:before {content: "\e809";} -.wangeditor-menu-img-align-left:before {content: "\e80a";} -.wangeditor-menu-img-align-center:before {content: "\e80b";} -.wangeditor-menu-img-align-right:before {content: "\e80c";} -.wangeditor-menu-img-list-bullet:before {content: "\e80d";} -.wangeditor-menu-img-indent-left:before {content: "\e80e";} -.wangeditor-menu-img-indent-right:before {content: "\e80f";} -.wangeditor-menu-img-list-numbered:before {content: "\e810";} -.wangeditor-menu-img-underline:before {content: "\e811";} -.wangeditor-menu-img-table:before {content: "\e812";} -.wangeditor-menu-img-eraser:before {content: "\e813";} -.wangeditor-menu-img-text-height:before {content: "\e814";} -.wangeditor-menu-img-brush:before {content: "\e815";} -.wangeditor-menu-img-pencil:before {content: "\e816";} -.wangeditor-menu-img-minus:before {content: "\e817";} -.wangeditor-menu-img-picture:before {content: "\e818";} -.wangeditor-menu-img-file-image:before {content: "\e819";} -.wangeditor-menu-img-cw:before {content: "\e81a";} -.wangeditor-menu-img-ccw:before {content: "\e81b";} -.wangeditor-menu-img-music:before {content: "\e911";} -.wangeditor-menu-img-play:before {content: "\e912";} -.wangeditor-menu-img-location:before {content: "\e947";} -.wangeditor-menu-img-happy:before {content: "\e9df";} -.wangeditor-menu-img-sigma:before {content: "\ea67";} -.wangeditor-menu-img-enlarge2:before {content: "\e98b";} -.wangeditor-menu-img-shrink2:before {content: "\e98c";} -.wangeditor-menu-img-newspaper:before{content: "\e904";} -.wangeditor-menu-img-camera:before{content: "\e90f";} -.wangeditor-menu-img-video-camera:before{content: "\e914";} -.wangeditor-menu-img-file-zip:before{content: "\e92b";} -.wangeditor-menu-img-stack:before{content: "\e92e";} -.wangeditor-menu-img-credit-card:before{content: "\e93f";} -.wangeditor-menu-img-address-book:before{content: "\e944";} -.wangeditor-menu-img-envelop:before{content: "\e945";} -.wangeditor-menu-img-drawer:before{content: "\e95c";} -.wangeditor-menu-img-download:before{content: "\e960";} -.wangeditor-menu-img-upload:before{content: "\e961";} -.wangeditor-menu-img-lock:before{content: "\e98f";} -.wangeditor-menu-img-unlocked:before{content: "\e990";} -.wangeditor-menu-img-wrench:before{content: "\e991";} -.wangeditor-menu-img-eye:before{content: "\e9ce";} -.wangeditor-menu-img-eye-blocked:before{content: "\e9d1";} -.wangeditor-menu-img-command:before{content: "\ea4e";} -.wangeditor-menu-img-font2:before{content: "\ea5c";} -.wangeditor-menu-img-libreoffice:before{content: "\eade";} -.wangeditor-menu-img-quotes-left:before{content: "\e977";} -.wangeditor-menu-img-strikethrough:before{content: "\ea65";} -.wangeditor-menu-img-desktop:before{content: "\f108";} -.wangeditor-menu-img-tablet:before{content: "\f10a";} -.wangeditor-menu-img-search-plus:before { - content: "\f00e"; -} -.wangeditor-menu-img-search-minus:before { - content: "\f010"; -} -.wangeditor-menu-img-trash-o:before { - content: "\f014"; -} -.wangeditor-menu-img-align-justify:before { - content: "\f039"; -} -.wangeditor-menu-img-arrows-v:before { - content: "\f07d"; -} -.wangeditor-menu-img-sigma2:before { - content: "\ea68"; -} -.wangeditor-menu-img-omega:before { - content: "\e900"; -} -.wangeditor-menu-img-cancel-circle:before { - content: "\e901"; -} -.hljs { - display: block; - overflow-x: auto; - padding: 0.5em; - color: #333; - background: #f8f8f8; - -webkit-text-size-adjust: none; -} - -.hljs-comment, -.diff .hljs-header { - color: #998; - font-style: italic; -} - -.hljs-keyword, -.css .rule .hljs-keyword, -.hljs-winutils, -.nginx .hljs-title, -.hljs-subst, -.hljs-request, -.hljs-status { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-hexcolor, -.ruby .hljs-constant { - color: #008080; -} - -.hljs-string, -.hljs-tag .hljs-value, -.hljs-doctag, -.tex .hljs-formula { - color: #d14; -} - -.hljs-title, -.hljs-id, -.scss .hljs-preprocessor { - color: #900; - font-weight: bold; -} - -.hljs-list .hljs-keyword, -.hljs-subst { - font-weight: normal; -} - -.hljs-class .hljs-title, -.hljs-type, -.vhdl .hljs-literal, -.tex .hljs-command { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-tag .hljs-title, -.hljs-rule .hljs-property, -.django .hljs-tag .hljs-keyword { - color: #000080; - font-weight: normal; -} - -.hljs-attribute, -.hljs-variable, -.lisp .hljs-body, -.hljs-name { - color: #008080; -} - -.hljs-regexp { - color: #009926; -} - -.hljs-symbol, -.ruby .hljs-symbol .hljs-string, -.lisp .hljs-keyword, -.clojure .hljs-keyword, -.scheme .hljs-keyword, -.tex .hljs-special, -.hljs-prompt { - color: #990073; -} - -.hljs-built_in { - color: #0086b3; -} - -.hljs-preprocessor, -.hljs-pragma, -.hljs-pi, -.hljs-doctype, -.hljs-shebang, -.hljs-cdata { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - background: #fdd; -} - -.hljs-addition { - background: #dfd; -} - -.diff .hljs-change { - background: #0086b3; -} - -.hljs-chunk { - color: #aaa; -} diff --git a/src/common/fork/wangeditor/fonts/icomoon.eot b/src/common/fork/wangeditor/fonts/icomoon.eot deleted file mode 100644 index 5d7e64a16b64a0ea0974dd62029105ca91cbf40e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15648 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 diff --git a/src/common/fork/wangeditor/fonts/icomoon.svg b/src/common/fork/wangeditor/fonts/icomoon.svg deleted file mode 100644 index 5d75856..0000000 --- a/src/common/fork/wangeditor/fonts/icomoon.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/common/fork/wangeditor/fonts/icomoon.ttf b/src/common/fork/wangeditor/fonts/icomoon.ttf deleted file mode 100644 index b4ea1e1f26d39e9c00e633e08263ab8879cc1802..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15484 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 Zq3j@g6wh&iz)lMRj1dC0$dK#h{y!taLva8A diff --git a/src/common/fork/wangeditor/fonts/icomoon.woff b/src/common/fork/wangeditor/fonts/icomoon.woff deleted file mode 100644 index 1b16ccb273e3ccad4f9c82a1f161b744e21ba601..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15560 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 - -
-
- - - 最多只能选择 {{max}} 项 - - - 没有符合条件的条目 - - -
-
- -
-
- - - - - - - - diff --git a/src/common/widget/NbTank.vue b/src/common/widget/NbTank.vue deleted file mode 100644 index 22fe582..0000000 --- a/src/common/widget/NbTank.vue +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - diff --git a/src/common/widget/NbTanks.vue b/src/common/widget/NbTanks.vue deleted file mode 100644 index 551700b..0000000 --- a/src/common/widget/NbTanks.vue +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - diff --git a/static/img/file/alien.svg b/static/img/file/alien.svg new file mode 100644 index 0000000..0c4e1cc --- /dev/null +++ b/static/img/file/alien.svg @@ -0,0 +1 @@ + From 960cff221702d1744e79bd346cc682e52056f6fe Mon Sep 17 00:00:00 2001 From: seaheart Date: Thu, 28 Dec 2017 15:21:36 +0800 Subject: [PATCH 07/22] add folder move batch style change. --- src/backyard/matter/List.vue | 1 + src/backyard/matter/widget/FolderTree.vue | 26 ++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/backyard/matter/List.vue b/src/backyard/matter/List.vue index 1b85c28..dacc294 100644 --- a/src/backyard/matter/List.vue +++ b/src/backyard/matter/List.vue @@ -293,6 +293,7 @@ let uuids = that.temporaryMatterUuids.join(',') that.matter.httpMove(uuids, this.targetMatter.uuid, function (response) { Message.success('移动成功!') + that.targetMatter.render(new Matter()) that.refresh() }) } diff --git a/src/backyard/matter/widget/FolderTree.vue b/src/backyard/matter/widget/FolderTree.vue index 5c4d165..1051ae2 100644 --- a/src/backyard/matter/widget/FolderTree.vue +++ b/src/backyard/matter/widget/FolderTree.vue @@ -1,11 +1,11 @@ @@ -52,9 +55,6 @@ default: false } }, - watch: { - - }, methods:{ deepFolderToggle () { this.deepFolder = !this.deepFolder @@ -65,7 +65,6 @@ }, components:{ NbExpanding - }, mounted() { if (!this.matter.uuid) { @@ -95,6 +94,9 @@ background: #eee; } } + .ml23{ + margin-left: 23px; + } } \ No newline at end of file From e8670fa9bab2333ce2c9817e9adf7c8d42d7db3a Mon Sep 17 00:00:00 2001 From: zicla Date: Thu, 28 Dec 2017 16:03:26 +0800 Subject: [PATCH 08/22] Fix the avatar things. --- src/backyard/matter/List.vue | 2 +- src/backyard/matter/widget/MatterImage.vue | 109 +++++++ src/backyard/matter/widget/MatterPanel.vue | 179 ++++++----- src/backyard/preference/Index.vue | 4 +- src/backyard/user/Create.vue | 153 +++++---- src/common/model/matter/Matter.js | 15 +- src/common/model/preference/Preference.js | 12 +- src/common/model/tank/Tank.js | 356 --------------------- src/common/model/user/User.js | 1 + 9 files changed, 294 insertions(+), 537 deletions(-) create mode 100644 src/backyard/matter/widget/MatterImage.vue delete mode 100644 src/common/model/tank/Tank.js diff --git a/src/backyard/matter/List.vue b/src/backyard/matter/List.vue index dacc294..67f1144 100644 --- a/src/backyard/matter/List.vue +++ b/src/backyard/matter/List.vue @@ -24,7 +24,7 @@ diff --git a/src/backyard/matter/widget/MatterImage.vue b/src/backyard/matter/widget/MatterImage.vue new file mode 100644 index 0000000..504ce96 --- /dev/null +++ b/src/backyard/matter/widget/MatterImage.vue @@ -0,0 +1,109 @@ + + + diff --git a/src/backyard/matter/widget/MatterPanel.vue b/src/backyard/matter/widget/MatterPanel.vue index dd5ee2e..1ba220b 100644 --- a/src/backyard/matter/widget/MatterPanel.vue +++ b/src/backyard/matter/widget/MatterPanel.vue @@ -1,13 +1,13 @@ diff --git a/src/backyard/preference/Index.vue b/src/backyard/preference/Index.vue index 8444aeb..c7e59ac 100644 --- a/src/backyard/preference/Index.vue +++ b/src/backyard/preference/Index.vue @@ -65,8 +65,6 @@ diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index ce9fefb..fb37cae 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -1,101 +1,111 @@ diff --git a/src/common/model/matter/Matter.js b/src/common/model/matter/Matter.js index eb0f562..1093766 100644 --- a/src/common/model/matter/Matter.js +++ b/src/common/model/matter/Matter.js @@ -4,6 +4,7 @@ import {getMimeType, MimeUtil} from '../../util/MimeUtil' import {containStr, endWith, getExtension, startWith} from '../../filter/str' import User from '../user/User' import UserInputSelection from '../../../backyard/user/widget/UserInputSelection' +import Vue from "vue" export default class Matter extends BaseEntity { constructor(args) { @@ -70,12 +71,7 @@ export default class Matter extends BaseEntity { getIcon() { if (this.dir) { - if (this.alien) { - return "/static/img/file/alien.svg" - } else { - return "/static/img/file/folder.svg" - } - + return "/static/img/file/folder.svg" } let mimeType = getMimeType(this.name) @@ -292,7 +288,6 @@ export default class Matter extends BaseEntity { let lastSize = 0 that.httpPost(Matter.URL_MATTER_UPLOAD, formData, function (response) { - //上传到tank服务器成功了,更新matterUuid. that.uuid = response.data.data.uuid if (typeof successCallback === "function") { @@ -301,8 +296,6 @@ export default class Matter extends BaseEntity { }, function (response) { - console.log("上传到tank服务器失败", response.data) - console.log(response) that.errorMessage = '上传出错,请稍后重试' that.clear() @@ -353,4 +346,8 @@ export default class Matter extends BaseEntity { } + getDownloadUrl() { + return Vue.http.options.root + '/alien/download/' + this.uuid + '/' + this.name + } + } diff --git a/src/common/model/preference/Preference.js b/src/common/model/preference/Preference.js index 3ef731f..2f34239 100644 --- a/src/common/model/preference/Preference.js +++ b/src/common/model/preference/Preference.js @@ -9,7 +9,6 @@ export default class Preference extends BaseEntity { //logo this.logoUrl = null this.faviconUrl = null - this.faviconTankUuid = null //底部第一行文字 this.footerLine1 = null @@ -28,8 +27,6 @@ export default class Preference extends BaseEntity { render (obj) { super.render(obj) - this.renderEntity('logoTank', Tank) - this.renderEntity('faviconTank', Tank) } getForm () { @@ -43,14 +40,7 @@ export default class Preference extends BaseEntity { } validate(){ - if (this.logoTank) { - this.logoTankUuid = this.logoTank.uuid - this.logoUrl = this.logoTank.url - } - if (this.faviconTank) { - this.faviconTankUuid = this.faviconTank.uuid - this.faviconUrl = this.faviconTank.url - } + return super.validate() } diff --git a/src/common/model/tank/Tank.js b/src/common/model/tank/Tank.js deleted file mode 100644 index fbceb86..0000000 --- a/src/common/model/tank/Tank.js +++ /dev/null @@ -1,356 +0,0 @@ -import BaseEntity from '../base/BaseEntity' -import {containStr, endWith, getExtension, startWith} from '../../filter/str' -import Vue from 'vue' -import {getMimeType} from "../../util/MimeUtil"; - -//当前tank处于怎样的步骤中 -let Procedure = { - 'FREE': 'FREE', - 'UPLOADING': 'UPLOADING', - 'DOWNLOADING': 'DOWNLOADING' -} - -export default class Tank extends BaseEntity { - constructor(filter = '*', privacy = true, maxSize = 0, uploadHint = null) { - super() - - /* - 此部分是数据库中的字段 - */ - this.userUuid = null - this.name = null - this.matterUuid = null - this.size = 0 - this.privacy = privacy - this.url = null - this.remark = null - this.confirmed = false - - /* - 此部分是上传的地址和token,临时信息。 - */ - this.uploadTokenUuid = null - this.uploadUrl = null - - - /* - 这部分是辅助UI的字段信息 - */ - //文件的类型,这个一般是由文件名推测出来的。 - this.type = null - //允许用户选择的文件类型 - this.filter = filter - //本地字段 - //允许上传的最大大小。 - this.maxSize = maxSize - //给用户的提示文字 - this.uploadHint = uploadHint - //浏览器中选择好的原生file,未作任何处理。 - this.file = null - this.disabled = false - //当前文件处于哪一个步骤中 - this.procedure = Procedure.FREE - //当前上传进度的数值 0-1之间 - this.progress = 0 - //实时上传速度 byte/s - this.speed = 0 - - } - - static URL_UPLOAD = '/matter/upload' - - render(obj) { - super.render(obj) - - this.type = getMimeType(this.name) - } - - getForm() { - - return { - filename: this.name, - privacy: this.privacy, - size: this.size - } - - } - - //从file中装填metaData - validate() { - - if (!this.file) { - this.errorMessage = '请选择上传文件' - return false - } - - this.name = this.file.name - if (!this.name) { - this.errorMessage = '请选择上传文件' - return false - } - - - if(this.file.size > this.maxSize){ - this.errorMessage = '文件超出指定大小' - return false - } - - this.size = this.file.size - this.type = getMimeType(this.name) - - this.type = this.file.type - if (!this.type) { - this.type = getMimeType(this.name) - } - this.errorMessage = null - return true - - } - - //具有了这最基本的3种属性,才能叫做“存在” - exist() { - return this.name && this.size && this.confirmed - } - - //公有图片链接。 - publicImgUrl() { - if (!this.exist()) { - return null - } - if (!this.privacy && this.confirmed) { - if (startWith(this.type, 'image')) { - return this.url - } else { - return null - } - } else { - return null - } - } - - //文件图标。在富文本编辑器中,我们使用图片,其他地方使用图标来表示。 - fileIcon(inEditor = false) { - - let host = window.location.protocol + "//" + window.location.host; - //给不同的文件准备不同的图标 - if (startWith(this.type, 'application/pdf')) { - if (inEditor) { - return host + '/static/img/file/pdf.png' - } else { - return 'fa fa-file-pdf-o color-pdf' - } - } - if (startWith(this.type, 'application/msword') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')) { - if (inEditor) { - return host + '/static/img/file/doc.png' - } else { - return 'fa fa-file-word-o color-doc' - } - } - if (startWith(this.type, 'application/vnd.ms-powerpoint') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')) { - if (inEditor) { - return host + '/static/img/file/ppt.png' - } else { - return 'fa fa-file-powerpoint-o color-ppt' - } - } - if (startWith(this.type, 'application/vnd.ms-excel') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) { - if (inEditor) { - return host + '/static/img/file/xls.png' - } else { - return 'fa fa-file-excel-o color-xls' - } - } - if (startWith(this.type, 'audio')) { - if (inEditor) { - return host + '/static/img/file/audio.png' - } else { - return 'fa fa-file-audio-o color-audio' - } - } - if (startWith(this.type, 'video')) { - if (inEditor) { - return host + '/static/img/file/video.png' - } else { - return 'fa fa-file-movie-o color-video' - } - } - if (startWith(this.type, 'text')) { - if (inEditor) { - return host + '/static/img/file/text.png' - } else { - return 'fa fa-file-text-o color-text' - } - } - if (startWith(this.type, 'image')) { - if (inEditor) { - return host + '/static/img/file/image.png' - } else { - return 'fa fa-file-image-o color-image' - } - } - if (endWith(this.name, 'zip') || endWith(this.name, 'rar') || endWith(this.name, '7z') || endWith(this.name, 'gz')) { - if (inEditor) { - return host + '/static/img/file/archive.png' - } else { - return 'fa fa-file-archive-o color-archive' - } - } - - if (inEditor) { - return host + '/static/img/file/file.png' - } else { - return 'fa fa-file-o text-success' - } - - } - - //验证过滤器有没有误填写,这个方法主要给开发者使用。 - validateFilter() { - - let filter = this.filter - if (filter === null || filter === '') { - this.errorMessage = '过滤器设置错误,请检查-1' - console.error('过滤器设置错误,请检查.-1') - return false - } - if (filter !== '*') { - let regex1 = /^(image|audio|video|text)(\|(image|audio|video|text))*$/g - let regex2 = /^(\.[\w]+)(\|\.[\w]+)*$/ - // 测试几种特殊类型 image|audio|video|text - - if (!regex1.test(filter)) { - //测试后缀名 - if (!regex2.test(filter)) { - this.errorMessage = '过滤器设置错误,请检查-2' - console.error('过滤器设置错误,请检查.-2') - return false - } - } - } - - //validate privacy - let privacy = this.privacy - if (privacy !== true) { - if (privacy !== false) { - this.errorMessage = 'privacy属性为Boolean类型' - console.error('privacy属性为Boolean类型.') - return false - } - } - - return true - } - - //验证用户上传的文件是否符合过滤器 - validateFileType() { - if (!this.filter) { - this.errorMessage = '该过滤条件有问题' - return false - } - if (this.filter === '*') { - this.errorMessage = null - return true - } - - let extension = getExtension(this.name) - let simpleType = this.type.substring(0, this.type.indexOf('/')) - - //专门解决android微信浏览器中名字乱命名的bug. - if (startWith(this.name, 'image%3A')) { - extension = 'jpg' - simpleType = 'image' - } else if (startWith(this.name, 'video%3A')) { - extension = 'mp4' - simpleType = 'video' - } else if (startWith(this.name, 'audio%3A')) { - extension = 'mp3' - simpleType = 'audio' - } - - if (containStr(this.filter, extension)) { - this.errorMessage = null - return true - } - - if (simpleType) { - if (containStr(this.filter, simpleType)) { - this.errorMessage = null - return true - } - } - this.errorMessage = '您上传的文件格式不符合要求' - return false - } - - //在上传的途中,清空一切,从头开始。 - clear() { - - //filter,privacy不变 - let newTank = new Tank() - newTank.filter = this.filter - newTank.privacy = this.privacy - newTank.errorMessage = this.errorMessage - newTank.uploadHint = this.uploadHint - newTank.maxSize = this.maxSize - - this.render(newTank) - - } - - //文件上传 - httpUpload(successCallback, failureCallback) { - - let that = this - - //验证是否装填好 - if (!this.validate()) { - return - } - - //验证用户填写的过滤条件是否正确 - if (!this.validateFilter()) { - return - } - - //验证是否满足过滤器 - if (!this.validateFileType()) { - return - } - - //(兼容性:chrome,ff,IE9及以上) - let formData = new FormData() - - formData.append('uploadTokenUuid', that.uploadTokenUuid) - formData.append('file', that.file) - - that.procedure = Procedure.UPLOADING - that.httpPost(that.uploadUrl, formData, function (response) { - - //上传到tank服务器成功了,更新matterUuid. - that.matterUuid = response.data.data.uuid - - }, function (response) { - - console.log("上传到tank服务器失败", response.data) - console.log(response) - - that.procedure = Procedure.FREE - that.errorMessage = '上传出错,请稍后重试' - that.clear() - - that.defaultErrorHandler(response, failureCallback) - - }, { - progress: function (event) { - - //上传进度。 - that.progress = event.loaded / event.total - - } - }) - - } - -} -Tank.prototype.Procedure = Procedure diff --git a/src/common/model/user/User.js b/src/common/model/user/User.js index 60d5d8b..c2c4f83 100644 --- a/src/common/model/user/User.js +++ b/src/common/model/user/User.js @@ -205,6 +205,7 @@ export default class User extends BaseEntity { getForm() { let form = { + avatarUrl: this.avatarUrl, username: this.username, password: this.password, email: this.email, From df37bc9e7dd8a712a980db7ba4a853fa860f1eb9 Mon Sep 17 00:00:00 2001 From: zicla Date: Thu, 28 Dec 2017 17:34:15 +0800 Subject: [PATCH 09/22] Fix the avatar save to localStorage things. --- src/backyard/user/Create.vue | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index fb37cae..9ca1e50 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -130,6 +130,13 @@ Notification.success({ message: that.user.editMode ? '修改用户成功!' : '创建用户成功!' }) + + + if (that.currentUser.uuid === that.user.uuid) { + that.currentUser.innerLogin(response) + } + + that.$router.go(-1) }) } From c91a0081bcbcfc8fd45a3cf291f5e09d8804d2c3 Mon Sep 17 00:00:00 2001 From: seaheart Date: Thu, 28 Dec 2017 18:20:33 +0800 Subject: [PATCH 10/22] add preference change. --- src/assets/css/global/variables.less | 3 ++ src/assets/css/inspinia/base.less | 6 +++ src/backyard/Frame.vue | 8 ++-- src/backyard/layout/BottomNavigation.vue | 60 ++++++++++++++++++++++++ src/backyard/layout/SideNavigation.vue | 2 +- src/backyard/preference/Edit.vue | 31 +++++++++++- 6 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/backyard/layout/BottomNavigation.vue diff --git a/src/assets/css/global/variables.less b/src/assets/css/global/variables.less index 28bb139..bfcb9c1 100644 --- a/src/assets/css/global/variables.less +++ b/src/assets/css/global/variables.less @@ -8,4 +8,7 @@ //上方导航栏高度 @frame-header-height: 80px; +//下方蓝眼博客高度 +@power-footer-height: 40px; + diff --git a/src/assets/css/inspinia/base.less b/src/assets/css/inspinia/base.less index 41ec527..e62dfdf 100644 --- a/src/assets/css/inspinia/base.less +++ b/src/assets/css/inspinia/base.less @@ -1197,6 +1197,12 @@ table.table-mail tr td { height: 96px; } +.img-blg { + width: 150px; + height: 150px; +} + + // BORDER RADIUS .b-r-xs { diff --git a/src/backyard/Frame.vue b/src/backyard/Frame.vue index 98fa661..2c9a224 100644 --- a/src/backyard/Frame.vue +++ b/src/backyard/Frame.vue @@ -32,7 +32,7 @@
- + @@ -43,6 +43,7 @@ import {Notification} from 'element-ui' import SideNavigation from './layout/SideNavigation.vue' import TopNavigation from './layout/TopNavigation.vue' + import BottomNavigation from './layout/BottomNavigation.vue' import enquire from 'enquire.js/dist/enquire' export default { @@ -58,7 +59,8 @@ }, components: { SideNavigation, - TopNavigation + TopNavigation, + BottomNavigation }, methods: { blankClick() { @@ -101,7 +103,7 @@ left: @sidebar-width; top: @top-navigation-height; right: 0; - bottom: 0; + bottom: @power-footer-height; overflow-y: auto; overflow-x: hidden; diff --git a/src/backyard/layout/BottomNavigation.vue b/src/backyard/layout/BottomNavigation.vue new file mode 100644 index 0000000..76b85a8 --- /dev/null +++ b/src/backyard/layout/BottomNavigation.vue @@ -0,0 +1,60 @@ + + + + + \ No newline at end of file diff --git a/src/backyard/layout/SideNavigation.vue b/src/backyard/layout/SideNavigation.vue index ef9161f..f2b5269 100644 --- a/src/backyard/layout/SideNavigation.vue +++ b/src/backyard/layout/SideNavigation.vue @@ -5,7 +5,7 @@
+ + + + diff --git a/src/common/model/matter/Matter.js b/src/common/model/matter/Matter.js index ccb1ab2..d013ece 100644 --- a/src/common/model/matter/Matter.js +++ b/src/common/model/matter/Matter.js @@ -60,6 +60,7 @@ export default class Matter extends BaseEntity { static URL_MATTER_DELETE = '/matter/delete' static URL_MATTER_DELETE_BATCH = '/matter/delete/batch' static URL_MATTER_RENAME = '/matter/rename' + static URL_CHANGE_PRIVACY = '/matter/change/privacy' static URL_MATTER_MOVE = '/matter/move' static URL_MATTER_DOWNLOAD = '/matter/download' static URL_MATTER_UPLOAD = '/matter/upload' @@ -130,6 +131,16 @@ export default class Matter extends BaseEntity { }, errorCallback) } + httpChangePrivacy(privacy, successCallback, errorCallback) { + let that = this + this.httpPost(Matter.URL_CHANGE_PRIVACY, {'uuid': this.uuid, 'privacy': privacy}, function (response) { + + that.privacy = privacy + + typeof successCallback === 'function' && successCallback(response) + }, errorCallback) + } + httpMove(srcUuids, destUuid, successCallback, errorCallback) { let form = {'srcUuids': srcUuids} if (destUuid) { @@ -281,6 +292,7 @@ export default class Matter extends BaseEntity { formData.append('puuid', that.puuid) formData.append('file', that.file) formData.append('alien', that.alien) + formData.append('privacy', that.privacy) //闭包 From 5155b1bd29b246d43ad510ad2bd1475ac8b74c26 Mon Sep 17 00:00:00 2001 From: seaheart Date: Fri, 29 Dec 2017 15:32:28 +0800 Subject: [PATCH 14/22] change user to currentUser. --- src/backyard/layout/SideNavigation.vue | 2 +- src/backyard/matter/List.vue | 12 +- src/backyard/preference/Index.vue | 4 +- src/backyard/user/Create.vue | 198 +++++++++++---------- src/backyard/user/Detail.vue | 230 +++++++++++++------------ src/backyard/user/List.vue | 34 ++-- src/backyard/user/Login.vue | 91 +++++----- src/backyard/user/Profile.vue | 68 -------- src/common/model/matter/Matter.js | 4 +- src/common/router/index.js | 5 +- 10 files changed, 298 insertions(+), 350 deletions(-) delete mode 100644 src/backyard/user/Profile.vue diff --git a/src/backyard/layout/SideNavigation.vue b/src/backyard/layout/SideNavigation.vue index 4ed5511..e79eea5 100644 --- a/src/backyard/layout/SideNavigation.vue +++ b/src/backyard/layout/SideNavigation.vue @@ -54,7 +54,7 @@ if (this.user.role === 'GUEST') { this.$router.push("/user/login"); } else { - this.$router.push("/user/profile/" + this.user.uuid); + this.$router.push("/user/detail/" + this.user.uuid); } diff --git a/src/backyard/matter/List.vue b/src/backyard/matter/List.vue index 888ab2d..7025d5f 100644 --- a/src/backyard/matter/List.vue +++ b/src/backyard/matter/List.vue @@ -317,7 +317,12 @@ }, created () { - + /*初始化inputSelection*/ + if (this.user.role === 'ADMINISTRATOR') { + this.pager.getFilter('userUuid').visible = true + } else { + this.pager.setFilterValue('userUuid', this.user.uuid) + } }, mounted () { @@ -331,11 +336,6 @@ this.pager.setFilterValue('puuid', 'root') } - if (this.user.role === 'ADMINISTRATOR') { - this.pager.getFilter('userUuid').visible = true - } else { - this.pager.setFilterValue('userUuid', this.user.uuid) - } //如果所有的排序都没有设置,那么默认以时间降序。 if (!this.pager.getFilterValue('orderDir') && !this.pager.getFilterValue('orderCreateTime') && !this.pager.getFilterValue('orderSize') && !this.pager.getFilterValue('orderName')) { diff --git a/src/backyard/preference/Index.vue b/src/backyard/preference/Index.vue index c4929d0..6b4ae86 100644 --- a/src/backyard/preference/Index.vue +++ b/src/backyard/preference/Index.vue @@ -83,6 +83,8 @@ diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index 9ca1e50..9153ed3 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -1,103 +1,103 @@ diff --git a/src/backyard/user/Detail.vue b/src/backyard/user/Detail.vue index 07f28b1..67be034 100644 --- a/src/backyard/user/Detail.vue +++ b/src/backyard/user/Detail.vue @@ -1,146 +1,142 @@ diff --git a/src/backyard/user/List.vue b/src/backyard/user/List.vue index 41c6bd3..15db850 100644 --- a/src/backyard/user/List.vue +++ b/src/backyard/user/List.vue @@ -17,48 +17,48 @@
-
+
- - + +
- - {{user.username}} - + {{userItem.username}} + (It's you)
- {{user.getRoleName()}} + {{userItem.getRoleName()}}
- - {{user.email}} + + {{userItem.email}} - - {{user.phone}} + + {{userItem.phone}}
- {{user.description}} + {{userItem.description}}
- 上次登录: {{user.lastTime | humanTime}} - 上次IP: {{user.lastIp}} + 上次登录: {{userItem.lastTime | humanTime}} + 上次IP: {{userItem.lastIp}} - + - + @@ -88,7 +88,7 @@ data () { return { pager: new Pager(User), - currentUser: this.$store.state.user + user: this.$store.state.user } }, components: { diff --git a/src/backyard/user/Login.vue b/src/backyard/user/Login.vue index 1921243..3293f3d 100644 --- a/src/backyard/user/Login.vue +++ b/src/backyard/user/Login.vue @@ -1,56 +1,57 @@ diff --git a/src/backyard/user/Profile.vue b/src/backyard/user/Profile.vue deleted file mode 100644 index 5785bfa..0000000 --- a/src/backyard/user/Profile.vue +++ /dev/null @@ -1,68 +0,0 @@ - - diff --git a/src/common/model/matter/Matter.js b/src/common/model/matter/Matter.js index d013ece..0726a8d 100644 --- a/src/common/model/matter/Matter.js +++ b/src/common/model/matter/Matter.js @@ -1,5 +1,6 @@ import BaseEntity from '../base/BaseEntity' import Filter from '../base/Filter' +import { Notification,Message } from 'element-ui' import {getMimeType, MimeUtil} from '../../util/MimeUtil' import {containStr, endWith, getExtension, startWith} from '../../filter/str' import User from '../user/User' @@ -134,9 +135,8 @@ export default class Matter extends BaseEntity { httpChangePrivacy(privacy, successCallback, errorCallback) { let that = this this.httpPost(Matter.URL_CHANGE_PRIVACY, {'uuid': this.uuid, 'privacy': privacy}, function (response) { - that.privacy = privacy - + Message.success(response.data.msg) typeof successCallback === 'function' && successCallback(response) }, errorCallback) } diff --git a/src/common/router/index.js b/src/common/router/index.js index e01c920..0ac6eff 100644 --- a/src/common/router/index.js +++ b/src/common/router/index.js @@ -50,7 +50,7 @@ const router = new Router({ breadcrumbs: [] } }, - { + /*{ path: 'user/profile/:uuid', name: 'UserProfile', component: UserDetail, @@ -64,7 +64,7 @@ const router = new Router({ } ] } - }, + },*/ { path: 'user/list', name: 'UserList', @@ -154,7 +154,6 @@ const router = new Router({ ] } }, - { path: 'preference', name: 'PreferenceIndex', From 9bd3b94b07900a576be42bd403e6c9272143c0d8 Mon Sep 17 00:00:00 2001 From: seaheart Date: Fri, 29 Dec 2017 15:54:49 +0800 Subject: [PATCH 15/22] add footer change. --- config/index.js | 4 +- src/App.vue | 112 +++++++++++------------ src/backyard/layout/BottomNavigation.vue | 2 +- src/backyard/preference/Index.vue | 2 +- 4 files changed, 59 insertions(+), 61 deletions(-) diff --git a/config/index.js b/config/index.js index 082475c..c6f46e7 100644 --- a/config/index.js +++ b/config/index.js @@ -33,8 +33,8 @@ module.exports = { assetsPublicPath: '/', proxyTable: { '/api': { - //target: 'http://tank.zicpo.cn', - target: 'http://localhost:6010', + target: 'http://tank.zicpo.cn', + //target: 'http://localhost:6010', changeOrigin: true, pathRewrite: { '^/api': '/api' diff --git a/src/App.vue b/src/App.vue index d0ad5e8..4944013 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,18 +1,17 @@ @@ -36,61 +34,61 @@ diff --git a/src/backyard/layout/BottomNavigation.vue b/src/backyard/layout/BottomNavigation.vue index d9cb54a..0149e49 100644 --- a/src/backyard/layout/BottomNavigation.vue +++ b/src/backyard/layout/BottomNavigation.vue @@ -4,7 +4,7 @@ {{preference.footerLine1}} - {{preference.footerLine2}} + diff --git a/src/backyard/preference/Index.vue b/src/backyard/preference/Index.vue index 6b4ae86..745a051 100644 --- a/src/backyard/preference/Index.vue +++ b/src/backyard/preference/Index.vue @@ -55,7 +55,7 @@ 底部第二行文字
- {{preference.footerLine2}} +
From ed679b73d76502a563b5537131bc4338c5630543 Mon Sep 17 00:00:00 2001 From: zicla Date: Fri, 29 Dec 2017 18:43:37 +0800 Subject: [PATCH 16/22] Add block for File upload. --- config/index.js | 4 ++-- src/backyard/user/Create.vue | 16 ++++++++++++---- src/backyard/user/Detail.vue | 8 ++++++++ src/common/model/user/User.js | 5 ++++- src/common/util/AnimationUtils.js | 13 ------------- 5 files changed, 26 insertions(+), 20 deletions(-) delete mode 100644 src/common/util/AnimationUtils.js diff --git a/config/index.js b/config/index.js index c6f46e7..9a01733 100644 --- a/config/index.js +++ b/config/index.js @@ -33,8 +33,8 @@ module.exports = { assetsPublicPath: '/', proxyTable: { '/api': { - target: 'http://tank.zicpo.cn', - //target: 'http://localhost:6010', + //target: 'http://tank.eyeblue.cn', + target: 'http://localhost:6010', changeOrigin: true, pathRewrite: { '^/api': '/api' diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index 9153ed3..65e64c4 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -52,20 +52,28 @@
+ +
+ +
+
+ +
+
- - - - + + + +
diff --git a/src/backyard/user/Detail.vue b/src/backyard/user/Detail.vue index 67be034..a33b172 100644 --- a/src/backyard/user/Detail.vue +++ b/src/backyard/user/Detail.vue @@ -56,11 +56,19 @@ 城市:{{currentUser.city}}
+
+
+ 单文件限制:{{currentUser.sizeLimit | humanFileSize}} +
+
+ +
状态:{{currentUser.getStatusName()}}
+
上次登录IP:{{currentUser.lastIp}} diff --git a/src/common/model/user/User.js b/src/common/model/user/User.js index 0e80fc0..f2928cb 100644 --- a/src/common/model/user/User.js +++ b/src/common/model/user/User.js @@ -77,6 +77,8 @@ export default class User extends BaseEntity { this.avatarUrl = null this.lastIp = null this.lastTime = null + //默认大小限制100Mb. + this.sizeLimit = 104857600 this.status = Status.USER_STATUS_OK //local fields @@ -209,7 +211,8 @@ export default class User extends BaseEntity { username: this.username, password: this.password, email: this.email, - gender: this.gender + gender: this.gender, + sizeLimit: this.sizeLimit } if (this.phone) { diff --git a/src/common/util/AnimationUtils.js b/src/common/util/AnimationUtils.js deleted file mode 100644 index 6eedb36..0000000 --- a/src/common/util/AnimationUtils.js +++ /dev/null @@ -1,13 +0,0 @@ -import $ from "jquery"; - -//check whether an obj is number. -export function smoothScroll(dom) { - let that = this; - if (!dom) { - console.error("使用smoothScroll必须指定dom."); - } - $('html, body').animate({ - scrollTop: $(dom).offset().top - }, 500); - -} From 46bdc8d0b694a4ab9a15ec4c0c7cda3bcd8e8c6c Mon Sep 17 00:00:00 2001 From: zicla Date: Mon, 1 Jan 2018 16:52:23 +0800 Subject: [PATCH 17/22] add license and change some details. --- LICENSE | 21 ++++++++++++++++ src/backyard/layout/BottomNavigation.vue | 12 +++++----- src/backyard/matter/widget/MatterImage.vue | 28 ++++++++++++++++++---- src/backyard/preference/Edit.vue | 8 +++---- src/backyard/preference/Index.vue | 10 ++++---- 5 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c3060d9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 蓝眼 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/backyard/layout/BottomNavigation.vue b/src/backyard/layout/BottomNavigation.vue index 0149e49..42cc8df 100644 --- a/src/backyard/layout/BottomNavigation.vue +++ b/src/backyard/layout/BottomNavigation.vue @@ -1,15 +1,15 @@ @@ -58,4 +58,4 @@ } } } - \ No newline at end of file + diff --git a/src/backyard/matter/widget/MatterImage.vue b/src/backyard/matter/widget/MatterImage.vue index 3b60a50..5e5b258 100644 --- a/src/backyard/matter/widget/MatterImage.vue +++ b/src/backyard/matter/widget/MatterImage.vue @@ -8,13 +8,17 @@
- + + {{value?'重新上传':'上传图片'}} +
+ {{uploadHint}} +
@@ -57,6 +61,22 @@ value: { type: String | null, required: true + }, + //filter. + filter: { + type: String, + required: false, + "default": "image" + }, + maxSize: { + type: Number, + required: false, + "default": 1024 * 1024 + }, + uploadHint: { + type: String, + required: false, + "default": "图片最大不超过1M" } }, methods: { @@ -68,9 +88,9 @@ let that = this let matter = that.matter; - matter.maxSize = 1024 * 1024 - matter.uploadHint = "图片最大不超过1M" - matter.filter = "image" + matter.maxSize = that.maxSize + matter.uploadHint = that.uploadHint + matter.filter = that.filter matter.privacy = false matter.dir = false diff --git a/src/backyard/preference/Edit.vue b/src/backyard/preference/Edit.vue index f79aeeb..1226ffe 100644 --- a/src/backyard/preference/Edit.vue +++ b/src/backyard/preference/Edit.vue @@ -20,26 +20,26 @@
- +
- +
- +
- +
diff --git a/src/backyard/preference/Index.vue b/src/backyard/preference/Index.vue index 745a051..dd64bf6 100644 --- a/src/backyard/preference/Index.vue +++ b/src/backyard/preference/Index.vue @@ -15,7 +15,7 @@
-
+
网站名称
@@ -24,7 +24,7 @@
-
+
logo
@@ -33,7 +33,7 @@
-
+
favicon
@@ -42,7 +42,7 @@
-
+
底部第一行文字
@@ -51,7 +51,7 @@
-
+
底部第二行文字
From c2c766785ad66dd069945de584381b940d90d27b Mon Sep 17 00:00:00 2001 From: zicla Date: Mon, 1 Jan 2018 17:01:46 +0800 Subject: [PATCH 18/22] Update the README file. --- README.md | 40 ++++++++++++++++++++++++++++++++++++---- config/index.js | 3 +-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fda8c87..9067beb 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,47 @@ -# 蓝眼云盘前端项目 +![蓝眼云盘logo](https://raw.githubusercontent.com/eyebluecn/tank/dev/build/doc/logo.png) -### [配套后端`tank`](https://github.com/eyebluecn/tank) +# 蓝眼云盘前端 +##### [在线Demo](http://tank.eyeblue.cn) +##### [配套后端tank](https://github.com/eyebluecn/tank) -### [在线体验](http://tank.zicpo.cn) +### 简介 +蓝眼云盘是 [蓝眼系列开源软件](https://github.com/eyebluecn) 中的第一个 +- 主要用于快速搭建私人云盘,可以简单理解为部署在自己服务器上的[百度云盘](https://pan.baidu.com/)。 +- 蓝眼云盘提供了编程接口,可以使用接口上传文件,作为其他网站、系统、app的资源存储器,可以当作单机版的[七牛云](https://www.qiniu.com)或[阿里云OSS](https://www.aliyun.com/product/oss)使用。 +蓝眼云盘可以作为团队内部或个人私有的云盘使用,亦可当作专门处理图片,音频,视频等二进制文件的第三方编程辅助工具。 +如果您觉得蓝眼云盘对您有帮助,请不要吝惜您的star :smile: +### 运行 +``` +npm install -> 详细文档正在撰写中,敬请期待... +npm run dev +``` +如果你有自己的tank后端,也可以在`config/index.js`中`proxyTable.target`修改为自己tank所在地址 +### 打包 + +``` +npm run build +``` + 打包的结果在`dist`文件夹下,将该文件夹下的内容放置在[后端tank](https://github.com/eyebluecn/tank)的`build/html`文件夹下即可。 + + #### 更多详细配置请参考[后端说明](https://github.com/eyebluecn/tank) + +### Contribution + +感谢所有蓝眼云盘的贡献者 [@zicla](https://github.com/zicla),[@seaheart](https://github.com/seaheart),@heying,[@hxsherry](https://github.com/hxsherry) + +如果您也想参与进来,请尽情的fork, star, post issue, pull requests + +### License + +[MIT](http://opensource.org/licenses/MIT) + +Copyright (c) 2017-present, eyeblue.cn diff --git a/config/index.js b/config/index.js index 9a01733..eff06db 100644 --- a/config/index.js +++ b/config/index.js @@ -33,8 +33,7 @@ module.exports = { assetsPublicPath: '/', proxyTable: { '/api': { - //target: 'http://tank.eyeblue.cn', - target: 'http://localhost:6010', + target: 'http://tank.eyeblue.cn', changeOrigin: true, pathRewrite: { '^/api': '/api' From 9c1bfac492e4168e2fddcd28112806c6adbf5e81 Mon Sep 17 00:00:00 2001 From: zicla Date: Mon, 1 Jan 2018 17:44:55 +0800 Subject: [PATCH 19/22] Fix a lot of details. --- src/backyard/layout/TopNavigation.vue | 4 +- src/backyard/preference/Index.vue | 4 +- src/backyard/user/Create.vue | 2 +- src/backyard/user/Detail.vue | 234 +++++++++++++------------- src/backyard/user/Login.vue | 4 - src/common/filter/str.js | 22 +-- 6 files changed, 132 insertions(+), 138 deletions(-) diff --git a/src/backyard/layout/TopNavigation.vue b/src/backyard/layout/TopNavigation.vue index 076a65c..f469ed2 100644 --- a/src/backyard/layout/TopNavigation.vue +++ b/src/backyard/layout/TopNavigation.vue @@ -7,7 +7,7 @@ - + {{preference.name}} @@ -37,7 +37,7 @@ //logo可以使用自定义的。 logoUrl() { if (this.preference.logoUrl) { - return this.preference.logoUrl + return this.preference.logoUrl + '?imageProcess=resize&imageResizeM=fill&imageResizeW=100&imageResizeH=100' } else { return defaultLogoPath } diff --git a/src/backyard/preference/Index.vue b/src/backyard/preference/Index.vue index dd64bf6..b703241 100644 --- a/src/backyard/preference/Index.vue +++ b/src/backyard/preference/Index.vue @@ -28,7 +28,7 @@ logo
- logo + logo
@@ -37,7 +37,7 @@ favicon
- favicon + favicon
diff --git a/src/backyard/user/Create.vue b/src/backyard/user/Create.vue index 65e64c4..9fe5d6c 100644 --- a/src/backyard/user/Create.vue +++ b/src/backyard/user/Create.vue @@ -52,7 +52,7 @@
- +
diff --git a/src/backyard/user/Detail.vue b/src/backyard/user/Detail.vue index a33b172..e70fc8b 100644 --- a/src/backyard/user/Detail.vue +++ b/src/backyard/user/Detail.vue @@ -1,140 +1,138 @@ diff --git a/src/backyard/user/Login.vue b/src/backyard/user/Login.vue index 3293f3d..30d6cc2 100644 --- a/src/backyard/user/Login.vue +++ b/src/backyard/user/Login.vue @@ -15,10 +15,6 @@ @keyup.enter="login">
-
- 体验账号: lish516@126.com 密码:123456 -
-