/**
 * MarcArea
 * A Kemar joint - 2011-07-07
 */

(function(){

    $(document).ready(function(){

        $('#drag-home').sliderHome();

        $('#quote').quotify(quotes);

        $('.ertl').unobfuscate();

        $('#folio-container').folio();

        $('pre, code').addClass('prettyprint');
        prettyPrint();

        $('#top').hide();// displayed on window.onload when necessary

        $('a.external').attr('target', '_blank');

        $('#q').suggest();

        $('#t').tweetSuggest();

    });

    $(window).load(function(){

        $('#top-link').bind('click', function(e) {
            e.preventDefault();
            $('html,body').animate({scrollTop:0}, 'slow', function(){
                $('a:first').focus();
            });
        });
        if ( document.documentElement.scrollHeight > document.documentElement.clientHeight ) {
            $('#top').show();
        };

        if ( $('#comment-preview').length ) {
            $('html,body').animate( {scrollTop: $('#comment-preview').offset().top }, 'slow' );
        };

        $('#comment-correct').bind('click', function(e) {
            e.preventDefault();
            $('html,body').animate( {scrollTop: $('#comment-form').offset().top }, 'slow' );
        });

        if ( $('#comment-status').length ) {
            $('html,body').animate( {scrollTop: $('#comment-status').offset().top }, 'slow' );
        };

        if ( $('#comment-form .error').length ) {
            $('html,body').animate( {scrollTop: $('#comment-form').offset().top }, 'slow' );
        };

    });

})();

jQuery.fn.unobfuscate = function() {

    var elements = this;

    if (elements.length) {
        elements.each(function(i) {
            var reversed = $(this).text().split('').reverse().join('');
            $(this).wrap('<a href="mailto:'+ reversed +'"></a>')
        });
    };

    return this;

};

jQuery.fn.sliderHome = function() {

    // ------------
    // Requirements
    // ------------
    // Dragdealer JS v0.9.5 - Ovidiu Chereches
    // http://code.ovidiu.ch/dragdealer
    // ------------

    var drag_container = $(this);

    if (drag_container.length && drag_container.css('display') != 'none') {

        var drag_handler = $('#drag-home-handler');
        var links = $('a[class^="slider-"]');
        var current_step = 1;
        var heights = [];
        var step_divs = $('div.step');

        drag_handler.show();// hidden via CSS - progressive enhancemen

        step_divs.each(function(){ heights.push($(this).height()); }).hide().first().show();
        var max_height = Math.max.apply(null, heights);
        step_divs.css({ 'min-height': max_height });

        var slideshow = new Dragdealer('drag-home',
        {
            steps: 6,
            speed: 35,
            animationCallback: function(x, y)
            {
                
                var new_step = undefined;
                
                if (x<0.1) {
                    new_step = 1;
                } else if (x>=0.1 && x<0.3) {
                    new_step = 2;
                } else if (x>=0.3 && x<0.5) {
                    new_step = 3;
                } else if (x>=0.5 && x<0.7) {
                    new_step = 4;
                } else if (x>=0.7 && x<0.9) {
                    new_step = 5;
                } else {
                    new_step = 6;
                };
                
                if (new_step != current_step) {
                    current_step = new_step;
                    links.removeClass('here');
                    $('a.slider-'+current_step).addClass('here');
                    step_divs.hide();
                    $('#step-'+current_step).show();
                };
                
            }
        });

        links.bind("click", function(e) {
            e.preventDefault();
            slideshow.setStep(this.className.match(/\d/g)[0]);
        });

    };

    return this;

};

jQuery.fn.folio = function() {

    var folio_container = $(this);

    if (folio_container.length) {

        var folio_box  = $('#folio');
        var images     = $('#folio img');
        var trigger    = $('#folio-container');
        var do_nothing = false;

        init();

        images
            .css('position','absolute')
            .addClass('none')
            .first()
                .removeClass('none');

        // Events
        trigger.bind('click', function(e) {
            e.preventDefault();
            if (e.pageX > $(document).width()/2) {
                doSwitch('next');
            } else {
                doSwitch('prev');
            };
        });
        $(window).bind('keyup', function(e) {
            if (e.keyCode == 39) {// RIGHT
                doSwitch('next');
            } else if (e.keyCode == 37) {// LEFT
                doSwitch('prev');
            };
        });
        $(window).bind('resize', function(e) {
            init();
        });

    };

    function init() {
        trigger
            .css('cursor','pointer');
        // 820 L = XXX H (400)
        // 480 L = 234 H
        // (820*234)/480 = new H (400)
        folio_box_height = Math.round((folio_box.width()*234)/480);
        folio_box
            .css('height', folio_box_height);
    };

    function doSwitch(switch_type) {
        if (do_nothing) {
            return;
        } else if (Modernizr.csstransforms3d) {
            switchImage3d(switch_type);
        } else {
            switchImage(switch_type);
        };
    };

    function switchImage(switch_type) {
        do_nothing = true;
        var outgoing = images.filter(':visible:first');
        if (switch_type == 'next') {
            var incoming = images.eq(outgoing.index()==images.length-1 ? 0 : outgoing.index()+1);
        } else if (switch_type == 'prev') {
            var incoming = images.eq(outgoing.index()-1);
        };
        incoming.css('z-index', 1).removeAttr('class');
        outgoing
            .css({
                'z-index': 10,
                'opacity': 1
            })
            .animate({'opacity':0}, 700, function(){
                $(this).attr('class', 'none').css('opacity', 1);
                do_nothing = false;
            });
    };

    function switchImage3d(switch_type) {
        do_nothing = true;
        folio_box.attr('class', 'initial');
        var outgoing_class = 'outgoing-' + switch_type;// switch_type == 'next' || 'prev'
        var incoming_class = 'incoming-' + switch_type;
        var outgoing = images.filter(':visible:first');
        if (switch_type == 'next') {
            var incoming = images.eq(outgoing.index()==images.length-1 ? 0 : outgoing.index()+1);
        } else if (switch_type == 'prev') {
            var incoming = images.eq(outgoing.index()-1);
        };
        outgoing
            .attr('class', outgoing_class)
            .attr('id', 'outgoing');
        incoming
            .attr('class', incoming_class)
            .attr('id', 'incoming')
            .bind('webkitTransitionEnd', switchImage3dCallback)
            .removeClass('none');
        window.setTimeout(function() { folio_box.attr('class', 'final'); }, 0);
    };

    function switchImage3dCallback() {
        folio_box.removeAttr('class');
        $('#outgoing')
            .attr('class', 'none')
            .removeAttr('id');
        $('#incoming')
            .removeAttr('class')
            .removeAttr('id');
        do_nothing = false;
    };

    return this;

};

