UNPKG

magix-components

Version:
547 lines 19.6 kB
/* ver:1.3.1 */ /* author:xinglie.lkf@alibaba-inc.com */ let Magix = require('magix'); let DD = require('../mx-dragdrop/index'); let Runner = require('../mx-runner/index'); let $ = require('$'); Magix.applyStyle('@index.less'); let BarId = Magix.guid('dbar_'); let PointerId = Magix.guid('pt_'); let Win = $(window); let Doc = $(document); let LEFT = 1; let TOP = 2; let RIGHT = 4; let BOTTOM = 8; let SCROLL_OFFSET = 20; let SCROLL_STEP = 7; let SCROLL_INTERVAL = 30; let HORIZONAL = 1; let VERTICAL = 2; let HANDV = HORIZONAL | VERTICAL; let UI = { '@{bar.create}'() { let node = $('#' + BarId); if (!node.length) { $('<div class="@index.less:bar" id="' + BarId + '"/>').appendTo('body'); } }, '@{drag.start}'(info) { if (info.child) { $(info.child).css({ opacity: 0.4 }); this['@{bar.create}'](); } }, '@{drag.end}'(info) { if (info.child) { $(info.child).css({ opacity: 1 }); } this['@{bar.hide}'](); this['@{pointer.hide}'](); }, '@{bar.hide}'() { $('#' + BarId).css({ left: -1e5 }); }, '@{bar.move}'(info, v) { let node = $('#' + BarId); let hasFound = false; if (info.anchor & VERTICAL) { if (v & TOP) { node.css({ height: 2, width: info.bound.width, top: info.bound.y - 1, left: info.bound.x }); hasFound = true; } else if (v & BOTTOM) { node.css({ height: 2, width: info.bound.width, top: info.bound.y + info.bound.height - 1, left: info.bound.x }); hasFound = true; } } if (!hasFound && info.anchor & HORIZONAL) { if (v & LEFT) { node.css({ height: info.bound.height, width: 2, top: info.bound.y, left: info.bound.x - 1 }); } else if (v & RIGHT) { node.css({ height: info.bound.height, width: 2, top: info.bound.y, left: info.bound.x + info.bound.width - 1 }); } } }, '@{pos.changed}'(info) { let me = this; if (info.atPlace && info.child != info.hover) { if (info.anchor == HANDV) { if (info['@{side.changed}']) { me['@{bar.move}'](info, info.side); } } else if (info['@{pos.changed}']) { me['@{bar.move}'](info, info.position); } me['@{pointer.change}'](true); } else { me['@{bar.hide}'](); me['@{pointer.change}'](); } }, '@{pointer.update}'(e) { let node = $('#' + PointerId); if (!node.length) { node = $('<div class="@index.less:pointer" id="' + PointerId + '"/>'); node.appendTo('body'); } let x = Math.max(0, Math.min(e.pageX + 10, Doc.width() - node.width())); let y = Math.max(0, Math.min(e.pageY + 18, Doc.height() - node.height())); node.css({ left: x, top: y, display: 'block' }); }, '@{pointer.change}'(state) { let node = $('#' + PointerId); if (state) { node.removeClass('@index.less:bad').addClass('@index.less:ok'); } else { node.addClass('@index.less:bad').removeClass('@index.less:ok'); } }, '@{pointer.hide}'() { $('#' + PointerId).hide(); } }; module.exports = Magix.View.extend({ init(extra) { let me = this; let oNode = $('#' + me.id); oNode.on('mousedown', extra.selector, e => { e.preventDefault(); me['@{drag.start}'](e); }); me.on('destroy', () => { oNode.off('mousedown'); }); me['@{owner.node}'] = oNode; let zones = [oNode.get(0)]; if (extra.drops) { zones = zones.concat(extra.drops.split(',')); } me['@{zone.ids}'] = zones; let hor = (extra.horizonal + '') === 'true'; let ver = (extra.vertical + '') === 'true'; if (!hor && !ver) { ver = true; } let anchor = 0; if (hor) { anchor |= HORIZONAL; } if (ver) { anchor |= VERTICAL; } me['@{anchor.direction}'] = anchor; let sort = true; if (Magix.has(extra, 'sort')) { sort = (extra.sort + '') === 'true'; } me['@{sort.ctrl}'] = sort; }, '@{findZone}'(node) { let me = this; let zones = me['@{zone.ids}']; for (let zone of zones) { if (Magix.inside(node, zone)) { return Magix.node(zone); } } return null; }, '@{findDirectChild}'(node, zone) { let me = this, result = null; if (!zone) { zone = me['@{findZone}'](node); } if (!me['@{sort.ctrl}'] && me['@{drag.start.node}']) { return { child: me['@{drag.start.node}'], zone: zone }; } while (zone != node) { if (node.parentNode == zone) { result = node; break; } else { node = node.parentNode; } } if (zone && !zone.firstChild && !result) { result = zone; } if (result) { if (result.getAttribute('ds-draggable') === 'false') { result = null; } } return { child: result, zone: zone }; }, '@{findPosition}'(nb, evt) { let position = 0, side = 0, toLeft = -1, toTop = -1, toRight = -1, toBottom = -1, hasNearest = false; if (evt.pageX >= nb.x && evt.pageX <= nb.x + nb.width && evt.pageY >= nb.y && evt.pageY <= nb.y + nb.height) { position = position | ((evt.pageX <= nb.x + nb.width / 2) ? LEFT : RIGHT); toLeft = evt.pageX - nb.x; toRight = nb.x + nb.width - evt.pageX; position = position | ((evt.pageY <= nb.y + nb.height / 2) ? TOP : BOTTOM); toTop = evt.pageY - nb.y; toBottom = nb.y + nb.height - evt.pageY; hasNearest = true; } if (hasNearest) { var temp = Math.min(toLeft, toTop, toRight, toBottom); if (temp > -1) { if (temp == toLeft) { side = LEFT; } else if (temp == toTop) { side = TOP; } else if (temp == toRight) { side = RIGHT; } else if (temp == toBottom) { side = BOTTOM; } } } let me = this; let info = me['@{hover.info}']; if (info) { if (info.zone === info.hover) { position = TOP; side = LEFT; } } return { position: position, atPlace: hasNearest, side: side }; }, '@{drag.start}'(e) { if (e.which === 1) { let me = this; let info = me['@{findDirectChild}'](e.target); if (info.child) { me['@{drag.start.node}'] = info.child; me['@{drag.start.zone}'] = info.zone; me['@{owner.node}'].trigger({ type: 'dragbegin', dragNode: info.child, dragZone: info.zone }); UI['@{drag.start}'](info); DD.begin(info.zone, e => { me['@{drag.move}'](e); }, e => { me['@{drag.end}'](e); }); } } }, '@{checkPosition}'(bound, e, info) { let me = this; let p = me['@{findPosition}'](bound, e); let sideChanage = p.side != me['@{last.side}'], positionChange = p.position != me['@{last.position}']; if (sideChanage || positionChange) { me['@{last.side}'] = p.side; me['@{last.position}'] = p.position; info['@{side.changed}'] = sideChanage; info['@{pos.changed}'] = positionChange; info.side = p.side; info.position = p.position; info.atPlace = p.atPlace; info.anchor = me['@{anchor.direction}']; UI['@{pos.changed}'](info); } }, '@{drag.move}'(e) { let current = DD.fromPoint(e.clientX, e.clientY); let me = this; UI['@{pointer.update}'](e); me['@{move.event}'] = e; me['@{has.moved}'] = true; me['@{start.zone.scroll}'](); me['@{start.win.scroll}'](); if (me['@{zone.start.scrolling}'] || me['@{win.start.scrolling}'] || !current) { delete me['@{last.hover.node}']; delete me['@{last.side}']; delete me['@{last.position}']; return; } if (me['@{last.hover.node}'] != current) { if (current.id === BarId) return;// me['@{last.hover.node}'] = current; delete me['@{last.side}']; let zone = me['@{findZone}'](current); if (zone) { if (zone != me['@{last.zone}']) { me['@{last.zone}'] = zone; me['@{owner.node}'].trigger({ type: 'enterzone', zone: zone, changePointer: UI['@{pointer.change}'] }); } let info = me['@{findDirectChild}'](current, zone); if (!info.child) return; let n = $(info.child); let offset = n.offset(); let bound = { x: offset.left, y: offset.top, width: n.outerWidth(), height: n.outerHeight() }; n = $(info.zone); offset = n.offset(); me['@{last.zone.bound}'] = { x: offset.left, y: offset.top, scrollX: n.prop('scrollLeft'), scrollY: n.prop('scrollTop'), maxWidth: n.prop('scrollWidth'), maxHeight: n.prop('scrollHeight'), width: n.width(), height: n.height() }; me['@{checkPosition}'](me['@{last.hover.node.bound}'] = bound, e, me['@{hover.info}'] = { child: me['@{drag.start.node}'], bound, zone: info.zone, hover: info.child }); } else if (me['@{last.zone}']) { me['@{owner.node}'].trigger({ type: 'leavezone', zone: me['@{last.zone}'], changePointer: UI['@{pointer.change}'] }); delete me['@{last.zone}']; } } else if (me['@{last.hover.node.bound}'] && Magix.inside(current, me['@{hover.info}'].zone)) { me['@{checkPosition}'](me['@{last.hover.node.bound}'], e, me['@{hover.info}']); } else { delete me['@{last.side}']; delete me['@{last.position}']; if (me['@{sort.ctrl}']) { UI['@{bar.hide}'](); UI['@{pointer.change}'](); } } }, '@{drag.end}'() { let me = this; me['@{stop.zone.scroll}'](); me['@{stop.win.scroll}'](); UI['@{drag.end}']({ child: me['@{drag.start.node}'] }); let position = me['@{last.position}'], side = me['@{last.side}'], move = me['@{has.moved}'], info = me['@{hover.info}'], dragNode = me['@{drag.start.node}']; if (move) { if (position || side) { let zone = info.zone; let a = me['@{anchor.direction}']; let v = a === HANDV ? side : position; if (((a & HORIZONAL) && (LEFT & v)) || ((TOP & v) && (a & VERTICAL))) { if (info.hover == zone) { zone.appendChild(dragNode); } else { zone.insertBefore(dragNode, info.hover); } } else if (((BOTTOM & v) && (a & VERTICAL)) || ((RIGHT & v) && (a & HORIZONAL))) { let next = info.hover.nextSibling; while (next && next.nodeType != 1) { next = next.nextSibling; } zone.insertBefore(dragNode, next); if (!next) {//如果是最后一个,则滚动 zone.scrollTop = zone.scrollHeight; } } } } if (info) { me['@{owner.node}'].trigger({ type: 'dragfinish', moved: move, dragNode: dragNode, dragZone: me['@{drag.start.zone}'], dropNode: info.hover, dropZone: info.zone, outZone: !me['@{last.zone}'] }); } delete me['@{drag.start.node}']; delete me['@{drag.start.zone}']; delete me['@{last.hover.node}']; delete me['@{hover.info}']; delete me['@{last.hover.node.bound}']; delete me['@{last.position}']; delete me['@{last.side}']; delete me['@{move.event}']; delete me['@{win.start.scrolling}']; delete me['@{last.zone}']; delete me['@{last.zone.bound}']; delete me['@{zone.start.scrolling}']; delete me['@{has.moved}']; }, '@{start.zone.scroll}'() { let me = this; if (!me['@{fn.zone.scroll}']) { me['@{fn.zone.scroll}'] = () => { let zoneBound = me['@{last.zone.bound}']; if (zoneBound) { let zone = me['@{hover.info}'].zone; let tx = 0, ty = 0, e = me['@{move.event}']; if (e.pageX > zoneBound.x && e.pageY > zoneBound.y && e.pageX < zoneBound.x + zoneBound.width && e.pageY < zoneBound.y + zoneBound.height) { if (e.pageX - zoneBound.x < SCROLL_OFFSET && zoneBound.scrollX > 0) { tx = -Math.min(SCROLL_STEP, zoneBound.scrollX); } else if (zoneBound.x + zoneBound.width - e.pageX < SCROLL_OFFSET && zoneBound.scrollX + zoneBound.width < zoneBound.maxWidth) { tx = Math.min(SCROLL_STEP, zoneBound.maxWidth - zoneBound.scrollX - zoneBound.width); } if (e.pageY - zoneBound.y < SCROLL_OFFSET && zoneBound.scrollY > 0) { ty = -Math.min(SCROLL_STEP, zoneBound.scrollY); } else if (zoneBound.y + zoneBound.height - e.pageY < SCROLL_OFFSET && zoneBound.scrollY + zoneBound.height < zoneBound.maxHeight) { ty = Math.min(SCROLL_STEP, zoneBound.maxHeight - zoneBound.scrollY - zoneBound.height); } if (tx || ty) { me['@{zone.start.scrolling}'] = true; me['@{prevent.win.scroll}'] = true; zone.scrollTop += ty; zone.scrollLeft += tx; zoneBound.scrollX += tx; zoneBound.scrollY += ty; delete me['@{has.moved}']; UI['@{bar.hide}'](); UI['@{pointer.change}'](); } else { delete me['@{zone.start.scrolling}']; delete me['@{prevent.win.scroll}']; } } else { delete me['@{zone.start.scrolling}']; delete me['@{prevent.win.scroll}']; } } }; Runner['@{task.add}'](SCROLL_INTERVAL, me['@{fn.zone.scroll}']); } }, '@{start.win.scroll}'() { let me = this; if (!me['@{fn.win.scroll}']) { me['@{fn.win.scroll}'] = () => { if (me['@{prevent.win.scroll}']) return; let tx = 0, ty = 0, e = me['@{move.event}']; let scrollTop = Win.scrollTop(); let winHeight = Win.height(); let maxHeight = Doc.height(); let maxWidth = Doc.width(); let winWidth = Win.width(); let scrollLeft = Win.scrollLeft(); if (e.pageX - scrollLeft < SCROLL_OFFSET && scrollLeft > 0) { tx = -Math.min(SCROLL_STEP, scrollLeft); } else if (scrollLeft + winWidth - e.pageX < SCROLL_OFFSET && scrollLeft + winWidth < maxWidth) { tx = Math.min(SCROLL_STEP, maxWidth - winWidth - scrollLeft); } if (e.pageY - scrollTop < SCROLL_OFFSET && scrollTop > 0) { ty = -Math.min(SCROLL_STEP, scrollTop); } else if (scrollTop + winHeight - e.pageY < SCROLL_OFFSET && scrollTop + winHeight < maxHeight) { ty = Math.min(SCROLL_STEP, maxHeight - winHeight - scrollTop); } if (tx || ty) { me['@{win.start.scrolling}'] = true; e.pageX += tx; e.pageY += ty; window.scrollBy(tx, ty); delete me['@{has.moved}']; UI['@{bar.hide}'](); UI['@{pointer.update}'](e); UI['@{pointer.change}'](); } else { delete me['@{win.start.scrolling}']; } }; Runner['@{task.add}'](SCROLL_INTERVAL, me['@{fn.win.scroll}']); } }, '@{stop.zone.scroll}'() { let me = this; if (me['@{fn.zone.scroll}']) { Runner['@{task.remove}'](me['@{fn.zone.scroll}']); delete me['@{fn.zone.scroll}']; delete me['@{prevent.win.scroll}']; } }, '@{stop.win.scroll}'() { let me = this; if (me['@{fn.win.scroll}']) { Runner['@{task.remove}'](me['@{fn.win.scroll}']); delete me['@{fn.win.scroll}']; } } });