Mar 02

Code snippet: Stopping a jQuery AJAX Request

I want JavaScript to feel as smooth as a native application. I think scrolling is one of the largest issues, but this code snippet is more about aborting the jQuery AJAX event before it has a chance to complete.

There's no good documentation in the jQuery docs about how to do this. other than to just use this command on an existing AJAX request:

var request = $.ajax('/url', data, callback);
request.abort();

That doesn't work. Well, it does work, but if you try to run it again or synchronously with other requests, you'll run into issues.

The issues are non-trivial, but avoidable. I'll cut to the chase; I came up with a solution, then found that somebody did it better and more correct.

Rather than spreading incorrect (rather, incomplete) code, I'll just show the proper way to do it and then link to the source.

_isAbort: function(xhr, o){
    var ret = !!( o.abortIsNoSuccess 
                  && ( !xhr 
                       || xhr.readyState === 0
                       || this.lastAbort === o.xhrID ) );
    xhr = null;
    return ret;
},

That's a lot of work. Don't bother, just use jquery.ajaxManager v.3.0: http://www.protofunc.com/scripts/jquery/ajaxManager3/

Note, however, that if you just google "jquery ajax manager" or some variant, you will end up at the old version, which is at: http://www.protofunc.com/scripts/jquery/ajaxManager/. They could do some work on their google juice pointing to the latest version.

Hope this helps somebody else, even if part of a google search for "jquery ajax stop request" someday.

Feb 16

A jQuery Plugin: Default Values for Input Fields

One of the best ways to write code that you tend to have to re-use is to put it in the public domain. That way when you need it again, it's a Google search away from your own blog.

This is a rather simple working example of default text on an input field. Click on the field, the text disappears, only to reappear if the user clicks somewhere else on the page without typing. The input also has a special class signifying that it is empty, so you can style the empty input.

Demo

JavaScript Code

(function($) {
    
    $.fn.extend({
        
        input_default: function(default_text, opts) {
            if (typeof default_text !== 'string') {
                opts = default_text;
            } else if (!opts) {
                opts = {
                    'default_text': default_text
                };
            } else {
                $.extend(opts, {'default_text': default_text});
            }
            
            var defaults = {
                'default_text': 'Type here...',
                'class_name': 'empty-input'
            };
            var options = $.extend({}, defaults, opts);

            return this.each(function () {
                var $this = $(this);

                if ($this.val() == '' 
                    || $this.val() == options['default_text']) {    
                    $this.addClass(options['class_name'])
                         .val(options['default_text']);
                }
                
                $this.bind('focus', function() {
                    if ($this.val() == options['default_text']) {
                        $this.val('')
                             .removeClass(options['class_name']);
                    } else {
                        $this.select();
                    }
                }).bind('blur', function() {
                    if ($.trim($this.val()) == '') {
                        $this.val(options['default_text'])
                             .addClass(options['class_name']);
                    } else {
                        $this.removeClass(options['class_name']);
                    }
                });
            });
        }
        
    });
    
})(jQuery);

Usage

First, the HTML you can use:
<label for="default-text" class="default-text-label">
    Here is a text box: 
    <input type="text" id="default-text" class="default-text" />
</label>
You can call `input_default` with no arguments and get the defaults:
$('.text').input_default();
Specify an optional string or class:
$('.text').input_default('Enter text here...', {'class_name': 'empty'});
Here is some sample CSS to use:
.default-text {
    border: 1px solid #C0C0C0;
    padding: 2px;
    font-weight: bold;
    font-size: 14px;
}

.empty-input {
    color: #A0A0A0;
}

.default-text-label {
    font-size: 16px;
    font-weight: bold;
    color: #303030;
}
Jan 18

A Faulty Heist: A Storybird

This Storybird is written by thesundaybest, found on twitter: @thesundaybest.

A Faulty Heist by thesundaybest on Storybird

Storybirds like this remind me why I love working with a community of artists and children's literature.

Jan 15

Syntax highlighting for Django using Pygments

The wonderful django-mingus includes a few separate syntax highlighters, including one from django-sugar. However, the pygmentize template filter only works on <code> blocks and tries to guess the language.

A better syntax would be to include the language in the class of the code block, like so:

<code class="python"> 
    import this 
    print [r for r in range(0,10,2)] 
</code> 

You can use this template filter, which is adapted from the Pygments Rendering Template Filter at Django Snippets.

import re 
import pygments 
from django import template 
from pygments import lexers 
from pygments import formatters 
from BeautifulSoup import BeautifulSoup 
 
