jquery.boxy.js扩展 (0.1.40)

jquery.boxy.js扩展 (0.1.40)
这个是ie6的bug,并非boxy的问题。在ie6下,select元素的zindex最大,select元素会透过boxy的弹出层显示在其上面。
这里用一个iframe挡住boxy弹出层下的select,使用时只要将useIframe置为true即可,源码如下:
(jquery.boxy.js并不好用,很多jquery的弹出层插件都解决了ie6的这个问题)

/* *
 * Boxy 0.1.4 - Facebook-style dialog, with frills
 *
 * (c) 2008 Jason Frame
 * Licensed under the MIT License (LICENSE)
 
*/
 
/*
 * jQuery plugin
 *
 * Options:
 *   message: confirmation message for form submit hook (default: "Please confirm:")
 * 
 * Any other options - e.g. 'clone' - will be passed onto the boxy constructor (or
 * Boxy.load for AJAX operations)
 
*/
jQuery.fn.boxy 
=   function (options) {
    options 
=  options  ||  {};
    
return   this .each( function () {      
        
var  node  =   this .nodeName.toLowerCase(), self  =   this ;
        
if  (node  ==  'a') {
            jQuery(
this ).click( function () {
                
var  active  =  Boxy.linkedTo( this ),
                    href 
=   this .getAttribute('href'),
                    localOptions 
=  jQuery.extend({actuator:  this , title:  this .title}, options);
                    
                
if  (active) {
                    active.show();
                } 
else   if  (href.indexOf('#')  >=   0 ) {
                    
var  content  =  jQuery(href.substr(href.indexOf('#'))),
                        newContent 
=  content.clone( true );
                    content.remove();
                    localOptions.unloadOnHide 
=   false ;
                    
new  Boxy(newContent, localOptions);
                } 
else  {  //  fall back to AJAX; could do with a same-origin check
                     if  ( ! localOptions.cache) localOptions.unloadOnHide  =   true ;
                    Boxy.load(
this .href, localOptions);
                }
                
                
return   false ;
            });
        } 
else   if  (node  ==  'form') {
            jQuery(
this ).bind('submit.boxy',  function () {
                Boxy.confirm(options.message 
||  'Please confirm:',  function () {
                    jQuery(self).unbind('submit.boxy').submit();
                });
                
return   false ;
            });
        }
    });
};

//
//
 Boxy Class

function  Boxy(element, options) {
    
    
this .boxy  =  jQuery(Boxy.WRAPPER);
    jQuery.data(
this .boxy[ 0 ], 'boxy',  this );
    
    
this .visible  =   false ;
    
this .options  =  jQuery.extend({}, Boxy.DEFAULTS, options  ||  {});
    
    //只在ie6下useIframe才起作用
    this.options.useIframe = (this.options.useIframe && jQuery.browser.msie && jQuery.browser.version < 7);

    
if (this.options.useIframe) {
        
this.options = jQuery.extend(this.options, {modal: true});
    }

    
    
if  ( this .options.modal) {
        
this .options  =  jQuery.extend( this .options, {center:  true , draggable:  false });
    }
    
    
//  options.actuator == DOM element that opened this boxy
     //  association will be automatically deleted when this boxy is remove()d
     if  ( this .options.actuator) {
        jQuery.data(
this .options.actuator, 'active.boxy',  this );
    }
    
    
this .setContent(element  ||   " <div></div> " );
    
this ._setupTitleBar();
    
    
this .boxy.css('display', 'none').appendTo(document.body);
    
this .toTop();

    
if  ( this .options.fixed) {
        
if  (jQuery.browser.msie  &&  jQuery.browser.version  <   7 ) {
            
this .options.fixed  =   false //  IE6 doesn't support fixed positioning
        }  else  {
            
this .boxy.addClass('fixed');
        }
    }
    
    
if  ( this .options.center  &&  Boxy._u( this .options.x,  this .options.y)) {
        
this .center();
    } 
else  {
        
this .moveTo(
            Boxy._u(
this .options.x)  ?   this .options.x : Boxy.DEFAULT_X,
            Boxy._u(
this .options.y)  ?   this .options.y : Boxy.DEFAULT_Y
        );
    }
    
    
if  ( this .options.show)  this .show();

};

