-
Notifications
You must be signed in to change notification settings - Fork 263
JEP Places API
An API for Firefox Places (History and Bookmarks).
- Don't expose an "update/refresh" method
- Rename
folders
togroups
-- more conceptual, and futureproofs if the UI of bookmarks is displayed differently - Make
id
property immutable - Robust query interface for bookmarks via
.get({}, {}, …)
have properties liketags
,urls
, and other bookmark fields. Will use several services to get the aggregate results. ANDs properties in a single query object, and ORs the results of several query objects (need intersection/union operators on bookmarks) - Always return a new data object, do not respect identity
- Add a resolution function to save, in event of out-of-date bookmark:
save({}, { resolve: function (mine, theirs) {
// If you want to clobber changes, just return mine
// if out of date -- or can only overwrite something like
// the tags property. Whatever is returned is saved.
return mine;
}})
- Remove
createBookmark
and similar methods (should just haveBookmark
which instantiates a data structureish class) - Remove
index
on Bookmark items ???? - Hide
id
??? - Map
v0
tov1
since a new bookmark will not have an updated time, so we'll need to map the initial save to the initial data structure to infer if conflict resolution is necessary - Remove
delete/remove
functions -- done via a variable likebookmark.removed = true
and passed intosave
method - remove
removeAllChildren
andgetChildren
-- can be done with a query with agroup
property - Recursively save group dependencies when saving bookmarks if needed (save the parent if it doesn't exist while saving a bookmark)
- remove
isBookmarked
-- can be done with a URL query - Support splats
- Remove
Tags
module -- roll into module withSet
s - Prevent duplicate creation (?)
-
Phase 1
- Provide easy to use API for CRUD, querying History and Bookmarks
-
Phase 2
- Hook Bookmark instances to platform observers (nsINavBookmarkObserver)
- How are keywords used?
- Should Backup/Restore be implemented? backup/restore
Bookmark contains static methods to create, update and manipulate bookmark items like bookmarks, folders and separators. Bookmark
, Group
and Separator
classes all are considered BookmarkItem
types.
- @param {Object} properties
- @return {Bookmark}
Takes an object of properties, and returns a new Bookmark
object.
-
String title
: required The name of the bookmark -
String|URL url
: required the url (either as aString
orURL
instance) -
Group group
: TheGroup
instance that the bookmark should live under. (Default: the menu folder) -
Number index
: The position of the bookmark within its parent. Defaults to the last position. (Default: -1) MAY BE REMOVED -
Set tags
: ASet
of tags.
let { Bookmark } = require('bookmark');
Bookmark({
title: 'Mozilla',
url: 'http://www.mozilla.org
});
- @param {Object} properties
- @return {Group}
Takes an object of properties, and returns a new Group
object.
-
String title
: required The name of the group -
Group group
: TheGroup
instance that the group should live under. (Default: the menu folder) -
Number index
: The position of the bookmark within its parent. Defaults to the last position. (Default: -1) MAY BE REMOVED
- @param {Object} properties
- @return {Separator}
Takes an object of properties, and returns a new Separator
object.
-
Group group
: TheGroup
instance that the separator should live under. (Default: the menu folder) -
Number index
: The position of the separator within its parent. Defaults to the last position. (Default: -1) MAY BE REMOVED
- @param {BookmarkItems|Array} …items
- @param {Object} options
- @return {Promise}
Pushes properties of items
to their platform counterparts -- returns a promise that resolves to new instances of these items upon saving.
Options object has one property, resolve
, which is a function accepting mine
and theirs
arguments, which are the item attempting to save and the item currently saved on the platform. resolve
is called if attempting to save a BookmarkItem
that has been updated since the object was fetched from the platform to perform a manual diff.
let { Bookmark, save } = require('bookmarks');
var bookmarks = [
{ title: "Moz", url: "http://mozilla.org" },
{ title: "Twitter", url: "http://twitter.com" }
].map(Bookmark);
save(bookmarks).then(function (bookmarks) {
// Updated `bookmarks`!
// These instances are new, fresh instances
// and !== the initial bookmarks passed into input
})
Resolving
let { query, save } = require('bookmarks');
query({ url: 'http://mozilla.org' }).then(updateBookmark);
function updateBookmark (bm) {
// So let's update this bookmark, and say the user
// or another add-on has already changed it, so
// this instance is out of date already.
bm.title = "My Moz";
save(bm, {
resolve: function (mine, theirs) {
// Here we can either just choose to
// overwrite the title via
// `theirs.title = mine.title; return theirs;`
// Which will keep the users' changes other
// than the title
// Or we can just completely ignore everything the
// user did and pass all of `bm`s current props:
// `return mine;`
}
})
}
Recursive Saving
let { Bookmark, Group, save } = require('bookmarks');
var g = Group({ title: "Mine" });
var b1 = Bookmark({ url: "http://foo", title: "foo", group: g });
var b2 = Bookmark({ url: "http://bar", title: "bar", group: g});
// Since both `b1` and `b2` have `g` as their parent,
// and `g` has not yet been saved, this will first
// save `g`, and then save `b1` and `b2`
save(b1, b2)
- @param {Object} options
- @return {Promise}
Queries can be performed on bookmark items by passing in one or more query options. Each query option can take several properties, which are AND'd together to make one complete query. For additional queries within the query, passing more query options in will OR the total results.
Query options:
** SHOULD THESE BE SINGULAR OR PLURAL? **
** Multiple groups should not be allow within a single query. Other properties are AND'd together, and even properties within itself (multiple tags for example) are AND'd, and while it wouldn't make sense to AND groups, following this pattern makes more sense **
-
String|Array tags
: Bookmarks with corresponding tags -
String|Array urls
: URLs that should match bookmarks -
Group group
: Group instances that should be owners of the returned children bookmarks -
String query
: Search terms to search url, title
More properties may be added via the HistoryQuerying service, such as searching titles.
let { query } = require('bookmarks');
// Assume we have group `g1`
// This query gives us all bookmarks with tag 'mozilla'
// that are children of `g1`.
query({
tags: 'mozilla',
group: g1
})
// If we wanted to get the children of g1
// that have tag 'mozilla' OR a bookmark anywhere that
// has tag 'firefox', we can make two query options that
// are OR'd together
query({
tags: 'mozilla',
group: g1
}, {
tags: 'firefox'
})
// Similar to the last query, we can all bookmarks that
// are children of `g1` that have BOTH the 'mozilla' and
// 'firefox' tag, as all the properties within a query
// are AND'd together
query({
tags: ['mozilla', 'firefox'],
group: g1
})
- @param {Bookmark|Folder|Separator|Array} items
- @return {Promise}
Removes the platform's bookmark based off of item
's ID.
let { remove } = require('bookmark');
let item = someQueryReturningAnItem();
remove(item).then(function () {
console.log('removed');
})
Here are some platform methods converted to using this API
let p = query({ query: 'my-folder' })
p.then((res) => query({ group: res[0] }))
query({ url: 'http://mozilla.org' })
query({ tags: 'firefox' })
function isBookmarked (url) {
let deferred = defer();
query({ url: 'http://mozilla.org' }).then((x) => {
deferred.resolve(!!x.length);
}, deferred.reject)
return deferred.promise;
}
These constants store the IDs of default folders and are used in other methods in Folder
and Bookmark
Bookmark.MENU
Bookmark.PLACES
Bookmark.TAGS
Bookmark.TOOLBAR
Bookmark.UNSORTED
-
id
readonly index
title
url
group
tags
-
id
readonly index
title
group
tags
-
id
readonly index
group
- @param {Object} options
- @return {Promise}
Returns a promise for an array of history items that match the query's options
.
-
String sort
: A string to specify the type of sort to use. Possible options:'title'
,'date'
,'url'
,'visitCount'
,'keyword'
,'dateAdded'
,'lastModified'
. Default is unsorted. -
Boolean ascending
: Whether or not the sorted results should be ascending. Default isfalse
, which returns the results in a descending order. Has no effect ifsort
is undefined. -
Number count
: Upper limit of how many items are returned. Default is no limit. -
Date|Number from
: Time relative from the epoch that history results should be limited to occuring after. Can accept aDate
object, or milliseconds from the epoch. Default is from the epoch (all time). -
Date|Number to
: Time relative from the epoch that history results should be limited to occuring before. Can accept aDate
object, or milliseconds from the epoch. Default is the current time. -
String query
: Search terms to match history results withquery
in its URL or title. -
String domain
: Limit results that originated from a specific domain. Can limit to whendomain
is only the host, like'mozilla.org'
, or specify that subdomains are allowed like'*.mozilla.org'
.
let { query } = require('sdk/places/history');
query({
sort: 'date',
count: 15,
from: new Date('1/1/2006'),
to: new Date('12/31/2006')
}).then(function (items) {
// `items` contain the first 15 results
// from the year 2006 in order
})