Created tab always open the url in the same tab - google-chrome

I have the following sample.js for Google Chrome extension and I would like to know if there is a way that make it able to open url in the same tab every time:
function getword(info,tab) {
chrome.tabs.create({
url: "http://translate.google.com/#en/ar/" + info.selectionText,
})
}
chrome.contextMenus.create({
title: "Translate: %s",
contexts:["selection"],
onclick: getword,
});
The extension send the selected text on the page to be translated on Google translate and I want every time the user uses it to open in the same Window's tab.

Us a variable to track if you have created a tab and once you have use chrome.tabs.update to update it instead of opening a new one. I think users will find this experience confusing though since sometimes a new tab is opened and sometimes there isn't. You will also have to handle the error situation if the users has closed the tab you are trying to update.
var tabId = false;
if (tabId === false) {
chrome.tabs.create({
url: "http://translate.google.com/#en/ar/" + info.selectionText,
}, function(tab) {
tabId = tab.id;
});
} else {
chrome.tabs.update(tabId, {
url: "http://translate.google.com/#en/ar/" + info.selectionText,
});
}

I had a similar requirement to avoid opening multiple tabs for the same URL. I also employed tabs.query to check if a tab with the URL property matching the new tab was already open. If so then I inform the user via a msg box with a 'yes' or 'no' button asking if he wants to open a new tab or over-write the current matching tab. If 'yes' then I tabs.update the already open tab with the url of the newly created tab and close the new tab. It is a bit cluggy but seems to work. I initially found the tabs.query function confusing but eventually have grown to like it.
In the code below I am doing something slightly different. I want to know if the browser has open a tab with the title of 'Agent Home'. If yes then I update that tab after retrieving its tab.id with the tab.url of the newly created tab. In a different scenario, I check if a tab containing "PAMM v4.0" in its title is open. If so I pop a message box then either close the newly created tab. I am in the process of opening the new tab but making it tabs.inactive.
chrome.tabs.onCreated.addListener(function funcName (tabs) {
var tabID = 0;
var tabURL = "";
var tabTitle = "";
var length = 0;
var HomeOrV4 = "";
chrome.tabs.query({}, function(T){
length = T.length;
if(length >0){
for(var i = 0; i<T.length; i++){
tabTitle = T[i].title;
tabID = T[i].id;
tabURL = T[i].url;
if(tabTitle == "PAMM - Agent Home"){
HomeOrV4 = "Home";
return;
}
if(tabTitle == "PAMM v4.0"){
HomeOrV4 = "V4";
return;
}
}
}
});
});
chrome.tabs.onUpdated.addListener(function(id, status){
var V4tabID = 0;
var V4TabURL = "";
var AHPtabID = 0;
if(status.status == "complete"){
console.log("Tab loaded ");
chrome.tabs.query({title:"PAMM - Agent Home Page"}, function(Tabs){
if(Tabs.length>1){
Tabs.remove(Tabs[0].id);
}
if(Tabs.length = 1){
AHPtabID = Tabs[0].id;
//chrome.tabs.remove(V4tabID );
}
});
chrome.tabs.query({title:"PAMM v4.0"}, function(Tabs){
if(Tabs.length > 1){
var r = confirm("You need to complete the open Guest Card. Press OK to continue ...")
if(r==true){
chrome.tabs.update(Tabs[Tabs.length-1].id,{active:false});
//chrome.tabs.remove(Tabs[Tabs.length-1].id);
chrome.tabs.update(Tabs[0].id,{selected:true});
}
}
if(Tabs.length == 1){
tabID = Tabs[0].id;
if (AHPtabID >0){
chrome.tabs.remove(AHPtabID);
}
V4TabURL = Tabs[0].url; }
});
}
else{
console.log("Tab loading");
}
});

In addition to above answers, you need to add permission to access tabs in the manifest file, in case you want to access url, title, or favIconUrl properties of tabs.
"permissions": ["contextMenus", "tabs"],

