mozilla

Revision 96332 of Displaying Places information using views

  • Revision slug: Displaying_Places_information_using_views
  • Revision title: Displaying Places information using views
  • Revision id: 96332
  • Created:
  • Creator: adw
  • Is current revision? No
  • Comment 19 words added, 10 words removed

Revision Content

{{ Firefox3() }}

Views are how you display {{ Interface("nsINavHistoryResult") }} objects to the user. Views implement the interface {{ Interface("nsINavHistoryResultViewer") }}.

The built-in views

If you need to show the content of Bookmarks or History in your extension or application, you may want to use the built-in Places Views, which are generic and will save you a lot of time writing basic functionality so that you can focus on building your extension or application.

Available views

Places makes available the following built-in views:

  • Tree
  • Menu
  • Toolbar - uses Menu Views for contained folders

Instantiating in XUL

  
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/"?>

<!-- Include the places stylesheet to get the XBL bindings -->
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>

<!-- You can also include the following stylesheet to apply the
     default styling (such as icons) to the tree -->
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>

<!-- Load the places overlay to include the required JavaScript files 
     as well as the default commands and context menu -->
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>

<!-- Examples of using the views to display History visits from only today -->

<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <!-- Tree View -->
  <tree id="myTree"
        type="places" 
        place="place:queryType=0&amp;sort=8&amp;maxResults=10&amp;beginTimeRef=1&amp;beginTime=0"
        height="200px;" width="200px;">
    <treecols>
      <treecol id="title" flex="1" primary="true"/>
      <treecol id="url" flex="1"/>
    </treecols>
    <treechildren flex="1"/>
  </tree>
  
  <!-- Menu View -->
  <menubar>
    <menu id="myMenu" label="My Menu">
      <menupopup type="places"
        place="place:queryType=0&amp;sort=8&amp;maxResults=10&amp;beginTimeRef=1&amp;beginTime=0"/>
    </menu>
  </menubar>
  
  <!-- Toolbar View -->
  <toolbox>
    <toolbar>
      <toolbaritem id="myToolbaritem">
        <hbox type="places"
              place="place:queryType=0&amp;sort=8&amp;maxResults=10&amp;beginTimeRef=1&amp;beginTime=0"/>
      </toolbaritem>
    </toolbar>
  </toolbox>
</window>

Script Hookup

var view = document.getElementById("your_view");
view.init(null);
view.appendController(PlacesController);

