diff --git a/build.dev.js b/build.dev.js index a9a0be5..d1827d0 100644 --- a/build.dev.js +++ b/build.dev.js @@ -22,8 +22,9 @@ const jsOpt = { plugins: [ 'transform-es2015-modules-amd', 'transform-decorators-legacy', - 'transform-class-properties', - 'transform-object-rest-spread' + 'transform-object-rest-spread', + ['transform-es2015-classes', { loose: true }], + ['transform-es2015-for-of', { loose: true }] ] } const cssOpt = { @@ -78,7 +79,6 @@ const compileHtm = (entry, output) => { /*===== ===*/ /*=======================================================*/ -const fontFiles = fs.ls('./src/font/', true) const jsFiles = fs.ls('./src/js/', true) const cssFiles = fs.ls('./src/css/', true) diff --git a/build.next.js b/build.next.js index b57a64d..0575040 100644 --- a/build.next.js +++ b/build.next.js @@ -65,7 +65,6 @@ const compileHtm = (entry, output) => { /*===== ===*/ /*=======================================================*/ -const fontFiles = fs.ls('./src/font/', true) const jsFiles = fs.ls('./src/js/', true) const cssFiles = fs.ls('./src/css/', true) @@ -74,11 +73,6 @@ if (fs.isdir(buildDir)) { log(chalk.cyan('清除旧目录 dist/')) } -// 字体文件直接复制 -fontFiles.forEach(file => { - fs.cp('./src/font/' + file, './dist/font/' + file) -}) - // css目录 cssFiles.forEach(file => { if (/\.scss$/.test(file)) { diff --git a/build.prod.js b/build.prod.js index 6d9527e..f5a487d 100644 --- a/build.prod.js +++ b/build.prod.js @@ -22,8 +22,9 @@ const jsOpt = { plugins: [ 'transform-es2015-modules-amd', 'transform-decorators-legacy', - 'transform-class-properties', - 'transform-object-rest-spread' + 'transform-object-rest-spread', + ['transform-es2015-classes', { loose: true }], + ['transform-es2015-for-of', { loose: true }] ] } const cssOpt = { @@ -37,10 +38,12 @@ const compileJs = (entry, output) => { } let t1 = Date.now() let tmpOpt = jsOpt - if (/anot/.test(entry)) { - tmpOpt = Object.assign({}, jsOpt, { plugins: [] }) + let code = '' + if (!/anot/.test(entry)) { + code = babel.transformFileSync(entry, jsOpt).code + } else { + code = fs.cat(entry).toString() } - let { code } = babel.transformFileSync(entry, tmpOpt) code = uglify.minify(code).code.replace(/\.scss/g, '.css') log( '编译JS: %s, 耗时 %s ms', @@ -79,7 +82,6 @@ const compileHtm = (entry, output) => { /*===== ===*/ /*=======================================================*/ -const fontFiles = fs.ls('./src/font/', true) const jsFiles = fs.ls('./src/js/', true) const cssFiles = fs.ls('./src/css/', true) @@ -88,11 +90,6 @@ if (fs.isdir(buildDir)) { log(chalk.cyan('清除旧目录 dist/')) } -// 字体文件直接复制 -fontFiles.forEach(file => { - fs.cp('./src/font/' + file, './dist/font/' + file) -}) - // css目录 cssFiles.forEach(file => { if (/\.scss$/.test(file)) { diff --git a/package.json b/package.json index 99ab780..274fd5f 100644 --- a/package.json +++ b/package.json @@ -12,21 +12,25 @@ "type": "git", "url": "git+https://github.com/yutent/doui.git" }, - "keywords": ["doui", "Anot"], + "keywords": [ + "doui", + "Anot" + ], "author": "yutent", "license": "MIT", "devDependencies": { "autoprefixer": "^7.2.6", - "babel-core": "^6.26.0", - "babel-plugin-transform-class-properties": "^6.24.1", + "babel-core": "^6.26.3", "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.23.0", "babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-preset-es2015": "^6.24.1", - "chalk": "^2.3.2", + "chalk": "^2.4.1", "chokidar": "^1.7.0", "iofs": "^1.0.3", - "node-sass": "^4.8.2", - "postcss": "^6.0.19", + "node-sass": "^4.9.0", + "postcss": "^6.0.22", "uglify-es": "^3.3.9" }, "dependencies": {} diff --git a/src/js/anot.shim.js b/src/js/anot.shim.js index f255be4..f39379b 100644 --- a/src/js/anot.shim.js +++ b/src/js/anot.shim.js @@ -234,20 +234,26 @@ vm.$id = $id VMODELS[$id] = vm - var $elem = document.querySelector('[anot=' + vm.$id + ']') - if ($elem) { - if ($elem === DOC.body) { - scanTag($elem, []) - } else { - var $parent = $elem - while (($parent = $parent.parentNode)) { - if ($parent.anotctrl) { - break + Anot.nextTick(function() { + var $elem = document.querySelector('[anot=' + vm.$id + ']') + if ($elem) { + if ($elem === DOC.body) { + scanTag($elem, []) + } else { + var $parent = $elem + while (($parent = $parent.parentNode)) { + if ($parent.anotctrl) { + break + } } + scanTag( + $elem.parentNode, + $parent ? [VMODELS[$parent.anotctrl]] : [] + ) } - scanTag($elem.parentNode, $parent ? [VMODELS[$parent.anotctrl]] : []) } - } + }) + return vm } else { this[0] = this.element = source @@ -2172,6 +2178,7 @@ injectDependency(array, binding) } }) + binding.getter = parseExpr(binding.expr, binding.vmodels, binding) binding.observers.forEach(function(a) { a.v.$watch(a.p, binding) @@ -3038,8 +3045,8 @@ } function addAssign(vars, vmodel, name, binding) { - var ret = [], - prefix = ' = ' + name + '.' + var ret = [] + var prefix = ' = ' + name + '.' for (var i = vars.length, prop; (prop = vars[--i]); ) { var arr = prop.split('.') var first = arr[0] @@ -3137,7 +3144,7 @@ /* jshint ignore:start */ var fn2 = scpCompile( names.concat( - "'use strict';" + 'return function(vvv){' + expr + ' = vvv\n}\n' + '"use strict";\n return function(vvv){' + expr + ' = vvv\n}\n' ) ) /* jshint ignore:end */ @@ -3178,11 +3185,23 @@ }) expr = '\nreturn ' + expr + ';' //IE全家 Function("return ")出错,需要Function("return ;") } + // log('') + // log( + // names + // .concat( + // "'use strict';\ntry{\nvar " + + // assigns.join(',\n') + + // expr + + // '\n}catch(e){console.log(e)}' + // ) + // .join('') + // ) + // log('') /* jshint ignore:start */ getter = scpCompile( names.concat( - "'use strict';\ntry{\nvar " + - assigns.join(',\n') + + "'use strict';\ntry{\n var " + + assigns.join(',\n ') + expr + '\n}catch(e){console.log(e)}' ) @@ -3290,7 +3309,7 @@ Anot.injectBinding(binding) if (binding.getter && binding.element.nodeType === 1) { //移除数据绑定,防止被二次解析 - //chrome使用removeAttributeNode移除不存在的特性节点时会报错 https://github.com/RubyLouvre/Anot/issues/99 + //chrome使用removeAttributeNode移除不存在的特性节点时会报错 binding.element.removeAttribute(binding.name) } } @@ -3505,8 +3524,8 @@ } function scanTag(elem, vmodels, node) { - //扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(100) - //--> :if-loop(110) --> :attr(970) ...--> :each(1400)-->:with(1500)--〉:duplex(2000)垫后 + //扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(90) + //--> :if-loop(110) --> :attr(970) ...--> :duplex(2000)垫后 var skip = elem.getAttribute('skip') node = elem.getAttributeNode('anot') var vm = vmodels.concat() @@ -3557,15 +3576,16 @@ newVmodel.props[k] = props[k] delete props[k] } else { - Anot.error( - 'props.' + - k + - ' needs [' + - newVmodel.props[k].checkType + - '], but [' + - newVmodel.props[k].result + - '] given.', - TypeError + console.error( + new TypeError( + 'props.' + + k + + ' needs [' + + newVmodel.props[k].checkType + + '], but [' + + newVmodel.props[k].result + + '] given.' + ) ) } } @@ -5463,11 +5483,6 @@ var kill = elem.previousSibling var start = binding.start - /*log(kill === start, kill) - while(kill !== start && kill.nodeName !== '#comment'){ - parent.removeChild(kill) - kill = elem.previousSibling - }*/ if (clear) { while (kill !== start) { parent.removeChild(kill) @@ -5509,9 +5524,6 @@ ) decorateProxy(proxy, binding, xtype) } else { - // if (xtype === "array") { - // proxy[param] = value[i] - // } fragments.push({}) retain[keyOrId] = true } @@ -5528,7 +5540,6 @@ if (xtype === 'array') { proxy.$first = i === 0 proxy.$last = i === length - 1 - // proxy[param] = value[i] } else { proxy.$val = toJson(value[keyOrId]) //这里是处理vm.object = newObject的情况 } diff --git a/src/js/layer/index.js b/src/js/layer/index.js index 8200f33..89e17f9 100644 --- a/src/js/layer/index.js +++ b/src/js/layer/index.js @@ -33,6 +33,7 @@ let defconf = { offset: [], // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左 btns: ['确定', '取消'] // 弹窗的2个按钮的文字 } +const $doc = Anot(document) const uuid = function() { return 'layer-' + lid++ } @@ -214,6 +215,9 @@ class __layer__ { outerBox.classList.add('do-layer') if (state.mask) { outerBox.classList.add('mask') + if (state.container && state.container !== document.body) { + outerBox.classList.add('inner') + } } if (state.maskColor) { outerBox.style.background = state.maskColor @@ -383,7 +387,6 @@ 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() @@ -564,23 +567,26 @@ const _layer = { return _layer.open(opt) }, - loading: function(style, time, cb) { + loading: function(style, container, cb) { style = style >>> 0 + style = style < 1 ? 1 : style > 5 ? 5 : style - if (typeof time === 'function') { - cb = time - time = 0 + if (typeof container === 'function') { + cb = container + container = null } else { - time = time >>> 0 + if (!(container instanceof HTMLElement)) { + container = null + } if (typeof cb !== 'function') { cb = Anot.noop } } return _layer.open({ + container, type: 6, load: style, yes: cb, - timeout: time, menubar: false, background: 'none', shift: 'ct', @@ -660,7 +666,7 @@ const _layer = { } Anot.directive('layer', { - priority: 1400, + priority: 8090, init: function(binding) { // 去掉:layer属性,避免二次扫描 binding.element.removeAttribute(binding.name) @@ -671,13 +677,15 @@ Anot.directive('layer', { }, update: function(val) { if (!val) { + console.error(this) return console.error( `SyntaxError: Unexpected [${this.name}=${this.expr}]` ) } + let state = Object.assign({ type: 7, wrap: true }, this.element.dataset) + if (!this.param) { - let state = Object.assign({ type: 7, wrap: true }, this.element.dataset) let init = { $id: 'layerwrap-' + val, state, props: {} } if (state.hasOwnProperty('area')) { @@ -709,7 +717,72 @@ Anot.directive('layer', { } layerDom[tmp.init.$id] = tmp.create() } else if (this.param === 'tips') { - _layer.tips(val, this.element) + let tips = document.createElement('div') + let cont = document.createElement('span') + let arrow = document.createElement('i') + tips.className = 'do-layer__tips' + cont.className = 'layer-content' + arrow.className = 'arrow' + cont.textContent = val + tips.appendChild(cont) + tips.appendChild(arrow) + this.element.appendChild(tips) + + if (state.color) { + style.color = state.color + } + if (state.color) { + style.background = state.background + } + + let style = {} + let css = getComputedStyle(tips) + let $container = Anot(this.element) + let cw = $container.innerWidth() + let ch = $container.innerHeight() + 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'] + + Anot(tips).css(style) + + $container.bind('mouseenter', ev => { + 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(tips).css(tmpStyle) + }) + $container.bind('mouseleave', () => { + setTimeout(() => { + arrow.classList.remove('offset-' + arrowOffset.join('-')) + arrowOffset = ['top'] + arrow.style.borderBottomColor = '' + arrow.style.borderTopColor = '' + tips.style.visibility = 'hidden' + }, 100) + }) + // _layer.tips(val, this.element) } } }) diff --git a/src/js/layer/skin/default.scss b/src/js/layer/skin/default.scss index 48b126b..4ebec21 100644 --- a/src/js/layer/skin/default.scss +++ b/src/js/layer/skin/default.scss @@ -75,9 +75,8 @@ /* tips类弹层(type 5) */ - &.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; + &.type-5 {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;color:#fff;background:rgba(0,0,0,.5);box-shadow:none; - // &.active {visibility:visible;opacity:1;} i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""} i.offset-top {left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);} i.offset-bottom {left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);} @@ -189,12 +188,23 @@ &.mask {position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.3); &.shift {transition: all .5s ease-out;} - + &.inner {position:absolute;} } &:active {z-index:65536;} } +/* 指令式的tips */ +.do-layer__tips {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,.5); + + i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""} + i.offset-top {left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);} + i.offset-bottom {left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);} + i.offset-top-left {right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);} + i.offset-bottom-left {right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);} + + .layer-content {min-height:20px;margin:0;padding:0} +} diff --git a/src/js/meditor/addon/attach.js b/src/js/meditor/addon/attach.js index 3452141..123b7de 100644 --- a/src/js/meditor/addon/attach.js +++ b/src/js/meditor/addon/attach.js @@ -11,6 +11,10 @@ import 'layer/index' import './attach.scss' const $doc = Anot(document) +const LANG = { + image: ['远程图片', '图片管理', '图片描述', '图片地址'], + file: ['远程附件', '附件管理', '附件描述', '附件地址'] +} class Uploader { constructor(url) { @@ -64,84 +68,6 @@ class Uploader { } } -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) { @@ -177,7 +103,7 @@ const fixCont = function(vm, tool) { 确定 + :click="confirm">确定