Mobilizing Tripsiders.com Tour Marketplace

I haven’t announced it yet here, in the last week of May I launched the Tour Marketplace in Tripsiders.com. It is made from Drupal. The site was only designed so far for the desktop users so one of the thing that was on my todo list was to make it mobile friendly. Over the weekend, I finally had time to create the mobile theme. The experience was great and I want to share the thought process behind it.

Just like any project, I defined my requirements first. One important thing that I had to consider was to choose between using a different subdomain or use Media Queries instead. Media Queries has been the easiest option. I used Media Queries for tablets like iPad since I did not have to tweak it that much. The design is still the same, it just needed adjustment of the width and some padding.

As for the small mobile device, I was inspired by the simplicity of Sephora‘s mobile design. I cannot do it using media queries so I chose to use subdomain (m.tripsiders.com) for the mobile devices and use a different theme.

I checked for possible modules to use and below were on my list: Continue reading

How to introduce someone in an email

I had been doing introduction lately via email only and it was a bit awkward because I did not know how to do it. Should I use the formal “please meet name” type introduction or something else? Googling about it did not help. Today, I found this article on how others do it so I just want to share.

Here is an example from the post:

Hi Sally,

Hope all is well with you! I really enjoyed your last blog post “insert topic here.”

I wanted to introduce you to Bob. Bob is doing “insert startup idea here” and is looking to meet people with expertise in the industry. Naturally, I thought of you since you “insert flattering remark here.”

Bob- I’ll let you take it from here.

Thanks,

Stella

How to find RSS links fast in a site

Are you also having trouble looking for rss links in some websites? Well, I did and not just once or twice but a couple of times! It really annoys me when I find a good blogs but doesn’t provide that little useful link in making me stick in their site. Sometimes they are just plainly playing hard-to-get and I won’t bother searching. Luckily I found a really good tip that made me love firefox even more!

Using firefox 3, you will see at the right side of your URL box a star and a rss image if it finds any link. It looks something like this:
RSS finder
Just click on that orange image and it will ask you to subscribe to that feed. It will automatically detect the RSS feed for you. I found this in this article which was written in 2005! Wow! It’s been here for quite a long time! So maybe this works in other firefox versions or other browsers, I just do not know how. You might want to check for your aggregator settings.

Zend Studio Installation Problem in Ubuntu Hardy

I had a very very long weekend tyring to make HP recovery works and Zend Studio show up to me! I messed up the HP recovery of my laptop last weekend and so windows vista won’t get installed. I decided then to use Ubuntu Hardy. Everything went fine until I installed Zend Studio editor. After the installation, it gave me the ffg blank screen:

Zend blank screen

and the ffg errors:

Preparing to install…
Extracting the JRE from the installer archive…
Unpacking the JRE…
Extracting the installation resources from the installer archive…
Configuring the installer for this system’s environment…

Launching installer…

Locking assertion failure. Backtrace:
#0 /usr/lib/libxcb-xlib.so.0 [0xb2800767]
#1 /usr/lib/libxcb-xlib.so.0(xcb_xlib_unlock+0×31) [0xb28008b1]
#2 /usr/lib/libX11.so.6(_XReply+0xfd) [0xaaa661bd]
#3 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab3fa76]
#4 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab2580a]
#5 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab25a51]
#6 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so(Java_sun_awt_X11GraphicsEnvironment_initDisplay+0×24) [0xaab25c5c]
#7 [0xb2896b28]
#8 [0xb2890aeb]
#9 [0xb2890aeb]
#10 [0xb288e1b4]
#11 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb76957ec]
#12 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb7858828]
#13 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb769561f]
#14 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so(JVM_DoPrivileged+0x32d) [0xb76f2d1d]
#15 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/libjava.so(Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2+0x3d) [0xb73a82cd]
#16 [0xb2896458]
#17 [0xb2890a14]
#18 [0xb288e1b4]
#19 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb76957ec]
Locking assertion failure. Backtrace:
#0 /usr/lib/libxcb-xlib.so.0 [0xb2800767]
#1 /usr/lib/libxcb-xlib.so.0(xcb_xlib_lock+0x2e) [0xb280081e]
#2 /usr/lib/libX11.so.6 [0xaaa65518]
#3 /usr/lib/libX11.so.6(XGetVisualInfo+0×26) [0xaaa5c0a6]
#4 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab246df]
#5 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab24970]
#6 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so [0xaab25b98]
#7 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/xawt/libmawt.so(Java_sun_awt_X11GraphicsEnvironment_initDisplay+0×24) [0xaab25c5c]
#8 [0xb2896b28]
#9 [0xb2890aeb]
#10 [0xb2890aeb]
#11 [0xb288e1b4]
#12 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb76957ec]
#13 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb7858828]
#14 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so [0xb769561f]
#15 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/server/libjvm.so(JVM_DoPrivileged+0x32d) [0xb76f2d1d]
#16 /tmp/install.dir.7943/Linux/resource/jre/lib/i386/libjava.so(Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2+0x3d) [0xb73a82cd]
#17 [0xb2896458]
#18 [0xb2890a14]
#19 [0xb288e1b4]

