What is Object details in Chrome.* API - api

I am learning Chrome extension development from the official documentation and learned a bit but I need understanding what it means by object details in API function parameters. For example one of browserAction method getTitle signature is
chrome.browserAction.getTitle(object details, function callback)
//object details integer (optional) tabId
Now I write in background.js
chrome.browserAction.getTitle({}, titleShow);
function titleShow(t){
console.log('tab title:' + t);
}
and it show title of my extension.As you can see here I send blank object {}.
How do I get tabId on very first line and send it with this method?
Does this method return tab Title if we send tab id?

You are asking questions that are easy to answer, just check the documentation and you'll see the details of the chrome.browserAction.getTitle() method (and all the other methods of the Chrome APIs).
Quoting from the documentation:
chrome.browserAction.getTitle(object details, function callback)
Gets the title of the browser action.
Parameters:
object details:
integer (optional) tabId. Specify the tab to get the title from. If no tab is specified, the non-tab-specific title is returned.
function callBack. The callback parameter should be a function that looks like this: function(string result) {...};
string result.
So, to answer your questions:
To get the tab id on the first line you've got to use the chrome.tabs.query() method (see documentation), request the tab with the details you're interested in and use its ID in the callback, something like this:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.browserAction.getTitle({tabId: tabs[0].id}, function(result) {
console.log("Browser action title:", result);
});
});
Browser actions can have different titles on different tabs. To set a different title for each tab you have to use the chrome.browserAction.setTitle() method. So if you send the tabId in the details object of the chrome.browserAction.getTitle() method, you'll not get the tab title, you'll only get the tab-specific title of the browser action. To get a specific tab title you should use the chrome.tabs.query() method.

Related

Can't get 'distance_meters' field from react-native-google-places-autocomplete query

