/**
 *  @description    一个不依赖于框架的 Tips 类
 *  @author         suches@btbtd.org
 *  @date           2011-6-18 10:01:21 
 *  @see            JTips 
 */ 
void function()
{
    
    function XTips( $box, $params )
    {        
        this.model = new Model($box, $params);
        this.view = new View( this.model );
    }
    
    XTips.exec =
    function($box, $params)
    {
        return new XTips($box, $params).init();
    };
    
    XTips.prototype =
    {
        init:
        function()
        {            
            var _ = this;
            
            if( !_.model.box )
            {
                throw new Error('XTips box is null!');
            }
            
            traversalNode
            ( 
                _.model.box,
                function(node)
                {
                    var tips = trim(node.getAttribute(_.model.textAttrKey)||'');   
                    //alert(tips)                 
                    if( !tips ) return;
                    
                    _.view.initNode( node, tips );
                    
                    return false;
                } 
            );
            
            return _;
        }
    };
    
    
    function Model($box, $params)
    {
        this.box = $box?( typeof $box==="string"?document.getElementById($box):$box ):document.body;
        //alert( this.box.innerHTML )
        
        this.textAttrKey = 'tips';
        this.tipsBoxId = '__XTIPS_BOX__';
        
        this.tipsStyle =
        {
          position: 'absolute'
          , width: '200px'
          , border: '1px solid #FFCC00'
          , padding: '5px'
          , background: '#5D5147'
          , 'lineHeight': '22px'
          , color: 'white'
          , 'zIndex': 90000
        };
        
        
        for( var k in $params )
        {
            this[k] = $params[k];
        }
    }
    
    Model.prototype =
    {
        tipsBox:
        function()
        {
            var box = document.getElementById(this.tipsBoxId);            
            if( !box)
            {
                box = document.createElement('div');
                box.id = this.tipsBoxId;
                box.style.display = 'none';
                
                if ( document.body.firstChild )
                {
                    document.body.insertBefore( box, document.body.firstChild );
                }
                else
                {
                    document.body.appendChild( box );
                }                
                
                opacity_f( box, 90 );
                
                for( var k in this.tipsStyle ) box.style[k] = this.tipsStyle[k];
            }
            
            return box;
        },
        
        tipsPos:
        function($evt)
        {
            var r = { x:0, y:0 }, padX = 14, padY = 14;
            var tipsBox = this.tipsBox();
            
            r.x = $evt.clientX + document.documentElement.scrollLeft + padX;
            r.y = $evt.clientY + document.documentElement.scrollTop + padY;
            
            
            var vp = viewport_f();
            
            var maxX = r.x + tipsBox.offsetWidth;
            var maxY = r.y + tipsBox.offsetHeight;
            
            
            if( maxX > vp.max_width - 20 )
            {
                r.x = $evt.clientX + document.documentElement.scrollLeft - 5 - tipsBox.offsetWidth;
                
                if( r.x < 0) r.x = 0;
            }
            
            if( maxY > vp.max_height - 20 )
            {
                r.y = $evt.clientY + document.documentElement.scrollTop - 6 - tipsBox.offsetHeight;
            }
            
            //if( maxX > $evt.clientWidth)
            
            return r;
        }
    };
    
    function View( $model )
    {
        this.model = $model;
    }
    
    View.prototype =
    {
        initNode:
        function( $node, $tips )
        {
            var _ = this;            
            
            //document.title = screen.clientWidth;
            attach_event_f( $node, 'mouseover', _.onMosueOver($node, $tips) );
            attach_event_f( $node, 'mouseout', _.onMouseOut($node, $tips) );
            attach_event_f( $node, 'mousemove', _.onMouseMove($node, $tips) );   
            
                    
            var tipsBox = _.model.tipsBox();            
            attach_event_f
            ( 
                window, 
                'mousemove', 
                function()
                {  
                    tipsBox.style.display = 'none';
                } 
            );          
        },
        
        onMosueOver:
        function($node, $tips)
        {
            var _ = this;
            return function($evt)
            { 
                $evt = $evt || window.event;
                if( $evt.preventDefault ) $evt.preventDefault();
                if( $evt.stopPropagation ) $evt.stopPropagation();
                
                var tipsBox = _.model.tipsBox();
                
                tipsBox.innerHTML = $tips;         
                       
                var point = _.model.tipsPos($evt);
                tipsBox.style.left = point.x + 'px';
                tipsBox.style.top = point.y + 'px';               
                
                tipsBox.style.display = 'block';
                
            };
        },
        
        onMouseMove:
        function($node)
        {
            var _ = this;
            return function($evt)
            {
                $evt = $evt || window.event;
                if( $evt.preventDefault ) $evt.preventDefault();
                if( $evt.stopPropagation ) $evt.stopPropagation();
                
                var tipsBox = _.model.tipsBox();    
                
                var point = _.model.tipsPos($evt);
                tipsBox.style.left = point.x + 'px';
                tipsBox.style.top = point.y + 'px';    
            };
        },
        
        onMouseOut:
        function($node)
        {
            var _ = this;
            return function($evt)
            {   
                $evt = $evt || window.event;
                if( $evt.preventDefault ) $evt.preventDefault();
                if( $evt.stopPropagation ) $evt.stopPropagation();
                
                var tipsBox = _.model.tipsBox();
                tipsBox.style.display = 'none';
            };
        }
    };
    
    
    
    /**
     *  遍历节点
     *  @author     suches@btbtd.org
     *  @date       2011-6-18          
     */         
    function traversalNode($box, $callback)
    {
        if(!$box) return;
        
        var fNode = 1;
        
        while( fNode = (fNode===1?$box.firstChild:fNode.nextSibling)   )
        {
            if( fNode.nodeType === 1 )
            {
                //if( $callback ) $callback(fNode);
                if( $callback && $callback(fNode) === false ) continue;
                arguments.callee( fNode, $callback );
            }
        }        
    }
    
    function trim( $s )
    {
        return $s.replace( /^[\s]*|[\s]*$/g, '' );
    }
    
/*  
    版本：2011-6-18
    作用：兼容各浏览器的附加事件函数
必填参数：e_, event_name_s, func_f
*/
function attach_event_f(e_, event_name_s, func_f, capture_b)
{/* shawl.qiu, void return, func:none */
    if(document.addEventListener){e_.addEventListener(event_name_s, func_f, capture_b);}
    else if(document.attachEvent)
    {
        event_name_s = 'on'+event_name_s;
        if(e_[event_name_s]==null){e_[event_name_s] = func_f;} else{e_.attachEvent(event_name_s, func_f);}
    }
    return;
}/* end function attach_event_f(e_, event_name_s, func_f, capture_b) */

/*  
    版本：2008-9-19
    作用：取屏幕的可用大小相关值
必填参数：none
*/
function viewport_f() 
{/* shawl.qiu code, return object, func: none */
  var myWidth = 0, myHeight = 0;
  if(typeof(window.innerWidth ) == 'number' ) 
  {/* Non-IE */
    width_i = window.innerWidth; height_i = window.innerHeight;
  } 
  else if 
  (
    document.documentElement &&( document.documentElement.clientWidth || document.documentElement.clientHeight ) 
  ) 
  {/* IE 6 */
    width_i = document.documentElement.clientWidth; height_i = document.documentElement.clientHeight;
  } 
  else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) 
  {/* IE 4 */
    width_i = document.body.clientWidth; height_i = document.body.clientHeight;
  }
  return {
            width:width_i
            , height:height_i
            , max_width: width_i+document.documentElement.scrollLeft
            , max_height: height_i+document.documentElement.scrollTop
          };
}/* function viewport_f() */

/*  
    版本：2008-9-5
    作用：设置HTML 元素透明度
必填参数：e_, opacity_i
*/
function opacity_f(e_, opacity_i)
{/* shawl.qiu code, return void, func:none */
  e_.style.opacity = opacity_i/100;
  e_.style.filter = 'alpha(opacity=' + opacity_i + ')';
  return;
}/* function opacity_f(e_, opacity_i) */
    
    window.XTips = XTips;
}();

