Archive for the ‘Programming’ Category

PHP Memcached Manager

We’ve been using memcached on both our sites for a while now to help alleviate database load and speed things up in general.

However, we’ve been lacking a good web-based manager to see the cache status and manually clear the cache.  (I’ve been doing this via telnet on the command line and have been to busy to write my own script…..)

Today, I stumbled accross this gem: http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/

It’s a simple GUI for memcached that is written in PHP and was exactly what I was looking for!

Javascript: Timer object

So, yesterday I was working on the UI for our category menus and needed a delay before displaying the menus.

Basically, I wanted to only show the dropdown menus if the user pauses the cursor over the menu in question.  To do this, I needed a timer object that I could start when the user first places the cursor over the menu title and cancel if they move on to quickly.

If you’ve ever used the setTimeout() and clearTimeout() functions that Javascript provides, you know that they don’t always work as advertised.  Especially when many are called very rapidly (as in the case of the user moving the cursor from one side of the screen to the other).  Using just these functions gave us some weird behavior (i.e. menus displaying when they shouldn’t).

To solve the problems we encountered, I created a timer object (sorely lacking in Javascript) that tracks its state so that it more reliably executes and cancels.

Below is the code for the object (requires prototype):

var timer = function(delay, callback){
    this.isRunning = false;
    this.hndl = null;
    this.delay = 0;
    this.callback = null;

    this.start = function(){
        if(!this.isRunning){
            this.hndl = setTimeout(this.callBackFunc.bind(this), this.delay);
            this.isRunning = true;
        }
    };

    this.stop = function(){
        if(this.isRunning){
            clearTimeout(this.hndl);
            this.hndl = null;
            this.isRunning = false;
        }
    };

    this.setDelay = function(d){
        this.delay = d * 1000;
    };

    this.setCallback = function(c){
        this.callback = c;
    };

    this.callBackFunc = function(){
        if(this.isRunning){
            this.isRunning = false;
            this.hndl = null;
            eval(this.callback);
        }
    };

    this.setCallback(callback);
    this.setDelay(delay);
};

You use it by creating a new instance of timer and calling the instance’s start() method for every action you want to delay.

Below are Parameter descriptions:

  • delay: how long to wait before running the callback code (in seconds)
  • callback: a string of Javascript code to execute after the delay

Example:

    <div onmouseover="myTimer = new timer(0.5, 'myfunction(5, 6, 7)'); myTimer.start();" onmouseout="if(myTimer){myTimer.stop();}">
        Some content
    </div>

The above code will start the timer when the user places the mouse over the div and cancel the action if the user moves the mouse out of the div before the timer has fired.

Javascript: Copy Text to Clipboard – Not anymore

In a previous post (Javascript: Copy Text to Clipboard), I described a method for using Javascript to copy text to a user’s clipboard.

Unfortunately, this method no longer works.  It relied on flash allowing script access to the user’s clipboard, and (with the release of flash 10) that is no longer the case.

Flash 10 requires that a user’s action originate in flash in order to gain access to the clipboard.  This means that IE is now the only browser that can access the clipboard from Javascript.  So unless IE is the only browser you care about, you’re out of luck using Javascript to access the clipboard. :(

The solution?  Write a flash application to handle copying data to the user’s clipboard.

PHP Alternative Syntax

So, I was having a discussion with a fellow developer at work today about the advantages of using PHP’s alternative syntax (details here).

Just so we know where everyone’s coming from, I come from a programming background and my colleage comes from a design background.

Anyway, he came to me asking my opinion on using the alternative syntax in scripts where we have a lot of HTML markup mixed in with the PHP code.  His reasons for wanting to do this?  The same as most proponents for using the alternative syntax…….it’s shorter and is easier to read.

Now I try to be impartial when making coding decisions because, let’s face it, our opinions do not affect how the machines execute our code.  It’s a travesty, but it’s true.  However, I just don’t agree that alternative syntax makes code shorter or easier to read.

Wait, wait.   Give me a chance to demonstrate my reasoning before you condem me.

Let’s look at some example code using the alternative syntax:

<p>What a niffty paragraph</p>
<?php if($a == $b): ?>
<p>Only the cool people see this!</p>
<?php endif; ?>
<p>Wow, aren't paragraphs great?</p>

Now, you might say, “this is super awesome. it’s so easy to see where the if block ends and there’s no separate lines for the PHP start and stop tags.”

However, you can do the same thing with less typing in the normal syntax.

Here’s the same code using the normal syntax:

<p>What a niffty paragraph</p>
<?php if($a == $b){ ?>
<p>Only the cool people see this!</p>
<?php } ?>
<p>Wow, aren't paragraphs great?</p>

As you can see, the normal syntax is shorter than the alternative syntax.  The number of lines are the same, but the number of characters is less.  Multiply this character difference by the number of times you use if, while, for, and switch in your script and you have a noticeably larger script file when using alternative syntax.  Which means?  Yep, it takes longer to execute scripts that use the alternative syntax than scripts that use the normal syntax.  Is this execution time difference big enough to matter?  Well, that’s a personal question that each script owner must answer for themselves.

And as for the readability aspect, any developer that is worth their salt uses an editor that highlights or otherwise shows matching braces.  Want to know where the other one is?  Just click on the one your curious about and the editor will show you the other one.

It is my experience that code is hard to read because the person who wrote it did  not format it properly.

Anyway, that’s just my opinion.  I’m sure everyone else has their own.  Please feel free to discuss.  Who knows, maybe you’ll change my mind ;)

Javascript: Copy Text to Clipboard

Update: this method no longer works.  For details: http://cthayer.wordpress.com/2009/02/26/javascript-copy-text-to-clipboard-not-anymore/

So, today we’re thinking that our users could benefit from some areas of our site auto-copying text to their clipboards so that they can just click and paste instead of copy, click, and paste.

IE has the handy window.clipboardData object which allows javascript direct access to the clipboard.  However, Mozilla/Firefox disables this functionality by default because of security concerns.  So, while the IE method works in Safari and Opera, it fails in Mozilla/Firefox and therefore we needed another way.

Turns out that while javascript is not allowed to access the clipboard, flash is.  So, by using flash and a little ajax magic you can create a copyToClipboard function in javascript that works in all browsers that support flash and ajax.

This code is posted on the web in many places and in this case it came from here:


function copyToClipboard(text) {
	var flashId = 'flashId-HKxmj5';

	/* Replace this with your clipboard.swf location */
	var clipboardSWF = 'http://appengine.bravo9.com/copy-into-clipboard/clipboard.swf';

	if (!document.getElementById(flashId)) {
		var div = document.createElement('div');
		div.id = flashId;
		document.body.appendChild(div);
	}

	document.getElementById(flashId).innerHTML = '';
	var content = '<embed src="' +
	clipboardSWF +
	'" FlashVars="clipboard=' + encodeURIComponent(text) +
	'" width="0" height="0" type="application/x-shockwave-flash"></embed>';

	document.getElementById(flashId).innerHTML = content;
}