register = template.Library() 
regex = re.compile(r'<code(.*?)>(.*?)</code>', re.DOTALL) 
 
@register.filter(name='pygmentize') 
def pygmentize(value): 
    last_end = 0 
    to_return = '' 
    found = 0 
    for match_obj in regex.finditer(value): 
        code_class = match_obj.group(1) 
        code_string = match_obj.group(2) 
        if code_class.find('class'): 
            language = re.split(r'"|\'', code_class)[1] 
            lexer = lexers.get_lexer_by_name(language) 
        else: 
            try: 
                lexer = lexers.guess_lexer(str(code)) 
            except ValueError: 
                lexer = lexers.PythonLexer() 
        pygmented_string = pygments.highlight(code_string, lexer, formatters.HtmlFormatter()) 
        to_return = to_return + value[last_end:match_obj.start(0)] + pygmented_string 
        last_end = match_obj.end(2) 
        found = found + 1 
    to_return = to_return + value[last_end:] 
    return to_return 

This is a template filter, which can be applied like so:

{{ code|pygmentize }}
You can read more about custom tempalte filters at the Django Project: Writing Custom Template Filters.
Jan 13

NewsBlur: Feed Reader with Artificial Intelligence

Every two to three years I start a new project. Having recently completed the SunRayLab blog, I turned to another problem that I have been having since i started visiting blogs and other sites through the lens of my RSS feed reader, NetNewsWire.

I am starting a new project called NewsBlur. NewsBlur is an RSS feed reader with intelligence. See NewsBlur in action.

My problem is simple: I subscribe to a few dozen blogs. I do not want to read all of their many stories, yet my unread count keeps climbing. Some blogs post frequently while other blogs post once a month. I want a feed reader that easily trims the undesirable fat from my feeds.

This has been done in varying degrees before, but each implementation has been lacking for any number of reasons:
  1. The reading interface was convulted, slow, difficult, too busy, or rough.
  2. The intelligence used to pare down my feeds to just what I want was either difficult to setup, hard to train, overly-burdensome, or even just plain stupid.
  3. Marking feeds and stories as typical of what I want in the future has never been done.
I am solving this problem in a unique way.

The challenge in creating an interesting experience that is different from any other experience is what drives me to work on NewsBlur. I want a service that works for me. I expect that before I finish, I will already have abandoned my tried-and-true NetNewsWire (on both Mac OS and iPhone) in favor of NewsBlur.

I will use this blog space as a means to communicate advances in NewsBlur, as well as methodologies, practices, and thoughts behind the creation of NewsBlur.

My hope is that NewsBlur becomes part of a community that further enhances the news and blog reading experience for everybody.
Jan 12

Powered by Kevin Fricovsky's django-mingus

Since 1999 I have had a presence on the web. I bought conesus.com back then and used it to link to projects, code samples, writings, and photographs. I now own conesus.com, samuelclay.com, and ofbrooklyn.com, all of which now serve different purposes.

My primary blog platform has been a hand-coded blog engine called SunRayLab that I used for ofbrooklyn.com for the past three years. It's time to retire it, as great as I have felt I made it. The whole caboodle is in aging PHP and the future is definitely not there.

Thanks to Kevin Fricofsky's hard work, I have django-mingus to use for a blog. It combines a few dozen different django applications with a minimal amount of glue. Surprisingly, everything hums along nicely and Kevin listens and acts quickly, so I have faith in the future of this platform, for once.

It is humbling to take down my old creations, but it also signifies a maturity inherent in code obsolescence. Code ages, much like a house. If you don't take care of it and upgrade it with working utilities, then it will begin to crumble. Whether the water main breaks (perhaps you upgraded a dependency elsewhere on your server and the new version breaks your current code), or the appliances are no longer shiny and clean (and you want code highlighting in your blog platform, but that requires a lot of tangentially work that cascades into more work quicker than you can say 'enough').

My goal is to post code, help others in a way similar to how I have been helped by developers posting tidbits, tutorials, and findings. I plan to write an occasionally essay, since I tend to disagree with opinions fairly often and want something to show for my trouble. I may even post photos.

The future is bright and my fingers are not yet tired.

Oct 01

Raphaël Demo - Cross Browser Vector Graphics - Topic Connections Graph

SVG, an open, standardized vector graphics markup language is now supported on 30% of all web browsers. The other 70% of browsers (specifically, Internet Explorer), support VML, a close cousin of SVG. If you write both SVG and VML, you can provide rich, interactive vector graphics > 99% of all browsers.

