Core-Gadget - Action Contributions

This is a DRAFT ...

    <!-- ///////////////////////////// -->
   <section title="The Action Contributions Feature (gadgets.actions)" anchor="gadgets.actions">

     <t>Some container implementations reserve portions of their user 
     interface for providing links, menus, buttons, etc that are 
     distinct from the gadgets they host. The "Action Contributions"
     feature allows gadgets to contribute functionality to these reserved
     areas.</t>

     <t>Additionally, gadgets can use the feature to associate actions with
     specific types of OpenSocial objects. In traditional desktop applications,
     such actions are often rendered as options on context menus when you 
     click on an object such as a person or file. For instance, selecting 
     a Person object might display options like "Start a Chat" or 
     "View Contact Information". With the "Action Contributions" feature, 
     a gadget can notify the container of which such actions it can provide 
     so that when a user selects the action, the container can direct the 
     appropriate gadget to carry it out.</t>
     
     <t>Containers SHOULD support the "Action Contributions" feature.</t>

     <t>The "Action Contributions" feature is enabled by specifying the 
     "actions" feature name with either an &lt;Optional&gt;
     or &lt;Require&gt; element within the &lt;ModulePrefs&gt;. The 
     actions contributed by the gadget are specified using a &lt;Param&gt;
     element with the name "action-contributions" within the feature declaration.</t>
     
     <figure><preamble>The following example defines an optional dependency
     on the "Action Contributions" feature and contributes a single action
     to the set of "Navigation Links" provided by the container. The "path"
     property on the &lt;action&gt; element specifies where the action is 
     being contributed. When the item is selected, the container will 
     invoke the callback handler provided by the JavaScript in the
     &lt;Content&gt; element.</preamble><artwork>
  &lt;Module>
    &lt;ModulePrefs title="Sample VOIP">
      &lt;Optional feature="actions">
        &lt;Param name="action-contributions">&lt;![CDATA[
          &lt;action id="org.samplervoip.navLink" 
            path="container/navigationLinks" 
            label="Phone" />
        ]]&gt;&lt;/Param>
      &lt;/Optional>
    &lt;/ModulePrefs>
    &lt;Content type="html">&lt;![CDATA[
      &lt;script>
      
        function navLink(selection) { ... }
      
        gadgets.util.registerOnLoadHandler(
          function() {
            if (gadgets.actions) {
              gadgets.actions.updateAction({
                id: "org.samplervoip.navLink",
                callback: navLink
              });
            }
          }
        );
      &lt;/script>
    ]]&gt;&lt;/Content>
  &lt;/Module>
     </artwork></figure>
     
     <figure><preamble>Contributing actions to specific OpenSocial data 
     types is similar. Rather than specifying the location to which the 
     action is to be added, the &lt;action&gt; element specifies the 
     data type. In either case, a callback function provided by the 
     gadget is registered and invoked to handle the action:</preamble><artwork>
  &lt;Module>
    &lt;ModulePrefs title="Sample VOIP">
      &lt;Require feature="actions">
        &lt;Param name="action-contributions">&lt;![CDATA[
          &lt;action id="org.samplevoip.callbyperson" 
            dataObject="opensocial.Person" 
            label="Call using VOIP Phone" />
        ]]&gt;&lt;/Param>
      &lt;/Require>
    &lt;/ModulePrefs>
    &lt;Content type="html">&lt;![CDATA[
      &lt;script>
      
        function dial(selection) { ... }
      
        gadgets.util.registerOnLoadHandler(
          function() {
            if (gadgets.actions) {
              gadgets.actions.updateAction({
                id: "org.samplevoip.callbyperson",
                callback: dial
              });
            }
          }
        );
      &lt;/script>
    ]]&gt;&lt;/Content>
  &lt;/Module>
     </artwork></figure>

     <figure><preamble>Actions can also be contributed programmatically by calling the 
     <spanx style="verb">gadgets.actions.addAction</spanx> API and passing
     in an "action" object. For instance:</preamble><artwork>
  var mycallback = function(){
    ...
  };
  
  var myaction = {
    id: "com.acme.mycallaction",
    tooltip: "My Action Tooltip",
    label: "Call Person",
    icon: "images/myicon.png",
    callback: mycallback,
    dataType: "opensocial.Person"
  }
  
  gadgets.actions.addAction(myaction);      
     </artwork></figure>
  
     <figure><preamble>In some simple cases, an action provided by a gadget might simply 
     be handled by navigating to an IRI. It such cases, a callback function
     is not required and the gadget developer can simply provide the IRI 
     in the action declaration. For instance, in the example below, the 
     container will display the provided IRI in a new tab when the "Contact US"
     navigation action is selected:</preamble><artwork>
  &lt;Module>
    &lt;ModulePrefs title="Sample VOIP">
      &lt;Require feature="actions">
        &lt;Param name="action-contributions">&lt;![CDATA[
          &lt;action id="org.example.goSomewhere" 
            path="container/navigationLinks" 
            label="Contact Us!" 
            url="http://www.example.org/contact" 
            viewTarget="TAB" />
        ]]&gt;&lt;/Param>
      &lt;/Require>
    &lt;/ModulePrefs>
    ...
  &lt;/Module>
     </artwork>
     
     <t>TODO: What happens is viewTarget is not specified and url is provided??</t>
  
     <t>When registering actions, gadget developers need only provide basic
     information about the action such as a unique identifier, text label,
     icon and callback function. Containers are responsible for determining 
     how contributed actions are to be rendered.</t>


     <section title="The &lt;action&gt; Element">
     
       <t>The &lt;action&gt; element, as illustrated in the previous 
       examples, is used within the value of &lt;Param name="action-contributions"&gt;
       elements to declaratively define the actions provided by a gadget. The
       "action-contributions" parameter value can have any number of 
       &lt;action&gt; elements, each of which MUST specify a unique "id" 
       attribute. Each actions ID MUST be unique within the scope of the 
       container -- that is, if multiple gadget's are rendered by
       the container, all of the actions contributed by each of the gadgets 
       MUST specify different IDs.</t>
       
       <t>There is no XML namespace defined for the &lt;action&gt; element.</t>
     
       <figure><artwork>
  BaseAction = {
    attribute id { text },
    attribute label { text },
    attribute tooltip { text }?,
    attribute icon { IRI }?,
    attribute iconSize { text }?,
    attribute iconOffset { text }?,
    attribute view { text }?,
    attribute viewTarget { "TAB" | "DIALOG" | "MODALDIALOG" | "FLOAT" | "SIDEBAR" }?,
    attribute url { IRI }?,
    undefinedAttribute*
  }
       
  PathAction = element action {
    BaseAction,
    attribute path { text }
  }
  
  TypeAction = element action {
    BaseAction,
    attribute type { text }
  }
  
  action = PathAction | TypeAction
       </artwork></figure>
       
       <t>The &lt;action&gt; element MUST contain the "id" and "label" 
       attributes and either the "path" or "type" attributes. The "label"
       specifies the plain-text label that a container SHOULD display 
       when rendering the action. The "path" attribute specifies a 
       location with the container's user interface where the action 
       is to be rendered. Possible values for the "path" attribute 
       are discussed below. The "type" attribute specifies the OpenSocial
       data type for which an action is to be associated. The value
       MUST be a valid OpenSocial Data Type as specified by 
       [TODO: New Core Data Reference].</t>
       
       <t>The following additional attributes MAY be specified:
         <list style="hanging">
           <t hangText="tooltip">Additional text that provides additional
           information about the action. Such text is typically displayed
           when the user hovers their mouse cursor over the action item.</t>
           <t hangText="icon">An IRI to an image resource that the container
           can display when rendering the action item. For instance, when
           rendering the action as a menu item, the contain can display the 
           icon next to the label. If a relative path is provided, it MUST
           be resolved relative to the URL of the gadget specification document.</t>
           <t hangText="iconSize">TODO: Need more info</t>
           <t hangText="iconOffset">TODO: Need more info</t>
           <t hangText="view">The name of the gadget view the container 
           SHOULD render when the action is invoked.</t>
           <t hangText="viewTarget">Specifies where the specified view is 
           to be rendered. Different container implementations MAY support
           the ability for individual gadget views to be displayed outside 
           the main area allocated to the gadget by the container. Examples 
           include rendering within a modal dialog box, or within a 
           "sidebar" area provided by the container. Acceptable values for
           the viewTarget attribute are "TAB", "DIALOG", "MODALDIALOG",
           "FLOAT" and "SIDEBAR". If not specified, the view will be rendered
           within the area already allocated to the gadget.</t>
           <t hangText="url">An IRI to use in place of a callback function.
           When used, the container will display the content of the URL 
           when the action is selected rather than invoking a JavaScript
           callback to handle the action. TODO: Need more info</t>
         </list>
       </t>
     
     </section>
     
     <section title="Action Contribution Paths" anchor="gadgets.actions.paths">
     
       <t>When a gadget contributes actions to the container's user interface,
       the intended location where the action is to be rendered is specified
       using a "path". The collection of available paths for which actions
       can be contributed is specific to each individual container implementation. 
       Some containers might not support user interface action contributions 
       at all.</t>
       
       <t>The following common paths MAY be supported by a container:
         <list style="hanging">
           <t hangText="&quot;container/navigationLinks&quot;">
             Identifies the area provided by the container for
             "top-level navigation". These are typically links
             or menu items that provide users with an overall 
             ability to navigate through the various available
             services provided by an application.
           </t>
           <t hangText="&quot;container/menus&gt;">
             Identifies the area provided by the container for
             menu options. These are typically hierarchically 
             nested actions that provide access to a variety 
             of options and tools currently available to the user.
           </t>
           <t hangText="&quot;container/toolbars&quot;">
             Identifies the area provided by the container for
             toolbars. These are typically shortcuts to commonly
             used options or tools currently available to the user.
           </t>
           <t hangText="&quot;gadget/menu&quot;">
             Identifies an "options" menu that a container might 
             provide for a gadget instance. Typically, such menus
             provide options and tools associated with a specific
             gadget instance.
           </t>
         </list>
       </t>
       
       <t>Contribution paths are hierarchical and container specific. For 
       instance, if a container supports a top level menu system such 
       as those typically found in many traditional desktop applications,
       a gadget might use path="container/menu/File" to add items to the 
       containers "File" menu. The depth of the path hierarchy is entirely
       determined by the container. Each segment of the path is separated
       by the forward slash (/) character.</t>
     
     </section>

     <section title="JavaScript API">
     
       <t>Gadget developers who contribute actions to the container use the 
       <spanx style="verb">gadgets.actions</spanx> JavaScript API to work
       with contributed actions.</t>
       
       <t>The API is used, for instance, to register callback functions to 
       handle actions, register or modify actions programmatically, or 
       work with contributions provided by other gadget specifications.</t>
       
       <section title="The Action Object" anchor="gadgets.actions.actionobjects">
       
         <t>The <spanx style="verb">Action</spanx> object is a JavaScript 
         representation of a contribution action. The properties available
         on the object correlate to each of the attributes on the &lt;action&gt;
         element. An additional "callback" property is provided that specifies
         the callback function the container will invoke when the action is
         selected.</t>
         
         <texttable align="left">
           <ttcol>Attribute</ttcol>
           <ttcol>Description</ttcol>
           <c>id</c>
           <c>Unique identifier</c>

           <c>label</c>
           <c>Text string to display for this action</c>

           <c>path</c>
           <c>The container-defined location for this action, as described in <eref target="#gadgets.actions.paths">Action Paths</eref>.  Example: path=container/menus/Edit</c>

           <c>dataType</c>
           <c>The Open Social Data type with which to associate this action. Example: opensocial.Person</c>

           <c>tooltip</c>
           <c>Tooltip to display on hovering over an icon</c>

           <c>icon</c>
           <c>Path to image icon.  Absolute URL or URL relative to gadget URL</c>

           <c>iconSize</c>
           <c>TODO: need more info</c>

           <c>iconOffset</c>
           <c>TODO: need more info</c>

           <c>view</c>
           <c>The view ID the gadget should navigate to when the action is invoked.</c>

           <c>viewTarget</c>
           <c>The target area to render the view.</c>

           <c>url</c>
           <c>Simple actions that are just links can specify a url instead of a callback function.</c>

         </texttable>
         
         <t>As is the case with the &lt;action&gt; element, the "id" and "label"
         properties are both required and values for either the "path" or "type" 
         MUST be provided. All other properties are optional.</t>
         
       </section>
       
       <section title="gadgets.actions.addAction" anchor="gadgets.actions.addAction">
       
         <t>Programmatically registers an action with the container.</t>
         
         <figure><artwork>
  &lt;static&gt; gadgets.actions.addAction(action)
         </artwork></figure>
         
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>action</c>
             <c><xref target="gadgets.actions.actionobjects">Action Object</xref></c>
             <c>The action to be added to the container</c>
           </texttable>
         </t>
         
         <figure><preamble>For example:</preamble><artwork type="code">
  var mycallback = function(){
    ...
  };
  
  var myaction = {
    id: "com.acme.mycallaction",
    tooltip: "My Action Tooltip",
    label: "Call Person",
    icon: "images/myicon.png",
    callback: mycallback,
    dataType: "opensocial.Person"  
  }

  gadgets.actions.addAction(myaction);
         </artwork></figure>
       </section>
       
       <section title="gadgets.actions.updateAction" anchor="gadgets.actions.updateAction">
       
         <t>Modifies the specified action contributed to the container.
         TODO: Question: any action or just actions provided by this one gadget?</t>
       
         <figure><artwork>
  &lt;static&gt; gadgets.actions.updateAction(action)
         </artwork></figure>

         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>action</c>
             <c><xref target="gadgets.actions.actionobjects">Action Object</xref></c>
             <c>A partial representation of the action to be updated within the container</c>
           </texttable>
         </t>

         <t>The Action object passed in to the <spanx style="verb">gadgets.actions.updateAction</spanx>
         method can be a partial representation of the action that contains 
         the "id" of the action being modified and only the properties that 
         need to be updated.</t>
         
         <figure><preamble>For instance, to specify the callback function 
         for an action contributed using the &lt;action&gt; element, a developer
         would invoke <spanx style="verb">gadgets.actions.updateAction</spanx>
         with an object that specifies only the "id" and "callback" properties:</preamble>
         <artwork>
  var mycallback = function(){
    ...
  };
  
  var myaction = {
    id: "com.acme.mycallaction",
    callback: mycallback
  }
  
  gadgets.actions.updateAction(myaction);
         </artwork></figure>
       </section> 
       
       <section title="gadgets.actions.removeAction" anchor="gadgets.actions.removeAction">
       
         <t>Removes the specified action from the container.
         TODO: I assume a gadget can only remove it's own actions
         </t>
         
         <figure><artwork>
  &lt;static&gt; gadgets.actions.removeAction
         </artwork></figure>
       
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>id</c>
             <c>String</c>
             <c>The ID of the action to be removed.</c>
           </texttable>
         </t>
         
         <figure><preable>For example,</preable><artwork>
  gadgets.actions.removeAction("com.acme.mycallaction");     
         </artwork></figure>
       </section>
       
       <section title="gadgets.actions.getActionsByPath" anchor="gadgets.actions.getActionsByPath">
       
         <t>Retrieves the collection of actions registered at the specified 
         path and passes the result to the provided callback function as 
         a JavaScript Array. TODO: is this all actions for the container, 
         or just this gadgets?? TODO: is this hierarchical</t>
         
         <figure><artwork>
  &lt;static&gt; gadgets.actions.getActionsByPath(path, callback)
         </artwork></figure>
       
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>path</c>
             <c>String</c>
             <c>The String representation of the path to the actions</c>
             <c>callback</c>
             <c>Function</c>
             <c>A callback function to handle the returned actions array</c>
           </texttable>
         </t>
         
         <figure><preamble>For example,</preamble><artwork>
  function listActions(actions) { ... }
  
  gadgets.actions.getActionsByPath("container/navigationLinks", callback);
         </artwork></figure>
         
       </section>
       
       <section title="gadgets.actions.getActionsByDataType" anchor="gadgets.actions.getActionsByDataType">
       
         <t>Retrieves the collection of actions registered for the specified
         data type and passes the result to the provided callback function
         a JavaScript Array. TODO: is this all actions for the container or
         just this gadgets??</t>
       
         <figure><artwork>
  &lt;static&gt; gadgets.actions.getActionsByDataType(dataType, callback)
         </artwork></figure>
         
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>dataType</c>
             <c>String</c>
             <c>The String representation of the associated data type</c>
             <c>callback</c>
             <c>Function</c>
             <c>A callback function to handle the returned actions array</c>
           </texttable>
         </t>
         
         <figure><preamble>For example,</preamble><artwork>
  function listActions(actions) { ... }
  
  gadgets.actions.getActionsByType("opensocial.Person", callback);
         </artwork></figure>
       </section>
       
       <section title="gadgets.actions.runAction" anchor="gadgets.actions.runAction">
       
         <t>Invokes the specified actions callback function; or, if the 
         "url" property is specified in place of a callback, causes the 
         container to navigate to the specified IRI. Gadget's can use
         this method to programmatically invoke an action.</t>
         
         <figure><artwork>
  &lt;static&gt; gadgets.actions.runAction (id, opt_selection)
         </artwork></figure>

         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>id</c>
             <c>String</c>
             <c>The ID of the action to execute.</c>
             <c>opt_selection</c>
             <c><xref target="gadgets.selection">Selection Object</xref></c>
             <c>An optional object that identifies the currently selected object as
             defined by <xref target="gadgets.selection"/>.</c>
           </texttable>
         </t>
         
         <figure><preamble>For example,</preamble><artwork>
  gadgets.actions.runAction("com.acme.mycallaction");
         </artwork></figure>
       </section>
       
       <section title="gadgets.actions.registerShowActionsListener" anchor="gadgets.actions.registerShowActionsListener">
       
         <t>Registers a callback function that the container will call whenever 
         new actions are added to the container. A gadget can use this listener
         to provide a rendering of any action contributed to the container
         by any other gadget.</t>
         
         <figure><artwork>
  &lt;static&gt; gadgets.actions.registerShowActionsListener (listener)
         </artwork></figure>
       
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>listener</c>
             <c>Function</c>
             <c>The gadgets's function to render actions in its UI. The 
             function will be invoked with one parameter which is an array 
             of action objects to render.</c>
           </texttable>           
         </t>

         <figure><preamble>For Example:</preamble><artwork type="code">
  var listener = function(actionObjs){
       // draw the UI, toolbars menus, etc
       // to do the invocation of the action, call the following API:
       // gadgets.actions.runAction(actionObjs[0].id);  
  }
  gadgets.actions.registerShowActionsListener(listener);
         </artwork></figure>
       </section>
       
      <section title="gadgets.actions.registerHideActionsListener" anchor="gadgets.actions.registerHideActionsListener">
      
        <t>Registers a callback function that the container will call whenever
        the a gadget that contributes actions is removed from the container.</t>
        
         <figure><artwork>
  &lt;static&gt; gadgets.actions.registerHideActionsListener (listener)
         </artwork></figure>
       
         <t>Input Parameters:
           <texttable align="left">
             <ttcol>Name</ttcol>
             <ttcol>Type</ttcol>
             <ttcol>Description</ttcol>
             <c>listener</c>
             <c>Function</c>
             <c>The gadgets's function to render actions in its UI. The 
             function will be invoked with one parameter which is an array 
             of action objects to hide.</c>
           </texttable>           
         </t>
        
         <figure><preamble>For Example:</preamble><artwork type="code">
  var listener = function(actionObjs){
       // remove the UI elements associated with the listed actions
  }
  gadgets.actions.registerHideActionsListener(listener);
         </artwork></figure>      
      </section>
     </section>
   </section> <!--  END CONTRIBUTED ACTIONS FEATURE  -->