Cake Bunny website now using twitter bootstrap!

Today, I spent couple hours to update my Cake Bunny 1.0 and Cake Bunny 2.0 websites. Cake Bunny is CakePHP website that I built to provide live demo for CakePHP tutorials in mt blog. At the moment, it has only two sample demos ( jQuery UI AutoComplete and jQuery UI AutoComplete Redirect).

I decided to make over the design using Twitter Bootstrap instead of CakePHP default template. For you guys that haven’t try twitter bootstrap yet, I suggest you give it a try. It has a lot of components inside it and provide you with basic layout ( pretty much similar with other CSS frameworks such as blueprint, 960, etc ).

And another great feature of twitter bootstrap is that you can build mobile friendly website by using what it called responsive design. Basically, it using Javascript to detect the browser that user using and will change certain elements to follow the user browser.

Click here to find out more about Twitter Bootstrap!

Rails set up namespace and redirect from namespace

In order to differentiate between admin actions and users actions, you can set up what called “namespace” in your rails apps. The basic idea of this feature is you will have different controller and view files for each role in your application.

This concept is similar with prefixes in CakePHP. However,  CakePHP allows you to put different action in one controller file, while in rails you have to create different controller and view file for the new namespace. Here is the sample namespace code that I put in my routes.rb file :

  namespace :admin do
    resources :users
    resources :products
    resources :categories
  end

The code means that users, products and categories will have admin namespace. The next step is to create new folder in your controller and view folder called “admin”. Here is the screenshot ( see the directory browser on the left hand side ) :

Put the template and controller files inside these folders. You have to add Admin:: in front of the class definition of your controller file. So it’s gonna be like this :

class Admin::UsersController < ApplicationController

After you set up everything done, you can try to access your apps through http://your-url/admin/controller-path ( ex: http://localhost:3000/admin/users ). It should automatically pick the controller and view files from admin folder. And if you want to redirect to the original route, you have to add ‘/’ in front of the controller name. Here is the code :

redirect_to :controller => "/sessions",:action => "new"

It means you will redirect the user to session controller outside of the namespace and load “new” action. That’s all.

Execute JWPlayer shortcode in WordPress custom template

JWPlayer has become my favorite video player for clients website especially after they release their official WordPress plugin. The plugin almost done all the basic things ( shortcode, custom player, etc ). It’s also integrated seamlessly with the WordPress Media library which makes your life so much easier because you can easily add the player to a post straightly from media library. However, aside from all that simple integration and setup, it lacks of documentation could cause a headache especially if you are trying to do something out of the lane.

Today, I was trying to use JWPlayer plugin to show video in a custom post type template which grab the video file from external URL ( not from Media Library ). I was thinking this would be an easy task because I could easily execute the shortcode using do_shortcode() function in WordPress. But, apparently JWPlayer plugin handle the shortcode quite different from another plugin so you have to use jwplayer_tag_callback() function instead of do_shortcode(). I don’t know the reason why they make it like that but as long as it works then it’s fine. Here is the sample code to make it clear:

//won't work
do_shortcode("[jwplayer link='http://xxx.com/xxx.mp4']");
 
//obviously will work
jwplayer_tag_callback("[jwplayer link='http://xxx.com/xxx.mp4']");

Auto redirect in CakePHP jQuery AutoComplete

Demo : http://cbunny.rudylee.com/autocomplete_redirect

Demo source code : https://github.com/rudylee/cbunny

In my previous post ( http://blog.rudylee.com/2011/07/25/jquery-ui-autocomplete-in-cakephp/ ) we have successfully integrated the jQuery AutoComplete with CakePHP with a little bit hacky way. Now we gonna add another feature that can redirect user to our desired place when they click the result value in the AutoComplete ( try the demo for more details ).

So let’s start the coding ( I assume you have integrated the jQuery UI AutoComplete in your apps, if you haven’t, just read my previous post ), so basically what we need to do are divided into 4 steps:

  • Wrap the jQuery UI AutoComplete search field in a form tag.
  • Add a hidden field which will hold the ID of the result.
  • Add ‘select’ option into the helper.
  • Set up the action that will handle the form submit

Here is the sample code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
    echo $this->Form->create('autoComplete',array('url' => array('controller' => 'users', 'action' => 'autoComplete'),'id' => 'GuestForm'));
    echo $this->Form->hidden('Guest.id');
    echo $this->Ajax->autoComplete('Guest.search', array(
	'source' => array(
	    'controller' => 'users',
	    'action' => 'autoComplete',
	    'prefix' => 'admin'
	),
	'select' => 'function(event, ui){
	    $("#GuestId").val(ui.item.id);
	    $("#GuestForm").submit()}'
    ));
    ?>
    </form>

