Reputation: 82
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> </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
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> </span>";
}
pageControls += "</div></div></div>";
document.getElementById("googleContent").innerHTML += pageControls;
}
else {
document.getElementById("googleContent").innerHTML = "No result found on " + query + ", try other";
}
}
Upvotes: 1
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
Reputation: 2747
I have try your Code into My local env. I am getting this error in response of google search.
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> </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