ymPrompt

  1/**
  2 * ymPrompt.js 消息提示组件
  3 * @author netman8410@163.com
  4 */

  5//<meta http-equiv="X-UA-Compatible" content="IE=7" />  IE8透明度解决方案
  6(function() {
  7    if (window.ymPrompt) return;
  8    window.ymPrompt = {
  9        version: '4.0',
 10        pubDate: '2009-02-16',
 11        apply: function(o, c, d) {
 12            if (d) ymPrompt.apply(o, d);
 13            if (o && c && typeof c == 'object'for (var p in c) o[p] = c[p];
 14            return o;
 15        }
,
 16        eventList: []
 17    }
;
 18    
 19    /*初始化可能在页面加载完成调用的接口,防止外部调用失败。_initFn:缓存初始调用传入的参数*/
 20    var initFn = ['setDefaultCfg','show'], _initFn = {},t;
 21    while(t=initFn.shift()) ymPrompt[t] = eval('0,function(){_initFn.'+t+'=arguments}');
 22
 23    /*以下为公用函数及变量*/
 24    var isIE=!+'\v1';    //IE浏览器
 25    var isCompat=document.compatMode == 'CSS1Compat';
 26    var IE6 = isIE && /MSIE (\d)\./.test(navigator.userAgent) && parseInt(RegExp.$1< 7//IE6需要用iframe来遮罩
 27    var useFixed=!isIE||(!IE6&&isCompat);    //滚动时IE7+及其它浏览器使用Fixed定位
 28    var $ = function(id) {
 29        return document.getElementById(id)
 30    }
//获取元素
 31    var $height = function(obj) {
 32        return parseInt(obj.style.height) || obj.offsetHeight
 33    }
//获取元素高度
 34    var addEvent = (function() {
 35        return new Function('env','fn','obj',['obj=obj||document;', window.attachEvent ? "obj.attachEvent('on'+env,fn)"'obj.addEventListener(env,fn,false)'';ymPrompt.eventList.push([env,fn,obj])'].join(''))
 36    }
)(); //事件绑定
 37    var detachEvent = (function() {
 38        return new Function('env','fn','obj',['obj=obj||document;', window.attachEvent ? "obj.detachEvent('on'+env,fn)"'obj.removeEventListener(env,fn,false)'].join(''))
 39    }
)(); //取消事件绑定
 40
 41    //为元素的特定样式属性设定值
 42    var setStyle = function(el, n, v) {
 43        if (!el) return;
 44        if (typeof n == 'object'{
 45            for (var i in n) setStyle(el, i, n[i]);
 46            return;
 47        }

 48        /*dom数组或dom集合*/
 49        if (el instanceof Array || /htmlcollection|nodelist/i.test(''+el)) {
 50            for (var i = el.length - 1; i >= 0; i--) setStyle(el[i], n, v);
 51            return;
 52        }

 53        try{el.style[n] = v}catch(e){}
 54    }
;
 55    /*----------------和业务有关的公用函数-----------------*/
 56    var btnIndex = 0, btnCache, seed = 0//当前焦点的按钮的索引、当前存在的按钮、id种子
 57    /*创建按钮*/
 58    var mkBtn = function(txt, sign, autoClose, id) {
 59        if (!txt) return;
 60        if (txt instanceof Array) {
 61            /*无效按钮删除*/
 62            var item,t=[],dftBtn={OK:[curCfg.okTxt, 'ok'], CANCEL:[curCfg.cancelTxt, 'cancel']};
 63            while(txt.length) (item=txt.shift())&&t[t.push(mkBtn.apply(null, dftBtn[item]||item))-1]||t.pop();
 64            return t;
 65        }

 66        id = id || 'ymPrompt_btn_' + seed++;
 67        autoClose = autoClose == undefined ? 'undefined'!!autoClose;
 68        return {
 69            id: id,
 70            html: "<input type='button' id='" + id + "' onclick='ymPrompt.doHandler(\"" + sign + "\"," + autoClose + ")' style='cursor:pointer' class='btnStyle handler' value='" + txt + "' />"
 71        }
;
 72    }
;
 73    /*生成按钮组合的html*/
 74    var joinBtn = function(btn) {
 75        if (!btn) return btnCache = '';
 76        if (! (btn instanceof Array)) btn = [btn];
 77        if(!btn.length) return btnCache='';
 78        btnCache = btn.concat();
 79        var html=[];
 80        while(btn.length) html.push(btn.shift().html);
 81        return html.join('&nbsp;&nbsp;');
 82    }

 83    /*默认显示配置及用户当前配置*/
 84    var dftCfg = {
 85        titleBar: true,
 86        fixPosition: true,
 87        dragOut: false,
 88        autoClose: true,
 89        showMask: true,
 90        maskAlphaColor: '#000',    //遮罩透明色
 91        maskAlpha: 0.1,        //遮罩透明度
 92        winAlpha:0.8,    //拖动窗体时窗体的透明度
 93        title: '标题',        //消息框标题
 94        message: '内容',    //消息框按钮
 95        width: 300,
 96        height: 185,
 97        winPos: 'c',
 98        iframe: false,
 99        btn: null,
100        closeBtn:true,
101        closeTxt: '关闭',
102        okTxt:' 确 定 ',
103        cancelTxt:' 取 消 ',
104        icoCls: '',
105        handler: function() {} //回调事件
106    }
,curCfg = {};
107    /*开始解析*/
108    (function() {
109        var rootEl=document.body;
110        if (!rootEl || typeof rootEl != 'object'return addEvent('load', arguments.callee, window); //等待页面加载完成
111        rootEl = isCompat ? document.documentElement: rootEl; //根据html Doctype获取html根节点,以兼容非xhtml的页面
112        var noFS=/body/i.test(document.body);    //不是frameset页面
113        if(!isIE&&!noFS) return;    //frameset页面且不是IE则直接返回,否则会出现错误。
114        /*保存窗口定位信息*/
115        var saveWinInfo = function() {
116            ymPrompt.apply(dragVar, {
117                _offX: ym_win.offsetLeft-rootEl.scrollLeft,    //弹出框相对屏幕的位移差
118                _offY: ym_win.offsetTop-rootEl.scrollTop
119            }
);
120        }
;
121        /*-------------------------创建弹窗html-------------------*/
122        var maskStyle = 'position:absolute;top:0;left:0;display:none;text-align:center';
123        var div = document.createElement('div');
124        div.innerHTML = [
125        /*遮罩*/
126        "<div id='maskLevel' style=\'" + maskStyle + ';z-index:10000;\'></div>', IE6 ? ("<iframe id='maskIframe' style='" + maskStyle + ";z-index:9999;filter:alpha(opacity=0);opacity:0'></iframe>") : '',
127        /*窗体*/
128        "<div id='ym-window' style='position:absolute;z-index:10001;display:none'>", IE6 ? "<iframe style='width:100%;height:100%;position:absolute;top:0;left:0;z-index:-1'></iframe>": '', "<div class='ym-tl' id='ym-tl'><div class='ym-tr'><div class='ym-tc' style='cursor:move;'><div class='ym-header-text'></div><div class='ym-header-tools'></div></div></div></div>""<div class='ym-ml' id='ym-ml'><div class='ym-mr'><div class='ym-mc'><div class='ym-body'></div></div></div></div>""<div class='ym-ml' id='ym-btnl'><div class='ym-mr'><div class='ym-btn'></div></div></div>", "<div class='ym-bl' id='ym-bl'><div class='ym-br'><div class='ym-bc'></div></div></div>""</div>"].join('');
129        document.body.appendChild(div),div = null;
130
131        var dragVar = {};
132        /*mask、window*/
133        var maskLevel = $('maskLevel');
134        var ym_win = $('ym-window');
135        
136        /*header*/
137        var ym_headbox = $('ym-tl');
138        var ym_head = ym_headbox.firstChild.firstChild;
139        var ym_hText = ym_head.firstChild;
140        var ym_hTool = ym_hText.nextSibling;
141        /*content*/
142        var ym_body = $('ym-ml').firstChild.firstChild.firstChild;
143        /*button*/
144        var ym_btn = $('ym-btnl');
145        var ym_btnContent = ym_btn.firstChild.firstChild;
146        /*bottom*/
147        var ym_bottom = $('ym-bl');
148        var maskEl=[maskLevel];
149        IE6&&maskEl.push($('maskIframe'));
150
151        /*绑定事件*/
152        var getWinSize=function(){return [Math.max(rootEl.scrollWidth,rootEl.clientWidth),Math.max(rootEl.scrollHeight,rootEl.clientHeight)]};
153        var winSize=getWinSize();    //保存页面的实际大小
154        var bindEl=ym_head.setCapture&&ym_head;    //绑定拖放事件的对象
155        var mEvent=function(e) 
156            e = e || window.event;
157            var sLeft = dragVar.offX + (e.x||e.pageX);
158            var sTop = dragVar.offY + (e.y||e.pageY);
159
160            if (!curCfg.dragOut) {
161                var flag=curCfg.fixPosition&&useFixed;    //自动滚动并使用fixed定位
162                var sl = flag?0:rootEl.scrollLeft,st = flag?0:rootEl.scrollTop;
163                sLeft = Math.min(Math.max(sLeft, sl), rootEl.clientWidth - ym_win.offsetWidth + sl);
164                sTop = Math.min(Math.max(sTop, st), rootEl.clientHeight - ym_win.offsetHeight + st);
165            }
else if(curCfg.showMask && ''+winSize!=''+getWinSize())
166                resizeMask(true);
167            setStyle(ym_win,{left:sLeft+'px',top:sTop+'px'});
168        }
;    //mousemove事件
169        var uEvent=function() {
170            /*frameset下不能实现半透明否则会消失,原因不明*/
171            noFS&&curCfg.winAlpha!=1&&setStyle(ym_win,isIE?{filter: 'Alpha(opacity=100)'}:{opacity:1});    //鼠标按下时取消窗体的透明度
172            detachEvent("mousemove",mEvent,bindEl);
173            detachEvent("mouseup",uEvent,bindEl);
174            saveWinInfo();//保存当前窗口的位置
175            bindEl&&(detachEvent("losecapture",uEvent,bindEl),bindEl.releaseCapture());
176            rootEl.style.cursor=rootEl._cursor;
177        }
;    //mouseup事件
178        addEvent('mousedown',function(e) {
179            rootEl._cursor=rootEl.style.cursor||'';
180            rootEl.style.cursor='pointer';
181            e = e || window.event;
182            /*frameset下不能实现半透明否则会消失,原因不明*/
183            noFS&&curCfg.winAlpha!=1&&setStyle(ym_win,isIE?{filter: 'Alpha(opacity='+curCfg.winAlpha*100+')'}:{opacity:curCfg.winAlpha});//鼠标按下时窗体的透明度
184            ymPrompt.apply(dragVar, {
185                offX: ym_win.offsetLeft-(e.x||e.pageX),    //鼠标与弹出框的左上角的位移差
186                offY: ym_win.offsetTop-(e.y||e.pageY)
187            }
);
188            addEvent("mousemove",mEvent,bindEl);
189            addEvent("mouseup",uEvent,bindEl);
190            bindEl&&(addEvent("losecapture",uEvent,bindEl),bindEl.setCapture());
191        }
,ym_head);
192        
193        /*键盘监听*/
194        var keydownEvent=function(e) {
195            var e = e || event, keyCode=e.keyCode;
196            if(keyCode==27) destroy();//esc键
197            if(btnCache){
198                var l = btnCache.length,nofocus;
199                /*tab键/左右方向键切换焦点*/
200                document.activeElement&&document.activeElement.id!=btnCache[btnIndex].id && (nofocus=true);
201                if (keyCode == 9 || keyCode == 39) nofocus&&(btnIndex=-1),$(btnCache[++btnIndex == l ? (--btnIndex) : btnIndex].id).focus();
202                if (keyCode == 37) nofocus&&(btnIndex=l),$(btnCache[--btnIndex < 0 ? (++btnIndex) : btnIndex].id).focus();
203                if (keyCode == 13return true;
204            }

205            /*禁止F1-F12/ tab 回车*/
206            return keyEvent(e,(keyCode > 110 && keyCode < 123|| keyCode == 9 || keyCode == 13);
207        }
;
208        /*页面滚动弹出窗口滚动*/
209        var scrollEvent=function(){
210            setStyle(ym_win, {
211                left:dragVar._offX + rootEl.scrollLeft + 'px',
212                top:dragVar._offY + rootEl.scrollTop + 'px'
213            }
);
214        }
;
215        /*监听键盘事件*/
216        var keyEvent=function(e,d){
217            e=e||event;
218            /*允许对表单项进行操作*/
219            if(!d&&/input|select|textarea/i.test((e.srcElement||e.target).tagName)) return true;
220            try{
221                e.returnValue=false;
222                e.keyCode = 0;
223            }
 catch(ex) {
224                e.preventDefault&&e.preventDefault();
225            }

226            return false;
227        }
;
228        maskLevel.oncontextmenu = ym_win.onselectstart = ym_win.oncontextmenu = keyEvent; //禁止右键
229        /*重新计算遮罩的大小*/
230        var resizeMask=function(noDelay){
231            setStyle(maskEl, 'display','none');    //先隐藏
232            var size=getWinSize();
233            var resize=function(){
234                setStyle(maskEl, {
235                    width:size[0]+'px',
236                    height:size[1]+'px',
237                    display:''
238                }
);
239            }
;
240            isIE?noDelay===true?resize():setTimeout(resize,0):resize();
241            setWinSize();
242        }
;
243        /*蒙版的显示隐藏,state:true显示,false隐藏,默认为true*/
244        var maskVisible = function(visible) {
245            if (!curCfg.showMask) return;
246            (visible === false?detachEvent:addEvent)("resize",resizeMask,window);
247            if (visible === falsereturn setStyle(maskEl, 'display','none');
248            setStyle(maskLevel, {
249                background:curCfg.maskAlphaColor,
250                filter: 'Alpha(opacity='+curCfg.maskAlpha * 100+')',
251                opacity:curCfg.maskAlpha
252            }
);
253            resizeMask(true);
254        }

255        var getPos=function(f){
256            var flag=curCfg.fixPosition&&useFixed;
257            var pos=[rootEl.clientWidth - ym_win.offsetWidth, rootEl.clientHeight - ym_win.offsetHeight, flag?0:rootEl.scrollLeft, flag?0:rootEl.scrollTop];
258            var arr=f.replace(/\{(\d)\}/g,function(s,s1){return pos[s1]}).split(',');
259            return [eval(arr[0]),eval(arr[1])];
260        }
;
261        var posMap = {
262            c: '{0}/2+{2},{1}/2+{3}',
263            l: '{2},{1}/2+{3}',
264            r: '{0}+{2},{1}/2+{3}',
265            t: '{0}/2+{2},{3}',
266            b: '{0}/2,{1}+{3}',
267            lt: '{2},{3}',
268            lb: '{2},{1}+{3}',
269            rb: '{0}+{2},{1}+{3}',
270            rt: '{0}+{2},{3}'
271        }
;
272        /*设定窗口大小及定位*/
273        var setWinSize = function(w, h) {
274            if (!ym_win || ym_win.style.display == 'none'return;
275            curCfg.height = parseInt(h) || curCfg.height;
276            curCfg.width = parseInt(w) || curCfg.width;
277            setStyle(ym_win, {
278                left:0,
279                top:0,
280                width:curCfg.width + 'px',
281                height:curCfg.height + 'px'
282            }
);
283            var pos = posMap[curCfg.winPos];
284            pos = pos ? getPos(pos) : curCfg.winPos; //支持自定义坐标
285            if(!(pos instanceof Array))pos=getPos(posMap['c']);
286            setStyle(ym_win, {
287                top: pos[1+ 'px',
288                left:pos[0+ 'px'
289            }
);
290            saveWinInfo();    //保存当前窗口位置信息
291            setStyle(ym_body, 'height', curCfg.height - $height(ym_headbox) - $height(ym_btn) - $height(ym_bottom) + 'px'); //设定内容区的高度
292        }
;
293        var _obj=[];    //IE中可见的obj元素
294        var winVisible = function(visible) {
295            var fn=visible===false?detachEvent:addEvent;
296            if(curCfg.fixPosition&&!useFixed) fn('scroll', scrollEvent, window);
297            setStyle(ym_win,'position',curCfg.fixPosition&&useFixed?'fixed':'absolute');
298
299            fn('keydown', keydownEvent);
300            if (visible === false{
301                setStyle(ym_win, 'display','none');
302                setStyle(_obj, 'visibility','visible');
303                _obj=[];
304                return ;
305            }

306            isIE&&setStyle(ym_win,'filter','');    //清除IE下的阴影滤镜,避免在fixed定位时iframe内容不可见的bug
307            for(var o=document.getElementsByTagName('object'),i=o.length-1;i>-1;i--) o[i].style.visibility!='hidden'&&_obj.push(o[i])&&(o[i].style.visibility='hidden');
308            setStyle([ym_hText, ym_hTool], 'display',(curCfg.titleBar ? '''none'));
309            ym_head.className = 'ym-tc' + (curCfg.titleBar ? ''' ym-ttc');
310            ym_hText.innerHTML = curCfg.title; //标题
311            ym_hTool.innerHTML = curCfg.closeBtn?"<div class='ymPrompt_close' title='"+curCfg.closeTxt+"' onclick='ymPrompt.doHandler(\"close\")'><strong>×</strong></div>":'';
312            ym_body.innerHTML = !curCfg.iframe ? ('<div class="ym-content">' + curCfg.message + '</div>') : "<iframe width='100%' height='100%' border='0' frameborder='0' src='" + curCfg.message + "'></iframe>"//内容
313            (function(el,obj){for(var i in obj)try{el[i]=obj[i]}catch(e){}})(ym_body.firstChild,curCfg.iframe);//为iframe添加自定义属性
314            ym_body.className = "ym-body " + curCfg.icoCls; //图标类型
315            setStyle(ym_btn, 'display',((ym_btnContent.innerHTML = joinBtn(mkBtn(curCfg.btn))) ? '''none')); //没有按钮则隐藏
316            setStyle(ym_win, 'display','');
317            setWinSize();    //定位窗口
318            btnCache && $(btnCache[btnIndex = 0].id).focus(); //第一个按钮获取焦点
319        }
//初始化
320        var isShow=false;
321        var init = function() {
322            isShow=true;
323            maskVisible();
324            winVisible();
325        }
//销毁
326        var destroy = function() {
327            isShow=false;
328            maskVisible(false);
329            winVisible(false);
330        }
;
331        ymPrompt.apply(ymPrompt, {
332            close: destroy,
333            getPage: function() {
334                return curCfg.iframe ? ym_body.firstChild: null
335            }
,
336            /*显示消息框,fargs:优先配置,会覆盖args中的配置*/
337            show: function(args, fargs) {
338                if(isShow) ymPrompt.doHandler('close',curCfg.autoClose,true);
339                /*支持两种参数传入方式:(1)JSON方式 (2)多个参数传入*/
340                var a = [].slice.call(args, 0), o = {};
341                if (typeof a[0!= 'object'{
342                    var cfg = ['message''width''height''title''handler''maskAlphaColor''maskAlpha''iframe''icoCls''btn''autoClose''fixPosition''dragOut''titleBar''showMask''winPos''winAlpha'];
343                    for (var i = 0,l = a.length; i < l; i++if (a[i]) o[cfg[i]] = a[i];
344                }
 else {
345                    o = a[0];
346                }

347                ymPrompt.apply(curCfg, ymPrompt.apply({},o, fargs), ymPrompt.setDefaultCfg()); //先还原默认配置
348                /*修正curCfg中的无效值(null/undefined)改为默认值*/
349                for(var i in curCfg) curCfg[i]=curCfg[i]!=null?curCfg[i]:ymPrompt.cfg[i];
350                init();
351            }
,
352            doHandler: function(sign, autoClose, closeFirst) {
353                if(autoClose == undefined ? curCfg.autoClose: autoClose) destroy();
354                try{(curCfg.handler)(sign)}catch(e){};
355            }
,
356            resizeWin: setWinSize,
357            /*设定默认配置*/
358            setDefaultCfg: function(cfg) {
359                return ymPrompt.cfg = ymPrompt.apply({}, cfg, ymPrompt.apply({}, ymPrompt.cfg, dftCfg));
360            }
,
361            getButtons:function(){
362                var btns=btnCache||[],btn,rBtn=[];
363                while(btn=btns.shift())rBtn.push($(btn.id));
364                return rBtn;
365            }

366        }
);
367        ymPrompt.setDefaultCfg(); //初始化默认配置
368        /*执行用户初始化时的调用*/
369        for (var i in _initFn) ymPrompt[i].apply(null, _initFn[i]);
370        /*取消事件绑定*/
371        addEvent('unload',function() {
372            while(ymPrompt.eventList.length) detachEvent.apply(null, ymPrompt.eventList.shift());
373        }
,window);
374    }
)();
375}
)(); //各消息框的相同操作
376ymPrompt.apply(ymPrompt, {
377    alert: function() {
378        ymPrompt.show(arguments, {
379            icoCls: 'ymPrompt_alert',
380            btn: ['OK']
381        }
);
382    }
,
383    succeedInfo: function() {
384        ymPrompt.show(arguments, {
385            icoCls: 'ymPrompt_succeed',
386            btn: ['OK']
387        }
);
388    }
,
389    errorInfo: function() {
390        ymPrompt.show(arguments, {
391            icoCls: 'ymPrompt_error',
392            btn: ['OK']
393        }
);
394    }
,
395    confirmInfo: function() {
396        ymPrompt.show(arguments, {
397            icoCls: 'ymPrompt_confirm',
398            btn: ['OK','CANCEL']
399        }
);
400    }
,
401    win: function() {
402        ymPrompt.show(arguments);
403    }

404}
);
posted @ 2009-02-22 02:05 fuyude.net 阅读(2192) 评论(0) 编辑 收藏