Reputation: 598
I'd like to be able to return an array of all a users bookmark folders from the root folder at any point in the tree.
This is the closest I've come which returns nothing of RESULT_TYPE_FOLDER:
function find_folders()
{
var history = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
var query = history.getNewQuery();
var options = history.getNewQueryOptions();
// Query users bookmarks, not history
options.queryType = options.QUERY_TYPE_BOOKMARKS;
// Execute the search and store results
var result = history.executeQuery(query, options);
// Open the root containerNode and open it
var resultContainerNode = result.root;
// OPEN resultContainerNode
resultContainerNode.containerOpen = true;
var folders = [];
// Search results are now child items of this container?
for (var i=0; i < resultContainerNode.childCount; ++i) {
var childNode = resultContainerNode.getChild(i);
if(childNode.type === childNode.RESULT_TYPE_FOLDER)
{
folders.push(childNode);
}
}
// CLOSE resultContainerNode
resultContainerNode.containerOpen = false;
return folders;
};
find_folders();
If I remove this result type checking I get lots of URIs, some RESULT_TYPE_QUERYs, but no RESULT_TYPE_FOLDER:
childNode.type: 0
childNode.type: RESULT_TYPE_QUERY
childNode.title: Most Visited
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: 0
childNode.type: RESULT_TYPE_QUERY
childNode.title: History
The documentation here: https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryQueryOptions#Query_type_constants suggests you can set:
excludeItems boolean This option excludes all URIs and separators from a bookmarks query. This would be used if you just wanted a list of bookmark folders and queries (such as the left pane of the places page). Ignored for queries over history. Defaults to false.
But setting this causes the query to return no results:
function find_folders()
{
var history = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
var query = history.getNewQuery();
var options = history.getNewQueryOptions();
options.queryType = options.QUERY_TYPE_BOOKMARKS;
options.excludeItems = true; // Exclude everything that isn't a folder?
// Execute the search and store results
var result = history.executeQuery(query, options);
// Open the root containerNode and open it
var resultContainerNode = result.root;
// OPEN resultContainerNode
resultContainerNode.containerOpen = true;
var folders = [];
// Search results are now child items of this container?
for (var i=0; i < resultContainerNode.childCount; ++i) {
var childNode = resultContainerNode.getChild(i);
folders.push(childNode);
}
// CLOSE resultContainerNode
resultContainerNode.containerOpen = false;
return folders;
};
find_folders(); // Returns nothing :C
Upvotes: 1
Views: 766
Reputation: 598
Okay looks like I've run into a few bugs and limitations in the Firefox Places query interface.
1 - (bug?) setting query.setFolders([folder_array], 1)
with the second paramater (folder count) to anything other than 1 causes no results. Setting it to 1 will only search the first folder from your array.
2 - (limitation) excludeItems
works only if you specify folders to search into which isn't helpful :C
3 - (limitation/bug?) query.setSearchTerm(term)
seems to not match folder names so I had to manually check them against the search term :Q__
Sketchy workaround solution is to create the array of folders to search and then search separately through each one, concatenating the results, like so:
bookmarkr_utilities.find_folders = function(search_term)
{
bookmarkr_utilities.debug_log("find_folders()");
bookmarkr_utilities.folders = [];
var folders = [ bookmarkr_utilities.bmsvc_service().toolbarFolder
, bookmarkr_utilities.bmsvc_service().bookmarksMenuFolder
, bookmarkr_utilities.bmsvc_service().unfiledBookmarksFolder ];
for (var i = 0; i < folders.length; i++)
{
bookmarkr_utilities.folders = bookmarkr_utilities.folders.concat(bookmarkr_utilities.find_inside_folder(search_term, folders[i]));
}
return bookmarkr_utilities.folders;
};
Helper function to actually run the search:
bookmarkr_utilities.find_inside_folder = function(search_term, search_folder)
{
var history = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
var result_folders = [];
var query = history.getNewQuery();
query.setFolders([search_folder], 1);
var options = history.getNewQueryOptions();
options.excludeItems = true; // exclude everything except folders
// only works when folders are set
// Execute the search and store results
var result = history.executeQuery(query, options);
// Open the root containerNode and open it
var resultContainerNode = result.root;
resultContainerNode.containerOpen = true;
// Search results are now child items of this container?
bookmarkr_utilities.debug_log("resultContainerNode.childCount: " + resultContainerNode.childCount);
for (var i=0; i < resultContainerNode.childCount; ++i) {
var childNode = resultContainerNode.getChild(i);
if(childNode.type === childNode.RESULT_TYPE_FOLDER)
{
// HACK HACK HACK
if(search_term)
{
if(childNode.title.toLowerCase() == search_term.toLowerCase())
result_folders.push(childNode);
}
// END HACK HACK HACK OH GOD
else
{
result_folders.push(childNode);
}
}
}
// Close container
resultContainerNode.containerOpen = false;
return result_folders;
}
Upvotes: 1
Reputation: 21
excludeItems
works only if you specify folders to search into, for example
query.setFolders([PlacesUtils.toolbarFolderId, PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId], 1);
It also doesn't return a flat list of folders, so you have to go through the results, open and collect contents recursively.
You are free to file an enhancement bug, if you have a good use-case to get a flat list of folders.
Finally, you are taking Places nodes out of the result and handing them out, this makes them zombie objects basically, would be better if you'd create your own object and add to it stuff you care about, like { title: node.title, uri: node.uri }
, or whatever else (I just found a bug here related to this behavior and I'm going to file and fix it).
Upvotes: 2