jQuery.fn.quotify = function(quotes) {

    var container = this;

    if (container.length) {
        var quote_container = $('p',container);
        var author_container = $('cite span',container);
        author_container
            .prepend('<a id="quote-reload">New quote</a>');
        $('#quote-reload')
            .bind('click',function(e){
                e.preventDefault();
                newQuote( quotes[Math.floor(Math.random()*quotes.length)] );
            })
            .trigger('click');
    };

    function newQuote(quote) {
        quote_container.text('"' + quote.quote + '"');
        if (quote.url) {
            author_container.html('-- <a target="_blank" href="' + quote.url + '">' + quote.author + '</a>');
        } else {
            author_container.text('-- ' + quote.author);
        };
    };

    return this;

};

var quotes = [
        {
            "quote": "If you are not paying for it, you're not the customer; you're the product being sold.",
            "author": "blue_beetle",
            "url": "http://www.metafilter.com/95152/userdriven-discontent#3256046"
        },
        {
            "quote": "The Internet? Is that thing still around?",
            "author": "Homer Simpson",
            "url": "http://www.snpp.com/guides/internet.html"
        },
        {
            "quote": "Programming is like sex: one mistake and you’re providing support for a lifetime.",
            "author": "Michael Sinz",
            "url": ""
        },
        {
            "quote": "If debugging is the process of removing software bugs, then programming must be the process of putting them in.",
            "author": "Edsger Dijkstra",
            "url": ""
        },
        {
            "quote": "Design is not just what it looks like and feels like. Design is how it works.",
            "author": "Steve Jobs",
            "url": ""
        },
        {
            "quote": "One thing is sure, however. The Internet will unite the world like no other mechanism ever has.",
            "author": "Rus Shuler",
            "url": "http://www.theshulers.com/whitepapers/internet_whitepaper/index.html"
        },
        {
            "quote": "Understand you'll spend 20% of the time coding and 80% of it maintaining, so code accordingly.",
            "author": "Joel Coehoorn",
            "url": "http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site/305381#305381"
        },
        {
            "quote": "Why not write to /dev/null? It's fast as hell",
            "author": "Mongo DB is web scale",
            "url": "http://www.xtranormal.com/watch/6995033/"
        },
        {
            "quote": "Use the style guide when it helps, ignore it when it's in the way.",
            "author": "Guido van Rossum",
            "url": "http://mail.python.org/pipermail/python-dev/2010-November/105681.html"
        },
        {
            "quote": "Large social-networking sites are walling off information posted by their users from the rest of the Web.",
            "author": "Tim Berners-Lee",
            "url": "http://www.scientificamerican.com/article.cfm?id=long-live-the-web"
        },
        {
            "quote": "Ruby performance tuning really feels like trying to get the best miles per gallon out of a tricycle.",
            "author": "David R. MacIver",
            "url": "http://harmful.cat-v.org/software/ruby/"
        },
        {
            "quote": "\[Svn is\] the IE6 of version control",
            "author": "James S.",
            "url": "http://harmful.cat-v.org/software/svn/"
        },
        {
            "quote": "I tried to come up with an IPv4 joke, but the good ones were all already exhausted.",
            "author": "#protolol",
            "url": "http://attrition.org/misc/ee/protolol.txt"
        },
        {
            "quote": "Design depends largely on constraints.",
            "author": "Charles Eames",
            "url": ""
        },
        {
            "quote": "Jesus saves, but only Buddha makes incremental backups",
            "author": "MrZebra",
            "url": "http://stackoverflow.com/questions/234075/what-is-your-best-programmer-joke/234159#comments-234159"
        }
];

