elfs: (Default)

I was looking at the Digg source code the other day and, I’ve gotta say, mega-props to the developer of their javascript. The traditional rule in web development has become, “Put your Javascript at the end of your page.”  That way, all of the DOM objects you might refer to are guaranteed to be present when you start referring to them.  This had been a chronic problem in web development, associated with much pulling of hair and gnashing of teeth. The more modern way is to load your scripts up front, but use jQuery’s $(document).ready(...) method to ensure that nothing would run until your DOM tree was loaded. You might still have to wait on media assets (you used to be able to say “images”, but with HTML5 media assets include sound and video), but the DOM will be there and ready. You’ll be free to set up onload events to the media assets. The $(document).ready(...) technique ensures that your javascript will run correctly but it still has one classic problem: download delay. If you want an anchor to do something more than just be a link when you click on it, you’ll have to live with the chance that the user will click on it before the javascript has run and it will just be a link. Digg doesn’t live with that. Instead of using $(document).ready(), they do something much more clever. In the header of their HTML document, they create unique event names that signal when some part of the page has been handed to the browser. You can do this with jQuery, which lets anything at all be an event. Let’s say you have an anchor that you want to do something funky when you click on it, something Ajaxy. First, in a javascript library that you load in the header, you define the function:

function dosomethingfunky() { /* ... do something funky with $(this) ... */ }

Then you bind it (note the completely custom event name):

$(document).bind('somethingfunky_ready', dosomethingfunky);

And finally, in the body, when the anchor has been loaded into the DOM, you trigger the set-up right there:

<a href="http://someexampleurl.com" id="somethingfunky">Funk Me!</a>
<script type="text/javascript">$(document).trigger('somethingfunky_ready');</script>

Now that’s cool.  Your race condition window is down to milliseconds; the event handler is probably set up even before the browser has a chance to render the object.  Yes, there’s a price: your page is littered with triggers and unobtrusiveness is a thing of the past.  But if you need this kind of set-up and performance, this is how it’s done, aesthetics be damned.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

Metacritic is an interesting website with a pretty stylish layout, but one thing that drives me nuts is the use of Flash for a simple slideshow on the home page. I decided, as an experiment, to try and replace that with one driven by Javascript.

The choice of javascript turned out to be simple: I’d use jQuery. Not only is it easy to write with, but there’s already an incredible plug-in for jQuery called Cycle. Having read through the documentation, the only “tricks” would involve automagically generating the thumbnails, placing them in-line within the slide show, and ensuring they had the right z-index so that they’d be visible.

You can read the description or skip right to the demo. The source code is all there.

The basic premise is that cycler automatically fade between the images, using the standard “fade” setting. So the entirety of the javascript, after importing jQuery and Cycler, is this:

$(document).ready(function() {
    $('#slides').cycle({
    fx: 'fade',
    delay: 4000,
    speed: 200,
    pager: '#slide-thumbnails',
    pagerAnchorBuilder: function(idx, slide) {
        var s = $('img', slide).attr('src');
        return ('<a href="#"><img src="' + s + '" /></a>');
    }})
});

Basically, we’re looking for the DOM element ’slides’, and all of its immediately children will be treated like slides. We also have a second DOM element ’slide-thumbnails’, which I’m filling with a simple anchor containing a copy of the image.

The DOM element ’slides’ has individual slides, which look like this:

<div>
  <img src="./95.jpg">
  <div>
    <h2>Omaha</h2>
    <p>At the annual Pumpkin patch run.</p>
  </div>
</div>

To be fair, I’m assuming every image is the same size. That’s relatively important.

The only remaining trick is to wrap slides is another div, ’slide-container’, position relative, and both ’slides’ and ’slide-thumbnails’ are positioned absolutely with respect to ’slider-container.’  ‘Slide-thumbnail’ is made the width of a thumbnail, forcing them into a vertical column.  The z-index of both ’slides’ and ’slide-thumbnails’ are both set so that the thumbnails are above the slides.

It’s simple and elegant.  A little positioning allows the title and text to be placed accordingly, and a nice black background, set to 66% opacity (which you can do with PNG) allows you to place the title and text on the page with a nice delimeter.

Metacritic has in-house artists who make sure the left thumbnail bar doesn’t stomp all over the image. You’ll have to master some fine Gimp or Photoshop to achieve the same effect.

Check out the demo.  Source code is all there.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

I had a job interview today, and one of the “challenges” with which I was presented was this: “We own several sites. We would like our user to be able to log into the central site as a subscriber, and then all the other sites will know what permissions that user has.”

The sites are cooperative, so getting content onto each one to support this idea isn’t difficult. Also, all of the sites belong to the same user, so getting a regular framework that you can deploy to all of them isn’t difficult either.

