0

Begin Migrating to the WordPress Multisite (Update 5)

This morning I moved all the files on the site to a subdirectory and replaced with a simple maintainance notification. This blog, however, I decided to stay it online to give migration status update within this post. After the migration completed, I will replace this blog with a brand new look.

Look forward to it.

Update 1: WordPress installed on the main site robbychen.com.

Update 2: Deleted all of the subdomains of the site except blog.robbychen.com for providing the migration status update temporarily.

Update 3: Finally enabled WordPress multisite feature. It took me almost 1 hour to figure out the wildcard subdomain issue. If you only have one domain in your account (which is the primary domain), you don’t have to enter anything in the directory path field when creating the wildcard subdomain. Apparently, cPanel always add the word “wildcard” to the directory field automatically. Make sure you drop this word so that the directory field is empty and press submit. It will create the subdomain without any error.

Update 4: The migration is almost finished. All I need to do is to migrate this blog into the multisite network.

Update 5: The migration finally completed. This blog is now a part of robbychen.com multisite network. I still need to convert my old main site robbychen.com to WordPress. I will keep you updated with the conversion process in a new post.

2

Creating an even Simpler Framework than MVC – Part 2

I discussed a little bit about this mini-framework in part 1. Today I rewrote the whole code for the index.php to be more configurable, and I added another folder for storing PHP pages. And yes, it includes the automatic page title generation.

It’s up to you to create other folders for the includes, images, and other files, but the PHP pages folder is a must have. Without this folder, the framework will grab the original page without process through the framework.

Let’s begin.

I need to first introduce the basic folder structure for the framework:

Note that I’ve included lessPHP inside the css folder to make writing styles easier.

The .htaccess file in the root folder is exactly the same as part 1‘s:

<IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>

However, the one in the pages folder is different:

<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteRule ^(.*)$ ../$1 [L]
</IfModule>

As those of you who understands the Apache better knows, the above code acts like access rejection. It means that whenever someone tries to access the pages folder or one of the files within it, this code will automatically rewrite the URL to the root folder. Note the difference between rewrite and redirect.

The pages folder is kinda like public or webroot folder, except it’s only used for PHP pages, not for images, stylesheets, Javascripts, or any other files.

Now the most important file, index.php. This file is placed in the root folder, and contains the most important code in the whole framework. I also added page title generation in this file as stated before.

[php]
<?php
	// Variables configuration
$rootDir = dirname(__FILE__) . "/";
$mainDir = "pages/";
$appDir = $rootDir . $mainDir;
if (isset($_GET['url'])):
	$url = $_GET['url'];
	$path = $appDir . $url . ".php";
else:
	$path = $appDir . "index.php";
endif;
if (!file_exists($path)):
	$path = $appDir . 'notfound.php';
	$title = "Page not found";
endif;

	// Set page title
	// First set the page title from the the title variable from the individual page if presented
