on Sep 20th, 2008PHP Templating in 5.3+

So, if you read my last post about pQuery you’d be familiar with me working on a way to enhance the PHP templating “experience”. I wasn’t very happy with how pQuery-0.1 turned out in the end as it’s way to bulky to split it up in several files, so I started glancing at PHP5.3 and what I could (ab-)use closures for. The technique I came up with borrows the DOM-hierarchy from pQuery but allows you to embed the layout code inside the templates, without mixing it with HTML.

How is this achieved? Well through a combination of some of PHPs lesser known features, namely:

  • The ability to return things from included files with the syntax $result = include 'file.php'; if you have a return statement in your include file.
  • If you have php-tags in the top of an XML-file it’s interpreted by the xml parser as a part of the xml document in the same way that is, but is ignored.
  • Closures in PHP5.3

So, let me give you a “small” template example, and let me explain how it works.

<?php
return function($tree, $data) {

	$tree->root->body->ul[1]->li->loop($data, function($tag, $item) {
		$tag->h2->text = $item['title'];
		$tag->p->text = $item['body'];
		$tag->span->em->text = sprintf($tag->span->em->text, $item['date']);
		$tag->span->em->a['href'] = "mailto:".$item['author']['email'];
		$tag->span->em->a->text = $item['author']['name'];

		// If empty, remove ul-list + h3 tag comment header
		if(empty($item['comments'])) {
			$tag->ul->remove();
			$tag->h3->remove();

		} else {
			$tag->ul->li->loop($item['comments'], function($tag, $item) {
				$tag->h4->text = $item['title'];
				$tag->p->text = $item['body'];
				$tag->span->em->text = str_replace(array_keys($item), array_values($item), $tag->span->em->text);
			});
		}

	});
}
?>
<html>
	<head>
		<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
		<title>example</title>
	</head>
	<body id="example" onload="">
		<include file="menu.html" />
		<ul id="post-list">
			<li>
				<h2></h2>
				<span class="small-text block">
					<em>
						Posted %s by
						<a href=""> </a>
					</em>
				</span>
				<p></p>
				<h3>Comments</h3>
				<ul>
					<li>
						<h4></h4>
						<span class="small-text block"><em class="test">Posted date by name</em></span>
						<p></p>
					</li>
				</ul>
			</li>
		</ul>
	</body>
</html>

The closure at the top gets fed (as the first argument) the DOM hierarchy of the HTML template below the PHP tags and is then free to modify it however it sees fit, please note that the bulky assignment syntax used with both str_replace() and sprintf() is just there until I have time to put in a better already working version of it.

The jQuery-style syntax works pretty much the same way, allowing it to be extended with custom plugins (the loop()-method call you see in the php-section is a default plugin I wrote).

This approach allows you to both keep the layout and layout-code together in one file, but still separating them so you don’t have to deal with that spaghetti-mess that PHP is so well known for.

If you want to check out the code and play around with it, here’s the .zip-file just zip it up somewhere and check out example.php + example.html in your favorite editor, and of course the rest of the source if you want to, but remember - this requires php5.3-alpha.

on Sep 20th, 2008Setting up mod_wsgi for apache on Windows

I just installed mod_wsgi on my windows (yeah yeah, I know…) laptop, it turned out to be amazingly easy but I figured I’d put up notes on how to do it here anyways.

  • Head over to http://adal.chiriliuc.com/mod_wsgi/ and fetch the latest (at the time of this writing it was revision_1018_2.3) apache module for your combination of python/apache
    • mod_wsgi_py24_apache20 is for Python 2.4 and Apache 2.0
    • mod_wsgi_py24_apache22 is for Python 2.4 and Apache 2.2
    • mod_wsgi_py25_apache20 is for Python 2.5 and Apache 2.0
    • mod_wsgi_py25_apache22 is for Python 2.5 and Apache 2.2
  • Save the mod_wsgi.so file into your apache modules directory, for me it was located in C:\Program Files\Apache Software Foundation\Apache2.2\modules
  • Create a directory somewhere outside of your webroot that will host your mod_wsgi-application, for simplicity’s sake I choose C:\wsgi
  • Locate your httpd.conf-file and open it up in a text editor, it’s usually located in the conf-directory of your apache installation, for me it was: C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf
  • Do a search for “LoadModule” and you’ll get a block of LoadModule-statements, put this on its own line there: LoadModule wsgi_module modules/mod_wsgi.so so it looks something like this:
    #LoadModule usertrack_module modules/mod_usertrack.so
    LoadModule version_module modules/mod_version.so
    #LoadModule vhost_alias_module modules/mod_vhost_alias.so
    LoadModule wsgi_module modules/mod_wsgi.so
  • Now find the <Directory> block for your web-root, for me it was: <Directory “C:/Program Files/Apache Software Foundation/Apache2.2/htdocs”>, under it add this block:
    WSGIScriptAlias /wsgi “C:/wsgi/handler.py”
    
    <Directory “C:/wsgi”>
            AllowOverride None
            Options None
            Order deny,allow
            Allow from all
    </Directory>

    Notice that the two bold sections point at where I created my application directory so if you didn’t choose C:\wsgi you need to change this to reflect whatever directory you chose, the /wsgi part of the just before the first bold statement is the apache alias we want to use for our wsgi application - which in this case will be /wsgi also. Also note the use of forward instead of backwards slashes even when on windows.

  • The observant reader might’ve noticed the /handler.py at the end of the first bolded statement in the bullet point above, this is our handler script / entrypoint into our application. So add this code to handler.py and put it in C:\wsgi

    def application(environ, start_response):
        status = '200 OK'
        output = 'Hello World!'
    
        response_headers = [('Content-type', 'text/plain'),
                            ('Content-Length', str(len(output)))]
        start_response(status, response_headers)
    
        return [output]
    
  • Now just restart apache and go to http://localhost/wsgi and enjoy the beautiful world of python web development

on Sep 20th, 2008Javascript-OO & Python-DuckTyping in PHP5.3

With the introduction of closures in PHP5.3 my mind has been working a lot trying to find new (ab-)uses for them, first out is a combination of javascript and python oo - honestly this object model is nicer then the standard PHP one.

This allows for changing objects methods during runtime, proper duck-typing, monkey-patching and a lot of other fun stuff only available in javascript/python/ruby normally.

Instance variables, class-variables, etc. it’s all there.

<?php
class MethodException extends Exception {}
class ObjectType {
	function __call($name, $args) {
		if(isset($this->{$name})) {
			array_unshift($args, $this);
			return call_user_func_array($this->{$name}, $args);
		} else {
			throw new MethodException($name);
		}
	}
}

$obj = function() {
	static $say_hi_counter = 0; // Static "class variable" for $obj-type
	$self = new ObjectType;
	$self->name = null;
	$self->say_hi = function($self) use(&$say_hi_counter) {
		echo "Hi, my name is: ", $self->name, " ", ++$say_hi_counter, "<br>\n";
	};

	return $self;
};

$foo = $obj();
$foo->name = "Foo";
$foo->say_hi();

$newobj = function() use($foo) {
	$self = clone $foo;
	$self->say_goodbye = function($self) {
		echo "Goodbye sir<br>\n";
	};
	return $self;
};

$bar = $newobj();
$bar->say_hi(); // Since $foo is it's "superclass" it will say Foo by default
$bar->name = "Bar";
$bar->say_hi();
$foo->say_hi(); // Still says Foo
$bar->say_goodbye();

$baz = clone $bar; // Create a sibling of bar
$baz->name = "Baz";
$baz->say_hi();	// Baz
$bar->say_hi(); // Stil bar, we changed one of its siblings

/*
Allows for python-style duck-typing
saving failed method calls
*/
try {
	$foo->say_goodbye(); // Fails with a "MethodException", $foo doesn't have say_goodbye();
} catch(MethodException $exc) {
	echo "Foo can't say goodbye<br>\n";
}

on Sep 19th, 2008Styled checkboxes & radiobuttons with jQuery

Updated

  • Added support for hover, mousedown events
  • Merged radize into checkize, so only call checkize from now on
  • Pre-loads images
  • Added support for “show_input” that will display the input boxes also (in FF&Safari, only input boxes in IE) - useful for debugging.

So, time for another small jQuery extension I wrote up - for myself this time, it’s for styling check boxes and radio buttons, all in all it’s *very* self explanatory and I don’t see much point in trying to describe it, usage is very simple:

$(document).ready(function(){
	$("input").checkize({
		checked:"images/checked.gif",
		checked_down:"images/checked_down.gif",
		checked_hover:"images/checked_hover.gif",

		unchecked:"images/unchecked.gif",
		unchecked_down:"images/unchecked_down.gif",
		unchecked_hover:"images/unchecked_hover.gif"
	});
});

Live demo here: http://totmacher.eu/jquery/radio/demo/
Source as text: http://totmacher.eu/jquery/radio/src/jquery.checkize.js
Download example code + source in one .zip-file: http://totmacher.eu/jquery/radio_v0.2.zip

Enjoy!

on Sep 19th, 2008Selenium Video

If you don’t know what Selenium is, you really should check it out - a good introduction is this video put up on railscasts.com: http://railscasts.com/episodes/116-selenium while parts of it is rails-specific it’s a nice introduction to what Selenium is and what it can do for you.

on Sep 18th, 2008PHP 5.3 and closures

<?php
function test() { return function() { echo "foo"; }; }
test()(); // fails
$func = test(); $func(); // works

Why, oh why!

on Sep 17th, 2008jQuery / Javascript - Customizeable Ajax pageination

Download: http://totmacher.eu/jquery_pageinate/jquery_pageinate_v0.1.zip (I forgot to add the download link at first, my bad).

So another jQuery/Javascript request came up from the same irc-channel - this time it’s about Ajax pagination. As with my last example the “serverside” of things is simulated with two .php-files (posts.php, server.php). The pagination is *very* customizable through the use of callbacks.

Live example: http://totmacher.eu/jquery_pageinate/client.html

Important files

  • pageinate.js- The pageinate jquery plugin
  • functions.js- Example dom-ready event that shows how to set it up

Not-so important files

  • client.html - the client example
  • server.php - returns a json string with page count and posts to be displayed
  • posts.php - simulates a return result from a database or something
  • jquery.js - jquery itself, needed for pageinate to run

on Sep 17th, 2008pQuery - Messing with the DOM from PHP

You can download the complete source-code + example here

So, this is a small pet-project I managed to get running with a decent API last night, it’s YAPTE (Yet Another PHP Templating Engine), but bare with me for a few minutes. My huge gripe with using PHP as a template language, embedding it within the html, is that it gets messy - quick. For small examples or limited real world usage it’s fine, but for large projects with complex views? No way.

But, I don’t want to create another template language a´la Smarty that basically just emulates a crappier (none thought that would be possible, huh? ;p) version of PHP. So my two main goals when designing the idea for pQuery in my head were these:

  • I want to use PHP to format, and output, my data.
  • I don’t want to mix PHP with (X)HTML, at all.

The result is, in lack of good imagination, for now named “pQuery” a homage to jQuery. At the moment the code is about 250 lines and the functionality is fairly limited. Let’s take a quick peek at an example template:

Example on a couple of different ways to push data into the template

<html>
	<head>
		<meta name="keywords" content="" />
		<meta name="description" content="" />
		<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
		<title></title>
		<script type="text/javascript" charset="utf-8">
			//<![CDATA[
			var annoy = function(){
				alert("Annoying...");
			}
			//]]>
		</script>
	</head>
	<body>
		<ul id="post-list">
			<li>
				<h2></h2>
				<span class="small-text block">
					Posted %date by
					<a href="mailto:%s"></a>
				</span>
				<p></p>
				<h3>Comments</h3>
				<ul>
					<li>
						<h4></h4>
						<span class="small-text block">
							<em>Posted date by name</em>
						</span>
						<p></p>
					</li>
				</ul>
			</li>
		</ul>
	</body>
</html>

And here’s how you’d fill it with data:

<?php
require 'pquery/parser.php';
$posts = include 'example_posts.php';

$p = new pQuery_Parser;
$html = $p->parse_file("example.html");
$html->head->title = "Demo of pQuery-0.1";

list($keywords, $description) = $html->head->meta;
$keywords["content"] = "php, html, separation";
$desription["content"] = "pQuery is just a pre-alpha release";

foreach($html->body->ul->loop($posts) as $items) {
	list($li, $post) = $items;

	$li->h2 = $post['title'];
	$li->p = $post['body'];

	$li->span->a = $post['author']['name'];
	$li->span->a->attr_format("href", array($post['author']['email']));
	$li->span = array('%date' => $post['date']);

	foreach($li->ul->loop($post['comments']) as $items) {
		list($li, $comment) = $items;

		$li->h4 = $comment['title'];
		$li->p = $comment['body'];
		$li->span->em = $comment;
	}
}

echo $html->render();

This allows you to keep the layout(template), presentation-logic(view), control-logic(controller), business-logic(model) 100% separate, although the view-layer probably should be split into two separate layers also, but that’s a topic for another post.

It would be great with some feedback on this, there are some parts of the syntax I’m not to happy about right now (for example the attr_format() function to printf() data into attributes) so there’s room for a lot of improvement. This is in no way production ready code, it was thought out over a couple of hours and written down in the same time.

For all my Python readers out there I have a working python Prototype built on top of cElementTree, but it’s not 100% functional yet so I decide to hold onto it for now.

Also, the above PHP version has no way to select elements based on css-selectors, a selector-engine prototype engine is in the works, but I need more spare time.

on Sep 12th, 2008jQuery / Javascript autocomplete checkbox-selection with memory

Edit: Fixed a small bug that would cause it to fetch to many results on slow connections, demo6.zip

So yeah, a messy title on this post - but I couldn’t really find a good way to explain this. It’s just an example I wrote up for a mate on IRC that asked for “an auto-complete Ajax widget that allows you to check auto-completed values and keep typing, remembering the ones you already checked”.

Code here: demo6.zip
Live Demo:http://totmacher.eu/upload/client.html (three characters minimum and 400ms delay)

Since it’s a few lines of code I’m only posting the javascript-code here, for the complete example I’ll post a .zip-file instead of linking it directly. Zip it up somewhere on a PHP5+ web-server and go to client.html.

Of course it won’t auto-complete anything, this is just the javascript/client-side of things, the server.php script just returns my three names and the value you put in a json string.

$(document).ready(function(){

	last_press = (new Date()).getTime()
	char_limit = 3
	delay = 300
	counter = 0
	input = $("#input")
	list = $("#list")

	do_update = function(check) {

		// Only fire one event, ever
		if (check != last_press)
			return

		// Only update the list if "delay"-milliseconds have passed and
		// the input length is greater then or equal to "char_limit"
		if ( ((new Date()).getTime() - last_press) > delay && input.val().length >= char_limit) {

			list.find("li").each(function(i, element){
				li = $(element)

				// If the checkbox in this list item isn't checked
				if(!li.find("input").attr("checked")) {
					li.remove()
				}
			})

			$.getJSON("server.php", {"value":input.val()}, function(result){
				for each (value in result) {
					// Create a new list item
					item =  $("<li></li>")

					// The checkbox, assign a unique id to it
					checkbox = $("<input type='checkbox'></input>")
								.attr("name","selected[]")
								.attr("value", value)
								.attr("id", "checkbox_"+(++counter))

					// Label that allows us to click on the text also
					label = $("<label>"+value+"</label>")
							.attr("for", "checkbox_"+counter)

					// Append the checkbox and label to the <li>-item
					item.append(checkbox)
					item.append(label)

					// Append the <li>-item to the <ul>-list
					list.append(item)
				}
			})
		}
	}

	input.keyup(function(){
		last_press = (new Date()).getTime()
		setTimeout("do_update("+last_press+");", delay+100)
	})

})

on Sep 12th, 2008Generic dispatching in python

Edit: I figured this had to have been done by someone at some point in the python community, i was right: http://pypi.python.org/pypi/simplegeneric. Very nice implementation indeed, go check it out if you like what you see here.

So, a bit more black-magic in python - this time implementing generic dispatching / functions, or at least - yet again - a simple proof of concept.

class Generic(object):
    def __init__(self):
        self.func_list = []

    def __call__(self, *args, **kwargs):
        result = []

        for check, func in self.func_list:
            try:
                if check is None or check(*args, **kwargs):
                    result.append(func(*args, **kwargs))
            except TypeError:
                pass

        return result

    def attach(self, func, check=None):
        self.when(check)(func)

    def when(self, check=None):
        def inner(func):
            self.func_list.append((check, func))
            return self

        return inner

if __name__ == "__main__":
    prnt = Generic()

    @prnt.when(lambda string: string == "fredrik")
    def _(string, times=1):
        print "my name "*times

    @prnt.when(lambda string: string == "holmstrom")
    def _(string, times=1):
        print "my surname "*times

    @prnt.when(lambda string, times: string == "holmstrom" and times == 2)
    def _(string, times):
        print "my surname "*times

    def _():
        print "foo bar baz"

    prnt.attach(_, lambda: 1==1) # silly, will always pass

    prnt("holmstrom", times=2)
    prnt("fredrik")
    prnt()

Yet another reason, why I love Python.