From fead12b0d2b8db97cfe1daffe15c586ccd0a5b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Fri, 18 May 2018 22:52:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96layer=E7=BB=84=E4=BB=B6tips?= =?UTF-8?q?=E7=9A=84=E5=AE=9A=E4=BD=8D;=E9=87=8D=E6=9E=84meditor=E7=9A=84?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/layer/index.js | 57 ++- src/js/layer/skin/default.scss | 3 +- src/js/meditor/addon/attach.js | 791 +++++++++++++++---------------- src/js/meditor/addon/attach.scss | 110 +++-- src/js/meditor/addon/base.js | 222 +++++---- src/js/meditor/index.js | 525 ++++++++++---------- src/js/meditor/skin/main.scss | 37 +- 7 files changed, 878 insertions(+), 867 deletions(-) diff --git a/src/js/layer/index.js b/src/js/layer/index.js index 683517d..161da7f 100644 --- a/src/js/layer/index.js +++ b/src/js/layer/index.js @@ -22,6 +22,7 @@ let defconf = { background: '#fff', mask: true, // 遮罩 maskClose: false, // 遮罩点击关闭弹窗 + maskColor: null, // 遮罩背景色 radius: '0px', // 弹窗圆角半径 area: ['auto', 'auto'], title: '提示', // 弹窗主标题(在工具栏上的) @@ -64,6 +65,7 @@ const close = function(id) { }, 200) } catch (err) {} } + document.body.style.overflow = '' } const repeat = function(str, num) { @@ -208,6 +210,9 @@ class __layer__ { if (state.mask) { outerBox.classList.add('mask') } + if (state.maskColor) { + outerBox.style.background = state.maskColor + } layBox.classList.add('layer-box') layBox.classList.add('skin-' + state.skin) @@ -373,40 +378,49 @@ class __layer__ { style.color = state.color style.opacity = 1 let $container = Anot(container) + let $doc = Anot(document) let $arrow = $container[0].querySelector('.arrow') let cw = $container.innerWidth() let ch = $container.innerHeight() - let ol = $container.offset().left - document.body.scrollLeft - let ot = $container.offset().top - document.body.scrollTop + let ol = $container.offset().left - $doc.scrollLeft() + let ot = $container.offset().top - $doc.scrollTop() let layw = parseInt(css.width) let layh = parseInt(css.height) - let arrowOffset = ['top'] - if (ot + 18 < layh) { - arrowOffset[0] = 'bottom' - $arrow.style.borderBottomColor = state.background - style.top = ot + ch + 8 - } else { - $arrow.style.borderTopColor = state.background - style.top = ot - layh - 8 - } - - if (ol + cw * 0.7 + layw > window.innerWidth) { - style.left = ol + cw * 0.3 - layw - arrowOffset[1] = 'left' - } else { - style.left = ol + cw * 0.7 - } - - $arrow.classList.add('offset-' + arrowOffset.join('-')) Anot(layerDom[$id][1]).css(style) + $container.bind('mouseenter', ev => { - layerDom[$id][1].style.visibility = 'visible' + let tmpStyle = { visibility: 'visible' } + ol = $container.offset().left - $doc.scrollLeft() + ot = $container.offset().top - $doc.scrollTop() + + if (ot + 18 < layh) { + arrowOffset[0] = 'bottom' + $arrow.style.borderBottomColor = state.background + tmpStyle.top = ot + ch + 8 + } else { + $arrow.style.borderTopColor = state.background + tmpStyle.top = ot - layh - 8 + } + + if (ol + cw * 0.7 + layw > window.innerWidth) { + tmpStyle.left = ol + cw * 0.3 - layw + arrowOffset[1] = 'left' + } else { + tmpStyle.left = ol + cw * 0.7 + } + + $arrow.classList.add('offset-' + arrowOffset.join('-')) + Anot(layerDom[$id][1]).css(tmpStyle) }) $container.bind('mouseleave', () => { setTimeout(() => { + $arrow.classList.remove('offset-' + arrowOffset.join('-')) + arrowOffset = ['top'] + $arrow.style.borderBottomColor = '' + $arrow.style.borderTopColor = '' layerDom[$id][1].style.visibility = 'hidden' }, 100) }) @@ -436,6 +450,7 @@ class __layer__ { Anot(layerDom[$id][1]).css(style) setTimeout(() => { + document.body.style.overflow = 'hidden' layerDom[$id][1].classList.add('shift') setTimeout(_ => { Anot(layerDom[$id][1]).css(offsetStyle) diff --git a/src/js/layer/skin/default.scss b/src/js/layer/skin/default.scss index 61aad1c..48b126b 100644 --- a/src/js/layer/skin/default.scss +++ b/src/js/layer/skin/default.scss @@ -75,7 +75,7 @@ /* tips类弹层(type 5) */ - &.type-5 {visibility:hidden;z-index:65534;min-width:75px;max-width:600px;line-height:1.5;color:#fff;background:rgba(0,0,0,.5);opacity:0;box-shadow:none;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out; + &.type-5 {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;line-height:1.5;color:#fff;background:rgba(0,0,0,.5);opacity:0;box-shadow:none;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out; // &.active {visibility:visible;opacity:1;} i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""} @@ -190,7 +190,6 @@ &.shift {transition: all .5s ease-out;} - .layer-box {position:absolute;} } &:active {z-index:65536;} } diff --git a/src/js/meditor/addon/attach.js b/src/js/meditor/addon/attach.js index 642b161..85a8d82 100644 --- a/src/js/meditor/addon/attach.js +++ b/src/js/meditor/addon/attach.js @@ -7,432 +7,419 @@ 'use strict' -define(['lib/layer/base', 'css!./attach'], function() { - var Uploader = function(url) { - this.url = url || '' - this.init() +import 'layer/index' +import './attach.scss' + +const $doc = Anot(document) + +class Uploader { + constructor(url) { + this.url = url + this.xhr = new XMLHttpRequest() + this.form = new FormData() } - Uploader.prototype = { - init: function() { - this.xhr = new XMLHttpRequest() - this.form = new FormData() - return this - }, - field: function(key, val) { - if (typeof key === 'object') { - for (var i in key) { - this.form.append(i, key[i]) - } - } else { - this.form.append(key, val) - } - return this - }, - start: function() { - var _this = this - - this.xhr.open('POST', this.url, true) - - var startTime = Date.now() - - this.xhr.upload.addEventListener( - 'progress', - function(evt) { - if (evt.lengthComputable && _this.progress) { - var res = Math.round(evt.loaded * 100 / evt.total) - _this.progress(res) - } - }, - false - ) - - this.xhr.onreadystatechange = function() { - if (_this.xhr.readyState === 4) { - if (_this.xhr.status >= 200 && _this.xhr.status < 205) { - var res = _this.xhr.responseText - try { - res = JSON.parse(res) - } catch (err) {} - _this.end && _this.end(res) - } else { - console.error(_this.xhr) - } - } - } - - this.xhr.send(this.form) - }, - onProgress: function(fn) { - this.progress = fn - return this - }, - onEnd: function(fn) { - this.end = fn - return this + field(key, val) { + this.form.append(key, val) + return this + } + onProgress(fn) { + this.progress = fn + return this + } + then(cb) { + if (!this.url) { + Anot.error('invalid upload url') } - } + let defer = Promise.defer() - function uploadScreenshot(vm, blob) { - var upload = new Uploader(vm.uploadUrl || ME.uploadUrl) - if (ME.beforeUpload) { - ME.beforeUpload(Date.now().toString(16) + '.jpg', function(qn) { - upload - .field('file', blob) - .field('token', qn.token) - .field('key', qn.key) - .onEnd(function(json) { - ME.insert(vm.$editor, '![截图](' + qn.url + ')') - }) - .start() + this.xhr.open('POST', this.url, true) + this.xhr.upload.addEventListener( + 'progress', + evt => { + if (evt.lengthComputable && this.progress) { + let res = Math.round(evt.loaded * 100 / evt.total) + this.progress(res) + } + }, + false + ) + + this.xhr.onreadystatechange = () => { + if (this.xhr.readyState === 4) { + if (this.xhr.status >= 200 && this.xhr.status < 205) { + let res = this.xhr.responseText + try { + res = JSON.parse(res) + } catch (err) {} + defer.resolve(cb(res)) + } else { + defer.reject(this.xhr) + } + } + } + + this.xhr.send(this.form) + return defer.promise + } +} + +var $init = function(vm) { + vm.$editor.addEventListener('paste', function(ev) { + var txt = ev.clipboardData.getData('text/plain').trim(), + html = ev.clipboardData.getData('text/html').trim() + + //文本类型直接默认处理 + if (txt || html) { + return + } + + if (ev.clipboardData.items) { + var items = ev.clipboardData.items, + len = items.length, + blob = null + for (var i = 0, it; (it = items[i++]); ) { + if (it.type.indexOf('image') > -1) { + blob = it.getAsFile() + } + } + + if (blob !== null) { + layer.msg('截图处理中...') + // 压缩截图,避免文件过大 + var reader = new FileReader() + reader.onload = function() { + var img = document.createElement('img'), + canvas = document.createElement('canvas') + + img.onload = function() { + canvas.width = img.width + canvas.height = img.height + + var ctx = canvas.getContext('2d') + ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.drawImage(this, 0, 0, canvas.width, canvas.height) + + if (canvas.toBlob) { + canvas.toBlob( + function(obj) { + uploadScreenshot(vm, obj) + }, + 'image/jpeg', + 0.8 + ) + } else { + var base64 = canvas.toDataURL('image/jpeg', 0.8), + buf = atob(base64.split(',')[1]), + arrBuf = new ArrayBuffer(buf.length), + intArr = new Uint8Array(arrBuf), + obj = null + + for (var i = 0; i < buf.length; i++) { + intArr[i] = buf.charCodeAt(i) + } + obj = new Blob([intArr], { type: 'image/jpeg' }) + uploadScreenshot(vm, obj) + } + } + img.src = this.result + } + reader.readAsDataURL(blob) + } + } + ev.preventDefault() + }) +} + +let cache = { + //缓存附件列表 + image: [], + file: [] +} + +const LANG = { + image: ['远程图片', '图片管理', '图片描述', '图片地址'], + file: ['远程附件', '附件管理', '附件描述', '附件地址'] +} + +const fixCont = function(vm, tool) { + let limit = false + if (vm.props.uploadSizeLimit) { + limit = (vm.props.uploadSizeLimit / (1024 * 1024)).toFixed(2) + } + return ` +
+
+
+ + ${LANG[tool][0]} + + 本地上传 + + ${LANG[tool][1]} + +
+
+
+
+ +
+
+ +
+
+ 确定 +
+
+
+
+ + 选择文件 + ${ + limit + ? `(上传大小限制:单文件最大${limit} MB)` + : '' + } +
+
    +
  • + 文件名 + 上传进度 + 操作 +
  • +
  • +

    + + + 插入 +

    +
  • +
+
+
    +
  • + +

    +
  • +
+
+
` +} + +/** + * [uploadFile 文件上传] + * @param {[type]} vm [vm对象] + * @param {[type]} tool [image/file] + */ +function uploadFile(vm, tool) { + for (let it of this.files) { + let ext = it.name.slice(it.name.lastIndexOf('.')) + if (tool === 'image' && !/^\.(jpg|jpeg|png|gif|bmp|webp|ico)$/.test(ext)) { + this.uploadQueue.push({ + name: it.name, + progress: '0%(文件类型错误)', + url: '' }) + continue + } + if (vm.props.uploadSizeLimit && it.size > vm.props.uploadSizeLimit) { + this.uploadQueue.push({ + name: it.name, + progress: '0%(文件体积过大)', + url: '' + }) + continue + } + let idx = this.uploadQueue.length + let fixName = new Date().format('YmdHis') + ext + let attach = { name: it.name, fixName, progress: '0%', url: '' } + let upload = new Uploader(vm.props.uploadUrl).field('file', it) + + this.uploadQueue.push(attach) + + if (vm.props.beforeUpload) { + vm.props + .beforeUpload(attach, upload) + .then(next => { + if (!next) { + return Promise.reject('something wrong with beforeUpload') + } + return upload + .onProgress(val => { + this.uploadQueue[idx].progress = val + '%' + }) + .then(res => { + return res.data + }) + }) + .then(data => { + this.uploadQueue[idx].url = data.url + }) + .catch(err => { + Anot.error(err) + }) } else { upload - .field('file', blob) - .onEnd(function(json) { - ME.insert(vm.$editor, '![截图](' + json.data.url + ')') + .onProgress(val => { + this.uploadQueue[idx].progress = val + '%' + }) + .then(res => { + return res.data + }) + .then(data => { + this.uploadQueue[idx].url = data.url + }) + .catch(err => { + Anot.error(err) }) - .start() } } +} - var $init = function(vm) { - if (!vm.uploadUrl && !ME.uploadUrl) { - console.error( - '使用附件上传,必须先设置uploadUrl;\n可以给vm增加uploadUrl属性,也可以通过ME.uploadUrl设置' - ) - } - if (!vm.manageUrl && !ME.manageUrl) { - console.error( - '使用附件管理功能,必须先设置manageUrl;\n可以给vm增加manageUrl属性,也可以通过ME.manageUrl设置' - ) - } - if (!ME.maxSize) { - ME.maxSize = 4194304 - } +function uploadScreenshot(vm, blob) { + let name = new Date().format('YmdHis') + '.jpg' + let attach = { name, url: '' } + let upload = new Uploader(vm.props.uploadUrl).field('file', blob) - vm.$editor.addEventListener('paste', function(ev) { - var txt = ev.clipboardData.getData('text/plain').trim(), - html = ev.clipboardData.getData('text/html').trim() - - //文本类型直接默认处理 - if (txt || html) { - return - } - - if (ev.clipboardData.items) { - var items = ev.clipboardData.items, - len = items.length, - blob = null - for (var i = 0, it; (it = items[i++]); ) { - if (it.type.indexOf('image') > -1) { - blob = it.getAsFile() - } - } - - if (blob !== null) { - layer.msg('截图处理中...') - // 压缩截图,避免文件过大 - var reader = new FileReader() - reader.onload = function() { - var img = document.createElement('img'), - canvas = document.createElement('canvas') - - img.onload = function() { - canvas.width = img.width - canvas.height = img.height - - var ctx = canvas.getContext('2d') - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.drawImage(this, 0, 0, canvas.width, canvas.height) - - if (canvas.toBlob) { - canvas.toBlob( - function(obj) { - uploadScreenshot(vm, obj) - }, - 'image/jpeg', - 0.8 - ) - } else { - var base64 = canvas.toDataURL('image/jpeg', 0.8), - buf = atob(base64.split(',')[1]), - arrBuf = new ArrayBuffer(buf.length), - intArr = new Uint8Array(arrBuf), - obj = null - - for (var i = 0; i < buf.length; i++) { - intArr[i] = buf.charCodeAt(i) - } - obj = new Blob([intArr], { type: 'image/jpeg' }) - uploadScreenshot(vm, obj) - } - } - img.src = this.result - } - reader.readAsDataURL(blob) - } - } - ev.preventDefault() + if (vm.props.beforeUpload) { + vm.props + .beforeUpload(attach, upload) + .then(upload => { + return upload.then(res => { + return res.data + }) + }) + .then(data => { + vm.insert(`![截图](${data.url})`) + }) + } else { + upload + .then(res => { + return res.data + }) + .then(data => { + vm.insert(`![截图](${data.url})`) }) - }, - lang = { - image: ['远程图片', '图片管理', '图片描述', '图片地址'], - file: ['远程附件', '附件管理', '附件描述', '附件地址'] - }, - opened = false, //记录是否已经打开 - openType = 'image', //打开类型, 图片/附件 - cache = { - //缓存附件列表 - image: [], - file: [] - }, - fixCont = function() { - return ( - '
' + - '
' + - '' + - lang[openType][0] + - '' + - '本地上传' + - '' + - lang[openType][1] + - '' + - '' + - '
' + - '
' + - '
' + - '
' + - lang[openType][2] + - '' + - '' + - '
' + - '
' + - lang[openType][3] + - '' + - '' + - '
' + - '
' + - '确定' + - '
' + - '
' + - '
' + - '
选择文件(上传大小限制:单文件最大 ' + - ((ME.maxSize / 1048576).toFixed(2) - 0) + - 'MB)
' + - '
    ' + - '
  • 文件名上传进度操作
  • ' + - '
  • ' + - '' + - '' + - '插入' + - '
  • ' + - '
' + - '
' + - '
    ' + - '
  • ' + - '' + - '

    ' + - '
  • ' + - '
' + - '
' + - '
' - ) - } - - /** - * [uploadFile 文件上传] - * @param {[type]} files [文件列表] - * @param {[type]} vm [vm对象] - * @param {[type]} type [image/file] - */ - function uploadFile(files, vm) { - for (var i = 0, it; (it = files[i++]); ) { - if ( - openType === 'image' && - !/\.(jpg|jpeg|png|gif|bmp|webp|ico)$/.test(it.name) - ) { - vm.uploadFile.push({ - name: it.name, - progress: '0%(失败,不允许的文件类型)', - url: '' - }) - continue - } - if (ME.maxSize > 0 && it.size > ME.maxSize) { - vm.uploadFile.push({ - name: it.name, - progress: '0%(文件体积过大)', - url: '' - }) - continue - } - var fixName = - Date.now().toString(16) + it.name.slice(it.name.lastIndexOf('.')) - - var idx = vm.uploadFile.length, - upload = new Uploader(vm.uploadUrl || ME.uploadUrl) - - vm.uploadFile.push({ name: it.name, progress: '0%', url: '' }) - - upload.field('file', it) - - if (ME.beforeUpload) { - ME.beforeUpload(fixName, function(qn) { - upload - .field('token', qn.token) - .field('key', qn.key) - .onProgress(function(val) { - vm.uploadFile[idx].progress = val + '%' - }) - .onEnd(function(json) { - vm.uploadFile[idx].url = qn.url - }) - .start() - }) - } else { - upload - .onProgress(function(val) { - vm.uploadFile[idx].progress = val + '%' - }) - .onEnd(function(json) { - vm.uploadFile[idx].url = json.data.url - }) - .start() - } - } } +} - function getAttach(vm, cb) { - var xhr = new XMLHttpRequest(), - url = vm.manageUrl || ME.manageUrl +function getAttach(vm, cb) { + var xhr = new XMLHttpRequest(), + url = vm.manageUrl || ME.manageUrl - if (/\?/.test(url)) { - url += '&type=' + openType + if (/\?/.test(url)) { + url += '&type=' + openType + } else { + url += '?type=' + openType + } + url += '&t=' + Math.random() + + xhr.open('GET', url, true) + xhr.onreadystatechange = function() { + if ( + this.readyState === 4 && + this.status === 200 && + this.responseText !== '' + ) { + var res = this.responseText + try { + res = JSON.parse(res) + } catch (err) {} + cb(res) } else { - url += '?type=' + openType + if (this.status !== 200 && this.responseText) + console.error(this.responseText) } - url += '&t=' + Math.random() - - xhr.open('GET', url, true) - xhr.onreadystatechange = function() { - if ( - this.readyState === 4 && - this.status === 200 && - this.responseText !== '' - ) { - var res = this.responseText - try { - res = JSON.parse(res) - } catch (err) {} - cb(res) - } else { - if (this.status !== 200 && this.responseText) - console.error(this.responseText) - } - } - xhr.send() } + xhr.send() +} - function showDialog(elem, vm) { - opened = true - var offset = yua(elem).offset(), - layid = layer.open({ - type: 7, - menubar: false, - shade: false, - fixed: true, - offset: [offset.top + 37 - ME.doc.scrollTop()], - tab: 2, - attach: '', - attachAlt: '', - uploadFile: [], //当前上传的列表 - attachList: [], //附件管理列表 - $switch: function(id) { - var lvm = yua.vmodels[layid] +function showDialog(elem, vm, tool) { + let offset = Anot(elem).offset() - lvm.tab = id - if (id === 3) { - lvm.attachList.clear() - if (cache[openType].length) { - lvm.attachList = cache[openType] - } else { - getAttach(vm, function(json) { - if (json) { - cache[openType] = json.data.list.map(function(it) { - it.thumb = - openType === 'image' - ? '' - : '' - return it - }) - lvm.attachList = json.data.list - } + layer.open({ + type: 7, + menubar: false, + fixed: true, + offset: [offset.top + 37 - $doc.scrollTop()], + tab: 2, + attach: '', + attachAlt: '', + uploadQueue: [], //当前上传的列表 + attachList: [], //附件管理列表 + switchTab: function(id) { + this.tab = id + if (id === 3) { + this.attachList.clear() + if (cache[tool].length) { + this.attachList = cache[tool] + } else { + getAttach(vm, function(json) { + if (json) { + cache[tool] = json.data.list.map(function(it) { + it.thumb = + tool === 'image' + ? '' + : '' + return it }) + this.attachList = json.data.list } - } - }, - $select: yua.noop, - $change: yua.noop, - $insert: function(it) { - if (!it.url) { - return - } - var val = - (openType === 'image' ? '!' : '') + - '[' + - it.name + - '](' + - it.url + - ')' - ME.insert(vm.$editor, val) - }, - $confirm: function() { - var lvm = yua.vmodels[layid] - if (!lvm.attach || !lvm.attachAlt) { - return layer.alert('描述和地址不能为空') - } - var val = '![' + lvm.attachAlt + '](' + lvm.attach + ')' + }) + } + } + }, + select() { + let ev = document.createEvent('MouseEvent') + ev.initEvent('click', false, false) + this.$refs.attach.dispatchEvent(ev) + }, + change(ev) { + this.files = ev.target.files + uploadFile.call(this, vm, tool) + }, + insert: function(it) { + if (!it.url) { + return + } + let val = `\n${tool === 'image' ? '!' : ''}[${it.name}](${it.url})` + vm.insert(val) + }, + confirm: function() { + if (!this.attach || !this.attachAlt) { + return layer.toast('描述和地址不能为空', 'error') + } + let val = `\n${tool === 'image' ? '!' : ''}[${this.attachAlt}](${ + this.attach + })` - ME.insert(vm.$editor, val) - lvm.no() - }, - success: function(id) { - var _this = yua.vmodels[id], - $file = document.body.querySelector('#meditor-attch') + vm.insert(val) + this.close() + }, - _this.no = function() { - layer.close(id) - opened = false - } - _this.$select = function() { - var ev = document.createEvent('MouseEvent') - ev.initEvent('click', false, false) - $file.dispatchEvent(ev) - } - _this.$change = function() { - uploadFile(this.files, _this) - } - }, - content: fixCont() - }) + content: fixCont(vm, tool) + }) +} + +const addon = { + attach(elem) { + showDialog(elem, this, 'file') + }, + image(elem) { + showDialog(elem, this, 'image') } +} - ME.addon.image = function(elem, vm) { - if (opened) { - return - } - openType = 'image' - showDialog(elem, vm) - } - - ME.addon.file = function(elem, vm) { - if (opened) { - return - } - openType = 'file' - showDialog(elem, vm) - } - - return $init -}) +export default addon diff --git a/src/js/meditor/addon/attach.scss b/src/js/meditor/addon/attach.scss index e779163..d9fa3a3 100644 --- a/src/js/meditor/addon/attach.scss +++ b/src/js/meditor/addon/attach.scss @@ -5,58 +5,76 @@ * @date 2017-04-20 19:13:24 * */ +@import 'var.scss'; -.do-meditor-attach {width:630px;height:auto;background:#f7f7f7;cursor:default; +.do-meditor-attach {width:630px;height:300px;cursor:default;color:nth($cgr, 1); + dt.close {position:absolute;z-index:65539;top:-8px;right:-8px;width:40px;height:40px;line-height:40px;font-size:20px;text-align:center;cursor:pointer; - .tab-box {width:100%;height:50px;line-height:49px;border-bottom:1px solid #e2e2e2;text-align:center; + &:hover {color:nth($ct, 1);font-size:28px;} + } + + .tab-box {float:left;width:130px;height:300px;padding:10px 5px;text-align:center;background:nth($cp, 2);border-radius:5px; - .item {position:relative;float:left;width:100px;height:49px;border-right:1px solid #ddd;cursor:pointer;} - .item.active {background:#fff;} - .item.active::after {position:absolute;left:0;bottom:-1px;width:100%;height:1px;background:#fff;content:""} - a.action-close {top:5px;width:40px;height:40px;line-height:40px;font-size:20px;} - a.action-close:hover {line-height:40px;border:0;} + .item {display:block;width:100%;height:40px;line-height:40px;border-radius:3px;cursor:pointer; + + &.active {background:#fff;} + } + } + + + .cont-box {position:relative;float:right;width:480px;height:auto;min-height:200px; + + .remote, + .local {position:relative;width:92%;height:auto;margin:0 auto;} + + .remote {padding:30px 0;} + .hide {display:none;} + + .section {display:block;width:100%;height:auto;margin:15px 0;line-height:35px; + + .txt {width:100%;height:45px;padding:0 10px;border:0;border-radius:5px;background:nth($cp, 2);color:nth($cgr, 1);font-size:14px;} + .submit {float:right;width:30%;height:45px;line-height:45px;} } - .cont-box {position:relative;width:100%;height:auto;min-height:200px;background:#fff; - .remote, - .local {position:relative;width:60%;height:auto;margin:0 auto;padding:15px 0 30px;} - .local {width:96%;} - - .hide {display:none;} - - .section {display:block;width:100%;height:auto;margin:15px 0;line-height:35px; - - &.input {line-height:33px;border:1px solid #e9e9e9;} - - .label {float: left;width:30%;text-align:center;background:#f7f7f7;} - .txt {float: left;width:70%;height:33px;padding:0 8px;border:0;border-left:1px solid #e9e9e9;background:#fff;color:#666;} - .submit {float:right;width:30%;height:35px;background:#ddd;color:#666;text-align:center;} - } - - - .select-file {width:100%;height:35px;line-height:33px} - .select-file span.file {float:left;width:100px;height:35px;border:1px solid #ddd;background:#f7f7f7;color:#666;text-align:center;cursor:pointer;} - .select-file span.tips {display:inline-block;padding:0 10px;line-height:35px;color:#666;} - .upload-box {width:100%;height:auto;min-height:190px;margin:10px 0;border:1px solid #e2e2e2;} - .upload-box .tr {width:100%;height:35px;line-height:35px;text-align:center;} - .upload-box .tr:hover {background:#fafafa} - .upload-box .thead {line-height:34px;border-bottom:1px solid #e2e2e2;background:#f7f7f7;} - - .upload-box .td {float:left;} - .upload-box .td.name {width:45%;} - .upload-box .td.progress {width:40%;} - .upload-box .td.option {width:15%;} - .upload-box .td.option a {display:inline-block;padding:3px 5px;line-height:13px;border:1px solid #e2e2e2;background:#f7f7f7;color:#666;} - .upload-box .td .red {color:#f30;} - - .manager {overflow:hidden;overflow-y:auto;width:100%;height:320px;padding:10px;} - .manager .item {float:left;width:22%;height:130px;margin:10px 1.5%;padding:5px;} - .manager .item:hover {background:#f7f7f7;} - .manager .thumb {display:block;width:100%;height:100px;} - .manager .name {overflow:hidden;height:20px;line-height:30px; text-align:center;} - .manager img {width:100%;height:100%;} - .manager .attach-icon {display:inline-block;width:100%;height:100px;text-align:center;font:50px/100px "ui font" !important;-webkit-font-smoothing: antialiased;-webkit-text-stroke-width: 0.2px;-moz-osx-font-smoothing: grayscale;} + .select-file {width:100%;height:35px;line-height:35px; + + .file {float:left;width:100px;height:35px;border-radius:3px;background:nth($cp, 1);text-align:center;cursor:pointer; + + &:hover {background:nth($cp, 2);} + &:active {background:nth($cp, 3);} + } + .tips {display:inline-block;padding:0 10px;} } + + .upload-box {width:100%;height:auto;min-height:255px;padding-top:10px; + + .thead {width:100%;height:35px;line-height:35px;background:nth($cp, 2);} + .thead .col {text-align:center;} + + .col {float:left;height:30px;padding:0 5px;} + .col:nth-child(1) {width:50%} + .col:nth-child(2) {width:35%} + .col:nth-child(3) {width:15%} + + .tbody {overflow:hidden;overflow-y:auto;width:100%;height:220px; + p {display:block;width:100%;height:30px;line-height:30px;} + } + + .insert {display:inline-block;padding:3px 5px;line-height:13px;background:nth($cp, 2);color:nth($cgr, 1);cursor:pointer;} + .red {color:#f30;} + } + + + + + .manager {overflow:hidden;overflow-y:auto;width:100%;height:320px;padding:10px;} + .manager .item {float:left;width:22%;height:130px;margin:10px 1.5%;padding:5px;} + .manager .item:hover {background:#f7f7f7;} + .manager .thumb {display:block;width:100%;height:100px;} + .manager .name {overflow:hidden;height:20px;line-height:30px; text-align:center;} + .manager img {width:100%;height:100%;} + .manager .attach-icon {display:inline-block;width:100%;height:100px;text-align:center;font:50px/100px "ui font" !important;-webkit-font-smoothing: antialiased;-webkit-text-stroke-width: 0.2px;-moz-osx-font-smoothing: grayscale;} + } } \ No newline at end of file diff --git a/src/js/meditor/addon/base.js b/src/js/meditor/addon/base.js index deb64d7..fbda73b 100644 --- a/src/js/meditor/addon/base.js +++ b/src/js/meditor/addon/base.js @@ -20,32 +20,33 @@ function trim(str, sign) { return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '') } +const $doc = Anot(document) + const addon = { - h1: function(elem, vm) { + h1: function(elem) { let that = this - let editor = vm.$refs.editor let offset = Anot(elem).offset() - let wrap = this.selection(editor, true) || '在此输入文本' + let wrap = this.selection(true) || '在此输入文本' layer.open({ type: 7, menubar: false, maskClose: true, + maskColor: 'rgba(255,255,255,0)', fixed: true, insert: function(level) { - wrap = wrap.replace(/^#{1,6} /, '') - wrap = that.repeat('#', level) + ' ' + wrap - that.insert(editor, wrap, true) + wrap = wrap.replace(/^(#{1,6} )?/, '#'.repeat(level) + ' ') + that.insert(wrap, true) this.close() }, offset: [ - offset.top + 40 - that.doc.scrollTop(), + offset.top + 40 - $doc.scrollTop(), 'auto', 'auto', - offset.left - that.doc.scrollLeft() + offset.left - $doc.scrollLeft() ], shift: { - top: offset.top - that.doc.scrollTop(), - left: offset.left - that.doc.scrollLeft() + top: offset.top - $doc.scrollTop(), + left: offset.left - $doc.scrollLeft() }, content: ` ` }) }, - quote: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + quote: function(elem) { + let wrap = this.selection() || '在此输入文本' wrap = '> ' + wrap - this.insert(vm.$refs.editor, wrap, true) + this.insert(wrap, true) }, - bold: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + bold: function(elem) { + let wrap = this.selection() || '在此输入文本' let wraped = trim(wrap, '\\*\\*') wrap = wrap === wraped ? '**' + wrap + '**' : wraped - this.insert(vm.$refs.editor, wrap, true) + this.insert(wrap, true) }, - italic: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + italic: function(elem) { + let wrap = this.selection() || '在此输入文本' let wraped = trim(wrap, '_') wrap = wrap === wraped ? '_' + wrap + '_' : wraped - this.insert(vm.$refs.editor, wrap, true) + this.insert(wrap, true) }, - through: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + through: function(elem) { + let wrap = this.selection() || '在此输入文本' let wraped = trim(wrap, '~~') wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped - this.insert(vm.$refs.editor, wrap, true) + this.insert(wrap, true) }, - unordered: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + unordered: function(elem) { + let wrap = this.selection() || '在此输入文本' wrap = '* ' + wrap - this.insert(vm.$refs.editor, wrap, false) + this.insert(wrap, false) }, - ordered: function(elem, vm) { - let wrap = this.selection(vm.$refs.editor) || '在此输入文本' + ordered: function(elem) { + let wrap = this.selection() || '在此输入文本' wrap = '1. ' + wrap - this.insert(vm.$refs.editor, wrap, false) + this.insert(wrap, false) }, - hr: function(elem, vm) { - this.insert(vm.$refs.editor, '\n\n---\n\n', false) + hr: function(elem) { + this.insert('\n\n---\n\n', false) }, - link: function(elem, vm) { + link: function(elem) { let that = this let offset = Anot(elem).offset() - let wrap = this.selection(vm.$refs.editor) || '' + let wrap = this.selection() || '' layer.open({ type: 7, menubar: false, maskClose: true, + maskColor: 'rgba(255,255,255,0)', fixed: true, link: '', linkName: wrap, @@ -124,29 +126,29 @@ const addon = { this.linkTarget === 1 ? ' "target=_blank"' : '' })` - that.insert(vm.$refs.editor, val, false) + that.insert(val, false) this.close() }, offset: [ - offset.top + 40 - that.doc.scrollTop(), + offset.top + 40 - $doc.scrollTop(), 'auto', 'auto', - offset.left - that.doc.scrollLeft() + offset.left - $doc.scrollLeft() ], shift: { - top: offset.top - that.doc.scrollTop(), - left: offset.left - that.doc.scrollLeft() + top: offset.top - $doc.scrollTop(), + left: offset.left - $doc.scrollLeft() }, content: `
-
+
-
+
-