chrome.windows.getAll() is undefined? - javascript

I want to write an extension (a session manager which has more features and eye candy than the ones already in the gallery) for google chrome / chromium.
But I can't get the following code to work:
function list_session() {
var list = [];
chrome.windows.getAll(
{"populate" : true},
function (window_list) {
for(window in window_list) {
list.concat(window.tabs);
}
}
);
console.log(list);
return list;
}
It's a fairly simple example for the use of the google api, but instead of a list of tabs I get only 'undefined'values in return. Furthermore, the window list seems to be empty.
I'm currently running Chromium 7.0.517.44 (64615) under Ubuntu 10.10. I've tried the official chrome release from google as well with the same results.
API documentation can be found here:
http://code.google.com/chrome/extensions/windows.html
phineas

Assuming you declared tabs permission in manifest, there are several problems with this code:
list_session() function will return empty list because you modify the list in a callback function, which could be called by chrome 15 minutes after your console.log(list); and return. You need to change your program structure to use callbacks instead.
concat method does not modify original array
in operator is not recommended to use to loop through an array as it might return not what you expect.
So I would write something like this:
function list_session(callback) {
chrome.windows.getAll({populate : true}, function (window_list) {
var list = [];
for(var i=0;i<window_list.length;i++) {
list = list.concat(window_list[i].tabs);
}
console.log(list);
if(callback) {
callback(list);
}
});
}
//usage
list_session(function(tab_list) {
//use array of tabs
});

Related

Adding a selectable 'not found' entry to a Twitter Typeahead Control

I've been combining Twitter Typeahead and Bloodhound into a Knockout custom binding as a bit of an experiment, and so far I have it working quite well. However I have a use case where I wanted to have a selectable entry in the list if a user types in a search term which finds no results. This isn't something that is available by default in typeahead but I did find this issue on Github which demonstrates a workaround that seems to fit the bill. Trouble is I can't get it to work at all and my fairly limited Javascript smarts have all but run out.
The gist of this workaround is that rather than creating a Bloodhound instance and then setting the source property of the typeahead to engine.ttAdaptor() you do the following:
var engine = new Bloodhound(/* ... */);
engine.initialize();
var emptyDatum = { val: 'i am suggestion shown when there are none!' };
var sourceWithEmptySelectable = function(q, cb) {
engine.get(q, injectEmptySelectable);
function injectEmptySelectable(suggestions) {
if (suggestions.length === 0) {
cb([emptyDatum]);
}
else {
cb(suggestions);
}
}
};
$('.typeahead').typeahead(null, {
// ...
source: sourceWithEmptySelectable
});
Using the latest versions of typeahead (v0.11.1) I get an error which simply says missing source. Looking at the source code for Bloodhound it looks to me like the engine.get(q, injectEmptySelectable) call no longer works as there is no method of get on the Bloodhound class with a signature that accepts a query and a callback. There is one on the Transport class but I'm not seeing how that would be the one being used in this example. Am I correct in this or am I missing something, or is there another way to accomplish this?

How can I read Excel custom properties in Office Javascript API?

I have a tab pane app that needs to access the custom properties of the current MS Office document, which can be Word or Excel.
There seems to be no built in way of doing this with the Office JavaScript API, but in Word, I use the Office.context.document.getFileAsync() method to return the entire file. I can then unzip it, read in the custom.xml file, and navigate through the XML to get the custom properties.
However, the Office.context.document.getFileAsync() is not available in Excel. Is there another way to read the custom properties?
I know that the question is quite old, but since I stumbled upon it while searching for the answer myself, I'm going to answer it nevertheless. The following JavaScript function is going to print all custom document properties at the end of the current document. It requires version 1.3 of the Office API (see also https://dev.office.com/reference/add-ins/word/documentproperties).
function getProperties() {
Word.run(function (context) {
var body=context.document.body;
var customDocProps = context.document.properties.customProperties;
context.load(customDocProps);
return context.sync().then(function () {
for (var i = 0; i < customDocProps.items.length; i++) {
body.insertText(customDocProps.items[i].key, Word.InsertLocation.end);
body.insertText('\n', Word.InsertLocation.end);
body.insertText(customDocProps.items[i].value, Word.InsertLocation.end);
body.insertText('\n', Word.InsertLocation.end);
}
})
})
}

Get account ID from Google Analytics Tracking code on page

