Google custom search for images only - javascript

Since Google image search API is deprecated, one should use Google custom search API for this.
I've made a small example using it. My problem is I want to return google image search results only. Whereby this shows web results, and the user may switch to the image result. How can I show only the image results by default?
<div id="cse" style="width: 100%;">Loading</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('search', '1', {language : 'hu'});
google.setOnLoadCallback(function() {
var customSearchOptions = {
enableImageSearch: true,
imageSearchOptions: {
layout: google.search.ImageSearch.LAYOUT_CLASSIC
}
};
var options = new google.search.DrawOptions();
options.setAutoComplete(true);
var customSearchControl = new google.search.CustomSearchControl('XXX', customSearchOptions);
customSearchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
customSearchControl.setAutoCompletionId('XXX');
customSearchControl.draw('cse', options);
}, true);
</script>
<link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" />
The API documentation is quite poor, it only describes how to add additional results.

Google images search is now supported in the Custom Search Engine API. See the API parameters section of this page. I'm using the API with python and for my application I just specify the parameter in the API call.
searchType = "image"
See this post on the cse blog.
EDIT: As Marc points out in his comment below, you need to click "Enable image search" in your CSE console.

Per the Google Custom Search Element Control API - documentation web site, this is possible.
https://developers.google.com/custom-search/docs/element
This is the fragment used for searching by image by default:
'defaultToImageSearch'
So I believe the full syntax for using this would be:
<script>
.
// Google custom search code, ids go here...
.
</script>
<gcse:search></gcse:search>
**<gcse:searchresults enableImageSearch="true" defaultToImageSearch="true">**

For those going through the WebExtensions tutorial, here's the updated code I used in popup.js to make it work with the new CSE functionality:
/**
* #param {string} searchTerm - Search term for Google Image search.
* #param {function(string,number,number)} callback - Called when an image has
* been found. The callback gets the URL, width and height of the image.
* #param {function(string)} errorCallback - Called when the image is not found.
* The callback gets a string that describes the failure reason.
*/
function getImageUrl(searchTerm, callback, errorCallback) {
// Google image search - 100 searches per day.
// https://developers.google.com/image-search/
// var searchUrl = 'https://ajax.googleapis.com/ajax/services/search/images' +
// '?v=1.0&q=' + encodeURIComponent(searchTerm);
var searchUrl = 'https://www.googleapis.com/customsearch/v1' +
'?key=' + key + '&cx=' + cx + '&searchType=image&q=' + encodeURIComponent(searchTerm);
var x = new XMLHttpRequest();
x.open('GET', searchUrl);
// The Google image search API responds with JSON, so let Chrome parse it.
x.responseType = 'json';
x.onload = function() {
// Parse and process the response from Google Image Search.
var response = x.response;
if (!response || !response.items || response.items.length === 0) {
errorCallback('No response from Google Image search!');
return;
}
var firstResult = response.items[0];
// Take the thumbnail instead of the full image to get an approximately
// consistent image size.
var imageUrl = firstResult.image.thumbnailLink;
var width = parseInt(firstResult.image.thumbnailWidth);
var height = parseInt(firstResult.image.thumbnailHeight);
console.assert(
typeof imageUrl == 'string' && !isNaN(width) && !isNaN(height),
'Unexpected respose from the Google Image Search API!');
callback(imageUrl, width, height);
};
x.onerror = function() {
errorCallback('Network error.');
};
x.send();
}
Mainly it's changing the search URL (which should have searchType=image as mentioned) and the response structural references in getImageUrl, and setting up the CSE engine. Make sure your CSE has Image search turned on, and under Sites to search make sure to select Search the entire web but emphasize included sites from the options list.

I'm not 100% certain on this, but I don't think the API supports what you're trying to do. This is not at all surprising, as Google's search API's are infamous for being lacking in even basic functionality (such as the standard search API's limit of 20 results, etc). I think the fact that I'm the first person to answer this in the 3 days it's been active is another indication that this is probably just not supported (or, if it is, Google never bothered to tell anyone).
I know you're not going to like this, but I think your best option is to scrape the images out of the returned result set yourself. That's typically what people have to resort to when dealing with Google results data. Fortunately, their frontend code is remarkably consistent, so a few well-tuned regex matches and/or splits should do the trick for ya.
And yes, it's total BS that Google has provided such lousy support for this API. =)

Try adding this line:
customSearchOptions['disableWebSearch'] = true;

I tried to get a more authoritative answer in the official Google AJAX APIs group,
and it seems the answer is NO(!). Google custom search API currently does not support image search only. You can use the deprecated Google image search API instead.
check this

