Archive for May, 2009

How To Add A DZone.com Button To Your WordPress Blog Posts Automatically

Saturday, May 30th, 2009

After previously adding the DZone.com voting buttons manually to each post (which you really don’t want to do every time as you need to set the post URL manually for the index page) I have modified the JavaScript provided by DZone and integrated some code into the WordPress files so that a button is added automatically on each post now just like the button to the left of this text.

Uploading The Modified JavaScript File

I noticed that DZone isn’t currently sending a cache header on every JavaScript request and that the snippet you are given to integrate into your post redirects via a 302 header to the real file. If you have 5 DZone buttons on your blog’s homepage (if you are displaying 5 posts) that means 10 additional HTTP requests to DZone.com that take time and delay the page loading process.

If you have already integrated the JavaScript snippet provided by DZone you should remove it now otherwise you will get two buttons per post. Just download this file and upload it to a directory of your choice on your server. You may even use the WordPress uploader but write down the final path to the JavaScript file as you need to enter it in the next step.

Now open Appearance > Editor in the WordPress Admin Panel on the left hand side and click on header.php on the right hand side. Add the following line somewhere within the <head> of the document:

1
<script src="/js/dzone.js" type="text/javascript"></script>

Replace “/js/dzone.js” by the path where you have uploaded the dzone.js file before. Then click on “Update File“.

Adding The Button To Every Post

After saving click on the link “single.php” on the right side just as you did before with the header.php file. Depending on your chosen WordPress theme the HTML code may look more or less like this:

1
2
<div class="entry">
<?php the_content('<p class="serif">Read the rest of this entry »</p>'); ?>

Just between the opened <div> tag and the following <?php tag insert the snippet code:

1
<span style="float:left;margin:0 10px 10px 0"><script type="text/javascript">dzone_show_linkbox('<?php the_permalink(); ?>', '<?php the_title(); ?>', null, 1);</script></span>

Thus the modified code will look like this:

1
<div class="entry"><span style="float:left;margin:0 10px 10px 0"><script type="text/javascript">dzone_show_linkbox('<?php the_permalink(); ?>', '<?php the_title(); ?>', null, 1);</script></span><?php the_content('<p class="serif">Read the rest of this entry »</p>'); ?>

Save the file by clicking on “Update File” afterwards.

Repeat this step for the index.php file and you’re done.

If you are using the WP Super Cache plugin or any other caching plugin you may need to clear the cache otherwise you won’t see the modified pages. When using WP Super Cache select Settings > WP Super Cache on the left side and then on the “Delete Cache” button on the page.

After reloading your blog’s homepage or any article page you will now see a DZone button just like this article does.

Tutorial: How To Use Prototype.js On Your Site

Saturday, May 30th, 2009

prototype.js is an amazing JavaScript framework that I have been using for some years now. This tutorial shows you how to work with prototype.js and what some best practices are. It won’t go into details on every available method but it will give you a quick introduction.

I apologize for the coding style but the WordPress plugin seems to eat spaces and tabs.

Obtaining Prototype.js

You can download the latest version of the prototype library from the download page and include this on your page like this if you have saved it as prototype.js in your document root directory:

1
2
3
4
5
6
7
8
9
<html>

<head>

<script src="prototype.js" type="text/javascript"></script>

...

</html>

There are also some packaged and minimized versions of the file available because the file itself is quite large.

Using Google To Load Prototype.js

Another option is using Google to include the Prototype JavaScript Library on your page thus offloading traffic from your server to Google. You can use Google’s AJAX Libraries API for that purpose. If you want to use Google which has the benefit of distributed servers around the world therefore likely speeding up the download this is how it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
<script src="http://www.google.com/jsapi"></script>

google.load("prototype", "1.6.0.3");