foreach (file($path) as $content):
	if (strstr($content, "title")):
		if (strstr($content, """)):
			$quote = """;
		else:
			$quote = "'";
		endif;
		$titleVar = explode($quote, $content);
		$title = $titleVar[1];
	endif;
endforeach;
	// Process the URL as the page title if title variable is not set
if (empty($title)):
	$urlPath = explode("/", $_SERVER['REQUEST_URI']);
	$titleVar = (string)$urlPath[sizeof($urlPath)-1];
	$title = "";
	for ($i=0; $i < strlen($titleVar); ++$i):
		if ($titleVar{$i} == strtoupper($titleVar{$i})):
			$title .= " ";
		endif;
	$title .= $titleVar{$i};
	endfor;
	$title = ucfirst($title);
endif;

	// Include the neccesary pages
include_once $rootDir . 'includes/header.php';
include_once $path;
include_once $rootDir . 'includes/footer.php';
?>
[/php]

As you have noticed, I’m using URL to auto-generate the page title. You can also set the page title for each page using the $title variable.

The $mainDir variable is configurable, so you can rename the pages folder to whatever you want.

That’s it. If you don’t count the img, css, and js folder and files inside them, the files for the framework would be total of 7 files.

Here is the completed files.

If you have any issues working with this mini-framework, leave a comment below and I will happy to help you.

0

Write CSS3 with Understandable Variables with LessPHP – Part 3

LessPHP allows you to use variables in your CSS stylesheet for the repeatable blocks of code.

In part 2, I provided you with the content of var.less. This part I will give you an example on how to use this .less file to write your own stylesheet. The provided example is based on the final project of this post on the Nettuts+.

First off, here is the folder structure for this example:

Example folder structure

Folder structure for the example

From top to bottom, they are:

css - folder

less - folder

lessc.inc.php in less folder - LessPHP compiler

main.less in less folder - source file to compile to CSS stylesheet

@import 'var';

body, html {
	@dimension(100%;100%);
}

body {
	@center;
}

#box {
  @bg-color(#e3e3e3);
  @dimension(400px;200px);
  @transition(all;1s);
  border: 1px dashed #666;
  margin: auto;
  cursor: pointer;
  position: relative;
 	:after {
 		@dimension(70%;10px);
 		@box-shadow(0;9px;20px;rgba(0,0,0,.4));
	  content: '';
	  position: absolute;
	  bottom: 0;
	  left: 15%;
	  z-index: -1;
	}
	> div {
  	@bg-color(#e3e3e3);
    @dimension(100%;100%);
    @transition(all;1s;ease-in-out);
    position: absolute;
    top: 0;
    left: 0;
    font: 45px/200px bold helvetica, arial, sans-serif;
    text-align: center;
  	:first-child {
	    position: relative;
  	  z-index: 2;
    }
 }
 :hover {
 	@rotate(;rotateY(180deg));
 	> div:first-child {
  	opacity: 0;
 	}
	div:last-child {
  	@rotate(rotateY(180deg));
 	}
 }
}



var.less in less folder - contains the LessPHP variables which I already provided it to you in part 2

index.php in css folder – contains the compile script which provided in part 1

main.css in css folder – contains the compiled CSS styles

index.php in root folder – contains the inclusion of main.css in css folder

Note that some of the code are directly copied from the above source. Also, in order to completely experience this example, you need to use Chrome or webkit compatible browsers.

Feel free to ask any question you have regarding the above code in the comment below.

2

Write CSS3 with Understandable Variables with LessPHP – Part 2 (Updated)

Update: I updated the code to add more explanation on the Flexible Box Model related properties.

LessPHP provides CSS stylesheet to have variables for reducing repeatable code in order to improve productivity.

In the last part, I talked about how to installing the LessPHP and general folder structure of an one-page web app using LessPHP. This part I will provide you with var.less which includes some CSS3 properties discussed in this post on Nettuts+.

Note that all of the code used LessPHP and CSS3 syntax. If you don’t understand the LessPHP syntax yet, here is its full documentation.

@bg-color(@color:red) {
 background-color: @color;
}

@bg-size(@xWidth:100%;@yWidth:100%) {
 background-size: @xWidth @yWidth;
 -o-background-size: @xWidth @yWidth;
 -webkit-background-size: @xWidth @yWidth;
 -moz-background-size: @xWidth @yWidth;
}

@border-radius(@radius:4px) {
 border-radius: @radius;
 -webkit-border-radius: @radius;
 -moz-border-radius: @radius;
}

 // Accepts start, end, center, baseline, stretch. Default to stretch
@box-align(@align:center) {
 -moz-box-align: @align;
 -webkit-box-align: @align;
 box-align: @align;
}

 // Accepts horizontal, verticle, inherit. Default to horizontal
@box-orient(@orientation:horizontal) {
 -moz-box-orient: @orientation;
 -webkit-box-orient: @orientation;
 box-orient: @orientation;
}

 // Accepts start, end, center, justify. Default to start
@box-pack(@pack:center) {
 -moz-box-pack: @pack;
 -webkit-box-pack: @pack;
 box-pack: @pack;
}

@box-shadow(@x:1px;@y:1px;@blur:3px;@color:#292929) {
 -webkit-box-shadow: @x @y @blur @color;
 -moz-box-shadow: @x @y @blur @color;
 box-shadow: @x @y @blur @color;
}

@box-shadow-multi(@shadows:1px 1px 3px green, -1px -1px 3px blue) {
 -webkit-box-shadow: @shadows;
 -moz-box-shadow: @shadows;
 box-shadow: @shadows;
}

@center {
 display: -moz-box;
 display: -webkit-box;
 display: box;
 @box-orient;
 @box-pack;
 @box-align;
}

@columns {
 display: -moz-box;
 display: -webkit-box;
 display: box;
 @fill(@fill:1) {
 box-flex: @fill;        // Accepts either 0 to be as is or an integer to fill the entire area of parent box
 -moz-box-flex: @fill;
 -webkit-box-flex: @fill;
 }
}

 // This is the test/default styles
@defaults {
 @dimension;
 @bg-color;
 @center;
}

@dimension(@width:100px; @height:100px) {
 width: @width;
 height: @height;
}

@resize(@direction:both) {
 resize: @direction;    // Value can be both, horizontal, vertical, or none
 -moz-resize: @direction;
 -webkit-resize: @direction;
}

@rotate(@rotateX:rotateX(0deg);@rotateY:rotateY(0deg);@rotateZ:rotateZ(0deg)) {
 transform: @rotateX @rotateY @rotateZ;
 -webkit-transform: @rotateX @rotateY @rotateZ;
 -moz-transform: @rotateX @rotateY @rotateZ;
}

@text-outline(@outterColor:black;@innerColor:white) {
 text-shadow: 0 1px 0 @outterColor, 0 -1px 0 @outterColor, 1px 0 0 @outterColor, -1px 0 0 @outterColor;
 color: @innerColor
}

@text-overflow{
 .on(@type:ellipsis;@width:500px) {
 text-overflow: @type;        // text-overflow accepts two values: ellipsis, and clip which didn't seem to work in Chrome
 -o-text-overflow: @type;
 width: @width;
 overflow:hidden;
 white-space:nowrap;
 }
 .off {
 white-space: normal;
 width:100%;
 }
}

@text-shadow(@x:1px;@y:1px;@blur:3px;@color:blue) {
 text-shadow: @x @y @blur @color;
}

@text-stroke(@length:3px;@outterColor:black;@innerColor:white) {
 -webkit-text-stroke: @length @outterColor;
 color: @innerColor;
}

@transition(@property:padding;@duration:0.4s;@easing:ease-in) {
 -webkit-transition: @property @duration @easing;
 -moz-transition: @property @duration @easing;
 -o-transition: @property @duration @easing;
 transition: @property @duration @easing;
}

Some of the above code is commented to give you more information about the acceptable values. One of the code blocks, @defaults, provides you the basic layout for an element. It allows you to add other CSS properties to enhance its layout. As the comment stated, it also provides you with a test layout to test an element.

You also can use the above code as a reference to CSS3 since some people think that CSS3 is harder and more complex than CSS2

You probably noticed that there aren’t multiple background images and @font-face, that’s because I can’t figure out how to integrate them with LessPHP yet.

Do you have any problem using the above stylesheet? Leave a comment below and I will respond to you quickly.

1

Write CSS3 with Understandable Variables with LessPHP – Part 1

LessPHP is the PHP version of LessCSS, a CSS stylesheet language which is relied on Node.js web server. All LessPHP need is the PHP server.

In this part I walked you through the installation of LessPHP compiler and general folder structure for a one-page web app using LessPHP. In the next part, I will give you some CSS3 properties with parameters which have easy to understand variables.

The installation of LessPHP is easier than you think. After you download its source from github, the only step is to copy lessc.inc.php into your web app folder and included in the page. Here is the basic structure for the folder:

Folder structure for the one-page web app

Folder structure for the one-page web app

Below is the explanation for each file and folder from top to bottom:

web app is the root of the web app.

styles contains lessPHP files and compiled CSS stylesheets.

less contains lessPHP compiler and less source.

main.less relates to main.css which I discussed below. It contains the styles information that will output to main.css.

var.less contains the lessPHP variable definitions which is imported to main.less using @import.

index.php in the styles folder is used to compile the less source to CSS stylesheet. It contains the following code:

<?php
 // Convert LESS to CSS styles
 include_once 'less/lessc.inc.php';
 try { lessc::ccompile('styles/less/main.less', 'styles/main.css'); }
 catch (exception $ex) { exit($ex->getMessage()); }
?>

main.css is the compiled stylesheet.

index.php contains the code of your web app but first you need to include the index.php from the styles folder:


<?php
 include_once 'styles/index.php';    // Include the LessPHP compiler in the beginning of this file
?>

The above is general folder structure of mine for one-page web app. If you need to create a multi-page web app, you can create a include folder and include the lessPHP compiler to header.php or somewhere similar.

When you edit the stylesheet, you need to only edit the .less files and it will re-generate main.css file once the page is loaded.

In the next part, I will provide you the content of var.less which mentioned above that includes some CSS3 properties for your reference or you can use it as a template.

If you have any question about this part, post them in the comment below.

0

New Blog Title, New Logo

As you already saw, I changed the title for this blog from “Robby Chen Personal Blog” to “Ubuntu Web Coder “as well as the logo.

One reason for changing the blog title is because I’m going to stick to Ubuntu, specifically Lucid Lynx (10.04.1), since I depend on some PPAs to get the updates. Maverick Meerkat (10.10) just doesn’t work for me. I will wait until Natty Narwhal (11.04) is out and see. If this still won’t work for me, I will stay with 10.04.1 and wait for the next release… Anyway, you get the idea.

As most of you who read this blog in the past know, I used to write code in Netbeans until I discovered the hidden potential of gedit for being such a good IDE. That’s why I abandoned Netbeans and replaced with gedit in the new logo. And I renamed blog title specifically to “coder” because I would like to try writing the code in each post from now on.

Besides the gedit logo in the new logo, I have also included two groups of logos, GNU/Linux and PHP. The GNU/Linux logos include Linux penguin, Chrome OS, Android, and Open Source. The PHP logos include PHP, CakePHP, and WordPress. I also included just released HTML5 logo created by W3C. I regularly use these tools and talked and will continue to talk about them in this blog. That’s why I included them in the logo.

What do you think about the new logo, blog title, and background color?

0

Some CakePHP Productive Tips

CakePHP Logo

I’ve been playing around with CakePHP for the last several days. I’m beginning to enjoy using it through the CLI (Command Line Interface) tools that comes with the framework. Maybe because I spent too much time on the command line thanks to the CR-48 (Chrome OS) developer mode :) . Anyway, here are some tips I found while learning this easy to use PHP framework:

  1. During the development, it’s a good practice to change the default value for CAKE_CORE_INCLUDE_PATH both in the index.php and test.php of webroot directory in case you forgot when deploy to the server. For example, I changed the value of this constant to $_SERVER['DOCUMENT_ROOT'] . DS . ‘cakephp’ which is converted into localhost/cakephp. Once I deployed the application to the server, the included path will change to robbychen.com/cakephp without any modification.
  2. According to the 1.2 documentation, each database has its own form control and data type relationship. For example, the tinyint data type for MySQL generates the checkbox control, whereas the boolean data type for SQLite also generates the checkbox control. It also applies to the latest stable version of CakePHP 1.3.
  3. If you want additional database options, you can download datasources plugin. This plugin also contains sqlite3 which, for some reasons, haven’t included with the CakePHP core yet. If you’re going to use SQLite in the framework without this plugin or just specify sqlite in the database config file, it will use version 2 instead.
  4. This is probably a bug in CakePHP: The CakePHP console cannot find the sqlite database file unless it’s in the root of the application folder, whereas the CakePHP web application looks for the file in the webroot directory of the application folder. The database configuration cannot be simply changed to webroot/database.sqlite. If it changes to that value, the console could find it (webroot/database.sqlite) but the web application could not (webroot/webroot/database.sqlite). The solution I decided is to make a link at the root folder to link to the sqlite file in the webroot directory. This way could both benefit the console and web application. It however does not suitable for some of you who are working on both the localhost and the production server, or often change folder, since the link target cannot be edited. The link will break once the whole directory is moved to a different machine or the target file was renamed or moved.
  5. Type cake api [type] [method] in the command line to browse through the CakePHP documentation. It is a very helpful command for use as a reference. However, you may learn some new tricks through this command, or you could use this as the primary learning resource for CakePHP assume that you already knew this command before you learn something else. For example, I found something useful for my project in the Ajax API: cake api helper ajax

I hope these tips help you to become more productive with CakePHP. If you have any questions regarding the above tips, feel free to post them in the comment below.

0

Use CR-48 as a Second Monitor (Updated)

Three laptops

Three laptopsUpdate: According to the Wikipedia, using meta tag to refresh the page is discouraged. However, I think it is okay for development. I also changed the refresh time. It seems that About.com where I originally copied the code from has incorrect information. The refresh time is in seconds, not in milliseconds.

Since my second monitor was broken long time ago, I always missed the two-screen experience.

I have an idea today that since CR-48 is always connected to the cloud, I can make it as a second monitor by connecting to my main machine’s localhost/IP address. This way I can write the code on my primary PC and instantaneously see the result from the secondary monitor by inserting the following meta tag to the testing web page:

<meta http-equiv="refresh" content="1" />

It allows web page to automatically refresh every one second so that it will show the latest rendering result whenever I save the edited web page.

Note that using this method, you can connect more than two PCs as multiple screens as long as they are connected to your home network.

Here are some photos demonstrating this method using a laptop, CR-84, and a netbook running different browsers:

Three laptops

From left to right: Firefox, Chrome OS, Opera

Address Bars

From top to bottom: Firefox (primary PC), Chrome OS, Opera

In case you don’t know, the command for checking the IP address for the primary PC is ifconfig or you can right-click the network connection icon at the top right corner and choose Connection Information:

Connection Information

Connection Information dialog

Discuss in the comment if you want to learn more about this method or have no idea what localhost is.

1

A Small Fancybox Tip – Show scrollbar when viewing Large Images

onStart callback function

Intro

I use Fancybox jQuery plugin to view large/original size of images. However, its default settings don’t setup to view the large size images. It auto resizes based on the browser window size instead. According to the documentation, the options “autoScale” and “scrolling” disables the automatic scaling and enables the scrollbar to be visible respectively. However, I couldn’t figure out the scrolling option since the horizontal scrollbar is missing when viewing a large image that is bigger than the browser width. After looked into the code generated by Fancybox, I noticed that the scrolling option is applied to other than the body element, which is what I want the scrollbars to be at (edges of the browser window). So I used onStart option to write a callback function that set the overflow property for the body element to be visible.

The Code

$("element").fancybox({
 transitionIn: "elastic",
 transitionOut: "elastic",
 autoScale: false,
 onStart: function() {
  $("body").css({overflow:"visible"});
 }
});

Below is the difference between use the scrolling option and use the onStart callback function:

Scrolling

Scrolling Option

onStart callback function

onStart Callback Function

Questions

All of the above options are explained in the Fancybox document page. If you still have questions, feel free to ask them below.

0

Final Revision for Scrolling Animation Code, Maybe

scrollAnime

Introduction

After I revised the scrolling animation jQuery code yesterday, I was going to rewrite it using Mootools. However, I noticed that this code was doing two unnecessary actions. The first one is the removing of the first set of images, and another one is the appending of new sets of images. Several minutes after my eyes watched the scrollbar animate back and forth, I revised the code to the following.

The Code


if ($("#whoWeAreImages").length != 0) {
  // Scroll Animation for the images in the Who We Are page
 var $whoWeAreImages = $("#whoWeAreImages"),
 $wwaLink = $whoWeAreImages.find("a"),
 $wwaImg = $whoWeAreImages.find("img"),
 scrollWidth = $whoWeAreImages.attr("scrollWidth");
  // Do the following once the page is loaded
 $whoWeAreImages.css({overflow:"hidden"})    // Hide the images scrollbar
 .scrollLeft(0)    // Make sure the scrollbar is at the beginning when the page is reloaded
 .append($(this).html()) // Add one more set of images
  // Begin the animation
 .autoscroll({
  direction: 0,
  step: 50,
  onEvaluate: function() {
    // Click action for the images in the Who We Are page
   $wwaLink.fancybox({
    transitionIn: "elastic",
    transitionOut: "elastic"
   })
    // Scroll to the beginning once it scrolls to the beginning of the second set of images
   if ($(this).scrollLeft() >= scrollWidth) {
    $(this).autoscroll("pause");
    $(this).attr("scrollLeft", "0");
    $(this).autoscroll("resume");
   }
  }
 })
 .autoscroll("addpausesource", $wwaImg);
}

Explanation

In the above code, I removed the remove() action and added the append action at the beginning of the loop. It means that it will only has two sets of images available instead of an infinite loop that remove and append continuously to limit two loops which has slower performance.

After this revision, the animation lag still exists. This is probably the final revision of the code before I rewrite it using Mootools because I might discover some techniques during the rewriting of this code.