T1E is hiring

studio

Typeoneerror is growing and I am looking for a select group of creative individuals who will form our core product-development team over the next year and assist with various client projects on a daily basis. I am searching for unique talents with experience in the development and design of interactive applications and games on multiple platforms.

I typically work with small teams of independent contractors on our projects, but reached a point where having people in the office makes sense. That's where you come in, I hope!


Roles

At this time, I am looking to hire a developer in the junior- to mid-level range, as well as a (paid) intern. Candidates should have front-end development experience as well as some experience with programming languages.


Requirements

  • HTML(5)
  • CSS(3)
  • Javascript(jQuery, OK)
  • Ability to translate PSD and FW templates to clean, responsive code
  • Experience with front-end PHP or Ruby development

A solid foundation in the basic web development technologies listed above are required for this position, and experience with PHP would be fantastic, but here's a list of some of the technologies I am currently working on that, if you had experience with, would certainly tip the scales in your favor:


Niceties

  • SmartyPHP
  • Understanding of version control (subversion, git)
  • Wordpress
  • Flash/Flex/AIR APIs
  • LAMP development
  • Rails/Ruby development
  • Experience with OOP & MVC frameworks (Zend, Rails, Django, CakePHP)
  • Objective-C (iOS apps)
  • Java (Android apps)
  • Facebook apps
  • Database design
  • Information architecture
  • Game Development (iOS, Android, XNA)
  • Familiarity with *nix, Apache
  • Front-end asset pipelines (sass, less, compass, haml)

Also required are positive attitudes and strong opinions about the web.


How to Apply

Candidates should feel free to submit a cover letter and resume (or relevant URL) with applicable work samples and salary requirements to hello@typeoneerror.com. Click the mailto links below to start:

Junior Developer
Intern

Thanks for reading, and feel free to tweet about this if you'd like to help me out.


About Typeoneerror

Located in the Ballard neighborhood of Seattle, Typeoneerror is an interactive design boutique led by artist and programmer Benjamin Borowski; committed to creating fine interactive applications via direct and collaborative engagements. Providing strategic design and development for websites, games, and mobile devices, our core expertise melds hand-crafted code with beautiful, user-centric design & strategy.

November 22nd, 2011 | Permalink

Reducing CSS/Javascript Requests and File Size with Ant and YUI

With continuing reliance on front-end Javascript plugins and CSS, it's important to keep HTTP requests and file sizes smaller to reduce page load times. On this site, we use jQuery, jQuery Address, a custom application Javascript include, and other plugins. We also use a master CSS file as well as a reset file and other CSS additions for things like @media queries and the like. We can reduce all these file requests to one or two requests by combining them all into one file and minifying them.

We can use a compression tool such as YUI Compressor to handle the minifying, but actually doing the work to compile all those files together and run them through the compressor can be a time-consuming task to perform manually. It'd be great if we had a tool to do that for us. Enter Apache Ant.

Ant is a java-based build automation tool. It can be used to perform a variety of tasks and is ideally suited for building files for web applications. If you're on Mac OS X, Ant comes pre-installed (1.7.x on 10.5 and 1.8.x on 10.6). For other systems, check out the easy instructions here. YUI is a simple download and extraction from here.

All we need for a basic Ant task is a build file. Create a "build.xml" file in the root of your application. To start, you just need some basic markup. I added a property that contains the path to the YUI Compressor .jar file.

<?xml version="1.0" encoding="UTF-8"?>

<!-- project name, default target and base directory -->
<project name="typeoneerror" default="init" basedir=".">

    <!-- path to YUI Compressor -->
    <property name="yuic" location="/Users/typeoneerror/bin/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar"/>

    <!-- path to build resources -->
    <property name="css" location="public/css"/>
    <property name="js" location="public/js"/>
    <property name="ui_css" location="public/ui/css"/>
    <property name="ui_js" location="public/ui/js"/>

    <!-- default target -->
    <target name="init"/>
</project>

This defines our project build with a default target (one of the actions that will run when we build) called "init". Also, we've defined some properties (paths to YUI and to our CSS and Javascript folder) that we'll use later.

Next, create the first target:

<!--concatenate javascript-->
<target name="concat.js" description="Stick all the JS together">
     <concat destfile="build/application.js">
        <!-- first concat all the files in the /ui/js directory -->
        <filelist dir="${ui_js}" files="jquery.min.js,jquery.address.min.js"/>
        <!-- then add our application js file -->
        <filelist dir="${js}" files="application.js"/>
    </concat>