Raphaël JavaScript Library does all the heavy lifting for the developer. Write your circles, paths, animations, and interactions (events, mouseovers, clicks) in Raphaël, and it will write compatible SVG and VML that works almost everywhere. I have contributed to Raphaël and am currently presenting a paper and a workshop on Raphaël at SVG Open 2009 at Google HQ in Mountain View, California.

I wrote this demo for Daylife, but this demo uses a number of features in Raphaël, showcasing a number of features that can be used to make interactive graphics that are unlike anything else natively supported by almost all web browsers. This means no plug-ins or installs. No Flash. Just what is already built into every web browser.

Demo - Topic Connections Graph

Code

1) Download jquery.topicconections.js

2) This code should go into your <style>:

.SO-module .SO-name {
    display: block;
    font-size: 10px;
    line-height: 11px;
    margin: 5px 0;
    position: absolute;
    text-align: center;
    visibility: hidden;
    width: 80px;
    color: #416799;
    font-family: "Lucida Grande";
}

.SO-module a {
    text-decoration: none;
    background: none;
}

.SO-active a {
    text-decoration: underline;
}

.SO-module ol li {
    list-style: none !important;
}

.SO-module {
    margin: 20px;
    position: relative;
}

3) Include these scripts in your <head>:

<script src="http://raphaeljs.com/raphael.js" 
        type="text/javascript" charset="utf-8"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" 
        type="text/javascript" charset="utf-8"></script>    
<script src="/scripts/jquery.topicconnections.js" 
        type="text/javascript" charset="utf-8"></script>

4) This code goes inline:

<div class="SO-module">
    <div id="SO-connections-graph-wrapper">
        <div id="connections_graph_186817" class="SO-connections-graph"></div>
        <ol class="SO-topics">
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/White_House">White House</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/U.S._Republican_Party">U.S. Republican Party</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/U.S._Democratic_Party">U.S. Democratic Party</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/U.S._Congress">U.S. Congress</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/George_W._Bush">George W. Bush</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/U.S._Senate">U.S. Senate</a>
            </li>
            <li class="SO-topic">
                <a class="SO-name" href="http://beta.daylife.com/topic/Economic_Recession">Economic Recession</a>
            </li>
        </ol>
    </div>
</div>

5) This JavaScript code also goes inline:

var images = [
    {
        'img': "/media/img/svg_demo/whitehouse.jpg",
        'text': "White House",
        'link': "http://beta.daylife.com/topic/White_House",
        's': "large"
    },
    {
        'img': "/media/img/svg_demo/repub.jpg",
        'text': "U.S. Republican Party",
        'link': "http://beta.daylife.com/topic/U.S._Republican_Party",
        's': "large"
    },
    {
        'img': "/media/img/svg_demo/demo.jpg",
        'text': "U.S. Democratic Party",
        'link': "http://beta.daylife.com/topic/U.S._Democratic_Party",
        's': "large"
    },
    {
        'img': "/media/img/svg_demo/congress.jpg",
        'text': "U.S. Congress",
        'link': "http://beta.daylife.com/topic/U.S._Congress",
        's': "medium"
    },
    {
        'img': "/media/img/svg_demo/bush.jpg",
        'text': "George W. Bush",
        'link': "http://beta.daylife.com/topic/George_W._Bush",
        's': "medium"
    },
    {
        'img': "/media/img/svg_demo/senate.jpg",
        'text': "U.S. Senate",
        'link': "http://beta.daylife.com/topic/U.S._Senate",
        's': "small"
    },
    {
        'img': "/media/img/svg_demo/econ.jpg",
        'text': "Economic Recession",
        'link': "http://beta.daylife.com/topic/Economic_Recession",
        's': "small"
    }
];

var topic_image = {
    'img': "/media/img/svg_demo/obama.jpg",
    's': 'xlarge'
};

var center_x = 125;
var center_y = 125;
var offset_x = 45;
var offset_y = 45;
var $graph = $("#connections_graph_186817")[0];
var graph_x = 340;
var graph_y = 340;

var sizes = {
    'small': 35,
    'medium': 55,
    'large': 75,
    'xlarge': 100
};

var topic_graph = new TopicConnectionGraph($graph, graph_x, graph_y, 
                                           center_x, center_y,
                                           offset_x, offset_y, sizes);
topic_graph.runner(images, topic_image);
Sep 01

Why Bother Going to College

In response to James Padolsey's blog post on his apprehension to studying Java before his first-year studying computer science.

University is unlike anything youve done, and unfortunately anything else youre going to do unless you really love the study of computer science. I recently graduated from university with a degree in Computer Engineering, taking roughly similar courses as a Comp Sci (except we also took harder classes related to engineering that were straight out of unrelated engineering disciplines, like thermodynamics, statics (bridges), and materials science).