Try this one
customSearchOptions['searchType'] = "image"
customSearchOptions['enableImageSearch'] = true
customSearchOptions['disableWebSearch'] = true;

Related

Read get request parameter with javascript

I want to create a script that highlights every instance of a string on a page and that string is received as a get request paramater. I want my page to link to the script like: <script src="../Scripts/highlightSearch.js" defer></script> and inside that script I want to have a function like function highlight(content) {...} where content is the string that I want to be highlighted throughout the page. How can I acess content via my script?
In terms of "reading the GET request" there is a relatively new API available that makes reading the querystring parameters trivial. This particular API is URLSearchParams
If you refer to the compatability table at the bottom you'll notice that Internet Exploder does not support this API so, as a possible alternative, you can use quite a simple function to process the querystring yourself. This following function could ( relatively ) easily be modified to provide similar methods to those found in the URLSearchParams api - alternatively search for a Polyfill
const getArgs=function() {
let o={};
location.search.substring(1).split('&').forEach( function( n ){
let l=n.indexOf('=');
if( ~l )o[ n.substring( 0, l ) ]=unescape( n.substring( l + 1 ) );
});
return o;
};
With those in place when you need to read / mainpulate the querystring you can fork the logic
if( 'URLSearchParams' in window ){ /* use methods available to/within the "URLSearchParams" api */ }
else {
let args=getArgs();
let query=args.hasOwnProperty('keyword') ? args.keyword ? false;
if( query ){
let res=RegExp(pattern[, flags]);
/* etc */
}
}
That should, I hope, help give a baseline with which to accomplish the stated goal - there are other ways open to you young Jedi. Good luck.

Change youtube video ID without page reloading