Related

Chrome extension: get current tab url

I am trying to get current tab url in Chrome extenstion.
All sources says that I need "chrome.tabs.query({active: true;})"
Truth is, that chrome.tabs.query can only be executed in background, and for background active tab is ALWAYS and ONLY "chrome://extensions".
Is there any way to get ACTUAL active tab's url?
Found solution.
As I previously mentioned, "chrome.tabs.query({active: true;})" can only run from background.js, and background.js's active tab is always browser's extensions page, so it's useless.
According to security policies we need instead to waste tons of PC's recources and do something like this:
in client.js:
function getcururl(){
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('gturl.js');
s.onload = function() {
window.postMessage({ type: "gtcrurl", value: cururl }, "*");
this.remove();
};
(document.head || document.documentElement).appendChild(s);}
document.addEventListener('DOMContentLoaded', getcururl());
in gturl.js:
var cururl = window.location.host;
Now we can do in popup.js something like:
var crurl = "empty";
window.addEventListener("message", function(event) {
if(event.data.type === 'gtcrurl') {
window._test = event.data.value;
console.log(event.data.value);
crurl = event.data.value;
}}, false);

How to update html in sidebar template from modal dialog template with javascript in Google Apps Script?

I have a form in a modal dialog. After submiting a form that dialog closes and does some actions in the background. After closing the modal dialog I also want to update html in the sidebar (without refreshing the sidebar). I have a div with "loader" id in the sidebar with class hidden (which prevents it to be visible). On modal dialog close I want to remove class hidden from the "loader" div. How do I access that "loader" div from the modal dialog template?
You could use the browser sessionStorage, set a timer, and continuously "poll" for available information.
Thanks to a comment, a variation was suggested which eliminates the need for polling:
jquery
$(window).bind('storage',
function(e){if(e.key === "newValuesWereEntered"){doSomething()}});
Script tag:
<script>
//Use a timer to keep checking for a completed action from another dialog
var theTimer;
window.setTheTimer = function() {
//To Do - Hide the Spinner
if (typeof(Storage) === "undefined") {
alert('HTML5 Storage is not supported. This App will not work in this browser. Please update your browser.');
return;
}
try {
window.sessionStorage.setItem("newValuesWereEntered","n"); //Make sure check value is reset
} catch(e) {
alert(e.error + ' You may have this apps cookies blocked in this browser, and/or this browser tab. Check cookie blocking.');
return;
};
theTimer = window.setInterval(monitorForTheResponse, 500); //Every 1/2 second, check for response value
};
window.monitorForTheResponse = function() {
var was_a_newValueEntered,dlgInfo;
was_a_newValueEntered = window.sessionStorage.getItem("newValuesWereEntered");
if (was_a_newValueEntered === 'y') {//Dialog just wrote value to window.sessionStorage
window.sessionStorage.setItem("newValuesWereEntered","n");//Reset
clearTimeout(theTimer);//turn off timer
//Get submitted values
dlgInfo = window.sessionStorage.getItem("newValuesToTransfer");
//To Do - Run code to display new value
};
};
</script>
The dialog that has the value to pass to the sidebar must save that value to session storage
window.theValueWasSavedOrEntered = function() {
var arry,objectOfNewValues,strJSON;
try{
if (typeof(Storage) !== "undefined") {//Browser has local storage
window.sessionStorage.setItem("newValuesWereEntered","y"); //Set to yes
objectOfNewValues = {};
objectOfNewValues.valueOne = arry[0];
objectOfNewValues.valueTwo = arry[1];
strJSON = JSON.stringify(objectOfNewValues);
window.sessionStorage.setItem("newValuesWereEntered","y"); //Set to yes
window.sessionStorage.setItem("newValuesToTransfer", strJSON);
};
google.script.host.close();
} catch(e) {
SendErr({'message':'ERROR: ' + e.stack + ' message: ' + e.message});
};
};