Boxy.EF 
=   function () {};

jQuery.extend(Boxy, {
    
    WRAPPER:    
" <table cellspacing='0' cellpadding='0' border='0' class='boxy-wrapper'> "   +
                
" <tr><td class='top-left'></td><td class='top'></td><td class='top-right'></td></tr> "   +
                
" <tr><td class='left'></td><td class='boxy-inner'></td><td class='right'></td></tr> "   +
                
" <tr><td class='bottom-left'></td><td class='bottom'></td><td class='bottom-right'></td></tr> "   +
                
" </table> " ,
    
    DEFAULTS: {
        title:                  
null ,            //  titlebar text. titlebar will not be visible if not set.
        closeable:               true ,            //  display close link in titlebar?
        draggable:               true ,            //  can this dialog be dragged?
        clone:                   false ,           //  clone content prior to insertion into dialog?
        actuator:                null ,            //  element which opened this dialog
        center:                  true ,            //  center dialog in viewport?
        show:                    true ,            //  show dialog immediately?
        modal:                   false ,           //  make dialog modal?
        fixed:                   true ,            //  use fixed positioning, if supported? absolute positioning used otherwise
        closeText:               " <img src='images/img_bgArea02.gif' /> " ,       //  text to use for default close link
        unloadOnHide:            false ,           //  should this dialog be removed from the DOM after being hidden?
        clickToFront:            false ,           //  bring dialog to foreground on any click (not just titlebar)?
        behaviours:             Boxy.EF,         //  function used to apply behaviours to all content embedded in dialog.
        afterDrop:              Boxy.EF,         //  callback fired after dialog is dropped. executes in context of Boxy instance.
        afterShow:              Boxy.EF,         //  callback fired after dialog becomes visible. executes in context of Boxy instance.
        afterHide:              Boxy.EF,         //  callback fired after dialog is hidden. executed in context of Boxy instance.
        beforeUnload:           Boxy.EF,          //  callback fired after dialog is unloaded. executed in context of Boxy instance.
        useIframe:                false            //支持iframe遮罩层,解决ie6下select z-index最高的bug,只在ie6下时才用的到
    },
    
    DEFAULT_X:          
50 ,
    DEFAULT_Y:          
50 ,
    zIndex:             
1337 ,
    dragConfigured:     
false //  only set up one drag handler for all boxys
    resizeConfigured:    false ,
    dragging:           
null ,
    
    
//  load a URL and display in boxy
     //  url - url to load
     //  options keys (any not listed below are passed to boxy constructor)
     //    type: HTTP method, default: GET
     //    cache: cache retrieved content? default: false
     //    filter: jQuery selector used to filter remote content
    load:  function (url, options) {
        
        options 
=  options  ||  {};
        
        
var  ajax  =  {
            url: url, type: 'GET', dataType: 'html', cache: 
false , success:  function (html) {
                html 
=  jQuery(html);
                
if  (options.filter) html  =  jQuery(options.filter, html);
                
new  Boxy(html, options);
            }
        };
        
        jQuery.each(['type', 'cache'], 
function () {
            
if  ( this   in  options) {
                ajax[
this =  options[ this ];
                
delete  options[ this ];
            }
        });
        
        jQuery.ajax(ajax);
        
    },
    
    
//  allows you to get a handle to the containing boxy instance of any element
     //  e.g. <a href='#' onclick='alert(Boxy.get(this));'>inspect!</a>.
     //  this returns the actual instance of the boxy 'class', not just a DOM element.
     //  Boxy.get(this).hide() would be valid, for instance.
    get:  function (ele) {
        
var  p  =  jQuery(ele).parents('.boxy - wrapper');
        
return  p.length  ?  jQuery.data(p[ 0 ], 'boxy') :  null ;
    },
    
    
//  returns the boxy instance which has been linked to a given element via the
     //  'actuator' constructor option.
    linkedTo:  function (ele) {
        
return  jQuery.data(ele, 'active.boxy');
    },
    
    
//  displays an alert box with a given message, calling optional callback
     //  after dismissal.
    alert:  function (message, callback, options) {
        
return  Boxy.ask(message, ['确定'], callback, options);
    },
    
    
//  displays an alert box with a given message, calling after callback iff
     //  user selects OK.
    confirm:  function (message, after, options) {
        
return  Boxy.ask(message, ['确定', '取消'],  function (response) {
            
if  (response  ==  '确定') after();
        }, options);
    },
    
    
//  asks a question with multiple responses presented as buttons
     //  selected item is returned to a callback method.
     //  answers may be either an array or a hash. if it's an array, the
     //  the callback will received the selected value. if it's a hash,
     //  you'll get the corresponding key.
    ask:  function (question, answers, callback, options) {
        
        options 
=  jQuery.extend({modal:  true , closeable:  false },
                                options 
||  {},
                                {show: 
true , unloadOnHide:  true });
        
        
var  body  =  jQuery(' < div ></ div > ').append(jQuery(' < div class = " question " ></ div > ').html(question));
        
        
//  ick
         var  map  =  {}, answerStrings  =  [];
        
if  (answers  instanceof  Array) {
            
for  ( var  i  =   0 ; i  <  answers.length; i ++ ) {
                map[answers[i]] 
=  answers[i];
                answerStrings.push(answers[i]);
            }
        } 
else  {
            
for  ( var  k  in  answers) {
                map[answers[k]] 
=  k;
                answerStrings.push(answers[k]);
            }
        }
        
        
var  buttons  =  jQuery(' < form class = " answers " ></ form > ');
        buttons.html(jQuery.map(answerStrings, 
function (v) {
            
return   " <input type='button' value=' "   +  v  +   " ' /> " ;
        }).join(' '));
        
        jQuery('input[type
= button]', buttons).click( function () {
            
var  clicked  =   this ;
            Boxy.get(
this ).hide( function () {
                
if  (callback) callback(map[clicked.value]);
            });
        });
        
        body.append(buttons);
        
        
new  Boxy(body, options);
        
    },
    
    
//  returns true if a modal boxy is visible, false otherwise
    isModalVisible:  function () {
        
return  jQuery('.boxy - modal - blackout').length  >   0 ;
    },
    
    _u: 
function () {
        
for  ( var  i  =   0 ; i  <  arguments.length; i ++ )
            
if  ( typeof  arguments[i]  !=  'undefined')  return   false ;
        
return   true ;
    },
    
    _handleResize: 
function (evt) {
        
var  d  =  jQuery(document);
        jQuery('.boxy
- modal - blackout').css('display', 'none').css({
            width: d.width(), height: d.height()
        }).css('display', 'block');
    },
    
    _handleDrag: 
