﻿/// <reference name="MicrosoftAjax.debug.js" />

String.isNullOrEmpty = function( value ){
    /// <summary>
    /// 指示指定的String是否null或者空字符串
    /// </summary>
    /// <param name="value" type="String">要判定的字符串</param>
    if( !value ) return true;
    if( value == null ) return true;
    if( typeof( value ) != "string" ) value = value.toString();
    return value.length == 0;
};

String.prototype.toUnicodeBytes = function (){
    /// <summary>
    /// 转换成Unicode编码的字节数组
    /// </summary>
    /// <returns type="Array"></returns>
    var unicodeBytes = [];
    for( var i = 0; i < this.length; i ++ )
    {
        var n = this.charCodeAt( i );
        if( n < 0 ) n = 0xFFFF + n + 1;
        unicodeBytes.push( n & 0xFF );
        if( n > 255 )
        {
            unicodeBytes.push( ( n >> 8 ) & 0xFF );
        }
        else
        {
            unicodeBytes.push( 0 );
        }
    }
    return unicodeBytes;
};

String.fromUnicodeBytes = function StringFromUnicodeBytes( unicodeBytes, startIndex, count ){
    /// <summary>
    /// 把Unicode编码的字节数组转换为字符串
    /// </summary>
    /// <param name="unicodeBytes" type="Array">包含Unicode方式编码的字符串的字节数组</param>
    /// <param name="startIndex" type="Number">指定从第startIndex个字节开始转换</param>
    /// <param name="count" type="Array">从startIndex开始，要转换为字符串的字节数</param>
    /// <returns type="String"></returns>
    if( !unicodeBytes || unicodeBytes == null || unicodeBytes.length == 0 ) return "";
    if( !startIndex ) startIndex = 0;
    if( !count ) count = unicodeBytes.length - startIndex;
    if( count % 2 == 1 ) throw Error.argument( "count", "Unicode字符串的字节数组长度应该是2的倍数。" );
    var txtBuilder = new Sys.StringBuilder();
    var endIndex = startIndex + count;
    for( var i = startIndex; i < endIndex; i += 2 )
    {
        txtBuilder.append( String.fromCharCode( unicodeBytes[ i ] | ( ( unicodeBytes[ i + 1 ] << 8 ) & 0xFF00 ) ) );
    }
    return txtBuilder.toString();
};

String.prototype.toUTF8Bytes = function(){
    /// <summary>
    /// 转换成UTF8编码的字节数组
    /// </summary>
    /// <returns type="Array"></returns>
    var utf8Bytes = [];
    for( var i = 0; i < this.length; i ++ )
    {
        var n = this.charCodeAt( i );
        if( n < 0 )  n = 0xFFFF + n + 1;
        if( n <= 0x007F )
        {
            //1 byte
            //0000 - 007F   0xxxxxxx 
            utf8Bytes.push( n );
        }
        else if( n <= 0x07FF )
        {
            //2 bytes
            //0080 - 07FF   110xxxxx 10xxxxxx 
            utf8Bytes.push( 0xC0 | ( ( n >> 6 ) & 0x1F ) ); 
            utf8Bytes.push( 0x80 | ( n & 0x3F ) );
        } 
        else
        {
            //3 bytes
            //0800 - FFFF   1110xxxx 10xxxxxx 10xxxxxx
            utf8Bytes.push( 0xE0 | (  ( n >> 12 ) & 0x0F ) );
            utf8Bytes.push( 0x80 | ( ( n >> 6 ) & 0x3F ) );
            utf8Bytes.push( 0x80 | ( n & 0x3F ) );
        }
    }
    return utf8Bytes;
};