google.setOnLoadCallback(function() {

// What to do once the file has been loaded

....

}

</script>

Throughout this tutorial I am assuming that you are loading the library without using Google as this makes initializing your own code more complicated.

JavaScript Coding With Prototype.js

After you have included the prototype.js library it’s time to start implementing your JavaScript code. With prototype.js I have come to use classes exclusively because this allows for a object-oriented architecture of your JavaScript code and encapsulates the code.

Create a new file – for demonstration purposes in this tutorial named test.js – and save it in your document root (or in any other directory like /js, just make sure to change the path accordingly in the <script> tag). Now add the following code to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Create the class

var myTestClass = Class.create({

initialize:function()

{

// Is called when the page has finished loading by the Event.observe code below

alert('Works!');

}

});

// Global variable for the instance of the class

var myTest;

// Creating an instance of the class if the page has finished loading

Event.observe(window, 'load', function() {

myTest = new myTestClass();

});

Now you need to create an HTML file named test.html containing the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<html>

<head>

<title>prototype.js Test</title>

<script type="text/javascript" src="prototype.js"></script>

<script type="text/javascript" src="test.js"></script>

</head>

<body>

<h1>prototype.js Test</h1>

<div id="container" style="display:none"></div>

<ul id="list">

<li>Item 1</li>

<li class="highlight">Item 2</li>

<li>Item 3</li>

<li>Item 4</li>

</ul>

<a href="http://www.dzone.com/" target="_blank" id="demoLink">Click me!</a>

</body>

</html>

If you then load this file in your browser a JavaScript alert box will pop up saying “Works”.

By creating an event hook for the window’s load event handler you can be sure that every element on the page has been loaded. If you are not using this code and leave out the Event.observe code in the test.js file it may happen that some elements on your page may not yet have loaded so the user may receive a JavaScript error message if you are trying to access elements on the page that do not yet exist.

You can also use ‘dom:loaded‘ instead on ‘load‘ in the Event.observe call which will be executed once the DOM tree of the HTML document has been fully created. This means that individual elements may not have been loaded (e.g. an image) but you can already access all of the elements on the page.

The Constructor

Whenever a new instance of a class is created the initialize() method of the class is called automatically (just like PHP’s __construct() method). You can of course define an arbitrary number of parameters as well. Just modify the line to see how it works:

1
2
3
4
5
6
7
8
9
initialize:function(url)

{

// Is called when the page has finished loading by the Event.observe code below

alert('Works @ '+url);

}

and

1
2
3
4
5
Event.observe(window, 'load', function() {

myTest = new myTestClass(location.href);

});

Methods

Defining methods within the class is very easy. In contrast to other programming languages you cannot declare specific methods (functions) as private, protected or public thus they can be accessed from the outside anyways even if you do not desire it.

Let’s create a new method and modify the class so that it looks like in this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var myTestClass = Class.create({

initialize:function(url)

{

// Is called when the page has finished loading by the Event.observe code below

alert('Works @ ' + this.toUppercase(url));

},

toUppercase:function(str)

{

return str.toUpperCase();

}

});

Please note the specific syntax for creating new methods. Every method must be separated by the one before with a comma and the last method in the class must not be followed by a comma (Internet Explorer does not like this).

You can simply call methods by prefixing them with a “this.” from within the class.

Accessing Elements

The most often used function from my experience is the $() function which allows you to access any element that has an id. The HTML code contains a link to dzone.com which has an id. To access that element you simply need to write

1
$('demoLink')

No need to write the long document.getElementById(‘demoLink’) anymore. Here is an example you can add to the initialize() method at the very end:

1
alert($('demoLink').getAttribute('href'));

This will show an alert box with http://www.dzone.com in it. Likewise you can set specific attributes easily:

1
2
3
$('demoLink').setAttribute('href', 'http://www.saschakimmel.com/');

alert($('demoLink').readAttribute('href'));

This will change the href attribute pointing to this blog’s homepage.

Now you may feel tempted to give any element that you may wish to access a specific id attribute. But wait – that’s not required! The Prototype library contains the $$() method which allows you to use CSS3 selectors (yes, even if the browser does not yet support it). So just as you might do with CSS you can do with prototype.js:

1
$$('#list li.highlight')[0].update('I was Item 2');

The $$() method always returns an array. Because our code only contains a single LI element with the given class “highlight” in an unordered list with the id “list” this code works.

You could even use something like this to achieve the same result:

1
$('list').down('li.highlight').update('I was Item 2');

The Element.up() and Element.down() methods return only a single element which is the first element found from the element given and also support CSS3 selectors.

The Element.select() method is similar to $$() but whereas the $$() method searches globally the select method searches from the given element within the DOM tree so you could also have used this code as well:

1
$$('ul')[0].select('.highlight')[0].update('I was Item 2');

This code may look a bit complex at the beginning but if you start using the library you will quickly recognize the different methods. I just urge you not to give every single element an id so that you can access it by using the $() method. You should use ids on semantic blocks like #topbar, #navigation and so on and use classes within the code wherever possible.

This way you are not blowing up your code by only using ids for accessing elements with JavaScript. It’s just not necessary if you’re using the prototype.js library.

Add more semantics to your code.

Updating And Modifying Elements And Classes

As you have already seen in the examples above you can use the Element.update() method to update element contents. If you wish to modify attributes you should use the Element.setAttribute() method (which is a native browser method).

You can also add, edit and remove class names at runtime easily.

To add a CSS class use the Element.addClassName() method:

1
$('demoLink').addClassName('democlass');

To find out whether a specific element has a specific class use Element.hasClassName():

1
2
3
4
5
6
7
$('demoLink').addClassName('democlass');

if ($('demoLink').hasClassName('democlass')) {

alert('Yikes!');

}

Loops

Forget those annoying for loops you have learned when using JavaScript. Prototype has its own methods that ease the implementation of loops. There are some pitfalls however which I am going to explain here.

We now want to loop over the <li> elements of the list and wrap a <strong> around the current contents of each <li> element. This is how it works:

1
2
3
4
5
$$('#list li').each(function(el) {

el.update('<strong>'+el.innerHTML+'</strong>');

});

In fact this is a method that is a bit dirty because we are using HTML code as a string in the update() method. This is a cleaner method but it’s very long in contrast to the method before:

1
2
3
4
5
6
7
8
9
10
11
12
13
$$('#list li').each(function(el) {

var oldContent = el.innerHTML;

var strongEl   = new Element('strong');

el.update('');

el.appendChild(strongEl);

strongEl.update(oldContent);

});

Most of the time I’m sticking with the shorter method above.

Using bind()

Now let’s call the toUppercase method we created in our class. Because the each() method has been implemented by prototype.js using the this keyword within the each loop would reference the each method itself so this will throw the error “this.toUppercase is not a function”:

1
2
3
4
5
$$('#list li').each(function(el) {

el.update('<strong>'+this.toUppercase(el.innerHTML)+'</strong>');

});

So in this case we need to bind the this keyword to our class. This can be achieved by using the bind() method:

1
2
3
4
5
$$('#list li').each(function(el) {

el.update('<strong>'+this.toUppercase(el.innerHTML)+'</strong>');

}.bind(this));

Now our code works! Whenever you are using specific prototype.js methods where you can use a this inside the method you need to bind it to your class in that way.

Event Handlers

Remember this code?

1
<a href="..." onclick="doThis()">Click here</a>

Or even this code?

1
<a href="<a href="javascript:doThis">javascript:doThis</a>()">Click here</a>

You don’t need this with prototype.js anymore as you can use the unobtrusive event handlers it provides. If a link is only useful and functional with JavaScript enabled only you should add a CSS style of “display:none” to the element and make it visible in the initialize() method.

Now let’s add an event listener to the link:

1
$('demoLink').observe('click', function() { alert('This link has been disabled!'); });

If you reload the page and click on the link you will see an alert box and if you click on the OK button the link will be opened in a new window/tab anyways. To prevent this you need to stop the event. Just modify the code to look like this:

1
$('demoLink').observe('click', function(e) { alert('This link has been disabled!'); Event.stop(e); });

As you see now the link is no longer opened. However using anonymous functions inline is not a good programming style so let’s create an additional method in our class:

1
2
3
4
5
6
7
8
9
showDisabledMessage:function(e)

{

Event.stop(e);

alert('This link has been disabled!');

},

You also need to modify the Event observer:

1
$('demoLink').observe('click', this.showDisabledMessage.bindAsEventListener(this));

Just as you did before with the call to the bind() method when using the each method when using an event listener you need to use the bindAsEventListener() method to bind the function to your class.

Here is some more code for you to see some more of what is possible with event listeners:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$('demoLink').observe('mouseover', function(e) { Event.element(e).setStyle({

'color': 'red',

'fontSize':'30px'

}); });

$('demoLink').observe('mouseout', function(e) { Event.element(e).setStyle({

'color': 'blue',

'fontSize':'12px'

}); });

I won’t go into the details on these methods so please have a look at the documentation.

AJAX

I know I have to show some demo code for AJAX usage when writing an article on the Prototype.js JavaScript framework so here we go. Create an HTML file named ajax.html and add the following code to it:

1
2
3
4
5
<div style="border:5px solid red;padding:15px;">

<h1>Loaded via AJAX!</h1>

</div>

We now want to update the <div> with the id “container” with this content after the ajax.html file has been loaded via AJAX after clicking on the link. Let’s clean up the code of the initialize() method:

1
2
3
4
5
6
7
initialize:function(url)

{

$('demoLink').observe('click', this.loadContent.bindAsEventListener(this));

},

Now add this method to the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loadContent:function(e)

{

Event.stop(e);

new Ajax.Updater('container', 'ajax.html', {

onComplete:function() {

$('container').show();

}

});

},

This method stops the event (i.e. it won’t open the dzone.com homepage in a new window/tab), sends an AJAX request to the ajax.html file, updates the div with the id “container” (the first parameter) and when the request has finished makes the container visible with the show method as it has an inline style reading “display:none”.

As you see you don’t even need any dynamic code on the server to use AJAX.

In this article I have only scratched the surface of what prototype.js has to offer. In encourage you to read the documentation and just play around with the methods. Prototype.js has so much in store it’s really fun developing. As you may have noticed in the article I am using unobtrusive JavaScript which means that there is not a single line of JavaScript code in the HTML file (except the two <script> elements of course).

Download the source code

How To Install Apache, MySQL and PHP (WAMP) On Windows Manually

Friday, May 29th, 2009

If you are using Windows as your operating system when developing your websites you should always test your websites on your local system before you upload the files to your live server.

Although there are several pre-packaged Apache-PHP-MySQL (WAMP) packages available for download when using these you are bound to their release cycles and the structure of the directories they are using.

This article describes how you can install Apache, PHP and MySQL manually on your local system with maximum flexibility because you can quickly update one program if the need may arise, e.g. if a new PHP version has been released.

This method also shows you where specific files are located which you may need to edit when changing settings so you can dive a bit deeper into the configuration files which may be quite helpful if an error occurs.

WAMP Setup

In this tutorial I’m assuming the following:

  • Apache, PHP and MySQL are installed to subdirectories of d:\webserver
  • The document root is d:\webroot
  • the first test domain is www.webserver.local
  • the document root for that VirtualHost is d:\webroot\www.webserver.local\htdocs which will contain all documents accessible via the browser

Installing The Apache Server

First of all you need to download the latest Windows distribution of the Apache HTTP server from the Apache download page. Pick the MSI installer including OpenSSL which is named something like „Win32 Binary including OpenSSL 0.x.x (MSI Installer)” and is listed under the section named something like “Apache HTTP Server 2.2.xx is the best available version”.

After launching the setup program pick the „Custom” setup and choose the directory d:\webserver\Apache as the installation path. Enter the information as shown in the screenshots below.

apache-install

apache-install-2

Installing PHP

Dowload the latest (stable) PHP 5 version from the PHP download page. Choose the „PHP 5.x installer”. After download and launching the file when prompted to select a directory choose d:\webserver\PHP

php-install

Webserver Setup – “Select the Web Server You Wish To Set Up” select “Apache 2.2.x”.

php-install-2

When prompted for the Apache configuration directory select d:\webserver\Apache\conf.

php-install-3

On “Choose Items To Install” select the extensions you’d like to install.

If you don’t know which might be useful you may use the following list to find some suggestions:

  • cURL (good for accessing HTTP servers)
  • EXIF (if you’re dealing with photos and wish to extract meta information)
  • GD2 (image creation and manipulation)
  • Multi-Byte String (mbstring, for i18n, e.g. conversion from ISO-8859-1 to UTF-8)
  • mcrypt (for encryption)
  • mysql, mysqli
  • other database extensions you might be using (postgreSQL etc.)
  • OpenSSL (for accessing https URLs)
  • PDO, PDO_Mysql, PDO_SQLITE
  • SOAP (if you’re planning to access SOAP resources or create you own SOAP server)
  • SQLite

Installing MySQL

To download the MySQL server visit this MySQL website and download the Windows MSI Installer package under „Community Edition”.

To ease administration and creation and editing of tables and databases I encourage you to download and install the MySQL GUI tools as well.

In the MySQL setup dialog pick the custom installation and select the directory d:\webserver\MySQL as the installation directory.

mysql-install-1

mysql-install-2

When configuring the MySQL server use the detailed configuration.

mysql-install-3

Use “Developer Machine” as your server type

mysql-install-4

Select “Multifunctional Database” in the database usage dialog:

mysql-install-5

Keep the default InnoDB tablespace settings and click Next:

mysql-install-6

Select “Decision Support” on the next dialog:

mysql-install-7

Keep the default values on the next screen:

mysql-install-8

When prompted to select a character set use the one that fits best, I’m using UTF-8 as the default charset.

mysql-install-9

On the next dialog you have to choose whether to install the server as a Windows service and if it shall be started automatically at boot time. This setting depends on how often you’re developing on your system. I’m keeping MySQL running in the background most of the time because it doesn’t eat that much memory.

mysql-install-10

The next dialog prompts you to select a root password. Keep this in mind.

mysql-install-11

After the installation has finished the MySQL server is already running and you can now begin to configure PHP and Apache.

Configuring Your System

For every VirtualHost (i.e. website/domain) you need to add a corresponding entry to your HOSTS file so that your browser knows that the given domain will be handled by the webserver running on your local system. Edit the file c:\windows\system32\drivers\etc\hosts with a text editor.

Windows Vista Information

On Windows Vista you have to launch Notepad as an administrator to see and edit the file.

Add a new line to your hosts file which has the following content:

1
127.0.0.1 www.webserver.local

Now requests to www.webserver.local from your browser will be sent to the webserver running on your local system.

Configuring The Apache Webserver

There are actually two files to edit. Please note that you always need to use forward slashes or a double backslash in path names.

General Settings

Open the file d:\webserver\Apache\conf\httpd.conf and search for the line reading

1
DocumentRoot "D:/webserver/Apache/htdocs"

The default document root is D:/webserver/Apache/htdocs. We now need to change this to point to the d:\webroot directory as defined above. So change this line now to

1
DocumentRoot "d:/webroot"

You also need to modify the line reading

1
<Directory "D:/webserver/Apache/htdocs">

to

1
<Directory "D:/webroot">

If you wish to use .htaccess files you also have to change the line reading

1
AllowOverride None

to

1
AllowOverride All

To include the VirtualHosts file which will contain all mappings of hostname to document root directory (and more) you have to change the line

1
#Include conf/extra/httpd-vhosts.conf

to

1
Include conf/extra/httpd-vhosts.conf

To enable automatic execution of an index.php file when the user accesses a directory (which you should always do) you need to add index.php to the DirectoryIndex directive just as in this example – simply add „index.php” to the end of the line:

1
2
3
4
5
<IfModule dir_module>

DirectoryIndex index.html index.php

</IfModule>

Creating The VirtualHosts Configuration

Open the file d:\webserver\Apache\conf\extra\httpd-vhosts.conf. Now it’s time to create a VirtualHost for our domain www.webserver.local.

Just add the following block to the end of the file.

1
2
3
4
5
6
7
8
9
10
11
12
13
<VirtualHost *:80>

ServerAdmin webmaster@example.com

DocumentRoot "D:/webroot/www.webserver.local/htdocs"

ServerName www.webserver.local

ErrorLog "logs/webserver.local-error.log"

CustomLog "logs/webserver.local-access.log" common

</VirtualHost>

This will tell Apache…

  • that the server administrator can be reached via webmaster@example.com (no need to enter your real email address, because on your own development system you’re the only one that would see your real email address so it doesn’t make sense
  • that the documents for www.webserver.local can be found in the directory d:/webroot/www.webserver.local
  • to log errors to the file d:/webserver/Apache/logs/webserver.local-error.log
  • to log every access to d:/webserver/Apache/logs/webserver.local-access.log

Creating The Documents

Create the directory D:/webroot/www.webserver.local/htdocs recursively and create the file D:/webroot/www.webserver.local/htdocs/index.php with the following contents:

1
<?php phpinfo(); ?>

Configuring PHP

The default PHP installation would not show you any errors in the browser and instead just return a 500 server error which would materialize as an empty white page.

Although this is the recommended setting for productions servers where you do not normally want to reveal any specific information like paths when an error occurs this makes life quite hard on your local development server. To enable the display of error messages in the browser open your php.ini file which is located at d:\webserver\php\php.ini and change the line

1
display_errors = Off

to

1
display_errors = On

To enable sending of emails via the mail() function you need to define a specific SMTP server name and port. You would normally enter your providers’s mail server name here. Please keep in mind that some providers use a so-called „POP-Before-SMTP” so that sending mails with PHP may fail if you have not downloaded new messages via POP3 from the server before.

Testing The Installation

Now you are ready to test your new web server. First of all you need to restart the Apache server via the included taskbar tool or via the Windows services panel.

After that open up your browser and enter http://www.webserver.local/

This should show the phpinfo() page.

And now: have fun developing!

Google Trends Gadget Reveals Interesting Weekly Search Behavior

Friday, May 22nd, 2009

Although Google Trends is nothing new embedding it on a website is. I just tried some Google Trends searches analyzing user search behaviour and some interesting  facts arose. When performing these searches you should always be aware that keywords may not have one meaning only thereby distorting the graph. So you shouldn’t use Google Trends to compare “apple” and “pear” because of the well known company named “Apple”.

The disadvantage of the Google Trends Gadget is that you cannot give a specific date for displaying statistics, only relative values so these graphs will surely look different each day you are looking at them on this page.

It’s Monday: Searching For A Doctor

It is interesting to note that these search terms have the highest search volume on Mondays and then fall off over the next days. In contrast to what one might expect there is not an even distribution over the weekdays and a lower search volume on weekends.

Weekend Priorities

As the weekend arrives other search terms dominate the search engine queries. The following graph shows some queries that show this weekend trend.
I just picked some words that came to my mind which are mostly unambiguous and have a comparable search volume.

Rather Even Distribution

As one might expect general search terms have a more even distribution over the week but a slight drop on weekends is noticeable which is somewhat expected.

Opposing Trends

Using Google Trends you can  also find somewhat opposing trends like this comparison of restaurants vs. hotels.

Browser Wars? Not Really.

This graph shows the distribution of the search queries for different browsers. With this graph you also need to keep in mind that the words “opera” and “safari” are ambiguous.

Using The Gadget For Your Own Statistics

You can of course use this information to find out when to launch specific campaigns or when to expect a higher AdWords search volume. If you want to see current statistics on Google search volumes for different keywords you can now simply create a page and embed the Google Gadget several times on that page just like I did on this page. So you don’t have to go to the Google Trends website to search for different terms one by one.

Embedding The Google Trends Gadget On A WordPress Blog

If you are using WordPress and want to embed these statistics on your blog you need to have a plugin for WordPress that enables the use of IFrames like Embed Iframe otherwise for security reasons WordPress will silently eat your IFrame code.

This is a sample code for embedding the gadget into your WordPress blog if you have installed the Embed IFrame plugin (you need to remove the space in front of the “iframe” word at the beginning and just before the closing bracket):

[ iframe http://www.gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/trends_gadget.xml&source=imag&up_is_init=true&up_cur_term=firefox,internet%20explorer,explorer,opera,safari&up_date=mtd&up_region=US 330 250 ]

tweetthis-15

Saving Link Juice With Nofollow For The “Twitter for WordPress” Plugin

Wednesday, May 20th, 2009

I have just recently enabled the Firefox Addon SearchStatus while on my blog’s homepage. I was amazed that the Twitter For WordPress plugin doesn’t add rel=”nofollow” to the My Latest Tweets widget (see on the right in the sidebar).

Therefore I have just added the corresponding code to the plugin’s PHP file and thought I should share this information because it might really be useful for other people.

Adding rel=”nofollow” to the Twitter links

First make a backup of the file wp-content/plugins/twitter-for-wordpress/twitter.php and save it as twitter.org.php in the same directory. Afterwards open the file twitter.php and modify the code as highlighted here. You need to scroll to the right to see the highlighted code:

function hyperlinks($text) {
    // match protocol://address/path/file.extension?some=variable&another=asf%
    $text = preg_replace("/\s([a-zA-Z]+:\/\/[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/i"," <a rel=\"nofollow\" href=\"$1\" class=\"twitter-link\">$1</a>$2", $text);
    // match www.something.domain/path/file.extension?some=variable&another=asf%
    $text = preg_replace("/\s(www\.[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/i"," <a rel=\"nofollow\" href=\"http://$1\" class=\"twitter-link\">$1</a>$2", $text);
    // match name@address
    $text = preg_replace("/\s([a-zA-Z][a-zA-Z0-9\_\.\-]*[a-zA-Z]*\@[a-zA-Z][a-zA-Z0-9\_\.\-]*[a-zA-Z]{2,6})([\s|\.|\,])/i"," <a rel=\"nofollow\" href=\"mailto://$1\" class=\"twitter-link\">$1</a>$2", $text);
    return $text;
}

function twitter_users($text) {
       $text = preg_replace('/([\.|\,|\:|\¡|\¿|\>|\{|\(]?)@{1}(\w*)([\.|\,|\:|\!|\?|\>|\}|\)]?)\s/i', "$1<a rel=\"nofollow\" href=\"http://twitter.com/$2\" class=\"twitter-user\">@$2</a>$3 ", $text);
       return $text;
}

After you have added the code save the file, upload it you your server and you’re done.

If you are using the WP Super Cache plugin be sure to empty the cache so that all pages are updated.

tweetthis-15

How To Create Search Engine Friendly RewriteRules For Domains

Tuesday, May 19th, 2009

Do you have multiple domains pointing to your website? From an SEO standpoint you shouldn’t have them all pointing to your document root directory because this might be interpreted as duplicate content by the search engines or you might even get a mixup of pages distributed over several domains and subdomains (like example.com and www.example.com) in the organic search results.

If you are using Apache and have access to the RewriteModule you should configure the VirtualHost like this so that all domains and subdomains are redirected to the main hostname via a search engine friendly HTTP 301 redirect:

<VirtualHost *:80>
ServerAdmin webmaster@example.com
DocumentRoot /srv/www/example.com/htdocs
ServerName www.example.com
ServerAlias example.com
ServerAlias www.example.org
ServerAlias example.org
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com$1 [L,R=301]
…
</VirtualHost>

This will redirect all requests not going directly to http://www.example.com to that hostname. So even if someone enters http://example.org/index.php the server will issue a redirect to http://www.example.com/index.php.

Of course this also works if someone links to your page with a link like http://example.com/file.gif. In that case the redirect will be issued to http://www.example.com/file.gif. Google likes that.

tweetthis-15

How To Fix The Aptana CSS View Problem On Windows Vista 64bit

Monday, May 18th, 2009

I’ve been using the free version of Aptana on Windows for more than a year now however when I switched to Windows Vista 64bit the CSS view stopped working displaying only a black box as shown below.

Aptana Studio CSS Problem on Windows Vista 64bit

Aptana Studio CSS Problem on Windows Vista 64bit

Although this bug exists since the end of 2007 it has only recently been fixed by the developers of Aptana.

The only solution to fix this problem right now is to download the alpha version of the upcoming release 1.4.

If you do not want to install an alpha version of the software you have to wait until the final version will be released or you will simply have to live with the fact. A simple workaround is to right-click on a CSS file and select to edit it with the text editor. Although you will lose all cool features like autocompletion and so on you can edit the CSS file.

PHP: Prompt The User To Download A Specific File

Sunday, May 17th, 2009

This is a function which allows you to prompt the user to download a specific file with any filename you like. This will also not render the file inline (like those direct PDF links most of us don’t like) but it will display a file dialog asking the user to either download or save the file.

I apologize for the bad code formatting but that WordPress plugin I’m using for code highlighting is driving me crazy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Prompts the user to download a file in the browser.
* Works even with IE6.
*
* @param string $path                   The file path to the file to be downloaded
* @param string $browserFilename        The name sent to the browser
* @param string $mimeType               The mime type like 'image/png'
*
* @return void
*/
function promptToDownload($path, $browserFilename, $mimeType)
{
if (!file_exists($path) || !is_readable($path)) {
return null;
}

header("Content-Type: " . $mimeType);
header("Content-Disposition: attachment; filename=\"$browserFilename\"");
header('Expires: ' . gmdate('D, d M Y H:i:s', gmmktime() - 3600) . ' GMT');
header("Content-Length: " . filesize($path));

// If you wish you can add some code here to track or log the download

// Special headers for IE 6
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');

$fp = fopen($path, "r");
fpassthru($fp);
}

Here is how to use the function:

1
promptToDownload(dirname(__FILE__).'/info.pdf', 'download.pdf', 'application/pdf');

The first parameter is the path to the file to be downloaded, the second is the name of the file as the user’s browser shall display it. The third parameter is the MIME type of the file. Here is a list of many MIME types.

Security Warning!

Never use any path provided directly by the user. You should never write something like this:

1
promptToDownload($_GET['path']'download.pdf', 'application/pdf');

This would allow the user to download arbitrary content from your server, even files like /etc/passwd!

So instead of using code as shown above you should put all of the files you are making available for download into one directory and only use the filename itself as a parameter like this:

1
promptToDownload(dirname(__FILE__).'/files/'.basename($_GET['file'])'download.pdf', 'application/pdf');

Internet Explorer 6 Problems

When using the code above and your PHP file is named download.php Internet Explorer 6 may not use the filename download.pdf but show “download.php” instead so it might be useful to use an Apache RewriteRule so that the browser sees a .pdf file extension instead. But this should only be a problem for you if you still want to support an outdated and insecure browser.

tweetthis-15

Why WolframAlpha Should Hire An SEO

Sunday, May 17th, 2009

Although my first look at WolframAlpha was rather disappointing I didn’t really intend to show everything that’s not working as I had expected. However I stumbled upon problem after problem.

Now I didn’t intend to write this article at all but just searching for what Google has already indexed of WolframAlpha and following some links made it clear that they obviously didn’t think about SEO at all prior to launching their site.

The problem is: they are doing many things that  might actually harm their Google rankings that are just beginning to show up. We don’t yet know who will be using WolframAlpha in two months, if it will grow to become something that most of the people will use  just like Google or if it is going to fail like WikiaSearch.

Remember: they received over 1000 links to their site within two days and this is likely to grow so it makes sense to optimize the site now to prevent damage.

So from a logical point of view if I had been responsible for the WolframAlpha website I would not have done any of the following that WolframAlpha has implemented:

  • You Should Prevent No-Result Pages From Being Indexed
    “no result” pages return an 200 HTTP status code, not a 404 – Google will likely index these pages. The page doesn’t contain any META robots tag containing “noindex,follow” either.
    Because the differences between different “no result” pages depending on the query are only marginal this might be seen as duplicate content which you should never have on your own site.
  • Don’t Use Redirects For Loadbalacing
    Using the search field on the homepage now redirects via a 302 redirect to a hostname like “www18.wolframalpha.com” leading to even more duplicate content if Google indexes the same page with two different hostnames, e.g. www18 and www76. Normally you would be using a loadbalancer and not use HTTP redirects to distribute the load. They should at least be using the canonical tag to tell Google the original URL, but they aren’t, regretfully.
  • Use A Robots.txt File
    WolframAlpha is currently not using a robots.txt file so they are not telling search engines what should not be indexed.
  • Optimize The Clickthrough Rate In The SERPS
    The result pages do not contain a META description field which I would recommend for a higher click-through rate in the organic search results.
  • Use Text To Display Text, Not Images
    The title tag could also be optimized but I still don’t understand why even simple text is rendered as an image.

What do you think?

tweetthis-15

Get Info On Domains With WolframAlpha

Saturday, May 16th, 2009

Did you know that WolframAlpha allows you to get info on specific websites and domains?

It’s quite easy as you just need to enter the domain name into the search field. Most of the data seems to have been retrieved from Alexa but it’s still a great idea. I still don’t understand the HTML element hierarchy graph but it looks interesting. However I don’t know what the tag information could be used for.

The following image shows the info WolframAlpha shows currently for this blog. And I think I need to say that the number of visitors is a bit far off ;-)

WolframAlpha Sascha Kimmel