</target>

This target uses the concat process to concatenate a list of javascript files into a destfile (destination file) build/application.js. This combines everything we're using into one file. The next target will use that file and minify it:

<!--minify javascript-->
<target name="minify.js" depends="concat.js" description="Minify JavaScript using YUI Compressor">
    <apply executable="java" parallel="false">
        <!-- look for any javascript files in the build dir -->
        <fileset dir="build" includes="*.js"/>
        <!-- pass arguments to the yui program -->
        <arg line="-jar"/>
        <arg path="${yuic}"/>
        <srcfile/>
        <!-- output minified files to our js dir with .min.js extenstion -->
        <arg line="-o"/>
        <mapper type="glob" from="*.js" to="${js}/*.min.js"/>
        <targetfile/>
    </apply>
</target>

The depends property defines actions that need to be performed before running the target. Add the minify.js target to the depends property of our default action:

<target name="init" depends="minify.js"/>

When we run the build, init will be run and then minify.js. Of course, concat.js will be run before minify.js since minify.js depends on it.

We add another two targets to concat and minify our CSS. Add another target to the list of targets in the init target. Our final build file looks something like this:

<?xml version="1.0" encoding="UTF-8"?>

<!-- project name, default target and base directory -->
<project name="typeoneerror" default="init" basedir=".">

    <!-- path to YUI Compressor -->
    <property name="yuic" location="/Users/typeoneerror/bin/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar"/>

    <!-- path to build resources -->
    <property name="css" location="public/css"/>
    <property name="js" location="public/js"/>
    <property name="ui_css" location="public/ui/css"/>
    <property name="ui_js" location="public/ui/js"/>

    <!-- default target -->
    <target name="init" depends="minify.js,minify.css"/>

    <!--concatenate javascript-->
    <target name="concat.js" description="Stick all the JS together">
         <concat destfile="build/application.js">
            <!-- first concat all the files in the /ui/js directory -->
            <filelist dir="${ui_js}" files="jquery.min.js,jquery.address.min.js"/>
            <!-- then add our application js file -->
            <filelist dir="${js}" files="application.js"/>
        </concat>
    </target>

    <!--minify javascript-->
    <target name="minify.js" depends="concat.js" description="Minify JavaScript using YUI Compressor">
        <apply executable="java" parallel="false">
            <!-- look for any javascript files in the build dir -->
            <fileset dir="build" includes="*.js"/>
            <!-- pass arguments to the yui program -->
            <arg line="-jar"/>
            <arg path="${yuic}"/>
            <srcfile/>
            <!-- output minified files to our js dir with .min.js extenstion -->
            <arg line="-o"/>
            <mapper type="glob" from="*.js" to="${js}/*.min.js"/>
            <targetfile/>
        </apply>
    </target>

    <!--concatenate css-->
    <target name="concat.css" description="Stick all the CSS together">
         <concat destfile="build/core.css">
            <filelist dir="${ui_css}" files="reset.min.css"/>
            <filelist dir="${css}" files="screen.css,additions.css"/>
        </concat>
    </target>

    <!--minify concatenated css-->
    <target name="minify.css" depends="concat.css" description="Minify CSS using YUI Compressor">
        <apply executable="java" parallel="false">
            <fileset dir="build" includes="*.css"/>
            <arg line="-jar"/>
            <arg path="${yuic}"/>
            <srcfile/>
            <arg line="-o"/>
            <mapper type="glob" from="*.css" to="${css}/*.min.css"/>
            <targetfile/>
        </apply>
    </target>
</project>

Running an Ant build file is as simple as shelling into the directory via your Terminal or command line interface and entering ant. It automatically looks for a file called "build.xml". You can also grab Simon Gregory's Ant TextMate Bundle if you want to just hit Cmd+R to build in your TextMate project (awesome).

December 20th, 2010 | Permalink

HTML5 & CSS3: Graceful Degradation

Webkit animations and transitions are a nifty way to add sexy effects and animations to browsers that use the webkit engine. As the list of browsers that implement these becomes longer (Safari, Chrome, Mobile Safari, Blackberry 6.0, Android, webOS, et al)—especially in the mobile space—the more you can rationalize using some of these features in production. The key words for things like this are "graceful degradation" i.e., use it, but provide a fallback solution for other browsers that will still engage the user. The idea is for the user to not think that something is missing or broken—they are still provided an engaging experience.