String.fromUTF8Bytes = function StringFromUTF8Bytes( utf8Bytes, startIndex, count ){
    /// <summary>
    /// 把UTF8编码的字节数组转换为字符串
    /// </summary>
    /// <param name="utf8Bytes" type="Array">包含UTF8方式编码的字符串的字节数组</param>
    /// <param name="startIndex" type="Number">指定从第startIndex个字节开始转换</param>
    /// <param name="count" type="Array">从startIndex开始，要转换为字符串的字节数</param>
    /// <returns type="String"></returns>
    if( !utf8Bytes || utf8Bytes == null || utf8Bytes.length == 0 ) return "";
    if( !startIndex ) startIndex = 0;
    if( !count ) count = utf8Bytes.length - startIndex;
    var index = startIndex;
    var endIndex = startIndex + count;
    var txtBuilder = new Sys.StringBuilder();
    while( index < endIndex )
    {
        var b0 = utf8Bytes[ index ++ ];
        if( b0 >> 7 == 0 )
        {
            txtBuilder.append( String.fromCharCode( b0 ) );
        }
        else
        {
            var b1 = utf8Bytes[ index ++ ];
            if( ( ( b0 >> 5 ) & 0x01 ) == 0 )
            {
                txtBuilder.append( String.fromCharCode(  ( b1 & 0x7F ) | ( ( b0 & 0x1F ) << 6 )  ) );
            }
            else
            {
                var b2 = utf8Bytes[ index ++ ];
                txtBuilder.append( String.fromCharCode(  ( b2 & 0x7F ) | ( ( b1 & 0x7F ) << 6 ) | ( ( b0 & 0x0F ) << 12 ) ) );
            }
        }
    }
    return txtBuilder.toString();
};


String.prototype.isNumeric = function( radix ){
    /// <summary>
    /// 确定字符串内容是不是一个有效的数字。
    /// </summary>
    /// <param name="radix" type="Number">进制</param>    
    /// <returns type="Boolean"></returns>
    if( !radix || typeof( radix ) != "number" ) radix = 10;
    else if( radix !== 2 && radix !== 8 && radix !== 10 && radix !== 16 ) radix = 10; 
    return !isNaN( parseInt( this, radix ) );
}; 

String.prototype.isNumbers = function(){
    /// <summary>
    /// 确定字符串内容是不是全是数字。
    /// </summary>
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c < 48 || c > 57 ) return false;
    }
    return true;
};

String.prototype.isFloat = function(){
    /// <summary>
    /// 确定字符串内容是不是一个有效的数字。
    /// </summary>
    /// <returns type="Boolean"></returns>
    return !isNaN( parseFloat( this ) );
}; 

String.prototype.toSBC = function(){
    /// <summary>
    /// 将字符串中的半角字符转成全角字符。
    /// </summary>
    /// <returns type="String"></returns>
    var txt = new Sys.StringBuilder();
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c == 32 ) c = 12288;
        else if( c < 128 ) c += 65248;
        txt.append( String.fromCharCode( c ) );  
    }
    return txt.toString();
};

String.prototype.toDBC = function(){
    /// <summary>
    /// 将字符串中的全角字符转成半角字符。
    /// </summary>
    /// <returns type="String"></returns>
    var txt = new Sys.StringBuilder();
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c == 12288 ) c = 32;
        else if( c > 65280 && c < 65375 ) c -= 65248;
        txt.append( String.fromCharCode( c ) );  
    }
    return txt.toString();
};

String.prototype.isLowerLetters = function(){
    /// <summary>
    /// 确定字符串内容是不是全是小写字母。
    /// </summary>
    /// <returns type="Boolean"></returns>
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c < 97 || c > 122 ) return false;
    }
    return true;
};

String.prototype.isUpperLetters = function(){
    /// <summary>
    /// 确定字符串内容是不是全是小写字母。
    /// </summary>
    /// <returns type="Boolean"></returns>
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c < 65 || c > 90 ) return false;
    }
    return true;
};

String.prototype.isLetters = function(){
    /// <summary>
    /// 确定字符串内容是不是全是小写字母。
    /// </summary>
    /// <returns type="Boolean"></returns>
    for( var i = 0; i < this.length; i ++ )
    {
        var c = this.charCodeAt( i );
        if( c < 0 ) c = 0xFFFF + c + 1;
        if( c < 65 || ( c > 90 && c < 97 ) || c > 122 ) return false;
    }
    return true;
};

String.prototype.isEmail = function(){
    /// <summary>
    /// 确定字符串内容是不是一个有效的电子邮件地址。
    /// </summary>
    /// <returns type="Boolean"></returns>
    //var regex = /^[a-z\d]+[a-z\d_\-\.]*[a-z\d]@[a-z\d_\-\.]*[a-z\d]\.[a-z]{2,}$/i;
    var regex = new RegExp( "^[a-z\\d]+[a-z\\d_\\-\\.]*[a-z\\d]@[a-z\\d_\\-\\.]*[a-z\\d]\\.[a-z]{2,}$", "ig" );
    return regex.test( this );
};

String.prototype.isMobile = function(){
    /// <summary>
    /// 确定字符串内容是不是一个有效的手机号。
    /// </summary>
    /// <returns type="Boolean"></returns>
    //var regex = /^(((\+)|(00))?\d{1,3})?0?1[35]\d{9}$/i;
    var regex = new RegExp( "^(((\\+)|(00))?\\d{1,3})?0?1[35]\\d{9}$", "ig" );
    return regex.test( this );
};