jQuery.fn.suggest = function() {

    var keywords_input = this;

    if (keywords_input.length) {

        var json_url = keywords_input.data('json-url');
        keywords_input.removeAttr('alt');

        var json_data = undefined;

        // on charge le JSON une seule fois au 1er focus sur l'input de recherche
        keywords_input.focus(function(){
            if (json_data===undefined) {
                $.getJSON(json_url, function(data,textStatus) {
                    json_data = data;
                });
            };
        });
        keywords_input.blur(function(){ setTimeout(function(){ $('#suggest').hide(100); }, 500 ); });
        keywords_input.keyup(init);
        keywords_input.attr('autocomplete','off');//get rid of the annoying autocomplete in Firefox
    };
    
    return this;
    
    function init(event) {

        if (json_data===undefined) { return; };

        // on récupère tout le texte saisi
        var input = $.trim($(keywords_input).val());
        if (input==='' || input==='?') { return endProcess(); };//on match le `?` en attendant un fix dans JSONQuery, flemme

        // on arrête si on detecte la touche ESC, BACK, LEFT ou RIGHT
        if (event.keyCode == 27) { return endProcess(); };//esc

        if (/^(37|39)$/.test(event.keyCode)) { return; };//left, right

        // sinon on peut construire le conteneur des suggestions
        buildSuggestionBox( keywords_input );

        // si on a quelquechose, on arrête si on detecte la touche DOWN, UP ou ENTER => on peut choisir au clavier
        if (event.keyCode == 40) { selectNextResult(); return; };//down
        if (event.keyCode == 38) { selectPrevResult(); return; };//up

        if (event.keyCode == 13) {//enter
            if ( $('#suggest li.selected').length ) {
                goToPost();
                keywords_input.keypress(function(e){
                    e.preventDefault();
                });
            };
        };

        // sinon on cherche des suggestions en limitant le nombre de requetes
        getSuggestions(input);
    };

    function endProcess() {
        $('#suggest').hide();
        return false;
    };
    
    // Insere le conteneur (ul#suggest) de la liste de suggestions
    function buildSuggestionBox(keywords_input) {
        if (!$('#suggest').length) {
            var input = jQuery(keywords_input);// l'input de saisi
            var suggestion_box = $('<ul class="suggest-list"></ul>');
            suggestion_box.attr('id','suggest').hide();
            input.parent().append(suggestion_box);
            var input_offset = keywords_input.offset();
            var body_offset = $('body').offset();
            suggestion_box.css({
                'position': 'absolute',
                'width': keywords_input.outerWidth(),
                'top': (input_offset.top + keywords_input.height() + 21),
                'left': (input_offset.left - body_offset.left) + 2
            });
        };
    };

    // on parse le json
    function getSuggestions(input) {
        var suggestion_box = $('#suggest'), content = '';
        var raw_input = input;
        var input = input.replace(/'/g,"\\'");
        query = "$[?title~'*" + input + "*'][0:6]";//search in name property, case insensitive 'contains'
        var results = JSONQuery(query,json_data);
        if ( results.length ) {
            for (var i=0, len=results.length; i<len; i++) {
                var title = results[i].title.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
                var year = results[i].year;
                var url = results[i].url;
                content += '<li><a href="' + url + '">' + title + ' <em>(' + year + ')</em>' + '</a></li>'
            };
            suggestion_box.html(content).show().highlight(raw_input);
        } else {
            suggestion_box.hide();
        };
    };

    // focus sur le prochain résultat de la liste
    function selectNextResult(){
        if ( $('#suggest li.selected').next().length ) {
            $('#suggest li.selected').removeClass('selected').next().addClass('selected');
            return;
        } else {
            $('#suggest li').removeClass('selected');
            $('#suggest li:first').addClass('selected');
            return;
        };
    };

    // focus sur le résultat précédent de la liste
    function selectPrevResult(){
        if ( $('#suggest li.selected').prev().length ) {
            $('#suggest li.selected').removeClass('selected').prev().addClass('selected');
            return;
        } else {
            $('#suggest li').removeClass('selected');
            return;
        };
    };

    // focus sur le résultat précédent de la liste
    function goToPost(){
        if ( $('#suggest li.selected').length ) {
            window.location = $('#suggest li.selected a').attr('href');
        };
    };

};

jQuery.fn.tweetSuggest = function() {

    // ------------
    // Requirements
    // ------------
    // highlight v3 - Johann Burkard http://johannburkard.de
    // http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
    // ------------
    // JSONQuery
    // https://github.com/jcrosby/jsonquery
    // http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/
    // ------------

    var search_input = this;

    if (search_input.length) {

        var result_list           = $('#tweets-list');
        var tweets_count          = $('#tweets-count');
        var toggle_dbclick_search = $('#tweets-toggle-dbclick-search');
        var tweets_reset_link     = $('#tweets-reset');
        var ajax_loader           = $('#tweets-ajax-loader');
        var result_cache          = hashtagize(result_list.html());
        var tweets_count_cache    = tweets_count.html();
        var json_url              = search_input.data('json-url');
        var max_results_num       = 500;
        var json_data             = undefined;
        var k = {
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            CMD: 91,
            ESC: 27
        };

        if (json_data===undefined) {
            $.getJSON(json_url, function(data,textStatus) {
                json_data = data;
            });
        };

        result_list
            .html(result_cache)
            .dblclick(function(e) {
                e.preventDefault();
                if (toggle_dbclick_search.attr('checked')) {
                    searchTweet( getSelectedText() );
                };
            });

        search_input
            .ajaxStart(function() { ajax_loader.show(); })
            .ajaxStop(function() { ajax_loader.hide(); })
            .keyup(init)
            .attr('autocomplete','off');

        $('#tweets-links a')
            .click(function(e) {
                e.preventDefault();
                searchTweet( $(this).attr('href').replace('#','') );
            });

        $('a[href^="#"]',result_list)
            .live('click', function(e) {
                e.preventDefault();
                searchTweet( $(this).attr('href') );
            });

        $('#tweets-search-form')
            .submit(function(e){
                e.preventDefault();
            });

        tweets_reset_link
            .click(function(e) {
                e.preventDefault();
                endProcess();
            })
            .hide();

        if (window.location.hash.length > 0) {
            $.getJSON(json_url, function(data,textStatus) {
                json_data = data;
                var location_hash = unescape( window.location.hash.replace('#','') );
                searchTweet(location_hash);
            });
        };

    };
    
    return this;

    function init(e) {
        e.preventDefault();
        if (e.keyCode === k.ESC) {
            return endProcess();
        };
        var cancel_keys = [k.LEFT,k.UP,k.RIGHT,k.DOWN,k.SHIFT,k.CTRL,k.ALT,k.CMD];
        if ($.inArray(e.keyCode, cancel_keys) >= 0) {
            return;// do nothing
        };
        var input = search_input.val();
        if (!input.length) {
            return endProcess();
        };
        searchTweet(input);
    };

    function endProcess() {
        window.location.hash = '';
        search_input.val('');
        result_list.html(result_cache);
        tweets_count.html(tweets_count_cache);
        tweets_reset_link.hide();
    };

    function searchTweet(input) {

        if (json_data===undefined || input.length<2) {
            return;
        };

        var input = input.replace(/\n/,'');

        //search in t property, case insensitive 'contains'
        query = "$[?t~'*" + input + "*'][0:" + max_results_num + "]";
        var results = JSONQuery(query,json_data);

        if (results.length) {
            result_list.removeHighlight();
            var content = '';
            for (var i=0, len=results.length; i<len; i++) {
                var text = results[i].t;
                content += '<li><span>' + hashtagize(urlize(text)) + '</span></li>';
            };
            result_list.html(content).highlight(input);
            tweets_count.html(results.length);// affiche le nb de résultats
            search_input.val(input);
            window.location.hash = escape(input);
        } else {
            result_list.html('<li>Pas de résultat.</li>');
            tweets_count.html('0');
        };

        tweets_reset_link.show();

    };

    function urlize(input) {
        // http://snippets.dzone.com/posts/show/452
        var url_match = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/g;
        return input.replace(url_match,'<a href="$1">$1</a>');
    };

    function hashtagize(input) {
        // http://jrgraphix.net/r/Unicode/0020-007F
        var hashtag_match = /(^|\s)(#[^\u0020-\u002f]+)/g;
        return input.replace(hashtag_match,'$1<a href="$2">$2</a>');
    };

    function getSelectedText() {
        // get selected text...
        var val = '';
        if (window.getSelection) {
            val = window.getSelection().toString();
        } else if (document.getSelection) {
            val = document.getSelection().toString();
        } else if (document.selection) {
            val = document.selection.createRange().text;
        };
        // ...then empty the selection
        if (window.getSelection) {
            var selection = window.getSelection();
            if (selection && selection.removeAllRanges) {
                selection.removeAllRanges();
            };
        } else if (document.selection && document.selection.empty) {
            document.selection.empty();
        };
        return $.trim(val);
    };

};




/* Modernizr 2.0.6 (Custom Build) | MIT & BSD
 * Contains: csstransforms3d | iepp | cssclasses | teststyles | testprop | testallprops | prefixes | domprefixes | load
 */
;window.Modernizr=function(a,b,c){function C(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+o.join(c+" ")+c).split(" ");return B(d,b)}function B(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function A(a,b){return!!~(""+a).indexOf(b)}function z(a,b){return typeof a===b}function y(a,b){return x(n.join(a+";")+(b||""))}function x(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l,m=Object.prototype.toString,n=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),o="Webkit Moz O ms Khtml".split(" "),p={},q={},r={},s=[],t=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},u,v={}.hasOwnProperty,w;!z(v,c)&&!z(v.call,c)?w=function(a,b){return v.call(a,b)}:w=function(a,b){return b in a&&z(a.constructor.prototype[b],c)};var D=function(a,c){var d=a.join(""),f=c.length;t(d,function(a,c){var d=b.styleSheets[b.styleSheets.length-1],g=d.cssRules&&d.cssRules[0]?d.cssRules[0].cssText:d.cssText||"",h=a.childNodes,i={};while(f--)i[h[f].id]=h[f];e.csstransforms3d=i.csstransforms3d.offsetLeft===9},f,c)}([,["@media (",n.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join("")],[,"csstransforms3d"]);p.csstransforms3d=function(){var a=!!B(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d);return a};for(var E in p)w(p,E)&&(u=E.toLowerCase(),e[u]=p[E](),s.push((e[u]?"":"no-")+u));x(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b<g)a.createElement(f[b])}a.iepp=a.iepp||{};var d=a.iepp,e=d.html5elements||"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",f=e.split("|"),g=f.length,h=new RegExp("(^|\\s)("+e+")","gi"),i=new RegExp("<(/*)("+e+")","gi"),j=/^\s*[\{\}]\s*$/,k=new RegExp("(^|[^\\n]*?\\s)("+e+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),l=b.createDocumentFragment(),m=b.documentElement,n=m.firstChild,o=b.createElement("body"),p=b.createElement("style"),q=/print|all/,r;d.getCSS=function(a,b){if(a+""===c)return"";var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,q.test(b)&&h.push(d.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},d.parseCSS=function(a){var b=[],c;while((c=k.exec(a))!=null)b.push(((j.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(h,"$1.iepp_$2")+c[4]);return b.join("\n")},d.writeHTML=function(){var a=-1;r=r||b.body;while(++a<g){var c=b.getElementsByTagName(f[a]),d=c.length,e=-1;while(++e<d)c[e].className.indexOf("iepp_")<0&&(c[e].className+=" iepp_"+f[a])}l.appendChild(r),m.appendChild(o),o.className=r.className,o.id=r.id,o.innerHTML=r.innerHTML.replace(i,"<$1font")},d._beforePrint=function(){p.styleSheet.cssText=d.parseCSS(d.getCSS(b.styleSheets,"all")),d.writeHTML()},d.restoreHTML=function(){o.innerHTML="",m.removeChild(o),m.appendChild(r)},d._afterPrint=function(){d.restoreHTML(),p.styleSheet.cssText=""},s(b),s(l);d.disablePP||(n.insertBefore(p,n.firstChild),p.media="print",p.className="iepp-printshim",a.attachEvent("onbeforeprint",d._beforePrint),a.attachEvent("onafterprint",d._afterPrint))}(a,b),e._version=d,e._prefixes=n,e._domPrefixes=o,e.testProp=function(a){return B([a])},e.testAllProps=C,e.testStyles=t,g.className=g.className.replace(/\bno-js\b/,"")+(f?" js "+s.join(" "):"");return e}(this,this.document),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h<e;h++)g=F[b[h]],g&&(f=g(f));for(h=0;h<c;h++)f=E[h](f);return f}function e(a,b,e,g,h){var i=f(a),j=i.autoCallback;if(!i.bypass){b&&(b=D(b)?b:b[a]||b[g]||b[a.split("/").pop().split("?")[0]]);if(i.instead)return i.instead(a,b,e,g,h);e.load(i.url,i.forceCSS||!i.forceJS&&/css$/.test(i.url)?"c":c,i.noexec),(D(b)||D(j))&&e.load(function(){d(),b&&b(i.origUrl,h,g),j&&j(i.origUrl,h,g)})}}function b(a,b){function c(a){if(C(a))e(a,h,b,0,d);else if(B(a))for(i in a)a.hasOwnProperty(i)&&e(a[i],h,b,i,d)}var d=!!a.test,f=d?a.yep:a.nope,g=a.load||a.both,h=a.callback,i;c(f),c(g),a.complete&&b.load(a.complete)}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?H(h):B(h)&&b(h,i);else B(a)&&b(a,i)},H.addPrefix=function(a,b){F[a]=b},H.addFilter=function(a){E.push(a)},H.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",G=function(){b.removeEventListener("DOMContentLoaded",G,0),b.readyState="complete"},0)),a.yepnope=d()}(this,this.document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};