As you can see in line 1, I defined the form and the controller + action that will handle the form submit. Line 2 is the hidden field that will hold the ID of the result. Line 3 is the AutoComplete form, I have added select option into the helper which will run the function defined to it each time user click the result. Line 10 means that the hidden field ( field that has ID GuestID ) will have value based on the AutoComplete Item ID ( which came from ui.item.id) and Line 11 will submit the form.

Here is the sample of the action code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    function admin_autoComplete() {
	if (!empty($this->data)) {
	    $this->redirect(array(
		'controller' => 'users',
		'action' => 'view', $this->data['Guest']['id']
	    ));
	}
	$this->autoRender = false;
	$guests = $this->User->getGuests(array(
	    'conditions' => array(
		'OR' => array(
		    'User.name LIKE' => '%' . $_GET['term'] . '%',
		    'User.surname LIKE' => '%' . $_GET['term'] . '%'
		)
	    )
		));
	echo json_encode($this->User->autoComplete_encode($guests));
    }

Just ignore line 8 and so, we gonna focus on line 2 to 7. In that line, I redirect the user to the view action which based on the Guest ID which I got from the form. You can change the controller/action in this section. I hope everything is clear. Cheers.

Holiday has arrived

Today is the last day of my exams and I will have holiday for 3 months. It’s quite long considering that you spent the same amount of time for study as well. That means in one semester you will have 3 months study and another 3 months for holiday. From my perspective, it’s not efficient, wasting time and of course wasting money :D . But who am I to judge the system, the system is there for a reason which I don’t care much.

