A Simple State Manager for History Keeper

Someone asked how to store a key value pair in HistoryKeeper recently, and this was my answer.

History Keeper does not provide any state management features beyond the information you store on the actual deep link (URL hash). However, you should be able to use the deep link information to grab the data you need out of a standard JS object (using it like a hash table):

var storage = {
    "/": {
        key: "home value"
    },
    "/about": {
        key: "about value"
    }
};

Once you have your values stored like that you can use the storage object to lookup your chunk of data by the deep link string:

function onHistoryChange(hash) {
    alert(storage[hash].key);
}
unFocus.History.addEventListener('historyChange', onHistoryChange);

You can make the “value” as deep as you want ( key: {more: “complex”} ), I only used a simple string for demonstration purposes.

This example is JavaScript, but the concepts are the same for Actionscript as well.

I hope that helps!

Frash shows Flash on iPhone can be Great (with Screenshots)

Warning: RANT ahead

Steve Jobs is full of crap. I could actually understand and respect a straightforward admission that the Flash Platform is a threat to Apple’s iOS business model – which is the real reason Jobs won’t let Flash on the iPhone and iPad. That’s not even a very good reason – the App Store has many compelling features on it’s own, even if Flash is in the browser, not the least of which is the easy to understand path to monitization. Performance is another issue – Flash is fast enough, faster than JS/Canvas by quite a bit, but it’s still not as fast as a native app and all it’s OpenGL goodness (among all the other great Apple APIs). Keeping Flash off iPhone (and especially CS5 iPhone apps) has nothing to do with performance, or compatibility. That’s just bunk! And nobody likes a liar.

/rant

Here are some screenshots to show how well many sites I’ve been involved with work in Flash on the iPhone (3GS using jailbreak and Frash).

A quit note on the technology: this is using Frash, which is a hack (a wrapper or compatibility layer) to get the Android version of Flash Player 10.1 running inside of iOS – it has not been optimized (or even completed at this point) to run well on iOS yet, and probably will never run as well as it can on Android. A recent test app I’ve been playing with runs 50% faster on a Droid Eris, vs. the iPhone 3GS – the Eris is slower hardware, running Android 2.1. It’s also crashy, and is missing features like streaming movie support (it does work with videos embedded in a swf) – and touch events are not quite as streamlined as they are on a real Android device (hover works better on Android for example, and hot spots are easier to hit). It’s also got all the quirks of the Wii and desktop Flash Player’s “noscale” feature (on Android there is a workaround that solves this, not implemented in Frash yet).

I just like to point that out, because some users are judging the viability of Flash on iOS/iPhone/iPad based on this hack (which is current at version 0.02), which is beyond silly.

For anyone interested, I followed these instructions to install it on my iPhone. Note: this uses SSH and dpkg to install. If you don’t know how to reverse that, you may want to find an apt repo and use Cydia to grab this, so you can uninstall Frash when you are done playing, as it can be quite unstable.

Including Page Templates from a WordPress Plugin

Recently, It occurred to me while writing a plugin dealing with custom post types and taxonomies for WordPress that it’d be nice to have some custom templates to go along with it. I seemed onerous to ask the the user to add template tags to their theme to be able to display a better page then what WordPress displays by default. So I set out to make the plugin include the┬átemplate pages from the plugin directory itself. The code below is derived directly from the WordPress source code, which means it’s GPL, so feel free to use it in your GPL licensed projects.

So the first thing I needed to figured out was what functions needed to be filtered to let me add the plugin directory to the locations that WordPress checks for. I eventually found the appropriate ones by reading the source code and asking in the #wordpress IRC chat (not #wordpress-dev, that’d be the wrong chat to ask this kind of question). “get_single_template()” and “get_taxonomy_template()” are the functions of interest and they in turn call “locate_template()” which is the function we need to rewrite.

function locate_plugin_template($template_names, $load = false, $require_once = true )
{
    if ( !is_array($template_names) )
        return '';
   
    $located = '';
   
    $this_plugin_dir = WP_PLUGIN_DIR.'/'.str_replace( basename( __FILE__), "", plugin_basename(__FILE__) );
   
    foreach ( $template_names as $template_name ) {
        if ( !$template_name )
            continue;
        if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
            $located = STYLESHEETPATH . '/' . $template_name;
            break;
        } else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
            $located = TEMPLATEPATH . '/' . $template_name;
            break;
        } else if ( file_exists( $this_plugin_dir .  $template_name) ) {
            $located =  $this_plugin_dir . $template_name;
            break;
        }
    }
   
    if ( $load && '' != $located )
        load_template( $located, $require_once );
   
    return $located;
}

(reference: ‘function locate_template‘)

The “locate_plugin_template()” function is a direct copy of “locate_template” function but I added the $this_plugin_dir variable (using code I found on the wordpress.org forums) and added a 3rd check to the foreach loop. (Some of the code here can be removed, for example the $load check with the load_template() call, as our code won’t be invoking it but I left it to better reflect the source.)

Next we have to filter the appropriate functions to call our new function.

add_filter( 'taxonomy_template', 'get_custom_taxonomy_template' );
add_filter( 'single_template', 'get_custom_single_template' );

There’s not much in the original functions that need to be changed:

function get_custom_taxonomy_template($template)
{
    // Twenty Ten adds a 'pretty' link at the end of the excerpt. We don't need it for the taxonomy.
        remove_filter( 'get_the_excerpt', 'twentyten_custom_excerpt_more' );
    remove_filter( 'get_the_excerpt', 'twentyten_auto_excerpt_more' );
   
    $taxonomy = get_query_var('taxonomy');
   
    if ( 'custom_taxonomy_name' == $taxonomy ) {
        $term = get_query_var('term');
   
        $templates = array();
        if ( $taxonomy && $term )
                $templates[] = "taxonomy-$taxonomy-$term.php";
        if ( $taxonomy )
                $templates[] = "taxonomy-$taxonomy.php";
   
        $templates[] = "taxonomy.php";
        $template = locate_plugin_template($templates);
    }
    // return apply_filters('taxonomy_template', $template);
    return $template;
}

(reference ‘function get_taxonomy_template‘)

There’s some bonus remove_filter calls at the beginning and ‘locate_template’ is replace by ‘locate_plugin_template’. The only other thing is that we simply return the $template variable instead of using ‘apply_filters’ (I got errors when trying to apply the filter while running the filter filtering the filter :-/). There is also a check to see if we are working with our own taxonomy: The code in the if statement doesn’t really need to run again unless it’s one of our taxonomies, else it’ll just return the original $template.

The single template function filter is much the same:

function get_custom_single_template($template)
{
    global $wp_query;
    $object = $wp_query->get_queried_object();
   
    if ( 'custom_post_type_name' == $object->post_type ) {
        $templates = array('single-' . $object->post_type . '.php', 'single.php');
        $template = locate_plugin_template($templates);
    }
    // return apply_filters('single_template', $template);
    return $template;
}

(reference ‘function get_single_template‘)

Now, this isn’t a perfect solution. For example, themes have much varying structures, so building a template that’s compatible with Twenty Ten wouldn’t necessarily be compatible with any other theme. If the theme isn’t compatible, it could be bad since you’ve interrupted the fallback that the theme provides in favor of yours. You should probably include a check to see if the current theme is the theme you are targeting. I suggest you use this code in a plugin that is basically a companion plugin for your own theme or framework. Additionally, you could offer template tag functions, shortcodes, and widgets as a more robust solution.