Opening links in a new tab from Google Chrome App webview

I have a Google Chrome App with a webview control. Some of the links in the webview are meant to open in a new tab (target="_blank"). However, clicking those links doesn't do anything, and right-clicking on them doesn't open a context menu to open/copy the link. How can I enable such links?
This is the best I've come up with so far:
var webview = null;
function isSafeUrl(url) {
// You may want to perform a more rigorous check.
// There's a technique that creates an <a> to parse the URI, but that seems
// like a security risk.
return !!url.match(/^(?:ftp|https?):\/\//i);
}
function onNewWindow(event) {
if (!isSafeUrl(event.targetUrl)) {
console.warn('Blocking unsafe URL: ' + event.targetUrl);
event.window.discard();
return;
}
var newWindow = null, features = '';
switch (event.windowOpenDisposition) {
case 'ignore':
// Not sure what this is used by. Default enum value, maybe.
console.debug('Ignoring new window request');
return;
case 'save_to_disk':
// Ctrl + S, maybe? Not sure how to reproduce that.
console.log('save_to_disk is not implemented');
return;
case 'current_tab':
webview.src = event.targetUrl;
break;
case 'new_background_tab':
case 'new_foreground_tab':
newWindow = open(event.targetUrl, '_blank');
if (event.windowOpenDisposition != 'new_background_tab') {
newWindow.focus();
}
break;
case 'new_window':
case 'new_popup':
if (event.initialWidth && event.initialHeight) {
features = 'width=' + event.initialWidth + ',height=' + event.initialHeight;
}
newWindow = open(event.targetUrl, '_blank', features);
newWindow.focus();
break;
}
}
function onDomReady() {
webview = document.getElementById('webview');
webview.addEventListener('newwindow', onNewWindow);
}
document.addEventListener('DOMContentLoaded', onDomReady);

chrome.omnibox ceases working after period of time. Begins working after restarting extension

I'm leveraging Google Chrome's omnibox API in my extension.
Current users, including myself, have noticed that the omnibox ceases responding entirely after an undetermined state change or a period of time lapsing. Typing the word to trigger entering into "omnibox" stops having any effect and the URL bar does not shift into omnibox mode.
Restarting Google Chrome does not fix the issue, but restarting my plugin by unchecking and then re-checking the 'enabled' checkbox on chrome://extensions does resolve the issue.
Does anyone have any suggestions on what to investigate? Below is the code used. It is only loaded once through my permanently persisted background page:
// Displays streamus search suggestions and allows instant playing in the stream
define([
'background/collection/streamItems',
'background/model/video',
'common/model/youTubeV2API',
'common/model/utility'
], function (StreamItems, Video, YouTubeV2API, Utility) {
'use strict';
console.log("Omnibox LOADED", chrome.omnibox);
var Omnibox = Backbone.Model.extend({
defaults: function () {
return {
suggestedVideos: [],
searchJqXhr: null
};
},
initialize: function () {
console.log("Omnibox INITIALIZED");
var self = this;
chrome.omnibox.setDefaultSuggestion({
// TODO: i18n
description: 'Press enter to play.'
});
// User has started a keyword input session by typing the extension's keyword. This is guaranteed to be sent exactly once per input session, and before any onInputChanged events.
chrome.omnibox.onInputChanged.addListener(function (text, suggest) {
// Clear suggested videos
self.get('suggestedVideos').length = 0;
var trimmedSearchText = $.trim(text);
// Clear suggestions if there is no text.
if (trimmedSearchText === '') {
suggest();
} else {
// Do not display results if searchText was modified while searching, abort old request.
var previousSearchJqXhr = self.get('searchJqXhr');
if (previousSearchJqXhr) {
previousSearchJqXhr.abort();
self.set('searchJqXhr', null);
}
var searchJqXhr = YouTubeV2API.search({
text: trimmedSearchText,
// Omnibox can only show 6 results
maxResults: 6,
success: function(videoInformationList) {
self.set('searchJqXhr', null);
var suggestions = self.buildSuggestions(videoInformationList, trimmedSearchText);
suggest(suggestions);
}
});
self.set('searchJqXhr', searchJqXhr);
}
});
chrome.omnibox.onInputEntered.addListener(function (text) {
// Find the cached video data by url
var pickedVideo = _.find(self.get('suggestedVideos'), function(suggestedVideo) {
return suggestedVideo.get('url') === text;
});
// If the user doesn't make a selection (commonly when typing and then just hitting enter on their query)
// take the best suggestion related to their text.
if (pickedVideo === undefined) {
pickedVideo = self.get('suggestedVideos')[0];
}
StreamItems.addByVideo(pickedVideo, true);
});
},
buildSuggestions: function(videoInformationList, text) {
var self = this;
var suggestions = _.map(videoInformationList, function (videoInformation) {
var video = new Video({
videoInformation: videoInformation
});
self.get('suggestedVideos').push(video);
var safeTitle = _.escape(video.get('title'));
var textStyleRegExp = new RegExp(Utility.escapeRegExp(text), "i");
var styledTitle = safeTitle.replace(textStyleRegExp, '<match>$&</match>');
var description = '<dim>' + video.get('prettyDuration') + "</dim> " + styledTitle;
return {
content: video.get('url'),
description: description
};
});
return suggestions;
}
});
return new Omnibox();
});
As far as I'm aware the code itself is fine and wouldn't have any effect on whether I see omnibox or not.
You can find full source code here: https://github.com/MeoMix/StreamusChromeExtension/blob/master/src/js/background/model/omnibox.js

Webkit Notifications on Multiple Tabs

I am using WebKit Notifications for my app. Say if I am using this code:
var n = window.webkitNotifications.createNotification(
'icon.png',
'New Comment',
'Praveen commented on your post!'
);
n.onclick = function(x) { window.focus(); this.cancel(); };
n.show();
PS 1: The first five lines are actually a single line. Just for readability I have posted this way.
PS 2: For the full code, please see this: Unable to show Desktop Notifications using Google Chrome.
My question is, what if I have more than one tab opened?
Say if this is gonna get fired when a new comment appears on my app. What if I have more than one tab open? Will this generate many notifications? Say, I have 10 - 15 tabs open and I get two notifications fired. How many notifications will be generated, 20 - 30?
If that is the case, how to prevent generation of a single notification multiple times for each opened tab?
You just need to specify "tag" option for notification. Notifications with the same value in tag only shows once even if many tabs are opened.
For example:
var notification = new Notification('Hey!', {
body : 'So nice to hear from you',
tag : 'greeting-notify',
icon : 'https://mysite.com/my_funny_icon.png'
});
A detailed explanation of Tagging notifications so only the last one appears is available
on the MDN docs site
An excerpt of the code [just in case the docs go down]
The HTML
<button>Notify me!</button>
The JS
window.addEventListener('load', function () {
// At first, let's check if we have permission for notification
// If not, let's ask for it
if (Notification && Notification.permission !== "granted") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
});
}
var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function () {
// If the user agreed to get notified
// Let's try to send ten notifications
if (Notification && Notification.permission === "granted") {
for (var i = 0; i < 10; i++) {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
}
}
// If the user hasn't told if he wants to be notified or not
// Note: because of Chrome, we are not sure the permission property
// is set, therefore it's unsafe to check for the "default" value.
else if (Notification && Notification.permission !== "denied") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
// If the user said okay
if (status === "granted") {
for (var i = 0; i < 10; i++) {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
}
}
// Otherwise, we can fallback to a regular modal alert
else {
alert("Hi!");
}
});
}
// If the user refuses to get notified
else {
// We can fallback to a regular modal alert
alert("Hi!");
}
});
});