gecko/mobile/chrome/content/bindings.xml

1207 lines
41 KiB
XML
Raw Normal View History

<?xml version="1.0"?>
<!DOCTYPE bindings [
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
%browserDTD;
]>
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="autocomplete-aligned" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<implementation>
<method name="openPopup">
<body><![CDATA[
this.popup.openAutocompletePopup(this, null);
this.setAttribute("open", "true");
]]></body>
</method>
<method name="closePopup">
<body><![CDATA[
this.removeAttribute("open");
// hack! we want to revert to the "all results" popup when the
// controller would otherwise close us because of an empty search
// string.
if (this.value == "")
this.showHistoryPopup();
]]></body>
</method>
</implementation>
<handlers>
<handler event="keypress" keycode="VK_RETURN" phase="capturing">
<![CDATA[
if (this.popup.allBookmarksItemSelected) {
this.popup.closePopup();
CommandUpdater.doCommand("cmd_bookmarks");
}
]]>
</handler>
</handlers>
</binding>
<binding id="popup_autocomplete_result">
<content orient="vertical">
<xul:hbox class="autocomplete-item-label" align="top" xbl:inherits="tags, favorite" mousethrough="always">
<xul:image xbl:inherits="src"/>
<xul:vbox flex="1">
<xul:label crop="center" xbl:inherits="value"/>
<xul:label class="autocomplete-item-url" xbl:inherits="value=url" crop="center" mousethrough="always"/>
</xul:vbox>
</xul:hbox>
</content>
</binding>
<binding id="popup_autocomplete">
<content>
<xul:vbox class="autocomplete-box" flex="1">
<!-- 24 child items, to match browser.urlbar.maxRichResults -->
<xul:scrollbox orient="vertical"
class="autocomplete-items"
anonid="autocomplete-items"
flex="1000">
<xul:autocompleteresult anonid="allbookmarks"
value="&allBookmarks.label;"
class="allbookmarks"/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
<xul:autocompleteresult/>
</xul:scrollbox>
<children/>
</xul:vbox>
</content>
<implementation implements="nsIAutoCompletePopup">
<!-- Used by the chrome input handler -->
<property name="boxObject"
readonly="true"
onget="return this._items.boxObject;"/>
<field name="_scrollBoxObject">
this.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
</field>
<!-- nsIAutocompleteInput -->
<property name="overrideValue"
readonly="true"
onget="return null;"/>
<field name="_input"/>
<property name="input"
readonly="true"
onget="return this._input;"/>
<field name="_selectedIndex">-1</field>
<field name="_selectedItem"/>
<property name="selectedIndex"
onget="return this._allBookmarksItem._hidden ? this._selectedIndex : this._selectedIndex - 1;">
<setter><![CDATA[
// Ignore invalid indices
if (val < -1 ||
val > this._matchCount - 1)
return val;
if (this._selectedItem)
this._styleItem(this._selectedItem, false);
// highlight the selected item
let item = this._items.childNodes.item(val);
if (item) {
this._selectedItem = item;
this._styleItem(this._selectedItem, true);
this._scrollBoxObject.ensureElementIsVisible(this._selectedItem);
}
return this._selectedIndex = val;
]]></setter>
</property>
<field name="_popupOpen">false</field>
<property name="popupOpen"
readonly="true"
onget="return this._popupOpen;"/>
<method name="openAutocompletePopup">
<parameter name="aInput"/>
<parameter name="aElement"/>
<body><![CDATA[
if (this._popupOpen)
return;
BrowserUI.pushDialog(this);
this._selectedItem = null;
this._input = aInput;
this._input.select();
if (this.hidden)
this.hidden = false;
this.collapsed = false;
this._popupOpen = true;
this.invalidate();
let event = document.createEvent("Events");
event.initEvent("popupshown", true, false);
this.dispatchEvent(event);
]]></body>
</method>
<method name="closePopup">
<body><![CDATA[
if (!this._popupOpen)
return;
this.selectedIndex = -1;
this.input.controller.stopSearch();
this.collapsed = true;
this._popupOpen = false;
let event = document.createEvent("Events");
event.initEvent("popuphidden", true, false);
this.dispatchEvent(event);
BrowserUI.showToolbar(false);
BrowserUI.popDialog();
]]></body>
</method>
<method name="scrollToTop">
<body><![CDATA[
if (this._items.scrollTop || this._items.scrollLeft)
this._scrollBoxObject.scrollTo(0, 0);
]]></body>
</method>
<!-- Helper used by active dialog system -->
<method name="close">
<body><![CDATA[
this.input.reset();
this.input.blur();
this.closePopup();
]]></body>
</method>
<field name="_XULNS">("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")</field>
<method name="invalidate">
<body><![CDATA[
// Don't bother doing work if we're not even open
if (!this.popupOpen)
return;
let controller = this.input.controller;
let searchString = controller.searchString;
let items = this._items;
// Remove the allBookmarksItem if present, before populating the list.
if (!this._allBookmarksItem._hidden) {
items.removeChild(this._allBookmarksItem);
this._allBookmarksItem._hidden = true;
}
// Need to iterate over all our existing entries at a minimum, to make
// sure they're either updated or cleared out. We might also have to
// add extra items.
let matchCount = this._matchCount;
let children = items.childNodes;
let iterCount = Math.max(children.length, matchCount);
for (let i = 0; i < iterCount; ++i) {
let item = children.item(i);
// Create an item if needed
if (!item) {
item = document.createElementNS(this._XULNS, "xul:autocompleteresult");
items.appendChild(item);
}
item._index = i;
// Check whether there's an entry to fill
if (i > matchCount - 1) {
// Just clear out the old item's value. CSS takes care of hiding
// everything else based on value="" (star, tags, etc.)
item.setAttribute("value", "");
item._empty = true;
continue;
}
item._empty = false;
// Assign the values
let type = controller.getStyleAt(i);
let title = controller.getCommentAt(i);
let tags = '';
if (title && type == "tag")
[, title, tags] = title.match(/^(.+) \u2013 (.+)$/);
item.setAttribute("tags", tags);
let url = controller.getValueAt(i);
item.setAttribute("value", title || url);
item.setAttribute("url", url);
let isBookmark = ((type == "bookmark") || (type == "tag"));
item.setAttribute("favorite", isBookmark);
item.setAttribute("src", controller.getImageAt(i));
}
// Show the "no results" or "all bookmarks" entries as needed
this._updateNoResultsItem(matchCount);
if (searchString == "") {
items.insertBefore(this._allBookmarksItem, items.firstChild);
this._allBookmarksItem._hidden = false;
}
// Make sure the list is scrolled to the top
this.scrollToTop();
]]></body>
</method>
<method name="_updateNoResultsItem">
<parameter name="isResults" />
<body><![CDATA[
let noResultsItem = this._items.childNodes.item(1);
if (isResults) {
noResultsItem.className = "";
}
else {
noResultsItem.className = "noresults";
noResultsItem.setAttribute("value", "]]>&noResults.label;<![CDATA[");
noResultsItem.removeAttribute("favorite");
noResultsItem.removeAttribute("url");
noResultsItem.removeAttribute("src");
noResultsItem.removeAttribute("tags");
}
]]></body>
</method>
<field name="_allBookmarksItem">document.getAnonymousElementByAttribute(this, "anonid", "allbookmarks");</field>
<property name="allBookmarksItemSelected" readonly="true"
onget="return this._selectedItem == this._allBookmarksItem;"/>
<method name="selectBy">
<parameter name="aReverse"/>
<parameter name="aPage"/>
<body><![CDATA[
let newIndex;
let lastIndex = this._matchCount - 1;
if (this._selectedIndex == -1)
newIndex = aReverse ? lastIndex : 0;
else
newIndex = this._selectedIndex + (aReverse ? -1 : 1);
// Deal with rollover
if (newIndex > lastIndex)
newIndex = 0;
else if (newIndex < 0)
newIndex = lastIndex;
this.selectedIndex = newIndex;
]]></body>
</method>
<!-- Helpers -->
<field name="_items">
document.getAnonymousElementByAttribute(this,
"anonid", "autocomplete-items");
</field>
<property name="_matchCount"
readonly="true">
<getter><![CDATA[
let matchCount = this.input.controller.matchCount;
return matchCount + (this._allBookmarksItem._hidden ? 0 : 1);
]]></getter>
</property>
<method name="_styleItem">
<parameter name="aItem"/>
<parameter name="aAddStyle"/>
<body><![CDATA[
if (aAddStyle)
aItem.className += " autocompleteresult-selected";
else
aItem.className = aItem.className.replace(/\s*autocompleteresult-selected/, "");
]]></body>
</method>
</implementation>
<handlers>
<handler event="click" button="0">
<![CDATA[
let target = event.originalTarget;
if (target == this._allBookmarksItem) {
this._selectedIndex = 0;
this.close();
CommandUpdater.doCommand("cmd_bookmarks");
}
else if (target.localName == "autocompleteresult" && !target._empty) {
let offset = this._allBookmarksItem._hidden ? 0 : 1;
this._selectedIndex = target._index + offset;
this.input.controller.handleEnter(true);
}
]]>
</handler>
</handlers>
</binding>
<binding id="place-base">
<content/>
<handlers>
<handler event="click" button="0">
<![CDATA[
if (this.control)
this.control._fireOpen(event, this);
]]>
</handler>
<handler event="contextmenu" phase="capturing">
<![CDATA[
if (!this.uri)
return;
let data = {
target: this,
json: {
2010-07-29 17:19:29 -07:00
types: ["edit-bookmark"],
label: this.uri.spec
}};
ContextHelper.showPopup(data);
]]>
</handler>
</handlers>
<implementation>
<field name="_uri">null</field>
<field name="_control">null</field>
<field name="_isEditing">false</field>
<field name="_nameField">
document.getAnonymousElementByAttribute(this, "anonid", "name");
</field>
<field name="_uriField">
document.getAnonymousElementByAttribute(this, "anonid", "uri");
</field>
<field name="_tagsField">
document.getAnonymousElementByAttribute(this, "anonid", "tags");
</field>
<property name="itemId" onget="return this.getAttribute('itemid');"/>
<property name="type" onget="return this.getAttribute('type');"/>
<property name="uri">
<getter><![CDATA[
if (!this._uri && this.getAttribute("uri"))
this._uri = Services.io.newURI(this.getAttribute("uri"), null, null);
return this._uri;
]]></getter>
</property>
<property name="name" onget="return this._nameField.value"
onset="this._nameField.value = val; return val;"/>
<property name="spec" onget="return this._uriField.value"
onset="this._uriField.value = val; return val;"/>
<property name="tags" onget="return this._tagsField.value"
onset="this._tagsField.value = val; return val;"/>
<property name="tagsAsArray" readonly="true">
<getter>
<![CDATA[
// we don't require the leading space (after each comma)
var tags = this.tags.split(",");
for (var i = 0; i < tags.length; i++) {
// remove trailing and leading spaces
tags[i] = tags[i].trim();
// remove empty entries from the array.
if (tags[i] == "") {
tags.splice(i, 1);
i--;
}
}
return tags;
]]>
</getter>
</property>
<property name="isEditing" readonly="true" onget="return this._isEditing;"/>
<property name="isReadOnly" readonly="true">
<getter><![CDATA[
return this.control && this.control._readOnlyFolders.indexOf(parseInt(this.itemId, 10)) != -1;
]]></getter>
</property>
<property name="control" readonly="true">
<getter>
<![CDATA[
if (this._control)
return this._control;
let parent = this.parentNode;
while (parent) {
if (parent.localName == "placelist") {
this._control = parent;
return this._control;
}
parent = parent.parentNode;
}
return null;
]]>
</getter>
</property>
<method name="startEditing">
<parameter name="autoSelect"/>
<body>
<![CDATA[
if (!this.itemId || this.isReadOnly)
return;
this._isEditing = true;
if (this.control) {
this.setAttribute("selected", "true");
this.control.scrollBoxObject.ensureElementIsVisible(this);
this.control.activeItem = this;
}
this.updateFields();
this._nameField.focus();
if (autoSelect)
this._nameField.select();
]]>
</body>
</method>
<method name="stopEditing">
<parameter name="shouldSave"/>
<body>
<![CDATA[
if (!this.itemId || this.isReadOnly)
return;
if (shouldSave)
this.save();
this._isEditing = false;
if (this.control && this.control.activeItem) {
this.control.activeItem.removeAttribute("selected");
this.control.activeItem = null;
}
this.updateFields();
let focusedElement = document.commandDispatcher.focusedElement;
if (focusedElement)
focusedElement.blur();
let event = document.createEvent("Events");
event.initEvent("close", false, false);
this.dispatchEvent(event);
]]>
</body>
</method>
<method name="save">
<body>
<![CDATA[
// Update the tags
if (this.uri && this.type != "folder") {
let currentTags = PlacesUtils.tagging.getTagsForURI(this.uri, {});
let tags = this.tagsAsArray;
if (tags.length > 0 || currentTags.length > 0) {
let tagsToRemove = [];
let tagsToAdd = [];
for (let i = 0; i < currentTags.length; i++) {
if (tags.indexOf(currentTags[i]) == -1)
tagsToRemove.push(currentTags[i]);
}
for (let i = 0; i < tags.length; i++) {
if (currentTags.indexOf(tags[i]) == -1)
tagsToAdd.push(tags[i]);
}
if (tagsToAdd.length > 0)
PlacesUtils.tagging.tagURI(this.uri, tagsToAdd);
if (tagsToRemove.length > 0)
PlacesUtils.tagging.untagURI(this.uri, tagsToRemove);
}
this.setAttribute('tags', this.tags);
// If the URI was updated change it in the bookmark, but don't
// allow a blank URI. Revert to previous URI if blank.
let spec = this.spec;
if (spec && this.uri.spec != spec) {
try {
let oldURI = this._uri;
this._uri = Services.io.newURI(spec, null, null);
PlacesUtils.bookmarks.changeBookmarkURI(this.itemId, this.uri);
this.setAttribute('uri', this.spec);
// move tags from old URI to new URI
let tags = this.tagsAsArray;
if (tags.length != 0) {
// only untag the old URI if this is the only bookmark
if (PlacesUtils.getBookmarksForURI(oldURI, {}).length == 0)
PlacesUtils.tagging.untagURI(oldURI, tags);
PlacesUtils.tagging.tagURI(this._uri, tags);
}
}
catch (e) { }
}
if (spec != this.uri.spec)
this.spec = this.uri.spec;
}
// Update the name and use the URI if name is blank
this.name = this.name || this.spec;
this.setAttribute('title', this.name);
PlacesUtils.bookmarks.setItemTitle(this.itemId, this.name);
]]>
</body>
</method>
<method name="remove">
<body>
<![CDATA[
PlacesUtils.bookmarks.removeItem(this.itemId);
// If this was the last bookmark (excluding tag-items and livemark
// children, see getMostRecentBookmarkForURI) for the bookmark's url,
// remove the url from tag containers as well.
if (this.uri && this.type != "folder") {
if (PlacesUtils.getMostRecentBookmarkForURI(this.uri) == -1) {
var tags = PlacesUtils.tagging.getTagsForURI(this.uri, {});
PlacesUtils.tagging.untagURI(this.uri, tags);
}
}
this.stopEditing(false);
let event = document.createEvent("Events");
event.initEvent("BookmarkRemove", true, false);
this.dispatchEvent(event);
if (this.control)
this.control.removeItem(this);
]]>
</body>
</method>
<method name="updateFields">
<body>
<![CDATA[
// implemented by sub classes
]]>
</body>
</method>
</implementation>
</binding>
<binding id="place-item" extends="chrome://browser/content/bindings.xml#place-base">
<content orient="vertical">
<xul:hbox anonid="bookmark-item" class="bookmark-item-label" align="top" flex="1" xbl:inherits="tags" mousethrough="always">
<xul:image xbl:inherits="src"/>
<xul:vbox flex="1">
<xul:label crop="center" xbl:inherits="value=title"/>
<xul:label anonid="bookmark-url" class="bookmark-item-url" xbl:inherits="value=uri" crop="center" mousethrough="always"/>
</xul:vbox>
</xul:hbox>
<xul:hbox anonid="bookmark-manage" class="bookmark-manage" hidden="true" flex="1">
<xul:image xbl:inherits="src"/>
<xul:vbox flex="1">
<xul:vbox flex="1">
<xul:textbox anonid="name" xbl:inherits="value=title"/>
<xul:textbox anonid="uri" xbl:inherits="value=uri"/>
<xul:textbox anonid="tags" xbl:inherits="value=tags" emptytext="&editBookmarkTags.label;"/>
</xul:vbox>
<xul:hbox class="bookmark-controls" align="center">
<xul:spacer flex="1"/>
<xul:button anonid="done-button" class="bookmark-done" label="&editBookmarkDone.label;"
oncommand="document.getBindingParent(this).stopEditing(true)"/>
</xul:hbox>
</xul:vbox>
</xul:hbox>
</content>
<implementation>
<method name="updateFields">
<body>
<![CDATA[
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-item").hidden = this._isEditing;
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-url").hidden = this._isEditing;
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-manage").hidden = !this._isEditing;
]]>
</body>
</method>
</implementation>
</binding>
<binding id="place-folder" extends="chrome://browser/content/bindings.xml#place-item">
<implementation>
<method name="updateFields">
<body>
<![CDATA[
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-item").hidden = this._isEditing;
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-url").hidden = this._isEditing;
this._uriField.hidden = true;
this._tagsField.hidden = true;
document.getAnonymousElementByAttribute(this, "anonid", "bookmark-manage").hidden = !this._isEditing;
]]>
</body>
</method>
</implementation>
</binding>
<binding id="place-label" extends="chrome://browser/content/bindings.xml#place-base">
<handlers>
<handler event="click" button="0">
<![CDATA[
if (this.control)
this.control.openFolder(this.previousSibling.itemId);
]]>
</handler>
</handlers>
<content align="center">
<xul:spacer xbl:inherits="width=indent"/>
<xul:image anonid="favicon" class="bookmark-folder-image"/>
<xul:label anonid="name" crop="end" flex="1" xbl:inherits="value=title"/>
</content>
</binding>
<binding id="place-list">
<content orient="vertical" flex="1">
<xul:vbox anonid="parent-items" class="place-list-parents" />
<xul:richlistbox anonid="child-items" class="place-list-children" flex="1" batch="25"/>
</content>
<implementation>
<constructor>
<![CDATA[
this._type = this.getAttribute("type");
this._mode = this.getAttribute("mode");
this._folderParents = {};
this._folderParents[this._desktopFolderId] = this.mobileRoot;
this._folderParents[PlacesUtils.bookmarks.unfiledBookmarksFolder] = this._desktopFolderId;
this._folderParents[PlacesUtils.bookmarksMenuFolderId] = this._desktopFolderId;
this._folderParents[PlacesUtils.toolbarFolderId] = this._desktopFolderId;
]]>
</constructor>
<field name="_desktopFolderId">-1000</field>
<field name="_desktopFolder"><![CDATA[
({
itemId: this._desktopFolderId, tags: "", uri: "",
title: Elements.browserBundle.getString("bookmarkList.desktop"),
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
})
]]></field>
<field name="_desktopChildren"><![CDATA[
[
{
itemId: PlacesUtils.bookmarks.unfiledBookmarksFolder, tags: "", uri: "",
title: PlacesUtils.bookmarks.getItemTitle(PlacesUtils.bookmarks.unfiledBookmarksFolder),
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
},
{
itemId: PlacesUtils.bookmarksMenuFolderId, tags: "", uri: "",
title: PlacesUtils.bookmarks.getItemTitle(PlacesUtils.bookmarksMenuFolderId),
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
},
{
itemId: PlacesUtils.toolbarFolderId, tags: "", uri: "",
title: PlacesUtils.bookmarks.getItemTitle(PlacesUtils.toolbarFolderId),
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
}
];
]]></field>
<field name="_readOnlyFolders"><![CDATA[
[
this._desktopFolderId,
PlacesUtils.bookmarks.unfiledBookmarksFolder,
PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId
];
]]></field>
<field name="_type"/>
<field name="_mode"/>
<field name="_activeItem">null</field>
<field name="_ignoreEditing">false</field>
<field name="_parents">
document.getAnonymousElementByAttribute(this, "anonid", "parent-items");
</field>
<field name="_children">
document.getAnonymousElementByAttribute(this, "anonid", "child-items");
</field>
<field name="scrollBoxObject">this._children.scrollBoxObject</field>
<property name="items" readonly="true" onget="return this._children.childNodes"/>
<field name="mobileRoot"><![CDATA[
PlacesUtils.annotations.getItemsWithAnnotation("mobile/bookmarksRoot", {})[0];
]]></field>
<property name="isRootFolder" readonly="true">
<getter>
<![CDATA[
let currentFolderId = this._parents.lastChild.itemId;
return currentFolderId == this.mobileRoot;
]]>
</getter>
</property>
<property name="activeItem">
<getter>
<![CDATA[
return this._activeItem;
]]>
</getter>
<setter>
<![CDATA[
if (!this._ignoreEditing) {
if (this._activeItem && this._activeItem.isEditing) {
this._ignoreEditing = true;
this._activeItem.stopEditing(false);
this._ignoreEditing = false;
}
this._activeItem = val;
}
return val;
]]>
</setter>
</property>
<method name="isDesktopFolderEmpty">
<body>
<![CDATA[
let options = PlacesUtils.history.getNewQueryOptions();
options.queryType = options.QUERY_TYPE_BOOKMARKS;
let query = PlacesUtils.history.getNewQuery();
let folders = [ PlacesUtils.bookmarks.unfiledBookmarksFolder,
PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId
];
query.setFolders(folders, 3);
let result = PlacesUtils.history.executeQuery(query, options);
let rootNode = result.root;
rootNode.containerOpen = true;
let isEmpty = !rootNode.childCount;
rootNode.containerOpen = false;
return isEmpty;
]]>
</body>
</method>
<method name="_getChildren">
<parameter name="aFolder"/>
<body>
<![CDATA[
let items = [];
let options = PlacesUtils.history.getNewQueryOptions();
options.queryType = (this._type == "bookmarks" ? options.QUERY_TYPE_BOOKMARKS : options.QUERY_TYPE_HISTORY);
// Exclude "query" items (e.g. "smart folders")
options.excludeQueries = true;
let query = PlacesUtils.history.getNewQuery();
if (aFolder)
query.setFolders([aFolder], 1);
let result = PlacesUtils.history.executeQuery(query, options);
let rootNode = result.root;
rootNode.containerOpen = true;
let cc = rootNode.childCount;
for (var i=0; i<cc; ++i) {
let node = rootNode.getChild(i);
// Ignore separators
if (node.type == node.RESULT_TYPE_SEPARATOR)
continue;
if (this._mode == "folders" && node.type == node.RESULT_TYPE_FOLDER) {
items.push(node);
}
else if (this._mode == "") {
items.push(node);
}
}
rootNode.containerOpen = false;
return items;
]]>
</body>
</method>
<method name="openFolder">
<parameter name="aRootFolder"/>
<body>
<![CDATA[
aRootFolder = aRootFolder || this.mobileRoot;
this._activeItem = null;
let parents = this._parents;
while (parents.firstChild)
parents.removeChild(parents.firstChild);
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var self = this;
let folderId = aRootFolder;
do {
let title;
if (folderId == this._desktopFolderId)
title = this._desktopFolder.title;
else
title = PlacesUtils.bookmarks.getItemTitle(folderId);
let parent = document.createElementNS(XULNS, "placelabel");
parent.setAttribute("class", "bookmark-folder");
parent.setAttribute("itemid", folderId);
parent.setAttribute("indent", 0);
parent.setAttribute("title", title);
parents.insertBefore(parent, parents.firstChild);
folderId = this._folderParents[folderId] || PlacesUtils.bookmarks.getFolderIdForItem(folderId);
} while (folderId != PlacesUtils.bookmarks.placesRoot)
let children = this._children;
while (children.firstChild)
children.removeChild(children.firstChild);
children.scrollBoxObject.scrollTo(0, 0);
let items = (aRootFolder == this._desktopFolderId) ? this._desktopChildren.concat()
: this._getChildren(aRootFolder);
if (aRootFolder == this.mobileRoot && !this.isDesktopFolderEmpty())
items.unshift(this._desktopFolder);
children.setItems(items.map(this.createItem));
]]>
</body>
</method>
<method name="createItem">
<parameter name="aItem"/>
<body>
<![CDATA[
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let child = document.createElementNS(XULNS, "placeitem");
child.setAttribute("itemid", aItem.itemId);
child.setAttribute("class", "bookmark-item");
child.setAttribute("title", aItem.title);
child.setAttribute("uri", aItem.uri);
child.setAttribute("tags", aItem.tags);
if (aItem.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER)
child.setAttribute("type", "folder");
else
child.setAttribute("src", aItem.icon);
return child;
]]>
</body>
</method>
<method name="removeItem">
<parameter name="aItem"/>
<body>
<![CDATA[
this._children.removeChild(aItem);
]]>
</body>
</method>
<method name="_fireOpen">
<parameter name="aEvent"/>
<parameter name="aItem"/>
<body>
<![CDATA[
let target = aEvent.originalTarget;
if (target.localName == "button" || this._activeItem == aItem)
return;
if (aItem.type == "folder") {
this.openFolder(aItem.itemId);
}
else {
// Force the item to be active
this._activeItem = aItem;
// This is a callback used to forward information to some
// external code [we fire an event & a pseudo attribute event]
let event = document.createEvent("Events");
event.initEvent("BookmarkOpen", true, false);
this.dispatchEvent(event);
let func = new Function("event", this.getAttribute("onopen"));
func.call(this, event);
}
]]>
</body>
</method>
</implementation>
</binding>
<binding id="richlistbox-batch" extends="chrome://global/content/bindings/richlistbox.xml#richlistbox">
<handlers>
<handler event="scroll">
<![CDATA[
// if there no more items to insert, just return early
if (this._items.length == 0)
return;
if (this._contentScrollHeight == -1) {
let scrollheight = {};
this.scrollBoxObject.getScrolledSize({}, scrollheight);
this._contentScrollHeight = scrollheight.value;
}
let y = {};
this.scrollBoxObject.getPosition({}, y);
let scrollRatio = (y.value + this._childrenHeight) / this._contentScrollHeight;
// If we're scrolled 80% to the bottom of the list, append the next
// set of items
if (scrollRatio > 0.8)
this._insertItems();
]]>
</handler>
</handlers>
<implementation>
<!-- Number of elements to add to the list initially. If there are more
than this many elements to display, only add them to the list once
the user has scrolled towards them. This is a performance
optimization to avoid locking up while attempting to append hundreds
of nodes to our richlistbox.
-->
<property name="batchSize" readonly="true" onget="return this.getAttribute('batch')"/>
<field name="_childrenHeight">this.scrollBoxObject.height;</field>
<field name="_items">[]</field>
<method name="setItems">
<parameter name="aItems"/>
<body><![CDATA[
this._items = aItems;
this._insertItems();
]]></body>
</method>
<method name="_insertItems">
<body><![CDATA[
let items = this._items.splice(0, this.batchSize);
if (!items.length)
return; // no items to insert
let count = items.length;
for (let i = 0; i<count; i++)
this.appendChild(items[i]);
// make sure we recalculate the scrollHeight of the content
this._contentScrollHeight = -1;
]]></body>
</method>
</implementation>
</binding>
<binding id="richlistitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<handlers>
<handler event="mousedown" phase="capturing">
<![CDATA[
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
<binding id="content-navigator">
<content pack="end">
<children includes="vbox"/>
<xul:hbox class="content-navigator-box panel-dark" pack="end">
<children includes="textbox|arrowscrollbox"/>
<xul:toolbarbutton anonid="previous-button" class="content-navigator-item button-image previous-button" xbl:inherits="command=previous"/>
<xul:toolbarbutton anonid="next-button" class="content-navigator-item button-image next-button" xbl:inherits="command=next"/>
</xul:hbox>
</content>
<implementation>
<field name="_previousButton">
document.getAnonymousElementByAttribute(this, "anonid", "previous-button");
</field>
<field name="_nextButton">
document.getAnonymousElementByAttribute(this, "anonid", "next-button");
</field>
<field name="_spacer">
document.getElementById(this.getAttribute("spacer"));
</field>
<method name="contentHasChanged">
<body><![CDATA[
let height = Math.floor(this.getBoundingClientRect().height);
this.top = window.innerHeight - height;
this._spacer.setAttribute("height", height);
]]></body>
</method>
<field name="_model">null</field>
<method name="show">
<parameter name="aModel" />
<body><![CDATA[
// call the hide callback of the current object if any
if (this._model && this._model.type != aModel.type)
this._model.hide();
this.setAttribute("type", aModel.type);
this.setAttribute("next", aModel.commands.next);
this.setAttribute("previous", aModel.commands.previous);
this.setAttribute("close", aModel.commands.close);
// buttons attributes sync with commands doesn not look updated when
// we dynamically switch the "command" attribute so we need to ensure
// the disabled state of the buttons is right when switching commands
this._previousButton.disabled = document.getElementById(aModel.commands.previous).disabled;
this._nextButton.disabled = document.getElementById(aModel.commands.next).disabled;
this._model = aModel;
this.contentHasChanged();
this._spacer.hidden = false;
]]></body>
</method>
<method name="hide">
<parameter name="aModel" />
<body><![CDATA[
this.removeAttribute("next");
this.removeAttribute("previous");
this.removeAttribute("close");
this.removeAttribute("type");
this._model = null;
this._spacer.hidden = true;
// give the form spacer area back to the content
// XXX this should probably be removed with layers
Browser.forceChromeReflow();
Browser.contentScrollboxScroller.scrollBy(0, 0);
Browser._browserView.onAfterVisibleMove();
]]></body>
</method>
</implementation>
</binding>
<binding id="menulist" display="xul:box" extends="chrome://global/content/bindings/menulist.xml#menulist">
<handlers>
<handler event="mousedown" phase="capturing">
<![CDATA[
// Stop the normal menupopup from appearing
event.stopPropagation();
]]>
</handler>
<handler event="click" button="0">
<![CDATA[
if (this.disabled || this.itemCount == 0)
return;
this.focus();
let choices = [];
let children = this.menupopup.children;
for (let i = 0; i < children.length; i++) {
let child = children[i];
choices.push({ text: child.label, selected: child.selected, optionIndex: i });
}
let self = this;
let wrapper = {
multiple: false,
choices: choices,
changeCallback: function() {
let evt = document.createEvent("XULCommandEvent");
evt.initCommandEvent("command", true, true, window, 0, false, false, false, false, null);
self.dispatchEvent(evt);
},
selectCallback: function(aIndex) { self.selectedIndex = aIndex; }
};
SelectHelperUI.show(wrapper);
]]>
</handler>
</handlers>
</binding>
<binding id="chrome-select-option">
<content orient="horizontal" flex="1">
<xul:image class="chrome-select-option-image" anonid="check"/>
<xul:label anonid="label" xbl:inherits="value=label"/>
</content>
<implementation>
<property name="selected">
<getter>
<![CDATA[
return this.hasAttribute("selected");
]]>
</getter>
<setter>
<![CDATA[
if (val)
this.setAttribute("selected", "true");
else
this.removeAttribute("selected");
return val;
]]>
</setter>
</property>
</implementation>
</binding>
<binding id="select-button" extends="xul:box">
<content>
<svg:svg width="11px" version="1.1" xmlns="http://www.w3.org/2000/svg" style="position: absolute; top: 35%; margin-left: 4px;">
<svg:polyline points="1 1 5 6 9 1" stroke="#414141" stroke-width="2" stroke-linecap="round" fill="transparent" stroke-linejoin="round"/>
</svg:svg>
</content>
</binding>
</bindings>