tag:blogger.com,1999:blog-8463171863233569292024-03-14T00:45:14.661-07:00Adventures in ThoughtlessnessSusan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-846317186323356929.post-44805193566261959792013-02-21T08:40:00.000-08:002013-02-21T08:40:53.831-08:00Moving on to "undefined"<p>Today’s post is more personal than usual. March 15 will be my last day at IBM, and will also be the beginning of a different relationship with Eclipse and Orion.</p>
<p>We all juggle different interests, but I find that every now and then (seems to be 12 years for me), I need to seriously reevaluate my career situation. It’s more than wanting a new team role, a different project, or new skills. I haven’t figured out where my next move sits on the continuum of job change, career change, or redefining the meaning of career. I think I'm moving toward a lot more slashes - farmer/writer/web developer/teacher. But to figure it out, I need to step away and gain a wider perspective. </p>
<a href="http://2.bp.blogspot.com/-WAeRTNwgClo/USP3ee26pKI/AAAAAAAAAJ8/vhP6dpmuwtU/s1600/perspective.png" imageanchor="1" ><img border="0" src="http://2.bp.blogspot.com/-WAeRTNwgClo/USP3ee26pKI/AAAAAAAAAJ8/vhP6dpmuwtU/s320/perspective.png" /></a>
<p>So I’m changing my relationship with software development for a while. I’d like to get away from my screen, spend more time outside, and work with people in my local community. I hope to do more volunteering, farming, teaching, learning, and writing. If you see me hoeing weeds outside, I might also be scheming a gardening or coding club at my son’s elementary school. Or maybe I’ll be pondering what the vastly changing webscape means to our local farmers, small rural economies, and people who don’t have access to the bandwidth and devices that we take for granted. Or perhaps I’ll simply enjoy the fresh air and clean row of crops.</p>
<a href="http://tuckeredoutfarm.com/img/plastics.png" imageanchor="1" ><img border="0" src="http://tuckeredoutfarm.com/img/plastics.png" /></a>
<p>I enjoy technical puzzles and helping people understand them. I seem to gravitate to UI technology, putting equal emphasis on usable API's and a simple, pragmatic UI. I enjoy writing about software and helping folks understand it better. So I imagine coming back to development at least a little bit after a break, probably as a freelancer. I hope to use Orion in my tool stack, and if so, I’ll contribute back. When I joined IBM in 2004, I was an independent Eclipse committer, so now it comes full circle. I’ll remain a committer, but I’m not quite ready to define my commitment.</p>
<p>The decision was neither easy nor quick. It’s exciting for sure, but also a little scary. IBM has been very good to me. I’ve been pleased to work exclusively in open source since joining IBM in 2004. I’ve had a very flexible schedule and work environment, and managers who value both the technical contributions and the real person behind them, while making unnecessary noise go away. For me, the Orion project has been an interesting exploration of web tooling platforms, what we need out of our visual components, and how coding in the cloud truly changes the way you think about your tools. After many years on the Eclipse platform writing Java code, the last few years in JavaScript have been a fun switch back to the typeless way, reminiscent of the days of Smalltalk. And developing in the cloud has been great fun for me. I haven't downloaded an SDK in over a year and I can move from device to device picking up where I left off.</p>
<p>My teammates throughout my time on Eclipse, Equinox, and now Orion have never failed to amaze me with their depth of knowledge, helpful spirit, and general humor and good fun. There are some very talented Orion developers whom I’ve not yet met in person, yet we still have that team bond and friendship. And there are others I’ve known for almost 20 years at <a href="http://en.wikipedia.org/wiki/Object_Technology_International">OTI</a>, IBM, and other project and company umbrellas. I stepped away from some of them before, only later to gravitate back to the smartest, most productive, and fun software team I’ve ever been part of.</p>
<p>I will continue to share my observations here and <a href="https://twitter.com/susanfmccourt">on twitter</a> as well as following the Eclipse adventure. Who knows, I may show up on an Orion status call by surprise one day, or pop into a UX hangout. It remains to seen. Please keep me in the loop if you see an interesting technical problem or experiment on the horizon. I hope to offer a perspective that balances the experience of implementing and delivering solutions with the freedom of not being on the hook for it, at least for a little while. Or I just might get curious enough to put my wheel hoe down and hack some code.</p>
<p>In the meantime, I've got about three weeks to finish up. I intend to finish my thoughts on <a href="http://adventuresinthoughtlessness.blogspot.com/2013/01/a-journey-toward-web-components-part-1.html">Web Components</a> before I go. I've got some bugs to fix, comments to add to code, and some <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=390356">overdue refactoring</a> and <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=396068">confessional documentation</a> that need to happen so I can leave with a clean conscience.</p>
<p>Cheers and thanks for all the fun!</p>
Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com4tag:blogger.com,1999:blog-846317186323356929.post-92031327586095798512013-01-29T08:44:00.000-08:002013-01-29T08:44:02.714-08:00A Journey Toward Web Components (Part 1)<p>A few months ago <a href="http://adventuresinthoughtlessness.blogspot.com/2012/10/more-css-less-js-orion-page-layout.html">I wrote about our efforts</a> to change the way we did page layout in Orion. Specifically, we did not want to rely on a JavaScript library to do our basic page grid, instead moving to a pure CSS solution. One of the outcomes of that effort was the necessity to write a small chunk of JavaScript code to provide an interactive splitter that would allow the user to change the layout or collapse a pane.</p>
<p>Recently, as a major goal of our Orion 2.0 release, we <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393810">removed even more library code</a> in order to improve our consumability and reduce our footprint. We had started out the project using dojo and dijit. But the browsers continue to add more native utilities, and we have the luxury of targeting only the most current browser implementations. It was becoming clear that we were using a smaller and smaller subset of the library, and we'd be better off using the existing browser support and small shims or other scripts as needed. Our editor had already been through this process, because it is consumed by browser tools such as Mozilla Scratchpad, where the adopter did not want to consume any additional utility libraries.</p>
<p>Newer versions of dojo (we were using a rather old 1.6) have refactored the library so that you only need to pull in the modules that you use. So we could solve a lot of the size problem by upgrading our library, but we had additional issues. Some of our adopters were already using dojo or dijit and wanted to upgrade at their own pace. Other consumers did not want to adopt any components that had additional dependencies. We also felt that our hybrid approach for components was causing additional complexity as we worked with different life cycles, theming, and layout approaches.</p>
<p>The exercise of removing our dependence on a utility and widget library was a pretty major effort, touching many lines of code in the Orion client. Our <a href="http://wiki.eclipse.org/index.php?title=Orion/Library_Independence">wiki page</a> kept a laundry list of the types of changes that were needed. Much of the effort involved mechanical changes from utility functions in dojo to newer browser functions. But there were also a few widgets we were using that needed to be replaced, namely the dropdown button and its associated menu, tooltips and popup dialogs, and modal dialogs.</p>
<a href="http://4.bp.blogspot.com/-V8MQl60-hbA/UQbm39hkiKI/AAAAAAAAAJU/X_RKidLxZgE/s1600/dropdownmenu.png" imageanchor="1" style=""><img border="0" height="279" width="320" src="http://4.bp.blogspot.com/-V8MQl60-hbA/UQbm39hkiKI/AAAAAAAAAJU/X_RKidLxZgE/s320/dropdownmenu.png" /></a>
<a href="http://4.bp.blogspot.com/-GmTVd6lMJi8/UQbqJ0M47-I/AAAAAAAAAJo/TziLxa95wUk/s1600/popups.png" imageanchor="1" style=""><img border="0" height="192" width="320" src="http://4.bp.blogspot.com/-GmTVd6lMJi8/UQbqJ0M47-I/AAAAAAAAAJo/TziLxa95wUk/s320/popups.png" /></a>
<p>We built these replacements after looking around at other implementations (such as plugins in jQuery or Twitter Bootstrap), and concluding that there wasn't much we could consume without adopting jQuery or some other library. Each replacement script was at most a few hundred lines of code, and the implementations were pretty straightforward. Most of these scripts supported pretty basic, low-level UI interactions.</p>
<ul>
<li>Attaching the right events (mouse clicks, keystrokes) to the DOM to get additional interactive behavior.</li>
<li>Styling (often just hiding and showing) different parts of the DOM according to user interaction.</li>
<li>Ensuring the right ARIA roles and attributes were set.</li>
<li>Managing default focus rules and keyboard traversal between fields.</li>
</ul>
<p>On one hand, replacing just a handful of widgets and modifying all of our client code to use browser utilities instead of library utilities is a great accomplishment for this release. Colleague Anton McConville reports a <a href="http://dev.eclipse.org/mhonarc/lists/orion-dev/msg02144.html">80% transfer reduction and 45% fewer page requests.</a> I have to say there was a big happy dance when we finally closed our <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393810">library independence bug.</a> </p>
<blockquote class="twitter-tweet"><p>when you close a bug that depends on 23 other bugs being closed first, that's got to feel good right @<a href="https://twitter.com/susanfmccourt">susanfmccourt</a> ?</p>— Ken Walker (@k_e_n__w) <a href="https://twitter.com/k_e_n__w/status/294521831229108225">January 24, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>So while I'm really happy about our move in this direction and pretty psyched to have completed such a big job, I'm left with a nagging feeling. The new code we had to write sounds like the kinds of things the browser should handle as UI components mature. So who's to say we won't be removing all these new implementations next year in favor of something different? Can we isolate this behavior so that our page markup is relatively stable and our JavaScript not sprinkled with API calls that we keep changing with the tides? </p>
<p>There are also some interesting technical questions surfacing during this exercise. If most of the replacement widgetry is described by HTML and CSS, and we are just tacking on some live behavior, who owns the HTML template? The application or the widget? For example, if I want to add splitter thumb behavior in the JavaScript, can my JavaScript splitter code add a splitter thumb node to the client DOM? Or does the client's markup have to include it? Folks coming from widget libraries are used to configuring things in API, and giving the widget more leeway in changing the native structure. Folks coming from pure HTML might consider it the client's job to know what nodes are needed in the template. As soon as we start trying to consistently address these issues, it starts to sound like we're building our own custom life-cycle and widget framework definition.</p>
<p>Then there's the matter of consumability. I've been struggling with what to call these new, small piles of code. Saying "widgets" as I've done above implies a replacement library. How can we communicate that all we want to do is add small bits of interactive behavior to the DOM that will hopefully be made obsolete by the browser someday? How can we share these small bits of behavior?</p>
<p>We are thinking the answer lies in <a href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">W3C Web Components</a>. Having completed this exercise of extracting widgetry and pushing as much definition as possible up into the DOM and CSS, we believe that the ultimate shape of this code should be custom DOM elements with rich interactive behaviors. So stay tuned. We've got a release to finish, but very soon we'll report back on efforts to implement one of these small bits of interactive behavior, such as our splitter, as a Web Component Custom Element.</p>Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com0tag:blogger.com,1999:blog-846317186323356929.post-81180450267425272002012-11-28T20:42:00.000-08:002012-11-28T20:42:27.117-08:00How CSS Triangles Work<p>Just search on "CSS Triangles" or "CSS Tooltip Triangles" and you'll see lots of posts showing how to use CSS borders to achieve a triangle.
</p>
<p>
I saw lots of pictures of triangles where I could copy the CSS but I didn't immediately grok how it worked. (I guess I don't use thick borders very often.) So here are the pictures I wish I'd seen in sequence. The first one (showing how thick borders are beveled around inner content) is the key. After that, you just imagine the inner content getting squished so that all you have left is triangles. Hope this helps.
</p>
<style type="text/css">
.zero {
height: 0;
width: 0;
}
.invisible {
border: 8px solid transparent;
}
.left {
border-left: 8px solid red;
}
.right {
border-right: 8px solid blue;
}
.bottom {
border-bottom: 8px solid green;
}
.top {
border-top: 8px solid orange;
}
.above:after {
position: absolute;
display: block;
border: 10px solid;
border-color: red transparent transparent;
left: 16px;
bottom: -20px;
content: '';
}
</style>
<h3>10 pixel borders on something with content</h3>
<div style="height: 100px; width: 100px" class="bottom top right left"></div>
<h3>10 pixel border on something empty</h3>
<div class="zero bottom top right left"></div>
<h3>Now just take the part you need</h3>
<p>Use transparency on all sides except where you want the triangle.</p>
<h4>Top</h4>
<div class="zero invisible top"></div>
<h4>Left</h4>
<div class="zero invisible left"></div>
<h4>Right</h4>
<div class="zero invisible right"></div>
<h4>Bottom</h4>
<div class="zero invisible bottom"></div>
<p>For tooltip tails, you just need to position an empty tail element relative to your tooltip element, and use negative coordinates to move the visible part of the border adjacent to the tooltip. One common trick is to generate the tail using a pseudo element in the CSS. This snippet is for tooltips appearing above an element. It generates an empty element after (below) the tooltip with a red tail that points downward toward the element.</p>
<pre>
.above:after {
position: absolute;
display: block;
border: 10px solid;
border-color: red transparent transparent;
left: 16px;
bottom: -20px;
content: '';
}
</pre>
<p>We are doing something like this in Orion, but the down side is that you end up with a flat tooltip (because only one element, the pseudo-element, renders the tail). For tooltips and tails with borders or shadows, you'll probably want to place multiple tail elements with different triangle effects. There are great examples out there so I won't cover that here. I just wanted to show the sequence of pictures that I wish I'd seen first.</p>Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com2tag:blogger.com,1999:blog-846317186323356929.post-25341872871142354022012-11-06T15:11:00.002-08:002012-11-09T07:26:48.052-08:00Dropping into Orion: HTML5 Drag and Drop<p>One of our goals for the next Orion release (2.0) is to make it a lot easier to get your stuff in and out of Orion. We've always supported uploading files, using SFTP, and cloning git repositories, but one could argue that the non-git scenarios haven't always been...errrrr...very usable. After fighting with Orion too much to get some image files replaced in a web site I'm playing with, I figured it was worth the time to implement support for dropping files from the desktop into Orion.</p>
<p>There are already a number of good articles and examples out there to follow, and I'm sure some of this discussion will be obsolete soon enough, as browser support evolves. In this post, I'll focus on Orion's role as the drop target for desktop files and folders, and some finer details such as feature detection, drop effects, and some notable browser differences.
</p>
<h2>Good starting points</h2>
<p>
A quick search on "HTML5 drag and drop" will give you plenty of articles and examples to start with, many of them over three years old. Here are a few that were key to my understanding.
<ul>
<li><a href="http://html5doctor.com/native-drag-and-drop/">Remy Sharp's HTML5 Doctor article</a> covers the API in breadth, from the perspective of both the "dragger" and the "droppee." His <a href="http://html5demos.com/drag-anything">Drag Anything Example</a> lets you drag items and see what the data objects in the API look like. This is great for checking things across browsers.</li>
<li><a href="http://www.htmlgoodies.com/html5/javascript/drag-files-into-the-browser-from-the-desktop-HTML5.html#fbid=oO1eYCjl5LZ">Robert Gravelle's HTMLGoodies example</a> focuses specifically on the API for desktop file drop.</li>
<li><a href="http://blog.protonet.info/post/26894439416/html5-drag-drop-files-and-folders">Christopher Blum's post</a> about folder support helped illuminate the difference between simple support for files and more advanced support of folders.</li>
<li>If you gravitate toward official specs, the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dnd">WHATWG Drag and Drop standard</a> is the authority.</li>
<li>If you want bleeding edge new features, you can read up on the <a href="http://wiki.whatwg.org/wiki/DragAndDropEntries">WHATWG wiki</a> to see extensions for drag data transfer.</li>
<li><a href="https://developer.mozilla.org/en-US/docs/DragDrop/Drag_and_Drop">Mozilla Developer Docs</a> are a great way to keep up with what is actually implemented in Firefox, including some special properties not in the generic spec.</li>
</ul>
</p>
<h2>Devil in the details</h2>
<p>Your first clue that you'll need to do a little digging is the second sentence in the spec.
<br><em>"This specification does not define exactly what a drag-and-drop operation actually is." </em>
<br>The sentence is actually referring to the UI gesture, and the fact that it might not be the traditional mouse down, move, mouse up sequence. But I think it's a good mantra to keep in mind anyway. Your code and the user's browser ultimately control the operation semantics.</p>
<h3>What can my browser do?</h3>
<p>Detecting what's implemented is important for setting user expectation. I checked <a href="http://modernizr.com/">Modernizr</a> to see what code is used to detect drag and drop support, and then quickly learned that detecting drag and drop support is not enough. For example, IE9 implements drag and drop, but not the file API that is needed to do desktop file drag and drop. You need to check for both. The <a href="https://github.com/Modernizr/Modernizr/tree/master/feature-detects">Modernizr feature detect directory</a> is a great place to browse the feature detection code. Using both of those checks, I can see if file drag/drop is supported.</p>
<pre>
var supportsFileDragDrop =
(('draggable' in myNode ) || ('ondragstart' in myNode && 'ondrop' in myNode )) &&
!!(window.File && window.FileList && window.FileReader);
</pre>
<p>The Orion navigator logs the lack of drag and drop support to the console in this case, and doesn't bother trying to hook up any events.</p>
<h3>What events to hook</h3>
<p>By default, only certain kinds of DOM elements recognize drag and drop. You need to hook four events to tell the browser that you want your DOM element to be a drop target. One of the initial brain-benders in this API is that since the default behavior is <strong>NOT</strong> to be a drop target, you have to hook some events and <em>prevent the default behavior and event propagation in order to cause the desired behavior to happen.</em> This takes a little getting used to and has caused some <a href="http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html">major ranting</a> about this API. The snippets below show you how to hook the events and minimally prevent the default browser processing. (These snippets are purposefully library independent, so perhaps a bit more verbose.)
<ul>
<li><strong>dragenter</strong> is where you tell the browser that your node wants to be a drop target. As mentioned, you do this by preventing the default browser behavior. You might also want to set a class on your node to indicate that it is a drop target.<br>
<pre>
node.addEventListener("dragenter", function(evt) {
node.classList.add("dropTarget");
evt.preventDefault();
evt.stopPropagation();
}, false);
</pre>
</li>
<li><strong>dragover</strong> is where you continue to express your undying loyalty to the idea of being a drop target. Again, you want to prevent the default event handling and bubbling. It sounds redundant, but this event gives you the opportunity in more complex scenarios to stop the drag if some state changes in your application.<br>
<pre>
node.addEventListener("dragover", function(evt) {
evt.preventDefault();
evt.stopPropagation();
}, false);
</pre></li>
<li><strong>drop</strong> is where the work for drop actually gets done. More on this soon enough.</li>
<li><strong>dragleave</strong> gives you a chance to clean up when the drag operation is done. For example, if you added a class when the drag began, you can remove it when the drag is done.
<pre>
node.addEventListener("dragleave", function(evt) {
node.classList.remove("dropTarget");
evt.preventDefault();
evt.stopPropagation();
}, false);
</pre>
</li>
</ul>
</p>
<h3>Handling dropped files</h3>
<p>
The <strong>dataTransfer</strong> property in the various drag events is where you can figure out what work to do. If your browser supports file drag and drop, this property should contain a list of files that are being dragged (or have been dropped.) You can use this to figure out if you want to accept the files or not. One caveat here is that folders will be in this list, also, and must be handled differently. In this snippet, we reverse engineer a way to tell if a file is indeed a folder.</p>
<pre>
node.addEventListener("drop", function(evt) {
if (evt.dataTransfer.files && evt.dataTransfer.files.length > 0) {
for (var i=0; i < evt.dataTransfer.files.length; i++) {
var file = evt.dataTransfer.files[i];
// this test is reverse engineered test for folders
// see http://www.w3.org/TR/FileAPI/#file
if (!file.length && (!file.type || file.type === "")) {
window.console.log("Skipping directory " + file.name);
} else {
dropFile(file); // upload this file to the Orion server
}
}
}
evt.preventDefault();
evt.stopPropagation();
}, false);
</pre>
<h3>Handling folders</h3>
<p>Dragging files is useful, but if you have a folder structure you want to drag into the Orion navigator, you want more than files. You want the folder structure to be replicated on the Orion server. Fortunately, this is a common requirement and the <a href="http://wiki.whatwg.org/wiki/DragAndDropEntries">Drag and Drop Entry</a> API allows you to traverse folder structures. At the time of this writing, this specification is only supported on Chrome (<a href="http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available">since Chrome 21</a>). We check for the file entry API in the drop event handler before reverting back to the file list.
<pre>
node.addEventListener("drop", function(evt) {
node.classList.remove("dragOver");
// webkit supports testing for and traversing directories
if (evt.dataTransfer.items && evt.dataTransfer.items.length > 0) {
for (var i=0; i < evt.dataTransfer.items.length; i++) {
var entry = null;
if (typeof evt.dataTransfer.items[i].getAsEntry === "function") {
entry = evt.dataTransfer.items[i].getAsEntry();
} else if (typeof evt.dataTransfer.items[i].webkitGetAsEntry === "function") {
entry = evt.dataTransfer.items[i].webkitGetAsEntry();
}
if (entry) {
dropFileEntry(entry, null, targetFolder);
} else {
window.console.log("Error processing " + evt.dataTransfer.items[i]);
}
}
} else {
// entries not supported, do the file list handling....
}
}, false);
</pre>
The <strong>dropFileEntry</strong> function checks to see if the file is a folder. It will traverse the folder contents if needed, creating Orion server directories along the way. This code is a bit more complex, as it is using Orion's deferred file API's, but I think it's better to show the real thing than to contrive an example. Here we already have some json data representing the <strong>target</strong> folder object on the server. For simplicity, we log messages to the console rather than reporting in the UI.
<pre>
function dropFileEntry(entry, path, target) {
path = path || "";
if (entry.isFile) {
// can't drop files directly into workspace.
if (target.Location.indexOf('/workspace') === 0){ //$NON-NLS-0$
window.console.log("You cannot copy files directly into the workspace. Create a folder first.");
} else {
entry.file(function(file) {
performDrop(target, file);
});
}
} else if (entry.isDirectory) {
var dirReader = entry.createReader();
// create a folder and then update the UI and traverse the folder content using our new folder as target
fileClient.createFolder(target.Location, entry.name).then(function(subFolder) {
explorer.changedItem(target, true);
dirReader.readEntries(function(entries) {
for (var i=0; i < entries.length; i++) {
dropFileEntry(entries[i], path + entry.name + "/", subFolder);
}
});
});
}
}
</pre>
</p>
<h3>Drop effects</h3>
<p>One annoyance with my initial implementation was that the icon shown during drag said "Move". But uploading a file or folder to a server is most definitely a copy. The API supports this, but not all browsers do yet. To specify that a copy is going to happen, you need to set the <b>dropEffect</b> in both the "dragenter" and "dragover" events. (Setting it only the "dragenter" was not enough. I tried.) I also added a check on the <b>effectAllowed</b> flag to ensure that "copy" is supported by the drag source.
<pre>
if (evt.dataTransfer.effectAllowed === "all" ||
evt.dataTransfer.effectAllowed === "uninitialized" ||
evt.dataTransfer.effectAllowed.indexOf("copy") >= 0) {
// only supported in Chrome.
evt.dataTransfer.dropEffect = "copy";
node.classList.add("dragOver");
}
</pre>
This gives me a proper copy icon on Chrome.
<a href="http://1.bp.blogspot.com/-ul7tI19TyG0/UJmV0xvuhWI/AAAAAAAAAIc/ad3VBEAQsqs/s1600/drag.png" imageanchor="1" style=""><img border="0" height="223" width="320" src="http://1.bp.blogspot.com/-ul7tI19TyG0/UJmV0xvuhWI/AAAAAAAAAIc/ad3VBEAQsqs/s320/drag.png" /></a>
<br>
Unfortunately we have a misleading "move" icon on Firefox. That issue is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=484511">tracked in bugzilla</a>.
</p>
<h2>Bleeding edge</h2>
<p>If you've stumbled upon this post and it's not early November 2012, make sure you check all the spec and proposal links in this article to understand the state of the art for both the spec and for browser support. My goal here is to show you some code you can work with, but more importantly show you the places to check for the latest information, and also how to check to see what your browser can do. When searching for the latest and greatest, you'll want to be specific, not just about drag and drop, but about the File API and the Drag Entry API.</p>
Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com5tag:blogger.com,1999:blog-846317186323356929.post-19320952809176108162012-10-19T11:13:00.000-07:002012-10-19T11:13:37.379-07:00Commanding Orion's Editor<p>In a very readable (and pretty) post, <a href="http://blog.peepcode.com/blog/2012/commanding-your-text-editor">Commanding Your Editor</a>, Geoffrey Grosenbach claims that you can learn six simple commands, rather than hundreds, and instantly increase your productivity in your code editor. When I realized that the first two commands in Geoffrey's article weren't implemented by default in Orion, I thought it'd be fun to review the six commands, and how you might do the same kinds of things in Orion.</p>
<p>Orion's editor commands and key bindings are mostly borrowed from <a href="http://en.wikipedia.org/wiki/Eclipse_%28software%29">Eclipse</a>, and we've not done a great job of exposing them to the end user. We've sometimes assumed people know them already from Eclipse or will figure them out. Given that we are seeing lots of activity on <a href="orionhub.org">orionhub.org</a> as folks try out Orion for the first time, it's probably a good time to go over some of the editor power commands. Let's start with Geoffrey's favorite six, and then add a few more.</p>
<h2>The mighty six?</h2>
<h3>Delete whole words</h3>
<p>The motivation is that if you have a typo, it's easier and faster to retype the whole word than to try to correct the part that's wrong. Orion doesn't specifically implement keystrokes for deleting the current, next, or previous word, but you can use <b>Ctrl+Backspace</b> to delete from your current position to the beginning of the word, or <b>Ctrl+Del</b> to delete from your position to the end. And you can use <b>Ctrl+Left Arrow</b> and <b>Ctrl+Right Arrow</b> to first navigate to the front or end of the word. I have to say that I'm much more likely to have already selected the word some other way (such as using <b>Find</b>) and then I simply type over it. So I haven't missed this command. If you can't live without a command to delete the current word, it sounds like the perfect candidate for an <a href="http://wiki.eclipse.org/Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.command">editor command extension</a> (and perhaps I'll show how in my next post).</p>
<h3>Add lines</h3>
<p>Geoffrey's premise is that it's a lot faster to add a line above or below from anywhere in the line, rather than cursoring to the end of a line and hitting return. I must admit that the extra keystroke to cursor to beginning or end of a line hasn't bothered me. Once again, you'd need to write an editor command extension to get this exact functionality, but it'd be simple enough. Our current commands have evolved as committers add the ones that they miss the most.</p>
<h3>In-file search</h3>
<p>Now we're talking. Orion has a pretty advanced in-file search. Use <b>Ctrl+F</b> to open a prompt and type in the word you are looking for. You'll see the matches light up in the editor. You can move to the next match using <b>Enter</b> or <b>Ctrl+K</b> and the previous match using <b>Shift+Enter</b> or <b>Ctrl+Shift+K</b>. (You can also use the next and previous buttons in the prompt.) A number of options are available to you from the prompt menu to fine tune your search, including regular expressions.</p>
<a href="http://1.bp.blogspot.com/-E8AyaRXLt70/UIGG1PWRUMI/AAAAAAAAAFo/sEVDTVgw4-0/s1600/findreplace.png" imageanchor="1" style=""><img border="0" height="113" width="320" src="http://1.bp.blogspot.com/-E8AyaRXLt70/UIGG1PWRUMI/AAAAAAAAAFo/sEVDTVgw4-0/s320/findreplace.png" /></a>
<p>Once you've found the word you are looking for, hit <b>Escape</b> to return focus to the editor, where you can type over that pesky incorrect word.</p>
<p>If you prefer not to move your eyes away from the editor cursor, Orion also provides an <i>Incremental search mode</i> (sometimes called <i>live search</i> in other editors) that doesn't open a prompt. To use incremental search, you use <b>Ctrl+J</b> to start live search. Your focus remains in the editor, but your typing applies to the search rather than the editor content. The editor status area in the toolbar will show you that you are in this mode. The editor will position you to the match (or give you a message in the toolbar if there's no match). </p><a href="http://3.bp.blogspot.com/-9Pll1BUYaQI/UIGImtZ5DjI/AAAAAAAAAF0/2HqDdFshq7Q/s1600/incremental.png" imageanchor="1" style=""><img border="0" height="125" width="320" src="http://3.bp.blogspot.com/-9Pll1BUYaQI/UIGImtZ5DjI/AAAAAAAAAF0/2HqDdFshq7Q/s320/incremental.png" /></a>
<p>You can use <b>Ctrl+J</b> to move to the next match. Pressing <b>Escape</b> ends the mode.</p>
<p>Of course, since Orion is part of a larger development environment, you can also perform searches across multiple files and do global replacements. That's another topic completely, and is described pretty well in the <a href="http://wiki.eclipse.org/Orion/Documentation/User_Guide/Tasks/Navigating_and_searching">Orion user doc</a>.</p>
<h3>Fuzzy file search</h3>
<p>You can open other files in the editor using the <b>Find File Named</b> command, <b>Ctrl+Shift+F</b>. The popup will look for matching file names, in addition to initially offering you the files you've marked as favorites. You can use wildcards to find the file. (We could do better here, highlighting the part of the pattern that matches.)</p><a href="http://2.bp.blogspot.com/-OObj3KJtJhE/UIGJN0g3-II/AAAAAAAAAGA/GlH3VZm82Mg/s1600/findfile.png" imageanchor="1" style=""><img border="0" height="209" width="320" src="http://2.bp.blogspot.com/-OObj3KJtJhE/UIGJN0g3-II/AAAAAAAAAGA/GlH3VZm82Mg/s320/findfile.png" /></a>
<p>If you are looking for path name matching, it's not currently supported from the file search. However, because the Orion editor is in a browser, you can find previously edited files by path name using the browser bar. You are of course at the mercy of your browser. Firefox does a pretty good job with this kind of path matching.</p><a href="http://2.bp.blogspot.com/-k1MOzVWkMbA/UIGKKNa-r6I/AAAAAAAAAGM/pTyvsAUkoTM/s1600/filepathsearch.png" imageanchor="1" style=""><img border="0" height="96" width="320" src="http://2.bp.blogspot.com/-k1MOzVWkMbA/UIGKKNa-r6I/AAAAAAAAAGM/pTyvsAUkoTM/s320/filepathsearch.png" /></a>
<h3>Automatic indentation</h3>
<p>
Orion's automatic indentation is pretty simple. It simply preserves the indent of the previous line. We don't (yet) recognize language specific blocks and indent. We do support automatic code formatting through plugins such as <a href="jsbeautifier.org">jsbeautifier</a>.</p>
<h3>Completion</h3>
<p>
Like Eclipse, you can invoke code completion using <b>Ctrl+Space</b>. Code completion has come a long way in Orion, thanks largely to the <a href="http://esprima.org/">Esprima</a> parsing engine and an Esprima-based plugin committed by our VMWare colleagues. Esprima-based content assist is now installed by default in Orion 1.0, so your code completions for JavaScript code are type-inferenced. Non-inferred proposals are also suggested (at the bottom of the list).
<a href="http://4.bp.blogspot.com/-I5d0_8JesOQ/UIGLK0SNtMI/AAAAAAAAAGY/DdmK0opzcms/s1600/contentassist.png" imageanchor="1" style=""><img border="0" height="165" width="320" src="http://4.bp.blogspot.com/-I5d0_8JesOQ/UIGLK0SNtMI/AAAAAAAAAGY/DdmK0opzcms/s320/contentassist.png" /></a>
</p>
<h2>More mightiness</h2>
<p>
What else should you know? First and foremost, you should know that you can find a complete list of keybindings and commands in the Orion editor by pressing <b>Alt+Shift+?</b> (or <b>Ctrl+Shift+?</b> on Mac OS X). </p>
<a href="http://4.bp.blogspot.com/-zatlj4-BZXY/UIGPn43F8gI/AAAAAAAAAG4/LqPNcecnV5w/s1600/keybindings.png" imageanchor="1" style=""><img border="0" height="201" width="320" src="http://4.bp.blogspot.com/-zatlj4-BZXY/UIGPn43F8gI/AAAAAAAAAG4/LqPNcecnV5w/s320/keybindings.png" /></a>
<h3>Maximizing space</h3>
<p>By default, the Orion editor opens with an outliner that lets you traverse your code by function. You can use <b>Ctrl+O</b> to hide the outliner. It's a toggle key, so you can use the same key binding to get the outliner back. You can also use <b>Ctrl+Shift+M</b> to "maximize" the editor, hiding the Orion banner and footer. This key is also a toggle. The end result is just the editor and its toolbar.</p><a href="http://1.bp.blogspot.com/-OBEI9aHIclI/UIGOiRm0pgI/AAAAAAAAAGs/ys56jdJXfqA/s1600/justeditor.png" imageanchor="1" style=""><img border="0" height="197" width="320" src="http://1.bp.blogspot.com/-OBEI9aHIclI/UIGOiRm0pgI/AAAAAAAAAGs/ys56jdJXfqA/s320/justeditor.png" /></a>
<h3>Navigating to errors</h3>
<p>The Orion editor shows annotations in a ruler on the right of the source file. Most folks know you can click on these annotations, or hover on them, to find out about errors and warnings in your file. Power users know that you can quickly move between annotations using <b>Ctrl+.</b> to move forward, or <b>Ctrl+,</b> to move backward. This works great for correcting errors that our built-in <a href="http://www.jslint.com/">jslint</a> validator finds.</p>
<h3>Toggle line comment</h3>
<p>You can use <b>Ctrl+/</b> to comment or uncomment a line of code. This works great when you are working with tracing logs or other debug code that you often toggle on and off.</p>
<h3>Moving lines around</h3>
<p>You can use <b>Alt+Up Arrow</b> and <b>Alt+Down Arrow</b> to move the current line up and down. If you have more than one line of text selected, you can use these commands to move multiple lines up and down without precisely selecting the whole lines. Adding the <b>Ctrl</b> key to use <b>Ctrl+Alt+Up Arrow</b> and <b>Ctrl+Alt+Down Arrow</b> will copy the line(s) around.</p>
<h3>Deleting a line</h3>
<p>You can use <b>Ctrl+D</b> to delete the current line. If you have more than one line of text selected, you can delete them all without precisely selecting the whole lines.</p>
<h3>Goto line</h3>
<p>You can use <b>Ctrl+L</b> to go to a particular line by line number. This is especially useful when you see an error in the browser debugger and you want to quickly go to the offending line in Orion.</p>
<h2>Going forward</h2>
<p>We certainly hope to do a better job of exposing all the powerful commands that the Orion editor provides. And we hope to see the community continue to add commands using our extension mechanisms. If you have your own ideas about "can't live without" editing commands, please consider writing an Orion plugin that contributes some of these! In a future post I'll show how simple that is. Some of our most powerful features started out as a plugin hosted at somebody else's site, and then became so widely adopted that they've been contributed back into the Orion base platform.</p>
<p>Thanks to Geoffrey Grosenbach for sparking the conversation (and for not naming his post something like "Six Brilliant Editor Commands You Must Know"). Thanks also to colleague <a href="https://twitter.com/mamacdon">Mark MacDonald</a> for suggesting some of the Orion commands to mention (he is much more the power user than me!)</p>
Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com0tag:blogger.com,1999:blog-846317186323356929.post-40742394828795145302012-10-04T20:10:00.000-07:002013-01-29T09:10:24.992-08:00More CSS, less JS: Orion Page Layout<p>We're in the "end game" of the Orion 1.0 release, and I realize that one of my bigger efforts won't surface in any of our end-user oriented <a href="http://planetorion.org/news/2012/09/orion-1-0-m2-new-and-noteworthy/">New and Noteworthy</a> lists. This summer, I revamped our JS-based approach for page layout and instead use mostly CSS for our layout and animation. Why didn't we do this in the first place? Here's a story about that.</p>
<h2>Viewports and layout</h2>
<p>Our very first Orion page was our editor. Given that a user might be editing a huge file, and working with only a small part of it, the editor does not render the entire document. It adds elements to the DOM as needed. The browser page can't do the scrolling since it doesn't know about the editor viewport. That meant we needed to pin the page footer to the bottom of the editor page, giving the editor the chunk of real estate between the header and footer. </p><a href="http://1.bp.blogspot.com/-ynt00syac8A/UG3avS0wF-I/AAAAAAAAAFU/SGJyF8ivg6Y/s1600/virtualviewport.png" imageanchor="1" style=""><img border="0" height="197" width="320" src="http://1.bp.blogspot.com/-ynt00syac8A/UG3avS0wF-I/AAAAAAAAAFU/SGJyF8ivg6Y/s320/virtualviewport.png" /></a>
<p>We found that dijit's <a href="http://livedocs.dojotoolkit.org/dijit/layout/BorderContainer">BorderContainer</a> managed exactly this kind of layout and happily delegated the positioning work to this widget. This approach was adopted for the rest of our Orion pages. It didn't immediately occur to me that the editor layout was really a special case, until I started watching sites like github move to <a href="https://github.com/blog/1007-skinny-header">skinnier headers</a> (and the requisite fatter footers). As footers became fatter (taller?), the fact that our footers were unnecessarily pinned to the page bottom really started to bother me. Shouldn't we be able to have a bottom area under a split main panel, but not have to pin it to the bottom?</p>
<h2>The pain of a hybrid approach</h2>
<p>That wasn't the only thing bugging me. Most of our UI implementation does not use dijit widgets. We have many of our own UI components, such as the editor, navigator, and compare view. We rely on dijit for things like menus, dropdowns and dialogs. It turns out that using dijit layout mechanisms to manage both dijit and non-dijit components is a pain. The dijit layouts very nicely handle the ripple associated with widget size changes and layout. But if your component is not a dijit widget, you end up with code that has to walk up the DOM looking for dijit layout managers to inform about what you've just done in the DOM. This just felt...errr....<b>wrong</b>. Note I'm not saying dijit layout is bad, just that a hybrid approach is bad. We needed to either embrace the dijit widget and layout model with all our components, or stop using dijit layout. The first idea wasn't viable because folks who consume our editor don't want to bring in a library they don't already use. And doesn't the rest of the world just use CSS?</p>
<h2>Leaner layout</h2>
<p>After looking at a few different grid systems and site templates, the first thing to decide was whether we were trying to build a generic grid and layout system or just solve our own problems. Orion plugins are either contributing behavior to our pages or linking to their own. Since it doesn't matter to us how you accomplish your layout, our solution needn't be too general or generic (a departure from our Eclipse thinking!)</p>
<h3>Page regions</h3>
<p>A quick tour of our pages showed that we have (at most) four regions to contend with. The header, the footer, an optional side panel, and main panel. The CSS classes use this terminology throughout. The model is one of a "side panel" defaulting to 1/3 width on the left and a "main panel" taking the rest of the room. A page always has a fixed header but may have a fluid footer (at the bottom of content) or a fixed footer on the bottom of the page. Part of the exercise in establishing this model was separating out the layout classes from the other styling, moving all of our layout related css to its <a href="https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.ui/web/css/layout.css">own layout file</a>.</p>
<h3>Splitters</h3>
<p>A missing piece was the splitter. By keeping the splitter very particular to Orion's model of a vertical split between side and main panel, this was only a <a href="https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.ui/web/orion/webui/splitter.js">couple hundred lines of JS</a>, including reasonable documentation. Splitter classes in the CSS control the default positioning and animation effects. The splitter is the only JS code managing any of our main page layout.</p>
<h3>CSS Transitions</h3>
<p>We previously relied on dojo's animation features to animate the effect of the side panel opening and closing. Now we've adopted simple CSS transitions for animating this effect. The downside is that you won't see the animation at play in older browsers like IE9, but the upside is that the animation is smoother, faster, and <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=386677">less buggy</a>.</p>
<h3>Some details</h3>
<p>If you read <a href="https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.ui/web/css/layout.css">the CSS</a>, you'll see it's mostly about the concepts I've described here. A few more details are involved.</p>
<h4>Toolbars</h4>
<p>Classes dealing with the toolbar ensure that the toolbar maintains a fixed vertical position and that message bars and input bars appear in the right place underneath the toolbar, letting the rest of the main panel scroll.</p>
<h4>dijitManagesLayout</h4>
<p>We have some CSS classes for pages to use if they are still using dijit layout widgets inside their implementation. At that point, it's up the page to deal with any "hybrid" problems when dijit is managing non-dijit widgets. We just need to know when dijit layout is taking over.
<h2>Fluid footers</h2>
<p>So where are those fluid footers? Since our footer is still pretty skinny, there wasn't a crying a need to revisit the footer content and pinning behavior for 1.0. Even so, I'm very happy with the result of this effort. We got rid of a lot of code, the animations are smoother, the DOM is simpler to debug, and our CSS is better organized. </p>Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com1tag:blogger.com,1999:blog-846317186323356929.post-59317489094955940292012-03-26T20:00:00.000-07:002012-03-26T20:00:18.733-07:00Delegated Content, Indirection, and the Two-Way Street<p>Seems like we just wrapped up the Orion 0.4 release, but the web never sleeps. One point of emphasis for our 0.5 effort is to develop a story for <a href="http://wiki.eclipse.org/Orion/Visual_Plugin_Strategy">visual plugins</a>. Our first stake in the ground when we started building Orion was that the browser should be the IDE, not Orion itself. In the cloud, your tools might come from anywhere, and our job in Orion is to provide pages for important development tasks (like JavaScript/HTML/CSS editing, managing code contributions, etc.) and an integration platform to let you seamlessly link to the pages needed to perform your development tasks.</p>
<p>In discussions about plugins and extension points, we have resisted the idea of the IDE mashup, where we provide visual extension points in the way that Eclipse defined views and editors. We want the user to use the browser (or browser extensions) to arrange the pages the way they see fit, building an IDE from task-focused pages. That said, we know that simply linking from Orion to tools at other sites is not a well integrated workflow. So one way of dipping our toe into the visual plugin waters is to provide a way for a plug-in to contribute page content that is wrapped inside the common Orion page "chrome." There is little, if any, interaction between the content and the chrome to start with. But by starting with some very shallow integrations that solve real world problems, we hope to advance the level of integration between third party content and the common Orion services.</p>
<h2>Delegated content vs. consumable chrome</h2>
There are two directions, outward and inward, in which we can think about integrating third party content with Orion. With <b>delegated content,</b> we can provide an Orion page that has all the common page trim, but delegates its content outward to a plug-in. In a <b>consumable chrome</b> scenario, we provide a javascript library that can be consumed by a third party page. The page brings the Orion chrome inward, by making library calls that assemble the interesting links back to Orion. Both scenarios are reasonable ways to go about the problem, and we think that the things that content and chrome want to talk to each other about are the same in either case. Our first explorations have been with delegated content, for two reasons:
<ul>
<li>With delegated content, we can bring unmodified content into an Orion page that was developed without any knowledge of Orion. We can use sites with existing embedding conventions and web API inside of Orion. It's important to learn how far we can push this kind of integration. Can a usable workflow be built from parts that know nothing about each other?</li>
<li>Building a small, performant consumable chrome library requires some refactoring. Today, the Orion banner is rendered by pages in Orion, so the banner code has access to everything from the service registry and extension points to the Orion workspace. Refactoring this code so that a banner library could access Orion services remotely requires a bit more work, and a bit more understanding of the problem.</li>
</ul>
</p>
<h2>The most shallow integration</h2>
<p>We start with a very shallow integration. We want to link to an external site from Orion, and launch it inside an Orion page so that the user can link back to Orion. Any number of simple integrations can be done in this manner. We'll use a <a href="webchat.freenode.net">WebChat</a> plugin to show how it works. The plugin source is <a href="http://sfmccourt.github.com/plugins/webchat/webChatPlugin.html">here</a>.</p>
<p>We start by defining a new service extension point, <b>orion.page.content</b>. In its simplest form, this extension point describes the name of the visual plugin, the id of the contribution, and a URI Template that describes how to link to the content. The WebChat plugin looks like this:</p>
<pre>
provider.registerServiceProvider("orion.page.content", {}, {
id: "orion.webchat.content",
name: "Webchat",
uriTemplate: "http://webchat.freenode.net?channels=eclipse-orion&uio=MT1mYWxzZSY5PXRydWUmMTE9MjI207"
});
</pre>
<p>The URL was obtained by using the "Add webchat to your site" wizard to create a custom URL that opens webchat up on the <b>orion-dev</b> IRC channel. To link to our new page from Orion, we add a link to the main Orion banner using the <b>orion.page.link</b> extension. The main point of interest here is that the href instructs Orion to open the content page (the Orion page that hosts delegated content) and specifies the id of the content provider. This id must match the id in the above extension point. The {OrionHome} variable is used to fully qualify the address to the content page.</p>
<pre>
provider.registerServiceProvider("orion.page.link", serviceImpl, {
name: "Webchat",
id: "orion.webchat.link",
href: "{OrionHome}/content/content.html#,contentProvider=orion.webchat.content"
});
</pre>
<p>When the Webchat link is clicked, the delegated content page will be opened and the URI specified in the <b>orion.page.content</b> extension will be loaded into the page content. The end result is a webchat page wrapped in the Orion chrome.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-htdG3LWuf6A/T3DuzRecvXI/AAAAAAAAAEM/2c9nv3aHY28/s1600/webchat.png" imageanchor="1" style=""><img border="0" height="202" width="320" src="http://4.bp.blogspot.com/-htdG3LWuf6A/T3DuzRecvXI/AAAAAAAAAEM/2c9nv3aHY28/s320/webchat.png" /></a></div>
<p>This isn't too earth shattering, but already we have external content that looks like it belongs in Orion and can link back to orion via the banner.</p>
<h2>Indirection from the workspace and back</h2>
<p>A more interesting scenario is that of the remote editor. Web developers often need to edit more than just JavaScript, CSS, or HTML. One common task is to edit the images that are shown on a site. We decided to integrate a web-based image editor using the visual plugin idea. We chose the <a href="http://pixlr.com/editor/">Pixlr</a> image editor because it is written to be embedded in other pages, and it also has an API for launching the editor on remote content and configuring it in specific ways. Our goal was to implement an open/edit/save workflow using Orion extension points and the existing Pixlr API. In this scenario, the integrating plugin and the use of URI template variables provide a level of indirection that glues together the Orion and Pixlr API.</p>
<p>We start with two existing extension points, <b>orion.edit.editor</b> and <b>orion.navigate.openWith</b>. The editor extension defines an image editor and the link for opening it. You'll notice that the link is very similar to the Webchat link. The navigator extension associates this editor with files that have image content types.</p>
<pre>
provider.registerServiceProvider("orion.edit.editor", {}, {
id: "orion.pixlr",
name: "Pixlr Image Editor",
uriTemplate: "{OrionHome}/content/content.html#{Location},contentProvider=orion.pixlr.content"
});
provider.registerServiceProvider("orion.navigate.openWith", {}, {
editor: "orion.pixlr",
contentType: ["image.gif", "image.jpeg", "image.ico", "image.png","image.tiff"]
});
</pre>
<p>If you followed the first example carefully, you'll already expect to see an <b>orion.page.content</b> extension point whose id is "orion.pixlr.content." The uriTemplate for the editor is using the delegated content page with the pixlr contentProvider id. There is also a new variable in the URI template, the {Location} variable. This variable will be filled in with the location of the resource on which the editor is opened.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-jbg6mARCxC4/T3D1JYfk-qI/AAAAAAAAAEY/CIZ19zq4jpY/s1600/pixlrlaunch.png" imageanchor="1" style=""><img border="0" height="211" width="320" src="http://4.bp.blogspot.com/-jbg6mARCxC4/T3D1JYfk-qI/AAAAAAAAAEY/CIZ19zq4jpY/s320/pixlrlaunch.png" /></a></div>
<p>The URI template used in the pixlr content extension is a bit more complicated than Webchat, because it uses the pixlr API to open pixlr on the image that was selected in the navigator.</p>
<pre>
provider.registerServiceProvider("orion.page.content", {}, {
id: "orion.pixlr.content",
name: "Pixlr",
saveToken: ["imgapi?image=","imgapi&image="],
saveTokenTerminator: "&",
uriTemplate: "http://pixlr.com/editor/?image={OrionHome}{Location}&referrer=Orion&title={Name}&locktype=true&exit={ExitURL}&target={SaveURL}imgapi&locktitle=true,contentProvider=orion.pixlr.content"
});
</pre>
<p>
The template opens pixlr, but uses the {OrionHome} and {Location} URI template parameters to tell Pixlr where to find the image file. Those variables will be set by the content page to the Orion installation and the location of the resource that was selected in the navigator. The {Name} variable fills in the name of the file, which Pixlr can use when showing the file. Armed with this information, Pixlr can be opened on the proper file. Since the hosting content page knows where the file lives in the workspace, the banner includes a complete breadcrumb and all related pages associated with that file.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-wAnbyyFmJU8/T3D3xmkcoTI/AAAAAAAAAEk/ZdqXyNXcDEg/s1600/pixlredit.png" imageanchor="1" style=""><img border="0" height="207" width="320" src="http://1.bp.blogspot.com/-wAnbyyFmJU8/T3D3xmkcoTI/AAAAAAAAAEk/ZdqXyNXcDEg/s320/pixlredit.png" /></a></div>
<p>
While you're in the pixlr editor, there's nothing specific to Orion going on. However, when you get ready to save the file, you'll see that Orion is a possible destination for the save.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-vMmbsH4DWMY/T3D4Jzjkl1I/AAAAAAAAAEw/OakLryVSBjM/s1600/pixlrsave.png" imageanchor="1" style=""><img border="0" height="176" width="320" src="http://2.bp.blogspot.com/-vMmbsH4DWMY/T3D4Jzjkl1I/AAAAAAAAAEw/OakLryVSBjM/s320/pixlrsave.png" /></a></div>
<p>
The appearance of Orion in the save dialog comes about because of the Pixlr invocation API. The <b>referrer</b> and <b>target</b> parameters give Pixlr a name and URL to use for saving the resulting file. When calling the provided URL, Pixlr provides a parameter that specifies the location of the saved file. The <b>saveToken</b> and <b>saveTokenTerminator</b> parameters for the extension point provide additional information for parsing the location out of the save URL. All of this means that when the user saves the file, Pixlr calls the provided Save URL, which is an Orion page. The content iframe now contains the save page, which can parse the URL to determine the location of the file and confirm with the user that the content should be saved back to Orion.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-ZksnfDoE0Qk/T3D5h6hiDFI/AAAAAAAAAE8/0hkVW4go9YM/s1600/pixlrsave2.png" imageanchor="1" style=""><img border="0" height="123" width="320" src="http://4.bp.blogspot.com/-ZksnfDoE0Qk/T3D5h6hiDFI/AAAAAAAAAE8/0hkVW4go9YM/s320/pixlrsave2.png" /></a></div>
<p>
The workflow is not ideal, but is somewhat usable. Because the file save URL is invoked by Pixlr with an HTTP GET, the URL should be stable. It cannot actually store the file. Instead, we put up a page that lets the user approve the saving of the file back to Orion. A link to the file is provided so that the user can look at the file and make sure that it should be saved. These extra confirmation steps mean that the workflow is not ideal for an "edit/save/edit/save/edit/save" lifecycle, but it definitely saves the user the step of downloading an image, editing it, and uploading it back into the Orion workspace.
</p>
<h2>Toward a two-way street</h2>
<p>
So far, we've shown how you can integrate an editor using delegated content. Though the workflow is a bit clunky, what's promising about this scenario is that three domains are involved, and only one (the plugin code) knows about the integration. Orion hosts the page and renders the common page elements. A plugin hosted at github uses knowledge of the Pixlr API to describe an editor. The Pixlr site provides the content, using existing API, without any knowledge of its hosting page. We imagine that many more integrations of this type can be developed independently of Orion, providing some shallow but useful integrations. Add some additional indirection, such as <a href="http://webintents.org/">web intents actions</a>, and we could have a breadth of editing scenarios available in Orion.
</p>
<p>
The next step is to start working on a "two way street" concept. The examples here still use the "don't call us, we'll call you" model of Orion plugins. The Pixlr plugin extends Orion in specific ways, and it is called when Orion needs to do something with the plugin. We also make a lot of simplifying assumptions in the code that allow this scenario to work. The fact that we implement our own page to receive the save request means that we can develop our own internal handshake for having the save page signal the outer page that the workspace save should be performed. If instead, we implemented some service APIs that plugins could use to talk to the host page, we could provide even better integration.
</p>
<ul>
<li>So far, the remote content is available to Pixlr only when the Orion workspace is "world readable." So data hosted on orionhub will be visible to Pixlr, but data from your localhost would not be. We need to come up with a more general story for exporting data from Orion to a publicly readable space on the web (with user permission.)</li>
<li>The save scenario only works because Pixlr lets us specify a save URL, and we have developed a page that performs the save. We also use a specific window.postMessage handshake for the inner save page to signal the outer page that save should happen. We'd like to expose the file service in some way to the plugin so that the save could be performed directly by the plugin. Even for plugins unaware of Orion, the Orion save page could use API to perform the save rather than signal the host page to do it.</li>
<li>You likely noticed that the Pixlr editor has its own menu bar, while the Orion toolbar is empty. Imagine an Orion-aware remote editor that instead contributed commands to the Orion toolbar.</li>
<li>Allowing Pixlr to post progress, status, or error information to the Orion page would improve the integration. Likewise, it would be nice if any prompts or confirmations would be performed by the outer page.</li>
<li>The keybindings inside and outside the content iframe are completely different. It'd be nice to see some of the common Orion bindings work even when focus is in the inner content area.</li>
</ul>
<p>
As you can see, even the simplest integration attempts produce a pretty good laundry list of what we'd like to see. We'll continue to deepen these integrations throughout the 0.5 release. In the meantime, we invite you to try to integrate your favorite tool into Orion and let us know how it goes.
</p>Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com0tag:blogger.com,1999:blog-846317186323356929.post-23473063630704396822012-02-27T15:39:00.000-08:002012-02-27T15:39:33.673-08:00The Power of Semantics<p>Last month, I <a href="http://adventuresinthoughtlessness.blogspot.com/2012/01/anatomy-of-orion-page.html">wrote about our attempts to build a semi-formal anatomy</a> of Orion's common page elements. This anatomy seemed more important than focusing too strongly on a particular visual look or layouts. I also (somewhat optimistically) asserted that by the time we finish 0.4 you wouldn't have to think about this anatomy, but instead would simply think, "wow, these guys always get those links and buttons in just the place I expect them to be!"
</p>
<p>
So, how'd we do? Release 0.4 is done for all practical purposes. The <a href="http://planetorion.org/news/2012/01/orion-0-4-m2-new-and-noteworthy/">M2 new and noteworthy</a> gives a taste of what we've been up to lately, and the summary of all the 0.4 new and noteworthy should be out in a couple of days. I think it's important, though, to spend time thinking about some of our new features in terms of both "syntax" and "semantics."
</p>
<p>In the web world, we all know about separation of styling (CSS) from the structure and content (HTML elements) on a page. But I'm talking about a distinction that goes beyond styling vs. structure. In the context of what's on a web page, I think of the styling and structure (layout, colors, fonts, buttons, graphics, words) as our syntax. The semantics are really the meaning behind that structure. Why do the various parts of the page appear where they do? How did we end up with those elements? Describing an additional level of semantics can help us not only design better pages, but provide function in ways we hadn't imagined before.
</p>
<p>
So I'd like to look at a few new Orion features in 0.4. For every screenshot of something new, I'd like to discuss not only the feature, but where we've made strides in the semantics behind it, and how this can help Orion get even better.
</p>
<h2>"New look" in the Orion page header</h2>
<p>
In Orion 0.4, you'll notice a new look. The header is divided into a skinnier common banner at the top and a taller page heading below.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-qWTwK7fjEek/T0v4MxsJ4MI/AAAAAAAAAC4/QPTMiZQRd_M/s1600/header04.png" imageanchor="1" style=""><img border="0" height="58" width="320" src="http://2.bp.blogspot.com/-qWTwK7fjEek/T0v4MxsJ4MI/AAAAAAAAAC4/QPTMiZQRd_M/s320/header04.png" /></a></div>
<h3>Syntax</h3>
<p>
From a presentation point of view, there are many things to notice. Some are simply stylistic changes, some represent a little more thought about the user tasks and workflows.
<ul>
<li>It's lighter and brighter than the previous gray, more contrast at the top.</li>
<li>Different fonts and colors than before.</li>
<li>The static part (logo, navigation links, user profile) is separated visually from the dynamic part (page title, breadcrumb, etc.)</li>
<li>The static part makes the header feel skinnier, while the dynamic part leaves more room for potentially lengthy content, such as a very long path name.</li>
</ul>
</p>
<h3>Semantics</h3>
<p>
The items in the header are powered by a <a href="http://wiki.eclipse.org/Orion/Page_Layout#Page_Elements">page anatomy</a>. The idea here is that if a page can say a few things about itself to the common header code, the header can figure out how to present it in terms of a title, a breadcrumb, and a location. There <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349531">is still work to do on the API side</a>, but I think focusing on the structure of a page and how it influences the heading is laying the groundwork for future improvement. A page that can describe itself semantically can inherit interesting common function that goes beyond the presentation. For example, let's consider another feature in Orion 0.4 that is powered by the same idea.
</p>
<h2>"Related pages" menu</h2>
<p>
One of the usability goals for Orion 0.4 was to make it easier to move around within Orion. We wanted to identify the common workflows and make sure it's easy to move within or between pages to accomplish a task. So we've added a "Related pages" menu that gives you a handful of choices for other pages you might be interested in, based on what you are working with on the current page.
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-jio9KR6uw30/T0v9Vav29nI/AAAAAAAAADE/5uRfTBXiCnM/s1600/relatedpages.png" imageanchor="1" style=""><img border="0" height="107" width="320" src="http://1.bp.blogspot.com/-jio9KR6uw30/T0v9Vav29nI/AAAAAAAAADE/5uRfTBXiCnM/s320/relatedpages.png" /></a></div>
<h3>Syntax</h3>
<p>
One reaction to this feature could be, "it's about time." What's so hard about adding a link on the editor page to "Git Status" when the file I'm editing is in a git repository? I suppose we could add features like this a little faster if we just added them rather than think about them in a generic sense. But if we know that from any Orion page, there is a handful of pages that the user will likely want to go to, isn't it nice that we can put them all in place? It's useful to think about the general case when designing a specific usability improvement. But even so, that's definitely in the "syntax" realm.
</p>
<h3>Semantics</h3>
<p>
The semantics behind "Related pages" gets more interesting. It's one thing for a page to be able to list the links to pages of interest. However, Orion is an extensible system, and we don't want every page to have to consider what other pages might be around. So some semantics that allow a page to say what it is showing, and what other things it might care about, rather than just itemizing links of related pages, can let us build more interesting relationships between pages. For example, consider this "Related pages" menu from the Orion git repository page:
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-QKnpDxT08JM/T0wTB_Q63nI/AAAAAAAAAEA/uKECrSjUR48/s1600/relatedgithub.png" imageanchor="1" style=""><img border="0" height="55" width="320" src="http://4.bp.blogspot.com/-QKnpDxT08JM/T0wTB_Q63nI/AAAAAAAAAEA/uKECrSjUR48/s320/relatedgithub.png" /></a></div>
<p>Here, the user is working in Orion with a git repository that is hosted at GitHub. So we figure out that one place the user might want to go is to that repository's GitHub page. This relationship can be determined because of some built-in semantics.
<ul>
<li>The page is able to call some common code that basically says, "hey, I'm a page that deals with repositories. Here's the URL I'm showing."</li>
<li>Another part of the code says, "I'd like to parse URLs and look for GitHub pages."</li>
<li>Finally, a related pages extension is used to establish that the "GitHub URL" command should be consulted when building the "Related pages" menu.</li>
</ul>
The way of expressing these relationships with API still needs work, but we have some pretty cool ideas of how we can make "Related pages" even more useful:
<ul>
<li>We could use the <a href="http://wiki.eclipse.org/Orion/Documentation/Developer_Guide/Plugging_into_Orion_pages#orion.core.linkScanner">link scanner</a> extension point so that any links built by the scanner in the Orion page content could also become candidates for "Related pages." For example, <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=371141">imagine a Bugzilla link showing up</a> in the "Related pages" menu because you referred to a bug in your code.</li>
<li>We could develop a <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=370903">URL translating syntax</a> so that plugins can more easily contribute mappings from page content to external links</li>
</ul>
</p>
<h2>Get Plugins</h2>
<p>One of my favorite new features in Orion is the workflow for getting new plugins. Our community is growing, and more folks are writing interesting plugins. We currently don't have an "official" plugin catalog or store, but my teammate Mark MacDonald has been hosting a plugin listing on a page in his GitHub repository. We wanted to make this catalog more noticeable and reduce the steps needed to install a plug-in.
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-9mONacRJpVA/T0wGJZEn2DI/AAAAAAAAADc/buq6DzZgtZ4/s1600/getplugins.png" imageanchor="1" style=""><img border="0" height="64" width="320" src="http://3.bp.blogspot.com/-9mONacRJpVA/T0wGJZEn2DI/AAAAAAAAADc/buq6DzZgtZ4/s320/getplugins.png" /></a></div>
</p>
<h3>Syntax</h3>
<p>
The link appears in the banner because the <a href="http://wiki.eclipse.org/Orion/Documentation/Developer_Guide/Plugging_into_Orion_pages#orion.page.link">orion.page.link</a> extension is used to specify a URL that should appear in the Orion banner. The links can refer to pages inside or outside of Orion. In this particular case, the link takes the user to Mark's catalog.
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-qFNg4ciGj2Q/T0wHFJPtbdI/AAAAAAAAADo/Rlem_qMTLck/s1600/plugincatalog.png" imageanchor="1" style=""><img border="0" height="128" width="320" src="http://4.bp.blogspot.com/-qFNg4ciGj2Q/T0wHFJPtbdI/AAAAAAAAADo/Rlem_qMTLck/s320/plugincatalog.png" /></a></div>
</p>
<p>
Nothing earth-shattering here, but suppose we click on one of these Install links. The link takes us back to Orion, ready to install the plugin we clicked.
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-FSk7qAHXPrg/T0wHruWcG6I/AAAAAAAAAD0/THW5ITx-8u0/s1600/installplugin.png" imageanchor="1" style=""><img border="0" height="77" width="320" src="http://1.bp.blogspot.com/-FSk7qAHXPrg/T0wHruWcG6I/AAAAAAAAAD0/THW5ITx-8u0/s320/installplugin.png" /></a></div>
</p>
<p>If you aren't paying close attention while you click these links, you might simply think that our plugin catalog didn't catch up to the new look for Orion. But the reality is that this workflow took the user out of Orion to a third-party plugin catalog, and links from that catalog were able to bring the user back into Orion at the correct page, with the correct information filled in for installing a plugin. The reason this is one of my favorite new features in Orion is that we were able to add this <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=370588">at the end of the 0.4 release cycle</a> <b>without inventing any new generic constructs</b>.
</p>
<h3>Semantics</h3>
<p>The semantics that allow this scenario to work have been covered in my previous blog posts, but it's kind of cool to review how they all play together in this workflow.
<ul>
<li>Our simple <a href="http://wiki.eclipse.org/Orion/Documentation/Developer_Guide/Plugging_into_Orion_pages#orion.page.link">orion.page.link</a> extension adds a link to the catalog. This extension has not been very interesting in the past because using it to link outside of Orion doesn't really enhance Orion's workflows, it just lets the user go somewhere else of interest. Kind of an "in-banner" bookmark.</li>
<li>We now provide a way for commands to describe the parameters they need so that <a href="http://adventuresinthoughtlessness.blogspot.com/2011/11/collecting-bits-of-input.html">common code can gather the information</a> from the user. So the command for installing a plugin can now declare that it needs a URL from the user, rather than collecting it itself.</li>
<li>We now allow pages to define <a href="http://adventuresinthoughtlessness.blogspot.com/2011/11/linking-to-power-of-orion.html">URL bindings</a>. These bindings let a page establish a relationship between a token appearing in the page URL and a parameter needed by a command. That means the URL needed by the command that installs plugins can now be specified in the install page URL. So a catalog can link back to the Orion plugins page and fill in the URL that the user selected in the catalog.</li>
</ul>
</p>
<h2>Where do we go from here?</h2>
<p>
We are already talking about our goals for Orion 0.5. While there will be many priorities and features to plan, I can imagine a lot of workflow improvements we can make by continuing to focus on the semantic definition of a page.
<ul>
<li>We can <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349531">make it simpler</a> for a page to describe itself to the common code.</li>
<li>We can add more detail about the resource a page is manipulating. This includes defining <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=370893">resource dimensions</a> that will give further control to the user for populating the page content.</li>
<li>A <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=370903">flexible URL translation syntax</a> could let plugins easily describe mappings between a page's resource metadata and links to other places.</li>
<li>If we package the common header code to be more consumable, it's possible that a page like Mark's plugin catalog could <a href="http://wiki.eclipse.org/Orion/Visual_Plugin_Strategy#Consuming_Orion_Chrome_in_another_Page">consume the common header</a> and thus more easily link back to Orion from the header and "Related pages" rather than have to know specifically how to get back to Orion.
</ul>
I won't make bold predictions this early for Orion 0.5. But in my continuing pursuit of thinking about semantics so that you don't have to...I predict that our work in formalizing page semantics will pay off in workflows that let users cross in and out of Orion without even realizing it.
</p>
Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com3tag:blogger.com,1999:blog-846317186323356929.post-44819509462672712502012-01-05T13:19:00.000-08:002012-01-05T13:19:02.483-08:00Anatomy of an Orion Page<p>When we first started building Orion, the site had two pages, a navigator and an editor. Over the course of our release 0.2 development, we grew quite a few pages as we added function. As part of this effort, we worked on the visual design for the pages, with most of that focus being on the overall visual style of Orion and the <a href="http://wiki.eclipse.org/Orion/Page_Layout/Page_Layout_0.2">layout of the header</a>.</p>
<h2>Are we anatomically correct?</h2>
<p>For our current release, we want to put a "fresh coat of paint" on the pages, but as I've looked at some of our most problematic pages, I've come to realize that we first need to stop talking about things like "headers" and "footers" and start talking about the common, semantic elements that appear on all Orion pages. I'm not talking about HTML elements per se. If we can define and agree on the list of building blocks, then we can talk about how to represent them in the DOM and arrange them visually. The work in progress is documented on the <a href="http://wiki.eclipse.org/Orion/Page_Layout">Orion wiki</a>. In this article, I'll describe some insights I've had while working on this anatomy.</p>
<p>
In an extensible system like Orion, it's important to think about anatomy vs. layout because we want to allow plug-ins to contribute functionality to existing Orion pages, as well as provide links to pages from another site. When I get a bug report that says, "how can I put a link in the Orion header" or "how can I put a command on the navigator toolbar," I like to ask what the link is for and what is the user workflow, because perhaps that link belongs somewhere else on the page. Hence the focus on anatomy vs. visual layout boxes.
</p>
<p>
The current list of body parts (no pun intended) is something like this. (The <a href="http://wiki.eclipse.org/Orion/Page_Layout">wiki page</a> will be kept up to date with our thinking and explanations of each.)</p>
<ul>
<li>Branding</li>
<li>Legalese (the fine print) </li>
<li>Discovery links</li>
<li>Expected links</li>
<li>User Info</li>
<li>Notifications</li>
<li>Search</li>
<li>Task (static page title)</li>
<li>Resource</li>
<ul>
<li>Dimensions</li>
<li>Hierarchical Location</li>
<li>Name</li>
</ul>
<li>Related Task Links</li>
<li>Task+Resource (Page) Level Commands</li>
<li>Resource View Controls</li>
<li>Resource Content</li>
</ul>
<p>
Here's a picture of how these elements <b>might</b> be organized on a page. (Note this is an anatomical picture, I'm not proposing that the Orion header adopt ice cream colors.) Most (all?) sites put the branding on the top left corner and legalese at the bottom, but of course if we stick with semantic definitions when structuring a page, this doesn't have to be true.</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-BqZ3St1Lfuo/TwX-9kqhGMI/AAAAAAAAACs/iUBIAdg8QSE/s1600/headerwireframe.png" imageanchor="1" style=""><img border="0" height="240" width="320" src="http://3.bp.blogspot.com/-BqZ3St1Lfuo/TwX-9kqhGMI/AAAAAAAAACs/iUBIAdg8QSE/s320/headerwireframe.png" /></a></div>
<h2>Some insights</h2>
<p>The body parts that might need some explaining are the ones where I've learned something about our page anatomy and have attempted to use terminology to further qualify an element. </p>
<h3>A link is a link is a link?</h3>
<p>With links, I find it helpful to differentiate links by thinking about their scope and purpose.</p>
<ul>
<li><b>Discovery links</b> are there so the user discovers pages that are helpful in the overall site workflows. If you are coding js in Orion, perhaps you'd like to know about "site xyz." (Hmmm....as I type this explanation I realize I haven't mentioned "advertisement" in the anatomy.) </li>
<li><b>Expected links</b> are links you might need to find someday, but you'll expect them and be willing to go looking for it. For example, how do I get support? How do I open a bug? </li>
<li><b>Related task links</b> are links that are directly related to what you are doing. For example, if you are looking at the git log for some repository/branch, it's highly likely you might want to see the git status for that branch.</li>
</ul>
We also have links that represent commands. These are buttons or links that let you act on a specific thing on the page. But the scopes, placement, and visual representation for these commands will be a future topic, so let's ignore them for now.
</p>
<h3>A resource by any other name?</h3>
<p>Another discovery for me is that it's not enough to talk about "the resource" that a user is operating on. I'm not talking about the page resource/URL, I'm talking about the way the user thinks about the resource they are working with. At a minimum, a resource has a fully qualified (hierarchical) location and a name. But if you add version control to the mix, then you might also want to talk about a particular version of that resource, or perhaps a particular repository. I'm still looking for a better word, but for now I call these <b>dimensions</b>.
</p>
<p>Allowing the user to consistently find (and change) dimensions can help the usability of our workflows. Let's take a specific example involving git. Today, in the Orion editor, I can be happily editing my js file. I can even use the breadcrumb to open a navigator within this hierarchy and find related files. But why can't I switch to another branch from the editor? We could hard-code a "switch branch" command into the editor page in the toolbar, but if we instead generalize this idea and have a way to show, and switch, dimensions in a common place on the page, then it will be easier for plug-ins to contribute dimensions and for users to have a common place to go to switch the resource content on the page. </p>
<h3>Drilling down</h3>
<p>The high level anatomy mentions "Resource Content" but we know there all kinds of ways to represent something, depending on how complex it is. The following terminology helps me talk about the different styles of pages we have:
<ul>
<li>A <b>single content area</b> is appropriate when a resource is best viewed as a unit. The Orion code editor is a good example of a resource that is best viewed with a single content area. Sometimes I think of it as "the <b>real</b> body of the page."</li>
<li><b>Sections</b> organize the view of the resource into separate pieces, so that you can work with different aspects of a resource at a time. </li>
<li><b>Outliners</b> help to navigate a content area. For a single content area, they may simply move the content in a structured way (like the editor outliner). For a resource organized in sections, they may navigate the sections (or help you to swap sections in and out on a page).</li>
</ul>
</p>
<p>By formalizing the sectional nature of pages, we can make it easy in the future for plug-ins to contribute additional sections to a page, provide common places for the user to find commands that apply to a particular section, and common controls for expanding/collapsing or organizing sections.
<h3>HTML5: to section or not to section?</h3>
<p>When I use the word "section" above I am really talking about a way to organize the viewing and manipulating of a resource. But I didn't want to use that word if it didn't jive with the notion of an HTML5 section. So I checked the HTML5 spec for guidance regarding <a href="http://dev.w3.org/html5/spec-author-view/the-section-element.html">HTML section elements</a>, and I think this is the right word to use, and that we will end up with HTML5 sections as the tags for these elements on the page. In particular, the spec says, "A general rule is that the section element is appropriate only if the element's contents would be listed explicitly in the document's outline." That seems to hold up to the way we are using them.
</p>
<h2>What does this mean to our technical page architecture?</h2>
<p>I'm not sure yet, but of course I'll guess.
<ul>
<li>For plug-in developers, we'll formalize our markup surrounding sections and how to describe them in a plug-in. I don't think we'll have plug-ins contributing sections per se in Orion 0.4, but I think we'll start down an implementation path that will make that possible. And we'll probably see a plugin's preferences rendered in a section on the preference page.</li>
<li>Inside the Orion implementation, I'd like to see the javascript code talking about the page in terms of tasks and task types, path, name, dimensions, etc. Some common code can map this information to a header (or footer) template, the breadcrumb, etc. If we decide we like combo boxes for changing dimensions one day, and later decide to use drop down menus, it shouldn't be the page's concern at all.</li>
<li>Having isolated our javascript code from the common templates, the page implementation code shouldn't even care how the DOM is structured in particular. But long run, it'd be nice to see the Orion page template get simpler, using HTML5 body header, footer, and sections within. Then "something outside the page" (CSS? JS? both?) can apply that to a layout that makes sense for the particular Orion installation, without mandating a particular JS library or approach for making that happen.</li>
</ul>
<p>What I do know is that in Orion 0.4, it will be easier for you to move between pages in your workflow. And in part, that will because of this anatomy and its corresponding implementation. But while you are using Orion, I don't want you to think about that. Hopefully, you'll just instinctively know how to find what you are trying to do, and think, "wow, these guys always get those links and buttons in just the place I expect them to be!"</p>Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com3tag:blogger.com,1999:blog-846317186323356929.post-43593237220799282532011-11-20T12:48:00.001-08:002011-11-20T15:58:02.853-08:00Linking to the power of OrionIn my <a href="http://adventuresinthoughtlessness.blogspot.com/2011/11/collecting-bits-of-input.html">last post</a>, I mentioned our Orion <b>command framework</b>, which allows our pages to define the commands that a user can run on a particular page. We were evolving the command definition to include the specification of what parameters it requires. While I focused more on the UI in the last discussion, now I'd like to talk about how this concept will allow you to link to Orion in interesting ways.<br />
<p>
Let's follow a simple example. One of the things a user can do from the Orion <b>Git Repositories</b> page is clone a git repository into an Orion folder. In the first iteration of the command framework, any work done after the user clicked the "Clone Repository" link was done in the command's callback.
<pre>cloneGitRepositoryCommand = new mCommands.Command({
name : "Clone Repository",
tooltip : "Clone an existing Git repository to a folder",
id : "eclipse.cloneGitRepository",
callback : function(item, commandId, domId, userData) {
var dialog = new orion.git.widgets.CloneGitRepositoryDialog({
serviceRegistry: serviceRegistry,
fileClient: fileClient,
func: function(gitUrl, path, name) {
// do the real work
}});
dialog.startup();
dialog.show();
}
});
</pre>
<p>
But now we allow the command to specify that it requires a URL parameter. We also indicate that there are additional parameters that can be collected if the user wants to specify additional options. (These snippets are intended to show you how things work, but this interface <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=363763">will certainly change</a> before the next release milestone.)
<br />
<pre>var cloneParameters = {};
<b>cloneParameters.url = {label: 'Repository URL:', type: 'url'}; </b>
<b>cloneParameters.options = true;</b> // indicate that we could collect additional options
cloneGitRepositoryCommand = new mCommands.Command({
name : "Clone Repository",
tooltip : "Clone an existing Git repository to a folder",
id : "eclipse.cloneGitRepository",
<b>parameters: cloneParameters,</b>
callback : function(item, commandId, domId, userData, <b>parameters</b>) {
if (parameters && <b>parameters.url.value</b>) {
// do the real work
} else {
// we could trigger a dialog to get the parameters, or report an error, etc...
}
});
</pre>
<p>
So far, we've just defined a command. Nothing is going to show up in the UI until we register a <b>command contribution</b> on a page. In the contribution, we can specify the DOM node where the command should be shown, such as a toolbar, and a key binding that can be used to trigger the same command via the keyboard. But the fun really starts now that we allow a <b>URLBinding</b> to be associated with a command. With a URL binding, a page can define a URL (fragment) query parameter that can be used to trigger command, and the parameter name of any value provided in the URL. For the clone command, the URL binding looks like this.
<pre>var urlBinding = new mCommands.URLBinding("cloneGitRepository", "url"));
commandService.registerCommandContribution("eclipse.cloneGitRepository", ..., urlBinding);
</pre>
<p>
This means that the query parameter <b>cloneGitRepository</b> should trigger the command, and the value in the URL should be bound to the <b>url</b> parameter in the command. From Orion's point of view, opening the <b>Git Repositories</b> page with the following link calls the same code as if the user had clicked on the command in the UI and typed in the URL:
<pre>http://orion.eclipse.org/git/git-clone.html#/workspace/H?<b>cloneGitRepository=ssh://myId@github.com/path/myId.github.com.git</b>
</pre>
<p>
One important note. A command invoked by a URL binding is not called by this URL. Rather the page is opened in a state for collecting the parameters. We just prefill the parameter information, and the user can hit the <b>Enter</b> key to start the clone, or click the <b>More</b> button to provide additional information. Our URL needs to be a stable GET. Reloading the URL multiple times should never alter the state of the resource on the page. So user intervention is always required in order to actually invoke the command. The URL binding, much like a key binding, simply gives the user a shortcut for starting the process.
<p>
We think the URL binding is a powerful concept. It allows us to start exposing linkable bits of function in a way that is completely separate from the code that defines the function. Being able to specify parameters in the URL syntax means that some other site can use its own logic to figure out what the user wants, and then link to an Orion page, providing contextual information.
<p>
Our favorite simple example is a bugzilla page that could use the product and component information in the bug definition to figure out which git repository the user might want to clone to look at the code. Another idea is the ability to author "cue card" style help systems that could guide the user through some set of tasks in Orion, simply by linking to the various commands involved in the steps.
<p>
We can't wait to see what you might do with this idea.Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com0tag:blogger.com,1999:blog-846317186323356929.post-87313525227055783572011-11-07T10:10:00.000-08:002011-11-07T10:10:25.276-08:00Collecting Bits of InputI've been looking around lately at the way different sites collect input when performing a task, and how we can do better in Orion.<br />
<br />
For the time being, I'm ignoring the main input task in Orion - editing source code. And I'm not talking about a form-based UI where describing or creating something is the main task at hand. Often, we just need a little bit of info (a name, a URL, a password) in order to do something. In Orion, we have a grab bag of techniques for collecting this kind of input.
<br />
<ul>
<li>Some times, we just put an input field near the place you are working.
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-0eV01hzm6Ds/TrgQhK2k1bI/AAAAAAAAABY/scFNbvKH2Ss/s1600/newfile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="http://3.bp.blogspot.com/-0eV01hzm6Ds/TrgQhK2k1bI/AAAAAAAAABY/scFNbvKH2Ss/s320/newfile.png" width="320" /></a></div>
</li>
<li> When we need to know more than one thing, or want to provide additional options, we open a dialog that collects parameters.<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-j6pBH-HMP7A/TrgRXD2NuMI/AAAAAAAAABk/Lwghw0nQSbY/s1600/clonedialog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="207" src="http://4.bp.blogspot.com/-j6pBH-HMP7A/TrgRXD2NuMI/AAAAAAAAABk/Lwghw0nQSbY/s400/clonedialog.png" width="400" /></a></div>
</li>
<li>In some cases (where we were doing something quick and dirty), we rely on the browser's prompt dialogs. <div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-4Fvj0qPh6RA/TrgRzkz-tWI/AAAAAAAAABw/qvmBnUwnqUU/s1600/gotoline.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="210" src="http://3.bp.blogspot.com/-4Fvj0qPh6RA/TrgRzkz-tWI/AAAAAAAAABw/qvmBnUwnqUU/s400/gotoline.png" width="400" /></a></div>
</li>
</ul>
These subtle differences can burden a user over time. We have learned in our years working on Eclipse that the best way to ensure some consistency is to provide code that does the right thing. Reducing the burden on the developer helps the user, too.<br />
<br />
We have a command framework in Orion that lets pages define commands that the user can run on a particular page. This allows us to separate the presentation decisions from the work performed by the command. For example, if you want to define a command that should be available on files in the Orion navigator, you can describe the command and provide code that does the work, and we are free to play around with where and how the command appears. Is it a button or a link? Is it text, icon, or both? Does it appear on hover or is it always there? Where on the page does it appear (in-line, in a menu or toolbar, in the banner?) The presentation decisions can evolve without a lot of hassle for developers who contribute these commands. (I'll write another post soon about how we see our page layouts evolving in this area.)<br />
<br />
This all sounds good, but today, we currently rely on the <b>handler</b>, the code that performs the command, to gather parameters. For example, when you press a "New File" link, the handler code is the one prompting you for the name and creating the file. This has its share of problems, though, and some of our new<a href="http://www.blogger.com/wiki.eclipse.org/Orion/Plan/0.4"> release goals for Orion 0.4</a> add more excitement:
<br />
<ul>
<li>As we've seen, it means that different commands collect parameters in different ways, causing a little extra thinking by the user. </li>
<li>We're finding that dialog placement and interaction <a href="http://bugs.dojotoolkit.org/ticket/13488">can be problematic</a> on tablets, and even more problematic when an <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349592"> on-screen keyboard pops up</a> to collect input. </li>
<li>We want to explore scenarios where a link from some other site <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359080">leads you to an Orion page</a> that requires input. So the way we gather input needs to be even more visible and predictable when you arrive at a page that's already asking for something, without being overly disruptive when you are already working on the page and need to answer that same question. </li>
<li>We need to make sure the solution is accessible. So using a common implementation can help us focus our efforts here (pun intended).</li>
</ul>
If we can instead allow a command to describe the parameters it needs to collect, we can then provide a consistent, appropriate presentation for gathering that input. Perhaps we'll come up with a way that plays well in all the scenarios we want to support. We might instead learn we need different presentations for these different situations. From the command handler's point of view, though, the implementation won't get called until the necessary input has been gathered.<br />
<br />
I'm currently working on a first stab at this idea. From a presentation point of view, I started out with some ideas that I'd like to validate:
<br />
<ul>
<li>The "form" or "dialog" that collects input should be inserted in the DOM vs. overlayed as a modal dialog or slideout. I think this can help with zooming and scrolling issues on tablets.</li>
<li>There should be enough animation that a user arriving at a page for the first time notices right away where the input is needed. But the animation should be fast and well supported on different devices, so I'm using <a href="http://dev.w3.org/csswg/css3-transitions/">CSS3 transitions</a> rather than a JS library.</li>
<li>Parameter types should be described using <a href="http://www.w3.org/TR/html5/the-input-element.html">HTML5 input types</a>. This means the browser can optimize the input control, and for some devices, it can mean customized keyboards (numeric, URL) that make input faster.</li>
<li>For added fun, my first implementation adds the <b>speech</b> attribute to the input field so that parameters can be spoken. If we can avoid popping up a keyboard altogether, that might make providing simple input much faster. For complex forms and dialogs, it might be a silly idea, but it makes for a fun demo right now.</li>
</ul>
My first try uses a slide-in parameter collector. I haven't spent much time on cosmetics, so expect it to look snazzier once our graphic designer gets a look at it. In the three cases shown above, the input is now collected by the command framework, in the same way (location depends on where the command appears.)
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" height="195" src="http://4.bp.blogspot.com/-6rsWAZjmeV4/TrgW_pfjcnI/AAAAAAAAACQ/UXG9WgXANrw/s400/gotolineslider.png" style="margin-left: auto; margin-right: auto;" width="400" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Go to Line parameter collector (with spinner courtesy of "number" input type)</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-6rsWAZjmeV4/TrgW_pfjcnI/AAAAAAAAACQ/UXG9WgXANrw/s1600/gotolineslider.png" imageanchor="1"> </a> </div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-kTRHorIE-sc/TrgW_TKtPuI/AAAAAAAAAB8/fSxkGHWdils/s1600/newfileslider.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="169" src="http://1.bp.blogspot.com/-kTRHorIE-sc/TrgW_TKtPuI/AAAAAAAAAB8/fSxkGHWdils/s320/newfileslider.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">New File parameter collector (speech enabled)</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-sjxsAVqlYkc/TrgW_rcV2TI/AAAAAAAAACI/Dv20VTa68sI/s1600/cloneslideout.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="280" src="http://2.bp.blogspot.com/-sjxsAVqlYkc/TrgW_rcV2TI/AAAAAAAAACI/Dv20VTa68sI/s320/cloneslideout.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Git Clone parameter collector</td></tr>
</tbody></table>
I'm not done with the code yet, but I hope to release it this week and get more user feedback on how it plays. In the meantime, I'm wondering if you've seen a technique somewhere that you like, that you think would meet similar goals?Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com0tag:blogger.com,1999:blog-846317186323356929.post-15507638043558474972011-09-26T13:38:00.000-07:002011-09-27T08:23:51.828-07:00Instant Thoughtlessness in the CloudI don't want to be thoughtless in an inconsiderate way. Just the <a href="http://www.sensible.com/dmmt.html">"don't make me think"</a> or <a href="http://www.ideo.com/by-ideo/thoughtless-acts">"thoughtless acts"</a> kind of thoughtless. I hate thinking about my tool when I'm trying to do something, so I like it when I have thoughtless experiences. I'm hoping to help bring more of the good kind of thoughtlessness into <a href="http://eclipse.org/orion/">Orion</a>.<br />
<br />
Last week, I returned from a summer-long leave of absence from IBM, where I work on Orion and Eclipse. As I left, we were just finishing up our first Orion release, 0.2, and some of the workflows were pretty new designs and just being wrapped up. I had this rather strange workflow for releasing code into our git repository, which involved a combination of <a href="http://code.google.com/p/msysgit/">msysgit</a>, both command line and git gui, combined with Orion's rapidly evolving git interface. I didn't like the workflow, but it had grown up from the time that we had no git UI in Orion, slowly moving workflows into Orion, and also working around bugs by jumping to the command line or git GUI when I didn't quite trust a build. <br />
<br />
Last Monday I was ready to get familiar with the code again, see how Orion had evolved while I was gone, and try to contribute something to our 0.3 release. I could barely remember my odd workflows, where I had installed msysgit, what was in my Eclipse workspace, or what build of Eclipse I was using to run the Orion server before I left. In the old days, I would have searched around for the current I-build Eclipse update repos and decided whether to download a new SDK or just update my Eclipse (depending on what might have changed since I was gone). I might have started to re-synch my workspace, before realizing that I needed to build a new one since the <a href="http://planetorion.org/news/2011/07/orion-on-the-move/">Orion code repository had moved</a> while I was gone.<br />
<br />
But Monday was different. I fortunately remembered my orion.eclipse.org login. I logged in, deleted my old folders, and cloned the Orion client repository. I searched through the Orion bugs to find a simple feature I could implement. I added the feature, tested it on an Orion site, committed it, and pushed to the repository. I had <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=358153">one slight hiccup</a> because I had pasted the wrong git repository URL (with an http protocol rather than ssh). So I had to ping a coworker to help figure out where to change that. He was surprised I was already pushing code so soon.<br />
<br />
It was a sweet reentry. No downloading, no upgrading, no re-synching. Just jump right into the cloud and <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=348133">produce something</a>.<br />
<br />
It's been a week now and I have yet to explicitly download a tool to do my work. Nice....and thoughtless.Susan McCourthttp://www.blogger.com/profile/02597761690243211608noreply@blogger.com2