String.prototype.isFixPhone = function(){
    /// <summary>
    /// 确定字符串内容是不是一个有效的固定电话号码。
    /// </summary>
    /// <returns type="Boolean"></returns>
    //var regex = /^(((\+)|(00))?\d{1,3})?((\(0[1-9]\d{1,2}\))|(0[1-9]\d{1,2}\-?))?[2-9]\d{6,7}(\-\d+)*$/i;
    var regex = new RegExp( "^(((\\+)|(00))?\\d{1,3})?((\\(0[1-9]\\d{1,2}\\))|(0[1-9]\\d{1,2}\\-?))?[2-9]\\d{6,7}(\\-\\d+)*$", "ig" );
    return regex.test( this );
};


Number.prototype.add32 = function( v ){
    /// <summary>
    /// 执行32位加法
    /// </summary>
    /// <param name="v" type="Number">被加数</param>
    /// <returns type="Number"></returns>
    var lsw = ( this & 0xFFFF ) + ( v & 0xFFFF );
    var msw = ( this >> 16 ) + ( v >> 16 ) + ( lsw >> 16 );
    return ( msw << 16 ) | ( lsw & 0xFFFF );
};

Number.prototype.sub32 = function( v ){
    /// <summary>
    /// 执行32位减法
    /// </summary>
    /// <param name="v" type="Number">被减数</param>
    /// <returns type="Number"></returns>
    var lsw = ( this & 0xFFFF ) - ( v & 0xFFFF );
    var msw = ( this >> 16 ) - ( v >> 16 ) + ( lsw >> 16 );
    return ( msw << 16 ) | ( lsw & 0xFFFF );
};

Number.prototype.rotateL32 = function( n ){
    /// <summary>
    /// 32位循环左移
    /// </summary>
    /// <param name="n" type="Number">左移位数</param>
    /// <returns type="Number"></returns>
    n %= 32;
    return ( ( this << n ) & 0xFFFFFFFF ) | this >>> ( 32 - n );
};

Number.prototype.rotateR32 = function( n ){
    /// <summary>
    /// 32位循环右移
    /// </summary>
    /// <param name="n" type="Number">左移位数</param>
    /// <returns type="Number"></returns>
    n %= 32;
    return ( this >>> n | this << ( 32 - n ) );
};

Number.prototype.swap32 = function(){
    /// <summary>
    /// 32位交换字节顺序
    /// </summary>
    /// <returns type="Number"></returns>
    return ( ( this >> 24 ) & 0x000000FF )
            | ( ( this << 24 ) & 0xFF000000 )
            | ( ( this >> 8 ) & 0x0000FF00 )
            | ( ( this << 8 ) & 0x00FF0000 );
};

Number.prototype.toBytes32 = function(){
    /// <summary>
    /// 将32位数字转换成字节数组
    /// </summary>
    /// <returns type="Array"></returns>
    return [
        this & 0xFF,
        ( this >>> 8 ) & 0xFF,
        ( this >>> 16 ) & 0xFF,
        ( this >>> 24 ) & 0xFF        
    ];
};

Number.fromBytes32 = function( bytes, offset ){
    /// <summary>
    /// 将数组中的4字节还原为32位数字。
    /// </summary>
    /// <param name="bytes" type="Array">字节数组</param>
    /// <param name="offset" type="Number">偏移位置</param>
    /// <returns type="Number"></returns>
    if( !offset ) offset = 0;
    if( bytes.length - offset - 4 < 0 ) throw Error.argumentOutOfRange( "offset", offset, null );
    return ( bytes[ offset ] & 0xFF )
     | ( ( bytes[ offset + 1 ] & 0xFF ) << 8 ) 
     | ( ( bytes[ offset + 2 ] & 0xFF ) << 16 ) 
     | ( ( bytes[ offset + 3 ] & 0xFF ) << 24 );
}


Array.prototype.toHexString = function( paddding ){
    /// <summary>
    /// 将数字型数组转换为16进制表示形式的字符串
    /// </summary>
    /// <param name="paddding" type="Number">填充长度</param>
    /// <returns type="String"></returns>
    if( !paddding ) paddding = 2;
    var hex = new Sys.StringBuilder();
    for( var i = 0; i < this.length; i ++ )
    {
        var _h = parseInt( this[ i ].toString() ).toString( 16 ).toUpperCase();
        var _pn = paddding - _h.length;
        while( _pn -- > 0 )
        {
            hex.append( "0" );
        }
        hex.append( _h );
    }
    return hex.toString();
};


