UNPKG

nuijs

Version:

nui框架

812 lines (785 loc) 30.5 kB
/** * @author Aniu[2016-11-10 22:39] * @update Aniu[2016-11-10 22:39] * @version 1.0.1 * @description layer弹出层 */ Nui.define(function(require){ this.imports('../../assets/components/layer/index'); var component = require('../../core/component'); var util = require('../../core/util'); var template = require('../../core/template'); var statics = { _maskzIndex:10000, _zIndex:10000, _init:function(){ var _class = this; var timer = null; Nui.win.on('resize', function(){ clearTimeout(timer); timer = setTimeout(function(){ Nui.each(_class.__instances, function(val){ var opts = val._options; if(opts.position || opts.isCenter === true){ val.resize() } }) }) }) }, _$fn:null, _$ready:null, init:null } var options = { //内容 content:'', //内容模版 template:'', //模版数据 data:{}, //高度 width:320, //宽度 height:'auto', //弹出层层级 zIndex:null, //最大宽度 maxWidth:0, //最大高度 maxHeight:0, //定时器,N毫秒后自动关闭 timer:0, //弹窗四周距离窗口边缘距离 edge:0, //弹窗容器 container:'body', //弹窗标题 title:'温馨提示', //当弹窗容器不是body时,是否以window窗口计算位置 isWindow:false, //是否可以拖动 isMove:false, //是否有遮罩 isMask:true, //是否只能在窗口内拖动 isInnerMove:false, //点击遮罩是否关闭弹窗 isClickMask:false, //是否使用遮罩拖动 isMoveMask:false, //是否能用hide方法关闭遮罩 isHide:true, //弹窗是否浏览器改变大小时显示在窗口中央 isCenter:true, //是否全屏显示 isFull:false, //是否在点击弹窗时将其置顶 isTop:false, //是否以提示框展示,没有标题,按钮 isTips:false, //是否拖动滚动条固定位置 isFixed:true, //当内容超过弹出层容器,是否显示滚动条 scrollbar:true, //是否点击弹窗或者点击遮罩层是否阻止事件冒泡 isStopProp:false, //按钮对齐方式 align:'center', //自定义拖动元素 moveElement:null, //是否以气泡形式展示,弹出层边缘会多出箭头 bubble:{ enable:false, dir:'top' }, //弹出层内容展示iframe,不建议跨域使用 iframe:{ enable:false, cache:false, src:'' }, //关闭按钮 close:{ enable:true, text:'×' }, //确定按钮 confirm:{ enable:false, name:'normal', text:'确定', callback:function(){ return true } }, //取消按钮 cancel:{ enable:true, text:'取消' }, /*弹出层定位 top/left/right/bottom position:{ top:10, left:10 } */ position:null, /*将弹出层置于遮罩层底部 under:[layer1, layer2] */ under:null, /*配置按钮,若id为confirm/cancel/close将会覆盖内置按钮参数 button:[{ id:'confirm', text:'确定', name:'normal', callback:function(){ } }] */ button:null, //onInit:弹出层显示时回调 //onDestroy:弹出层注销时回调 //当拖动弹出层移动后回调 onMove:null, //窗口改变大小位置时回调 onResize:null, //容器滚动时回调 onScroll:null, //弹窗隐藏前回调,若返回false则不能隐藏 onHideBefore:null, //弹窗销毁前回调,若返回false则不能销毁 onDestroyBefore:null, //定时关闭弹窗回调 onTimer: null, //弹窗渲染出来后回调,先于onInit onRender: null, } return this.extend(component, { _static:statics, _options:options, _template:{ layout: '<div class="<% className %>" style="<% include \'style\' %>">'+ '<div class="layer-box">'+ '<%if close%>'+ '<% var btn = close %>'+ '<% include "button" %>'+ '<%/if%>'+ '<%if bubble%>'+ '<span class="layer-bubble layer-bubble-<%bubble.dir||"top"%>"'+ '<%if bubble.style%>'+ ' style="<%each bubble.style v n%><%n%>:<%v%>;<%/each%>"'+ '<%/if%>'+ '><b></b><i></i></span>'+ '<%/if%>'+ '<%if title%>'+ '<div class="layer-head">'+ '<span class="layer-title"><%title%></span>'+ '</div>'+ '<%/if%>'+ '<div class="layer-body">'+ '<div class="layer-main">'+ '<%content%>'+ '</div>'+ '</div>'+ '<%if button && button.length%>'+ '<div class="layer-foot" style="text-align:<%align%>">'+ '<div class="layer-inner">'+ '<%each button btn%>'+ '<%include "button"%>'+ '<%/each%>'+ '</div>'+ '</div>'+ '<%/if%>'+ '</div>'+ '</div>', button: '<button type="button" class="ui-button'+ '<%if btn.name%>'+ '<%each [].concat(btn.name) name%> ui-button-<%name%><%/each%>'+ '<%/if%> layer-button-<%btn.id%>"'+ '<%if btn.style%>'+ ' style="<%each btn.style v n%><%n%>:<%v%>;<%/each%>"'+ '<%/if%>><%btn.text || "按钮"%></button>', iframe: '<iframe<%each attr%> <%$index%>="<%$value%>"<%/each%>></iframe>', mask: '<div class="nui-layer-mask'+ '<%if skin%> nui-layer-mask-<%skin%><%/if%>" style="<%include \'style\'%>">'+ '<div class="layer-mask"></div>'+ '</div>', movemask: '<div class="nui-layer-movemask'+ '<%if skin%> nui-layer-movemask-<%skin%><%/if%>" style="<%include \'style\'%>">'+ '</div>', style: '<%each style%><%$index%>:<%$value%>;<%/each%>' }, /* top:弹窗距离窗口顶部距离 left:弹窗距离窗口左边距离 width:弹窗宽度 height:弹窗高度 */ data:{}, _init:function(){ this._zIndex = ++this.constructor._zIndex; this._exec() this._emitListener('init') }, _exec:function(){ var self = this, opts = self._options; self._container = self._jquery(opts.container); if(self._container){ self._containerDOM = self._container.get(0); if(self._containerDOM.tagName !== 'BODY' && opts.isWindow !== true){ self._window = self._container; self._isWindow = false; var pos = self._container.css('position'); if('absolute relative fixed'.indexOf(pos) === -1){ self._container.css('position', 'relative') } } else{ self._window = Nui.win; self._isWindow = true; } self._isFixed = opts.isFixed === true && !Nui.bsie6 && self._isWindow; self._create(); } }, _create:function(){ var self = this, opts = self._options; var buttons = self._createButton(), isTitle = false; if(opts.isTips !== true){ isTitle = typeof opts.title === 'string'; } var data = self._tplData({ content:self._getContent(), close:buttons.close, button:buttons.button, title:isTitle ? (opts.title||'温馨提示') : null, bubble:opts.bubble.enable === true ? opts.bubble : null, align:opts.align || 'center', style:{ 'z-index':isNaN(parseInt(opts.zIndex)) ? self._zIndex : opts.zIndex, 'position':'absolute', 'display':'block' } }); if(self._isFixed){ data.style.position = 'fixed'; } self._setTop(); opts.element = self.element = self._bindComponentName($(self._tpl2html('layout', data)).appendTo(self._container)); self._box = self.element.children('.layer-box'); self.head = self._box.children('.layer-head'); self._body = self._box.children('.layer-body'); self.main = self._body.children('.layer-main'); self.foot = self._box.children('.layer-foot'); self.moveElement = self._jquery(opts.moveElement); if(opts.isTips !== true){ if(opts.iframe.enable === true){ self._iframe = self.main.children('iframe'); self._iframeOnload() } if(opts.isMove === true && (self.moveElement || isTitle)){ self._bindMove(); } if(opts.isStopProp === true){ self._stopProp(); } if(opts.isTop === true){ self._bindTop(); } } if(self._button.length){ self._buttonEvent(); } if(opts.isFixed === true && !self._isFixed === true){ self._bindScroll() } self._callback('Render'); self._event(); self._show() }, _getContent:function(){ var self = this, opts = self._options, content = '', tpl = opts.template; if(opts.isTips !== true && opts.iframe.enable === true){ content = self._createIframe(); } else{ if(tpl){ var data = opts.data; if(typeof data === 'function'){ data = opts.data.call(this) } if(typeof tpl === 'string'){ content = template.render(tpl, data) } else if(Nui.type(opts.template, 'Object')){ content = template.render.call(tpl, tpl.main, data) } } else if(typeof opts.content === 'string'){ content = opts.content } else if(opts.content instanceof jQuery){ content = opts.content.prop('outerHTML') } } return content }, _createIframe:function(){ var self = this, opts = self._options, name = 'layer-iframe'+self.__id, src = opts.iframe.src; if(opts.iframe.cache === false){ src = util.setParam('_', new Date().getTime(), src) } return self._tpl2html('iframe', { attr:{ frameborder:'0', name:name, id:name, src:src, scroll:'hidden', style:'width:100%;' } }) }, _iframeOnload:function(){ var self = this; self._iframe.load(function(){ self._iframeDocument = self._iframe.contents(); self._resize() }) }, _createButton:function(){ var self = this, opts = self._options, defaults = {}, buttons = {}, caches = {}, isTips = opts.isTips === true; var add = function(id, btn){ self._button[id === 'close' ? 'unshift' : 'push'](btn) } self._button = []; Nui.each(['close', 'confirm', 'cancel'], function(id){ if(!isTips || id === 'close'){ var btn = opts[id]; defaults[id] = { id:id } for(var i in btn){ defaults[id][i] = btn[i] } } }); if(!isTips && opts.button && opts.button.length){ Nui.each(opts.button, function(val){ var id = val.id, btn = val, def; if(!caches[id]){ caches[id] = true; if(def = defaults[id]){ delete defaults[id] if(!def.enable){ return true } btn = $.extend(true, {}, def, val); } add(id, btn) } }) } Nui.each(defaults, function(val, id){ if(val.enable){ add(id, val) } }); if(self._button[0] && self._button[0].id === 'close'){ if(opts.close.enable){ buttons.close = self._button[0] } buttons.button = self._button.slice(1); } else{ buttons.button = self._button } return buttons }, _buttonEvent:function(){ var self = this, opts = self._options; Nui.each(self._button, function(val){ self._on('click', self.element, '.layer-button-'+val.id, function(e, button){ if(!button.hasClass('nui-button-disabled')){ var id = val.id, callback = val.callback; self.triggerId = id; var isCall = typeof callback === 'function' ? callback.call(opts, self, e, button) : null; if((id === 'confirm' && isCall === true) || (id !== 'confirm' && isCall !== false)){ self.destroy() } } }) }) }, _stopProp:function(){ this._on('click', this.element, function(e){ e.stopPropagation() }); }, _bindTop:function(){ var self = this; self._on('click', self.element, function(){ self._setzIndex(); }); }, _bindMove:function(){ var self = this, opts = self._options, element = self.element; var _class = self.constructor, elem = element, isMove = false, x, y, _x, _y; var moveElement = self.moveElement || self.head; self._on('mousedown', moveElement, function(e, ele){ isMove = true; self._setzIndex(); if(opts.isMoveMask === true){ elem = self._moveMask = $(self._tpl2html('movemask', { skin:opts.skin, style:{ 'z-index':self._zIndex+1, 'cursor':'move', 'position':self._isFixed ? 'fixed' : 'absolute' } })).appendTo(self._container); elem.css({ width:self.data.outerWidth - _class._getSize(elem, 'lr', 'all'), height:self.data.outerHeight - _class._getSize(elem, 'tb', 'all'), top:self.data.top, left:self.data.left }); } ele.css('cursor','move'); x = e.pageX - self.data.left; y = e.pageY - self.data.top; //e.stopPropagation(); }); self._on('mousemove', Nui.doc, function(e){ var width = self._container.outerWidth(), height = self._container.outerHeight(); if(isMove){ _x = e.pageX - x; _y = e.pageY - y; _x < 0 && (_x = 0); _y < 0 && (_y = 0); if(opts.isInnerMove === true){ _x + self.data.outerWidth > width && (_x = width - self.data.outerWidth); _y + self.data.outerHeight > height && (_y = height - self.data.outerHeight); } self.data.top = _y; self.data.left = _x; elem.css({top:_y, left:_x}); return !isMove; } }); self._on('mouseup', Nui.doc, function(e){ if(isMove){ isMove = false; moveElement.css('cursor','default'); if(opts.isMoveMask === true){ element.css(self.data); self._moveMask.remove(); self._moveMask = null; } self._callback('Move'); self.data.offsetTop = self.data.top - self._window.scrollTop(); self.data.offsetLeft = self.data.left - self._window.scrollLeft(); } }); }, _bindScroll:function(){ var self = this; self._on('scroll', self._window, function(e, elem){ var top = self.data.offsetTop + self._window.scrollTop(); var left = self.data.offsetLeft + self._window.scrollLeft(); self.data.top = top; self.data.left = left; self.element.css(self.data); self._callback('Scroll', [e, elem, {top:top, left:left}]); }) }, //鼠标点击弹出层将弹出层层级设置最大 _setzIndex:function(){ var self = this, _class = self.constructor; if(self._isTop && self.element){ self._isTop = false; self._zIndex = ++_class._zIndex; self.element.css('zIndex', self._zIndex); self._setTop(); } }, _setLower:function(destroy){ var self = this, _class = self.constructor, opts = self._options, unders = []; if(opts.under){ unders = unders.concat(opts.under); if(unders.length){ Nui.each(unders, function(obj, k){ if(obj && obj.element){ obj.element.css('z-index', destroy ? (isNaN(parseInt(obj._options.zIndex)) ? obj._zIndex : obj._options.zIndex) : _class._maskzIndex-1) } }) } } }, _setTop:function(){ var self = this, _class = self.constructor; Nui.each(_class.__instances, function(val){ if(val && val !== self && val._options.isTop === true){ val._isTop = true; } }); }, _position:function(){ var self = this, data = self.data, pos = self._options.position, _pos = {}, _v; if(typeof pos === 'function'){ pos = pos.call(self._options, self) } Nui.each(pos, function(v, k){ if(Nui.type(v, ['String', 'Number'])){ _v = v; if(typeof v === 'string' && v !== 'auto'){ if(!v){ _v = 0 } else{ if(k === 'top' || k === 'bottom'){ if(v === 'self'){ _v = data.outerHeight } else if(/[\+\-\*\/]/.test(v)){ _v = (new Function('var self = '+data.outerHeight+'; return '+v))() } } else{ if(v === 'self'){ _v = data.outerWidth } else if(/[\+\-\*\/]/.test(v)){ _v = (new Function('var self = '+data.outerWidth+'; return '+v))() } } } } _pos[k] = _v } }) return _pos }, _resize:function(type){ var self = this, _class = self.constructor, opts = self._options, element = self.element; var wWidth = self._window.outerWidth(); var wHeight = self._window.outerHeight(); var stop = 0; var sleft = 0; if(!self._isFixed){ sleft = self._window.scrollLeft(); stop = self._window.scrollTop(); } self._setSize(); if(opts.position){ var pos = element.css(self._position()).position(); if(Nui.bsie6){ sleft = 0; stop = 0; } self.data.left = pos.left + sleft; self.data.top = pos.top + stop; } else{ if(type === 'init' || opts.isCenter === true){ var left = (wWidth - self.data.outerWidth) / 2 + sleft; var top = (wHeight - self.data.outerHeight) / 2 + stop; var edge = opts.edge > 0 ? opts.edge : 0; self.data.left = left > 0 ? left : edge; self.data.top = top > 0 ? top : edge; } } self.data.offsetTop = self.data.top - self._window.scrollTop(); self.data.offsetLeft = self.data.left - self._window.scrollLeft(); element.css(self.data); }, _setSize:function(){ var self = this, _class = self.constructor, opts = self._options, element = self.element; var edge = opts.edge > 0 ? opts.edge*2 : 0; var wWidth = self._window.outerWidth() - edge; var wHeight = self._window.outerHeight() - edge; var scrollbar = opts.scrollbar; self._body.css({height:'auto', overflow:'visible'}); element.css({top:'auto', left:'auto', width:'auto', height:'auto'}); var edgeSize = _class._getSize(self._box, 'tb', 'all') + self.head.outerHeight() + _class._getSize(self.head, 'tb', 'margin') + _class._getSize(self._body, 'tb', 'all') + self.foot.outerHeight() + _class._getSize(self.foot, 'tb', 'margin'); var width = element.outerWidth(); if(opts.isFull !== true){ if(opts.width > 0){ width = opts.width } else if(opts.width === '100%' || (opts.scrollbar === true && width > wWidth)){ width = wWidth; } if(opts.maxWidth > 0 && width >= opts.maxWidth){ scrollbar = true; width = opts.maxWidth } } else{ width = wWidth; } var ws = 'nowrap'; if(opts.width > 0 || width == opts.maxWidth || width == wWidth){ ws = 'normal'; } self.data.width = width - _class._getSize(element, 'lr', 'all'); self.main.css('white-space', ws); element.width(self.data.width); var height = element.outerHeight(); if(self._iframeDocument){ self._iframeDocument[0].layer = self; height = edgeSize + self._iframeDocument.find('body').outerHeight(); } if(opts.isFull !== true){ if(opts.height > 0){ height = opts.height } else if(opts.height === '100%' || ((opts.scrollbar === true || self._iframeDocument) && height > wHeight)){ height = wHeight } if(opts.maxHeight > 0 && height >= opts.maxHeight){ scrollbar = true; height = opts.maxHeight } } else{ height = wHeight } self.data.outerWidth = width; self.data.outerHeight = height; self.data.height = height - _class._getSize(element, 'tb', 'all'); element.height(self.data.height); var _height = self.data.height - edgeSize; if(self.main.outerHeight() > _height && !self._iframe && scrollbar === true){ self._body.css('overflow', 'auto') } if(self._iframe){ self._iframe.height(_height); } self._body.height(self.data.contentHeight = _height) }, _showMask:function(){ var self = this, _class = self.constructor, opts = self._options; if(!self._containerDOM.__layermask__){ self._containerDOM.__layermask__ = $(self._tpl2html('mask', { skin:opts.skin, style:{ 'z-index':_class._maskzIndex, 'position':self._isFixed ? 'fixed' : 'absolute', 'top':'0px', 'left':'0px', 'width':'100%', 'height':self._isFixed ? '100%' : self._container.outerHeight()+'px' } })).appendTo(self._container); } if(opts.isStopProp === true){ self._on('click', self._containerDOM.__layermask__, function(e){ e.stopPropagation() }) } if(opts.isClickMask === true){ self._on('click', self._containerDOM.__layermask__, function(){ self.hide() }) } }, _show:function(){ var self = this, opts = self._options; component.init(self.main); self._resize('init'); self._setLower(); if(opts.isMask === true){ self._showMask() } if(opts.timer > 0){ self._time = opts.timer; self._timer(); } self._callback('Init'); return self }, _timer:function(){ var self = this, opts = self._options; if(self._time > 0){ self._callback('Timer', [self._time]); self._timerid = setTimeout(function(){ self._time -= 1000; self._timer(); }, self._time > 1000 ? 1000 : self._time) } else{ self.hide() } }, _reset:function(){ var self = this, _class = self.constructor, noMask = true; if(this._iframe){ this._iframe.remove() } component.exports._reset.call(this); component.destroy(self.main); Nui.each(_class.__instances, function(val){ if(val && val._options.isMask === true && val !== self && val._containerDOM === self._containerDOM){ return (noMask = false); } }); if(noMask && self._containerDOM.__layermask__){ self._containerDOM.__layermask__.remove(); self._containerDOM.__layermask__ = null; } if(self._options.timer > 0){ self.timer = 0; clearTimeout(self._timerid); } }, reset:function(){ if(this._callback('ResetBefore') !== false){ this.option(true) this._callback('Reset') } return this; }, resize:function(){ var self = this, opts = self._options, element = self.element; self._resize(); self._callback('Resize'); return self }, hide:function(){ if(this._options.isHide === true){ if(this._callback('HideBefore') === false){ return } this.destroy() } }, destroy:function(){ var self = this, _class = self.constructor, opts = self._options; if(self._callback('DestroyBefore') === false){ return } self._delete(); self._reset(); self._setLower(true); if(!self._isdestroy){ _class._zIndex--; self._isdestroy = true; } self._callback('Destroy'); } }) });