/* prettify-6.2011
 */
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

/**
 * Dragdealer JS v0.9.5
 * http://code.ovidiu.ch/dragdealer
 *
 * Copyright (c) 2010, Ovidiu Chereches
 * MIT License
 * http://legal.ovidiu.ch/licenses/MIT
 */

/* Cursor */

var Cursor =
{
    x: 0, y: 0,
    init: function()
    {
        this.setEvent('mouse');
        this.setEvent('touch');
    },
    setEvent: function(type)
    {
        var moveHandler = document['on' + type + 'move'] || function(){};
        document['on' + type + 'move'] = function(e)
        {
            moveHandler(e);
            Cursor.refresh(e);
        }
    },
    refresh: function(e)
    {
        if(!e)
        {
            e = window.event;
        }
        if(e.type == 'mousemove')
        {
            this.set(e);
        }
        else if(e.touches)
        {
            this.set(e.touches[0]);
        }
    },
    set: function(e)
    {
        if(e.pageX || e.pageY)
        {
            this.x = e.pageX;
            this.y = e.pageY;
        }
        else if(e.clientX || e.clientY)
        {
            this.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
            this.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
        }
    }
};
Cursor.init();

/* Position */

var Position =
{
    get: function(obj)
    {
        var curleft = curtop = 0;
        if(obj.offsetParent)
        {
            do
            {
                curleft += obj.offsetLeft;
                curtop += obj.offsetTop;
            }
            while((obj = obj.offsetParent));
        }
        return [curleft, curtop];
    }
};

/* Dragdealer */

