Draft
This page is not complete.
Controllers are one component of the Places model-view-controller design. They are responsible for enabling, disabling and performing commands based on the state of a Places view.
Although Places provides its own built-in controller, controllers of different purposes are used throughout an application and are not specific to Places. See the Commands and Updating Commands pages in the XUL tutorial for general information about them.
The built-in controller
Places provides a built-in controller, PlacesController
, a prototype defined in browser/components/places/content/controller.js
. The built-in Places views automatically use PlacesController
, so if you use a built-in view, you need not write your own controller, worry about hooking up your view to a controller, or really read the rest of this page. You do, however, need to include PlacesController
's source in your XUL document. The recommended way of doing so is by overlaying browser/components/places/content/placesOverlay.xul
. This file also contains the built-in Places context menu and XUL commandset
. See Displaying Places information using views for more information.
If you have a custom view that supports all the commands that PlacesController
supports and only those commands, you can also use PlacesController
. If your view supports only a subset of those commands, you may still be able to take advantage of PlacesController
; see Creating custom controllers below.
Places commands
Listed below are the commands that PlacesController
supports along with their descriptions.
Many of the commands operate on the nodes that are currently selected in the controller's view. Unless noted otherwise, the selected node is found by reading the selectedNode
property of the view's nsIPlacesView
interface. Because the selectedNode
property assumes that the view is single-selection, commands that rely on selectedNode
also also assume that the view is single-selection and will not work if the view's selection contains multiple nodes.
Some commands insert new nodes into the results of the controller's view. The position in the results at which nodes are inserted is determined by reading the insertionPoint
property of the view's nsIPlacesView
interface.
- placesCmd_deleteDataHost
- Removes all data stored for the selected node's domain by calling
nsIPrivateBrowsingService.removeDataFromDomain()
. - placesCmd_moveBookmarks
- Shows the UI used to move the selected nodes to another folder. The note above about single selection does not apply here; this command calls
nsIPlacesView.getSelectionNodes()
on the view. - placesCmd_new:bookmark
- Shows the UI used to add a new bookmark by calling
PlacesUIUtils.showAddBookmarkUI()
. The new bookmark is inserted at the view's insertion point. If no insertion point exists,NS_ERROR_NOT_AVAILABLE
is thrown. - placesCmd_new:folder
- Shows the UI used to add a new folder by calling
PlacesUIUtils.showAddFolderUI()
. The new folder is inserted at the view's insertion point. If no insertion point exists,NS_ERROR_NOT_AVAILABLE
is thrown. - placesCmd_new:livemark
- Shows the UI used to add a new livemark by calling
PlacesUIUtils.showAddLivemarkUI()
. The new livemark is inserted at the view's insertion point. If no insertion point exists,NS_ERROR_NOT_AVAILABLE
is thrown. - placesCmd_new:separator
- Adds a new separator at the view's current insertion point. If no insertion point exists,
NS_ERROR_NOT_AVAILABLE
is thrown. - placesCmd_open
- Opens the view's selected node in the current tab by calling
PlacesUIUtils.openNodeIn()
. - placesCmd_open:tab
- Opens the view's selected node in a new tab by calling
PlacesUIUtils.openNodeIn()
. - placesCmd_open:window
- Opens the view's selected node in a new window by calling
PlacesUIUtils.openNodeIn()
. - placesCmd_reload
- Reloads the view's selected node if it is a livemark by calling
nsILivemarkService.reloadLivemarkFolder()
. - placesCmd_reloadMicrosummary
- Reloads the view's selected node if it has a microsummary by calling
nsIMicrosummaryService.refreshMicrosummary()
. - placesCmd_show:info
- Shows the UI used to edit the properties of the view's selected node by calling
PlacesUIUtils.showItemProperties()
. - placesCmd_sortBy:name
- Sorts the contents of the view's selected node if it is a folder by calling
nsIPlacesTransactionsService.sortFolderByName()
.
PlacesController
also supports the standard Edit commands:
- cmd_copy
- Copies the view's selected nodes to the clipboard. The note above about single selection does not apply here; this command calls
nsIPlacesView.getSelectionNodes()
on the view.
- cmd_cut
- Copies the view's selected nodes to the clipboard and removes them. The implementation of this command is simply a copy followed by a delete.
- cmd_delete
- Removes the view's selected nodes. The note above about single selection does not apply here; this command calls
nsIPlacesView.getRemovableSelectionNodes()
on the view. - cmd_paste
- Adds the nodes in the clipboard to the view's results at the current insertion point. If no insertion point exists,
NS_ERROR_NOT_AVAILABLE
is thrown. - cmd_redo
- Redoes the last Places transaction by calling
nsITransactionManager.redoTransaction()
on thensIPlacesTransactionsService
instance kept byPlacesUIUtils
. - cmd_selectAll
- Selects all the nodes in the view by calling
nsIPlacesView.selectAll()
on the view. - cmd_undo
- Undoes the last Places transaction by calling
nsITransactionManager.undoTransaction()
on thensIPlacesTransactionsService
instance kept byPlacesUIUtils
.
Creating custom controllers
You will need to write your own controller if you want to use commands that PlacesController
does not support or if you want to handle commands in a way that PlacesController
does not. Otherwise, even if you are writing a custom view, you should save yourself the work and use PlacesController
as is. If you are not familiar with controllers, see the Commands and Updating Commands pages in the XUL tutorial.
If you are writing a controller for a built-in view, you can take advantage of the fact that the view automatically hooks itself up to its own default controller, an instance of PlacesController
. Your custom view need only support the commands that PlacesController
either does not support or supports in ways you wish to override. All other commands will be passed to the view's default controller. To ensure that your controller overrides the default, it must precede the default in the view's list of controllers. (If you are not sure why, see the tutorial links given in the previous paragraph.) The view simply appends its default controller to the end of the list, so you should insert yours by calling the nsIControllers.insertControllerAt()
method with index 0.
The following example creates a controller that supports two commands: placesCmd_open
, which will override the handling of that command by the view's default controller, and aCommandOfMyOwn
, a custom command. All other commands will be handled by the view's default controller:
var controller = { doCommand: function (aCmd) { switch (aCmd) { case "placesCmd_open": alert("No."); break; case "aCommandOfMyOwn": alert("Shrimp and white wine."); break; } }, isCommandEnabled: function (aCmd) { return true; }, onEvent: function (aEventName) {}, supportsCommand: function (aCmd) { return ["placesCmd_open", "aCommandOfMyOwn"].indexOf(aCmd) >= 0; } }; var treeView = document.getElementById("myTreeView"); treeView.controllers.insertControllerAt(0, controller);
If your custom controller is for a custom view, your set of commands includes some of those supported by PlacesController
, and you are happy with the way PlacesController
handles those commands, then you can still rely on PlacesController
to save yourself some work. There are a couple of strategies. You can attach two controllers, one a PlacesController
instance and one a custom, in the way described in the previous paragraphs. Or you can attach a single controller, either an instance of PlacesController
modified to suit your needs or a completely custom controller that delegates to a PlacesController
instance.
The following example creates a PlacesController
object, overrides its handling of the placesCmd_open
command, and falls back on the default actions for all other commands. In this case, because the our hypothetical view's only controller is the custom one we're creating here, it is not important that it precede anything; we therefore add the controller by calling nsIControllers.appendController()
instead of insertControllerAt()
:
var treeView = document.getElementById("myCustomTreeView"); var controller = new PlacesController(treeView); controller._doCommand = controller.doCommand; controller.doCommand = function (aCmd) { if (aCmd === "placesCmd_open") alert("No."); else this._doCommand(aCmd); }; treeView.controllers.appendController(controller);