bicycle4431
bicycle4431

Reputation: 82

Google Custom Search JSON API Constantly Refreshing when called

For some reason when I use the code below to search for a term on a website that I have setup a google custom search engine with, it refreshes infinitely, I believe there is some bug in the code that I cannot catch. I found the code from another stackoverflow answer located here What I'm trying to do here is get the JSON data that is returned from each search query and show it similar to the design of normal google search results.

Search.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <form action="results.html" id="cse-search-box">
        <div>
            <input class="" name="q" type="text"> 
            <input class="" type="submit">
        </div>
    </form>
</body>
</html>

Results.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>JSON Custom Search API</title>

    <style type="text/css">
        body{
            width: 100%;
        }
        .gs-image{
            max-width: 100px;
        }
    </style>
</head>
<body>
    <h2 style="font-weight: bold; ">Search Results:</h2>
    <div class="gsc-result-info" id="resInfo-0"></div>
    <hr/>
    <div id="googleContent"></div>

    <script>
    //Handler for response from google.
    function hndlr(response) {
        if (response.items == null) {
            //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
            //So if we get to the invalid one, send them back a page.
            window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
            return;
        }
        //Search results load time
        document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
        //Clear the div first, CMS is inserting a space for some reason.
        document.getElementById("googleContent").innerHTML = "";
        //Loop through each item in search results
        for (var i = 0; i < response.items.length; i++) {
            var item = response.items[i];
            var content = "";

            content += "<div class='gs-webResult gs-result'>" +
            "<table class='gsc-table-result'><tbody><tr>";
            //Thumbnail image
            // if (item.pagemap.cse_thumbnail != null)
            //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
            // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
            //Link
            content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
            //File format for PDF, etc.
            if (item.fileFormat != null)
                content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
            //description text and URL text.
            content += item.htmlSnippet.replace('<br>','') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl +"</div>" +
            "<br/></td></tr></tbody></table></div>";
            document.getElementById("googleContent").innerHTML += content;
        }
        //Page Controls
        var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
        var currentPage = Math.floor(start / 10 + 1);
        var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
        //Page change controls, 10 max.
        for (var x = 1; x <= totalPages && x<=10; x++) {
            pageControls += "<span class='gsc-cursor-page";
            if (x === currentPage)
                pageControls += "gsc-cursor-current-page";
            var pageLinkStart = x * 10 - 9;
            pageControls+="'><a href='results.html?start="+pageLinkStart+"&q="+query+"'>"+x+"</a>&nbsp;&nbsp;</span>";
        }
        pageControls += "</div></div></div>";
        document.getElementById("googleContent").innerHTML += pageControls;
    }

    //Get search text from query string.a
    var query = document.URL.substr(document.URL.indexOf("q=") + 2);
    var start = document.URL.substr(document.URL.indexOf("start=") + 6, 2);
    if (start === "1&" || document.URL.indexOf("start=") === -1)
        start = 1;

    //Load the script src dynamically to load script with query to call.
    //DOM: Create the script element
    var jsElm = document.createElement("script");
    //Set the type attribute
    jsElm.type = "application/javascript";
    //Make the script element load file
    jsElm.src = "https://www.googleapis.com/customsearch/v1?key=yourAPIkeyHERE&cx=yourSEARCHengineIDhere&start="+start+"&q=" +query +"&callback=hndlr";
    //Finally insert the element to the body element in order to load the script
    document.body.appendChild(jsElm);
</script>
</body>
</html>

Upvotes: 2

Views: 832

Answers (3)

Prabhat
Prabhat

Reputation: 802

please handle the response data. Actually, Every time response will not have items property because every search keyword don't have the result. So, you need to check 'is response object have items property or not?

please replace the hndlr() function with my changes and run. I hope it'll work fine. I didn't handle error thing if you have time check and implement.

function hndlr(response) {
        if (response.items) {
            if (response.items == null) {
                //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
                //So if we get to the invalid one, send them back a page.
                window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
                return;
            }
            //Search results load time
            document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
            //Clear the div first, CMS is inserting a space for some reason.
            document.getElementById("googleContent").innerHTML = "";
            //Loop through each item in search results
            for (var i = 0; i < response.items.length; i++) {
                var item = response.items[i];
                var content = "";

                content += "<div class='gs-webResult gs-result'>" +
                    "<table class='gsc-table-result'><tbody><tr>";
                //Thumbnail image
                // if (item.pagemap.cse_thumbnail != null)
                //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
                // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
                //Link
                content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
                //File format for PDF, etc.
                if (item.fileFormat != null)
                    content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
                //description text and URL text.
                content += item.htmlSnippet.replace('<br>', '') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl + "</div>" +
                    "<br/></td></tr></tbody></table></div>";
                document.getElementById("googleContent").innerHTML += content;
            }
            //Page Controls
            var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
            var currentPage = Math.floor(start / 10 + 1);
            var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
            //Page change controls, 10 max.
            for (var x = 1; x <= totalPages && x <= 10; x++) {
                pageControls += "<span class='gsc-cursor-page";
                if (x === currentPage)
                    pageControls += "gsc-cursor-current-page";
                var pageLinkStart = x * 10 - 9;
                pageControls += "'><a href='results.html?start=" + pageLinkStart + "&q=" + query + "'>" + x + "</a>&nbsp;&nbsp;</span>";
            }
            pageControls += "</div></div></div>";
            document.getElementById("googleContent").innerHTML += pageControls;
        }
        else {
            document.getElementById("googleContent").innerHTML = "No result found on " + query + ", try other";
        }
    }