So what is my plan for holiday ? not sure, I was planning to go back to Indonesia but looks like I am gonna trapped here with a bunch of works to do. I wish I can surprise my girlfriend by I suddenly appear at her rented room and let her hug me tightly like in the movies but looks like that impossible to happen at the moment. I hope she can understand ( I know she can’t :( ).

By the way, I have a number of tasks that need to be done during this break. First thing is to renew my passport which will be expired in January 2012. Without this passport, I can’t go back to Indonesia because you need to have passport that expired more than 6 months if you are planning to go overseas. That’s what I have been told, not sure whether it’s true or not. It cost around 40$ to get a new passport, not too expensive considering the living cost in here is far different from Indonesia ( 40$ is just like 200k in Indonesian rupiah ).

The second thing is to find new place to stay that closer to my university. My current place is not bad at all considering I have lived there for almost 1 year, quite comfortable with the people that live there and it’s just around 20-30 minutes walk from my university. But, I think it’s better if I can find a place that nearer to my university and of course cheaper :D

The third one and the final one is to complete pending projects that have been waiting for months. Most of them are fun projects which I created to learn new technology. Fascinating, but the reality is not easy as it looks especially because I am well-known for being undisciplined and unmotivated person.

That’s all my story for this month, still need to write a blog post for last month :D

Picture is taken from http://www.flickr.com/photos/8810648@N03/3048143981/

Short conversation with my mom

Sepenggal perbincangan di telepon dengan nyokap…

Gwa: Jadi kapan koko ted bakal married ? ( koko ted adalah panggilan gwa buat koko gwa :P )

Nyokap: Belom tau, rumah aja blom selesai dibangun.

Gwa: Oh gitu…

Nyokap: Jadi setelah si Teddy married, giliran lu lagi la ?

Gwa: Enggak donk… kan beda umur gwa ama koko 5 tahun… jadi gwa married masih 5 tahun lagi…

Nyokap: Emang orang tuanya Riani bolehin ? bukannya biasanya orang tua suka ketar ketir kalo belum jelas kek begini. Kalau gwa jadi orang tuanya pun khawatir.

Gwa: …

PS : kata2 sedikit diubah agar mudah dimengerti

Reasons why I hate long weekend

Too much sleep

Less productive

Tasks waiting after holiday

and

Far away from your girlfriend

Gource

Gource is a software version control visualization tool. It was built using C/C++ ( not sure ). Several version controls that supported by Gource are Git, SVN, Mercurial and Bazaar.

Basically Gource is a command line tool that you can use to visualize your project’s progress that using software version control. Here is the example of my project :

Cool isn’t it ? In my video, there is only one person because I am working for this project alone. However, if you are looking in YouTube, you can find a lot of big projects that using Gource to visualize their progress. One of the project that you should see is the Linux Kernel project.

Here is the link to the Gource Website

jQuery UI AutoComplete in CakePHP

Demo : http://cbunny.rudylee.com/autocomplete

Demo source code : https://github.com/rudylee/cbunny
The post to add auto redirect feature into the AutoComplete : http://blog.rudylee.com/2011/12/12/auto-redirect-in-cakephp-jquery-autocomplete/
You can copy the modified Ajax and Javascript helpers from here https://github.com/rudylee/topping

Last week I was trying to use jQuery UI Autocomplete in my CakePHP apps. However, CakePHP Ajax and Javascript helpers don’t support jQuery by default. After googling a little bit, I found that this guy ( http://www.cakephp.bee.pl/ ) already made Ajax and Javascript helpers for jQuery.

So I just copied these helpers from his site and put it into my apps. It’s done ? obviously not. It turned out that the autocomplete script that he using in his helper is the old one ( http://docs.jquery.com/Plugins/autocomplete ).

Thus, I had to add a method inside that helper to use jQuery UI autocomplete. Here are the sample codes ( you can copy from my github for the complete file, this one is just snippet ) :

 /**
     * Options for auto-complete editor.
     *
     * @var array
     */
    var $autoCompleteOptions = array(
	'select', 'source'
    );
 
    /**
     * Create a text field with Jquery UI Autocomplete.
     *
     * Creates an autocomplete field with the given ID and options.
     * needs include jQuery UI Autocomplete file
     *
     * @param string $field DOM ID of field to observe
     * @param array $options Ajax options
     * @return string Ajax script
     * check out http://jqueryui.com/demos/autocomplete/
     */
    function autoComplete($field, $options = array()) {
	$var = '';
	if (isset($options['var'])) {
	    $var = 'var ' . $options['var'] . ' = ';
	    unset($options['var']);
	}
 
	if(isset($options['source'])) {
	    $options['source'] = "'".Router::url($options['source'])."'";
	}
 
	if (!isset($options['id'])) {
	    $options['id'] = Inflector::camelize(str_replace(".", "_", $field));
	}
 
	$htmlOptions = $this->__getHtmlOptions($options);
	$htmlOptions['autocomplete'] = "off";
 
	foreach ($this->autoCompleteOptions as $opt) {
	    unset($htmlOptions[$opt]);
	}
 
	$options = $this->_optionsToString($options, array('multipleSeparator'));
	$callbacks = array('formatItem', 'formatMatch', 'formatResult', 'highlight');
 
	foreach ($callbacks as $callback) {
	    if (isset($options[$callback])) {
		$name = $callback;
		$code = $options[$callback];
		switch ($name) {
		    case 'formatResult':
			$options[$name] = "function(data, i, max) {" . $code . "}";
			break;
		    case 'highlight':
			$options[$name] = "function(data, search) {" . $code . "}";
			break;
		    default:
			$options[$name] = "function(row, i, max, term) {" . $code . "}";
			break;
		}
	    }
	}
	$options = $this->_buildOptions($options, $this->autoCompleteOptions);
 
	$text = $this->Form->text($field, $htmlOptions);
	$script = "{$var} $('#{$htmlOptions['id']}').autocomplete(";
	$script .= "{$options});";
 
	return "{$text}\n" . $this->Javascript->codeBlock($script);
    }

And here are the sample to use it in our application

echo $this->Ajax->autoComplete('Guest.search', array(
    'source' => array(
	'controller' => 'users',
	'action' => 'autoComplete',
	'prefix' => 'host'
    ),
));

Action code :

 /**
     * Auto Complete Action for Host
     *
     * Auto Complete action for host list of guests
     * also process the search
     */
    function host_autoComplete() {
	if (!empty($this->data)) {
	    $this->redirect(array(
		'controller' => 'users',
		'action' => 'view', $this->data['Guest']['id']
	    ));
	}
	$this->autoRender = false;
	$guests = $this->User->getGuests(array(
		    'host_id' => Configure::read('User.id'),
		    'conditions' => array(
			'OR' => array(
			    'User.name LIKE' => '%' . $_GET['term'] . '%',
			    'User.surname LIKE' => '%' . $_GET['term'] . '%'
			)
		    )
		));
	echo json_encode($this->User->autoComplete_encode($guests));
    }

Model method ( encode the data array to display fields that we want, in this example I am just showing firstname and surname )

  /**
     * autoComplete encode
     *
     * Parsing passed array and change it to consume-able
     * by autocomplete jQuery UI
     * @param array $data
     * @return json $data
     */
    function autoComplete_encode($postData = array()) {
	$temp = array();
	foreach ($postData as $user) {
	    array_push($temp, array(
		'id' => $user['User']['id'],
		'label' => $user['User']['name'].' '.$user['User']['surname'],
		'value' => $user['User']['name'],
	    ));
	}
	return $temp;
    }

Don’t forget to use $_GET['term'] to get data from autocomplete field and also encode the data to JSON so it can be displayed by jQuery UI.

Change wordpress default email and name

Actually you can find this solution easily in Google. However, I’ll put it in my blog just because I am lazy to find it again.

So wordpress has default email address and name which are “WordPress” as the name, wordpress@yourdomain.com as the email. To change it you can use plugin or put these wordpress action to your functions.php file in themes folder :

add_filter('wp_mail_from', 'new_mail_from');
add_filter('wp_mail_from_name', 'new_mail_from_name');
 
function new_mail_from($old) {
 return 'no-reply@rudylee.com';
}
 
function new_mail_from_name($old) {
 return 'Rudy';
}

Just change the email address and name to your’s. Hope it works, cheers.