壹號車場

終於完成 Automall 的 revamp。因為一些外在因素,這網站遲了差不多半年才面世。又是一個 CakePHP + jQuery 的 project,當中遇到不少問題,例如CakePHP跟MSSQL的連接,Multilingual,處理某些Big-5編碼(舊系統用Big-5,而且MSSQL沒有UTF-8)會出現的怪獸字等。這些問題最終都能一一解決,多謝在網上分享的先知們及在MSN上當我求救的時候給我回應的好友。

其實這個網站還有很多地方可以改善,例如更好的SEO,使用AJAX後的Deep-linking等。

Title tag for better SEO & web accessibility

I’m MAD!

This is a website we have done for a doctor specialized in hair transplant.

Dr. Eric Lam Hair Transplant Center

As our STANDARD web development package, we offer SEO-friendly web structure to our clients. Although the SERP (Search Engine Results Page) rank might not be at the top, if the client is doing well with all the updates and maintenance, the rank may be on the first page.

After handing the project to the client, an SEO company helps the client to update the <title> tags and <meta> tags for all pages of the website. This is not a problem if the page titles are optimized to a descriptive sentence of the page content. However, all page titles and meta tags are the same in ALL pages. The website features 3 language version and there are around 50 pages in a single language version. There are totally 150 pages with the same titles and meta tags!

PLEASE!!! PLEASE!!! PLEASE!!!

This is like the first most basic important rule for SEO.

PLEASE MAKE UNIQUE & DESCRIPTIVE TITLES!!!!!!

This also a bad practice for web accessibility. Imagine if a blind person visit this website, the voice browser will always speaks the same page title when s/he browse different pages.

I’m starting to see duplicate page titles and meta tags in my Google Webmaster Tools account. This is another bad time when you see somebody else screw your work up.

HKID Card check digit validation with CakePHP

HKID is always needed when filling application forms. It’s a string with combination of maximum 9 characters. The pattern is like this.

XY123456(Z)

X and Y are 2 letters from A to Z. After that is a 6-digit number. The whole HKID is ended with a check digit displayed with a pair of parenthesis. The validation rule can be found in Wikipeida – Hong Kong Idenitiy Card.

With the strong validation feature of CakePHP, we can define our customized validation rule for HKID check digit.

In the model class file.

var $validate = array(
     'hkid' => array(
        'checkDigit' => array(
            'rule' => 'checkDigit',
            'message' => '請填寫正確的香港身份證號碼。<br />Please input a valid HKID.'
        )
    )
);
 
function checkDigit($hkid){
    // the value is stored in $hkid['hkid'], store it back to $hkid for ease of use
    $hkid = $hkid['hkid'];
 
    // create an array for the weight of the letters
    $weight = array();
    for ($i=65; $i&lt;91; $i++){
        $weight[chr($i)] = ($i-65)%11+1;
    }
 
    // add a space with weight 0 for HKID without the first letter
    $weight[' '] = 0;
 
    if ((strlen($hkid) == 8) || (strlen($hkid) == 9)){
        // convert all letters to uppercase
        $hkid = strtoupper($hkid);
        // make all HKID become 9-digit long
        if (strlen($hkid) == 8){
            $hkid = ' '.$hkid;
        }
        // split the HKID string into a 9-element long array
        $chars = preg_split('//', $hkid, -1, PREG_SPLIT_NO_EMPTY);
 
        $value = 0;
        // calculate the sum with the 9-position value
        $value += $weight[$chars[0]]*9;
        $value += $weight[$chars[1]]*8;
 
        for ($i=2; $i&lt;8; $i++){
            $value += $chars[$i]*(9-$i);
        }
 
        // compare the check digit value and the calculated 11 - 11-modulus 
        if (is_numeric($chars[8])){
            $checkValue = $chars[8];
        }
        elseif ($chars[8] == 'A'){
            $checkValue = 10;
        }
        return ($checkValue == (11 - $value%11));
    }
    return false;
}

So simple but very handy validation function for checking HKID check digit.

Dealing with CJK in CakePHP

As a web development company in Hong Kong, we are in a lot of projects with multilingual support, usually English, Traditional Chinese & Simplified Chinese. Having the web application and database running in UTF-8 is very important.

CakePHP is set to run in UTF-8 by default. However, this is not the case with MySQL. If you do your MySQL connection with purely PHP, you need to run a SQL statement.

SET NAMES = 'UTF8';

