Labs/Jetpack/Reboot/JEP/102

< Labs‎ | Jetpack‎ | Reboot‎ | JEP
Revision as of 22:49, 28 April 2010 by Dietrich (talk | contribs)

JEP 102 - Single UI Element

  • Champion: Aza Raskin - aza@mozilla.com
    • Other Peeps: Alex Faaborg, Daniel Buchner, Jennifer Boriss, Dietrich Ayala
  • Status: Under Review
  • Bug Ticket: bug 543585
  • Type: API


Proposal

20100205-pc8ufm5fsqu9tq92gmg2nrrgms.png

/**
Creates a new simple feature, whose properties are that it has a small 32x32
pixel display, as well as a larger display that defaults to 350px by 450px.
@constructor
@param options {object}
  @prop content {uri|html|xml|window}
        This is the small view of the feature.
        uri: A link to the URL of either an icon or a webpage
        html: A HTML string that will be rendered
        xml: E4X version of the above
        window: a reference to a DOM window object
  @prop [panel] {uri|html|xml|window|panel}
        See above descriptions.
        panel: A reference to a panel object
        If a panel is specified then the default action is that a 
        click on the content area opens the panel. If you wish 
        to override this behavior you do it in the standard way:
        by creating a new widget.onClick that returns false, or
        calls event.preventDefault().
  @prop [on*] {function}
        You can optionally place event handlers in the constructor.
**/
widget = require("widget").Widget(options);
// Using the convention that constructors can optionally
// take new or not.

/**
Event handlers
@method
@param callback {function}
Potential to be all standard events. But for now: load, click, mouseover, mouseout
**/
widget.on*( callback ) //f.e., widget.onClick()

/**
Remove event handlers. Without any arguments, all bound events are removed.
If the function that was passed to bind is provided, only that specific event handler is removed.
@method
@param [callback] {function}
**/
widget.on*.unbind( [callback] )

/**
Enumerates all event handlers of the type specified, returning
a list of event handlers.
@method
**/
for( var eventHandler in widget.on* ){ console.log( eventHandler ); }

/**
Removes the widget from the interface.
@method
**/
widget.destroy()


/**
@prop [content] {canvas|window}
      If there was a image passed into the constructor this will be a canvas
      you can draw on. It updates the displayed icon in real time. If there
      was a page, then this is a window element.
@prop [panel] {panel}
      A reference to the panel object.
**/
feature.property

Sizing

The bar can have two sizes: one where the height of the widgets are 24px and one where they are 16px. The size is set by the user/Firefox, and cannot be changed via this API. For now, the widgets are always rendered as if at a height of 24px and then scaled to 16px height.

Notes

  • Do we want a widget.listEventsHandlers()?

Open Issues

  • What are the conditions that we should impose on add-ons being included in this UI element.
  • Need to figure out ContentFrames.
  • How is overflow handled?
  • Can users pin a widget?
  • Can users change widget order? Via drag-and-drop?
  • Can widgets stay alive, but manage their own visibility? (ie: only show if there's activity)
  • Can widgets change their own position in the display? Or force themselves out of overflow into the visible set?

Dependencies & Requirements

  • JEP 103 - Panel
  • ContentFrame
  • Update-allowable implementation of "icon" - may share similar implementation of content area with Panel and other JEPs
  • Icons sizes should be in the following size formats: Large: 24px, Small: 16px

Use Cases

  • Create a email notifier that shows you a small view that has the latest count/sparkline of emails yet to be read, and when you click on it it shows the detailed information about those unread messages.
  • A clock, which has no detail view. Similarly, an x-eyes reimplementation (the eyes follow your cursor around).
  • A Stumble Upon-style interface, where the small view allows you to upvote/downvote a page, and when a triangle is clicked shows a detailed view of ratings of this page.
  • Snow-globe, where when you click it causes the snow to swirl around the page you are looking at. Clicking a little gear opens a detailed view for setting the color and strength of the snow storm. (Like the previous case.)
  • An expanding search interface. It is displayed as a small search box. When you click in it, the search box expands in width with a quick animation. As you start typing, a panel appears which has search results listed in which you can arrow up/down, or mouse to.

Examples

Snow Globe

function SnowGlobe(win){
  // ...
}

var globes = {};

widget = require("basic-widget").Widget({
  content: "snowglobe.png",
  onClick: function(){
    tabs = require("tabs");
    var win = tabs.focused.contentWindow;
    if( !globes[win] ) globes[win] = new SnowGlobe(win);
    globes[win].shake();
  }
});

Mobile Reddit

widget = require("basic-widget").Widget({
  content: "http://reddit.com/favicon",
  panel: "http://m.reddit.com"
})

Wikipedia Lookup

widget = require("basic-widget").Widget({
  content: "http://wikipedia.com/favicon",
  panel: "Loading..."
})

widget.onClick(function(){
  var sel = require("selection").text;
  var url = "http://wikipedia.com/search?q=" + sel;
  widget.panel.content = url;
});