Almost everybody enrolled in the computer science department started out years before school, programming in somethingusually web development (esp. Javascript, the bad parts). A healthy number of them drop out of the program and switch to math/physics/management or even art history. They drop comp sci not because they are dumb, or have a slower intake of the sheer volume of dense material fed to them. Its because they discover that the internals, things like how primitives are actually allocated in different ways in memory, sometimes even to your advantage to use the right one, are not as interesting as they had hoped. Low-level course material, such as transistor logic, VHDL, networking, operating systems (easily one of the most challenging and rewarded courses taught in computer science), and systems programming, are all above and beyond what most contractor/freelancers will face while they are busy earning 25% more than their comp sci cousins.

But the difference is worth a lot. Take a look at that one, systems programming. Here is a short description of whats taught:

EECS 337 Systems Programming - 4 credits Lexical analyzers; symbol tables and their searching; assemblers, one-pass and two-pass, conditional assembly, and macros; linkers and loaders; interpreters, pcodes, threaded codes; introduction to compilation, grammar, parsing, and code generation; preprocessors; text editors, line-oriented and screen-oriented; bootstrap loaders, ROM monitors, interrupts, and device drivers. Laboratory. Prereq: EECS 233 and EECS 281.

If you want to write code that does anything that involves automated decision making, the true back-end of great companies to work for or start, you need to actually study and learn about these low-levels to build better decision trees (data structures alone make it worthwhile) and neural networks. There are so many fascinating topics out there, and they are all more expressive than having to design web sites for clients.

I absolutely love the study of artificial intelligence, and am working on a project where the meat of the project is in the AI that feeds the site, but I dont write algorithms or architect systems for a living. I write Javascript code (and Python on the back-end serving up the front-end), designing a web app for publishers to create photo galleries. Its not quite the academic challenge I get on my project, but you also have to be very, very good at computer science to get recognized and to make big contributions, even to small companies (think startups).

Computer Science is a rich and engaging degree, and while it isnt for many who think it is, those who stick with it all 4 (to 5) years end up very happy. This is the golden age of software. Theres a lot of upheaval which will forge new empires, and I bet something as notable as the few winners of the California gold rush of the 19th century didnt even have the prestige that good engineers have. Think of all the famous and very wealthy nerds. Think about that when youre slogging through decimal floating-point arithmetics in binary by hand.

Jul 14

Presenting at SVG Open 2009: Workshop on Raphaël JS

We were accepted! Here is our finished abstract, also available on the SVG Open 2009 workshop page: http://www.svgopen.org/2009/registration.php?section=workshops.

Dmitry Baranovskiy - http://dmitry.baranovskiy.com - dmitry@baranovskiy.com
Samuel Clay - http://www.ofbrooklyn.com - samuel@ofbrooklyn.com