This tells your PHP page to connect MySQL in UTF-8 collation. In CakePHP, the default database setting in database.php is like this:

var $default = array(
	'driver' => 'mysqli',
	'persistent' => false,
	'host' => 'localhost',
	'login' => {database_username},
	'password' => {database_password},
	'database' => {database_name},
	'prefix' => ''
);

This won’t connect MySQL in UTF-8. To add UTF-8 support with MySQL in CakePHP, simply add one line after ‘prefix’ => ”.

var $default = array(
	'driver' => 'mysqli',
	'persistent' => false,
	'host' => 'localhost',
	'login' => {database_username},
	'password' => {database_password},
	'database' => {database_name},
	'prefix' => '',
	'encoding' => 'utf8'
);

Data save to and read from MySQL will be in UTF-8.

Web Accessibility, SEO & Cross-browser compatible

I found many companies ignore the importance of web accessibility. They even don’t want to spend resources to make their websites more accessible. I did a very short presentation on web accessibility to my BNI members last week and I hope this little piece of information would help them to understand that a good website can be a profit centre. The slides can be found at http://kopanda.creativeworks.com.hk/web_accessibility/bni_23_feb_2010.html.

Some notes.

1. Web accessibility encompasses all disabilities. – w3.org

2. Disabilities includes blindness, deaf, aging-related conditions, colour blindness, etc.

3. To increase website traffic, we should focus on Search Engines

4. Search Engines are disables as they don’t see image, flash and all new media. They only read text.

5. A promotional website we did for China UnionPay. Although all elements are graphics, we did SEO to let search engines to understand the content of the website. It was ranking at the 1st place 3 days after the site was launched.

6. A simple search for “無錢開飯,有錢叫雞”, my blog link was ranked right after 陶傑.

7. To make web content more available to all users. – w3.org

8. Even MS has announced they are not giving any support to IE6, IE6 covers a significant portion of market share. We need to make all browsers view the web in the same way.

9. Websites should be cross-browser compatible. Our projects can be seen with nearly the same output from all major browsers.

10. Websites can also be available with mobile devices like iPhone, PSP, etc.

11. Websites can be connected to social networks like Facebook and Twitter.

12. All about VISIBILITY.

.live() and change event in IE6 and IE7 with jQuery 1.4.2

I’m working on an online nomination application for The Hong Kong Academy for Gifted Education (HKAGE). Again, extensive work on CakePHP and jQuery. As usual, jQuery is linked from Google API. I only define the major version so that the application always link to the latest jQuery version. Bryan and I faced an issue on IE6 and IE7 with .live() and change event.

$("select").live("change", function(){
	alert('haha');
});

It worked on Firefox, Safari and Chrome but not IE6 & IE7. I felt strange about this as .live() has been implemented since jQuery 1.3 and it’s supposed to be stable in later versions.

To make this work in IE6 & 7, either use jQuery 1.4.1 or livequery.

I hope this can be fixed soon.

IE6 IE7 ordered list numbering bug

There is a strange bug in IE6 and IE7. Usually when you do

<ol>
<li>xxx</li>
<li>yyy</li>
</ol>

The xxx and yyy will be listed with 1 and 2. This is not the case in IE. Number before list items are always 1 in an ordered list.

IE7 nubmering bug

To fix this, please add

ol li { display: list-item; }

in your CSS.

Please also take a look at the last item on the list on the right hand side. The number is align at the bottom of the item instead at the top. So simply add

ol li { vertical-align: top; }

The ordered list should display as expected.

Error creating AIR file

On Norman’s request, I help him to create a lucky draw program to randomly draw an instant photo from all those taken from his wedding banquet. All the photos will be digitalized and loaded to the program. As the program has to access local files, I package the Flash file as an AIR application. Everything went well during the development until the final step. When I made the AIR package, I got this error:

Error creating AIR file Unexpected or unknown element or attribute in the application descriptor file

I looked for Adobe’s documentation and could find any errors related to this. I then deleted the application descriptor file (xxx-app.xml) and made the package again. It worked without any error. I thought the file might be changed due to a copy from Windows at office and my Mac at home. The XML application descriptor file is as weak as the application file in Flex. If you would like to make changes by yourself, please be careful. The compiler won’t tell you much on what is wrong on the file. It’s okay when you are doing some small piece of work. However, when you are working on a big project, you might have to change the application file on your preference, it would spend you much time on debugging it.