var Dragdealer = function(wrapper, options)
{
    if(typeof(wrapper) == 'string')
    {
        wrapper = document.getElementById(wrapper);
    }
    if(!wrapper)
    {
        return;
    }
    var handle = wrapper.getElementsByTagName('div')[0];
    if(!handle || handle.className.search(/(^|\s)handle(\s|$)/) == -1)
    {
        return;
    }
    this.init(wrapper, handle, options || {});
    this.setup();
};
Dragdealer.prototype =
{
    init: function(wrapper, handle, options)
    {
        this.wrapper = wrapper;
        this.handle = handle;
        this.options = options;
        
        this.disabled = this.getOption('disabled', false);
        this.horizontal = this.getOption('horizontal', true);
        this.vertical = this.getOption('vertical', false);
        this.slide = this.getOption('slide', true);
        this.steps = this.getOption('steps', 0);
        this.snap = this.getOption('snap', false);
        this.loose = this.getOption('loose', false);
        this.speed = this.getOption('speed', 10) / 100;
        this.xPrecision = this.getOption('xPrecision', 0);
        this.yPrecision = this.getOption('yPrecision', 0);
        
        this.callback = options.callback || null;
        this.animationCallback = options.animationCallback || null;
        
        this.bounds = {
            left: options.left || 0, right: -(options.right || 0),
            top: options.top || 0, bottom: -(options.bottom || 0),
            x0: 0, x1: 0, xRange: 0,
            y0: 0, y1: 0, yRange: 0
        };
        this.value = {
            prev: [-1, -1],
            current: [options.x || 0, options.y || 0],
            target: [options.x || 0, options.y || 0]
        };
        this.offset = {
            wrapper: [0, 0],
            mouse: [0, 0],
            prev: [-999999, -999999],
            current: [0, 0],
            target: [0, 0]
        };
        this.change = [0, 0];
        
        this.activity = false;
        this.dragging = false;
        this.tapping = false;
    },
    getOption: function(name, defaultValue)
    {
        return this.options[name] !== undefined ? this.options[name] : defaultValue;
    },
    setup: function()
    {
        this.setWrapperOffset();
        this.setBoundsPadding();
        this.setBounds();
        this.setSteps();
        
        this.addListeners();
    },
    setWrapperOffset: function()
    {
        this.offset.wrapper = Position.get(this.wrapper);
    },
    setBoundsPadding: function()
    {
        if(!this.bounds.left && !this.bounds.right)
        {
            this.bounds.left = Position.get(this.handle)[0] - this.offset.wrapper[0];
            this.bounds.right = -this.bounds.left;
        }
        if(!this.bounds.top && !this.bounds.bottom)
        {
            this.bounds.top = Position.get(this.handle)[1] - this.offset.wrapper[1];
            this.bounds.bottom = -this.bounds.top;
        }
    },
    setBounds: function()
    {
        this.bounds.x0 = this.bounds.left;
        this.bounds.x1 = this.wrapper.offsetWidth + this.bounds.right;
        this.bounds.xRange = (this.bounds.x1 - this.bounds.x0) - this.handle.offsetWidth;
        
        this.bounds.y0 = this.bounds.top;
        this.bounds.y1 = this.wrapper.offsetHeight + this.bounds.bottom;
        this.bounds.yRange = (this.bounds.y1 - this.bounds.y0) - this.handle.offsetHeight;
        
        this.bounds.xStep = 1 / (this.xPrecision || Math.max(this.wrapper.offsetWidth, this.handle.offsetWidth));
        this.bounds.yStep = 1 / (this.yPrecision || Math.max(this.wrapper.offsetHeight, this.handle.offsetHeight));
    },
    setSteps: function()
    {
        if(this.steps > 1)
        {
            this.stepRatios = [];
            for(var i = 0; i <= this.steps - 1; i++)
            {
                this.stepRatios[i] = i / (this.steps - 1);
            }
        }
    },
    addListeners: function()
    {
        var self = this;
        
        this.wrapper.onselectstart = function()
        {
            return false;
        }
        this.handle.onmousedown = this.handle.ontouchstart = function(e)
        {
            self.handleDownHandler(e);
        };
        this.wrapper.onmousedown = this.wrapper.ontouchstart = function(e)
        {
            self.wrapperDownHandler(e);
        };
        var mouseUpHandler = document.onmouseup || function(){};
        document.onmouseup = function(e)
        {
            mouseUpHandler(e);
            self.documentUpHandler(e);
        };
        var touchEndHandler = document.ontouchend || function(){};
        document.ontouchend = function(e)
        {
            touchEndHandler(e);
            self.documentUpHandler(e);
        };
        var resizeHandler = window.onresize || function(){};
        window.onresize = function(e)
        {
            resizeHandler(e);
            self.documentResizeHandler(e);
        };
        this.wrapper.onmousemove = function(e)
        {
            self.activity = true;
        }
        this.wrapper.onclick = function(e)
        {
            return !self.activity;
        }
        
        this.interval = setInterval(function(){ self.animate() }, 25);
        self.animate(false, true);
    },
    handleDownHandler: function(e)
    {
        this.activity = false;
        Cursor.refresh(e);
        
        this.preventDefaults(e, true);
        this.startDrag();
        this.cancelEvent(e);
    },
    wrapperDownHandler: function(e)
    {
        Cursor.refresh(e);
        
        this.preventDefaults(e, true);
        this.startTap();
    },
    documentUpHandler: function(e)
    {
        this.stopDrag();
        this.stopTap();
        //this.cancelEvent(e);
    },
    documentResizeHandler: function(e)
    {
        this.setWrapperOffset();
        this.setBounds();
        
        this.update();
    },
    enable: function()
    {
        this.disabled = false;
        this.handle.className = this.handle.className.replace(/\s?disabled/g, '');
    },
    disable: function()
    {
        this.disabled = true;
        this.handle.className += ' disabled';
    },
    setStep: function(x, y, snap)
    {
        this.setValue(
            this.steps && x > 1 ? (x - 1) / (this.steps - 1) : 0,
            this.steps && y > 1 ? (y - 1) / (this.steps - 1) : 0,
            snap
        );
    },
    setValue: function(x, y, snap)
    {
        this.setTargetValue([x, y || 0]);
        if(snap)
        {
            this.groupCopy(this.value.current, this.value.target);
        }
    },
    startTap: function(target)
    {
        if(this.disabled)
        {
            return;
        }
        this.tapping = true;
        
        if(target === undefined)
        {
            target = [
                Cursor.x - this.offset.wrapper[0] - (this.handle.offsetWidth / 2),
                Cursor.y - this.offset.wrapper[1] - (this.handle.offsetHeight / 2)
            ];
        }
        this.setTargetOffset(target);
    },
    stopTap: function()
    {
        if(this.disabled || !this.tapping)
        {
            return;
        }
        this.tapping = false;
        
        this.setTargetValue(this.value.current);
        this.result();
    },
    startDrag: function()
    {
        if(this.disabled)
        {
            return;
        }
        this.offset.mouse = [
            Cursor.x - Position.get(this.handle)[0],
            Cursor.y - Position.get(this.handle)[1]
        ];
        
        this.dragging = true;
    },
    stopDrag: function()
    {
        if(this.disabled || !this.dragging)
        {
            return;
        }
        this.dragging = false;
        
        var target = this.groupClone(this.value.current);
        if(this.slide)
        {
            var ratioChange = this.change;
            target[0] += ratioChange[0] * 4;
            target[1] += ratioChange[1] * 4;
        }
        this.setTargetValue(target);
        this.result();
    },
    feedback: function()
    {
        var value = this.value.current;
        if(this.snap && this.steps > 1)
        {
            value = this.getClosestSteps(value);
        }
        if(!this.groupCompare(value, this.value.prev))
        {
            if(typeof(this.animationCallback) == 'function')
            {
                this.animationCallback(value[0], value[1]);
            }
            this.groupCopy(this.value.prev, value);
        }
    },
    result: function()
    {
        if(typeof(this.callback) == 'function')
        {
            this.callback(this.value.target[0], this.value.target[1]);
        }
    },
    animate: function(direct, first)
    {
        if(direct && !this.dragging)
        {
            return;
        }
        if(this.dragging)
        {
            var prevTarget = this.groupClone(this.value.target);
            
            var offset = [
                Cursor.x - this.offset.wrapper[0] - this.offset.mouse[0],
                Cursor.y - this.offset.wrapper[1] - this.offset.mouse[1]
            ];
            this.setTargetOffset(offset, this.loose);
            
            this.change = [
                this.value.target[0] - prevTarget[0],
                this.value.target[1] - prevTarget[1]
            ];
        }
        if(this.dragging || first)
        {
            this.groupCopy(this.value.current, this.value.target);
        }
        if(this.dragging || this.glide() || first)
        {
            this.update();
            this.feedback();
        }
    },
    glide: function()
    {
        var diff = [
            this.value.target[0] - this.value.current[0],
            this.value.target[1] - this.value.current[1]
        ];
        if(!diff[0] && !diff[1])
        {
            return false;
        }
        if(Math.abs(diff[0]) > this.bounds.xStep || Math.abs(diff[1]) > this.bounds.yStep)
        {
            this.value.current[0] += diff[0] * this.speed;
            this.value.current[1] += diff[1] * this.speed;
        }
        else
        {
            this.groupCopy(this.value.current, this.value.target);
        }
        return true;
    },
    update: function()
    {
        if(!this.snap)
        {
            this.offset.current = this.getOffsetsByRatios(this.value.current);
        }
        else
        {
            this.offset.current = this.getOffsetsByRatios(
                this.getClosestSteps(this.value.current)
            );
        }
        this.show();
    },
    show: function()
    {
        if(!this.groupCompare(this.offset.current, this.offset.prev))
        {
            if(this.horizontal)
            {
                this.handle.style.left = String(this.offset.current[0]) + 'px';
            }
            if(this.vertical)
            {
                this.handle.style.top = String(this.offset.current[1]) + 'px';
            }
            this.groupCopy(this.offset.prev, this.offset.current);
        }
    },
    setTargetValue: function(value, loose)
    {
        var target = loose ? this.getLooseValue(value) : this.getProperValue(value);
        
        this.groupCopy(this.value.target, target);
        this.offset.target = this.getOffsetsByRatios(target);
    },
    setTargetOffset: function(offset, loose)
    {
        var value = this.getRatiosByOffsets(offset);
        var target = loose ? this.getLooseValue(value) : this.getProperValue(value);
        
        this.groupCopy(this.value.target, target);
        this.offset.target = this.getOffsetsByRatios(target);
    },
    getLooseValue: function(value)
    {
        var proper = this.getProperValue(value);
        return [
            proper[0] + ((value[0] - proper[0]) / 4),
            proper[1] + ((value[1] - proper[1]) / 4)
        ];
    },
    getProperValue: function(value)
    {
        var proper = this.groupClone(value);

        proper[0] = Math.max(proper[0], 0);
        proper[1] = Math.max(proper[1], 0);
        proper[0] = Math.min(proper[0], 1);
        proper[1] = Math.min(proper[1], 1);
        
        if((!this.dragging && !this.tapping) || this.snap)
        {
            if(this.steps > 1)
            {
                proper = this.getClosestSteps(proper);
            }
        }
        return proper;
    },
    getRatiosByOffsets: function(group)
    {
        return [
            this.getRatioByOffset(group[0], this.bounds.xRange, this.bounds.x0),
            this.getRatioByOffset(group[1], this.bounds.yRange, this.bounds.y0)
        ];
    },
    getRatioByOffset: function(offset, range, padding)
    {
        return range ? (offset - padding) / range : 0;
    },
    getOffsetsByRatios: function(group)
    {
        return [
            this.getOffsetByRatio(group[0], this.bounds.xRange, this.bounds.x0),
            this.getOffsetByRatio(group[1], this.bounds.yRange, this.bounds.y0)
        ];
    },
    getOffsetByRatio: function(ratio, range, padding)
    {
        return Math.round(ratio * range) + padding;
    },
    getClosestSteps: function(group)
    {
        return [
            this.getClosestStep(group[0]),
            this.getClosestStep(group[1])
        ];
    },
    getClosestStep: function(value)
    {
        var k = 0;
        var min = 1;
        for(var i = 0; i <= this.steps - 1; i++)
        {
            if(Math.abs(this.stepRatios[i] - value) < min)
            {
                min = Math.abs(this.stepRatios[i] - value);
                k = i;
            }
        }
        return this.stepRatios[k];
    },
    groupCompare: function(a, b)
    {
        return a[0] == b[0] && a[1] == b[1];
    },
    groupCopy: function(a, b)
    {
        a[0] = b[0];
        a[1] = b[1];
    },
    groupClone: function(a)
    {
        return [a[0], a[1]];
    },
    preventDefaults: function(e, selection)
    {
        if(!e)
        {
            e = window.event;
        }
        if(e.preventDefault)
        {
            e.preventDefault();
        }
        e.returnValue = false;
        
        if(selection && document.selection)
        {
            document.selection.empty();
        }
    },
    cancelEvent: function(e)
    {
        if(!e)
        {
            e = window.event;
        }
        if(e.stopPropagation)
        {
            e.stopPropagation();
        }
        e.cancelBubble = true;
    }
};