This question is about scripting the main youtube site, client side from javascript.
While it looks easy as a click, I found no way to change the current video by a new non in context video ID without reloading.
This seems to be related with the polymer library in use, with a lot of shadow dom and some special behavior.
Here is the context: I am making for my own use a bookmarklet that load videos from the reddit json api, wich supports CORS calls.
So far so good, I can load many videos, image previews and links into the youtube sidebar, with this simple enough handcrafted script.
Bookmarklet to call the script:
javascript:void%20function(){target=document.getElementsByTagName(%22script%22)[0],inj=document.createElement(%22script%22),inj.src=%22https://webdev23.github.io/reddube/reddube.js%22,target.appendChild(inj)}();
This bookmarklet is loading into the DOM a js file, that is parsing the json api to get what I need.
Here is the content of the called file:
var reds = ["/r/videos","/r/unknownvideos","/r/DeepIntoYouTube","/r/newsreels","/r/fullmoviesonyoutube","/r/SF_Videos","/r/classicfilms","/r/Documentaries","/r/artdocumentaries","/r/ShowsonYT","/r/YTPL","/r/NotTimAndEric","/r/youtubehaiku","/r/PlayItAgainSam","/r/ObscureMedia","/r/360video","/r/AccidentalComedy","/r/amibeingdetained","/r/ArtisanVideos","/r/AwfulCommercials","/r/bestofworldstar","/r/cringe","/r/CommercialCuts","/r/contagiouslaughter","/r/cookingvideos","/r/curiousvideos","/r/deepintoyoutube","/r/documentaries","/r/educativevideos","/r/FastWorkers","/r/fightporn","/r/FuckingWithNature","/r/fullmoviesonyoutube","/r/happycrowds/","/r/idiotsfightingthings","/r/lectures","/r/mealtimevideos","/r/motivationvideos","/r/ObscureMedia","/r/playitagainsam","/r/Prematurecelebration","/r/PublicFreakout","/r/Roadcam","/r/streetfights","/r/sweetjustice","/r/TheWayWeWereOnVideo","/r/trailers","/r/UnexpectedThugLife","/r/videoporn","/r/vids","/r/vines","/r/virtualfreakout","/r/woahtube","/r/listentothis/","/r/Tekno/","/r/reggae/","/r/RootsReggae","r/ska","/r/dub","/r/hip_hop","/r/treemusic/","/r/stonerrock/","/r/frenchrap/","/r/trance/","/r/minimal/"]
var rview = ["","/new/","/rising/","/controversial/","/top/"]
related.innerHTML = "<div style='filter: sepia(38%) invert(100%) saturate(100%) brightness(1) grayscale(0%) hue-rotate(360deg) contrast(100%)'><span id='subR' data-ccc='25' style='color:white;background:#141e1b;font-size:1.44em;width:20px'></span><input type='range' value='0' max='64' id ='redR' style='float:right;width:230px' onchange='redList.innerHTML=\"\";redd(this.value)'><br><span onclick='redList.innerHTML=\"\";' style='float:right;margin:3px 0 0 0'><button id='rflt' data-filter='0' onclick='this.dataset.filter=0;redd(redR.value)'>hot</button><button onclick='rflt.dataset.filter=1;redd(redR.value)'>new</button><button onclick='rflt.dataset.filter=2;redd(redR.value)'>rising</button><button onclick='rflt.dataset.filter=3;redd(redR.value)'>controversial</button><button onclick='rflt.dataset.filter=4;redd(redR.value)'>top</button></span><hr /><hr /><hr /><hr /><hr /><tr><br></div><div id='redList'>"
function redd(it){
console.log(it)
console.log(reds[1])
subR.innerHTML = reds[it]
xhr = new XMLHttpRequest
xhr.open("GET","https://www.reddit.com"+reds[it]+rview[rflt.dataset.filter]+".json?limit=200",true)
xhr.send(null)
xhr.onreadystatechange = function() {
if (xhr.readyState === xhr.DONE) {
if(this.status === 200) {
vids = JSON.parse(xhr.responseText)
cc = subR.dataset.ccc
for (var j=0;j<=cc;j++){
try{
var rt = vids['data']['children'][j]['data']['title'],
rl = vids['data']['children'][j]['data']['url'],
rp = vids['data']['children'][j]['data']['secure_media']['oembed']['thumbnail_url'],
rr = vids['data']['children'][j]['data']['permalink']
redList.innerHTML += "<td><a href='"+rl+"'><img style='width:150px;height:auto;max-width:120px' src='"+rp+"'></img></a><span style='max-width:68%;float:right;text-align:center;font-size:1.23em'><a class='yt-simple-endpoint style-scope ytd-compact-video-renderer' style='text-decoration:bold;font-size:1.23em;text-align:left;min-width:260px' href='"+rl+"'>"+rt+"</a><a target='blank' style='text-decoration:bold;color:black;float:right' href='https://www.reddit.com"+rr+"'>⮊</a></span></td><br>"
}catch(e){console.log(e)}
}
}
}
}
}
related.innerHTML += "</tr><button onclick='redList.innerHTML=\"\";redd(redR.value)'>Load more</button>"
redd(0)
window.onscroll = function() {
var d = document.documentElement,
offset = d.scrollTop + window.innerHeight,
height = d.offsetHeight
if (offset >= '2000' && offset <= '2300') {
subR.dataset.ccc = 25
}
if (offset >= '2000' && offset <= '2100') {
subR.dataset.ccc = 50
}
if (offset >= '3400' && offset <= '3500') {
subR.dataset.ccc = 100
}
if (offset >= '5400' && offset <= '5500') {
subR.dataset.ccc = 150
}
if (offset >= '7400' && offset <= '7500') {
subR.dataset.ccc = 200
}
}
At this stage, clicking a link is just reloading the page.
I tried many things, changing the content of elements, try to alter the "next" recommended video.
Also creating a link in the DOM, isn't working, it is reloading.
Here is the problem in a simple way:
Let's say you are in this yt page https://www.youtube.com/watch?v=YgGzAKP_HuM
From the console, how to load this non related id -q7ZVXOU3kM
into the page, just like a link click on the recommendation sidebar?
The following is NOT working: Visibility monitor is not attached
xhr = new XMLHttpRequest
xhr.open("GET","https://www.youtube.com/watch?v=-q7ZVXOU3kM",true)
xhr.send(null)
document.body.innerHTML = xhr
18 OF MARCH 2018: END OF BOUNTY: QUESTION UNRESOLVED!!!
This is a fairly complex stuff.
The dom content is constantly changing at every reload, and it include recommended video id into the changing scripts. This id's only are allowed to use the ajax capabilities.
This recommendation are changing at any reload, but they are coming back in loop.
I am building a tool to deeply analyse differences, and i found many interesting things, much more that I was searching.
This topic isn't close!
It's not about the destination, it's about the journey.
Despite the videoId being YgGzAKP_HuMif you inspect the <video> you will see something like that:
<video class="video-stream html5-main-video" src="blob:https://www.youtube.com/8e1ef216-1901-ec44-9b76-ea8276e368c6"></video>
You need to find how youtube create their Blob from a videoId and change the src of the player if you want to avoid reloading the page.
But maybe for your project you should think about using the IFrame Player API. It does exactly what you want. And if you want to stay on youtube.com you can replace the youtube original player by an iframe in the DOM.
Good Luck!
it appears that there is no (public) api for the player on youtube :/
but there is one for the iframe youtube player - there you can just call
player.loadVideoById("Vw4KVoEVcr0", 0, "default");
for details see https://developers.google.com/youtube/iframe_api_reference#loadVideoById
That is a quick example I found where you see it in action: http://jsfiddle.net/QtBlueWaffle/8bpQ8/1/
If you really want to directly modify youtube you probably have to dig around in the obfuscated code :/ I tried to find it... but it's obfuscated so you can't easily find it. And even if you find it it will be something like _yt_player.h.xx.xy.h(). Also whenever it will be generated new (and maybe even it is even different for countries... ) your code may break.
Also, it appears to have nothing to do with polymer as there is a player element but it does not have a function to change the video. Apparently, it is only to place the player... control still resides within the js function.
I'm sorry to not have any better news - maybe someone else knows more.
Trying to find a hidden YouTube API is incredibly difficult and it's likely that the next tweak Google makes to YouTube will break your bookmarklet and you'd be back where you started. I think you should take another route altogether. Google provides an API to create, delete, and otherwise manipulate YouTube playlists here: https://developers.google.com/youtube/v3/docs/playlists.
If you’ve never used YouTube API before, see here: https://developers.google.com/youtube/v3/getting-started
Then, (finally!) you can write some JavaScript that creates YouTube playlists from reddit at your command.

How to Create Gmail Filters Programmatically?

I would like to create Gmail filters programmatically in a Chrome extension for standard Gmail users (read non Google App). Currently, thanks to those 2 (outdated) resources:
Grexit Filters API
Gmail Filter Assistant, Userscript
I have managed to develop an early prototype able to create a filter which automatically archives ("cf2_ar=true") emails received at a certain email address ("cf1_to="). However, it seems like any other "cf2" parameters used by Gmail are not valid anymore. For instance, applying a label with parameters "cf2_cat=" or "cf2_sel=" does nothing.
I know that Gmail's code is not very friendly and open when it comes to app or extension development but I would appreciate any help if some of you have any ideas, suggestions or updates regarding the current parameters used by Gmail to create filters, especially the one(s) used to apply labels to messages.
script.js (DOM end)
// Inject API into Gmail DOM
var s = document.createElement('script');
s.src = chrome.runtime.getURL('js/lib/api.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
s.parentNode.removeChild(s);
};
document.addEventListener('Demo_connectExtension', function(e) {
if(e.detail) {
// Gmail GLOBALS : DATA
DATA = e.detail;
user_data[0] = DATA[9]; // Id (ik)
user_data[1] = DATA[10]; // Email
user_data[2] = DATA[17][9][8]; // Locale
user_data[3] = DATA[7]; // Gmail inbox
var emailarr = user_data[1].split('#');
user_data[4] = emailarr[0] + '+do#' + emailarr[1]; // email for filter
var regex_cookie = new RegExp("GMAIL_AT=(.+?);");
if (typeof document.cookie !== 'undefined') {
// Get cookie
var gmcookie = document.cookie.match(regex_cookie)[1];
console.log('cookie:' + gmcookie);
var gmail_filter_url = 'https://mail.google.com' + user_data[3] +
'/?ui=2&ik=' + user_data[0] +
'&at=' + gmcookie +
'&view=up&act=cf&pcd=1&mb=0&rt=c';
var postdata = 'search=cf&cf1_to=' +
encodeURIComponent(user_data[4]) +
'&cf2_ar=true';
$.post(gmail_filter_url, postdata, function(gmail_response){
console.log(gmail_response);
});
}
// [...]
api.js (injected into Gmail)
'use strict';
var GLOBALS;
setTimeout(function() {
/* Send Gmail Data to my extension */
document.dispatchEvent(
new CustomEvent('Demo_connectExtension', {
detail: GLOBALS
}));
}, 1);
Actually, cf2_sel parameter does work for me. I had somewhat similar issue, described in this question and answer.
My code uses Grexit filters project and solves a sample use case:
"When a keyword is present in email content, add label, archive and set filter for this keyword"
I tested it successfully and when looking at Grexit code, 'labelas' action sets abovementioned "cf2_sel" parameter.
My sample project can be found here and provide you with means for quick testing and verification if this works for you.

Search function! JS API

There's a company that has a local website that provides a list of job search opportunities.
The website is something similar to Indeed.com! Here is the link. -
http://www.akronworks.com/
The entire website is in ASP.NET! C#, SQL, HTML, CSS.
Is there a link or a way to use Indeed API? Or a way to find the basic "Search Function Structure Template? I'm creating an application that needs a basic local job search function.
Everything else can be written in the SQL Database.
I found something that was written in Javascript.
Heres the code -
function indeed_clk(a,sig) { var hr = a.href; var si = hr.indexOf('&jsa='); if (si > 0) return; var jsh = hr + '&jsa=' + sig; if ( jsh.indexOf('&inchal') == -1 ) jsh += '&inchal=apiresults'; a.href = jsh; }function init(){(new Image()).src=document.location.protocol+'//gdc.indeed.com/rpc/apilog?a=apiresults';}if (window.addEventListener){window.addEventListener('load', init, false);}else if (window.attachEvent){window.attachEvent('onload', init);}
I found this inside of there source-code. I'm wondering how all of the positions get displayed. How many databases do you think you this site would take to operate? All of the positions have to be store in multiple databases right?
Is there any open-source code that could provide the same functionality?
Thanks - Blake
Indeed does have an api you can use their site link (you will need to create a developer account):
http://www.indeed.com/jsp/apiinfo.jsp
and additional info, how to's, etc. you can go to:
http://www.programmableweb.com/api/indeed

Google Ajax search API

I'm wondering, is it possible to receive google results over their own ajax API in a way like, 100 results per page?
Without a visible search field, I'd like to get the results in the background to create a progression for some search phrases.
My basic question is, what are the restrictions of the google search api ?
--update--
is it possible to change language for a search with google api ? From the start on, it
just delivers from .com in english
Kind Regards
--Andy
The largest number of results you can get is 64, 8 per page of the searcher.
It is possible to combine all of these into one page, but it involves the searcher making 8 calls to the Google Ajax Search API.
Further, you will need to create your own function to render the results:
var s;
var page = 1;
google.load('search', '1', {'nocss' : true});
google.load('jquery', '1.4.2'); // optional
google.setOnLoadCallback(function() {
// T&C's state you should display branding, create a <div id="branding"></div>
google.search.Search.getBranding(document.getElementById('branding'));
s = new google.search.WebSearch();
s.setResultSetSize(google.search.Search.LARGE_RESULTSET);
s.setSearchCompleteCallback(this, searchComplete, null);
s.setNoHtmlGeneration();
});
function searchComplete() {
if(s.results && s.results.length > 0) {
var results = s.results;
for(var i = 0; i < results.length; i++) {
var result = results[i];
// render the results
}
if(page < 8) {
s.gotoPage(page);
page++;
}
}
}
For information about how to render your results see: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GwebResult
To change the language, add the hl argument when including the script in web pages:
<script src="http://www.google.com/jsapi?hl=en" type="text/javascript"></script>
http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GSearchControl
This has information about the main controller class used. It appears that the following answers your question about result size:
.setResultSetSize(switchTo)
This method is called to select the
number of results returned by each of
the searchers. Note, this is not a
scalar. It is an enumeration that
indicates either a small number of
results, or a large number of results.
In the future, this method may be
enhanced to support medium and extra
large result sets. From the sample
applications, you have probably seen
the more/less twiddle control at the
top of the search control. This method
is used by that twiddle control.
switchTo - supplies en enumeration
which indicates the desired number of
search results to return for each
configured searcher. Valid values
include:
google.search.Search.LARGE_RESULTSET -
request a large number of results
(typically 8 results)
google.search.Search.SMALL_RESULTSET -
request a small number of results
(typically 4 results)
google.search.Search.FILTERED_CSE_RESULTSET
- request up to 10 results. This will only work for Web Search queries
scoped to a Filter Custom Search
engine, otherwise an error will be
returned. returns - n/a
Here is my code:
<script src="https://www.google.com/jsapi?key=GOOGLE_SEARCH_KEY" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
//<![CDATA[
google.load("search", "1");
function OnLoad() {
// Create a search control
var searchControl = new google.search.SearchControl();
var options = new google.search.SearcherOptions();
options.setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN);
searchControl.addSearcher(new google.search.WebSearch(),options);
searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
// Tell the searcher to draw itself and tell it where to attach
searchControl.draw(document.getElementById("searchcontrol"));
}
google.setOnLoadCallback(OnLoad);
//]]>
</script>
<style>.gsc-control { width: 80%; } input.gsc-search-button { border: 1px solid black; }</style>

Categories

Resources