The View is initialized with null (the default View Configuration - for options, read Places:View Configurations for more information on using the ViewConfig object to modify a View's functionality), and the Controller is attached. The View is now ready to use.

The PlacesView Interface

For information about interacting with the View through the PlacesView interface, read The PlacesView interface.

The Built-In Tree View

The most common type of view is in a tree control, but it is also relatively difficult to implement. Therefore, Places provides a built-in view object for when you want to display a result in a tree. The object, PlacesTreeView, is implemented in {{ Source("browser/components/places/content/treeView.js") }}.

The view recognizes certain magic values of the id attribute on your treecol elements.  It uses these values to select properties of the nsINavHistoryResultNode objects corresponding to each row of your tree.  Each property is bound to a column using an id attribute.  The following table shows the mappings between these magic id values and their corresponding nsINavHistoryResultNode properties:

treecol id or anonid Corresponding nsINavHistoryResultNode property
title title
url
uri
date
time
visitCount
accessCount
keyword *
description *
dateAdded
dateAdded
lastModified
lastModified
tags
tags

*keyword and description are looked up in the Places database using the nsINavHistoryResultNode property itemId.

In lieu of setting an id on a treecol, you may specify an anonid attribute.  This is useful when a treecol is contained in anonymous content, as in XBL.  If both an id attribute and anonid attribute are specified, the anonid is used.

As with all Places views, the built-in tree view implements nsINavHistoryResultViewer, and because it is a tree view, it also implements {{ Source("/layout/xul/base/src/tree/public/nsITreeView.idl", "nsITreeView") }}. You can therefore use this object to bridge between a result (see Querying Places) and a tree:

var result = historyService.executeQuery(...); // your Places query result
var tree = document.getElementById("mytree"); // your tree control

var showRootNodeInTree = true;
var treeviewer = new PlacesTreeView(showRootNodeInTree);

result.viewer = treeviewer;
tree.view = treeviewer.QueryInterface(Components.interfaces.nsITreeView);

The built-in tree view also allows observers to attach that implement nsINavHistoryResultViewObserver (declared in {{ Source("toolkit/components/places/public/nsINavHistoryService.idl", "nsINavHistoryService.idl") }}). This observer interface allows external components to see what is happening and to take appropriate action. For the Places trees, the controller attaches and, for example, notices when something has been drag-and-dropped on the tree. It then takes the appropriate action.

Creating custom views

If you need greater flexibility or to provide a customized appearance for your display of Places information, you can create a custom view to do so.

Registering a view

Register the view by setting the viewer attribute on nsINavHistoryResult. When you do this, the result will in turn set the result attribute on the given view. You should not set the result attribute on the view explicitly. To clear the view, set the viewer attribute to null. This will cause the view's result attribute to be set to null as well.

Be careful about reference cycles. The view and the result both hold owning references to each other. For these objects to be deleted, you must clear this cycle, by setting result.viewer to null. The built-in tree view (see below) does this automatically. When the tree is destroyed or a different nsITreeView is associated with the tree, the tree will call nsITreeView.tree = null; The viewer detects this case and also detaches itself from the result.

Implementing a view

If you require a customized tree view, it may be easiest to wrap the nsINavHistoryResultTreeViewer in your own class. For example, if you wanted a "special" first row, your object would provide nsITreeView responses for the first row, and pass all other messages through to the built-in tree view with indices shifted by one.

The attribute nsINavHistoryResultNode.viewIndex is provided explicitly for the use of the view. These values are initialized to -1 when each node is created. You can use this value to keep track of visible nodes. The built-in tree viewer uses this attribute to store the row index that the node is on.

The nsINavHistoryResultViewer also has an observer interface to allow an nsINavHistoryResultViewObserver to observer changes. However, this observer interface is specifically for trees. The {{ Bug("337638") }} is for moving this to the nsINavHistoryResultTreeViewer object. Other implementors if nsINavHistoryResultViewer should use their own observers.

See also

{{ languages( { "ja": "ja/Displaying_Places_information_using_views" } ) }}

Revision Source

<p>{{ Firefox3() }}</p>
<p>Views are how you display {{ Interface("nsINavHistoryResult") }} objects to the user. Views implement the interface {{ Interface("nsINavHistoryResultViewer") }}.</p>
<h2 name="The_built-in_views">The built-in views</h2>
<p>If you need to show the content of Bookmarks or History in your extension or application, you may want to use the built-in Places Views, which are generic and will save you a lot of time writing basic functionality so that you can focus on building your extension or application.</p>
<h3 name="Available_views">Available views</h3>
<p>Places makes available the following built-in views:</p>
<ul> <li>Tree</li> <li>Menu</li> <li>Toolbar - uses Menu Views for contained folders</li>
</ul>
<h3 name="Instantiating_in_XUL">Instantiating in XUL</h3>
<pre>  
&lt;?xml version="1.0"?&gt;
&lt;?xml-stylesheet href="chrome://global/skin/"?&gt;

&lt;!-- Include the places stylesheet to get the XBL bindings --&gt;
&lt;?xml-stylesheet href="chrome://browser/content/places/places.css"?&gt;

&lt;!-- You can also include the following stylesheet to apply the
     default styling (such as icons) to the tree --&gt;
&lt;?xml-stylesheet href="chrome://browser/skin/places/places.css"?&gt;

&lt;!-- Load the places overlay to include the required JavaScript files 
     as well as the default commands and context menu --&gt;
&lt;?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?&gt;

&lt;!-- Examples of using the views to display History visits from only today --&gt;

&lt;window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&gt;

  &lt;!-- Tree View --&gt;
  &lt;tree id="myTree"
        type="places" 
        place="place:queryType=0&amp;amp;sort=8&amp;amp;maxResults=10&amp;amp;beginTimeRef=1&amp;amp;beginTime=0"
        height="200px;" width="200px;"&gt;
    &lt;treecols&gt;
      &lt;treecol id="title" flex="1" primary="true"/&gt;
      &lt;treecol id="url" flex="1"/&gt;
    &lt;/treecols&gt;
    &lt;treechildren flex="1"/&gt;
  &lt;/tree&gt;
  
  &lt;!-- Menu View --&gt;
  &lt;menubar&gt;
    &lt;menu id="myMenu" label="My Menu"&gt;
      &lt;menupopup type="places"
        place="place:queryType=0&amp;amp;sort=8&amp;amp;maxResults=10&amp;amp;beginTimeRef=1&amp;amp;beginTime=0"/&gt;
    &lt;/menu&gt;
  &lt;/menubar&gt;
  
  &lt;!-- Toolbar View --&gt;
  &lt;toolbox&gt;
    &lt;toolbar&gt;
      &lt;toolbaritem id="myToolbaritem"&gt;
        &lt;hbox type="places"
              place="place:queryType=0&amp;amp;sort=8&amp;amp;maxResults=10&amp;amp;beginTimeRef=1&amp;amp;beginTime=0"/&gt;
      &lt;/toolbaritem&gt;
    &lt;/toolbar&gt;
  &lt;/toolbox&gt;
&lt;/window&gt;

</pre>
<h3 name="Script_Hookup">Script Hookup</h3>
<pre>var view = document.getElementById("your_view");
view.init(null);
view.appendController(PlacesController);
</pre>
<p>The View is initialized with <code>null</code> (the default View Configuration - for options, read <a href="/en/Places/View_Configurations" title="en/Places/View_Configurations">Places:View Configurations</a> for more information on using the ViewConfig object to modify a View's functionality), and the <a href="/En/Places/View_Controller" title="En/Places/View_Controller">Controller</a> is attached. The View is now ready to use.</p>
<h3 name="The_PlacesView_Interface">The PlacesView Interface</h3>
<p>For information about interacting with the View through the PlacesView interface, read <a href="/en/The_PlacesView_interface" title="en/The_PlacesView_interface">The PlacesView interface</a>.</p>
<h3>The Built-In Tree View</h3>
<p>The most common type of view is in a tree control, but it is also relatively difficult to implement. Therefore, Places provides a built-in view object for when you want to display a result in a tree. The object, <code>PlacesTreeView</code>, is implemented in {{ Source("browser/components/places/content/treeView.js") }}.</p>
<p>The view recognizes certain magic values of the <code>id</code> attribute on your <code>treecol</code> elements.  It uses these values to select properties of the <code>nsINavHistoryResultNode</code> objects corresponding to each row of your tree.  Each property is bound to a column using an <code>id</code> attribute.  The following table shows the mappings between these magic <code>id</code> values and their corresponding <code>nsINavHistoryResultNode</code> properties:</p>
<table border="1" cellspacing="0" style="" width="645"> <tbody> <tr> <td><code><strong>treecol</strong></code><strong> <code>id</code> or </strong><code><strong>anonid</strong></code></td> <td><strong>Corresponding <code>nsINavHistoryResultNode</code> property</strong></td> </tr> <tr> <td><code>title</code></td> <td><code>title</code></td> </tr> <tr> <td><code>url<br> </code></td> <td><code>uri</code></td> </tr> <tr> <td><code>date<br> </code></td> <td><code>time</code></td> </tr> <tr> <td><code>visitCount<br> </code></td> <td><code>accessCount</code></td> </tr> <tr> <td><code>keyword</code></td> <td>*</td> </tr> <tr> <td><code>description</code></td> <td>*</td> </tr> <tr> <td><code>dateAdded<br> </code></td> <td><code>dateAdded</code></td> </tr> <tr> <td><code>lastModified<br> </code></td> <td><code>lastModified</code></td> </tr> <tr> <td><code>tags<br> </code></td> <td><code>tags</code></td> </tr> </tbody>
</table>
<p>*<code>keyword</code> and <code>description</code> are looked up in the Places database using the <code>nsINavHistoryResultNode</code> property <code>itemId</code>.</p>
<p>In lieu of setting an <code>id</code> on a <code>treecol</code>, you may specify an <code>anonid </code>attribute.  This is useful when a <code>treecol</code> is contained in anonymous content, as in XBL.  If both an <code>id</code> attribute and <code>anonid</code> attribute are specified, the <code>anonid</code> is used.</p>
<p>As with all Places views, the built-in tree view implements <code>nsINavHistoryResultViewer</code>, and because it is a tree view, it also implements {{ Source("/layout/xul/base/src/tree/public/nsITreeView.idl", "nsITreeView") }}. You can therefore use this object to bridge between a result (see <a href="/en/Querying_Places" title="en/Querying_Places">Querying Places</a>) and a tree:</p>
<pre>var result = historyService.executeQuery(...); // your Places query result
var tree = document.getElementById("mytree"); // your tree control

var showRootNodeInTree = true;
var treeviewer = new PlacesTreeView(showRootNodeInTree);

result.viewer = treeviewer;
tree.view = treeviewer.QueryInterface(Components.interfaces.nsITreeView);
</pre>
<p>The built-in tree view also allows observers to attach that implement <code>nsINavHistoryResultViewObserver</code> (declared in {{ Source("toolkit/components/places/public/nsINavHistoryService.idl", "nsINavHistoryService.idl") }}). This observer interface allows external components to see what is happening and to take appropriate action. For the Places trees, the controller attaches and, for example, notices when something has been drag-and-dropped on the tree. It then takes the appropriate action.</p><h2 name="Creating_custom_views">Creating custom views</h2>
<p>If you need greater flexibility or to provide a customized appearance for your display of Places information, you can create a custom view to do so.</p>
<h3 name="Registering_a_view">Registering a view</h3>
<p>Register the view by setting the <code>viewer</code> attribute on <code>nsINavHistoryResult</code>. When you do this, the result will in turn set the <code>result</code> attribute on the given view. <em>You should not set the <code>result</code> attribute on the view explicitly.</em> To clear the view, set the <code>viewer</code> attribute to <code>null</code>. This will cause the view's <code>result</code> attribute to be set to <code>null</code> as well.</p>
<p>Be careful about reference cycles. The view and the result both hold owning references to each other. For these objects to be deleted, you must clear this cycle, by setting <code>result.viewer</code> to <code>null</code>. The built-in tree view (see below) does this automatically. When the tree is destroyed or a different <code>nsITreeView</code> is associated with the tree, the tree will call <code>nsITreeView.tree = null;</code> The viewer detects this case and also detaches itself from the result.</p>
<h3 name="Implementing_a_view">Implementing a view</h3>
<p>If you require a customized tree view, it may be easiest to wrap the <code>nsINavHistoryResultTreeViewer</code> in your own class. For example, if you wanted a "special" first row, your object would provide <code>nsITreeView</code> responses for the first row, and pass all other messages through to the built-in tree view with indices shifted by one.</p>
<p>The attribute <code>nsINavHistoryResultNode.viewIndex</code> is provided explicitly for the use of the view. These values are initialized to <code>-1</code> when each node is created. You can use this value to keep track of visible nodes. The built-in tree viewer uses this attribute to store the row index that the node is on.</p>
<p>The <code>nsINavHistoryResultViewer</code> also has an observer interface to allow an <code>nsINavHistoryResultViewObserver</code> to observer changes. However, this observer interface is specifically for trees. The {{ Bug("337638") }} is for moving this to the <code>nsINavHistoryResultTreeViewer</code> object. Other implementors if <code>nsINavHistoryResultViewer</code> should use their own observers.</p>
<h3 name="See_also">See also</h3>
<ul> <li><a href="/en/The_PlacesView_interface" title="en/The_PlacesView_interface">The PlacesView interface</a></li>
</ul>
<p>{{ languages( { "ja": "ja/Displaying_Places_information_using_views" } ) }}</p>
Revert to this revision