The scenario we want to support is this. We have two websites, the remote authentication server framework. Let’s call it “rasf.com” (which, sadly, does not go to rec.arts.sf.written), and let’s call the site that wants authentication “brandx.com.” (Sadly, this is a parked site that leads to a stock photography reseller.) The idea is that you’re a subscriber to rasf.com. You visit brandx.com, and Brand-X initially has no idea who you are. We want Brand-X to be able to say, “Hey, Rasf, who is this guy?” and have Rasf come back “Oh, he’s John Smith, he’s a legit user, and here are some details.”

The trick involves public key cryptography.  Both Rasf and Brand-X have public and private keys.  To understand the scenario, you must appreciate that much of the heavy lifting is done away from both sites on the browser.  The problem is that, on the browser, any windows opened between Rasf and Brand-X cannot communicate with each other; this is known as the sandbox, and it keeps malicious sites from using iframes or Ajax to either inject malware Javascript into the victim page or allow the nefarious iframe from ripping data (like username and password keystrokes) from the victim page.  We want to violate the sandbox, but how?

Assumption: You’ve visited Rasf recently, and have a cookie from Rasf saying “Yes, I, Joe Smith, and a valid user of Rasf and affiliated sites!”

You access a page from Brand-X.    Secretly, Brand-X creates a one-pixel-wide iframe and set the iframe’s src attribute to the “authenticate this user” page on Rasf, including in the request its public key as an argument.   After the iframe loads, the loaded page from Rasf now has the session information on the browser, and it has Brand-X’s public key.  The session information includes the Rasf cookie.    So now, Rasf knows two things: it knows who you are, and it knows that Brand-X wants to know who you are.

How does that who you are information get back to Brand-X?  Here’s where the cooperation comes from.  The iframe from Rasf, using the onload() event, creates yet another iframe, this time calling back to a specified page (the cross-domain receiver page) on Brand-X’s site, and that URL is loaded with your user ID, a cross-domain session key, and other information, all signed with the Rasf private key (so the Brand-X site can unpack with Rasf’s known public key).

Now, because both the containing page and the iframe two layers in are in the same domain, they’re in the same sandbox, and can communicate with one another via javascript.  The innermost iframe communicates with the cookies of the outermost page, the calls reload: all this information has now been pushed back to the Brand-X server, which can now use the signed cross-domain session key to make back-end requests of Rasf’s web services API and say, “Okay, now that I know he’s user 12345, and I have a session key validating this conversation, what else can you tell me about him?”

There are lots of other details here.  What if he’s not logged in to Rasf at all?  Well, enlarge the 1-pixel iframe to a size big enough to show a log-in within the Rasf domain, get his username and password, authenticate and proceed as before.

This is a generic description of what Facebook Connect does, and it’s how you can do it as well.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

Yes, that’s a signal boost.

I’ve only played with Node.js for about 24 hours now, and I’m already deeply impressed with it. Node.js is something of a holy grail: an implementation of server-side (and desktop) Javascript with a modern engine (Google’s V8), in which all I/O is event-handled. You no longer care about multiplexing, spinning off threads, or any of the myriad gazillion other cares that server developers used to worry about. Instead, that’s been built into a reactor core inside Node.js, and instead you receive notice of events (just like in browser-based Javascript), where the events will things like “header received,” “body received,” “message end,” “connection made,” and to which you’ll be able to attach enclosured functions that will respond appropriately. It’s an application server’s base language on acid, and while I’m bad at making predictions, I suspect Node.js will be with us for a while.

Already there’s a NoSQL database interface, the start of an application server, the start of a CLib-like library (like Python or Perl’s standard library), and even a comet server. This could be fun.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

So, I just kicked out another edition of Red State Poly, and I’m trying to figure out what, if anything, I should do with it. There are a few things I could do: obviously, I could work hella harder to make it absolutely consistent with all browsers, but now it works with IE6, 7, Firefox and Chromium, so I’m happier with it.

I found a nasty bug in jQuery’s cookie handler. Under Chromium, it returns null, not an empty string, when there are no cookies. Ick. Handled and fixed. My code also passes most of the JSLint whines.

There are a few things I could do with it. I could (1) make it handle 20 names gracefully, (2) make it handle multiple dates per woman, and calculate fertility based on that, (3) make editing of incorrectly entered dates more graceful.

All of these would be work, some moreso than others, for what was essentially a lark I wrote months ago to teach myself how jQuery was different from EXT-JS. This page is a one-shot pure Javascript play that demonstrates my client-side scripting chops. There’s no server-side at all to it. Does anyone think I ought to pursue this further, or is it “good enough” as is? And what do I do with it?

The source code is all there, by the way, in case anyone wants to review it. I haven’t compressed the Javascript at all.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com

CSS Sprites

Sep. 6th, 2009 03:08 pm
elfs: (Default)

It seems like such a stupid thing, but hey, now I know how to use CSS sprites.

