修复layer组件的回调及对shift属性的优化;移植meditor到新的框架
							parent
							
								
									8be3b9c70a
								
							
						
					
					
						commit
						d256f145cf
					
				|  | @ -4,7 +4,7 @@ $cpp: #651fff #7c4dff #6200ea; | ||||||
| $cb: #2196f3 #64b5f6 #1976d2; | $cb: #2196f3 #64b5f6 #1976d2; | ||||||
| $cr: #ff5722 #ff7043 #e64a19; | $cr: #ff5722 #ff7043 #e64a19; | ||||||
| $co: #ff9800 #ffa726 #f57c00; | $co: #ff9800 #ffa726 #f57c00; | ||||||
| $cp: #e7e8eb #ecf0f1 #bdc3c7; | $cp: #e7e8eb #ecf0f1 #d3d5db; | ||||||
| $cgr: #546e7a #607d8b #37474f; | $cgr: #546e7a #607d8b #37474f; | ||||||
| 
 | 
 | ||||||
| @mixin ts($c: all, $t: .2s, $m: ease-in-out){ | @mixin ts($c: all, $t: .2s, $m: ease-in-out){ | ||||||
|  |  | ||||||
|  | @ -182,8 +182,8 @@ class __layer__ { | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       mounted: function() { |       mounted: function() { | ||||||
|         if (typeof this.success === 'function') { |         if (typeof this.props.success === 'function') { | ||||||
|           this.success(_id) |           this.props.success.call(this) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | @ -216,7 +216,9 @@ class __layer__ { | ||||||
|       layBox.classList.add('__' + state.shift) |       layBox.classList.add('__' + state.shift) | ||||||
|     } else { |     } else { | ||||||
|       for (let k in state.shift) { |       for (let k in state.shift) { | ||||||
|         layBox.style.cssText += `${k}: ${state.shift[k]};` |         let val = state.shift[k] | ||||||
|  |         val += isFinite(val) ? 'px' : '' | ||||||
|  |         layBox.style.cssText += `${k}: ${val};` | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,414 +1,438 @@ | ||||||
| /** | /** | ||||||
|  *  |  * | ||||||
|  * @authors yutent (yutent@doui.cc) |  * @authors yutent (yutent@doui.cc) | ||||||
|  * @date    2017-04-19 21:17:26 |  * @date    2017-04-19 21:17:26 | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| "use strict"; | 'use strict' | ||||||
| 
 | 
 | ||||||
|  | define(['lib/layer/base', 'css!./attach'], function() { | ||||||
|  |   var Uploader = function(url) { | ||||||
|  |     this.url = url || '' | ||||||
|  |     this.init() | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| define([ |   Uploader.prototype = { | ||||||
|     'lib/layer/base', |     init: function() { | ||||||
|     'css!./attach' |       this.xhr = new XMLHttpRequest() | ||||||
|     ], function(){ |       this.form = new FormData() | ||||||
| 
 |       return this | ||||||
|     var Uploader = function(url){ |     }, | ||||||
|         this.url = url || '' |     field: function(key, val) { | ||||||
|         this.init() |       if (typeof key === 'object') { | ||||||
|     } |         for (var i in key) { | ||||||
| 
 |           this.form.append(i, key[i]) | ||||||
|     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 |  | ||||||
|         } |         } | ||||||
|  |       } 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 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   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, '') | ||||||
|  |           }) | ||||||
|  |           .start() | ||||||
|  |       }) | ||||||
|  |     } else { | ||||||
|  |       upload | ||||||
|  |         .field('file', blob) | ||||||
|  |         .onEnd(function(json) { | ||||||
|  |           ME.insert(vm.$editor, '') | ||||||
|  |         }) | ||||||
|  |         .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 | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       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() | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |     lang = { | ||||||
|  |       image: ['远程图片', '图片管理', '图片描述', '图片地址'], | ||||||
|  |       file: ['远程附件', '附件管理', '附件描述', '附件地址'] | ||||||
|  |     }, | ||||||
|  |     opened = false, //记录是否已经打开
 | ||||||
|  |     openType = 'image', //打开类型, 图片/附件
 | ||||||
|  |     cache = { | ||||||
|  |       //缓存附件列表
 | ||||||
|  |       image: [], | ||||||
|  |       file: [] | ||||||
|  |     }, | ||||||
|  |     fixCont = function() { | ||||||
|  |       return ( | ||||||
|  |         '<dl class="do-meditor-attach do-meditor-font">' + | ||||||
|  |         '<dt class="tab-box" :drag="do-layer" data-limit="window">' + | ||||||
|  |         '<span class="item" :class="active:tab === 1" :click="$switch(1)">' + | ||||||
|  |         lang[openType][0] + | ||||||
|  |         '</span>' + | ||||||
|  |         '<span class="item" :class="active:tab === 2" :click="$switch(2)">本地上传</span>' + | ||||||
|  |         '<span class="item" :class="active:tab === 3" :click="$switch(3)">' + | ||||||
|  |         lang[openType][1] + | ||||||
|  |         '</span>' + | ||||||
|  |         '<a href="javascript:;" :click="no" class="action-close do-ui-font"></a>' + | ||||||
|  |         '</dt>' + | ||||||
|  |         '<dt class="cont-box">' + | ||||||
|  |         '<div class="remote" :visible="tab === 1">' + | ||||||
|  |         '<section class="section do-fn-cl input"><span class="label">' + | ||||||
|  |         lang[openType][2] + | ||||||
|  |         '</span>' + | ||||||
|  |         '<input class="txt" :duplex="attachAlt" />' + | ||||||
|  |         '</section>' + | ||||||
|  |         '<section class="section do-fn-cl input"><span class="label">' + | ||||||
|  |         lang[openType][3] + | ||||||
|  |         '</span>' + | ||||||
|  |         '<input class="txt" :duplex="attach" />' + | ||||||
|  |         '</section>' + | ||||||
|  |         '<section class="section do-fn-cl">' + | ||||||
|  |         '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' + | ||||||
|  |         '</section>' + | ||||||
|  |         '</div>' + | ||||||
|  |         '<div class="local" :visible="tab === 2">' + | ||||||
|  |         '<div class="select-file"><input id="meditor-attch" multiple :change="$change" type="file" class="hide" /><span class="file" :click="$select">选择文件</span><span class="tips">(上传大小限制:单文件最大 ' + | ||||||
|  |         ((ME.maxSize / 1048576).toFixed(2) - 0) + | ||||||
|  |         'MB)</span></div>' + | ||||||
|  |         '<ul class="upload-box">' + | ||||||
|  |         '<li class="tr thead"><span class="td name">文件名</span><span class="td progress">上传进度</span><span class="td option">操作</span></li>' + | ||||||
|  |         '<li class="tr" :repeat="uploadFile">' + | ||||||
|  |         '<span class="td name" :text="el.name"></span>' + | ||||||
|  |         '<span class="td progress" :html="el.progress"></span>' + | ||||||
|  |         '<span class="td option"><a href="javascript:;" :click="$insert(el)">插入</a></span>' + | ||||||
|  |         '</li>' + | ||||||
|  |         '</ul>' + | ||||||
|  |         '</div>' + | ||||||
|  |         '<ul class="manager" :visible="tab === 3">' + | ||||||
|  |         '<li class="item" :repeat="attachList" :click="$insert(el)">' + | ||||||
|  |         '<span class="thumb" :html="el.thumb"></span>' + | ||||||
|  |         '<p class="name" :attr-title="el.name" :text="el.name"></p>' + | ||||||
|  |         '</li>' + | ||||||
|  |         '</ul>' + | ||||||
|  |         '</dt>' + | ||||||
|  |         '</dl>' | ||||||
|  |       ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |   /** | ||||||
|  |    * [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: '<span class="red">0%(失败,不允许的文件类型)</span>', | ||||||
|  |           url: '' | ||||||
|  |         }) | ||||||
|  |         continue | ||||||
|  |       } | ||||||
|  |       if (ME.maxSize > 0 && it.size > ME.maxSize) { | ||||||
|  |         vm.uploadFile.push({ | ||||||
|  |           name: it.name, | ||||||
|  |           progress: '<span class="red">0%(文件体积过大)</span>', | ||||||
|  |           url: '' | ||||||
|  |         }) | ||||||
|  |         continue | ||||||
|  |       } | ||||||
|  |       var fixName = | ||||||
|  |         Date.now().toString(16) + it.name.slice(it.name.lastIndexOf('.')) | ||||||
| 
 | 
 | ||||||
|     function uploadScreenshot(vm, blob){ |       var idx = vm.uploadFile.length, | ||||||
|         var upload = new Uploader(vm.uploadUrl || ME.uploadUrl) |         upload = new Uploader(vm.uploadUrl || ME.uploadUrl) | ||||||
|         if(ME.beforeUpload){ | 
 | ||||||
|             ME.beforeUpload(Date.now().toString(16) + '.jpg', function(qn){ |       vm.uploadFile.push({ name: it.name, progress: '0%', url: '' }) | ||||||
|                 upload.field('file', blob) | 
 | ||||||
|                     .field('token', qn.token) |       upload.field('file', it) | ||||||
|                     .field('key', qn.key) | 
 | ||||||
|                     .onEnd(function(json){ |       if (ME.beforeUpload) { | ||||||
|                         ME.insert(vm.$editor, '') |         ME.beforeUpload(fixName, function(qn) { | ||||||
|                     }) |           upload | ||||||
|                     .start() |             .field('token', qn.token) | ||||||
|  |             .field('key', qn.key) | ||||||
|  |             .onProgress(function(val) { | ||||||
|  |               vm.uploadFile[idx].progress = val + '%' | ||||||
|             }) |             }) | ||||||
|         }else{ |             .onEnd(function(json) { | ||||||
|             upload.field('file', blob) |               vm.uploadFile[idx].url = qn.url | ||||||
|                 .onEnd(function(json){ |  | ||||||
|                     ME.insert(vm.$editor, '') |  | ||||||
|                 }) |  | ||||||
|                 .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 |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             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() |  | ||||||
|             }) |             }) | ||||||
|         }, |             .start() | ||||||
|         lang = { |         }) | ||||||
|             image: ['远程图片', '图片管理', '图片描述', '图片地址'], |       } else { | ||||||
|             file: ['远程附件', '附件管理', '附件描述', '附件地址'] |         upload | ||||||
|         }, |           .onProgress(function(val) { | ||||||
|         opened = false, //记录是否已经打开
 |             vm.uploadFile[idx].progress = val + '%' | ||||||
|         openType = 'image', //打开类型, 图片/附件
 |           }) | ||||||
|         cache = { //缓存附件列表
 |           .onEnd(function(json) { | ||||||
|             image: [], |             vm.uploadFile[idx].url = json.data.url | ||||||
|             file: [] |           }) | ||||||
|         }, |           .start() | ||||||
|         fixCont = function(){ |       } | ||||||
|             return '<dl class="do-meditor-attach do-meditor-font">' |  | ||||||
|                 + '<dt class="tab-box" :drag="do-layer" data-limit="window">' |  | ||||||
|                     + '<span class="item" :class="active:tab === 1" :click="$switch(1)">' + lang[openType][0] +'</span>' |  | ||||||
|                     + '<span class="item" :class="active:tab === 2" :click="$switch(2)">本地上传</span>' |  | ||||||
|                     + '<span class="item" :class="active:tab === 3" :click="$switch(3)">' + lang[openType][1] + '</span>' |  | ||||||
|                     + '<a href="javascript:;" :click="no" class="action-close do-ui-font"></a>' |  | ||||||
|                 + '</dt>' |  | ||||||
|                 + '<dt class="cont-box">' |  | ||||||
|                     + '<div class="remote" :visible="tab === 1">' |  | ||||||
|                         + '<section class="section do-fn-cl input"><span class="label">'+ lang[openType][2] + '</span>' |  | ||||||
|                             + '<input class="txt" :duplex="attachAlt" />' |  | ||||||
|                         + '</section>' |  | ||||||
|                         + '<section class="section do-fn-cl input"><span class="label">'+ lang[openType][3] + '</span>' |  | ||||||
|                             + '<input class="txt" :duplex="attach" />' |  | ||||||
|                         + '</section>' |  | ||||||
|                         + '<section class="section do-fn-cl">' |  | ||||||
|                             + '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' |  | ||||||
|                         + '</section>' |  | ||||||
|                     + '</div>' |  | ||||||
|                     + '<div class="local" :visible="tab === 2">' |  | ||||||
|                         + '<div class="select-file"><input id="meditor-attch" multiple :change="$change" type="file" class="hide" /><span class="file" :click="$select">选择文件</span><span class="tips">(上传大小限制:单文件最大 ' |  | ||||||
|                             + ((ME.maxSize/1048576).toFixed(2) - 0) |  | ||||||
|                             + 'MB)</span></div>' |  | ||||||
|                         + '<ul class="upload-box">' |  | ||||||
|                             + '<li class="tr thead"><span class="td name">文件名</span><span class="td progress">上传进度</span><span class="td option">操作</span></li>' |  | ||||||
|                             + '<li class="tr" :repeat="uploadFile">' |  | ||||||
|                                 + '<span class="td name" :text="el.name"></span>' |  | ||||||
|                                 + '<span class="td progress" :html="el.progress"></span>' |  | ||||||
|                                 + '<span class="td option"><a href="javascript:;" :click="$insert(el)">插入</a></span>' |  | ||||||
|                             + '</li>' |  | ||||||
|                         + '</ul>' |  | ||||||
|                     + '</div>' |  | ||||||
|                     + '<ul class="manager" :visible="tab === 3">' |  | ||||||
|                         + '<li class="item" :repeat="attachList" :click="$insert(el)">' |  | ||||||
|                             + '<span class="thumb" :html="el.thumb"></span>' |  | ||||||
|                             + '<p class="name" :attr-title="el.name" :text="el.name"></p>' |  | ||||||
|                         + '</li>' |  | ||||||
|                     + '</ul>' |  | ||||||
|                 + '</dt>' |  | ||||||
|             + '</dl>' |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * [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: '<span class="red">0%(失败,不允许的文件类型)</span>', url: ''}) |  | ||||||
|                 continue |  | ||||||
|             } |  | ||||||
|             if(ME.maxSize > 0 && it.size > ME.maxSize){ |  | ||||||
|                 vm.uploadFile.push({name: it.name, progress: '<span class="red">0%(文件体积过大)</span>', 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){ |   function getAttach(vm, cb) { | ||||||
|         var xhr = new XMLHttpRequest(), |     var xhr = new XMLHttpRequest(), | ||||||
|             url = vm.manageUrl || ME.manageUrl; |       url = vm.manageUrl || ME.manageUrl | ||||||
| 
 | 
 | ||||||
|         if(/\?/.test(url)){ |     if (/\?/.test(url)) { | ||||||
|             url += '&type=' + openType |       url += '&type=' + openType | ||||||
|         }else{ |     } else { | ||||||
|             url += '?type=' + openType |       url += '?type=' + openType | ||||||
|         } |     } | ||||||
|         url += '&t=' + Math.random() |     url += '&t=' + Math.random() | ||||||
|          | 
 | ||||||
|         xhr.open('GET', url, true) |     xhr.open('GET', url, true) | ||||||
|         xhr.onreadystatechange = function(){ |     xhr.onreadystatechange = function() { | ||||||
|             if(this.readyState === 4 &&  |       if ( | ||||||
|             this.status === 200 && |         this.readyState === 4 && | ||||||
|             this.responseText !== ''){ |         this.status === 200 && | ||||||
|                 var res = this.responseText |         this.responseText !== '' | ||||||
|                 try{ |       ) { | ||||||
|                     res = JSON.parse(res) |         var res = this.responseText | ||||||
|                 }catch(err){} |         try { | ||||||
|                 cb(res) |           res = JSON.parse(res) | ||||||
|             }else{ |         } catch (err) {} | ||||||
|                 if(this.status !== 200 && this.responseText) |         cb(res) | ||||||
|                     console.error(this.responseText) |       } else { | ||||||
|  |         if (this.status !== 200 && this.responseText) | ||||||
|  |           console.error(this.responseText) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     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] | ||||||
|  | 
 | ||||||
|  |           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' | ||||||
|  |                         ? '<img src="' + it.url + '"/>' | ||||||
|  |                         : '<em class="attach-icon"></em>' | ||||||
|  |                     return it | ||||||
|  |                   }) | ||||||
|  |                   lvm.attachList = json.data.list | ||||||
|  |                 } | ||||||
|  |               }) | ||||||
|             } |             } | ||||||
|         } |           } | ||||||
|         xhr.send() |         }, | ||||||
|     } |         $select: yua.noop, | ||||||
| 
 |         $change: yua.noop, | ||||||
|     function showDialog(elem, vm){ |         $insert: function(it) { | ||||||
|         opened = true |           if (!it.url) { | ||||||
|         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] |  | ||||||
| 
 |  | ||||||
|                     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' ? '<img src="' + it.url + '"/>' : '<em class="attach-icon"></em>' |  | ||||||
|                                         return it |  | ||||||
|                                     }) |  | ||||||
|                                     lvm.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 = '' |  | ||||||
| 
 |  | ||||||
|                     ME.insert(vm.$editor, val) |  | ||||||
|                     lvm.no() |  | ||||||
|                 }, |  | ||||||
|                 success: function(id){ |  | ||||||
|                     var _this = yua.vmodels[id], |  | ||||||
|                         $file = document.body.querySelector('#meditor-attch') |  | ||||||
| 
 |  | ||||||
|                     _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() |  | ||||||
|             }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     ME.addon.image = function(elem, vm){ |  | ||||||
|         if(opened){ |  | ||||||
|             return |             return | ||||||
|         } |           } | ||||||
|         openType = 'image' |           var val = | ||||||
|         showDialog(elem, vm) |             (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 = '' | ||||||
|  | 
 | ||||||
|  |           ME.insert(vm.$editor, val) | ||||||
|  |           lvm.no() | ||||||
|  |         }, | ||||||
|  |         success: function(id) { | ||||||
|  |           var _this = yua.vmodels[id], | ||||||
|  |             $file = document.body.querySelector('#meditor-attch') | ||||||
|  | 
 | ||||||
|  |           _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() | ||||||
|  |       }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ME.addon.image = function(elem, vm) { | ||||||
|  |     if (opened) { | ||||||
|  |       return | ||||||
|     } |     } | ||||||
|  |     openType = 'image' | ||||||
|  |     showDialog(elem, vm) | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| 
 |   ME.addon.file = function(elem, vm) { | ||||||
|     ME.addon.file = function(elem, vm){ |     if (opened) { | ||||||
|         if(opened){ |       return | ||||||
|             return |  | ||||||
|         } |  | ||||||
|         openType = 'file' |  | ||||||
|         showDialog(elem, vm) |  | ||||||
|     } |     } | ||||||
|  |     openType = 'file' | ||||||
|  |     showDialog(elem, vm) | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| 
 |   return $init | ||||||
| 
 | }) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     return $init |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| }) |  | ||||||
|  |  | ||||||
|  | @ -6,10 +6,10 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| 'use strict' | 'use strict' | ||||||
| import 'layer/base' | import 'layer/index' | ||||||
| 
 | 
 | ||||||
| function objArr(num) { | function objArr(num) { | ||||||
|   var arr = [] |   let arr = [] | ||||||
|   while (num > 0) { |   while (num > 0) { | ||||||
|     arr.push({ v: 0 }) |     arr.push({ v: 0 }) | ||||||
|     num-- |     num-- | ||||||
|  | @ -19,292 +19,373 @@ function objArr(num) { | ||||||
| function trim(str, sign) { | function trim(str, sign) { | ||||||
|   return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '') |   return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '') | ||||||
| } | } | ||||||
| function getOrderArr(len) { | 
 | ||||||
|   var arr = [], |  | ||||||
|     i = 0 |  | ||||||
|   while (i < len) { |  | ||||||
|     arr.push(i++) |  | ||||||
|   } |  | ||||||
|   return arr |  | ||||||
| } |  | ||||||
| const addon = { | const addon = { | ||||||
|   h1: function(elem, vm) { |   h1: function(elem, vm) { | ||||||
|     var offset = Anot(elem).offset(), |     let that = this | ||||||
|       wrap = ME.selection(vm.$editor, true) || '在此输入文本', |     let editor = vm.$refs.editor | ||||||
|       h1ID = layer.open({ |     let offset = Anot(elem).offset() | ||||||
|         type: 7, |     let wrap = this.selection(editor, true) || '在此输入文本' | ||||||
|         menubar: false, |     layer.open({ | ||||||
|         shadeClose: true, |       type: 7, | ||||||
|         fixed: true, |       menubar: false, | ||||||
|         $insert: function(level) { |       maskClose: true, | ||||||
|           wrap = wrap.replace(/^#{1,6} /, '') |       fixed: true, | ||||||
|           wrap = ME.repeat('#', level) + ' ' + wrap |       insert: function(level) { | ||||||
|           ME.insert(vm.$editor, wrap, true) |         wrap = wrap.replace(/^#{1,6} /, '') | ||||||
|           layer.close(h1ID) |         wrap = that.repeat('#', level) + ' ' + wrap | ||||||
|         }, |         that.insert(editor, wrap, true) | ||||||
|         offset: [ |         this.close() | ||||||
|           offset.top + 37 - ME.doc.scrollTop(), |       }, | ||||||
|           'auto', |       offset: [ | ||||||
|           'auto', |         offset.top + 40 - that.doc.scrollTop(), | ||||||
|           offset.left - ME.doc.scrollLeft() |         'auto', | ||||||
|         ], |         'auto', | ||||||
|         content: |         offset.left - that.doc.scrollLeft() | ||||||
|           '<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">' + |       ], | ||||||
|           '<li :click="$insert(1)" class="h1">一级标题</li>' + |       shift: { | ||||||
|           '<li :click="$insert(2)" class="h2">二级标题</li>' + |         top: offset.top - that.doc.scrollTop(), | ||||||
|           '<li :click="$insert(3)" class="h3">三级标题</li>' + |         left: offset.left - that.doc.scrollLeft() | ||||||
|           '<li :click="$insert(4)" class="h4">四级标题</li>' + |       }, | ||||||
|           '<li :click="$insert(5)" class="h5">五级标题</li>' + |       content: ` | ||||||
|           '<li :click="$insert(6)" class="h6">六级标题</li>' + |       <ul class="do-meditor-h1 do-fn-noselect do-meditor__font"> | ||||||
|           '</ul>' |         <li :click="insert(1)" class="h1"><i class="do-meditor__icon icon-h1"></i>一级标题</li> | ||||||
|       }) |         <li :click="insert(2)" class="h2"><i class="do-meditor__icon icon-h2"></i>二级标题</li> | ||||||
|  |         <li :click="insert(3)" class="h3"><i class="do-meditor__icon icon-h3"></i>三级标题</li> | ||||||
|  |         <li :click="insert(4)" class="h4"><i class="do-meditor__icon icon-h4"></i>四级标题</li> | ||||||
|  |         <li :click="insert(5)" class="h5"><i class="do-meditor__icon icon-h5"></i>五级标题</li> | ||||||
|  |         <li :click="insert(6)" class="h6"><i class="do-meditor__icon icon-h6"></i>六级标题</li> | ||||||
|  |       </ul>` | ||||||
|  |     }) | ||||||
|   }, |   }, | ||||||
|   quote: function(elem, vm) { |   quote: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本' |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|     wrap = '> ' + wrap |     wrap = '> ' + wrap | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, true) |     this.insert(vm.$refs.editor, wrap, true) | ||||||
|   }, |   }, | ||||||
|   bold: function(elem, vm) { |   bold: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本', |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|       wraped = trim(wrap, '\\*\\*') |     let wraped = trim(wrap, '\\*\\*') | ||||||
| 
 | 
 | ||||||
|     wrap = wrap === wraped ? '**' + wrap + '**' : wraped |     wrap = wrap === wraped ? '**' + wrap + '**' : wraped | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, true) |     this.insert(vm.$refs.editor, wrap, true) | ||||||
|   }, |   }, | ||||||
|   italic: function(elem, vm) { |   italic: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本', |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|       wraped = trim(wrap, '_') |     let wraped = trim(wrap, '_') | ||||||
| 
 | 
 | ||||||
|     wrap = wrap === wraped ? '_' + wrap + '_' : wraped |     wrap = wrap === wraped ? '_' + wrap + '_' : wraped | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, true) |     this.insert(vm.$refs.editor, wrap, true) | ||||||
|   }, |   }, | ||||||
|   through: function(elem, vm) { |   through: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本', |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|       wraped = trim(wrap, '~~') |     let wraped = trim(wrap, '~~') | ||||||
| 
 | 
 | ||||||
|     wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped |     wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, true) |     this.insert(vm.$refs.editor, wrap, true) | ||||||
|   }, |   }, | ||||||
|   unordered: function(elem, vm) { |   unordered: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本' |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|     wrap = '* ' + wrap |     wrap = '* ' + wrap | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, false) |     this.insert(vm.$refs.editor, wrap, false) | ||||||
|   }, |   }, | ||||||
|   ordered: function(elem, vm) { |   ordered: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本' |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|     wrap = '1. ' + wrap |     wrap = '1. ' + wrap | ||||||
| 
 | 
 | ||||||
|     ME.insert(vm.$editor, wrap, false) |     this.insert(vm.$refs.editor, wrap, false) | ||||||
|   }, |   }, | ||||||
|   hr: function(elem, vm) { |   hr: function(elem, vm) { | ||||||
|     ME.insert(vm.$editor, '\n\n---\n\n', false) |     this.insert(vm.$refs.editor, '\n\n---\n\n', false) | ||||||
|   }, |   }, | ||||||
|   link: function(elem, vm) { |   link: function(elem, vm) { | ||||||
|     var offset = Anot(elem).offset(), |     let that = this | ||||||
|       wrap = ME.selection(vm.$editor) || '', |     let offset = Anot(elem).offset() | ||||||
|       layid = layer.open({ |     let wrap = this.selection(vm.$refs.editor) || '' | ||||||
|         type: 7, | 
 | ||||||
|         menubar: false, |     layer.open({ | ||||||
|         shadeClose: true, |       type: 7, | ||||||
|         fixed: true, |       menubar: false, | ||||||
|         link: '', |       maskClose: true, | ||||||
|         linkName: wrap, |       fixed: true, | ||||||
|         linkTarget: 1, |       link: '', | ||||||
|         $confirm: function() { |       linkName: wrap, | ||||||
|           var lvm = Anot.vmodels[layid] |       linkTarget: 1, | ||||||
|           if (!lvm.link || !lvm.linkName) { |       insert: function() { | ||||||
|             return layer.alert('链接文字和地址不能为空') |         if (!this.link || !this.linkName) { | ||||||
|           } |           return layer.toast('链接文字和地址不能为空', 'error') | ||||||
|           var val = |         } | ||||||
|             '[' + |         let val = `[${this.linkName}](${this.link} ${ | ||||||
|             lvm.linkName + |           this.linkTarget === 1 ? ' "target=_blank"' : '' | ||||||
|             '](' + |         })` | ||||||
|             lvm.link + | 
 | ||||||
|             (lvm.linkTarget === 1 ? ' "target=_blank"' : '') + |         that.insert(vm.$refs.editor, val, false) | ||||||
|             ')' |         this.close() | ||||||
|           ME.insert(vm.$editor, val, false) |       }, | ||||||
|           layer.close(layid) |       offset: [ | ||||||
|         }, |         offset.top + 40 - that.doc.scrollTop(), | ||||||
|         offset: [ |         'auto', | ||||||
|           offset.top + 37 - ME.doc.scrollTop(), |         'auto', | ||||||
|           'auto', |         offset.left - that.doc.scrollLeft() | ||||||
|           'auto', |       ], | ||||||
|           offset.left - ME.doc.scrollLeft() |       shift: { | ||||||
|         ], |         top: offset.top - that.doc.scrollTop(), | ||||||
|         content: |         left: offset.left - that.doc.scrollLeft() | ||||||
|           '<div class="do-meditor-common do-meditor-font">' + |       }, | ||||||
|           '<section class="input"><span class="label">链接文字</span>' + |       content: ` | ||||||
|           '<input class="txt" :duplex="linkName" />' + |       <div class="do-meditor-common do-meditor__font"> | ||||||
|           '</section>' + |         <section class="input"> | ||||||
|           '<section class="input"><span class="label">链接地址</span>' + |           <input class="txt" :duplex="linkName" placeholder="链接文字"/> | ||||||
|           '<input class="txt" :duplex="link"/>' + |         </section> | ||||||
|           '</section>' + |         <section class="input"> | ||||||
|           '<section>' + |           <input class="txt" :duplex="link" placeholder="链接地址"/> | ||||||
|           '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="1"/> 新窗口打开</label>' + |         </section> | ||||||
|           '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="2"/> 本窗口打开</label>' + |         <section> | ||||||
|           '</section>' + |           <label> | ||||||
|           '<section>' + |             <input  | ||||||
|           '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' + |               name="link"  | ||||||
|           '</section>' + |               type="radio"  | ||||||
|           '</div>' |               class="radio"  | ||||||
|       }) |               :duplex-number="linkTarget"  | ||||||
|  |               value="1"/> | ||||||
|  |             新窗口打开 | ||||||
|  |           </label> | ||||||
|  |           <label> | ||||||
|  |             <input  | ||||||
|  |               name="link"  | ||||||
|  |               type="radio"  | ||||||
|  |               class="radio"  | ||||||
|  |               :duplex-number="linkTarget"  | ||||||
|  |               value="2"/> | ||||||
|  |             本窗口打开 | ||||||
|  |           </label> | ||||||
|  |         </section> | ||||||
|  |         <section> | ||||||
|  |           <a  | ||||||
|  |             href="javascript:;"  | ||||||
|  |             class="do-meditor__button submit"  | ||||||
|  |             :click="insert">确定</a> | ||||||
|  |         </section> | ||||||
|  |       </div>` | ||||||
|  |     }) | ||||||
|   }, |   }, | ||||||
|   time: function(elem, vm) { |   time: function(elem, vm) { | ||||||
|     ME.insert(vm.$editor, new Date().format(), false) |     this.insert(vm.$refs.editor, new Date().format(), false) | ||||||
|   }, |   }, | ||||||
|   face: function(elem, vm) { |   face: function(elem, vm) { | ||||||
|     var offset = Anot(elem).offset(), |     let that = this | ||||||
|       faceid = 0, |     let offset = Anot(elem).offset() | ||||||
|       layid = layer.open({ | 
 | ||||||
|         type: 7, |     layer.open({ | ||||||
|         title: '插入表情', |       type: 7, | ||||||
|         fixed: true, |       title: '插入表情', | ||||||
|         shadeClose: true, |       fixed: true, | ||||||
|         arr: getOrderArr(36), |       maskClose: true, | ||||||
|         offset: [ |       arr: [ | ||||||
|           offset.top + 37 - ME.doc.scrollTop(), |         '😀', | ||||||
|           'auto', |         '😅', | ||||||
|           'auto', |         '😂', | ||||||
|           offset.left - ME.doc.scrollLeft() |         '🤣', | ||||||
|         ], |         '😇', | ||||||
|         content: |         '😉', | ||||||
|           '<ul class="do-meditor-face">' + |         '😍', | ||||||
|           '<li class="item" :repeat="arr" ><img :attr-src="ME.path + \'/addon/face/\' + el + \'.gif\'" :click="$insert(this.src)" /></li>' + |         '😗', | ||||||
|           '</ul>', |         '😋', | ||||||
|         $insert: function(src) { |         '😛', | ||||||
|           ME.insert(vm.$editor, '', false) |         '😜', | ||||||
|           layer.close(layid) |         '🤨', | ||||||
|         } |         '🧐', | ||||||
|       }) |         '🤓', | ||||||
|  |         '😎', | ||||||
|  |         '😞', | ||||||
|  |         '😔', | ||||||
|  |         '😭', | ||||||
|  |         '😤', | ||||||
|  |         '😡', | ||||||
|  |         '😱', | ||||||
|  |         '😰', | ||||||
|  |         '😓', | ||||||
|  |         '😬', | ||||||
|  |         '🙄', | ||||||
|  |         '😴', | ||||||
|  |         '😪', | ||||||
|  |         '🤮', | ||||||
|  |         '😷', | ||||||
|  |         '💩', | ||||||
|  |         '👻', | ||||||
|  |         '💀', | ||||||
|  |         '🤝', | ||||||
|  |         '👎', | ||||||
|  |         '👍', | ||||||
|  |         '🙏' | ||||||
|  |       ], | ||||||
|  |       offset: [ | ||||||
|  |         offset.top + 40 - that.doc.scrollTop(), | ||||||
|  |         'auto', | ||||||
|  |         'auto', | ||||||
|  |         offset.left - that.doc.scrollLeft() | ||||||
|  |       ], | ||||||
|  |       shift: { | ||||||
|  |         top: offset.top - that.doc.scrollTop(), | ||||||
|  |         left: offset.left - that.doc.scrollLeft() | ||||||
|  |       }, | ||||||
|  |       content: ` | ||||||
|  |         <ul class="do-meditor-face"> | ||||||
|  |           <li class="item" :repeat="arr"> | ||||||
|  |             <span :html="el" :click="insert(el)"></span> | ||||||
|  |           </li> | ||||||
|  |         </ul>`, | ||||||
|  |       insert: function(val) { | ||||||
|  |         that.insert(vm.$refs.editor, val, false) | ||||||
|  |         this.close() | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|   }, |   }, | ||||||
|   table: function(elem, vm) { |   table: function(elem, vm) { | ||||||
|     var offset = Anot(elem).offset() |     let that = this | ||||||
|  |     let offset = Anot(elem).offset() | ||||||
|  | 
 | ||||||
|     layer.open({ |     layer.open({ | ||||||
|       type: 7, |       type: 7, | ||||||
|       title: '0行 x 0列', |       title: '0行 x 0列', | ||||||
|       fixed: true, |       fixed: true, | ||||||
|       shadeClose: true, |       maskClose: true, | ||||||
|       offset: [ |       offset: [ | ||||||
|         offset.top + 37 - ME.doc.scrollTop(), |         offset.top + 40 - that.doc.scrollTop(), | ||||||
|         'auto', |         'auto', | ||||||
|         'auto', |         'auto', | ||||||
|         offset.left - ME.doc.scrollLeft() |         offset.left - that.doc.scrollLeft() | ||||||
|       ], |       ], | ||||||
|  |       shift: { | ||||||
|  |         top: offset.top - that.doc.scrollTop(), | ||||||
|  |         left: offset.left - that.doc.scrollLeft() | ||||||
|  |       }, | ||||||
|       matrix: objArr(10).map(function() { |       matrix: objArr(10).map(function() { | ||||||
|         return objArr(10) |         return objArr(10) | ||||||
|       }), |       }), | ||||||
|       content: |       content: ` | ||||||
|         '<ul class="do-meditor-table">' + |       <ul class="do-meditor-table" ref="table"> | ||||||
|         '<li :repeat="matrix"><span :repeat-o="el" :class="{active: o.v}" :data="{x: $index, y: $outer.$index}"></span></li>' + |         <li :repeat="matrix"> | ||||||
|         '</ul>', |           <span  | ||||||
|       success: function(id) { |             :repeat-o="el"  | ||||||
|         var tb = document.querySelector('.do-meditor-table'), |             :class="{active: o.v}"  | ||||||
|           _this = Anot.vmodels[id], |             :data="{x: $index, y: $outer.$index}"></span> | ||||||
|           lastx, |         </li> | ||||||
|           lasty |       </ul>`, | ||||||
|         Anot(tb).bind('mousemove', function(ev) { |       success: function() { | ||||||
|  |         let tb = this.$refs.table | ||||||
|  |         let lastx, lasty | ||||||
|  | 
 | ||||||
|  |         Anot(tb).bind('mousemove', ev => { | ||||||
|           if (ev.target.nodeName === 'SPAN') { |           if (ev.target.nodeName === 'SPAN') { | ||||||
|             var x = ev.target.dataset.x - 0, |             let x = ev.target.dataset.x - 0 | ||||||
|               y = ev.target.dataset.y - 0 |             let y = ev.target.dataset.y - 0 | ||||||
|             if (x === lastx && y === lasty) { |             if (x === lastx && y === lasty) { | ||||||
|               return |               return | ||||||
|             } |             } | ||||||
|             lastx = x |             lastx = x | ||||||
|             lasty = y |             lasty = y | ||||||
|             _this.title = y + 1 + '行 x ' + (x + 1) + '列' |             this.title = y + 1 + '行 x ' + (x + 1) + '列' | ||||||
|             for (var i = 0; i <= 9; i++) { |             for (let i = 0; i <= 9; i++) { | ||||||
|               for (var j = 0; j <= 9; j++) { |               for (let j = 0; j <= 9; j++) { | ||||||
|                 _this.matrix[i][j].v = i <= y && j <= x ? 1 : 0 |                 this.matrix[i][j].v = i <= y && j <= x ? 1 : 0 | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|         Anot(tb).bind('mouseleave', function(ev) { |         Anot(tb).bind('mouseleave', ev => { | ||||||
|           lastx = -1 |           lastx = -1 | ||||||
|           lasty = -1 |           lasty = -1 | ||||||
|           _this.title = '0行 x 0列' |           this.title = '0行 x 0列' | ||||||
|           for (var i = 0; i <= 9; i++) { |           for (let i = 0; i <= 9; i++) { | ||||||
|             for (var j = 0; j <= 9; j++) { |             for (let j = 0; j <= 9; j++) { | ||||||
|               _this.matrix[i][j].v = 0 |               this.matrix[i][j].v = 0 | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|         Anot(tb).bind('click', function(ev) { |         Anot(tb).bind('click', ev => { | ||||||
|           if (ev.target.nodeName === 'SPAN') { |           if (ev.target.nodeName === 'SPAN') { | ||||||
|             var x = ev.target.dataset.x - 0 + 1, |             let x = ev.target.dataset.x - 0 + 1 | ||||||
|               y = ev.target.dataset.y - 0 + 1 |             let y = ev.target.dataset.y - 0 + 1 | ||||||
| 
 | 
 | ||||||
|             var val = |             let thead = `\n\n${that.repeat('| 表头 ', x)}|\n` | ||||||
|               '\n\n' + |             let pipe = `${that.repeat('| -- ', x)}|\n` | ||||||
|               ME.repeat('| 表头 ', x) + |             let tbody = that.repeat(that.repeat('| ', x) + '|\n', y) | ||||||
|               '|\n' + | 
 | ||||||
|               ME.repeat('| -- ', x) + |             that.insert(vm.$refs.editor, thead + pipe + tbody, false) | ||||||
|               '|\n' + |             this.close() | ||||||
|               ME.repeat(ME.repeat('| ', x) + '|\n', y) |  | ||||||
|             ME.insert(vm.$editor, val, false) |  | ||||||
|             layer.close(id) |  | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|   }, |   }, | ||||||
|   image: function(elem, vm) { |   image: function(elem, vm) { | ||||||
|     var offset = Anot(elem).offset(), |     let that = this | ||||||
|       wrap = ME.selection(vm.$editor) || '', |     let offset = Anot(elem).offset() | ||||||
|       layid = layer.open({ |     let wrap = this.selection(vm.$refs.editor) || '' | ||||||
|         type: 7, |  | ||||||
|         menubar: false, |  | ||||||
|         shadeClose: true, |  | ||||||
|         fixed: true, |  | ||||||
|         img: '', |  | ||||||
|         imgAlt: wrap, |  | ||||||
|         $confirm: function() { |  | ||||||
|           var lvm = Anot.vmodels[layid] |  | ||||||
|           if (!lvm.img || !lvm.imgAlt) { |  | ||||||
|             return layer.alert('图片描述和图片地址不能为空') |  | ||||||
|           } |  | ||||||
|           var val = '' |  | ||||||
| 
 | 
 | ||||||
|           ME.insert(vm.$editor, val, false) |     layer.open({ | ||||||
|           layer.close(layid) |       type: 7, | ||||||
|         }, |       menubar: false, | ||||||
|         offset: [ |       maskClose: true, | ||||||
|           offset.top + 37 - ME.doc.scrollTop(), |       fixed: true, | ||||||
|           'auto', |       img: '', | ||||||
|           'auto', |       imgAlt: wrap, | ||||||
|           offset.left - ME.doc.scrollLeft() |       insert: function() { | ||||||
|         ], |         if (!this.img || !this.imgAlt) { | ||||||
|         content: |           return layer.toast('链接文字和地址不能为空', 'error') | ||||||
|           '<div class="do-meditor-common do-meditor-font">' + |         } | ||||||
|           '<section class="input"><span class="label">图片描述</span>' + |         let val = `` | ||||||
|           '<input class="txt" :duplex="imgAlt" />' + | 
 | ||||||
|           '</section>' + |         that.insert(vm.$refs.editor, val, false) | ||||||
|           '<section class="input"><span class="label">图片地址</span>' + |         this.close() | ||||||
|           '<input class="txt" :duplex="img"/>' + |       }, | ||||||
|           '</section>' + |       offset: [ | ||||||
|           '<section>' + |         offset.top + 40 - that.doc.scrollTop(), | ||||||
|           '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' + |         'auto', | ||||||
|           '</section>' + |         'auto', | ||||||
|           '</div>' |         offset.left - that.doc.scrollLeft() | ||||||
|       }) |       ], | ||||||
|  |       shift: { | ||||||
|  |         top: offset.top - that.doc.scrollTop(), | ||||||
|  |         left: offset.left - that.doc.scrollLeft() | ||||||
|  |       }, | ||||||
|  |       content: ` | ||||||
|  |       <div class="do-meditor-common do-meditor__font"> | ||||||
|  |         <section class="input"> | ||||||
|  |           <input class="txt" :duplex="imgAlt" placeholder="图片描述"/> | ||||||
|  |         </section> | ||||||
|  |         <section class="input"> | ||||||
|  |           <input class="txt" :duplex="img" placeholder="图片地址"/> | ||||||
|  |         </section> | ||||||
|  |         <section> | ||||||
|  |           <a  | ||||||
|  |             href="javascript:;"  | ||||||
|  |             class="do-meditor__button submit"  | ||||||
|  |             :click="insert">确定</a> | ||||||
|  |         </section> | ||||||
|  |       </div> | ||||||
|  |       ` | ||||||
|  |     }) | ||||||
|   }, |   }, | ||||||
|   file: function(elem, vm) { |   attach: function(elem, vm) { | ||||||
|     this.link(elem, vm, false) |     this.addon.link.call(this, elem, vm, false) | ||||||
|   }, |   }, | ||||||
|   inlinecode: function(elem, vm) { |   inlinecode: function(elem, vm) { | ||||||
|     var wrap = ME.selection(vm.$editor) || '在此输入文本', |     let wrap = this.selection(vm.$refs.editor) || '在此输入文本' | ||||||
|       wraped = trim(wrap, '`') |     let wraped = trim(wrap, '`') | ||||||
| 
 | 
 | ||||||
|     wrap = wrap === wraped ? '`' + wrap + '`' : wraped |     wrap = wrap === wraped ? '`' + wrap + '`' : wraped | ||||||
|     ME.insert(vm.$editor, wrap, true) |     this.insert(vm.$refs.editor, wrap, true) | ||||||
|   }, |   }, | ||||||
|   blockcode: function(elem, vm) { |   blockcode: function(elem, vm) { | ||||||
|     var layid = layer.open({ |     let that = this | ||||||
|  |     layer.open({ | ||||||
|       type: 7, |       type: 7, | ||||||
|       title: '添加代码块', |       title: '添加代码块', | ||||||
|       $lang: [ |       $lang: [ | ||||||
|  | @ -350,11 +431,11 @@ const addon = { | ||||||
|         var val = |         var val = | ||||||
|           '\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n' |           '\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n' | ||||||
| 
 | 
 | ||||||
|         ME.insert(vm.$editor, val, false) |         that.insert(vm.$refs.editor, val, false) | ||||||
|         layer.close(layid) |         layer.close(layid) | ||||||
|       }, |       }, | ||||||
|       content: |       content: | ||||||
|         '<div class="do-meditor-codeblock do-meditor-font">' + |         '<div class="do-meditor-codeblock do-meditor__font">' + | ||||||
|         '<section class="do-fn-cl"><span class="label">语言类型</span>' + |         '<section class="do-fn-cl"><span class="label">语言类型</span>' + | ||||||
|         '<select :duplex="lang">' + |         '<select :duplex="lang">' + | ||||||
|         '<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' + |         '<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' + | ||||||
|  | @ -384,9 +465,11 @@ const addon = { | ||||||
|     layer.open({ |     layer.open({ | ||||||
|       type: 7, |       type: 7, | ||||||
|       title: '关于编辑器', |       title: '关于编辑器', | ||||||
|       offset: [offset.top + 37 - ME.doc.scrollTop()], |       maskClose: true, | ||||||
|  |       offset: [offset.top + 37 - this.doc.scrollTop()], | ||||||
|  |       shift: { top: offset.top - this.doc.scrollTop() }, | ||||||
|       content: |       content: | ||||||
|         '<div class="do-meditor-about do-meditor-font">' + |         '<div class="do-meditor-about do-meditor__font">' + | ||||||
|         '<pre>' + |         '<pre>' + | ||||||
|         ' __  __ _____    _ _ _\n' + |         ' __  __ _____    _ _ _\n' + | ||||||
|         '|  \\/  | ____|__| (_) |_ ___  _ __\n' + |         '|  \\/  | ____|__| (_) |_ ___  _ __\n' + | ||||||
|  | @ -394,7 +477,7 @@ const addon = { | ||||||
|         '| |  | | |__| (_| | | || (_) | |\n' + |         '| |  | | |__| (_| | | || (_) | |\n' + | ||||||
|         '|_|  |_|_____\\__,_|_|\\__\\___/|_|    ' + |         '|_|  |_|_____\\__,_|_|\\__\\___/|_|    ' + | ||||||
|         'v' + |         'v' + | ||||||
|         ME.version + |         this.version + | ||||||
|         '</pre>' + |         '</pre>' + | ||||||
|         '<p>开源在线Markdown编辑器</p>' + |         '<p>开源在线Markdown编辑器</p>' + | ||||||
|         '<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' + |         '<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' + | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | export default 1234 | ||||||
|  | @ -17,13 +17,14 @@ marked.setOptions({ | ||||||
|     return Prism.highlight(code, Prism.languages[lang]) |     return Prism.highlight(code, Prism.languages[lang]) | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| var editorVM = [] | let editorVM = [] | ||||||
| Anot.ui.meditor = '1.0.0' | Anot.ui.meditor = '1.0.0' | ||||||
|  | const log = console.log | ||||||
| //存放编辑器公共静态资源
 | //存放编辑器公共静态资源
 | ||||||
| window.ME = { | window.ME = { | ||||||
|   version: Anot.ui.meditor, |   version: Anot.ui.meditor, | ||||||
|  |   // 工具栏title
 | ||||||
|   toolbar: { |   toolbar: { | ||||||
|     //工具栏title
 |  | ||||||
|     pipe: '', |     pipe: '', | ||||||
|     h1: '标题', |     h1: '标题', | ||||||
|     quote: '引用文本', |     quote: '引用文本', | ||||||
|  | @ -45,19 +46,19 @@ window.ME = { | ||||||
|     fullscreen: '全屏', |     fullscreen: '全屏', | ||||||
|     about: '关于编辑器' |     about: '关于编辑器' | ||||||
|   }, |   }, | ||||||
|   addon, //已有插件
 |   addon, // 已有插件
 | ||||||
|   //往文本框中插入内容
 |   // 往文本框中插入内容
 | ||||||
|   insert: function(dom, val, isSelect) { |   insert: function(dom, val, isSelect) { | ||||||
|     if (document.selection) { |     if (document.selection) { | ||||||
|       dom.focus() |       dom.focus() | ||||||
|       var range = document.selection.createRange() |       let range = document.selection.createRange() | ||||||
|       range.text = val |       range.text = val | ||||||
|       dom.focus() |       dom.focus() | ||||||
|       range.moveStart('character', -1) |       range.moveStart('character', -1) | ||||||
|     } else if (dom.selectionStart || dom.selectionStart === 0) { |     } else if (dom.selectionStart || dom.selectionStart === 0) { | ||||||
|       var startPos = dom.selectionStart, |       let startPos = dom.selectionStart | ||||||
|         endPos = dom.selectionEnd, |       let endPos = dom.selectionEnd | ||||||
|         scrollTop = dom.scrollTop |       let scrollTop = dom.scrollTop | ||||||
| 
 | 
 | ||||||
|       dom.value = |       dom.value = | ||||||
|         dom.value.slice(0, startPos) + |         dom.value.slice(0, startPos) + | ||||||
|  | @ -82,15 +83,15 @@ window.ME = { | ||||||
|     if (document.selection) { |     if (document.selection) { | ||||||
|       return document.selection.createRange().text |       return document.selection.createRange().text | ||||||
|     } else { |     } else { | ||||||
|       var startPos = dom.selectionStart, |       let startPos = dom.selectionStart | ||||||
|         endPos = dom.selectionEnd |       let endPos = dom.selectionEnd | ||||||
| 
 | 
 | ||||||
|       if (endPos) { |       if (endPos) { | ||||||
|         //强制选择整行
 |         //强制选择整行
 | ||||||
|         if (line) { |         if (line) { | ||||||
|           startPos = dom.value.slice(0, startPos).lastIndexOf('\n') |           startPos = dom.value.slice(0, startPos).lastIndexOf('\n') | ||||||
| 
 | 
 | ||||||
|           var tmpEnd = dom.value.slice(endPos).indexOf('\n') |           let tmpEnd = dom.value.slice(endPos).indexOf('\n') | ||||||
|           tmpEnd = tmpEnd < 0 ? 0 : tmpEnd |           tmpEnd = tmpEnd < 0 ? 0 : tmpEnd | ||||||
| 
 | 
 | ||||||
|           startPos += 1 //把\n加上
 |           startPos += 1 //把\n加上
 | ||||||
|  | @ -169,27 +170,24 @@ var elems = { | ||||||
|   }, |   }, | ||||||
|   hr: '\n\n___\n\n', |   hr: '\n\n___\n\n', | ||||||
|   a: function(str, attr, inner) { |   a: function(str, attr, inner) { | ||||||
|     var href = attr.match(attrExp('href')), |     let href = attr.match(attrExp('href')) | ||||||
|       title = attr.match(attrExp('title')), |     let title = attr.match(attrExp('title')) | ||||||
|       tar = attr.match(attrExp('target')) |     let tar = attr.match(attrExp('target')) | ||||||
|  |     let attrs = '' | ||||||
| 
 | 
 | ||||||
|     href = (href && href[1]) || '' |     href = (href && href[1]) || null | ||||||
|     title = (title && title[1]) || '' |     title = (title && title[1]) || null | ||||||
|     tar = (tar && tar[1]) || '_self' |     tar = (tar && tar[1]) || '_self' | ||||||
| 
 | 
 | ||||||
|     href = href === 'javascript:void(0);' ? 'javascript:;' : href |     if (!href) { | ||||||
|  |       return inner || href | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return ( |     href = href.replace('viod(0)', '') | ||||||
|       '[' + |     attrs = `target=${tar}` | ||||||
|       (inner || href) + |     attrs += title ? `;title=${title}` : '' | ||||||
|       '](' + | 
 | ||||||
|       href + |     return `[${inner || href}](${href} "${attrs}")` | ||||||
|       ' "title=' + |  | ||||||
|       title + |  | ||||||
|       ';target=' + |  | ||||||
|       tar + |  | ||||||
|       '")' |  | ||||||
|     ) |  | ||||||
|   }, |   }, | ||||||
|   em: function(str, attr, inner) { |   em: function(str, attr, inner) { | ||||||
|     return (inner && '_' + inner + '_') || '' |     return (inner && '_' + inner + '_') || '' | ||||||
|  | @ -233,7 +231,12 @@ function html2md(str) { | ||||||
|   try { |   try { | ||||||
|     str = decodeURIComponent(str) |     str = decodeURIComponent(str) | ||||||
|   } catch (err) {} |   } catch (err) {} | ||||||
|   str = str.replace(/\t/g, '    ').replace(/<meta [^>]*>/, '') | 
 | ||||||
|  |   str = str.replace(/\t/g, '  ').replace(/<meta [^>]*>/, '') | ||||||
|  |   str = str.replace( | ||||||
|  |     /<(div|span|dl|dd|dt|table|tr|td|thead|tbody|i|em|strong|h[1-6]|ul|ol|li) [^>]*>/g, | ||||||
|  |     '<$1>' | ||||||
|  |   ) | ||||||
| 
 | 
 | ||||||
|   for (var i in elems) { |   for (var i in elems) { | ||||||
|     var cb = elems[i], |     var cb = elems[i], | ||||||
|  | @ -313,7 +316,7 @@ var defaultToolbar = [ | ||||||
|     '|', |     '|', | ||||||
|     'table', |     'table', | ||||||
|     'image', |     'image', | ||||||
|     'file', |     'attach', | ||||||
|     'inlinecode', |     'inlinecode', | ||||||
|     'blockcode', |     'blockcode', | ||||||
|     '|', |     '|', | ||||||
|  | @ -330,7 +333,7 @@ function tool(name) { | ||||||
|   return ( |   return ( | ||||||
|     '<span title="' + |     '<span title="' + | ||||||
|     ME.toolbar[name] + |     ME.toolbar[name] + | ||||||
|     '" class="icon-' + |     '" class="do-meditor__icon icon-' + | ||||||
|     name + |     name + | ||||||
|     '" ' + |     '" ' + | ||||||
|     (name !== 'pipe' ? ':click="onToolClick(\'' + name + '\', $event)"' : '') + |     (name !== 'pipe' ? ':click="onToolClick(\'' + name + '\', $event)"' : '') + | ||||||
|  | @ -340,35 +343,43 @@ function tool(name) { | ||||||
| 
 | 
 | ||||||
| Anot.component('meditor', { | Anot.component('meditor', { | ||||||
|   render: function() { |   render: function() { | ||||||
|     var toolbar = (this.toolbar || defaultToolbar) |     let toolbar = (this.toolbar || defaultToolbar).map(it => tool(it)).join('') | ||||||
|       .map(function(it) { | 
 | ||||||
|         return tool(it) |  | ||||||
|       }) |  | ||||||
|       .join('') |  | ||||||
|     delete this.toolbar |     delete this.toolbar | ||||||
|     return ( | 
 | ||||||
|       '<div class="do-meditor do-meditor-font" :visible="editorVisible"' + |     return ` | ||||||
|       ' :class="{fullscreen: fullscreen, preview: preview}">' + |     <div  | ||||||
|       '<div class="tool-bar do-ui-font do-fn-noselect">{toolbar}</div>' + |       class="do-meditor do-meditor__font"  | ||||||
|       '<textarea ref="textarea" class="editor-body" spellcheck="false" :duplex="plainTxt" :attr="{disabled: disabled}" :on-paste="$paste($event)"></textarea>' + |       :visible="editorVisible" | ||||||
|       '<content class="md-preview do-marked-theme" :visible="preview" :html="htmlTxt"></content>' + |       :class="{fullscreen: fullscreen, preview: preview}"> | ||||||
|       '</div>' |       <div class="tool-bar do-fn-noselect">${toolbar}</div> | ||||||
|     ).replace(/\{toolbar\}/g, toolbar) |       <textarea  | ||||||
|  |         ref="editor" | ||||||
|  |         class="editor-body"  | ||||||
|  |         spellcheck="false"  | ||||||
|  |         :attr="{disabled: disabled}" | ||||||
|  |         :duplex="plainTxt" | ||||||
|  |         :on-paste="onPaste($event)"></textarea> | ||||||
|  |       <content  | ||||||
|  |         class="md-preview do-marked-theme"  | ||||||
|  |         :visible="preview"  | ||||||
|  |         :html="htmlTxt"></content> | ||||||
|  |     </div> | ||||||
|  |     ` | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   construct: function(base, opt, attr) { |   construct: function(props, state) { | ||||||
|     Anot.mix(base, opt, attr) |     // Anot.mix(base, opt, attr)
 | ||||||
|     if (base.$addons && Array.isArray(base.$addons)) { |     // if (base.$addons && Array.isArray(base.$addons)) {
 | ||||||
|       extraAddons = base.$addons.map(function(name) { |     //   extraAddons = base.$addons.map(function(name) {
 | ||||||
|         return ME.path + '/addon/' + name |     //     return ME.path + '/addon/' + name
 | ||||||
|       }) |     //   })
 | ||||||
|       delete base.$addons |     //   delete base.$addons
 | ||||||
|  |     // }
 | ||||||
|  |     if (props.hasOwnProperty('$show')) { | ||||||
|  |       state.editorVisible = props.$show | ||||||
|  |       delete props.$show | ||||||
|     } |     } | ||||||
|     if (base.hasOwnProperty('$show')) { |  | ||||||
|       base.editorVisible = base.$show |  | ||||||
|       delete base.$show |  | ||||||
|     } |  | ||||||
|     return base |  | ||||||
|   }, |   }, | ||||||
|   componentWillMount: function(vm) {}, |   componentWillMount: function(vm) {}, | ||||||
|   componentDidMount: function(vm, elem) { |   componentDidMount: function(vm, elem) { | ||||||
|  | @ -411,25 +422,32 @@ Anot.component('meditor', { | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
|     plainTxt: function(val) { |     plainTxt: function(val) { | ||||||
|       this.$compile() |       this.compile() | ||||||
|       //只有开启实时预览,才会赋值给htmlTxt
 |       //只有开启实时预览,才会赋值给htmlTxt
 | ||||||
|       if (this.preview) { |       if (this.preview) { | ||||||
|         this.htmlTxt = this.$htmlTxt |         this.htmlTxt = this.$htmlTxt | ||||||
|       } |       } | ||||||
|       this.$onUpdate(this.plainTxt, vm.$htmlTxt) |       if (typeof this.props.onUpdate === 'function') { | ||||||
|  |         this.props.onUpdate(this.plainTxt, this.$htmlTxt) | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   state: { |   state: { | ||||||
|     disabled: false, //禁用编辑器
 |     disabled: false, //禁用编辑器
 | ||||||
|     fullscreen: false, //是否全屏
 |     fullscreen: false, //是否全屏
 | ||||||
|     preview: false, //是否显示预览
 |     preview: false, //是否显示预览
 | ||||||
|     $editor: null, //编辑器元素
 |     // $editor: null, //编辑器元素
 | ||||||
|     editorVisible: true, |     editorVisible: true, | ||||||
|     $htmlTxt: '', //临时储存html文本
 |     $htmlTxt: '', //临时储存html文本
 | ||||||
|     htmlTxt: '', //用于预览渲染
 |     htmlTxt: '', //用于预览渲染
 | ||||||
|     plainTxt: '', //纯md文本
 |     plainTxt: '', //纯md文本
 | ||||||
|     $safelyCompile: true |     $safelyCompile: true | ||||||
|   }, |   }, | ||||||
|  |   props: { | ||||||
|  |     onSuccess: Anot.PropsTypes.isFunction(), | ||||||
|  |     onUpdate: Anot.PropsTypes.isFunction(), | ||||||
|  |     onFullscreen: Anot.PropsTypes.isFunction() | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     onToolClick: function(name, ev) { |     onToolClick: function(name, ev) { | ||||||
|       if (ME.addon[name]) { |       if (ME.addon[name]) { | ||||||
|  | @ -438,24 +456,23 @@ Anot.component('meditor', { | ||||||
|         console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name) |         console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name) | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     $onSuccess: Anot.noop, |     onPaste: function(ev) { | ||||||
|     $onUpdate: Anot.noop, |  | ||||||
|     $onFullscreen: Anot.noop, |  | ||||||
|     $paste: function(ev) { |  | ||||||
|       ev.preventDefault() |       ev.preventDefault() | ||||||
|       var txt = ev.clipboardData.getData('text/plain').trim(), |       let txt = ev.clipboardData.getData('text/plain').trim() | ||||||
|         html = ev.clipboardData.getData('text/html').trim() |       let html = ev.clipboardData.getData('text/html').trim() | ||||||
| 
 | 
 | ||||||
|       html = html2md(html) |       html = html2md(html) | ||||||
| 
 | 
 | ||||||
|       if (html) { |       if (html) { | ||||||
|         ME.insert(this, html) |         ME.insert(ev.target, html) | ||||||
|       } else if (txt) { |       } else if (txt) { | ||||||
|         ME.insert(this, txt) |         ME.insert(ev.target, txt) | ||||||
|       } |       } | ||||||
|       this.plainTxt = this.value |       log(ev.target.value) | ||||||
|  |       this.plainTxt = this.$refs.editor.value | ||||||
|     }, |     }, | ||||||
|     compile: function() { |     compile: function() { | ||||||
|  |       log(this) | ||||||
|       var txt = this.plainTxt.trim() |       var txt = this.plainTxt.trim() | ||||||
| 
 | 
 | ||||||
|       if (this.$safelyCompile) { |       if (this.$safelyCompile) { | ||||||
|  |  | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -7,15 +7,13 @@ | ||||||
| 
 | 
 | ||||||
| import './highlight.scss' | import './highlight.scss' | ||||||
| 
 | 
 | ||||||
| var _self = window |  | ||||||
| 
 |  | ||||||
| var Prism = (function() { | var Prism = (function() { | ||||||
|   // Private helper vars
 |   // Private helper vars
 | ||||||
|   var lang = /\blang(?:uage)?-(\w+)\b/i |   var lang = /\blang(?:uage)?-(\w+)\b/i | ||||||
|   var uniqueId = 0 |   var uniqueId = 0 | ||||||
| 
 | 
 | ||||||
|   var _ = (_self.Prism = { |   var _ = (window.Prism = { | ||||||
|     manual: _self.Prism && _self.Prism.manual, |     manual: window.Prism && window.Prism.manual, | ||||||
|     util: { |     util: { | ||||||
|       encode: function(tokens) { |       encode: function(tokens) { | ||||||
|         if (tokens instanceof Token) { |         if (tokens instanceof Token) { | ||||||
|  | @ -221,7 +219,7 @@ var Prism = (function() { | ||||||
| 
 | 
 | ||||||
|       _.hooks.run('before-highlight', env) |       _.hooks.run('before-highlight', env) | ||||||
| 
 | 
 | ||||||
|       if (async && _self.Worker) { |       if (async && window.Worker) { | ||||||
|         var worker = new Worker(_.filename) |         var worker = new Worker(_.filename) | ||||||
| 
 | 
 | ||||||
|         worker.onmessage = function(evt) { |         worker.onmessage = function(evt) { | ||||||
|  | @ -487,13 +485,13 @@ var Prism = (function() { | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (!_self.document) { |   if (!window.document) { | ||||||
|     if (!_self.addEventListener) { |     if (!window.addEventListener) { | ||||||
|       // in Node.js
 |       // in Node.js
 | ||||||
|       return _self.Prism |       return window.Prism | ||||||
|     } |     } | ||||||
|     // In worker
 |     // In worker
 | ||||||
|     _self.addEventListener( |     window.addEventListener( | ||||||
|       'message', |       'message', | ||||||
|       function(evt) { |       function(evt) { | ||||||
|         var message = JSON.parse(evt.data), |         var message = JSON.parse(evt.data), | ||||||
|  | @ -501,15 +499,15 @@ var Prism = (function() { | ||||||
|           code = message.code, |           code = message.code, | ||||||
|           immediateClose = message.immediateClose |           immediateClose = message.immediateClose | ||||||
| 
 | 
 | ||||||
|         _self.postMessage(_.highlight(code, _.languages[lang], lang)) |         window.postMessage(_.highlight(code, _.languages[lang], lang)) | ||||||
|         if (immediateClose) { |         if (immediateClose) { | ||||||
|           _self.close() |           window.close() | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       false |       false | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     return _self.Prism |     return window.Prism | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   //Get current script and highlight
 |   //Get current script and highlight
 | ||||||
|  | @ -537,7 +535,7 @@ var Prism = (function() { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return _self.Prism |   return window.Prism | ||||||
| })() | })() | ||||||
| 
 | 
 | ||||||
| Prism.languages.markup = { | Prism.languages.markup = { | ||||||
|  |  | ||||||
|  | @ -232,7 +232,6 @@ Prism.languages.insertBefore('cpp', 'keyword', { | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| /*-----------------------coffeescript-----------------------*/ | /*-----------------------coffeescript-----------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   // Ignore comments starting with { to privilege string interpolation highlighting
 |   // Ignore comments starting with { to privilege string interpolation highlighting
 | ||||||
|   var comment = /#(?!\{).+/, |   var comment = /#(?!\{).+/, | ||||||
|  | @ -322,7 +321,6 @@ Prism.languages.insertBefore('cpp', 'keyword', { | ||||||
| })(Prism) | })(Prism) | ||||||
| 
 | 
 | ||||||
| /*---------------------------ruby---------------------------*/ | /*---------------------------ruby---------------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   Prism.languages.ruby = Prism.languages.extend('clike', { |   Prism.languages.ruby = Prism.languages.extend('clike', { | ||||||
|     comment: [ |     comment: [ | ||||||
|  | @ -650,7 +648,6 @@ Prism.languages.haskell = { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*---------------------------jade---------------------------*/ | /*---------------------------jade---------------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   Prism.languages.jade = { |   Prism.languages.jade = { | ||||||
|     comment: { |     comment: { | ||||||
|  | @ -862,7 +859,6 @@ Prism.languages.json = { | ||||||
| Prism.languages.jsonp = Prism.languages.json | Prism.languages.jsonp = Prism.languages.json | ||||||
| 
 | 
 | ||||||
| /*--------------------------kotlin----------------------------*/ | /*--------------------------kotlin----------------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   Prism.languages.kotlin = Prism.languages.extend('clike', { |   Prism.languages.kotlin = Prism.languages.extend('clike', { | ||||||
|     keyword: { |     keyword: { | ||||||
|  | @ -1525,7 +1521,6 @@ Prism.languages.rust = { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*------------------------------------------------------------*/ | /*------------------------------------------------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   Prism.languages.sass = Prism.languages.extend('css', { |   Prism.languages.sass = Prism.languages.extend('css', { | ||||||
|     // Sass comments don't need to be closed, only indented
 |     // Sass comments don't need to be closed, only indented
 | ||||||
|  | @ -1676,7 +1671,6 @@ Prism.languages.scss['atrule'].inside.rest = Prism.util.clone( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| /*-----------------------------smarty-------------------------*/ | /*-----------------------------smarty-------------------------*/ | ||||||
| 
 |  | ||||||
| ;(function(Prism) { | ;(function(Prism) { | ||||||
|   var smarty_pattern = /\{\*[\s\S]+?\*\}|\{[\s\S]+?\}/g |   var smarty_pattern = /\{\*[\s\S]+?\*\}|\{[\s\S]+?\}/g | ||||||
|   var smarty_litteral_start = '{literal}' |   var smarty_litteral_start = '{literal}' | ||||||
|  |  | ||||||
		Reference in New Issue
	
	 宇天
						宇天