Mahemoff’s Software As She’s Developed [Mini Edition]

Mahemoff’s Software As She’s Developed [Mini Edition]

Michael Mahemoff  //  Web designer/developer. Rails/Ajax/etc

This is my random anything-goes blog - I am treating it as an easy way to generate mini web pages, rather than a continuous flow of consciousness on any particular topic. It gives me an outlet for things I can't say on Twitter in 140 characters, but are too unstructured, short, incomplete, and grammatically trainwrecked to post on my main blog at http://softwareas.com.

Mar 16 / 4:24am

A plancast "widget" - parsing @plancast RSS data

I've been enjoying plancast - similar to foursquare, which I don't really use, but instead of saying where you *are*, you say where you *will be*. And for meaningful places, ie industry events, not just checking in because you have to be at the dry cleaners.

In my homepage revamp, I decided to integrate my next event using my plancast feed. However, the feed doesn't provide much in the way of timing details. There's no human-friendly format ("in 3 days") and in fact, there's no structured date format (i.e. 12092840482 seconds after 1970), and in fact, there's not even a specific field for the time at all. It just appears in the "description" field, and it appears in different ways, i.e. a single date vs. a date range. (And different again if it spans two months, and if it spans two years, hmmm, it doesn't seem to be working yet for that - ).

So I wrote a custom parser to deal with it. It accepts the "description" string from the RSS feed:

  function plancastDaysAgo($descriptionString) {

    $match = preg_match("/When: (.*?)<br/", $descriptionString, $matches);
    if (!$match) return;
    $whenString = $matches[1];

    # "Monday, March 14, 2010" or "March 14-15, 2010"
    $match = preg_match("/^(?:\w+, )?(\w+) (\d+)(?:\-\d+)?, (\d+)$/", $whenString, $matches);

    # "May 30- June 2, 2010";
    if (! $match) $match = preg_match("/^(\w+) (\d+)\- \w+ \d+, (\d+)/", $whenString, $matches);

    date_default_timezone_set('Europe/London');
    $inputDateString = $matches[1]." ".$matches[2].", ".$matches[3];
    $days = floor((time() - strtotime($inputDateString))/86400);

    if ($days==0) return "today";
    elseif ($days==1) return "yesterday";
    elseif ($days==-1) return "tomorrow";
    elseif ($days>1) return "$days days ago";
    return "in ".abs($days)." days";

  }

It's called daysAgo for compatibility with standards "timeAgo"/"daysAgo" libraries, even though most of the time, the date will be in the future in this case.

Incidentally, a single item looks like this:
 <item> <title><![CDATA[2010: The Year We Broadcast Our Credit Card at Radisson Austin, Tuesday, March 16, 2010, 12:30pm (Robert Scoble)]]></title> <link>http://plancast.com/a/1g51?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=feed</link> <description><![CDATA[Robert Scoble shared a new plan.<br /><br />What: 2010: The Year We Broadcast Our Credit Card<br />When: Tuesday, March 16, 2010, 12:30pm<br />Where: Radisson Austin]]></description> <pubDate>Mon, 08 Mar 2010 19:05:08 +0000</pubDate> <guid isPermaLink="false">l3095567@plancast.com</guid> <author>Robert Scoble (Scobleizer)</author> </item>
I'm using MagpieRSS, so it looks something like:
     if ($rss) {
      $next = $rss->items[0];
      print "on the calendar: ".plancastDaysAgo($next[description]);
    }

Comments (0)

Mar 15 / 9:22am

author-specific wordpress feed for ajaxian

A while ago, a mate of mine asked me if there was a way to see just my articles on Ajaxian. I finally looked into it and discovered it's possible:

(And also the more raw, canonical URL - http://ajaxian.com/?author=7)

I'm updating my homepage today and wanted to include my Ajaxian posts alongside my personal blog, posterous (you are here), and twittering.

Comments (0)

Mar 10 / 1:38am

Harmony drawing tool

Comments (0)

Mar 10 / 1:37am

Harmony drawing tool on iPhone

Comments (0)

Mar 1 / 5:06pm

sandboxing, widgets, iframes - visit from @premasagar and @jamespadolsey

(super-brief notes... this is more about Prem's work on Sqwidget and related things, which James is also picking up. I blogged it earlier (http://softwareas.com/not-your-grandpas-framesets-premasagar-rose-shows-us-iframe-2-0), but now I'll repeat myself and refine based on my further understanding.)

* The central theme here is Sqwidget, a very lightweight, unobtrusive (in the sense of not imposing grand standards), framework for widgets which are embedded into a "host page", e.g. a blog (the host page) showing a twitter badge (the widget). The widget might be third-party or it might be provided by the host page.

* Normally, widgets are just a third-party providing a script tag, which document.write's an iframe pointing to a URL on the third-party site. That's do-able already, so how does Sqwidget help? Variously, but Prem's main point regards rich interaction, e.g. doing things like lightbox effects or iphone-like sideswipe effects, which wouldn't be possible with an ordinary iframe. He also sees the possibility of widgets interacting with the host page, e.g. to do things like resizing. Several Sqwidget-powered widgets on the page at once might have interesting interactions with each other. You might pull up a lightbox for one widget, and you'll see a dropdown showing all the widgets on the page, so you can immediately switch the lightbox over without having to close the lightbox. Or Sqwidget might change the way it presents widgets depending on the environment its in, e.g. for a mobile browser, it provides a launch button instead of showing the actual content.

* Compared to something like OpenSocial, Sqwidget widgets are just plain-old HTML - a single file containing all the HTML, CSS, Javascript, and images. (It used to be that a SPA was HTML/CSS/Javascript - now, thanks to the MHTML image hack, we have a new permanent fixture.)

* There are several related projects here (see http://github.com/premasagar)

- Sqwidget itself - a library the host file includes, which will augment all widgets with special sqwidget attributes with the actual widget (performing an on-demand load according to a widget URL specified in those attributes). It will also allow widgets to be conjured up and placed via programmatic means.

- Apple of my iFrame - a library that's all about iframe injection. $.iframe("<b>some stuff for the new doc</b>").appendTo("body"). Whereas traditional widgets use iframes to get around cross-domain restrictions and ensure security, Prem and James are using them for a primarily different reason: Sandboxing of CSS and Javascript state. Stuff injected into an iFrame has its own styling (although use of the iframe's allowTransparency attribute, and background "transparent" lead to interesting transparency effects) and a separate global (window) object. Apple of My IFrame handles tricky issues like moving the iframe to different parts of the DOM. (Should be easy, Isn't.)

- Sanitising - not something Prem's working on, but a Caja type thing in JS (see also FuseJS) would be great for Sqwidget to hook into, to ensure what it injects into the iFrame is secure. (The host page would probably set some flag to indicate it wants sanitisation to take place, versus saying it trusts the widget provider.)

- CleanSlate - what I think of as "extreme CSS resets". Lets you say "from this element down, apply this CSS and only this CSS". So it wipes out any inheritance from above, and also any rules that specifically targeted these elements. This is an alternative to Apple of my iFrame, which might be better in some circumstances.


Today, I made a tiny POC cloud IDE using the tool. (basically $.iframe($("#html").val()).appendTo("#output"); ) and we then spent a long time discussing the "embed code", i.e. what does it look like when the owner of the host page embeds a widget. We had several considerations:

* Shouldn't be blocking, so a script tag is ruled out. (Can't rely on browser features like "async" and "defer".)
* We spent a long time deciding how to hold the widget parameters, e.g. for an RSS widget, the host page would need to pass in the RSS URL. This was way more complicated than we expected, because we wanted the programmatic interface to match up with the one where the spec is embedded in the DOM and automagically widgetified upon startup. As an attribute, you can only really have a simple string, which the guys intend to ensure is a comma-separated list of key-value pairs; whereas if it's a Javascript argument, it can be any arbitrary data structure. The decision ultimately was to support both means, though this does lead to problems with the simple attribute model - typing is ambiguous, and nested data structures are impossible. So it may be that the widget provider receives only key-value pairs, where both key and value must be strings.I think Prem and James are still talking this issue over.

Comments (0)

Feb 27 / 3:34am

Having uploaded Wiki-Data showcase, we're halfway through 12 Days of TiddlyWiki http://12days.osmosoft.com

Comments (0)

Feb 22 / 1:47am

Ajax was the key improvement in search in recent years, says search expert

starO'Reilly Radar - Insight, analysis, and research about emerging technologies.
February 19, 2010 3:00 PM
by Mac Slocum

Search is the Web's fun and wicked problem

Peter Morville, co-author of "Search Patterns" and a long-time observer of the search domain, looks at the next wave of search in the following Q&A. He shows how "weird ideas" will shape search's future, and he also reveals the one recent innovation that unlocked a watershed moment for search (it's not what you'd expect).

MS: What's been the best search/UI development of the last 3-5 years? What really opened things up?

PM: Autocomplete is an old pattern from the desktop that's found new life in Web and mobile search. Once relegated to the musty modules of "help" in desktop software, autocomplete is now part of our everyday experience. It's a great answer to the question: why wait for results? It saves time and typos by serving up suggested searches or destinations while we're still entering our query. And, it's a simple design pattern with powerful potential. For instance, Yahoo complements basic autocomplete with an offer to explore related concepts. By analyzing query-query reformulation data and post-query browse behavior, Yahoo is able to suggest similar queries that don't even contain the original keywords. We can find what we didn't know to seek.

So, what really opened things up? I'd argue it was Google Maps. All of a sudden, designers realized what could be done with programming frameworks like Ajax, and autocomplete was simply one of many interaction design patterns that flourished on the Web soon after that watershed moment.

Comments (0)

Feb 19 / 2:34am

UnderscoreJS's _.isEqual() is perfect for unit tests

UPDATE: @andybeeching points out what shouldabeen the bleeding obvious: QUnit's same(). (I'd internalised QUnit as having just ok() and equal() as I always think it's unusally small compared to Junit's myriad ofassertGreaterThan etc (which I prefer)...I forgot the third and obvious one.)

Drop this into your QUnit (http://docs.jquery.com/QUnit) test (or similar in other Javascript testing frameworks). It's a drop-in replacement for the standard "equals" equality test in QUnit. It will recurse through data structures and so check proper equality of objects and arrays. Plus, it will still compare normal values too, using === (http://longgoldenears.blogspot.com/2007/09/triple-equals-in-javascript.html).

I just started using it here:

to test:

Comments (0)

Feb 18 / 3:23am

PHP serialisation

Working with @FND to get a PHP script talking to TiddyWeb. (The same way it would talk to a MySQL server for persistence, but making RESTful HTTP calls.) Anyway, trivial stuff and we divvy up between JSON serialisation and making the HTTP call. Here's the JSON serialisation:

<?

  require_once "JSON.php";

  $teams = array(
    "carlton" => "blues",
    "collingwood" => "maggies",
    "essendon" => "bombers",
    "wins" => 16,
    "managers" => array("president" => "bob", "caretaker"=>"harry" ),
    "years" => array(1906, "1915-1915", FALSE)
  );

  $json = new Services_JSON();
  print($json->encode($teams));

?>

It's using Michael Mygurski's PHP library (http://mike.teczno.com/json.html) ... now in PEAR.

Aside: Thanks to jQuery 1.4 making a big deal of it, I'm now using "" on the left-hand side (the hash keys), always. Whether in PHP (where I have to), Javascript (where it's possible not to), or wherever. It's the standard.

Comments (0)

Feb 17 / 10:32am

State of TiddlySpace

We've done some work between last week and tomorrow's weekly hackathon. Building the current tiddlyspace is pretty easy, which will hopefully get tomorrow's session off to a flying start:

> git clone git@github.com:FND/

tiddlyspace.git
> cd tiddlyspace
> ./dev.sh (uncomment the "pip install" line the first time you run it, to ensure you have the latest version)

All things being excellent, you'll then have some instructions about how to try out your new TiddlySpace instance.

We should be able to change Javascript under this setup and just refresh the browser; and Python changes we just need to run "twanager server".

Comments (0)