I am performing an audit using a custom web crawler of mine and was trying to garner the accountID for the legacy implementations of Google Analytics, but I cannot seem to get any of the JavaScript functions in _gaq to return the accountId in use. Does anybody know how to do this? All the documentation I've read really only mentions how to set variables, not how to get variables out once set for the purpose of auditing an implementation.
Thanks in advance
UPDATE
Thanks everyone! I wish I could check off all of your responses as good answers.
After a bit of testing, I have come up with the following function that handles pretty much every use case.
function getAccount() {
try {
if (_gaq) {
for (i = 0; i < _gaq.length; i++) {
if (_gaq[i][0] == "_setAccount") {
return _gaq[i][1]
}
}
}
if (_gat) {
if (_gat.fb) {
return _gat.fb
}
}
if (ga) {
return ga.getAll()[0].a.data.values[':trackingId']
}
} catch (e) { }
return ""
}
Joshua, this isn't a standard feature / get function that would be available.
You can however manually access ga object created by the tracking library.
If you for example open console for this webpage and type in:
ga.getAll()[0].a.data.values[':trackingId']
You will receive UA-5620270-1 which is probably the main Analytics Account for Stack Overflow. Similar approach should work in your case as well - and also any other attribute that's accessible:
Screen: http://fii.cz/sbdqevk
If you are prepared to accept a less than elegant solution you could use
function getAccount(_gaq) {
for (i = 0; i < _gaq.length; i++) {
if (_gaq[i][0] == "_setAccount") {
return _gaq[i][1];
}
}
}
_gaq is an array of arrays, the function simply loops through until it finds a subarray where the first element is _setAccount and returns the second element, which is the account number (_gaq.push(['_setAccount', 'UA-XXXXX-X']);).
As you are talking of legacy implementations, there are even older versions of the code so you might need more checks. The oldest version I could find on an active page was:
<script type="text/javascript">
_uacct = "UA-XXXXXXXX-X";
urchinTracker();
</script>
It's quite easy to get the Account Id from there. There is also the synchronous version of the code (sorry, can't find an example right now).
And for the current version look at Petrs answer.
According to documentation first you get all the trackers set on page
// returns an array with all the trackers
const trackers = ga.getAll();
And then, for each tracker, you can obtain the tracking id for each one getting the property
// returns the 'trackingId' propperty
const trackingId = tracker.get('trackingId'));
If you want to shorten it up, you could do
const trackingIds = ga.getAll().map(tracker => tracker.get('trackingId'));
Warning:
Remember to run this always after the ga ready.
Don't — use ga object methods outside a readyCallback as the methods
may not be available yet.
var trackers = ga.getAll();
Do — use ga object methods inside a
readyCallback as they're guaranteed to be available.
ga(function() {
var trackers = ga.getAll();
});
I just did it using an alternative method, as follows:
var _gaq = _gaq || [];
_gaq.push(function() {
var trackers, i;
trackers = _gat._getTrackers();
for (i = trackers.length - 1; i >= 0; i--) {
var account = trackers[i]._getAccount();
console.log("tracker account", account);
}
});

Trying to access this JSON attribute, but my method is not working (screenshot of JSON object provided)

For the sake of simplicity, and to make our lives easier, I just took a screen shot of the JSON object, here: http://i.imgur.com/zT4wUSc.png
Right now, I am trying to access 1's __text value. I use this code, which I am able to access other attribute:value pairs, like the title under 0.
entireJSON.TEI.text.body.div.forEach(function(entry) {
entry.p.forEach(function(dp) {
var dateCurr = dp.title; // this works fine
}
}
But where it goes wrong is when I try the following code (I've tried other variations too). I've tried many different kinds of syntax, and I just can't get it. How do I access the attribute:value (__text:text's value) under 1?
entireJSON.TEI.text.body.div.forEach(function(entry) {
entry.p.forEach(function(dp) {
var dateCurr = dp.title; // this works fine
dp.persName.forEach(function(test) { // DOESN'T WORK
console.log(test.__text); //DOESNT'T WORK
});
});
});
I would try using a conditional since the first index p[0] doesn't have a property for persName in the screenshot and would throw an error like Cannot reach property forEach of undefined
entireJSON.TEI.text.body.div.forEach(function(entry) {
entry.p.forEach(function(dp) {
var dateCurr = dp.title; // this works fine
// if it's an array
if (Object.prototype.toString.call(dp.persName) === '[object Array]') {
dp.persName.forEach(function(test) { // DOESN'T WORK
console.log(test.__text); //DOESNT'T WORK
});
} else {
// everything else
console.log(dp.persName);
}
});
});
You can still use Array.isArray if you just want to support modern browsers.

immutable chrome sqlite return objects

I am using a sqlite DB as a storage system for a webapp. I been using the objects that are returned from queries directly in application. For example:
function get_book_by_id(id,successCallback,errorCallback)
{
function _successCallback(transaction, results)
{
if(results.rows.length==0) {successCallback(null);}
else
{
book=results.rows.item(0);
successCallback(book);
}
}
db.transaction(
function (transaction) {
transaction.executeSql("SELECT id,title,content,last_read from books where id=?;",[id], _successCallback, errorCallback);
});
}
This returns me an object with the given id, all columns are provided as properties. Nice. The problem I just figured out is that all the properties of the result set object are immutable. So for example if I want to change the property 'title' it takes no effect, which in my opinion makes no sense. Example:
get_book_by_id(1,handle,error);
function handle(book)
{
//THIS DOESN'T WORK, book.title is still what it was.
book.title=book.title+"more text";
}
I of course can convert all my DB objects into mutable objects, but I rather would not do that.
Is that an expected behavior? Can I request mutable objects?
I am using google chrome 9.0 on Mac OS X.
The WebSQL spec doesn't require for the returned item to be sealed, but it's up to the implementation (the spec does require for the item to be an ordered dictionary with the properties in the same order as the columns in your query).
And no, there is no way to explicitly request a mutable object, so you'll want to do something like the convert_to_mutable() approach suggested by Stan.
BTW, assuming you're using a 3rd party library, it probably has a function for this, for example jQuery.extend() or _.extend().
Building on Stepan's answer, but for people like me that want a quick fix from SO.
You can create another basic object and copy the sqlite row properties onto it.
Something like this:
var immutable_book = results.rows.item(0);
var book = {};
for (var prop in immutable_book) {
if (immutable_book.hasOwnProperty(prop)) {
book[prop] = immutable_book[prop];
}
}
That goes in the _successCallback, and then later you can do this:
book.title=book.title+"more text"; // works now !
I came across this issue in iOS Safari, but in Chrome and Android web-kit browsers I was able to update properties of the returned row object directly.

Categories

Resources