And it seems Beryl is the culprit! I’ve never used Beryl before but since this is by default installed in Ubuntu Hardy, so I really never know it was there but the theme looks cool though. Anyway, it seems that Beryl is messing up with the JRE. Here is the complete information from Zend studio.

Zend Studio starts up with an empty window, or other GUI problems, due to XGL-Compiz/Beryl (with JRE) compatibility issues

Symptoms

When running Zend Studio:
1. The ZS’s main window comes up totally empty.
2. Sometimes the window has some of the frames painted, but the rest of the window is empty.
3. In the empty ZS window the mouse cursor is changing while moving around the window (as if there are objects: like buttons and other objects).
4. There were erratic mouse/window movements reported.

Summary

Zend Studio starts up with various windowing GUI problems in some linux distros, while using the XGL-Compiz/Beryl product.

Cause

1. Incompatibility between the XGL environment, the JRE, and the Zend Studio Client.
2. The decoration in the 3D environment clashes with the Java Runtime and distorts the operation and visualization of the Zend Studio client’s window.

Get the solution

I have very unique problems when installing zend studio in different versions of Ubuntu. Hmp! I hope the next version, it will work flawlessly.

PHP Security Tips

At the devzone, Cal Evans has written 21 php security tips. I have only read #17 where you can download a 37 page guide (in pdf) that explains the terms and concepts involved in securing your PHP application.

Application security should not be a “when all else fails” situation. It’s not something you can “put in later”. As we’ve mentioned before, there is no single silver bullet to solve your application security issues. Security is something that should be rolling around in the back of your dead in the design phase, the coding phase, the testing phase, even after you’ve rolled your code into production.

Source

Troubleshooting your cakePhp installation

If your a first timer installing cakePhp, it’s quite annoying if your not getting it to work. Really, I’ve seen people take up to 3 days just installing it because they don’t know what the problem is. The common problem I’ve seen is usually a mod_rewrite issue. If your installing an application made in cakePhp and can’t make it work, I suggest the ffg:
1. Get the most recent stable version from cakephp.org and follow the instructions from the Manual Section 3. Install it in a subfolder. You can always move it somewhere else after the installation. Let’s say the subfolder name is /mycake. Also make sure to change the permission to /app/tmp
2. After running it, see if the page is a bit colorful. If yes, then go to the next step. If not, check the src of the <link> tag. The link tag should most likely look like this
<link src="/mycake/css/style.css">
If the src is only “/css/style.css“, then I bet you have a mod_rewrite problem. Check your apache configuration. For windows, I believe it is named httpd.conf and most likely it was just commented out in the list of modules so look for the word mod_rewrite. In ubuntu, most likely it is in the /ect/apache2/, I don’t know in other distros. I can’t give much info in troubleshooting it in ubuntu or linux, there could be a couple of ways. After successfully doing so, remember to restart your apache and check again. Don’t stop until you see those colors. Go to the next step afterwards.
3. You can stop right here. The ffg step is just for me to verify that no doubt the installation works. Proceed if you like.
Create a simple controller with the ffg content:
[php]var $uses = null // so you dont have to use a model
function index() {}[/php]
Then create your view named index.thtml (im using the 1.1 version). If that successfully loaded, congratulations! You have verified your installation successful. If not, then tell me about it.

Another problem I experienced before when installing this in a server is the “new installation of cake: open_basedir restriction error“. Basically, here are the solutions:
1. Hack the core. Change the fileExistsInPath (located in /cake/basics.php) function to:
[php]function fileExistsInPath($file) {
$paths = explode(PATH_SEPARATOR, ini_get(’include_path’));
// removing /usr/share/pear from the list of includes_path
array_shift($paths); //added
array_shift($paths); //added
// the rest goes here
}[/php]
2. .htaccess config. Add the ffg lines to your .htaccess so that the php include_path doesn’t have all the extra stuff you don’t need:
[php]php_value include_path[/php]
Read more info here.
For IIS installation, I just found this help . If you have other experience, write about it or add a comment and let us all know.

How to change your DEBUG level on the fly

The debugging features of cakePhp is very very helpful to me specially the full debug with sql. Sometimes it’s a bit irritating if your dealing with ajax calls. In looking at the cheesecake source code, I found this hack to change it to 0, 1, 2 or 3 on the fly:
[php]Configure::write(‘debug’,0);[/php]
Here is the complete code on how they handle ajax calls:

[php]// Hack to prevent wierd output with AJAX
if ($this->RequestHandler->isAjax()) {
$db =& ConnectionManager::getDataSource(‘default’);
$db->fullDebug = false;

}[/php]

cakePhp $html->checkbox htmlattributes issues

It’s not obvious but certainly I was caught offguard for a certainly small issue that made me use the old habit of doing the checkbox thingy.

When I explicitly tell the html helper to check a certain checkbox, I always do array('checked'=>'checked'); to add the checked attribute but I am left wondrin why it does not do what I want. I really can’t remember what I did to make others work but certainly it was such a headache that I opted to use the old <input type=’checkbox’ /> tags. After looking at the html helper, I found out the ffg comments

