Modal Dialog JQuery Plugin

This has been a while coming, but I made a little “yet another modal dialog lightbox JQuery plugin” thing this week.

Demo and Download for Modal Dialog – JQuery Plugin

It was driven by TiddlyDocs, but I’ve been wanting one anyway for a while. Mostly because lightbox libraries generally do some hocus-pocus on page load, like applying to everything marked rel=”lightbox”, but don’t let you dynamically produce the lightbox yourself. That’s fine for pages that are just a static image gallery, but not useful to someone building a dynamic web app.

I’ve subsequently used nyromodal, on good advice, but wanted something smalller and with a simple API for my main use case, which is just showing some text.

The plugin also simplifies work by not requiring you to install a separate CSS file. Doing that, and linking to it, as well as installing any images, is something that always slows me down when I want to start using a graphical client. In keeping with the “happy path” You-Aint-Gonna-Need-It (YAGNI) mantra, I’d rather keep a library to a single Javascript file – be evil and do styling in the library by default, but still support users who want to put custom CSS in a stylesheet.

A-Z of game design – quick notes – @cennydd talk at #uxcamplondon

A-Z of game design

(nice format for a barcamp session – walking through concepts in A-Z)

avatar – people tend to act like their avatar (study)

boss – build up to the big challenge

cheats – can’t be bothered going through everything, ie you put cheats into the game (maybe release

difficulty curve – perfect example of flow in UX; task should be perfectly matched to your skill

environment – massive impact on gameplay. can use it to cause problems for AI, final fantasy – drag monster to rock where game designers didn’t think it would be.

flow.

grinding. people doing nothing particularly intelligent or challenging to keep moving up. (not sure what the design implication is here; if people like it …)

hacks. constant battle between hackers and designers.

iteration. we tend to iterate to solve problems, keep refining.

jobs. different tasks.

killing. more graphical over time.

leaderboard. whatever the variable it shows, top guy gets the most cachet etc.

MMORPGs. Each has its own community, vocabulary, etc. Duality of competition and co-operation. e.g. people waiting together for a monster to appear. Tribal phenomenon. (Formed a “static” – same group of people, because the only way to beat it was to work with the same group of people, get used to their style, etc – shifted body clock to California time.)

narrative. games becoming more cinematic. e.g. Bioshock – conveys political message through its narrative.

options.

quite ridiculous strangeness. e.g. “Captain Blood” – talked to aliens in weird language.

rewards. Have to choose appropriate reward system, e.g. if people find way to get massive points easily, no more challenge.

speedruns. wikipedia

tutorials. good way to do it is what educators call “scaffolding”. (mm aka happy trajectory)

user generated content.

virtual economies. Can lead to Gold farming - game sweatshops.

xyz – have to be “xylophone” “yachts” and “zombies”

“whither location”@cyberdees and @Cennydd #uxcamplondon quick notes

talking about location in UX. random tidbits at this session follow …

apparently mozilla looked at location based preferences

location relevance depends on time. some of it highly real-time based and “useless” afterwards, dopplr based on the future #uxcamplondon

great locations, in human terms “the cheapest pub near me” “the away match” #uxcamplondon

“home ground advantage”: knowing about your own area helps you, e.g. living near football stadium, you don’t go shopping. (discussion about “match day” conditions on parking restrictions – which sport, what match, is today a match day???)

mapumental – good example of embodying tacit knowledge locals have

kevin lynch – talks about legibility of a city. http://www.csiss.org/classics/content/62 e.g. NYC cnr of 5rd and 27th. easy. whereas london – easy to get lost, which is maybe why postcodes are so specific, to compensate. Ireland doesn’t have a postcode system outside Dublin (wot?!) http://en.wikipedia.org/wiki/Postal_code#Ireland.

Will there be laws to prevent discriminating based on location? Companies like BT and Royal Mail have social obligation policies.

“Diary of a Madmen” talk by @otrops on doing UX as a developer

Questioning Alan Cooper when he says developer’s job is at conflict of interest with user needs and difficult to treat usability

Jeff walks through his career, started out doing web tech, fascinated by IA, got into it

Learned lessons earlier on

Five years later, started job as developer but now doing UX

Two contrasting projects: One he knows the code backwards, one he doesn’t. Interesting to see contrast between project where he knows the code and where he doesn’t. Difficult to feel like the UI is “magic” when you know the code backwards – feels more free in ignorance of the code.

Good to do lo-fi prototyping etc, but especially user testing.

Fin.

Discussion:

Can cut off options too early if put in developer arguments too early.

(me) Everyone needs to user test anyway. But I find I an detach myself as a developer and see things as a user.

Others not sure about this. example – if you’re coming up with multiple undo, part of your brain starts screaming!

Talking about advantages of coming to UX as a developer versus coming to UX as a developer. As a developer – you can’t be blagged by IT guys saying “it can’t be done”; can open up new possibilities that UX people mightn’t have been aware of.

You can have a website without designers, but you can’t have a website without developers – you can’t make it work by putting a wireframe online. So UX people need to know enough to spec it, not be blagged.

Notes from @detyro talk on BodyCasting at #uxcamplondon – Modelling UI with Human Actors

Quick notes

Looked at Bill Buxton – Sketching User Experiences. Lo-fi/Hi-fi – can even use video as lo-fi if keep it sketchy style production

The idea is to use human bodies to model the interaction – the humans represent different things in the UI moving around.

Reminds me of software design techniques. e.g. I recall physical versions of CRC where people represent software objects, communicating with each other. Also a good way of explaining traditional CS algorithms like bubble sort.

I participated in a demo where we were columns on a UI while a “user” shifted the columns (that is us) around.

Not only high level and sketchy, but also nice that it’s fun an light – helps people to enjoy the process.

The developers who are serving as actors in the process learn about the algorithm wh ile they act out the parts. e.g. when I did the demo, it started dawning on me after two or three “runs” that I need to start shifting out of the way. e.g. user says “c olumn D, move to between column A and B”, so initially I ignore the user being colum n E. But then I realise I’m part of the system and I have to get into gear and start shuffling along too.

Will Bespin really end up with multiple backends?

Google groups thread

Bespin has the idea of multiple backends attaching to the same client. Right now, Python is apparently “winning” while Java has fallen behind and PHP appears to have faded away.

The situation is very analogous to Shindig (http://incubator.apache.org/shindig/) which has a strong Java back-end, a PHP back-end that took a long time to get started in earnest and AFAICT from a quick glance has tapered off, and a number of non-starters.

I do wonder whether something like this is really viable – can you have a vibrant ecosystem of back-ends in different languages? Granted, there are hundreds of implementations of SMTP, FTP, and so on, in all the languages of the rainbow. Those are actual protocols based on strong standards. Likewise, Shindig had a fair crack at it because it’s based on the OpenSocial standard (but the diversity effort is probably hampered by the fact that most companies who want to be OpenSocial hosts tend to fall in the Java camp).

Bespin would need to formalise things and establish proper standards to support multiple backends. Nothing as onerous as the IETF standards, but still, they’d need to nail down all the subtle issues and edge cases in order to support multiple backends. Good for cleanliness perhaps, but at the expense of project velocity. Years ago, I asked SpringSource’s Rod Johnston about why one should use Spring over the upcoming EJB3, and one of his reasons – quite rightly – was that his code was available NOW while the committee-driven EJB standard and subsequent implementations were a long way off. In other words, Spring demonstrates that working, open, code is in many respects far more powerful than a standard. I can’t imagine Bespin will want to formally document its protocols; instead it will rely on code. But of course, if the code is a moving target, how easy will it be for different backends to keep up?

Also, how motivated will the second, third, and fourth guys be? It’s more fun being the first to see the concept become reality; less so to be building a port from one language to another. As with the previous point, though, I stand to be corrected; some people might enjoy the engineering challenge of building a parallel backend. (Maybe I’m being solipsistic here, as I’m personally 20x more motivated by user stories than implementation details.)

Java hosting is notoriously painful compared to the ease of cheap PHP hosting, so I can see the argument for both; companies will want to host Bespin on their own shiny enterprise Java servers, while rebellious little startups will want to do the same thing for a sliver of the cost on commodity iron.

Update: Ben Galbraith responds

Towards A Single Page Application Framework

Tonight, I was thinking of making a Twitter app to manage my various accounts (I have ~dormant accounts related to projects like @webwait and @listoftweets). The app would be holding username and password details for each of these accounts, so it made sense to build it as a Single Page Application (SPA). This way, a more paranoid user could always keep the app in their local file system, while a less paranoid user could always stick the file on a protected server somewhere, having configured all the username-password details.

TiddlyWiki is a framework for developing SPAs. One might say it’s the framework for developing SPAs, since there are no prominent alternatives. So my obvious choice was a TiddlyWiki. However, not too long ago, the TiddlyWiki core guys extracted out the secret sauce for SPAs: the ingenius bit of code that saves files without requiring any browser extensions. (I’ve tried to explain this to people and it always leaves even the most brilliant minds a little dumbstruck, but yes TiddlyWiki demonstrates there are pragmatic hacks that can be used to read a file into the browser and then write it out again.) I was keen to explore this saving mechanism, so experimentation ensued.

The file management techniques ship conveniently in a JQuery plugin, jQuery.twFile. There is a basic demo which lets you edit the entire text and save it. The demo confused me at first – because it was editing the entire body of the file, I wasn’t sure how to translate that info into what I, as an application developer needed. The demo is useful for framework developers understanding the plugin, but less so for application developers. So I extracted it into a demo that is still minimalistic, but closer to the kind of thing you’d do in an application.

The SPA demo is here.

Once I did that, I realised what’s required is a SPA framework. In practice, most developers using twFile will be keeping all the HTML, CSS, and Javascript in a single file, so it’s possible to build a higher-level abstraction on twFile, so that developers can focus only on the content. I built the demo in a way that distinguished what was boilerplate framework code and what was application-specific HTML, CSS, and Javascript.

It was all still in one file, and that’s fine for many developers – you can give the developer the file, tell them “edit these bits”, and they can come up with something functional. I decided to extract things further though, and found the Jinja templating framework to be useful here. Jinja has a concept of template inheritance, so you can easily build up an “include” system. The net effect is I was able to encapsulate SPA logic in a single file, which was passed through a Jinja processor to produce the executable HTML document.

The basic SPA logic is shown below:

  1. {% extends "spa-template.html" %}
  2. {% block title %}JQuery SPA demo{% endblock %}
  3. {% block css %}
  4.   etc etc
  5.   body { background: black; padding: 0; margin: 0; font-family: Gill Sans, sans-serif; }
  6.   h1 { background: white; color: black; padding: 10px 10px 0; margin: 0; height: 52px; }
  7. {% endblock %}
  8. {% block html %}
  9.   <h1>
  10.   <img id="logo" src="data:image/jpeg,%FFetc etc"/>
  11.     <span id="title">JQuery-SPA Demo</span>
  12.   </h1>
  13.  
  14.   <div id="main">
  15.  
  16.     <ol>
  17.       <li>Save this file to your local file system and open your local copy in the browser (using a file:/// URI). The browser might ask for special permission for this document, and you will need to grant it.</li>
  18.  
  19.       <li>Type your message: <input id="message" value="change me"></input></li>
  20.  
  21.       <li>Save this page: <input id="saveButton" value="Save" type="button"></li>
  22.  
  23.       <li>Hit shift-reload to perform a clean reload the page and observe that your message has been saved.</li>
  24.     </ol>
  25.  
  26.     <h3>What is this?</h3>
  27.  
  28.     <p>This is a demo of an experimental Single Page Application I am building atop <a href="http://jquery.tiddlywiki.org/twFile.html">jQuery.twFile</a>, the file saving plugin extracted from TiddlyWiki. Forked from <a href="http://jquery.tiddlywiki.org/twFileDemo.html">this twFile Demo</a>. Only tested on Firefox for now.</p>
  29.  
  30.   </div>
  31. {% endblock %}
  32. {% block javascript %}
  33.     $.spa.save = function(text) {
  34.       return text.replace(/<input id="message".*?></input>/,
  35.               '<input id="message" value="'+$("#message").val()+'"></input>');
  36.     }
  37. {% endblock %}

So it contains separate HTML/CSS/Javascript blocks. Probably not a good engineering practice (though it doesn’t impact on the end-user experience, which is always a single file), but it’s convenient for now. The key SPA logic is here:

  1. <li>Type your message: <input id="message" value="change me"></input></li>
  2.       ....
  3.     $.spa.save = function(text) {
  4.       return text.replace(/<input id="message".*?></input>/,
  5.               '<input id="message" value="'+$("#message").val()+'"></input>');
  6.     }

As an app developer, all you have to do is override $.spa.save (which in retrospect should be renamed as it doesn’t actually perform the save). This function receives the text of the file as it was stored on disk when the page loaded. It must then return the text that should be saved to disk. Thus, it must store application state in HTML, probably by performing some kind of substitution.

Having put this together, I’m keen to proceed with the envisioned Twitter app. It’s not yet clear if there’s any mileage here over a regular TiddlyWiki, but as someone who is more familiar with starting apps from a blank HTML page (or a simple Project Deploy* template), it might end up being a more familiar way to kick an app off. Watch this space.

TiddlyDocs User Authentication – Generic Design and Custom Features

We are working on a design that will keep TiddlyDocs as generic as possible. The core TiddlyDocs product will have a concept of “rooms”. This is the same kind of room you see in online forums or chat sites, where everyone inside the room contributes and sees content inside the room they’re in, and can’t see or do anything about rooms they’re not in.

Our design works like this. Each room is a recipe of several room-specific bags, along with a global config bag. Each room is associated with a unique user role.

Note the role is used inside the respective bags’ policy files, and they each vary somewhat. e.g. the comments bag says readable by everyone in ‘role’, appendable (“create tiddler” permission) by everyone in ‘role’, editable by “#(role)_admin”. (ie there is a second role called “role_admin”.); whereas the content bags says readable and writeable and editable by everyone in ‘role’; and the config bag says readable by everyone in ‘role’, appendable by ‘#{role}_admin”.

For now, there’s a “makeroom” script that generates the recipe, the bags and the policies. (I’d ideally like to see the recipe be “magic” in some respects, using a wildcard mechanism).

That’s the basic design. We also have some unique challenges in this particular installation – (a) users are authenticated using a custom, enterprise-specific, single-sign on solution, where the incoming header for each request identifies user’s ID and (effectively) company; (b) we have certain rooms whose composition is manually configured and are a subset of the company’s membership, and we also have a “everyone” room which is automatically composed of everyone in the company (e.g. we might have a “megacorp-everyone” room along with the manually configured “megacorp-accounting” room, and “megacorp-marketing” room); (c) to let users allocate specific TiddlyDocs to users, we need a dropdown containing real names of all users.

BTW I’m simplifying some of the finer details here to make the discussion more pertinent to the general topic of TiddlyWeb/TiddlyDocs, rather than our specific problem. All of the following will be developed as proprietary plugins for our own installation. It’s a somewhat complicated set of requirements because it’s a real-world enterprise problem, where we have specialised requirements, combined with integration issues where we can control some things, but can’t control others. (e.g. We can’t change the underlying user store, where we would ideally store which rooms a user is in, instead of holding secondary user records inside TiddlyDocs.)

We will be building a TiddlyWeb plugin that sets the “extractor” filter. This is one of the several filters the request is subject to, on the way into TiddlyWeb. It is usually paired with the challenger filter – where challenger might present a username/password form and set a cookie, and extractor will read the cookie and set usersign (aka user ID) and any other info like users’ roles. In this case, though, we already have the header set, so we don’t need a challenger at all. We simply need an extractor that sets the usersign from the incoming header, and also notes the user’s company. Verification will then check that (a) if the user is attempting to access the “everyone” company room, they are a member of the company; (b) if the user is attempting to access a “manual” company room, they are a member of the company and they have the role associated with the company. We use a naming convention to determine which company a manual room belongs to.

On (c), we need a tiddler in the room “config” bag containing a list of user names. So in addition to the custom extractor, we will also need a periodic script to poll the user store associated with the SSO system. This will give us all the info about users in each company, so we can build up a mapping from company to list of users, where each user record has an ID and name. company->list[{user ID, user name]}. The script will then (a) rewrite the list of user names for the “everyone room” based on the company list, by effectively “copying” the results for that company (b) rewrite the list of user names for each manual room, by walking through each user, checking their roles, and accumulating their user name into the room list for each room they’re in (c) do some cleanup – removing TiddlyWeb records for any users not in the list.

There’s nothing very elegant about these custom implementations, and I’ve primarily written these details for the benefit of myself and colleagues who are implementing these custom features. The more interesting, general, point here is about open-source and plugins. TiddlyWeb’s architecture allows us deliver a generic solution for TiddlyDocs rooms, which is applicable to any organisation, and we can then superimpose a custom feature using the plugin mechanism. Furthermore, the plugin mechanism is a great way to decouple concerns – plugins are moduels on steroids. The core TiddlyDocs developer can concentrate on building an open-source, functional, multi-room TiddlyDocs edition, using the default authentication mechanism. Meanwhile, other developers can work in parallel on custom plugins.

(This post is a refinement of this post; we have been doing further thinking as we get closer to the final product and we learn more about our external environment.)

Styling a Top Bar

Digg Bar launched with some controversy recently. It’s iframe trapping all over again; sites like About didn’t make themselves too popular with this technique, and so it died down until recently. I think there are legitimate uses for the top bar though; certainly the Digg Bar is useful to at least those people who are currently logged into Digg.

In fact, the reaction in the past few months suggests that top bars are here to stay. There was an initial uproar, but it seems to have been accepted, and I think top bars will start to become a fixture of the web. Given the valuable tracking data that comes from it, I can imagine dominance of the top 40 pixels of the browser window will become a big deal too…and right now, the big GYM guys (Google/Yahoo/Microsoft) aren’t doing it. Through development or acquisition, IMO that will change.

Users always trade off privacy against utility, and what can be an uproar about privacy concerns and google juice theft quickly dies down when people find value in a new feature. In this case, companies like Digg and StumbleUpon aren’t producing top bars as part of a cynical get-rich-scheme; I believe competition is too fierce to resort to cheap tricks that will get users off-side. Instead, I believe they are genuinely aiming to win, adding awesome features to improve user experience first and foremost. The Google Juice and tracking data that comes with it is a gigantic dollop of icing on the cake and top bars therefore constitute another example of having your cake and eating it too.

But this article is about web design, not web trends. An application of top bars I’ve been looking at recently is a “trails player” I’ve been building into Scrumptious lately. User creates a trail of websites for someone to visit, and each of them shows up in a trail bar at the top of the page.

To style this, I made like the web greats and peeked under the covers at a bunch of similar websites:

I’ve made a dead-simple bar to illustrate the concept.

View the top bar here.

The canonical layout works like this:

  1. <head>
  2.     <link href="layout.css" rel="stylesheet" type="text/css" />
  3.   </head>
  4.   <style>
  5.     body { overflow: hidden; }
  6.     iframe, div, body { margin: 0; padding: 0; }
  7.     #bar { position: absolute; top: 0; left: 0; width: 100%; height: 50px;
  8.               z-index: 100;
  9.               background: #ddf; border-bottom: 1px solid #888; }
  10.     #content { padding: 5px; }
  11.     iframe { margin-top: 50px; width: 100%; height: 100%; }
  12.   </style
  13.  <body>
  14.     <div id="bar">
  15.       <div id="content">I am bar.</div>
  16.     </div>
  17.     <iframe src="http://yahoo.com"></iframe>
  18.   </body>
  19. </html>

So the bar is absolute-positioned in the top-left, with width: 100% to span the entire width, and height set to whatever height you want for the bar. Make the iframe top margin match that height, and you’re set.

Note that the bar shouldn’t have any padding, otherwise it will add to the 100% width (padding isn’t included in the width under standard CSS box model) . So if you want padding, put it inside an inner div, like #content above.

An interesting thing is that you can set the iframe’s source, but you can’t actually detect it, because of cross-domain security, under modern browsers. Which is unfortunate. The user might start clicking around inside the iframe, after you have set its initial source URL, and you won’t actually know where they are at. Good for the user’s privacy, but bad if you want to provide certain awesome features. e.g. Digg would probably like to show the number of Diggs on any page users click over to, and StumbleUpon would like to show votes as well as related pages. In Scrumptious, I’d like to provide a “trails recorder” that automatically scoops up pages you visit into a trail…but I’ll have to achieve that with a browser extension.

And in all these cases, you probably want a “close bar” feature that would ideally work by setting document location to the iframe’s source. ie you want something like document.location.href=$("iframe").attr("src");. But that fails because the right-hand side is null. The best you can do is set document.location.href to the last URL you pointed the iframe at.

@WHATWG Twitter Day

Today, @WHAT-WG started posting weird stuff on Twitter. Turns out whatwg.org had an open form to post to its Twitter account, right on the homepage. The interesting thing is it sat peacefully for two years on the homepage of a relatively prominent organisation’s website, until someone started being funny, and then others noticed, and by the end of the day…it’s in lockdown, with a password attached to the form. Still fairly open as you can apparently ask for the password in IRC.

Anyway, I found it an interesting phenomenon, watching it unfold, and captured the tweets using ListOfTweets and grabbed some screenshots.

Before:

After:

Twitter storm begins:

(interestingly, they deleted the tweets involving any swearing, but left the rest)

Twitter storm ends with the comment, “For 2 years, anyone could post on this twitter account, and nobody abused it … You still can, ask us for the password on freenode #whatwg.”