Upvotes: 1

holymoof
holymoof

Reputation: 128

If response does not contain items the handler will redirect you to the same page again and again. This can happen for any error returned by the API (e.g. wrong API credentials, quota exceeded etc.). In that scenario the following code sets start to a negative value (or even to NaN) which results to a infinite loop.

if (response.items == null) {
    //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
    //So if we get to the invalid one, send them back a page.
    window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
    return;
}

I don't think it's a good idea to use substr for retrieving those values from URL in this case, but you can use a helper instead.

So you can do something like this in your code:

var query = getQueryVariable('q');
var start = getQueryVariable('start');
if (!start || start < 1) {
  start = 1
}

And of course handle possible response.error as per @mayur's answer.

Upvotes: 0

Mayur Kukadiya
Mayur Kukadiya

Reputation: 2747

I have try your Code into My local env. I am getting this error in response of google search.

enter image description here

hndlr This function calls a page again and again when response is null Right ? So Due to your API key , response object return error, and that's why page is refreshing continuously.

If you Provide right API Key then google return response and page not getting refresh because you have put condition on it like below :

response.items === null

We can again manage some more condition for prevent that recursiveness by adding one more condition into it.

I have update one condition in code in hndlr function :

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>JSON Custom Search API</title>

    <style type="text/css">
        body {
            width: 100%;
        }

        .gs-image {
            max-width: 100px;
        }
    </style>
</head>

<body>
    <h2 style="font-weight: bold; ">Search Results:</h2>
    <div class="gsc-result-info" id="resInfo-0"></div>
    <hr />
    <div id="googleContent"></div>

    <script>
        //Handler for response from google.
        function hndlr(response) {
            console.log(response);
            if (response.items == null && !response.error) {

                //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
                //So if we get to the invalid one, send them back a page.
                window.location.replace("customsearch.html?start=" + (start - 10) + "&q=" + query);
                return;
            }
            //Search results load time
            document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
            //Clear the div first, CMS is inserting a space for some reason.
            document.getElementById("googleContent").innerHTML = "";
            //Loop through each item in search results
            for (var i = 0; i < response.items.length; i++) {
                var item = response.items[i];
                var content = "";

                content += "<div class='gs-webResult gs-result'>" +
                    "<table class='gsc-table-result'><tbody><tr>";
                //Thumbnail image
                // if (item.pagemap.cse_thumbnail != null)
                //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
                // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
                //Link
                content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
                //File format for PDF, etc.
                if (item.fileFormat != null)
                    content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
                //description text and URL text.
                content += item.htmlSnippet.replace('<br>', '') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl + "</div>" +
                    "<br/></td></tr></tbody></table></div>";
                document.getElementById("googleContent").innerHTML += content;
            }
            //Page Controls
            var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
            var currentPage = Math.floor(start / 10 + 1);
            var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
            //Page change controls, 10 max.
            for (var x = 1; x <= totalPages && x <= 10; x++) {
                pageControls += "<span class='gsc-cursor-page";
                if (x === currentPage)
                    pageControls += "gsc-cursor-current-page";
                var pageLinkStart = x * 10 - 9;
                pageControls += "'><a href='customsearch.html?start=" + pageLinkStart + "&q=" + query + "'>" + x + "</a>&nbsp;&nbsp;</span>";
            }
            pageControls += "</div></div></div>";
            document.getElementById("googleContent").innerHTML += pageControls;
        }

        //Get search text from query string.a
        var query =  document.URL.substr(document.URL.indexOf("q=") + 2);
        var start = document.URL.substr(document.URL.indexOf("start=") + 6, 2);
        if (start === "1&" || document.URL.indexOf("start=") === -1)
            start = 1;

        //Load the script src dynamically to load script with query to call.
        //DOM: Create the script element
        var jsElm = document.createElement("script");
        //Set the type attribute
        jsElm.type = "application/javascript";
        //Make the script element load file
        jsElm.src = "https://www.googleapis.com/customsearch/v1?key=yourAPIkeyHERE&cx=yourSEARCHengineIDhere&start=" + start + "&q=" + query + "&callback=hndlr";
        //Finally insert the element to the body element in order to load the script
        document.body.appendChild(jsElm);
    </script>
</body>

</html>

Upvotes: 0

Related Questions