How do I get the tabId of a new created tab? My tabId I want to send in sendMessage is undefinded.
How do I get the tabId?
Later I need the tabId to update the tabs....
popup.js
$(document).ready(function () {
"use strict";
$('button').on('click', function () {
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlDe'});
window.close();
});
chrome.tabs.create({
url: "http://google.com"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlCom'});
window.close();
});
});
background.js
chrome.runtime.onMessage.addListener(function(request) {
if (request.type === 'urlDe') {
alert(request.type + request.content);
} else if (request.type === 'urlCom') {
alert(request.type + request.content);
}
});
You need to access to the tabId via tab.id in your callback function, because chrome.tabs.create is async function:
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
chrome.runtime.sendMessage({content: tab.id, type:'urlDe'});
});
});
More information are in documentation or in this question.
Related
I have a popup with a button like shown below
I am having a click function like below in popup.js
$('#fetch_article').on('click',()=>{
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
const url=tabs[0].url;
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles || [];
if(articles.length<=0 && Object.keys(articles).length === 0){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}else{
// Check if URL already exists
const linkFound = articles.find(link=>link.url===url);
if(linkFound===undefined){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}
}
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
});
});
})
function fetcArticles(url){
chrome.runtime.sendMessage({type: "fetch_article",url:url},(response)=>{
if(response.type==='success'){
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles;
const linkIndex = articles.findIndex(link=>link.url===response.data.url);
if(linkIndex!==-1){
articles[linkIndex].state='Done';
articles[linkIndex].data={summary:response.data.summary,title:response.data.title};
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
}else{
console.error("Error in Fetching articles from session");
}
});
}else{
console.error("Could not Fetch article, So deleting it from storage");
removerArticleFromStorage(url);
}
});
}
In Backgroun.js
chrome.runtime.onMessage.addListener( (request, sender, sendResponse) => {
switch (request.type) {
case "fetch_article":
$.ajax({
type: "POST",
url: "http://someajaxurl.com/method",
data: JSON.stringify({url:request.url}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(response){
if(response.type==='error'){
sendResponse({type:'error',msg:response.msg});
}else{
response.data.url=request.url;
sendResponse({type:'success',data:response.data});
}
}
});
return true;
break;
default:
sendResponse({type:'error',msg:'Nothing Found Here...'});
break;
}
});
This works all good if I click the fetch article button and stays in that tab, but if I click the fetch article button in Tab1 and Move to Tab2 The fetcArticles callback is not working expectedly. What I am doing wrong here.
I'm using ajax to do so and am responding with res.end on the backend but so far, I can only POST once. Here is my code:
Server
app.post("/awesome", passwordless.restricted({ failureRedirect: "/" }), (req, res, next) => {
// ...do a bunch of stuff
res.end();
});
Client
$("[data-new-save]").on("click", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This sounds like a case for event-delegation. The best guess I have is that your refreshContent() function is removing the original [data-new-save] elements and creating new ones. This will cause the bound click event to be removed as well as it is a property of the DOM nodes that existed when it was originally called. You can get around this by delegating the event to a DOM node that does not get "refreshed", I'm assuming that the <body> tag does not get redrawn, only some set of children, so if you target <body> and look for selectors that match "[data-new-save]" it should function properly:
$('body').on('click', "[data-new-save]", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This is what i used for something similar:
$(document).ready(function () {
$('#myform').on('submit', function(e) {
e.preventDefault();
$.ajax({
url : $(this).attr('action') || window.location.pathname,
type: "GET",
data: $(this).serialize(),
success: function (data) {
$("#form_output").html(data);
},
error: function (jXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});
I'm trying to use mocha paired with PhantomJS to run some integration tests without needing to open a new window. My code looks something like:
var waitForAccounts = function(callback) {
if (Accounts.loginServicesConfigured()) {
callback();
} else {
setTimeout(function() {
waitForAccounts(callback);
}, 10);
}
}
var waitForLogin = function(callback) {
if (!!Meteor.user()) {
callback();
} else {
setTimeout(function() {
waitForLogin(callback)
}, 10);
}
}
if (!(typeof MochaWeb === 'undefined')){
MochaWeb.testOnly(function(){
describe("Menu bar", function(){
it("should have the correct title", function() {
expect($('.navbar-brand').html()).to.equal('Lynx');
});
describe('when logged in', function() {
beforeEach(function(done) {
waitForAccounts(function() {
if (!Meteor.user()) {
Meteor.loginWithFacebook({
loginStyle: 'redirect'
});
waitForLogin(function() {
console.log('User:', Meteor.user());
done();
});
} else {
done();
}
});
});
it('should have a logout link', function() {
expect($('#logout').html()).to.exist;
expect($('#login').html()).to.be.undefined;
});
});
});
});
});
I'm guessing this has something to do with the code reloading on every page load, which happens when the account logs in (currently there's a proxy that fakes and auto accepts for the fb oauth.) I'm just not sure how to solve it at this point.
The UI is written using ReactJS and the backend/reactivity is written using Meteor.
I have a problem with passing data from injected js to background.js
injected js name "getDOM.js" and injected with this code in background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
i want to pass data from getDOM.js to background.js, so in background.js there is a function that will be ran when context menu clicked
this is the function in background.js :
function SetLinks(info, tab) {
chrome.extension.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
alert(tabURL);
});
}
as you can see i tried to send a massage and want to get tabURL (this is just for test)
in getDOM.js file i've wrote this code :
chrome.extension.onMessage.addListener(function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
sendResponse( {navURL:'test'} );
}
});
so the navURL must be returned. but it not working
it works reverse, i mean if i was trying for sending request "from" getDOM.js it will work. it seams the request function should be in getDOM.js otherwise it will not work. please help me
I also tried it this way :
background.js
function SetLinks(info, tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
chrome.contextMenus.onClicked.addListener(SetLinks);
// Set up context menu tree at install time.
chrome.runtime.onInstalled.addListener(function() {
// Create one test item for each context type.
var contexts = ["page","selection","link","editable","image","video",
"audio"];
var context = contexts[1];
var title = "test";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
but still not working
Sending a request from the extension/background.js to a content script that you need to specify which tab to send it to. https://developer.chrome.com/extensions/messaging.
I created the sample code and tested it works with me as below:
Background.js:
chrome.contextMenus.create({"title": "sample text", "contexts":["page"],
"id": "ViewAlert"
});
function contextClicked(info, tab) {
if (info.menuItemId == "ViewAlert" ) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
};
chrome.contextMenus.onClicked.addListener(contextClicked);
Content.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
Also keep in mind to add "permissions": ["contextMenus"...] in your manifest.
i have found the solution
background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
How can I send variable from server to page.evaluate ?
var test = 'Lorem Ipsum';
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(){
$('body').html(test);
});
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Thank you in advance for your help.
Edit1
Now it look like
var message = function(){
return {message: 'Hello Word'};
};
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(content){
$('body').html(content);
}, message);
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Now I haven't any error, but I don't know how can I handle this object to use it in page.evaluate
try with
page.evaluate(function (...) {...}, function (err, data){...}, arg1, arg2, ...);
example:
var message = 'hello world';
page.evaluate(function(content){
$('body').html(content);
return 'any data'
}, function (err, anydata) {}, message);
Adding jquery to page
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function(err) {
//jQuery Loaded.
//Wait for a bit if site have AJAX
setTimeout(function() {
return page.evaluate(function() {
// USE JQUERY HERE
//
//
return
}, function(err, result) {
console.log(result);
ph.exit();
});
}, 3000);
});
see readme at:
https://github.com/alexscheelmeyer/node-phantom