* + ‘compact’
* + ‘checked’
* + ‘declare’
* + ‘readonly’
* + ‘disabled’
* + ‘selected’
* + ‘defer’
* + ‘ismap’
* + ‘nohref’
* + ‘noshade’
* + ‘nowrap’
* + ‘multiple’
* + ‘noresize’
*
* And its value is one of:
* + 1
* + true
* + ‘true’
*
* Then the value will be reset to be identical with key’s name.
* If the value is not one of these 3, the parameter is not output.

This does not only involve the checkbox but all the input tags because they pass this step first before outputting any parameter. I wish I explored on this much earlier, it would have saved me a lot of energy. Oh well, atleast I learned something new for the day :)

You may also want to check the function yourself. It is the function _parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) in the html helper. You can see the $insertBefore = ' ', $insertAfter = null, this is useful for checkboxes to add labels but currently, that option is not available in the 1.1 version. Someone already asked this enhancement in trac so I am not reporting it again. I hope that saves some of your time :)

Validate radio buttons in cakePhp’s ajax->form

It took me a while to learn how to add validation using the $ajax->form() of cakePhp. I think the ajax helper simplifies your work for ajax calls but you should first understand how to use it. The manual isn’t that helpful in explaining the deatails of this helper. Here is one example that I used in an application I am involve with and this hopefully could brighten someone’s day.

In my view.thtml, I have this form

<?php
// !important: name your form
$form_options['id'] = ‘myform’;
$form_options['update'] = ‘my-results’;
// this is where you’ll call the validation function
$form_options['before'] = ‘if (!validate()) return false;’;
echo $ajax->form(‘/controller/action’, null, $form_options)
?>
<div id=”errMsg”></div>
<table>
<tr valign=”top”>
<td nowrap><span class=”required”>*</span> Subscription type </td>
<td><div id=”ModelType”><?php echo $html->radio(‘Model/type’, $my_type, ‘<br />’) ?></div></td>
</tr>
<tr valign=”top”>
<td nowrap><span class=”required”>*</span> Receive updates </td>
<td><div id=”ModelRange”><?php echo $html->radio(‘Model/range’, $my_range, ‘ ‘) ?></div></td>
</tr>
</table>
</form><div id=”my-results”></div>

The validation looks like this

function validate() {
var validation_cnt = 0;
// you must delete the previous message
removeMsg(['err1', 'err2', 'err3']);

// begin the validation
if (isRadioEmpty(“myform”, “data[Rss][type]“)) {
insertMsg(‘RssType’, 1, ‘This is required.’);
validation_cnt++;
}

if (isRadioEmpty(“myform”, “data[Rss][range]“)) {
insertMsg(‘RssRange’, 2, ‘This is required.’);
validation_cnt++;
}

if (validation_cnt > 0) {
var req_msg = ”;
if (validation_cnt == 1) {
req_msg = ‘Found ‘+ validation_cnt +’ error. Please double check your answers. Some fields are required.’
} else {
req_msg = ‘Found ‘+ validation_cnt +’ errors. Please double check your answers. Some fields are required.’
}
insertMsg(‘errMsg’, 3, req_msg);
validation_cnt = 0;
return false;
}

return true;
}

One problem I had with this one is that I need to validate radio buttons. But since cakePhp uses illegal characters in its name, you cannot just use the normal call for it. I found an explanation of how to do this here. Here is the function that validates the radiobuttons:

/**
* Returns true if any of radio boxes with the NAMEs of elementName contained in the FORM named formName is checked
*
* @param formName – ID of the FORM
* @param elementName – NAME of the radio boxes
* @author: Rachel
*/
function isRadioEmpty(formName, elementName) {
var empty = true;
for (i=0; i<=document.forms[formName].elements[elementName].length – 1; i++) {
if (document.forms[formName].elements[elementName][i].checked) empty = false;
}

if (empty) return true;
return false;
}

I am also using some prototype methods to insert the error messages at the bottom of the fields and count the errors. Here is the function for that

/**
* Insert error message after the element containerID
* Add style to class errFld to add style to the error message
* You can delete the previous message created by using @link removeID(‘err’+errID)
*
* @param containerID – ID of an element preceeding the error message
* @param errID – any unique ID that you can give to the error message to uniquely identify it
* @param msg – message
* @param containerType – default value is DIV tag
* @author: rage
*/
function insertMsg(containerID, errID, msg, containerType) {
if (!containerType) containerType = ‘div’;
new Insertion.After(containerID, ‘<’+containerType+’ id=”err’+errID+’” class=”errFld”>’+msg+’</’+containerType+’>’);
}

/**
* Delete the element if it exist. Do nothing if it doesnt exist
*
* @param id – element IDs
* @author: rage
*/
function removeMsg(ids) {
for (x=0; x<=ids.length – 1; x++) {
try { Element.remove(ids[x]); } catch (err) {} // do nothing
}
}

You can check the whole code for simplicity here.