Labs/Jetpack/JEP/30: Difference between revisions

From MozillaWiki
< Labs‎ | Jetpack‎ | JEP
Jump to navigation Jump to search
(→‎JEP 30 - First-run Help: Added links to docs and bugs)
 
(18 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{draft}}
{{draft}}


== JEP 30 - First-run Support ==
== JEP 30 - First-run Help ==


* Champion: Aza Raskin <aza at mozilla dot com>
* Champion: Aza Raskin <aza at mozilla dot com>
Line 9: Line 9:
* Created: 17 Nov 2009
* Created: 17 Nov 2009
* Reference Implementation: None
* Reference Implementation: None
* Relevant Bugs:  
* Relevant Bugs: {{bug|532860}}, {{bug|535464}}
* Implementation Documentation: [https://developer.mozilla.org/en/Jetpack/Meta/First_run First-run pages], [https://developer.mozilla.org/en/Jetpack/Meta/Me me.onFirstRun()]
* [[Labs/Jetpack/JEPs|JEP Index]]
* [[Labs/Jetpack/JEPs|JEP Index]]


Line 20: Line 21:
=== Proposal ===
=== Proposal ===


First-run will live at <code>jetpack.manifest</code>.
== Creating a First-run Page ==
 
There are times when simply pointing out the new UI features (see below) aren't enough. In this case, you can create a first-run page. The first-run will live at <code>jetpack.manifest</code>.


http://img.skitch.com/20091117-c8maetc49ke7ptf6yj2bieg7ac.png
http://img.skitch.com/20091117-c8maetc49ke7ptf6yj2bieg7ac.png


The first-run experience is coded inside of the manifest, which is (not un-coincidentally) where the settings are placed.  
The first-run experience is coded inside of <code>manifest</code>, the feature's manifest, which is (not un-coincidentally) where the settings are placed.  


<pre class="brush:js;">
<pre class="brush:js;">
jetpacks.manifest = {
var manifest = {
   firstRun: options
   firstRunPage: stringOrXml
}
}
</pre>
</pre>


''options'': {html: "<div>", url: "http://", text: "", img: "http://" } or html/url/img-url (a url is uniquely identifiable by starting with "http://" that doesn't end in an three-letter image extension).
<code>stringOrXml</code> is either a string or E4X XML.  If it's a string and a valid URI, such as <code>"http://mozilla.com/"</code>, the iframe's content is the content referenced by the URI.  Otherwise it's assumed to be HTML, and it becomes the <code>body</code> of the iframe's content.
 
== Events ==


* Want to take care of the case where it's just some text. Just a single image. A full HTML page.
All events live in the <code>jetpack.me</code> namespace (used for introspection of the current running Jetpack).
* Want to take care of settings. Both as a link which pops open the goodness (jetpack.settings.open) and as something which is embedded (<div class="jetpack-settings">) and as something which is in-flowed <input class="jetpack-setting" id="twitter.id"/>.
 
<pre class="brush:js;">
jetpack.me.onFirstRun( function )
jetpack.me.onReenabled( function )
jetpack.me.onDisabled( function )
jetpack.me.onUninstall( function )
</pre>
 
The <code>me.onFirstRun</code> gets called on the first run of an extension. If an extension is uninstalled and reinstalled (and the original data wasn't removed) then the callback(s) passed to <code>onFirstRun</code> aren't called.
 
The rest of the event handlers should be self-explanatory.
 
'''FOR THE FUTURE'''


== Interaction with Settings ==
== Interaction with Settings ==


One of the standard use cases for the first-run page—besides pedagogical—will be to setup up the Jetpack's settings. There are three ways of doing this:
One of the standard use cases for the first run experience—besides pedagogical—will be to setup up the Jetpack's settings. There are three ways of doing this:


#Allow calling jetpack.settings.open() from the first-run page. (Although jetpack.settings.open is not yet implemented.)
#Allow calling jetpack.settings.open() from Jetpack-defined HTML content.
#Embed the settings in the first-run page (see below)
#Embed the settings in the first-run page (see below)
#Inline inclusion of settings (see below).
#Inline inclusion of settings (see below).
Line 47: Line 64:
== Embedding the Settings ==
== Embedding the Settings ==


Embedding the settings into the first run-page is as simple as including a special id'ed tag, <code><div id="settings"></code>, which automatically gets interpolated into the settings widget.
Embedding the settings into the first run-page is as simple as including a special id'ed tag, <code><div id="settings"/></code>, which automatically gets interpolated into the settings widget.


== Inline Inclusion ==
== Inline Inclusion ==
Line 65: Line 82:


Note: This convenience method only works for values which don't require sanitization (like numerical inputs) until we have an implementation of HTML5 forms.
Note: This convenience method only works for values which don't require sanitization (like numerical inputs) until we have an implementation of HTML5 forms.
'''EVEN MORE IN THE FUTURE'''


== Object-based Help ==
== Object-based Help ==
Line 91: Line 110:
If it turns out that these messages are annoying or too much, we will add the ability to, from the manifest, suppress these messages.
If it turns out that these messages are annoying or too much, we will add the ability to, from the manifest, suppress these messages.


Finally, and importantly, because arbitrary HTML is allowed in the help, you can use the inline embedding (see below) to allow for setting of settings inside the bubbles.
http://img.skitch.com/20091124-pn91agmru81sf4e7pgaatfeqkk.png
<code><input class="jetpack.setting" id="splashText"/></code>
=== Hidden Elements ===
Some Jetpacks only expose UI through elements that are hidden by default (a context menu) or that do not have a visual representation (a pageMod). We need a way of handling these edge-cases.
Firefox will soon have a browser button (AKA the Tools button):
http://people.mozilla.com/~faaborg/files/20090924-noRibbonUI/firefox4Proposal-right.png
At that point, we can have all non-visible UI help concatenated and displayed through a bubble that points to the browser button. For now, however, we can have the bubble appear from the site-badge button.
http://img.skitch.com/20091124-8rhysh79k8ppfq4i7x6sjf6nce.png
This example corresponds to the following code:
<pre class="brush:js;">
jetpack.menu.context.page.add({
  icon: "http://...",
  label: "Inject jQuery",
  help: "Right-click any ... <img src='...'/>",
  command: function(){ ... }
});
jetpack.pageMods.add( callback, {
  matches: "*",
  help: "As it loads, check every website..."
});
</pre>
</pre>
flowed <code><input class="jetpack-setting" id="twitter.id"/></code>.


== Multiple Jetpacks ==
== Multiple Jetpacks ==

Latest revision as of 02:27, 20 December 2009

Draft-template-image.png THIS PAGE IS A WORKING DRAFT Pencil-emoji U270F-gray.png
The page may be difficult to navigate, and some information on its subject might be incomplete and/or evolving rapidly.
If you have any questions or ideas, please add them as a new topic on the discussion page.

JEP 30 - First-run Help

Introduction and Rationale

This JEP describes an API for creating first-run pages for Jetpacks.

After installing a Jetpack, without some sort of instructions on how to use the features just installed, the user can feel lost, bewildered, and confused. The first-time experience is exactly when users need the greatest reassurance and instruction, which is why so many Firefox add-ons create a first-run page to explain and guide the user through the new functionality. With Jetpacks, we have the opportunity to create a more unified feel.

Proposal

Creating a First-run Page

There are times when simply pointing out the new UI features (see below) aren't enough. In this case, you can create a first-run page. The first-run will live at jetpack.manifest.

20091117-c8maetc49ke7ptf6yj2bieg7ac.png

The first-run experience is coded inside of manifest, the feature's manifest, which is (not un-coincidentally) where the settings are placed.

var manifest = {
  firstRunPage: stringOrXml
}

stringOrXml is either a string or E4X XML. If it's a string and a valid URI, such as "http://mozilla.com/", the iframe's content is the content referenced by the URI. Otherwise it's assumed to be HTML, and it becomes the body of the iframe's content.

Events

All events live in the jetpack.me namespace (used for introspection of the current running Jetpack).

jetpack.me.onFirstRun( function )
jetpack.me.onReenabled( function )
jetpack.me.onDisabled( function )
jetpack.me.onUninstall( function )

The me.onFirstRun gets called on the first run of an extension. If an extension is uninstalled and reinstalled (and the original data wasn't removed) then the callback(s) passed to onFirstRun aren't called.

The rest of the event handlers should be self-explanatory.

FOR THE FUTURE

Interaction with Settings

One of the standard use cases for the first run experience—besides pedagogical—will be to setup up the Jetpack's settings. There are three ways of doing this:

  1. Allow calling jetpack.settings.open() from Jetpack-defined HTML content.
  2. Embed the settings in the first-run page (see below)
  3. Inline inclusion of settings (see below).

Embedding the Settings

Embedding the settings into the first run-page is as simple as including a special id'ed tag,

, which automatically gets interpolated into the settings widget.

Inline Inclusion

Inline inclusion involves two things. The first is that we expose jetpack.storage.settings to the first-run webpage. This way, the page has full power to change and update the settings as it wishes, with whatever UI it desires.

The second is that we add a convenience method built on top of that functionality. If an DOM element has an ID matching a setting in the manifest, we store its value automatically into the settings.

For instance,

<b>Twitter Name:</b>
<input type="text" id="jetpack.storage.settings.twitterName"/>

Which works if twitterName was defined in the manifest. Otherwise an warning is logged to the console.

Note: This convenience method only works for values which don't require sanitization (like numerical inputs) until we have an implementation of HTML5 forms.

EVEN MORE IN THE FUTURE

Object-based Help

Enabling support for teaching people how to use specific UI-features in Jetpack is important to making the onramp for new feature adoption shallow. One way of doing this is have first-run documentation (and potentially later-on help) be displayed as close as possible to the interaction points, for instance as dismissible tooltips.

Take the example of a status-bar icon. During install, instead of writing a full HTML-based page that has to duplicate, with screenshots, how the status-bar looks (which isn't immune to getting out of date when the platform changes, or for appearing with the wrong OS look-and-feel) we can have Jetpack just put the one or two lines of help right there.

20091119-j4a6qcqe5mhfc277gsfhfh94y6.png

In code, this would be written in the same place as your definition of the UI element:

jetpack.statusBar.append({
  url: "graph.html",
  onReady: function(){ ... },
  help: "I'm your personal tab-user grapher...",
});

These messages are shown/or are accessible from from:

  • On first run, these messages get shown.
  • All visual UI elements will also have a context-menu option of "Help" which will bring up the message.
  • Every Jetpack listed on the installed page will have link/button that will cause the messages to re-open.

If it turns out that these messages are annoying or too much, we will add the ability to, from the manifest, suppress these messages.

Finally, and importantly, because arbitrary HTML is allowed in the help, you can use the inline embedding (see below) to allow for setting of settings inside the bubbles.

20091124-pn91agmru81sf4e7pgaatfeqkk.png

<input class="jetpack.setting" id="splashText"/>

Hidden Elements

Some Jetpacks only expose UI through elements that are hidden by default (a context menu) or that do not have a visual representation (a pageMod). We need a way of handling these edge-cases.

Firefox will soon have a browser button (AKA the Tools button):

firefox4Proposal-right.png

At that point, we can have all non-visible UI help concatenated and displayed through a bubble that points to the browser button. For now, however, we can have the bubble appear from the site-badge button.

20091124-8rhysh79k8ppfq4i7x6sjf6nce.png

This example corresponds to the following code:

jetpack.menu.context.page.add({
  icon: "http://...",
  label: "Inject jQuery",
  help: "Right-click any ... <img src='...'/>",
  command: function(){ ... }
});

jetpack.pageMods.add( callback, {
  matches: "*",
  help: "As it loads, check every website..."
});

flowed <input class="jetpack-setting" id="twitter.id"/>.


Multiple Jetpacks

FOR FUTURE IMPLEMENTATION

One of the pain points in original-flavor extensions has been that bundling two or more extensions together leads to a jarring experience on installation—numerous first-run pages pop-up like zits on a teenagers face after an oil bath.

With the Jetpack method of doing first-run pages, we can more easily intercept these first-run pages in the case of a bundle and create a unified experience.

20091117-msbxk1bw2ue7w1i1km5s4c9h4u.png