howtos » howto
I was recently writing a demo to showcase the new Google Language API, and in my demo I did the usual thing of instructing users to View > Page Source in order to view the source code and comments. I know this is less than ideal, because it forces users to have to process the instructions, and then execute them. Somewhere in there you lose them and they never execute the desired action.
It got me thinking: is there a way to have the source code in front of them in one click? A few Google searches later, and the answer was yes!
Using JavaScript you can open a new window to display the source code view of the current window:
-
window.open('view-source:' + window.location.href, 'mysource');
Voila! How easy was that? Now it's your turn.
This is a list of my "must-have" Mozilla Firefox add-ons. If you can recommend anything similar or better, be sure to drop me a comment.
Page Analysis & SEO
Minimise Nuisance
Bookmark Management
Download Management
Productivity
Web Development & Design
Security
Functional Extensions
Tab Management
Add-Ons Management
Page Analysis & SEO
About This Site Bookmarks - right-click on a page, select "About This Site Bookmarks" and you will see a list of handy links pointing off to informational sites such as Alexa, Compete, Netcraft, del.icio.us, etc.
Minimising Nuisance
Bookmark Management
Download Management
Download Statusbar - manage your downloads via the Firefox status bar.
DownThemAll - conveniently download all link targets on a page.
FlashGot - allows for single and multiple downloads utilising an external download manager of your choice (I prefer FlashGet).
Productivity
Auto Copy - highlight a piece of text and the selection is automatically copied to your clipboard.
FoxClocks - displays local times around the world in the statusbar or toolbar. Great for if you are dealing with friends and colleagues across multiple timezones.
FoxyTunes - operate your currently running media player from your Firefox statusbar.
Google Notebook - conveniently clip text and links to your Google Notebook.
Linkification - Converts text links (including e-mail addresses) into clickable links.
Web Development & Design
ColorZilla - eye-dropper tool that allows you to pick the HEX & RGB values of colours of elements on the page.
Firebug - the quintessential Javascript debugger. It also allows for excellent DOM and CSS debugging and manipulation.
IE View - open the current page in an IE window.
Live HTTP Headers - view HTTP request and response headers in realtime.
User Agent Switcher - allows you to spoof the User-Agent string and have Firefox masquerade as the Googlebot, etc, to see how your site reacts to different user-agents.
View Source Chart - renders page source HTML in an easy-to-read manner.
Web Developer - a must for the serious web developer.
YSlow - an addon to the Firebug debugger. It allows you to profile a page and identify bottlenecks. Provided by Yahoo. Also see Yahoo's articles on improving page load performance.
Security
McAfee SiteAdvisor - lets you know if the currently viewed site is considered "safe" or not.
Functionality Extensions
CustomizeGoogle - customize your Google search and application experiences.
ErrorZilla - extends the standard page not found error screen with convenient links such as access to the page's Google cached copy.
Tab Management
Faviconize Tab - minimize a tab's width to the width of the favicon.
Add-Ons Management
FEBE - a convenient extensions & settings backup tool. Allows you to also run scheduled backups. The backups can be used to transport your extensions and their settings to another machine or Firefox profile.
MR Tech Local Install - install power tools for add-ons
Secure File Copy (scp) allows you to copy files between hosts using the SSH protocol.
To copy from a remote host to your current host
-
scp -r user@remotehost:path/to/remotefiles localtarget
-
-
#-r recursive copy
-
#you will be prompted for user's password @ remotehost
To copy files from your current host across to the remote host
-
scp -r localfiles user@remotehost:path/to/remotetarget
There are many examples where you would need to retrieve a random record or more from a set of tables. For example your page template may be cycling through QOTDs, testimonials, offers, specials, and so forth.
To retrieve a random row in MySQL, use the ORDER BY RAND() statement to randomly order the rows of a table. Then use LIMIT x to retrieve the first x rows from the randomised representation of the table.
For example:
-
/* Retrieve 5 random special offers to display in your e-commerce store's sidebar */
-
SELECT offer_id
-
FROM special_offers
-
ORDER BY RAND()
-
LIMIT 5
Of course, we can make our query as complex as needed, and then randomly order the resultset.
-
SELECT so.offer_id, i.title
-
FROM special_offers so
-
LEFT JOIN items i ON (so.item_id = i.item_id)
-
LEFT JOIN item_categories ic ON (i.item_id = ic.item_id)
-
WHERE ic.category_id = 2344
-
ORDER BY RAND()
-
LIMIT 5
This snippet of code reorders items in a table based on the number of steps you want to move an item from its current position. It moves the item of interest to its new position and shifts all other items to their new shifted positions.
-
function moveItem ($n_steps) {
-
if ($n_steps == 0) {
-
return;
-
}
-
-
$cur_pos = $this->pos;
-
$new_pos = $cur_pos + $n_steps;
-
-
if ($n_steps <0) {
-
$min_pos = $cur_pos + $n_steps;
-
$max_pos = $cur_pos - 1;
-
$shift_sign = '+';
-
} elseif ($n_steps> 0) {
-
$min_pos = $cur_pos + 1;
-
$max_pos = $cur_pos + $n_steps;
-
$shift_sign = '-';
-
} else {
-
return;
-
}
-
-
$id = $this->id;
-
-
//Reorder existing items that will be existed by moving this item
-
$sql = "UPDATE positions
-
SET order_num = order_num $shift_sign 1
-
WHERE id = $id
-
AND position>= $min_pos
-
AND position <= $max_pos";
-
-
$this->db->query($sql);
-
-
//Now set new position for this item
-
$sql = "UPDATE postions SET position = $new_pos WHERE id = $id";
-
$this->db->query($sql);
-
}
In most projects there are going to be files that you wish to ignore in version control. These could be temporary files, log or debug files, and so forth. These are files that you can safely ignore when executing commands such as svn commit and svn st. The following shows how to configure your svn client to ignore particular files in your working copy.
svn propedit svn:ignore /path/with/files/to/ignore/
svn opens up your text editor of choice
Use file patterns to indicate which files to ignore from version control. Each pattern goes on a new line. e.g.
log_12*.log *.tmp
Save your file and exit
Now whenever you perform commands like svn st or svn commit, svn will ignore files with the patterns you specified in the directories that you specified.
My previous post showed how to create classes in Javascript. This addendum post shows how to create an inherited class from a parent class.
The concept is simple.
- Declare and define your parent class
- Declare and define your child class without defining the parent-child relationship
- Add a new instance of your parent class to your child class' prototype. Now the child class has access to the parent class' properties and methods. This last step may seem counter-intuitive, but the example below helps to clarify what I mean.
-
function SuperHero(heroID, p1, p2, p3) {
-
...
-
...
-
...
-
}
-
-
/* Do some extending of SuperHero's prototype here */
-
-
//Now let's define our child class - note that we do not initially define the parent-child relationship
-
function AlienSuperHero(heroID, homePlanet, race, p1, p2, p3) {
-
...
-
//Now we indicate the parent-child relationship
-
this.prototype = new SuperHero(heroID, p1, p2, p3);
-
}
-
-
/* Do some extending of AlienSuperHero's prototype here */
Usage would be along the lines of:
-
var MartianManhunter = new AlienSuperHero(3454, 'Mars', 'Martian', 'Flight', 'Telepathy', 'Shapeshifting');
-
if (fire) {
-
//This is a method defined in the parent class
-
MartianManhunter.losePowers();
-
}
Javascript is a prototype-based language rather than a class-based language (e.g. Java). For an explanation of the difference, see Mozilla's comparison of class-based and prototype-based languages.
In short, in a class-based language, objects are created by instantiating classes. The classes' list of properties and methods cannot be altered (e.g. added to) at runtime. A prototype-based language does not have the notion of a class. Everything is an object. A prototype-based object can have its list of properties and methods modified during runtime.
The examples below show how to create a class in Javascript. First we define a function that will behave as our constructor. Then we extend that function's prototype to include further functions that will behave as the class' methods. Note the use of the "this" keyword to refer to the prototype of the current object.
-
//This is our constructor
-
function SuperHero(heroID, p1, p2, p3) {
-
this.heroID = heroID;
-
this.name = null;
-
-
this.power_1 = p1;
-
this.power_2 = p2;
-
this.power_3 = p3;
-
-
this.power_ultimate = p1 + p2 + p3;
-
}
-
-
//Now add some methods to the class
-
SuperHero.prototype.getPower1 = function() {
-
return this.power_1;
-
}
-
-
SuperHero.prototype.losePowers = function() {
-
this.power_1 = null;
-
this.power_2 = null;
-
this.power_3 = null;
-
}
-
-
SuperHero.prototype.setName = function(name) {
-
this.name = name;
-
}
-
-
SuperHero.prototype.alertProfile = function() {
-
var str = 'Hero Profile:\n' +
-
'Name: ' + this.name + '\n' +
-
'Name: ' + this.name + '\n' +
-
'Name: ' + this.name + '\n' +
-
'Name: ' + this.name + '\n' +
-
}
And now we have a simple class with a few simple properties and methods. Usage of the class would be something like:
-
var Superman = new SuperHero(2331, 'Flight', 'Speed', 'Strength');
-
Superman.setName('Superman: Man of Steel');
-
var power_1 = Superman.getPower1();
-
-
if (kryptonite) {
-
Superman.losePowers();
-
}
-
-
Superman.alertProfile();
A few sites I administer have recently had the misfortune of having spambots visit their enquiry and contact pages. These pages usually have a contact form, where an enquirer can leave their name, e-mail, and request or comment. When they submit the form, a copy of the message is e-mailed to the site owner. The spambots try and submit messages that usually contain gibberish but also multiple URLs to spam sites. Something had to be done to prevent site owners from receiving hundreds of spam messages a day.
I considered a few methods for preventing the bots from visiting the enquiry page. These included firewall configuration, user-agent detection, rudimentary parsing of the messages, captcha systems, and so forth. These methods were either too cumbersome to implement, could be circumvented, or spoiled the user experience for a genuine user. The latter was a critical concern.
Enter Akismet
The Akismet API is an open API used to assess the spam score of comments left or enquiries made on a site. It is in widespread use as a plugin for WordPress blogs. Its effectiveness has become a must-have plugin for WordPress installations. The Akismet API however can be applied to any site or application capable of making HTTP requests.
First you need an API key. You can obtain one by registering for a WordPress.com user account (you do not need to have an active WordPress blog). Your API key will be e-mailed to you once you have activated your account.
Akismet and PHP5
Download the PHP5 Akismet Library.
Extract the contents of the downloaded package and place them in a location that your application can access when required.
Here's how to use the Akismet API in your PHP5 code.
-
require_once('Akismet.class.php');
-
-
$API_key = 'xxxxxxxxxxxx';
-
$source_url = 'http://www.mysite.com/contact.php';
-
-
$akismet = new Akismet($source_url, $API_key);
-
$akismet->setCommentAuthor($enquirer_name);
-
$akismet->setCommentAuthorEmail($enquirer_email);
-
$akismet->setCommentContent($enquiry);
-
-
if ($akismet->isCommentSpam()){
-
//Enquiry is spammy - log it for later review by site owner
-
//If false positive, be sure to submit to Akismet so that it can learn from
-
// its mistake. Use Akismet::submitHam()
-
} else {
-
//Enquiry is not spammy - e-mail it to the site owner
-
//If false, be sure to submit to Akismet so that it can train itself better.
-
// Use Akismet::submitSpam()
-
}
-
-
//Below are other Akismet methods that you could call
-
$akismet->setCommentAuthorURL($enquirer_url);
-
$akismet->setCommentType($enquiry_type); //{'blank', 'comment', 'trackback', 'pingback', or custom}
-
$akismet->setPermalink($url); //A permanent URL referencing the resource for which a comment is being left for
Akismet and PHP4
Download the PHP4 Akismet library. Extract the contents of the downloaded package and place them in a location that your application can access when required.
Here's how to use the Akismet API in your PHP4 code.
-
require_once('Akismet.class.php');
-
-
$API_key = 'xxxxxxxxxxxx';
-
$source_url = 'http://www.mysite.com/contact.php';
-
-
'email' => $enquirer_email,
-
'website' => $enquirer_uri,
-
'body' => $enquiry,
-
'permalink' => $this_page_uri,
-
'user_ip' => $referrer_ip, // optional, defaults to $_SERVER['REMOTE_ADDR']
-
'user_agent' => $client_ua, // optional, defaults to $_SERVER['HTTP_USER_AGENT']
-
);
-
-
$akismet = new Akismet($source_url, $API_key, $comment);
-
-
// test for errors before submitting to Akismet
-
if($akismet->errorsExist()) {
-
if($akismet->isError('AKISMET_INVALID_KEY')) {
-
//...
-
} elseif($akismet->isError('AKISMET_RESPONSE_FAILED')) {
-
//...
-
} elseif($akismet->isError('AKISMET_SERVER_NOT_FOUND')) {
-
//...
-
}
-
} elseif ($akismet->isSpam()) {
-
//Enquiry is spammy - log it for later review by site owner
-
//If false positive, be sure to submit to Akismet so that it can learn from
-
// its mistake. Use Akismet::submitHam()
-
} else {
-
//Enquiry is not spammy - e-mail it to the site owner
-
//If false, be sure to submit to Akismet so that it can train itself better.
-
// Use Akismet::submitSpam()
-
}
If you are dealing with multiple users in different timezones or simply want to display times in a timezone other than your server's settings, it is best to store timestamps as their UTC (~ GMT) equivalents. When you read those timestamps later, you can convert them to local time.
Local time to UTC time
date_default_timezone_set sets the default timezone for all date & time operations.
gmmktime is analogous to mktime except it takes in local time values and creates the corresponding UTC timestamp.
gmdate similarly takes in local time values and creates the corresponding UTC date & time.
UTC time to Local time
-
$ts_utc = read_timestamp_from_db(); //Some custom function in your script
-
date_default_timezone_set('Australia/Sydney');
-
$ts_local = $ts_utc + $offset;