Function.allwaysReturnFalse = function(){
    /// <summary>
    /// 总是返回false。
    /// </summary>
    alert( "allwaysReturnFalse" );
    return false;
};

Type.registerNamespace( "BadBug.DataStructures" );

BadBug.DataStructures.LinkedListNode = function( value ){
    /// <summary>
    /// 表示链表的节点
    /// </summary>
    /// <param name="value" type="Object">存储在节点中的对象</param>
    /// <field name="prev" type="BadBug.DataStructures.LinkedListNode">指向链表中的上一个节点</field>
    /// <field name="next" type="BadBug.DataStructures.LinkedListNode">指向链表中的下一个节点</field>
    /// <field name="value" type="Object">存储在节点中包含的值</field>
    BadBug.DataStructures.LinkedListNode.initializeBase( this );
    this.prev = null;
    this.next = null;
    this.value = value;
};

BadBug.DataStructures.LinkedListNode.prototype = {
    initialize: function(){
        BadBug.DataStructures.LinkedListNode.callBaseMethod( this, "initialize" );    
    },
    dispose: function(){
        BadBug.DataStructures.LinkedListNode.callBaseMethod( this, "dispose" );
    }
};

BadBug.DataStructures.LinkedListNode.registerClass( "BadBug.DataStructures.LinkedListNode", Sys.Component );

BadBug.DataStructures.LinkedList = function(){
    /// <summary>
    /// 双向链表
    /// </summary>
    BadBug.DataStructures.LinkedList.initializeBase( this );
    this._firstNode = null;
    this._lastNode = null;
    this._nodeCount = 0;
};

