(function($){
    if(window.chrome || ($.browser.safari && /(chrome)[ \/]([\w.]+)/.test(navigator.userAgent.toLowerCase()))) {
        delete $.browser.safari;
        $.browser.chrome = true;
    }
    
    $.effectMisc = function(key, val) {
        var misc = $.parseJSON($.cookie('misc')) || {};
        !!val && (misc[key] = val);
        var retVal = misc[key];
        val === null && delete misc[key];
        $.cookie('misc', $.toJSON(misc), { path: '/', expires: 31536000 });
        return retVal;
    };
    
    $.winScrollTo = function(pos, duration, easing) {
        duration = duration || 1000;
        easing = easing || 'swing';
        
        if (!$.easing[easing]) {
            $.easing[easing] = function (x, t, b, c, d) {
                return c*((t=t/d-1)*t*t*t*t + 1) + b;
            };
        }
        
        var startTime = $.now();
        var endTime = startTime + duration;
        var timerId = null;
        var start = +$('body').scrollTop();
        var distance = pos - start;
        var radix;
        
        var step = function() {
            var now = $.now();
            if (now > endTime) { clearInterval(timerId); }
            
            var n = now - startTime;
            var s = n / duration;
            var radix = $.easing[easing](s, n, 0, 1, duration);
            var nowPosition = start + distance * radix;
            $('body').scrollTop(nowPosition)
        };
        
        timerId = setInterval( step, 13 );
    };
    
    $.fn.scroller = function(option) {
        option = $.extend({ height: this.height(),
            stopOver: 2000,
            speed: 1500,
            direction: 'up' }, option || {});
        
        var subject = this.children('div');
        var length = subject.length;
        var subHeight = subject.height();
        
        subject.css({ 'position': 'absolute', 'top': function(index, value) {
            return index * subHeight;
        }});
        this.height(option.height).css({ 'position': 'relative', 'overflow': 'hidden' });
        
        var scroll = function() {
            var executed = false;
            if (option.direction === 'up') {
                subject.animate({ 'top': '-=' + subHeight + 'px' }, option.speed, function() {
                    if (parseInt($(this).css('top')) < 0) {
                        $(this).css({ 'top': (length - 1) * subHeight })
                    }
                });
            } else {
                subject.animate({ 'marginTop': '+=' + subHeight + 'px' }, option.speed, function() {
                    subject.first().after(subject.last());
                    subject.css({ 'marginTop': 0 });
                });
            }
        };
        
        setInterval(scroll, option.speed + option.stopOver);
    };
    
    $.fn.colorPulsate = function() {
        $(this).stop(true);
        var color = ['#E33333', '#E88888'];
        for (var i = 0; i < 7; i++) {
            $(this).animate({ 'backgroundColor': color[i % 2] }, 150);
        }
        $(this).animate({ 'backgroundColor': 'white' }, 600);
    };

    var getRGB = function(color) {
        var result;

        if ( color && color.constructor == Array && color.length == 3 ) { return color; }

        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) { 
            return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
        }

        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) {
            return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
        }
        
        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) {
            return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
        }
        
        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) {
            return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
        }

        return colors[jQuery.trim(color).toLowerCase()];
    }
    
    var getColor = function(elem, attr) {
        var color;
        do {
            color = jQuery.curCSS(elem, attr);
            if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") ) { break; } 
            attr = "backgroundColor";
        } while ( elem = elem.parentNode );
        return getRGB(color);
    };
    
    var aboutColorAttrs = ['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'];
    $.each(aboutColorAttrs, function(i,attr){
        $.fx.step[attr] = function(fx){
            if ( fx.state == 0 ) {
                fx.start = getColor( fx.elem, attr );
                fx.end = getRGB( fx.end );
            }

            fx.elem.style[attr] = "rgb(" + [
                Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
                Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
                Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
            ].join(",") + ")";
        }
    });

    var colors = {
        aqua:[0,255,255],
        azure:[240,255,255],
        beige:[245,245,220],
        black:[0,0,0],
        blue:[0,0,255],
        brown:[165,42,42],
        cyan:[0,255,255],
        darkblue:[0,0,139],
        darkcyan:[0,139,139],
        darkgrey:[169,169,169],
        darkgreen:[0,100,0],
        darkkhaki:[189,183,107],
        darkmagenta:[139,0,139],
        darkolivegreen:[85,107,47],
        darkorange:[255,140,0],
        darkorchid:[153,50,204],
        darkred:[139,0,0],
        darksalmon:[233,150,122],
        darkviolet:[148,0,211],
        fuchsia:[255,0,255],
        gold:[255,215,0],
        green:[0,128,0],
        indigo:[75,0,130],
        khaki:[240,230,140],
        lightblue:[173,216,230],
        lightcyan:[224,255,255],
        lightgreen:[144,238,144],
        lightgrey:[211,211,211],
        lightpink:[255,182,193],
        lightyellow:[255,255,224],
        lime:[0,255,0],
        magenta:[255,0,255],
        maroon:[128,0,0],
        navy:[0,0,128],
        olive:[128,128,0],
        orange:[255,165,0],
        pink:[255,192,203],
        purple:[128,0,128],
        violet:[128,0,128],
        red:[255,0,0],
        silver:[192,192,192],
        white:[255,255,255],
        yellow:[255,255,0]
    };
    
    $.disdainIE = function (version) {
        version = version || 10;
        if (!$.browser.msie || $.browser.version > version) { return; }
        var delayTime = 6000;
        
        $('body').delay(500).animate({ 'marginTop': 26 }, 700).delay(delayTime).animate({ 'marginTop': 0 }, 700);
        var disdainer = $('<div>', { 'id': 'ieDisdainer' }).css({
                                                    'position': $.browser.version == 6 && 'absolute' || 'fixed',
                                                    'zIndex': 9999999,
                                                    'left': 0,
                                                    'top': 0,
                                                    '_position': 'absolute', 
                                                    '_top': 'expression(eval(document.documentElement.scrollTop))',
                                                    'width': '100%',
                                                    'height': '24',
                                                    'marginTop': -30,
                                                    'background': 'rgb(254, 239, 218) none repeat scroll 0% 0%',
                                                    'borderBottom': '1px solid rgb(247, 148, 29)'
                                                }).appendTo('body');
        disdainer.delay(500).animate({ 'marginTop': 0 }, 700).delay(delayTime).animate({ 'marginTop': -30 }, 700, function() { $(this).remove(); });
        
        $('<img>').css({ 'position': 'relative', 'float': 'right', 'left': -4, 'top': 4, 'cursor': 'pointer' })
                  .attr('src', '/scenes/default/images/ie6nomore-cornerx.jpg').click(function() {
                      $('body').stop(true).animate({ 'marginTop': 0 }, 700);
                      disdainer.stop(true).animate({ 'marginTop': -26 }, 700, function() { $(this).remove(); });
                  }).appendTo(disdainer);
                  
        var content = $('<div>').css({ 'position': 'relative', 'height': 25 }).appendTo(disdainer);
        $('<img>').css({ 'margin': '4px 0px 0px 4px', 'verticalAlign': 'top' }).attr('src', '/scenes/default/images/admin/!.gif').appendTo(content);
        $('<span>').css({ 'fontSize': 12, 'margin': '0px 5px', 'verticalAlign': $.browser.version == 6 && 'middle' || 'text-top' })
                   .text('还要继续用落后的ＩＥ浏览器？强烈推荐非ＩＥ核心浏览器，').appendTo(content);
        $('<a>', { 'href': 'http://www.google.cn/chrome', 'target': '_blank' }).css({ 'textDecoration': 'none' })
            .append($('<font>').css({ 'fontSize': '12px' }).append('谷歌浏览器：')).append(function() {
            return $('<img>').css({ 'margin': '2px 4px', 'width': 20, 'height': 20 }).attr('src', '/scenes/default/images/chrome.gif');
        }).appendTo(content);
        $('<a>', { 'href': 'http://download.firefox.com.cn/releases/webins3.0/official/zh-CN/Firefox-latest.exe', 'target': '_blank' }).css({ 'textDecoration': 'none' })
            .append($('<font>').css({ 'fontSize': '12px' }).append('、火狐浏览器：')).append(function() {
            return $('<img>').css({ 'margin': '2px 4px', 'width': 20, 'height': 20 }).attr('src', '/scenes/default/images/firefox.gif');
        }).appendTo(content);
        $('<a>', { 'href': 'http://windows.microsoft.com/zh-CN/internet-explorer/downloads/ie-8', 'target': '_blank' }).css({ 'textDecoration': 'none' })
            .append($('<font>').css({ 'fontSize': '12px' }).append('，或者升级到ＩＥ８：')).append(function() {
            return $('<img>').css({ 'margin': '2px 4px', 'width': 20, 'height': 20 }).attr('src', '/scenes/default/images/ie8.gif');
        }).appendTo(content);
        $('<span>').css({ 'fontSize': 12, 'margin': '0px 5px', 'verticalAlign': $.browser.version == 6 && 'middle' || 'text-top' })
                   .text('，点击下载').appendTo(content);
    }
    
    $.fn.number = function(opt) {
        var $el = $(this);
        if (!$el.is(':text')) { return; }
        
        opt = $.extend({ money: false, defaultZero: false }, opt || {});
        
        if (opt.defaultZero && !$el.val()) {
            $el.val(opt.money && '0.0' || 0);
        }
        var regMatch = null;
        var regReplace = null;
        
        if (opt.money) {
            regMatch = /^\d*(.\d+)?$/;
            regReplace = /[^\d.]/g;
        } else {
            regMatch = /^\d*$/;
            regReplace = /\D/g;
        }
        
        $el.keypress(function() {
            return event.keyCode >= 48 && event.keyCode <= 57 || ( opt.money && event.keyCode === 46 );
        }).keyup(function() {
            var $el = $(this);
            if(!regMatch.test($el.val())) {
                $el.val(function(index, value) {
                    value = value.replace(regReplace, '');
                    
                    while (value.indexOf('.') != value.lastIndexOf('.')) {
                        value = value.substring(0, value.lastIndexOf('.'));
                    }
                    
                    return value;
                });
            }
        }).blur(function() {
            var $el = $(this);
                $el.val(function(index, value) {
                    value = new Number(value);
                    if (isNaN(value)) { return ''; }
                    value = value.toString();
                    while (!value) {
                        value = value.substring(0, value.lastIndexOf('.'));
                        value = new Number(value).toString();
                    }
                    if (opt.money && value.indexOf('.') < 0) {
                        value = (+value).toFixed(1);
                    }
                    return value;
                });
            if(opt.defaultZero && !$el.val()) {
                $el.val(opt.money && '0.0' || 0);
            }
        }).css('imeMode', 'disabled');
    };
    
    $.newDate = function(data) {
        try {
            var now = new Date();
            data = $.extend({
                        year: now.getYear() + 1900, 
                        month: now.getMonth() + 1, 
                        date: now.getDate(), 
                        hours: now.getHours(), 
                        minutes: now.getMinutes(), 
                        seconds: now.getSeconds()
                    }, data);
            return new Date(data.year, data.month - 1, data.date, data.hours, data.minutes, data.seconds);
        } catch(e) {
            return null;
        }
    };
    
    $.dateFormat = function(data, format) {
        if (data instanceof Date) {
            data = {
                        year: data.getYear() + 1900, 
                        month: data.getMonth(), 
                        date: data.getDate(), 
                        hours: data.getHours(), 
                        minutes: data.getMinutes(), 
                        seconds: data.getSeconds()
                   };
        }
        if (data.year < 1900) {
        	data.year = data.year + 1900;
        }
        format = format.replace(/yyyy/g, data.year);
        format = format.replace(/yy/g, data.year.toString().substr(2, 2));
        format = format.replace(/MM/g, (+data.month < 9 ? '0': '') + (data.month + 1));
        format = format.replace(/dd/g, (+data.date < 10 ? '0': '') + data.date);
        format = format.replace(/hh/g, (+data.hours < 10 ? '0': '') + data.hours);
        format = format.replace(/mm/g, (+data.minutes < 10 ? '0': '') + data.minutes);
        format = format.replace(/ss/g, (+data.seconds < 10 ? '0': '') + data.seconds);
        return format;
    };
    
    $.pageRender = function(renderer) {
        var defaultRenderer = (function() {
            return {
                // 创建所有分页链接
                createLinks: function(options) {
                    var temporary = $('<ul>');
                    // 首页
                    if (options.showEdge) {
                        var firstPage = this.makeSlice(1, options.curPageNum, options.pageCount, { text: options.firstText });
                        !options.showPrevAlways && options.curPageNum === 1 && firstPage.hide();
                        temporary.append(firstPage.data('mark', 'first'));
                    }
                    
                    // 上一页
                    var prevPage = this.makeSlice(options.curPageNum - 1, options.curPageNum, options.pageCount, { text: options.prevText });
                    !options.showPrevAlways && (options.curPageNum - 1) < 1 && prevPage.hide();
                    temporary.append(prevPage.data('mark', 'prev'));
                    
                    // 中间页---------begin
                    var scope = this.interval(options);
                    
                    for (var i = 1; i <= options.edgeSize; i++) {
                        if (i > options.pageCount) { break; }
                        temporary.append(this.makeSlice(i, options.curPageNum, options.pageCount));
                    }
                    
                    scope.start > options.edgeSize + 1 && temporary.append($('<li>').addClass('page omission').text(options.omissionText));
                    
                    for (var i = scope.start; i <= scope.end; i++) {
                        if (i <= options.edgeSize) { continue; }
                        temporary.append(this.makeSlice(i, options.curPageNum, options.pageCount));
                    }
                    
                    scope.end < options.pageCount - options.edgeSize && temporary.append($('<li>').addClass('page omission').text(options.omissionText));
                    
                    for (var i = options.pageCount - options.edgeSize + 1; i <= options.pageCount; i++) {
                        if (i <= scope.end) { continue; }
                        temporary.append(this.makeSlice(i, options.curPageNum, options.pageCount));
                    }
                    // 中间页---------end
                    
                    // 下一页
                    var nextPage = this.makeSlice(options.curPageNum + 1, options.curPageNum, options.pageCount, { text: options.nextText });
                    !options.showNextAlways && (options.curPageNum + 1) > options.pageCount && nextPage.hide();
                    temporary.append(nextPage.data('mark', 'next'));
                    
                    // 尾页
                    if (options.showEdge) {
                        var lastPage = this.makeSlice(options.pageCount, options.curPageNum, options.pageCount, { text: options.lastText });
                        !options.showNextAlways && options.curPageNum === options.pageCount && lastPage.hide();
                        temporary.append(lastPage.data('mark', 'last'));
                    }
                    
                    return temporary.children();
                }, 
                
                // 计算主显示范围开始与结束位置
                interval: function(options) {
                    var half = Math.floor(options.mainPartSize / 2);
                    var start = Math.max(Math.min(options.curPageNum - half, options.pageCount - options.mainPartSize + 1), 1);
                    var end = Math.min(Math.max(options.curPageNum + half, options.mainPartSize), options.pageCount);
                    return { start: start, end: end };
                },
                
                // 创建单个页面链接
                makeSlice: function(pageNum, curPageNum, pageCount, attributes) {
                    pageNum = pageNum || 1;
                    pageNum = (pageNum <= pageCount && pageNum) || pageCount;
                    attributes = attributes || {};
                    
                    var slice = $('<li>').text(pageNum).data('pageNum', pageNum);
                    $.each(attributes, function(key, value) {
                        (key == 'text' && slice.text(value)) ||
                        (key == 'html' && slice.html(value)) ||
                        (key == 'class' && slice.addClass(value)) ||
                        slice.attr(key, value);
                    });
                    
                    if (+pageNum === +curPageNum) {
                        slice.addClass('currentPage');
                    } else {
                        slice.addClass('page');
                    }
                    //slice.attr('id', pageNum);
                    return slice;
                }
            };
        })();
        
        return renderer === 'default' ? defaultRenderer : null;
    };
    
    $.pagination = {
        inited: false,
        // 加载数据
        loading: function(options) {
            if (options.url) {
                return this.ajaxLoading(options);
            } else if (options.data) {
                return this.dataLoading(options);
            }
        },
        
        // ajax方式加载
        ajaxLoading: function(options) {
            var exLoading = !!options.loadingPlace;
            var loadingPlace;
            exLoading && (loadingPlace = typeof options.loadingPlace === 'string' && $(options.loadingPlace) || options.loadingPlace);
            exLoading = typeof loadingPlace === 'object';
            
            var parameters = $.extend(options.parameters, {});
            parameters[options.pageSizeName] = options.pageSize;
            parameters[options.pageNumberName] = options.curPageNum;
            var __this = this;
            var callback = function(data) {
                if (data) {
                    var pager = data.pager && data.pager || data;
                    options.pageCount = pager[options.pageCountName] && pager[options.pageCountName] || options.pageCount;
                    options.recordCount = pager[options.recordCountName] && pager[options.recordCountName] || options.recordCount;
                    (!__this.inited || options.autoRefresh) && __this.initPagination(options);
                    options.callback(data);
                }
            };
            
            options.callBefore();
            exLoading && 
                !$.exPost(options.url, parameters, callback, 'json', loadingPlace) || 
                !$.post(options.url, parameters, callback, 'json');
        },
        
        // TODO 缓存方式加载
        dataLoading: function(options) {
            alert('data');
        },
        
        setupAction: function(links, options) {
            var __this = this;
            $.each(links, function(index, link) {
                var $link = $(link);
                if ($link.is('.omission')) {
                	return true;
                }
                if ((($link.data('mark') === 'first' || $link.data('mark') === 'prev') && options.curPageNum <= 1)
                    || (($link.data('mark') === 'last' || $link.data('mark') === 'next') && options.curPageNum >= options.pageCount)
                    || $link.data('pageNum') === options.curPageNum) {
                    return true;
                }
                $link.click(function() {
                    options.curPageNum = $(this).data('pageNum');
                    __this.loading(options);
                });
            });
        },
        
        // 初始化
        initPagination: function(options) {
            var pageRenderer = $.pageRender(options.renderer);
            if (!pageRenderer) { return; } // 如果根据指定的渲染器名称找不到对应的渲染器，终止
            
            options.pageSize = (!options.pageSize || options.pageSize < 0) ? 1 : options.pageSize;
            options.recordCount = options.recordCount || 0;
            options.pageCount = Math.ceil(options.recordCount / options.pageSize);
            options.curPageNum = (options.curPageNum > options.pageCount && options.pageCount) || options.curPageNum;
            options.curPageNum = (options.curPageNum < 1 && 1) || options.curPageNum;
            
            var $pagination = options.pagination;
            
            if (options.pageCount <= 1) {
                $pagination.hide();
                return;
            }
            
            $pagination.show();
            var links = pageRenderer.createLinks(options);
            this.setupAction(links, options);
            $pagination.empty().append(links);
            
            this.inited = true;
        }
    };
    
    $.fn.pagination = function(url, options) {
        options = !options && url || options;
        options = $.extend({
            url: '', // ajax路径也可在options中给出
            data: '', // 如不使用ajax取数据，则需提供存储其他分页数据的缓存id或对象
            pageSize: 10, // 每页数量
            recordCount: 0, // 记录总数，自动加载时会纠正记录总数
            mainPartSize: 7, // 当前页数左右主显示范围数量
            curPageNum: 1, // 当前页数
            pageCount: 0, // 总页数，设置无用
            edgeSize: 2, // 首页/尾页显示页数数量
            prevText: '前一页',
            nextText: '后一页',
            firstText: '首页',
            lastText: '尾页',
            omissionText: '...',
            pageSizeName: 'pageSize', // ajax参数pageSize的服务器参数名
            pageNumberName: 'pageNumber', // ajax参数pageNumber的服务器参数名
            pageCountName: 'pageCount', // ajax参数pageCount的服务器参数名
            recordCountName: 'recordCount', // ajax参数recordCount的服务器参数名
            renderer: 'default',
            showEdge: false,//首页,尾页是否显示
            showPrevAlways: true,
            showNextAlways: true,
            loadCurPage: true,
            loadingPlace: null,
            parameters: {},
            pagination: null,
            autoRefresh: true, // 自动刷新，在每次loading数据回来，重新计算分页参数
            callBefore: function() { // 请求前函数
                return;
            },
            callback: function(){ // 回调函数
                return false;
            }
        }, options || {});
        
        if (typeof url === 'object' && !options.data) { return; } // 如果没有指定ajax地址，并且没有指定数据缓存，终止
        if (!options.recordCount && !options.pageCount && !options.loadCurPage) { return; } // 如果不指定数据记录总数，并不加载当前页面，则无法获取记录总数，终止
        typeof url === 'string' && (options.url = url);
        options.pagination = $(this);
        options.pagination.addClass('pagination');
        
        if (options.loadCurPage) {
            $.pagination.loading(options);
        } else {
            $.pagination.initPagination(options);
        }
    };
    
    $.exPost = function(url, data, fn, type, pos) {
        var left, top;
        if (pos.size() > 0) {
            pos = $(pos);
            left = pos.offset().left + pos.width() / 2 - 80 + 'px';
            top = pos.offset().top + pos.height() / 2 - 12 + 'px';
        } else {
            left = '45%';
            top = '49%';
        }
        
        var loading = $('<img>', { src: '/scenes/default/images/loading.gif' })
                .css({ 
                    position: 'absolute',
                    zIndex: 1000,
                    left: left,
                    top: top })
                .appendTo('body');
        var fnProxy = function(data) {
            loading.remove();
            fn(data);
        }
        $.post(url, data, fnProxy, type);
    };
    
    $.enRijndael = function(original, key) {
        if(rijndaelEncrypt) {
            return rijndaelEncrypt(original, key);
        } else {
            return original;
        }
    };
    
    $.deRijndael = function(ciphertext, key) {
        if(rijndaelDecrypt) {
            var original = new String(rijndaelDecrypt(ciphertext, key));
            return original.toString();
        } else {
            return ciphertext;
        }
    };

    $.fn.sorted = function(customOptions) {
        var options = {
            reverse: false,
            by: function(a) { return a.attr('id'); }
        };

        $.extend(options, customOptions);

        arr = $(this).get();
        arr.sort(function(a, b) {
            var valA = options.by($(a));
            var valB = options.by($(b));
            if (options.reversed) {
                return (valA < valB) ? 1 : (valA > valB) ? -1 : 0;
            } else {
                return (valA < valB) ? -1 : (valA > valB) ? 1 : 0;
            }
        });
        return $(arr);
    };

    $.cookie = function(key, value, options) {
        // key and at least value given, set cookie...
        if(arguments.length > 1 && String(value) !== "[object Object]") {
            options = jQuery.extend({ }, options);

            if(value === null || value === undefined) {
                options.expires = -1;
            }

            if(typeof options.expires === 'number') {
                var days = options.expires, t = options.expires = new Date();
                t.setDate(t.getDate() + days);
            }

            value = String(value);

            // 默认coooooooookie的domain
            !!!options.domain && (options.domain = '192.168.1.7');

            return (document.cookie = [
                encodeURIComponent(key), '=',
                options.raw ? value : encodeURIComponent(value),
                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
                options.path ? '; path=' + options.path : '',
                options.domain ? '; domain=' + options.domain : '',
                options.secure ? '; secure' : ''
            ].join(''));
        }

        // key and possibly options given, get cookie...
        options = value || { };
        var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
        return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
    };

    var _escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;

    var _meta = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\'
    };
    $.toJSON = function(o) {
        if (typeof(JSON) == 'object' && JSON.stringify) { return JSON.stringify(o); }

        var type = typeof(o);

        if (o === null) { return "null"; }

        if (type == "undefined") { return undefined; }
        if (type == "number" || type == "boolean") { return o + ""; }
        if (type == "string") { return $.quoteString(o); }
        if (type == 'object') {
            if (typeof o.toJSON == "function") { return $.toJSON( o.toJSON() ); }

            if (o.constructor === Date) {
                var month = o.getUTCMonth() + 1;
                if (month < 10) { month = '0' + month; }

                var day = o.getUTCDate();
                if (day < 10) { day = '0' + day; }

                var year = o.getUTCFullYear();

                var hours = o.getUTCHours();
                if (hours < 10) { hours = '0' + hours; }

                var minutes = o.getUTCMinutes();
                if (minutes < 10) { minutes = '0' + minutes; }

                var seconds = o.getUTCSeconds();
                if (seconds < 10) { seconds = '0' + seconds; }

                var milli = o.getUTCMilliseconds();
                if (milli < 100) { milli = '0' + milli; }
                if (milli < 10) { milli = '0' + milli; }

                return '"' + year + '-' + month + '-' + day + 'T' +
                             hours + ':' + minutes + ':' + seconds +
                             '.' + milli + 'Z"';
            }

            if (o.constructor === Array) {
                var ret = [];
                for (var i = 0; i < o.length; i++) {
                    ret.push( $.toJSON(o[i]) || "null" );
                }
                return "[" + ret.join(",") + "]";
            }

            var pairs = [];
            for (var k in o) {
                var name;
                var type = typeof k;

                if (type == "number") {
                    name = '"' + k + '"';
                } else if (type == "string") {
                    name = $.quoteString(k);
                } else {
                    continue;  //skip non-string or number keys
                }
                if (typeof o[k] == "function") {
                    continue;  //skip pairs where the value is a function.
                }
                var val = $.toJSON(o[k]);

                pairs.push(name + ":" + val);
            }

            return "{" + pairs.join(", ") + "}";
        }
    };

    $.evalJSON = function(src) {
        if (typeof(JSON) == 'object' && JSON.parse) { return JSON.parse(src); }
        return eval("(" + src + ")");
    };

    $.secureEvalJSON = function(src) {
        if (typeof(JSON) == 'object' && JSON.parse) { return JSON.parse(src); }

        var filtered = src;
        filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
        filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
        filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');

        if (/^[\],:{}\s]*$/.test(filtered)) {
            return eval("(" + src + ")");
        } else {
            throw new SyntaxError("Error parsing JSON, source is not valid.");
        }
    };

    $.quoteString = function(string) {
        if (string.match(_escapeable)) {
            return '"' + string.replace(_escapeable, function (a) {
                var c = _meta[a];
                if (typeof c === 'string') { return c; }
                c = a.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            }) + '"';
        }
        return '"' + string + '"';
    };

    $.fn.overlay = function(toggle, zIndex, fn) {
        toggle = !!toggle;
        if(typeof zIndex === 'function') {
            fn = zIndex;
            zIndex = 999;
        }
        
        if (this && +this.css('zIndex') > zIndex) {
            zIndex = +this.css('zIndex') + 1;
        }
        
        if(!$('#overlay-jq').length) {
            $('<div>', { id: 'overlay-jq' }).css({
                position: 'absolute',
                left: '0px',
                top: '0px',
                width: '100%',
                display: 'none',
                zIndex: (zIndex || 999),
                backgroundColor: 'black',
                opacity: .5
            }).appendTo('body');
        }
        $('#overlay-jq').css('height', $(document).height()).toggle(toggle).click(function() { if(!!fn) { fn(); } });
        return this;
    };

    $.fn.center = function(option) {
        var options = {
            h: true,
            v: true,
            offset: {
                left: 0,
                top: 0
            },
            width: 0,
            height: 0
        };
        option = $.extend(true, options, option);

        return this.each(function() {
            var $el = $(this);

            var width = option.width || $el.width(),
                height = option.height || $el.height(),
                paddingTop = parseInt($el.css("paddingTop")),
                paddingBottom = parseInt($el.css("paddingBottom")),
                borderTop = parseInt($el.css("borderTopWidth")),
                borderBottom = parseInt($el.css("borderBottomWidth"));
            var mediaBorder = (borderTop + borderBottom) / 2;
                mediaPadding = (paddingTop + paddingBottom) / 2;
                positionType = $el.parent().css("position");
            var halfWidth = width / 2 * -1 + option.offset.left;
                halfHeight = height / 2 * -1 - mediaPadding - (mediaBorder || 0) + option.offset.top;
            /*var halfWidth = (document.documentElement.clientWidth - width) / 2 + document.documentElement.scrollLeft;
                halfHeight = (document.documentElement.clientHeight - height) / 2 + document.documentElement.scrollTop;*/

            var cssProp = {};
            if($.browser.msie && parseInt($.browser.version) < 7) {
                cssProp.position = 'absolute';
            } else {
                cssProp.position = 'fixed';
            }
            if(option.v){
                if($.browser.msie && parseInt($.browser.version) < 7) {
                    cssProp.top = $(window).height() / 2 + $(window).scrollTop() + halfHeight;
                } else {
                    cssProp.top = '50%';
                    cssProp.marginTop = halfHeight;
                }
            }
            if(option.h){
                if($.browser.msie && parseInt($.browser.version) < 7) {
                    cssProp.left = $('body').width() / 2 + halfWidth;
                } else {
                    cssProp.left = '50%';
                    cssProp.marginLeft = halfWidth;
                }
            }
            $el.css(cssProp);
        });
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*  url query  *↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*/
    
    var tag2attr = {
        a: 'href',
        img: 'src',
        form: 'action',
        base: 'href',
        script: 'src',
        iframe: 'src',
        link: 'href'
    }, key = ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "fragment"], // keys available to query
     aliases = {
        "anchor": "fragment"
    }, // aliases for backwards compatability
     parser = {
        strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs
        loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
    }, querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs
     fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs
    function parseUri(url, strictMode) {
        var str = decodeURI(url), res = parser[strictMode || false ? "strict" : "loose"].exec(str), uri = {
            attr: {},
            param: {},
            seg: {}
        }, i = 14;
        
        while (i--) {
            uri.attr[key[i]] = res[i] || "";
        }
        
        // build query and fragment parameters
        
        uri.param['query'] = {};
        uri.param['fragment'] = {};
        
        uri.attr['query'].replace(querystring_parser, function($0, $1, $2) {
            if ($1) {
                uri.param['query'][$1] = $2;
            }
        });
        
        uri.attr['fragment'].replace(fragment_parser, function($0, $1, $2) {
            if ($1) {
                uri.param['fragment'][$1] = $2;
            }
        });
        
        // split path and fragement into segments
        
        uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g, '').split('/');
        
        uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g, '').split('/');
        
        // compile a 'base' domain attribute
        
        uri.attr['base'] = uri.attr.host ? uri.attr.protocol + "://" + uri.attr.host + (uri.attr.port ? ":" + uri.attr.port : '') : '';
        
        return uri;
    };
    
    function getAttrName(elm) {
        var tn = elm.tagName;
        if (tn !== undefined) 
            return tag2attr[tn.toLowerCase()];
        return tn;
    }
    
    $.fn.url = function(strictMode) {
        var url = '';
        
        if (this.length) {
            url = $(this).attr(getAttrName(this[0])) || '';
        }
        
        return $.url(url, strictMode);
    };
    
    $.url = function(url, strictMode) {
        if (arguments.length === 1 && url === true) {
            strictMode = true;
            url = undefined;
        }
        
        strictMode = strictMode || false;
        url = url || window.location.toString();
        
        return {
        
            data: parseUri(url, strictMode),
            
            // get various attributes from the URI
            attr: function(attr) {
                attr = aliases[attr] || attr;
                return attr !== undefined ? this.data.attr[attr] : this.data.attr;
            },
            
            // return query string parameters
            param: function(param) {
                return param !== undefined ? this.data.param.query[param] : this.data.param.query;
            },
            
            // return fragment parameters
            fparam: function(param) {
                return param !== undefined ? this.data.param.fragment[param] : this.data.param.fragment;
            },
            
            // return path segments
            segment: function(seg) {
                if (seg === undefined) {
                    return this.data.seg.path;
                } else {
                    seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.path[seg];
                }
            },
            
            // return fragment segments
            fsegment: function(seg) {
                if (seg === undefined) {
                    return this.data.seg.fragment;
                } else {
                    seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.fragment[seg];
                }
            }
            
        };
        
    };
    
    
    
    
    
    
    
    
    
    
    
    /*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*  md5 *↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*↓*/
    var rotateLeft = function(lValue, iShiftBits) {
        return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
    }
    
    var addUnsigned = function(lX, lY) {
        var lX4, lY4, lX8, lY8, lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
        if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        if (lX4 | lY4) {
            if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }
    
    var F = function(x, y, z) {
        return (x & y) | ((~ x) & z);
    }
    
    var G = function(x, y, z) {
        return (x & z) | (y & (~ z));
    }
    
    var H = function(x, y, z) {
        return (x ^ y ^ z);
    }
    
    var I = function(x, y, z) {
        return (y ^ (x | (~ z)));
    }
    
    var FF = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    
    var GG = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    
    var HH = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    
    var II = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    
    var convertToWordArray = function(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWordsTempOne = lMessageLength + 8;
        var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
        var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
        var lWordArray = Array(lNumberOfWords - 1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while (lByteCount < lMessageLength) {
            lWordCount = (lByteCount - (lByteCount % 4)) / 4;
            lBytePosition = (lByteCount % 4) * 8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount - (lByteCount % 4)) / 4;
        lBytePosition = (lByteCount % 4) * 8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
        lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
        lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
        return lWordArray;
    };
    
    var wordToHex = function(lValue) {
        var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
        for (lCount = 0; lCount <= 3; lCount++) {
            lByte = (lValue >>> (lCount * 8)) & 255;
            WordToHexValueTemp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
        }
        return WordToHexValue;
    };
    
    var uTF8Encode = function(string) {
        string = string.replace(/\x0d\x0a/g, "\x0a");
        var output = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                output += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                output += String.fromCharCode((c >> 6) | 192);
                output += String.fromCharCode((c & 63) | 128);
            } else {
                output += String.fromCharCode((c >> 12) | 224);
                output += String.fromCharCode(((c >> 6) & 63) | 128);
                output += String.fromCharCode((c & 63) | 128);
            }
        }
        return output;
    };
    
    $.extend({
        md5: function(string) {
            var x = Array();
            var k, AA, BB, CC, DD, a, b, c, d;
            var S11=7, S12=12, S13=17, S14=22;
            var S21=5, S22=9 , S23=14, S24=20;
            var S31=4, S32=11, S33=16, S34=23;
            var S41=6, S42=10, S43=15, S44=21;
            string = uTF8Encode(string);
            x = convertToWordArray(string);
            a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
            for (k = 0; k < x.length; k += 16) {
                AA = a; BB = b; CC = c; DD = d;
                a = FF(a, b, c, d, x[k+0],  S11, 0xD76AA478);
                d = FF(d, a, b, c, x[k+1],  S12, 0xE8C7B756);
                c = FF(c, d, a, b, x[k+2],  S13, 0x242070DB);
                b = FF(b, c, d, a, x[k+3],  S14, 0xC1BDCEEE);
                a = FF(a, b, c, d, x[k+4],  S11, 0xF57C0FAF);
                d = FF(d, a, b, c, x[k+5],  S12, 0x4787C62A);
                c = FF(c, d, a, b, x[k+6],  S13, 0xA8304613);
                b = FF(b, c, d, a, x[k+7],  S14, 0xFD469501);
                a = FF(a, b, c, d, x[k+8],  S11, 0x698098D8);
                d = FF(d, a, b, c, x[k+9],  S12, 0x8B44F7AF);
                c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1);
                b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE);
                a = FF(a, b, c, d, x[k+12], S11, 0x6B901122);
                d = FF(d, a, b, c, x[k+13], S12, 0xFD987193);
                c = FF(c, d, a, b, x[k+14], S13, 0xA679438E);
                b = FF(b, c, d, a, x[k+15], S14, 0x49B40821);
                a = GG(a, b, c, d, x[k+1],  S21, 0xF61E2562);
                d = GG(d, a, b, c, x[k+6],  S22, 0xC040B340);
                c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51);
                b = GG(b, c, d, a, x[k+0],  S24, 0xE9B6C7AA);
                a = GG(a, b, c, d, x[k+5],  S21, 0xD62F105D);
                d = GG(d, a, b, c, x[k+10], S22, 0x2441453);
                c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681);
                b = GG(b, c, d, a, x[k+4],  S24, 0xE7D3FBC8);
                a = GG(a, b, c, d, x[k+9],  S21, 0x21E1CDE6);
                d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6);
                c = GG(c, d, a, b, x[k+3],  S23, 0xF4D50D87);
                b = GG(b, c, d, a, x[k+8],  S24, 0x455A14ED);
                a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905);
                d = GG(d, a, b, c, x[k+2],  S22, 0xFCEFA3F8);
                c = GG(c, d, a, b, x[k+7],  S23, 0x676F02D9);
                b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A);
                a = HH(a, b, c, d, x[k+5],  S31, 0xFFFA3942);
                d = HH(d, a, b, c, x[k+8],  S32, 0x8771F681);
                c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122);
                b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C);
                a = HH(a, b, c, d, x[k+1],  S31, 0xA4BEEA44);
                d = HH(d, a, b, c, x[k+4],  S32, 0x4BDECFA9);
                c = HH(c, d, a, b, x[k+7],  S33, 0xF6BB4B60);
                b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70);
                a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6);
                d = HH(d, a, b, c, x[k+0],  S32, 0xEAA127FA);
                c = HH(c, d, a, b, x[k+3],  S33, 0xD4EF3085);
                b = HH(b, c, d, a, x[k+6],  S34, 0x4881D05);
                a = HH(a, b, c, d, x[k+9],  S31, 0xD9D4D039);
                d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5);
                c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8);
                b = HH(b, c, d, a, x[k+2],  S34, 0xC4AC5665);
                a = II(a, b, c, d, x[k+0],  S41, 0xF4292244);
                d = II(d, a, b, c, x[k+7],  S42, 0x432AFF97);
                c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7);
                b = II(b, c, d, a, x[k+5],  S44, 0xFC93A039);
                a = II(a, b, c, d, x[k+12], S41, 0x655B59C3);
                d = II(d, a, b, c, x[k+3],  S42, 0x8F0CCC92);
                c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D);
                b = II(b, c, d, a, x[k+1],  S44, 0x85845DD1);
                a = II(a, b, c, d, x[k+8],  S41, 0x6FA87E4F);
                d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0);
                c = II(c, d, a, b, x[k+6],  S43, 0xA3014314);
                b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1);
                a = II(a, b, c, d, x[k+4],  S41, 0xF7537E82);
                d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235);
                c = II(c, d, a, b, x[k+2],  S43, 0x2AD7D2BB);
                b = II(b, c, d, a, x[k+9],  S44, 0xEB86D391);
                a = addUnsigned(a, AA);
                b = addUnsigned(b, BB);
                c = addUnsigned(c, CC);
                d = addUnsigned(d, DD);
            }
            var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
            return tempValue.toLowerCase();
        }
    });

})(jQuery);
