         var fixurl = {update: function (searchControl, searcher, query) {
            window.location.hash = encodeURIComponent(query).replace(/%20/g, "+");
         }};
         
         // the cse class encapsulates a left and right search control
         // both controls are driven by a shared search form
         function cse() {
            var sFormDiv = document.getElementById("searchForm");
            var leftScDiv = document.getElementById("leftSearchControl");
            var rightScDiv = document.getElementById("rightSearchControl");

            // create a left, right search control
            // create a custom search form
            this.leftControl = new GSearchControl();
            this.rightControl = new GSearchControl();
            this.leftControl.setSearchStartingCallback(fixurl, fixurl.update)
            this.searchForm = new GSearchForm(true, sFormDiv);

            // bind clear and submit functions
            this.searchForm.setOnSubmitCallback(this, cse.prototype.onSubmit);
            this.searchForm.setOnClearCallback(this, cse.prototype.onClear);

            // set up for large result sets
            this.leftControl.setResultSetSize(GSearch.LARGE_RESULTSET);
            this.rightControl.setResultSetSize(GSearch.LARGE_RESULTSET);
            this.leftControl.setLinkTarget(GSearch.LINK_TARGET_SELF);
            this.rightControl.setLinkTarget(GSearch.LINK_TARGET_SELF);

            var searcher;
            var options;
            
            // configure left control for
            // -- All Results
            // -- Articles Refinement
            // -- Blog Refinement
            // Site Restrict to CSE ID for O'ReillyNet Search
            var cseId = "011173270467069993225:qgrna8fnrjk";
            
            searcher = new GwebSearch();
            options = new GsearcherOptions();
            searcher.setSiteRestriction(cseId, "Courses");
            searcher.setUserDefinedLabel("Courses");
            options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
            this.leftControl.addSearcher(searcher, options);

            searcher = new GwebSearch();
            options = new GsearcherOptions();
            searcher.setSiteRestriction(cseId, "Books");
            searcher.setUserDefinedLabel("Books");
            this.leftControl.addSearcher(searcher, options);

            searcher = new GwebSearch();
            options = new GsearcherOptions();
            searcher.setSiteRestriction(cseId, "Articles");
            searcher.setUserDefinedLabel("Articles");
            this.leftControl.addSearcher(searcher, options);
            
            // Old web searcher using blog refinements, better results with GblogSearch
            searcher = new GwebSearch();
            options = new GsearcherOptions();
            searcher.setSiteRestriction(cseId, "Blogs");
            searcher.setUserDefinedLabel("Blogs");
            this.leftControl.addSearcher(searcher, options);
            
            // Search O'Reillynet and Radar blogs
            // XML.com and Perl.com are filed under oreillynet
            // searcher = new GblogSearch();
            // options = new GsearcherOptions();
            // searcher.setQueryAddition("inurl:blog OR inurl:archives inurl:oreillynet.com OR inurl:radar.oreilly.com");
            // searcher.setUserDefinedLabel("Blogs");
            // this.leftControl.addSearcher(searcher, options);

            searcher = new GwebSearch();
            options = new GsearcherOptions();
            searcher.setSiteRestriction(cseId, null);
            searcher.setUserDefinedLabel("All");
	    //options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
            this.leftControl.addSearcher(searcher, options);

            // configure right control for
            // Book Search
            searcher = new GbookSearch();
            options = new GsearcherOptions();
            options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
            searcher.setUserDefinedLabel("Books");
            searcher.setQueryAddition("inpublisher:O'Reilly");
            this.rightControl.addSearcher(searcher, options);

            // draw the left and right controls
            // the right control is drawn in tabbed mode
            var drawOptions = new GdrawOptions();
            drawOptions.setDrawMode(GSearchControl.DRAW_MODE_TABBED);

            this.leftControl.draw(leftScDiv, drawOptions);
            this.rightControl.draw(rightScDiv);

            // Execute an inital search, use the existing anchor param if present
            var query = decodeURIComponent(location.hash.substring(1).replace(/\+/g, "%20"));
            if (query) {
               this.searchForm.execute(query);
            } else {
               this.searchForm.execute("");
            }
         }

         // when the form fires a submit, grab its
         // value and call the left and right control
         cse.prototype.onSubmit = function(form) {
            var q = form.input.value;
            if (q && q!= "") {
               this.leftControl.execute(q);
               this.rightControl.execute(q);
            }
            return false;
         }

         // when the form fires a clear, call the left and right control
         cse.prototype.onClear = function(form) {
            this.leftControl.clearAllResults();
            this.rightControl.clearAllResults();
            form.input.value = "";
            return false;
         }

         function OnLoad() {
            new cse();
         }
         GSearch.setOnLoadCallback(OnLoad);