BadBug.DataStructures.LinkedList.prototype = {
    initialize: function(){
        BadBug.DataStructures.LinkedList.callBaseMethod( this, "initialize" );    
    },
    dispose: function(){
        BadBug.DataStructures.LinkedList.callBaseMethod( this, "dispose" );
    },
    getFirstNode: function(){
        /// <summary>
        /// 获取链表的第一个节点
        /// </summary>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this._firstNode;
    },
    getLastNode: function(){
        /// <summary>
        /// 获取链表的最后一个节点
        /// </summary>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this._lastNode;
    },
    getNodeCount: function(){
        /// <summary>
        /// 获取链表中实际包含的节点数
        /// </summary>
        /// <returns type="Number"></returns>
        return this._nodeCount;
    },
    addNodeAfter: function( node, newNode ){
        /// <summary>
        /// 在链表中指定的现有节点后面添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要在其后面插入newNode的节点</param>
        /// <param name="newNode" type="BadBug.DataStructures.LinkedListNode">要添加到链表的新节点</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        newNode.prev = node;
        newNode.next = null;
        if( node.next != null )
        {
            newNode.next = node.next;
            node.next.prev = newNode;
        }
        node.next = newNode;
        this._nodeCount ++;    
        return newNode;
    },
    addAfter: function( node, value ){
        /// <summary>
        /// 在链表中指定的现有节点后面添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要在其后面插入包含value的新节点的节点</param>
        /// <param name="value" type="Object">要添加到链表的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this.addNodeAfter( node, new BadBug.DataStructures.LinkedListNode( value ) );
    },
    addNodeBefore: function( node, newNode ){
        /// <summary>
        /// 在链表中指定的现有节点前面添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要在其前面插入newNode的节点</param>
        /// <param name="newNode" type="BadBug.DataStructures.LinkedListNode">要添加到链表的新节点</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        newNode.next = node;
        newNode.prev = null;
        if( node.prev != null )
        {
            newNode.prev = node.prev;
            node.prev.next = newNode;
        }
        node.prev = newNode;
        this._nodeCount ++;    
        return newNode;
    },
    addBefore: function( node, value ){
        /// <summary>
        /// 在链表中指定的现有节点前面添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要在其前面插入包含value的新节点的节点</param>
        /// <param name="value" type="Object">要添加到链表的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this.addNodeBefore( node, new BadBug.DataStructures.LinkedListNode( value ) );
    },    
    addNodeFirst: function( node ){
        /// <summary>
        /// 在链表的开头处添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要添加在链表开头处的新节点</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        node.prev = null;
        if( this._firstNode == null )
        {   
            node.next = null;
            this._firstNode = this._lastNode = node;
        }
        else
        {
            node.next = this._firstNode;
            this._firstNode.prev = node;
            this._firstNode = node;
        }
        this._nodeCount ++;  
        return node;  
    },
    addFirst: function( value ){
        /// <summary>
        /// 在链表的开头处添加包含指定值的新节点
        /// </summary>
        /// <param name="value" type="Object">要在链表的开头处添加的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this.addNodeFirst( new BadBug.DataStructures.LinkedListNode( value ) );
    },
    addNodeLast: function( node ){
        /// <summary>
        /// 在链表的末尾处添加指定的新节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要添加在链表末尾处的新节点</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        node.next = null;
        if( this._lastNode == null )
        {   
            node.prev = null;
            this._lastNode = this._firstNode = node;
        }
        else
        {
            node.prev = this._lastNode;
            this._lastNode.next = node;
            this._lastNode = node;
        }
        this._nodeCount ++;    
        return node;
    },
    addLast: function( value ){
        /// <summary>
        /// 在链表的末尾处添加包含指定值的新节点
        /// </summary>
        /// <param name="value" type="Object">要在链表的末尾处添加的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        return this.addNodeLast( new BadBug.DataStructures.LinkedListNode( value ) );
    },
    clear: function(){
        /// <summary>
        /// 在链表中移除所有节点
        /// </summary>
        this._nodeCount = 0;
        var node = this._firstNode;
        this._firstNode = this._lastNode = null;
        var _t;
        while( node != null )
        {
            _t = node.next;
            node.prev = null;
            node.next = null;
            node = _t;
        }    
    },
    contains: function( value ){
        /// <summary>
        /// 确定某值是否在链表中
        /// </summary>
        /// <param name="value" type="Object">要在链表中定位的值</param>
        /// <returns type="Boolean"></returns>
        var node = this._firstNode;
        while( node != null )
        {
            if( node.value == value ) return true;
            node = node.next;
        }
        return false;
    },
    copyTo: function( destArray, index ){
        /// <summary>
        /// 从目标数组的指定索引处开始将整个链表的内容复制到兼容的一维数组。
        /// </summary>
        /// <param name="destArray" type="Array">作为从链表复制的元素的目标位置的一维数组</param>
        /// <param name="index" type="Number">数组中从零开始的索引，从此处开始复制</param>
        var node = this._firstNode;
        while( node != null )
        {
            destArray[ index ++ ] = node.value;
            node = node.next;
        }
    },
    find: function( value ){
        /// <summary>
        /// 查找包含指定值的第一个节点
        /// </summary>
        /// <param name="value" type="Object">要在链表中定位的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        var node = this._firstNode;
        while( node != null )
        {
            if( node.value == value ) return node;
            node = node.next;
        }
        return null;
    },
    findLast: function( value ){
        /// <summary>
        /// 查找包含指定值的最后一个节点
        /// </summary>
        /// <param name="value" type="Object">要在链表中定位的值</param>
        /// <returns type="BadBug.DataStructures.LinkedListNode"></returns>
        var node = this._lastNode;
        while( node != null )
        {
            if( node.value == value ) return node;
            node = node.prev;
        }
        return null;    
    },
    removeNode: function( node ){
        /// <summary>
        /// 从链表中移除指定的节点
        /// </summary>
        /// <param name="node" type="BadBug.DataStructures.LinkedListNode">要从链表中移除的节点</param>
        if( node.prev != null )
        {
            node.prev.next = node.next;
        }
        if( node.next != null )
        {
            node.next.prev = node.prev;
        }
        if( this._firstNode == node )
        {
            this._firstNode = node.next;
        }
        if( this._lastNode == node )
        {
            this._lastNode = node.prev;
        }
        node.prev = null;
        node.next = null;
        this._nodeCount --;
    },
    remove: function( value ){
        /// <summary>
        /// 从链表中移除指定值的第一个匹配项
        /// </summary>
        /// <param name="value" type="Object">要从链表中移除的值</param>
        /// <returns type="Boolean"></returns>
        var node = this.find( value );
        if( node != null ) this.removeNode( node );
        return node != null;
    },
    removeFirst: function(){
        /// <summary>
        /// 移除位于链表开头处的节点
        /// </summary>
        if( this._firstNode != null ) this.removeNode( this._firstNode );
    },
    removeLast: function(){
        /// <summary>
        /// 移除位于链表末尾处的节点
        /// </summary>
        if( this._lastNode != null ) this.removeNode( this._lastNode );    
    }
};