/*

highlight v3

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>

*/

jQuery.fn.highlight = function(pat) {
    function innerHighlight(node, pat) {
        var skip = 0;
        if (node.nodeType == 3) {
            var pos = node.data.toUpperCase().indexOf(pat);
            if (pos >= 0) {
                var strongnode = document.createElement('strong');
                strongnode.className = 'highlight';
                var middlebit = node.splitText(pos);
                var endbit = middlebit.splitText(pat.length);
                var middleclone = middlebit.cloneNode(true);
                strongnode.appendChild(middleclone);
                middlebit.parentNode.replaceChild(strongnode, middlebit);
                skip = 1;
            };
        } else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
            for (var i = 0; i < node.childNodes.length; ++i) {
                i += innerHighlight(node.childNodes[i], pat);
            };
        };
        return skip;
    };
    return this.each(function() {
        innerHighlight(this, pat.toUpperCase());
    });
};

jQuery.fn.removeHighlight = function() {
    return this.find("strong.highlight").each(function() {
        this.parentNode.firstChild.nodeName;
        with (this.parentNode) {
            replaceChild(this.firstChild, this);
            normalize();
        };
    }).end();
};

/*
Copyright Jason E. Smith 2008 Licensed under the Apache License, Version 2.0 (the "License");
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/

/*
* CREDITS:
* Thanks to Kris Zyp from SitePen for contributing his source for
* a standalone port of JSONQuery (from the dojox.json.query module).
*
* OVERVIEW:
* JSONQuery.js is a standalone port of the dojox.json.query module. It is intended as
* a dropin solution with zero dependencies. JSONQuery is intended to succeed and improve upon
* the JSONPath api (http://goessner.net/articles/JsonPath/) which offers rich powerful
* querying capabilities similar to those of XQuery.
*
* EXAMPLES / USAGE:
* see http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/
*
*     *Ripped from original source.
*         JSONQuery(queryString,object)
        and
        JSONQuery(queryString)(object)
        always return identical results. The first one immediately evaluates, the second one returns a
        function that then evaluates the object.

      example:
        JSONQuery("foo",{foo:"bar"})
        This will return "bar".

      example:
        evaluator = JSONQuery("?foo='bar'&rating>3");
        This creates a function that finds all the objects in an array with a property
        foo that is equals to "bar" and with a rating property with a value greater
        than 3.
        evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}])
        This returns:
        {foo:"bar",rating:4}

      example:
        evaluator = JSONQuery("$[?price<15.00][\rating][0:10]");
        This finds objects in array with a price less than 15.00 and sorts then
        by rating, highest rated first, and returns the first ten items in from this
        filtered and sorted list.


  example:      
    var data = {customers:[
      {name:"Susan", purchases:29},
      {name:"Kim", purchases:150}, 
      {name:"Jake", purchases:27}
    ]};

    var results = json.JSONQuery("$.customers[?purchases > 21 & name='Jake'][\\purchases]",data);
    results 

    returns customers sorted by higest number of purchases to lowest.

*/

 (function() {
    function map(arr, fun
    /*, thisp*/
    ) {
        var len = arr.length;
        if (typeof fun != "function")
        throw new TypeError();

        var res = new Array(len);
        var thisp = arguments[2];
        for (var i = 0; i < len; i++) {
            if (i in arr)
            res[i] = fun.call(thisp, arr[i], i, arr);
        }

        return res;
    }

    function filter(arr, fun
    /*, thisp*/
    ) {
        var len = arr.length;
        if (typeof fun != "function")
        throw new TypeError();

        var res = new Array();
        var thisp = arguments[2];
        for (var i = 0; i < len; i++) {
            if (i in arr) {
                var val = arr[i];
                // in case fun mutates this
                if (fun.call(thisp, val, i, arr))
                res.push(val);
            }
        }

        return res;
    };


    function slice(obj, start, end, step) {
        // handles slice operations: [3:6:2]
        var len = obj.length,
        results = [];
        end = end || len;
        start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);
        end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);
        for (var i = start; i < end; i += step) {
            results.push(obj[i]);
        }
        return results;
    }
    function expand(obj, name) {
        // handles ..name, .*, [*], [val1,val2], [val]
        // name can be a property to search for, undefined for full recursive, or an array for picking by index
        var results = [];
        function walk(obj) {
            if (name) {
                if (name === true && !(obj instanceof Array)) {
                    //recursive object search
                    results.push(obj);
                } else if (obj[name]) {
                    // found the name, add to our results
                    results.push(obj[name]);
                }
            }
            for (var i in obj) {
                var val = obj[i];
                if (!name) {
                    // if we don't have a name we are just getting all the properties values (.* or [*])
                    results.push(val);
                } else if (val && typeof val == 'object') {

                    walk(val);
                }
            }
        }
        if (name instanceof Array) {
            // this is called when multiple items are in the brackets: [3,4,5]
            if (name.length == 1) {
                // this can happen as a result of the parser becoming confused about commas
                // in the brackets like [@.func(4,2)]. Fixing the parser would require recursive
                // analsys, very expensive, but this fixes the problem nicely.
                return obj[name[0]];
            }
            for (var i = 0; i < name.length; i++) {
                results.push(obj[name[i]]);
            }
        } else {
            // otherwise we expanding
            walk(obj);
        }
        return results;
    }

    function distinctFilter(array, callback) {
        // does the filter with removal of duplicates in O(n)
        var outArr = [];
        var primitives = {};
        for (var i = 0, l = array.length; i < l; ++i) {
            var value = array[i];
            if (callback(value, i, array)) {
                if ((typeof value == 'object') && value) {
                    // with objects we prevent duplicates with a marker property
                    if (!value.__included) {
                        value.__included = true;
                        outArr.push(value);
                    }
                } else if (!primitives[value + typeof value]) {
                    // with primitives we prevent duplicates by putting it in a map
                    primitives[value + typeof value] = true;
                    outArr.push(value);
                }
            }
        }
        for (i = 0, l = outArr.length; i < l; ++i) {
            // cleanup the marker properties
            if (outArr[i]) {
                delete outArr[i].__included;
            }
        }
        return outArr;
    }
    var JSONQuery = function(
    /*String*/
    query,
    /*Object?*/
    obj) {
        // summary:
        //     Performs a JSONQuery on the provided object and returns the results.
        //     If no object is provided (just a query), it returns a "compiled" function that evaluates objects
        //     according to the provided query.
        // query:
        //     Query string
        //   obj:
        //     Target of the JSONQuery
        //
        //  description:
        //    JSONQuery provides a comprehensive set of data querying tools including filtering,
        //    recursive search, sorting, mapping, range selection, and powerful expressions with
        //    wildcard string comparisons and various operators. JSONQuery generally supersets
        //     JSONPath and provides syntax that matches and behaves like JavaScript where
        //     possible.
        //
        //    JSONQuery evaluations begin with the provided object, which can referenced with
        //     $. From
        //     the starting object, various operators can be successively applied, each operating
        //     on the result of the last operation.
        //
        //     Supported Operators:
        //     --------------------
        //    * .property - This will return the provided property of the object, behaving exactly
        //     like JavaScript.
        //     * [expression] - This returns the property name/index defined by the evaluation of
        //     the provided expression, behaving exactly like JavaScript.
        //    * [?expression] - This will perform a filter operation on an array, returning all the
        //     items in an array that match the provided expression. This operator does not
        //    need to be in brackets, you can simply use ?expression, but since it does not
        //    have any containment, no operators can be used afterwards when used
        //     without brackets.
        //    * [^?expression] - This will perform a distinct filter operation on an array. This behaves
        //    as [?expression] except that it will remove any duplicate values/objects from the
        //    result set.
        //     * [/expression], [\expression], [/expression, /expression] - This performs a sort
        //     operation on an array, with sort based on the provide expression. Multiple comma delimited sort
        //     expressions can be provided for multiple sort orders (first being highest priority). /
        //    indicates ascending order and \ indicates descending order
        //     * [=expression] - This performs a map operation on an array, creating a new array
        //    with each item being the evaluation of the expression for each item in the source array.
        //    * [start:end:step] - This performs an array slice/range operation, returning the elements
        //    from the optional start index to the optional end index, stepping by the optional step number.
        //     * [expr,expr] - This a union operator, returning an array of all the property/index values from
        //     the evaluation of the comma delimited expressions.
        //     * .* or [*] - This returns the values of all the properties of the current object.
        //     * $ - This is the root object, If a JSONQuery expression does not being with a $,
        //     it will be auto-inserted at the beginning.
        //     * @ - This is the current object in filter, sort, and map expressions. This is generally
        //     not necessary, names are auto-converted to property references of the current object
        //     in expressions.
        //     *  ..property - Performs a recursive search for the given property name, returning
        //     an array of all values with such a property name in the current object and any subobjects
        //     * expr = expr - Performs a comparison (like JS's ==). When comparing to
        //     a string, the comparison string may contain wildcards * (matches any number of
        //     characters) and ? (matches any single character).
        //     * expr ~ expr - Performs a string comparison with case insensitivity.
        //    * ..[?expression] - This will perform a deep search filter operation on all the objects and
        //     subobjects of the current data. Rather than only searching an array, this will search
        //     property values, arrays, and their children.
        //    * $1,$2,$3, etc. - These are references to extra parameters passed to the query
        //    function or the evaluator function.
        //    * +, -, /, *, &, |, %, (, ), <, >, <=, >=, != - These operators behave just as they do
        //     in JavaScript.
        //
        //
        //
        //   |  dojox.json.query(queryString,object)
        //     and
        //   |  dojox.json.query(queryString)(object)
        //     always return identical results. The first one immediately evaluates, the second one returns a
        //     function that then evaluates the object.
        //
        //   example:
        //   |  dojox.json.query("foo",{foo:"bar"})
        //     This will return "bar".
        //
        //  example:
        //  |  evaluator = dojox.json.query("?foo='bar'&rating>3");
        //    This creates a function that finds all the objects in an array with a property
        //    foo that is equals to "bar" and with a rating property with a value greater
        //    than 3.
        //  |  evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}])
        //     This returns:
        //   |  {foo:"bar",rating:4}
        //
        //  example:
        //   |  evaluator = dojox.json.query("$[?price<15.00][\rating][0:10]");
        //      This finds objects in array with a price less than 15.00 and sorts then
        //     by rating, highest rated first, and returns the first ten items in from this
        //     filtered and sorted list.
        tokens = [];
        var depth = 0;
        var str = [];
        query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,
        function(t) {
            depth += t == '[' ? 1: t == ']' ? -1: 0;
            // keep track of bracket depth
            return (t == ']' && depth > 0) ? '`]':
            // we mark all the inner brackets as skippable
            (t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :
            // and replace all the strings
            t;
        });
        var prefix = '';
        function call(name) {
            // creates a function call and puts the expression so far in a parameter for a call
            prefix = name + "(" + prefix;
        }
        function makeRegex(t, a, b, c, d) {
            // creates a regular expression matcher for when wildcards and ignore case is used
            return str[d].match(/[\*\?]/) || c == '~' ?
            "/^" + str[d].substring(1, str[d].length - 1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g, "\\$1$2").replace(/([\*\?])/g, ".$1") + (c == '~' ? '$/i': '$/') + ".test(" + a + ")":
            t;
        }
        query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,
        function() {
            throw new Error("Unsafe function call");
        });

        query = query.replace(/([^<>=]=)([^=])/g, "$1=$2").
        // change the equals to comparisons
        replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,
        function(t) {
            return t.charAt(0) == '.' ? t:
            // leave .prop alone
            t == '@' ? "$obj":
            // the reference to the current object
            (t.match(/:|^(\$|Math|true|false|null)$/) ? "": "$obj.") + t;
            // plain names should be properties of root... unless they are a label in object initializer
        }).
        replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,
        function(t, a, b) {
            var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/);
            // [?expr] and ?expr and [=expr and =expr
            if (oper) {
                var prefix = '';
                if (t.match(/^\./)) {
                    // recursive object search
                    call("expand");
                    prefix = ",true)";
                }
                call(oper[1].match(/\=/) ? "map": oper[1].match(/\^/) ? "distinctFilter": "filter");
                return prefix + ",function($obj){return " + oper[2] + "})";
            }
            oper = t.match(/^\[\s*([\/\\].*)\]/);
            // [/sortexpr,\sortexpr]
            if (oper) {
                // make a copy of the array and then sort it using the sorting expression
                return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,
                function(t, a, b) {
                    return "var av= " + b.replace(/\$obj/, "a") + ",bv= " + b.replace(/\$obj/, "b") +
                    // FIXME: Should check to make sure the $obj token isn't followed by characters
                    ";if(av>bv||bv==null){return " + (a == "/" ? 1: -1) + ";}\n" +
                    "if(bv>av||av==null){return " + (a == "/" ? -1: 1) + ";}\n";
                }) + "})";
            }
            oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/);
            // slice [0:3]
            if (oper) {
                call("slice");
                return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")";
            }
            if (t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)) {
                // ..prop and [*]
                call("expand");
                return (t.charAt(1) == '.' ?
                ",'" + b + "'":
                // ..prop
                t.match(/,/) ?
                "," + t:
                // [prop1,prop2]
                "") + ")";
                // [*]
            }
            return t;
        }).
        replace(/(\$obj\s*(\.\s*[\w_$]+\s*)*)(==|~)\s*`([0-9]+)/g, makeRegex).
        // create regex matching
        replace(/`([0-9]+)\s*(==|~)\s*(\$obj(\s*\.\s*[\w_$]+)*)/g,
        function(t, a, b, c, d) {
            // and do it for reverse =
            return makeRegex(t, c, d, b, a);
        });
        query = prefix + (query.charAt(0) == '$' ? "": "$") + query.replace(/`([0-9]+|\])/g,
        function(t, a) {
            //restore the strings
            return a == ']' ? ']': str[a];
        });
        // create a function within this scope (so it can use expand and slice)
        var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}");
        for (var i = 0; i < arguments.length - 1; i++) {
            arguments[i] = arguments[i + 1];
        }
        return obj ? executor.apply(this, arguments) : executor;
    };


    if (typeof namespace == "function") {
        namespace("json::JSONQuery", JSONQuery);
    }
    else {
        window["JSONQuery"] = JSONQuery;
    }
})();