Basically, it’s the same idea as a viewport slider: treat your rectangular space as a viewport onto a background image. By using the background-position attribute and the .css() control (in jQuery; there are others in other libraries), you can move the background image around. If you have two different icons of the same dimensions, you can make the DIV (or whatever rectangle you want) the same size as one of them, and concatenate all of the images together (either left/right or top/bottom). The first image will show up in the DIV. When you want the other image to show up, set the background position to the negative (left or top) of the width or height (respectively), and it’ll slide your first image out of view and show the second one.

I discovered this when I saw that Firefox was making a round-trip every time I hit the end of a paginator, because it was fetching the “enabled”/”disabled” buttons that the previous programmer had built there. A round trip for every action? My gods, you’d better save that for state control, not special effects. Anyway, it’s working now, and no more “fetches from the database” to get even a 302 (item cached) transaction.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)
I spent a solid two hours figuring out how to do this, so I decided to share with the world. Those of you with small monitors (or other strange habits) might have operating system dock (the thing at the bottom or top of the screen that you use to start programs, check the clock, and see what's running away with your CPU and network) set to "autohide," so it comes and goes as you mouse over it.

If you've ever wanted to simulate that in your HTML, I've figured out how to do it with jQuery. I've even provided a bare-bones skeleton of a dock, along with a working example. Feel free to embellish it at your leisure.
elfs: (Default)

The correct call for posting to a user’s facebook wall with Python and pyfacebook, after you’ve established both user authentication via FacebookConnect and gotten stream_publish permission, is:

request.facebook.stream.publish(
    message = render_to_string(template_path, fb_context),
    action_links = simplejson.dumps(
        [{'text': "Check Us Out!", 'href': "http://someurl.com"}]),
    target_id = 'nf')

See that ‘nf’ down there in target_id?  It’s not on any of the Facebook documentation pages, but that is the correct string to post to your user’s facebook Newsfeed. (For that matter, the fact that you have to run the action_links through simplejson, and that they have to match the PublishUserAction API action_links spec, is also not documented; the documentation says it just needs an array of arrays.)  I have no idea how to post to some other user’s newfeed, but at least I’m one step closer.

Oh, another important tip: in order to make my news “stories” consistent, I’m using a template to post them to Facebook.  The template must not have newlines within, or they will show up on Facebook and it’ll look all ugly.  Every paragraph should be one long line of text without line breaks.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

I have added Restricting a function’s scope to a specific object to the Javascript Framework Phrasebook.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

As some of you may have heard, I recently lost my job at Isilon. In that great tradition, I have put up my resume. Have a look, and please comment on the content or presentation of either version:

Kenneth M. Sternberg, Senior Web and User Interface Developer and Designer.

There’s a copy for printing here.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)

I work with EXT and Prototype at the office, and Dojo at home. I have a lot more time with EXT than either of the other two, so when I’m working on a personal project my first thought is “If this were EXT, I’d do it this way, but how do I do it in Dojo?”

It’s useful to write that knowledge down.

Last night, I ginned up a quick wiki, dropped in a theme I liked, and put the whole thing up. It only has a few entries right now but they should be enough to show what I’m trying to accomplish. If you find this a useful idea, please contribute to it and publicize it:

The Javascript Framework Phrasebook

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
elfs: (Default)
A few months ago, I asked what the new operator does in Javascript. There wasn't much of a response, but I did eventually figure it out. Sometimes you just have to wade through the specifications. Here's the outcome of my research:

Deep geekery ahead! )
I just wanted to put that somewhere where it wouldn't get lost.

It also took me a while to realize that Result(N) means "the product after performing the operation of step N.

The new keyword allows you to define objects with prototypes, so that you can have a class heirarchy that doesn't require external maintenence. I strongly suspect that Doug Crockford's lecture on "prototypal inheritance" would be edifying here.
elfs: (Default)
For javascript programmers, Prototype.js is probably the coolest thing around; easy to learn, but not so easy to wrap your head around all at once. Probably the hardest thing to grasp about it is the way it hybridizes Javascript's lisp-like internal structure with more traditional OO constructs like classes, construtors, and interators, then turns around and re-exposes those lisp-like capabilities with functional utilities like detect() and map().

But Prototype is not always complete. A noteable example can be found in PeriodicalExecuter, which takes two arguments: a function to callback, and an interval, and on the interval it calls the callback. The problem is that there's no utilitarian way to pause a PeriodicalExecuter; you can only stop and restart it. If the callback function has some state (which is possible in Javascript, now that closures in Javascript have become commonplace), tough.

So I wrote a PeriodicalExecuterToggled, which allows you to stop and start the PeriodicalExecuter at will and keep the callback unchanged.

Javascript deepness )Combined with something like the Scriptaculous Slider, this version of PeriodicalExecuter can provide for some interesting user-controlled experiences with javascript animation, regular updates from back-end servers, and other Web 2.0 services.

Sorry about this article bouncing around like this: I never realized just how frakkin' hard it is to post source code to LJ!

Profile

elfs: (Default)
Elf Sternberg

June 2025

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 3rd, 2025 03:00 am
Powered by Dreamwidth Studios