BadBug.DataStructures.LinkedList.registerClass( "BadBug.DataStructures.LinkedList", Sys.Component );


$getXmlNodeValue = function( node ){
    /// <summary>
    /// 获取Xml节点的值
    /// </summary>
    /// <param name="node" type="Object">Xml节点</param>
    /// <returns type="String"></returns>
    if( Sys.Browser.agent == Sys.Browser.Firefox ) return node.textContent;
    return node.text;
};

if( Sys.Browser.agent == Sys.Browser.Firefox )
{
        Element.prototype.swapNode = function( node ){
            var nextSibling = this.nextSibling;
            var parentNode = this.parentNode;
            node.parentNode.replaceChild( this, node );
            parentNode.insertBefore( node, nextSibling );
        }
                
        if( document.implementation.hasFeature( "XPath", "3.0" ) )
        {
            if( typeof XMLDocument != "undefined" )
            {
                XMLDocument.prototype.selectNodes = function( xPath, xNode, userNSResolver ){
                    if( !xNode ) { xNode = this; } 
                    var oNSResolver = this.createNSResolver( this.documentElement );
                    var aItems = this.evaluate( xPath, xNode, function( prefix ){
                        var r = oNSResolver.lookupNamespaceURI( prefix );
                        if( r == null )
                        {
                            if( typeof userNSResolver == "function" )
                            {
                                try
                                {
                                    r = userNSResolver( prefix );
                                }
                                catch( ex )
                                {
                                    r = null;
                                }
                            }
                        }                    
                        return r;
                    }, 
                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
                    var aResult = [];
                    for( var i = 0; i < aItems.snapshotLength; i++)
                    {
                        aResult[i] = aItems.snapshotItem( i );
                    }
                    return aResult;
                };
                XMLDocument.prototype.selectSingleNode = function( xPath, xNode, userNSResolver )
                {
                    if( !xNode ) { xNode = this; } 
                    var xItems = this.selectNodes( xPath, xNode, userNSResolver );
                    if( xItems.length > 0 )
                    {
                        return xItems[0];
                    }
                    else
                    {
                        return null;
                    }
                };
                HTMLDocument.prototype.selectNodes = XMLDocument.prototype.selectNodes;
                HTMLDocument.prototype.selectSingleNode = XMLDocument.prototype.selectSingleNode;
            }
            if( typeof Document != "undefined" )
            {
                Document.prototype.selectNodes = function( xPath, xNode, userNSResolver ){
                    if( !xNode ) { xNode = this; } 
                    var oNSResolver = this.createNSResolver( this.documentElement );
                    var aItems = this.evaluate( xPath, xNode, function( prefix ){
                        var r = oNSResolver.lookupNamespaceURI( prefix );
                        if( r == null )
                        {
                            if( typeof userNSResolver == "function" )
                            {
                                try
                                {
                                    r = userNSResolver( prefix );
                                }
                                catch( ex )
                                {
                                    r = null;
                                }
                            }
                        }                    
                        return r;
                    }, 
                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
                    var aResult = [];
                    for( var i = 0; i < aItems.snapshotLength; i++)
                    {
                        aResult[i] = aItems.snapshotItem( i );
                    }
                    return aResult;
                };
                Document.prototype.selectSingleNode = function( xPath, xNode, userNSResolver )
                {
                    if( !xNode ) { xNode = this; } 
                    var xItems = this.selectNodes( xPath, xNode, userNSResolver );
                    if( xItems.length > 0 )
                    {
                        return xItems[0];
                    }
                    else
                    {
                        return null;
                    }
                };
                HTMLDocument.prototype.selectNodes = Document.prototype.selectNodes;
                HTMLDocument.prototype.selectSingleNode = Document.prototype.selectSingleNode;
            }            
        
            Element.prototype.selectNodes = function( xPath, userNSResolver ){
                if( this.ownerDocument.selectNodes )
                {
                    return this.ownerDocument.selectNodes( xPath, this, userNSResolver );
                }
                else
                { 
                    throw "For XML Elements Only";
                }
            };

            Element.prototype.selectSingleNode = function( xPath, userNSResolver ){ 
                if(this.ownerDocument.selectSingleNode)
                {
                    return this.ownerDocument.selectSingleNode( xPath, this, userNSResolver );
                }
                else
                {
                    throw "For XML Elements Only";
                }
            };
            
            
        }
}


if ( typeof(Sys) !== "undefined" ) Sys.Application.notifyScriptLoaded();