An example of this we created recently is a mobile-optimized HTML5 site for First Bank. At the moment it's a place to download free books in PDF form. We'll be adding more activities soon ;) On the books page, though, we use @webkit-keyframes to create a 3D transition effect when changing pages and a Mac-style "bouncing icon in the dock" effect when a book is clicked (try it in Chrome or Safari). In other browsers (Firefox, IE, etc), Javascript is used to create a simple tween animation to show the next page of books. So we give "fancy-ass" browsers some cool effects, but still give the average crowd a nice animation as well.

Here's how we created the Mac icon dock bounce. First, you define a series of keyframes that will define our animation. This is just in your CSS file—I know it looks kind of crazy when you're thinking CSS:

@-webkit-keyframes book-active {
    from {top:0px;}
    to {top:-10px;}
}

Pretty simply, we've defined an "animation name" called book-active. This animation would move whatever element it is applied to from 0 to -10. To run the animation, create a class with a similar name (I find it helps organize) and add the animation-name to it:

.book-active {
     -webkit-animation-name:book-active;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

You can see above we gave it an "animation-name" of "book-active". The animation will take 0.2 seconds to complete and it'll repeat the animation 10 times. The animation-direction parameter tells it to reverse the animation for each interaction. Hence, we bounce.

To apply the animation, you simply add the class to the element:

<article class="book-active"></article>

On the First Bank micro-site, we applied two separate bounce animations to the books. One to bounce the book element, and one to scale the shadow underneath the book on the same bounce to give it some depth. Here's the whole CSS section for the book bounce, shadow, and the 3D transform during the page change animation:

@-webkit-keyframes book-active {
    from {top:0px;}
    to {top:-10px;}
}

@-webkit-keyframes shadow-bounce {
    from {-webkit-transform:scale(1.0);}
    to {-webkit-transform:scale(1.05);}
}

@-webkit-keyframes book-transition {
    from {
        -webkit-transform:scale(1.0);
        -webkit-animation-timing-function:ease-out;
    }
    20% {
        -webkit-transform:scale(0.9);
        webkit-animation-timing-function:ease-in;
    }
    to {
        -webkit-transform:scale(1.0);
        -webkit-animation-timing-function:ease-out;
    }
}

.book-active {
     -webkit-animation-name:book-active;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

.book-transition {
    -webkit-animation-name:book-transition;
    -webkit-animation-duration:1s;
    -webkit-animation-iteration-count:1;
}

.shadow-bounce {
     -webkit-animation-name:shadow-bounce;
     -webkit-animation-duration:0.2s;
     -webkit-animation-iteration-count:10;
     -webkit-animation-direction:alternate;
}

One caveat for animation with webkit, is that repeating animations is tricky. Once the class has been added, you need to remove the animation-name from the element to restart the animation. We created this simple jQuery element function to help:

$.fn.startWebkitAnimation = function(name)
{
    var element = $(this);
    if (!element.hasClass(name))
    {
        element.addClass(name);
    }
    else
    {
        element.css("-webkit-animation-name", "none");
        setTimeout(function() {
            element.css("-webkit-animation-name", name);
        }, 0);
    }
    return $(this);
}

So to start an animation, simply call $("selector").startWebkitAnimation("animation-name"). The CSS class and the keyframes should have the same name. What this does is clear the animation-name property and then reset it. This is based on Apple's own recommendation for resetting animations.

On First Bank Free, we use Modernizr to check if CSS Animations are available. If they are, we start the bouncing animation when the book is clicked and delay the transition to the link. Otherwise, we go right to the link (graceful degradation!):

$("#book-list li a").click(function(event)
{
    if ($(this).data("was-clicked") != undefined)
    {
        // prevent multiple clicks
        event.preventDefault();
        return;
    }
    if (Modernizr.cssanimations)
    {
        event.preventDefault();
        // prevent multiple clicks
        $(this).data("was-clicked", 1);
        // start the book bouncing
        $(this).startWebkitAnimation("book-active");
        // start the shadow bouncing
        $(this).parent().find(".book-shadow").startWebkitAnimation("shadow-bounce");
        // delay the page direction for a tick
        setTimeout('window.location = "' + $(this).attr("href") + '"', 1000);
    }
});

So, you can see how HART (HTML5 and Related Technologies) can be used right now with a little extra effort. The keys are fallbacks and degradation. Also—and I find this to be critical—definitely let your clients know up front what to expect for different browser vendors. This might be defined in functional specification or proposal before development begins.

October 2nd, 2010 | Permalink