Update url in tab and title - google-chrome-extension

I want to update a tab over the Id. This is working. After it, I want to set the title of the tab. The Code below is not working. For a short time the title is shown, but then it gets overwritten with the updated site...
chrome.tabs.update(globalData.bbId, {url: 'MYURL'}, function (){
chrome.tabs.executeScript(globalData.bbId, {code: 'document.title = "Test"'});
});
Its possible to set the title easily?
thanks

Chrome's update tab API callback is called when the new URL is in started to load and not when the loading is completed, you can check that in the callback as well.
// basic query.
chrome.tabs.query({active: true}, (tabs) => {
chrome.tabs.update(tabs[0].id, {url: 'http://facebook.com'}, (tab) => {
console.log(tab.status); // loading
})
})
After "loading" status "completed" status comes when url is completely loaded and it's where your Title is getting overwritten. And you have no callback to catch completed state.
So, you can get your work done by below options :-
Option 1 - Use setTimeout() and set expected time when you think reload will be done. I have set it to 3 seconds here.
chrome.tabs.query({active: true}, (tabs) => {
chrome.tabs.update(tabs[0].id, {url: 'http://facebook.com'}, (tab) => {
setTimeout(() => { chrome.tabs.executeScript(tab.id, {code: "document.title = 'New Title'"}) }, 3000);
})
})
Option 2 - You can listen to Tab Updated Event like
let tabUpdateHandler = (tabId, {url: updatedUrl, status}, tab) => {
if (updatedUrl && status = 'completed') {
// set your new title here
}
}
chrome.tabs.onUpdated.addListener(tabUpdateHandler);
Both the options can set your Title correctly.
Happy Coding.

Related

Unchecked runtime.lastError: No tab with <id>, Chrome Extension

I don't understand why i recieve this error
Error
This code works
chrome.tabs.onUpdated.addListener(handleUrls);
function handleUrls(tabId, { changeInfo }, tab) {
const isOauthTokenPage = tab.url?.match(CONFIG.OAUTH_TOKEN_PAGE_PATTERN);
if (isOauthTokenPage) {
chrome.tabs.remove(tabId);
}
}
But why i get this error?
I tried chrome.tabs.onUpdated.removeListener before and after chrome.tabs.remove(tabId), tried chrome.tabs.query to get "actual" tabId
So it's trigger more than once
To avoid it
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// check url state
if (!changeInfo.url) return;
// your code...
if ((tab.url).match(CONFIG.OAUTH_TOKEN_PAGE_PATTERN)) {
// won't invoke onUpdated several times
chrome.tabs.remove(tabId);
}
});

Firestore web save data offline feedback

I'm searching for a method to give feedback to a user of my Firebase/Firestore web app when offline. Lets see some code.
var colRef = db.collection('collectionName').doc('anyDoc');
var setWithMerge = colRef.set({
'value': 'someValue',
}, {
merge: true
})
.then(function () {
alert('Success');
})
.catch(function (error) {
alert("Fail :" + error);
});
Online: Call the function, and the success alert works perfect.
Offline: Call the function, and nothing happens. But when user goes online, the app shows all alerts in a row.
In short, the .then part of the code only runs online. I need some sort of feedback for offline user.
What you're seeing is the expected behavior. Local write operations don't regularly fail, so there is no completion handler for them. If you want to do something after the local write completes, just use normal coding logic and put it after the set:
var colRef = db.collection('collectionName').doc('anyDoc');
var setWithMerge = colRef.set({
'value': 'someValue',
}, {
merge: true
})
alert("Value set");
Thx #Frank, #Blackwood.
I changed the alerts for a non blocking notification.
function doSomething() {
try {
var colRef = db.collection('collectionName').doc('anyDoc');
var setWithMerge = colRef.set({
'value': 'someValue',
}, {
merge: true
})
.then(function () {
alertify.notify('Data saved online.', 'success', 5);
})
.catch(function (error) {
alert('Error: ' + error);//or
//alertify.notify('Data saved online.', 'error', 10);
});
alertify.notify('Data saved on cache.', 'warning', 5);
} catch (error) {
alert('Error: ' + error);
}}
Online: Call the function, and launches 2 notifies (cached and online) almost at same time.
Offline: Call the function, launches 1 notify and when user goes online, the app shows all pendent online notifies in a row.
A very acceptable behavior.
I do not speak English, forgive my mistakes.

How to Get Window Variable Using WebdriverIO