The power of web browsers has reached the point when it is easy to use native vector graphics without any 3rd party plugins and installs. In this session, we will discover how to build rich graphics in your web app using Raphal (http://raphaeljs.com/) JavaScript vector library, the features Raphal provides, and walk through how to apply these features into a fully built module.

This course will cover a number of features ranging in complexity from basic layout to event-driven interaction. The module will be a moderately complex application consisting of parts SVG, Javascript, jQuery, and HTML. While Javascript experience is expected, it is not necessary, considering the syntax of Javascript in this capacity is not far different than many other languages.

The module, which will be used to demonstrate a number of techniques in creating both interactive and layered elements in SVG, will be sufficiently advanced as to cover many topics, but so in-depth that it cannot be built entirely from scratch in the time allotted for the course--including time used for demonstrating Raphal.

The 150 minute course will consist of 3 parts, with questions taken throughout:

  • Introduction to Raphael (35 min)
    • 5 minutes: Introduction and Overview of the People Connection widget
    • 10 minutes: Looking at the Raphael JS Library's methods and documentation
    • 10 minutes: Setting up data for the module to be used in drawing
    • 10 minutes: Loading data into Raphael
  • Drawing the widget (45 min)
    • 10 minutes: Images
    • 15 minutes: Shapes
    • 20 minutes: Lines, straight and curved (quadratic and bicubic)
  • Interaction model (60 min)
    • 20 minutes: Handling user/triggered events
    • 15 minutes: Animation
    • 25 minutes: Interacting with the DOM and jQuery

There is a time buffer built into each part, and if there is extra time, we will be prepared to discuss:

  • Raphael versus other SVG/Javascript libraries
  • Other projects built on Raphael
  • Browser compatibility with Raphael

For each section of the course, we plan to discuss:

  • Implementation and coding conventions
  • Potential pitfalls with certain techniques (browser incompatibilities, misconceptions, and common mistakes)
  • Building the widget by coding in real-time (and not using blobs of code already written).

The flow of this walk-through course will be aligned with the building of the module, where we will start with a empty file and progress over each step used in creating the overall effect and feel of the finished widget. Each piece of the widget puzzle will be complemented with a demonstration of the incremental improvement. At the end of the course, a complete module, with all of its pieces, will be fully functional and fully explained. Participants will also have all of these Raphal resources to use in their own SVG projects.

Jun 04

Raphael Plugin: Animation Easing

Raphael is a wonderful Javascript library, used for creating vector graphics, and interacting with SVG/VML elements through Javascript. Raphael allows the developer to interact with these elements through a number of complex animations. 

Until now, the only speed for an animation was a linear movement from one state to another. This plugin extends the animation of Raphael to allow for easing animations. Derived from jQuery Easing Plugin (version 1.3): http://gsgd.co.uk/sandbox/jquery/easing/.

NOTE: As of June 2009, this plugin requires a forked version of RaphaelJS. You can download it here: https://github.com/conesus/raphael/tree. Hopefully, these forked changes will be merged with the master Raphael JS code.

Demo:

View a demo of animation easing techniques here: http://demos.daylife.com/samuel/svg_photo_flipper_prototype.xhtml

To use:

  1. Download raphael.easing.1.3.js from: http://github.com/conesus/raphael-easing/tree/master.
  2. Include the raphael.easing.1.3.js file after your raphael.js file.
  3. Specify the easing technique in the .animate() function, like so:

    Element.animate({"scale": [1.25, 1.25]}, 750, "easeOutCubic", callback);

Available easing techniques:

  • linear
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInQuint
  • easeOutQuint
  • easeInOutQuint
  • easeInExpo
  • easeOutExpo
  • easeInOutExpo
  • easeInElastic
  • easeOutElastic
  • easeInOutElastic
  • easeInBounce
  • easeOutBounce
  • easeInOutBounce
May 18

Proposal for SVG Open 2009

The SVG Open 2009 is in October at Google's campus in California. I recently submitted my proposal for a course on writing SVG through Javascript and the Raphael Javascript Library. Below is my proposal. Let's hope it is approved and I am able to continue work in SVG.

I am proposing to teach a course about building an interactive SVG module on the web through the use of the Raphael Javascript Library. From start to finish, the course will walk attendees through the process of creating an interactive widget, with a number of features ranging in complexity from basic layout to event-driven interaction. The widget will be a moderately complex application consisting of parts SVG, Javascript, jQuery, and HTML. While Javascript experience is expected, it is not necessary, considering the syntax of Javascript in this capacity is not far different than many other languages.

The widget, which will be used to demonstrate a number of techniques in creating both interactive and layered elements in SVG, is a "People Connection" module which shows a graph of how various people are connected to each other. See Figure 1 and Figure 2 for illustrations, and see http://www.daylife.com/topic/Barack_Obama/beta#title=Connections for a demonstration.

The 150 minute course will consist of 3 parts, with questions taken throughout:

  • Introduction to Raphael (35 min)
    • 5 minutes: Introduction and Overview of the People Connection widget
    • 10 minutes: Looking at the Raphael JS Library's methods and documentation
    • 10 minutes: Setting up data for the module to be used in drawing
    • 10 minutes: Loading data into Raphael
  • Drawing the widget (45 min)
    • 10 minutes: Images
    • 15 minutes: Shapes
    • 20 minutes: Lines, straight and curved (quadratic and bicubic)
  • Interaction model (60 min)
    • 20 minutes: Handling user/triggered events
    • 15 minutes: Animation
    • 25 minutes: Interacting with the DOM and jQuery

There is a time buffer built into each part, and if there is extra time, I will be prepared to discuss:

  • Raphael versus other SVG/Javascript libraries
  • Other projects built on Raphael
  • Browser compatibility with Raphael

For each section of the course, I plan to discuss:

  • Implementation and coding conventions
  • Potential pitfalls with certain techniques (browser incompatibilities, misconceptions, and common mistakes)
  • Building the widget by coding in real-time (and not using blobs of code already written).

The flow of this walk-through course will be aligned with the building of the People Connection widget, where I will start with a empty file and progress over each step used in creating the overall effect and feel of the finished widget. Each piece of the widget puzzle will be complemented with a demonstration of the incremental improvement. At the end of the course, a complete widget, with all of its pieces, will be fully functional and fully explained.