| « [Places] nsINavHistoryResultNode からブックマークの各種情報を取得する | JavaScript 関数と XPCOM メソッドの例外ハンドリング » |
[Places] フォルダ内のブックマークを列挙する
Places データベースへの問い合わせ結果から得たブックマークのノードは nsINavHistoryResultNode インタフェースを実装するオブジェクトであるが、ブックマークフォルダは nsINavHistoryContainerResultNode インタフェースも合わせて実装しており、 childCount プロパティで子ノードの数を調べたり、 getChild メソッドで指定したインデックスの子ノードを取得することができる。
例えば、[Places] ビューと nsIPlacesView インタフェース の続きとして、右クリックしたブックマークフォルダ内の子ノードにアクセスするには、以下のようにすればよい。ただし、ビュー上でフォルダが開いていることを前提とする。
// assume that node is instanceof Ci.nsINavHistoryContainerResultNode and is open.
for (var i = 0; i < node.childCount; i++) {
var childNode = node.getChild(i);
}
一方、ビュー上でフォルダが閉じた状態になっている場合、 childCount プロパティなどを使って子ノードへアクセスしようとすると NS_ERROR_NOT_AVAILABLE 例外がスローされる。そこで、ブックマークフォルダのノードの containerOpen プロパティへ true をセットすることで一時的にフォルダを開いてから子ノードへアクセスし、処理が終わった後に false をセットしてフォルダを閉じるようにする。以下は、引数で指定したブックマークフォルダ内のすべてのブックマークを再帰的に取得し、配列として返す関数である。
function flatChildNodes(aNode) {
var ret = [];
var closeOriginally = !aNode.containerOpen;
if (closeOriginally)
// if the folder is closed, open it.
aNode.containerOpen = true;
for (var i = 0; i < aNode.childCount; i++) {
var childNode = aNode.getChild(i);
if (PlacesUtils.nodeIsBookmark(childNode))
ret.push(childNode);
else if (PlacesUtils.nodeIsFolder(childNode) &&
!PlacesUtils.nodeIsLivemarkContainer(childNode))
// call this function recursive
ret = ret.concat(arguments.callee(childNode));
}
if (closeOriginally)
// don't forget to restore the folder's original closed state
aNode.containerOpen = false;
return ret;
}
上記の例では、ビュー上に表示されているブックマークフォルダ、つまりデータベースへの問い合わせ結果が取得済みのブックマークフォルダを対象としていた。ビューへの表示が無い場面でフォルダ内のノードへアクセスするには、データベースへ問い合わせを行う必要がある。通常 Places データベースへの問い合わせを行うには、 nsINavHistoryService#getNewQuery でクエリオブジェクトを生成し executeQuery で実行するという手続きが必要であるが、 PlacesUtils.getFolderContents を使えばより単純なコードでフォルダ内のノードへアクセス可能である。
var result = PlacesUtils.getFolderContents(node.itemId); // nsINavHistoryResult
var parentNode = result.root;
for (var i = 0; i < parentNode.childCount; i++) {
var childNode = parentNode.getChild(i);
}
以下は、ブックマークフォルダの itemId プロパティを引数に、そのフォルダ内の全ブックマークを再帰的に取得して配列として返す関数である。
function flatChildNodes(aItemId) {
var ret = [];
var parentNode = PlacesUtils.getFolderContents(aItemId).root;
for (var i = 0; i < parentNode.childCount; i++) {
var childNode = parentNode.getChild(i);
if (PlacesUtils.nodeIsBookmark(childNode))
ret.push(childNode);
else if (PlacesUtils.nodeIsFolder(childNode) &&
!PlacesUtils.nodeIsLivemarkContainer(childNode))
// call this function recursive
ret = ret.concat(arguments.callee(childNode.itemId));
}
return ret;
}