I am trying to run webdriverio with PhantomJS/Chrome to load a page and then grab the window object for use with other scripts. For some reason I am unable to get the window object. Everytime I get, I end up seeing output like this:
Title is: XXXXX
{ state: 'pending' }
Using the following script:
var webdriverio = require('webdriverio');
var options = {
desiredCapabilities: {
browserName: 'chrome',
logLevel: 'verbose'
}
};
var client = webdriverio.remote(options);
client
.init()
.url('https://xxxx.com')
.waitUntil(function () {
return client.execute(function () {
return Date.now() - window.performance.timing.loadEventEnd > 40000;
}).then(function (result) {
console.log(window);
return window;
});
})
.end();
Does anyone know how I can fix my code so that the window object is returned to my NodeJS console app after the page is completely loaded?
Thanks!
Window is an object in the browser's DOM, so it's only available inside of the 'execute' function. If you wanted access to it, you could return it from your 'execute' function:
return client.execute(function () {
return window;
}).then(function (result) {
console.log(result);
});
This work as well:
browser.execute('return window');

Scraping with phantomJS and NodeJS

I'm following the tutorial listed here :
http://code.tutsplus.com/tutorials/screen-scraping-with-nodejs--net-25560
When I run the code:
var host = 'http://www.shoutcast.com/?action=sub&cat=Hindi#134';
var phantom = require('phantom');
phantom.create(function(ph) {
return ph.createPage(function(page) {
return page.open(host, function(status) {
console.log("opened site? ", status);
page.injectJs('http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', function() {
//jQuery Loaded.
//Wait for a bit for AJAX content to load on the page. Here, we are waiting 5 seconds.
setTimeout(function() {
return page.evaluate(function() {
//Get what you want from the page using jQuery. A good way is to populate an object with all the jQuery commands that you need and then return the object.
console.log(document.getElementsByClassName('transition')[0]);
return document.getElementsByClassName('transition')[0];
}, function(result) {
console.log(result);
ph.exit();
});
}, 5000);
});
});
});
});
I get the following error :
phantom stdout: ReferenceError: Can't find variable: $
phantom stdout: phantomjs://webpage.evaluate():7
phantomjs://webpage.evaluate():10
phantomjs://webpage.evaluate():10
I have no idea what this means and there's no help on how to resolve it ...
How can this be solved ?
Basically I want all the 'a' tags with class transition from the site I'm scraping. All these tags are loaded asynchronously on the site.
The $ is due to jQuery and possible conflicts. You hardly require to inject jQuery just to scrape 'a' tags with class transition. You always have document.querySelector or document.querySelectorAll.
var host = 'http://www.shoutcast.com/?action=sub&cat=Hindi#134';
var phantom = require('phantom');
phantom.create(function(ph) {
ph.createPage(function(page) {
page.open(host, function(status) {
console.log("opened site? ", status);
//Wait for a bit for AJAX content to load on the page. Here, we are waiting 5 seconds.
setTimeout(function() {
page.evaluate(function() {
// here you need to add more code to get the html/text
// more code incase you use querySelectorAll
return document.document.querySelector('a.transition');
//return document.document.querySelectorAll('a.transition');
},
function(result) {
console.log(result);
ph.exit();
});
}, 5000);
});
});
});
However, I am not able to understand the way function (result) { console.log(result); ...} is coded. I am not aware if page.evaluate takes callback function as second parameter. Please check that with the documentation.

SpookyJS: Extra Then Required After Filling Forms

The CasperJS Quickstart Guide has this example on filling out a form:
casper.start('http://google.fr/', function() {
// search for 'casperjs' from google form
this.fill('form[action="/search"]', { q: 'casperjs' }, true);
});
casper.then(function() {
// aggregate results for the 'casperjs' search
links = this.evaluate(getLinks);
// now search for 'phantomjs' by filling the form again
this.fill('form[action="/search"]', { q: 'phantomjs' }, true);
});
The form is submitted automatically because of the true parameter being passed to this.fill, and the next casper.then function is called as soon as the new page is loaded.
But when writing Cucumber tests with SpookyJS like so:
spooky.start("http://www.somepage.com");
spooky.then(function () {
this.fill("form", {username: "foo", password: "bar"}, true);
});
spooky.then(function () {
this.echo(this.getPageContent());
this.echo(this.getCurrentUrl());
});
By looking at the page content and the URL, I can tell that Spooky is saying it's still on the form page when the spooky.then function is called. But if you add one more spooky.then like so:
//Empty Spooky.then call so we can do what we want on the correct page
this.spooky.then(function () {});
this.spooky.then(function () {
this.echo(this.getPageContent());
this.echo(this.getCurrentUrl());
});
Suddenly, this works. Why is an extra spooky.then call needed here, when it isn't needed while using Casper? I have tested this in Casper and it works as expected, but with Spooky, an extra then call is needed.

Resources