function (evt) {
        
var  d;
        
if  (d  =  Boxy.dragging) {
            d[
0 ].boxy.css({left: evt.pageX  -  d[ 1 ], top: evt.pageY  -  d[ 2 ]});
        }
    },
    
    _nextZ: 
function () {
        
return  Boxy.zIndex ++ ;
    },
    
    _viewport: 
function () {
        
var  d  =  document.documentElement, b  =  document.body, w  =  window;
        
return  jQuery.extend(
            jQuery.browser.msie 
?
                { left: b.scrollLeft 
||  d.scrollLeft, top: b.scrollTop  ||  d.scrollTop } :
                { left: w.pageXOffset, top: w.pageYOffset },
            
! Boxy._u(w.innerWidth)  ?
                { width: w.innerWidth, height: w.innerHeight } :
                (
! Boxy._u(d)  &&   ! Boxy._u(d.clientWidth)  &&  d.clientWidth  !=   0   ?
                    { width: d.clientWidth, height: d.clientHeight } :
                    { width: b.clientWidth, height: b.clientHeight }) );
    }

});

Boxy.prototype 
=  {
    
    
//  Returns the size of this boxy instance without displaying it.
     //  Do not use this method if boxy is already visible, use getSize() instead.
    estimateSize:  function () {
        
this .boxy.css({visibility: 'hidden', display: 'block'});
        
var  dims  =   this .getSize();
        
this .boxy.css('display', 'none').css('visibility', 'visible');
        
return  dims;
    },
                
    
//  Returns the dimensions of the entire boxy dialog as [width,height]
    getSize:  function () {
        
return  [ this .boxy.width(),  this .boxy.height()];
    },
    
    
//  Returns the dimensions of the content region as [width,height]
    getContentSize:  function () {
        
var  c  =   this .getContent();
        
return  [c.width(), c.height()];
    },
    
    
//  Returns the position of this dialog as [x,y]
    getPosition:  function () {
        
var  b  =   this .boxy[ 0 ];
        
return  [b.offsetLeft, b.offsetTop];
    },
    
    
//  Returns the center point of this dialog as [x,y]
    getCenter:  function () {
        
var  p  =   this .getPosition();
        
var  s  =   this .getSize();
        
return  [Math.floor(p[ 0 +  s[ 0 /   2 ), Math.floor(p[ 1 +  s[ 1 /   2 )];
    },
                
    
//  Returns a jQuery object wrapping the inner boxy region.
     //  Not much reason to use this, you're probably more interested in getContent()
    getInner:  function () {
        
return  jQuery('.boxy - inner',  this .boxy);
    },
    
    
//  Returns a jQuery object wrapping the boxy content region.
     //  This is the user-editable content area (i.e. excludes titlebar)
    getContent:  function () {
        
return  jQuery('.boxy - content',  this .boxy);
    },
    
    
//  Replace dialog content
    setContent:  function (newContent) {
        newContent 
=  jQuery(newContent).css({display: 'block'}).addClass('boxy - content');
        
if  ( this .options.clone) newContent  =  newContent.clone( true );
        
this .getContent().remove();
        
this .getInner().append(newContent);
        
this ._setupDefaultBehaviours(newContent);
        
this .options.behaviours.call( this , newContent);
        
return   this ;
    },
    
    
//  Move this dialog to some position, funnily enough
    moveTo:  function (x, y) {
        
this .moveToX(x).moveToY(y);
        
return   this ;
    },
    
    
//  Move this dialog (x-coord only)
    moveToX:  function (x) {
        
if  ( typeof  x  ==  'number')  this .boxy.css({left: x});
        
else   this .centerX();
        
return   this ;
    },
    
    
//  Move this dialog (y-coord only)
    moveToY:  function (y) {
        
if  ( typeof  y  ==  'number')  this .boxy.css({top: y});
        
else   this .centerY();
        
return   this ;
    },
    
    
//  Move this dialog so that it is centered at (x,y)
    centerAt:  function (x, y) {
        
var  s  =   this [ this .visible  ?  'getSize' : 'estimateSize']();
        
if  ( typeof  x  ==  'number')  this .moveToX(x  -  s[ 0 /   2 );
        
if  ( typeof  y  ==  'number')  this .moveToY(y  -  s[ 1 /   2 );
        
return   this ;
    },
    
    centerAtX: 
function (x) {
        
return   this .centerAt(x,  null );
    },
    
    centerAtY: 
function (y) {
        
return   this .centerAt( null , y);
    },
    
    
//  Center this dialog in the viewport
     //  axis is optional, can be 'x', 'y'.
    center:  function (axis) {
        
var  v  =  Boxy._viewport();
        
var  o  =   this .options.fixed  ?  [ 0 0 ] : [v.left, v.top];
        
if  ( ! axis  ||  axis  ==  'x')  this .centerAt(o[ 0 +  v.width  /   2 null );
        
if  ( ! axis  ||  axis  ==  'y')  this .centerAt( null , o[ 1 +  v.height  /   2 );
        
return   this ;
    },
    
    
//  Center this dialog in the viewport (x-coord only)
    centerX:  function () {
        
return   this .center('x');
    },
    
    
//  Center this dialog in the viewport (y-coord only)
    centerY:  function () {
        
return   this .center('y');
    },
    
    
//  Resize the content region to a specific size
    resize:  function (width, height, after) {
        
if  ( ! this .visible)  return ;
        
var  bounds  =   this ._getBoundsForResize(width, height);
        
this .boxy.css({left: bounds[ 0 ], top: bounds[ 1 ]});
        
this .getContent().css({width: bounds[ 2 ], height: bounds[ 3 ]});
        
if  (after) after( this );
        
return   this ;
    },
    
    
//  Tween the content region to a specific size
    tween:  function (width, height, after) {
        
if  ( ! this .visible)  return ;
        
var  bounds  =   this ._getBoundsForResize(width, height);
        
var  self  =   this ;
        
this .boxy.stop().animate({left: bounds[ 0 ], top: bounds[ 1 ]});
        
this .getContent().stop().animate({width: bounds[ 2 ], height: bounds[ 3 ]},  function () {
            
if  (after) after(self);
        });
        
return   this ;
    },
    
    
//  Returns true if this dialog is visible, false otherwise
    isVisible:  function () {
        
return   this .visible;    
    },
    
    
//  Make this boxy instance visible
    show:  function () {
        
if  ( this .visible)  return ;
        
if  ( this .options.modal) {
            
var  self  =   this ;
            
if  ( ! Boxy.resizeConfigured) {
                Boxy.resizeConfigured 
=   true ;
                jQuery(window).resize(
function () { Boxy._handleResize(); });
            }
            
this .modalBlackout  =  jQuery(' < div class = " boxy-modal-blackout " ></ div > ')
                .css({zIndex: Boxy._nextZ(),
                      opacity: 
0 ,
                      width: jQuery(document).width(),
                      height: jQuery(document).height()})
                .appendTo(document.body);
            
this .toTop();
            
if  ( this .options.closeable) {
                jQuery(document.body).bind('keypress.boxy', 
function (evt) {
                    
var  key  =  evt.which  ||  evt.keyCode;
                    
if  (key  ==   27 ) {
                        self.hide();
                        jQuery(document.body).unbind('keypress.boxy');
                    }
                });
            }
        }
        
this .boxy.stop().css({opacity:  1 }).show();
        
this .visible  =   true ;
        
this ._fire('afterShow');
        this.center();
        
if (this.options.useIframe == true) {
            
this.temp_iframe = jQuery("<iframe class='bg_iframe' src='javascript:void(0);' scrolling='no' frameborder='0' style='position: absolute;'></iframe>");
            
this.temp_iframe.width(this.getSize()[0]);
            
this.temp_iframe.height(this.getSize()[1]);
            
this.temp_iframe[0].zIndex =  - 1;
            var v = Boxy._viewport();
            this.temp_iframe.css("top",this.getPosition()[1]);
            
this.temp_iframe.css("left",this.getPosition()[0]);
            jQuery(document.body).append(this.temp_iframe);
            this.toTop();
        }

        
return   this ;
    },
    //弹层大小会改变时会用到这个方法,Boxy.get(this).auto_resize();
    auto_resize:function(){
        
if (this.options.useIframe == true) {
            
this.temp_iframe.width(this.getSize()[0]);
            
this.temp_iframe.height(this.getSize()[1]);
        }
    },

    
    
//  Hide this boxy instance
    hide:  function (after) {
        
if  ( ! this .visible)  return ;
        
var  self  =   this ;
        
if  ( this .options.modal) {
            jQuery(document.body).unbind('keypress.boxy');
            
this .modalBlackout.animate({opacity:  0 },  function () {
                jQuery(
this ).remove();
            });
        }
        
this .boxy.stop().animate({opacity:  0 },  300 function () {
            self.boxy.css({display: 'none'});
            self.visible 
=   false ;
            self._fire('afterHide');
            
if  (after) after(self);
            
if  (self.options.unloadOnHide) self.unload();
        });
        if (this.options.useIframe == true) {
            jQuery("iframe").remove(".bg_iframe"); 
        }

        
return   this ;
    },
    
    toggle: 
function () {
        
this [ this .visible  ?  'hide' : 'show']();
        
return   this ;
    },
    
    hideAndUnload: 
function (after) {
        
this .options.unloadOnHide  =   true ;
        
this .hide(after);
        
return   this ;
    },
    
    unload: 
function () {
        
this ._fire('beforeUnload');
        
this .boxy.remove();
        
if  ( this .options.actuator) {
            jQuery.data(
this .options.actuator, 'active.boxy',  false );
        }
    },
    
    
//  Move this dialog box above all other boxy instances
    toTop:  function () {
        
this .boxy.css({zIndex: Boxy._nextZ()});
        
return   this ;
    },
    
    
//  Returns the title of this dialog
    getTitle:  function () {
        
return  jQuery(' >  .title - bar h2',  this .getInner()).html();
    },
    
    
//  Sets the title of this dialog
    setTitle:  function (t) {
        jQuery('
>  .title - bar h2',  this .getInner()).html(t);
        
return   this ;
    },
    
    
//
     //  Don't touch these privates
    
    _getBoundsForResize: 
function (width, height) {
        
var  csize  =   this .getContentSize();
        
var  delta  =  [width  -  csize[ 0 ], height  -  csize[ 1 ]];
        
var  p  =   this .getPosition();
        
return  [Math.max(p[ 0 -  delta[ 0 /   2 0 ),
                Math.max(p[
1 -  delta[ 1 /   2 0 ), width, height];
    },
    
    _setupTitleBar: 
function () {
        
if  ( this .options.title) {
            
var  self  =   this ;
            
var  tb  =  jQuery( " <div class='title-bar'></div> " ).html( " <h2> "   +   this .options.title  +   " </h2> " );
            
if  ( this .options.closeable) {
                tb.append(jQuery(
" <a href='#' class='close'></a> " ).html( this .options.closeText));
            }
            
if  ( this .options.draggable) {
                tb[
0 ].onselectstart  =   function () {  return   false ; }
                tb[
0 ].unselectable  =  'on';
                tb[
0 ].style.MozUserSelect  =  'none';
                
if  ( ! Boxy.dragConfigured) {
                    jQuery(document).mousemove(Boxy._handleDrag);
                    Boxy.dragConfigured 
=   true ;
                }
                tb.mousedown(
function (evt) {
                    self.toTop();
                    Boxy.dragging 
=  [self, evt.pageX  -  self.boxy[ 0 ].offsetLeft, evt.pageY  -  self.boxy[ 0 ].offsetTop];
                    jQuery(
this ).addClass('dragging');
                }).mouseup(
function () {
                    jQuery(
this ).removeClass('dragging');
                    Boxy.dragging 
=   null ;
                    self._fire('afterDrop');
                });
            }
            
this .getInner().prepend(tb);
            
this ._setupDefaultBehaviours(tb);
        }
    },
    
    _setupDefaultBehaviours: 
function (root) {
        
var  self  =   this ;
        
if  ( this .options.clickToFront) {
            root.click(
function () { self.toTop(); });
        }
        jQuery('.close', root).click(
function () {
            self.hide();
            
return   false ;
        }).mousedown(
function (evt) { evt.stopPropagation(); });
    },
    
    _fire: 
function (event) {
        
this .options[event].call( this );
    }
    
};



你可能感兴趣的:(jquery.boxy.js扩展 (0.1.40))