In the documentation for the Google API (https://developers.google.com/maps/documentation/places/web-service/autocomplete), it says that if you use the 'origin' param with a (latitude, longitude) value, it should return the field 'distance_meters'.
When I put the api call into my browser (https://maps.googleapis.com/maps/api/place/autocomplete/xml?input=Ar&types=establishment&origin=40.70823656815506,-73.94331559793082&key=<API_KEY>) I do get the 'distance_meters' field, as you can see at the bottom of the image.
However, when I add the same params into the 'query' prop of the GooglePlacesAutocomplete component in react-native, I only get back a few of the fields shown above, and I do not get the 'distance_meters' field.
Please advise me on how to get the 'distance_meters' field using the GooglePlacesAutocomplete field. My code is below, I am console logging the rowData from renderRow.
When you check the GooglePlacesAutocomplete.d.ts source file of the react-native-google-places-autocomplete library, scroll to see the interface Query and you will notice that the origin parameter is not yet included in the library
// #see https://developers.google.com/places/web-service/autocomplete
interface Query<T = AutocompleteRequestType> {
key: string;
sessiontoken?: string;
offset?: number;
location?: string;
radius?: number;
language?: Language;
components?: string;
rankby?: string;
type?: T;
strictbounds?: boolean;
// deprecated. see https://github.com/FaridSafi/react-native-google-places-autocomplete/pull/384
types?: T;
}
In addition, to see all the Autocomplete predictions results, you can use the renderDescription function and log the data since this function determines the data passed to each renderRow (search result).
renderDescription={(data) => console.log(data)}
Here's a sample code where you will see that the distance_meters is not returned since the origin parameter is not defined in the Query interface.
You can file the issue on the github repository here.

Office UI Fabric - PeoplePicker: Cannot get createGenericItem to work

Perhaps it's just a misunderstanding on my side, but I thought the callback for createGenericItem in the PeoplePicker (https://developer.microsoft.com/en-us/fabric#/components/peoplepicker) was used to handle input, that cannot be matched to any of the available items, and then give the possibility to create an adhoc item for this. But, whatever I tried, the callback is never called.
I made a simple pen here for the issue: https://codepen.io/anon/pen/daGPWe?editors=0010
In the example, there are two items, Peter and Maria. If you type something different (and hit enter, tab, space, whatever) I'd expect the createGenericItem callback to be called, but it isn't.
What am I doing wrong? Or is there a misunderstanding of the purpose of this callback? I'm unable to find an example anywhere.
Regarding
but I thought the callback for createGenericItem in the PeoplePicker
(https://developer.microsoft.com/en-us/fabric#/components/peoplepicker)
was used to handle input
that's correct. In order to trigger IBasePickerProps.createGenericItem function, IBasePickerProps.onValidateInput function needs to be provided with ValidationState.valid as a return value, for example:
<NormalPeoplePicker
createGenericItem={this.createGenericItem}
onValidateInput={this.handleValidateInput}
selectedItems={this.state.selectedItems}
onResolveSuggestions={this.handleResolveSuggestions}
onChange={this.handleChange}
/>
private handleValidateInput(input: string) {
return ValidationState.valid;
}
private createGenericItem(input: string, validationState: ValidationState) {
return { text: "Unknown person", state: validationState };
}
This demo demonstrates it, once tab or enter key is clicked and value cannot be resolved to any of the available items, Unknown person item is getting displayed

safari visibleContentsAsDataURL() is undefined

My goal is to take screenshot of a webpage using safari 6 via an extension. I am using this in my extension global page:
function handle_message(event) {
event.target.page.dispatchMessage("handle_message",
{image:
safari.application.activeBrowserWindow.activeTab.visibleContentsAsDataURL()
}
}
safari.application.addEventListener("message",handle_message,false);
On the receiving end the event message.image is undefined. Is there anything I need to do different. I can successfully send other tab properties such as url, just not the screenshot data image url. Any idea?
Thanks,
Stan
I found it myself, the method needs a callback (of course)
safari.application.activeBrowserWindow.activeTab.visibleContentsAsDataURL(
function(image_url){
//do something with image_url
}
)

JQuery Tab function not firing via JQuery templates

Hi I'm using JQuery tabs http://jqueryui.com/demos/tabs/ with search results being returned from my server with each row potentially having its own tabs depending on the search results. If the user clicks on the sorting options then the search results change including the tabs within each row returned which may or may not have tabs. In the example above you can see there are 2 records returned and the top record has tabs called Other Videos.
I have been successfully able to retrieve the resultset back from the server and the template is bulding correctly, however i cannot get the .tabs() function to fire? Does anyone have any experience with using tabs and know how I can get my tabs() function to fire?
Here is the code I use to dynamically load the template after the json result set is returned:
$(".searchBox").fadeOut("fast", function () {
$(this).html("").fadeIn("fast", function () {
$("#searchTemplate").tmpl(json.Data.SearchResults.Results).appendTo(".searchBox").fadeIn("fast");
});
});
And here is a for loop that I use to iterate over the results after the template has been loaded with the new html tabs created to try and get the .tabs() function to fire:
for(var i=0;i<json.Data.SearchResults.Results.length;i++){
if (json.Data.SearchResults.Results[i].OtherVideos.length || json.Data.SearchResults.Results[i].VideoFriends.FriendCount > 0)
{
$(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").tabs();
if ($(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").length > 0)
alert("it exists");
else
alert("it dont");
}
}
Suffice to say the alert box "it exists" appears successfully so it is finding the dynamically created html tab that the template generated however the tab itself is not being initialized by the statement:
$(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").tabs();
Does anybody know the reason why or what I'm missing here to get my .tabs() function to fire ...
I've examined the dynamic content and double checked the html code using firebug inspector and everything is according to how it should be the id's are correct, the #id's are there and so on, so my only conclusion is that the .tabs() function is not firing. Is this a limitation on the JQuery tabs itself? Can it not perform this type of "live" loading capability? Is there a callback function I should be using as part of loading the template itself?
Here is a picture of what is being returned after the call to the server without the tabs working:
Okay I fixed the problem, and thought I'd better give my answer for those of you who suffer a similar problem.
I should have placed my for loop inside of the same callback function as the tmpl call e.g:
$(".searchBox").fadeOut("fast", function () {
$(this).html("").fadeIn("fast", function () {
$("#searchTemplate").tmpl(json.Data.SearchResults.Results).appendTo(".searchBox").fadeIn("fast");
// For loop should go here!
});
});
I had the for loop after this block of code and the tabs() function essentially was not referencing the newly created tabs at all.

How do I get data from a background page to the content script in google chrome extensions

I've been trying to send data from my background page to a content script in my chrome extension. i can't seem to get it to work. I've read a few posts online but they're not really clear and seem quite high level. I've got managed to get the oauth working using the Oauth contacts example on the Chrome samples. The authentication works, i can get the data and display it in an html page by opening a new tab.
I want to send this data to a content script.
i'm having a lot of trouble with this and would really appreciate if someone could outline the explicit steps you need to follow to send data from a bg page to a content script or even better some code. Any takers?
the code for my background page is below (i've excluded the oauth paramaeters and other )
` function onContacts(text, xhr) {
contacts = [];
var data = JSON.parse(text);
var realdata = data.contacts;
for (var i = 0, person; person = realdata.person[i]; i++) {
var contact = {
'name' : person['name'],
'emails' : person['email']
};
contacts.push(contact); //this array "contacts" is read by the
contacts.html page when opened in a new tab
}
chrome.tabs.create({ 'url' : 'contacts.html'}); sending data to new tab
//chrome.tabs.executeScript(null,{file: "contentscript.js"});
may be this may work?
};
function getContacts() {
oauth.authorize(function() {
console.log("on authorize");
setIcon();
var url = "http://mydataurl/";
oauth.sendSignedRequest(url, onContacts);
});
};
chrome.browserAction.onClicked.addListener(getContacts);`
As i'm not quite sure how to get the data into the content script i wont bother posting the multiple versions of my failed content scripts. if I could just get a sample on how to request the "contacts" array from my content script, and how to send the data from the bg page, that would be great!
You have two options getting the data into the content script:
Using Tab API:
http://code.google.com/chrome/extensions/tabs.html#method-executeScript
Using Messaging:
http://code.google.com/chrome/extensions/messaging.html
Using Tab API
I usually use this approach when my extension will just be used once in a while, for example, setting the image as my desktop wallpaper. People don't set a wallpaper every second, or every minute. They usually do it once a week or even day. So I just inject a content script to that page. It is pretty easy to do so, you can either do it by file or code as explained in the documentation:
chrome.tabs.executeScript(tab.id, {file: 'inject_this.js'}, function() {
console.log('Successfully injected script into the page');
});
Using Messaging
If you are constantly need information from your websites, it would be better to use messaging. There are two types of messaging, Long-lived and Single-requests. Your content script (that you define in the manifest) can listen for extension requests:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == 'ping')
sendResponse({ data: 'pong' });
else
sendResponse({});
});
And your background page could send a message to that content script through messaging. As shown below, it will get the currently selected tab and send a request to that page.
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: 'ping'}, function(response) {
console.log(response.data);
});
});
Depends on your extension which method to use. I have used both. For an extension that will be used like every second, every time, I use Messaging (Long-Lived). For an extension that will not be used every time, then you don't need the content script in every single page, you can just use the Tab API executeScript because it will just inject a content script whenever you need to.
Hope that helps! Do a search on Stackoverflow, there are many answers to content scripts and background pages.
To follow on Mohamed's point.
If you want to pass data from the background script to the content script at initialisation, you can generate another simple script that contains only JSON and execute it beforehand.
Is that what you are looking for?
Otherwise, you will need to use the message passing interface
In the background page:
// Subscribe to onVisited event, so that injectSite() is called once at every pageload.
chrome.history.onVisited.addListener(injectSite);
function injectSite(data) {
// get custom configuration for this URL in the background page.
var site_conf = getSiteConfiguration(data.url);
if (site_conf)
{
chrome.tabs.executeScript({ code: 'PARAMS = ' + JSON.stringify(site_conf) + ';' });
chrome.tabs.executeScript({ file: 'site_injection.js' });
}
}
In the content script page (site_injection.js)
// read config directly from background
console.log(PARAM.whatever);
I thought I'd update this answer for current and future readers.
According to the Chrome API, chrome.extension.onRequest is "[d]eprecated since Chrome 33. Please use runtime.onMessage."
See this tutorial from the Chrome API for code examples on the messaging API.
Also, there are similar (newer) SO posts, such as this one, which are more relevant for the time being.