Created
August 17, 2010 02:00
-
-
Save johan/528134 to your computer and use it in GitHub Desktop.
Like the chrome.bookmarks.onRemoved.addListener call at http://code.google.com/chrome/extensions/bookmarks.html#event-onRemoved but guaranteed to fire even if the onremove event fired on a containing folder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// makes sure fn gets called when bm_id is removed, whether it was a direct kill | |
// or it got caught in collateral damage from a recursive bookmark removal spree | |
function addBookmarkRemoveListener(bm_id, fn) { | |
// as we won't get an onRemoved callback for bm_id when any of its parents got | |
// removed recursively, keep a list of all its parents to know when to fire fn | |
function indexParentsFor(bm_id, bookmarks) { | |
function bookmarkParents(id, bms, path) { | |
////console.log('bookmarkParents(', id, bms, path, ')'); | |
for (var i = 0, bm, found; bm = bms[i]; i++) { | |
if (bm.id === id) return path; | |
if (bm.url) continue; | |
if ((found = bookmarkParents(id, bm.children, path.concat(bm.id)))) { | |
//console.info('found: ', found, ')'); | |
return found; | |
} | |
} | |
return null; | |
} | |
///console.log('indexParentsFor(', bm_id, bookmarks, ')'); | |
return parent_ids[bm_id] = bookmarkParents(bm_id, bookmarks, []); | |
} | |
function register(bm_id, fn) { | |
//console.log('addBookmarkRemoveListener.register(', bm_id, fn, ')'); | |
var parents = parent_ids[bm_id]; | |
if (parents) { // already indexed? | |
if (!parents.some(strictlyEquals(fn))) | |
callbacks[bm_id].push(fn); | |
} | |
else { | |
callbacks[bm_id] = (callbacks[bm_id] || []).concat(fn); | |
chrome.bookmarks.getTree(function(bms) { indexParentsFor(bm_id, bms); }); | |
} | |
} | |
function strictlyEquals(x) { return function(y) { return x === y; }; } | |
// array of all bm_id:s we are tracking | |
function idsTracked() { | |
var ids = []; | |
for (var id in parent_ids) | |
if (Number(id) !== NaN) | |
ids.push(id); | |
return ids; | |
} | |
// refresh parent_id cache post-move | |
function onMove(bm_id, info) { | |
//console.log('onMove(', bm_id, info, ')'); | |
function reindex(bookmarks) { | |
for (var i = 0, id, ids = idsTracked(); id = ids[i]; i++) { | |
indexParentsFor(bm_id, bookmarks); | |
} | |
} | |
chrome.bookmarks.getTree(reindex); | |
} | |
// when one or more of the bookmarks we track is removed, call their listeners | |
// and remove their associated data from our list of tracked ids and callbacks | |
function onRemove(bm_id, info) { | |
//console.log('onRemove(', bm_id, info, ')'); | |
var is_bm_id = strictlyEquals(bm_id); | |
for (var i = 0, id, ids = idsTracked(); id = ids[i]; i++) { | |
if (id !== bm_id && !parent_ids[id].some(is_bm_id)) continue; | |
for (var j = 0, fn, fns = callbacks[id]; fn = fns[j]; j++) | |
fn(bm_id, Object.create(info)); | |
delete parent_ids[id]; | |
delete callbacks[id]; | |
} | |
} | |
var self = addBookmarkRemoveListener, | |
callbacks = self.callbacks = self.callbacks || {}, // id => array<fn> | |
parent_ids = self.parent_ids = self.parent_ids || {}; // id => array<id> | |
self.onMove = self.onMove || // only add our listener for onMoved once | |
(onMove, chrome.bookmarks.onMoved.addListener(onMove)); // reindex bookmarks | |
self.onRemoved = self.onRemove || // only add our listener for onRemoved once | |
(onRemove, chrome.bookmarks.onRemoved.addListener(onRemove)); // real worker | |
register(bm_id, fn); // index the parents for this bm_id and register its fn | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment