Create Simple WordPress Mobile Theme Using Sencha Touch – Part 1

September 24th, 2011 by aditia rahman / 4 Comments  

     

Today post I want to share a simple mobile wordpress theme using sencha touch, I will separate the post in 2 part, and all the source code I share on the part 2, I created this post because I think this is one of the good way to learn more both about wordpress function and sencha touch. This image below are the mockup theme.

sencha touch wordpress

The wordpress theme in this post are really simple, maybe you can develop further, I only create these features: index page with pagination, single post page, comment list page, and submit comment. For sencha touch the application structure not really different from my previous post about sencha touch gallery, it MVC structure that generated using sencha command.

Setting Up Themes

The theme file structure is based on generated sencha touch command, remember to add index.php and style.css file in the theme directory, and use the wordpress theme url to include the css or javascript file, something like this

<script type="text/javascript" src="<?php bloginfo("template_url"); ?>/lib/touch/sencha-touch.js"></script>

And make sure to load other sencha touch file like style, controller, models, views. For communicating to server we will using ajax for all pages so I make the blog url for fetching ajax response stored in javascript variable, all of these script are on the index.php file

<script type="text/javascript">
    var INDEX_URL       = '<?php bloginfo("url"); ?>/?index';
    var MAXPAGE_URL     = '<?php bloginfo("url"); ?>/?maxpage';
    var SINGLE_URL      = '<?php bloginfo("url"); ?>/?single';
    var COMMENT_URL     = '<?php bloginfo("url"); ?>/?comment';
    var ICOMMENT_URL    = '<?php bloginfo("url"); ?>/?insertcomment';
    var THEME_URL       = '<?php bloginfo("template_url"); ?>';

    var BLOG_TITLE      = '<?php echo get_bloginfo('name') ?>';
    var BLOG_DESC       = '<?php echo get_bloginfo('description'); ?>';

    // comment attibute
    var VISITOR_IP      = '<?php echo $_SERVER["REMOTE_ADDR"]; ?>';
    var VISITOR_AGENT   = '<?php echo $_SERVER["HTTP_USER_AGENT"] ?>';
</script>

Now create the functions.php file inside this file create script to redirect ajax response

<?php

if ( isset( $_REQUEST['index'] ) ) {
	require_once( TEMPLATEPATH . '/get-index.php' );
	die();
}

if ( isset( $_REQUEST['single'] ) ) {
	require_once( TEMPLATEPATH . '/get-single.php' );
	die();
}

if ( isset( $_REQUEST['maxpage'] ) ) {
	require_once( TEMPLATEPATH . '/get-maxpage.php' );
	die();
}

if ( isset( $_REQUEST['insertcomment'] ) ) {
	require_once( TEMPLATEPATH . '/insert-comment.php' );
	die();
}

if ( isset( $_REQUEST['comment'] ) ) {
	require_once( TEMPLATEPATH . '/get-comment.php' );
	die();
}

?>
Index Page

Model: app/models/Post.js, url model set with default javascript variable, but when the index controller called the url will change cause it need for index pagination.

Ext.regModel("Post", {
    fields: [
        {name: "id", type: "integer"},
        {name: "title", type: "string"},
        {name: "permalink", type: "string"},
        {name: "date", type: "string"},
        {name: "author_id", type: "string"},
        {name: "author", type: "string"},
        {name: "content", type: "string"},
    ],

    proxy: {
        type: 'ajax',
        url: INDEX_URL,
        reader: {
            root: 'posts',
            type: 'json'
        }
    }
});

Post List: get-index.php, in this file wordpress get_posts() function used so we can easily store the posts attribute to json format, if we using for example the_author() or the_content() function it will automatically print on the page we need to use ob_start php function.

<?php

$posts = array();

$numberposts = 5;
$offset = (intval($_GET['page']) - 1) * $numberposts;

$num_posts = wp_count_posts('post');

$num_pages = intval($num_posts->publish / $numberposts);
if ($num_posts->publish % $numberposts != 0) {
    $num_pages++;
}

if ($page <= $num_pages) {

    $args = array( 'numberposts' => $numberposts, 'offset'=> $offset );
    $myposts = get_posts( $args );

    foreach( $myposts as $post ) : setup_postdata($post);
        $posts[] = array(
            'id' => $post->ID,
            'title' => $post->post_title,
            'permalink' => $post->guid,
            'date' => str_replace("-", "/", substr($post->post_date, 0, 11)),
            'author_id' => $post->post_author,
            'author' => get_userdata($post->post_author)->display_name,
            'content' => wpautop(strstr($post->post_content, '<!--more-->', true))
        );
    endforeach;

    echo(json_encode(array('posts' => $posts)));
}

?>

Get Max Page: get-maxpage.js

<?php

$numberposts = 5;

$num_posts = wp_count_posts('post');

$max_pages = intval($num_posts->publish / $numberposts);
if ($num_posts->publish % $numberposts != 0) {
    $max_pages++;
}

echo $max_pages;

?>

Controller: app/controllers/Post.js, the prev pagination button is the simple one, just checking if the value is one then no more previous page, but for the next pagination we have to check the maximum page, that’s why the script get-maxpage.php needed.

index: function(page) {

    if (typeof(page) == 'object') {
        page = 1;
    }

    if (!this.listPanel) {
        this.listPanel = this.render({
            xtype: 'wp_touch-index',
            listeners: {
                list: {
                    select: function(list, record) {
                        this.single(record.data.id);
                    },
                    scope: this
                },
                activate : function(listPanel) {
                    listPanel.list.getSelectionModel().deselectAll();
                }
            }
        });

        this.listPanel.store.proxy.url = INDEX_URL + '&page=' + page;

        var added = false;

        this.listPanel.query('#prevButton')[0].on({
            tap: function() {
                if (added) {
                    page++;
                }
                page--;
                if (page > 0) {
                    this.listPanel.store.proxy.url = INDEX_URL + '&page=' + page;
                    this.listPanel.store.load();
                } else {
                    page++;
                }
                added = false;
            },
            scope: this
        });

        this.listPanel.query('#nextButton')[0].on({
            tap: function() {
                page++;
                this.listPanel.store.proxy.url = INDEX_URL + '&page=' + page;
                this.listPanel.store.load();
                Ext.Ajax.request({
                    url: MAXPAGE_URL,
                    method: 'POST',
                    success: function(xhr) {
                        if (page >= parseInt(xhr.responseText)) {
                            page = parseInt(xhr.responseText) - 1;
                            added = true;
                        }
                    }
                });
            },
            scope: this
        });

        wp_touch.viewport.setActiveItem(this.listPanel);
    } else {
        wp_touch.viewport.setActiveItem(this.listPanel, {
            type: 'slide',
            direction: 'right'
        });
    }
},

Views: app/views/Post/Index.js

wp_touch.views.Index = Ext.extend(Ext.Panel, {
    layout: 'fit',
    initComponent: function() {
        this.store = new Ext.data.Store({
            autoLoad: true,
            model: 'Post'
        });

        this.dockedItems = [{
            xtype: 'toolbar',
            dock: 'top',
            style: 'font-size:11px;',
            title: BLOG_TITLE + ': ' + BLOG_DESC
            }, {
                xtype: 'toolbar',
                dock: 'bottom',
                ui: 'light',
                items:[{
                    iconMask: true,
                    iconCls: 'arrow_left',
                    itemId: 'prevButton'
                }, {
                    iconMask: true,
                    itemId: 'nextButton',
                    iconCls: 'arrow_right'
                }]
        }];

        this.list = new Ext.List({
            itemTpl: '<div class="post">' +
                        '<h2>{title}</h2>' +
                        '<div class="meta">by {author} on {date}</div>' +
                        '<p>{content}</p>' +
                    '</div>',
            store: this.store
        });

        this.items = [this.list];

        wp_touch.views.Index.superclass.initComponent.apply(this, arguments);
    }
});

Ext.reg('wp_touch-index', wp_touch.views.Index);

Here are example screenshot

        submit to reddit Delicious

4 Comments Leave a Comment Subscribe RSS

  • Kartik Roa says:

    Brilliant tutorial! Thanks.

  • awesome. thanks for sharing

  • Matthijs says:

    Nice! I only got one problem. When I trie to add the_post_thumbnail in the array in the get-index.php and get-single.php files, Sencha returns a JSON error.

    When I’m not using the function and I add a value for the image manually, it works.

    Why can’t I use that particular function?

  • HNH says:

    Very nice. I integrated this theme to my wordpress plugin .. so i have a folder structure like ../wp-content/plugins/my_plugin/themes/my_theme

    So i want to use your theme for my plugin, but I got a problem with the functions.php … I CAN’T required the php files(get-index.php and so on) in the functions.php. So Sencha Touch return a JSON error.

    I have tried
    define( ‘PLUGIN_PATH’, plugin_dir_path(__FILE__) ); or
    define( ‘PLUGIN_PATH’, plugin_basename(__FILE__).’my_plugin/themes/my_theme/’ );

    but everything no works ;(
    Maybe u can help. THX!

Leave a Comment