25 Aug

jQuery maskImage plugin

I had a need today to write some code which involved masking one image with another, dynamically.

There is no simple way to do this in JavaScript. The nearest I came to finding working code online that does it was edge.js, but that’s not free.

So, I wrote my own.

demo

Download: zip (25k), bz2 (24k)

In the demo, what’s happening is that an image such as this:

is being used as a mask for another image:

to create a masked image:

For Firefox and Chrome and other recent browsers, it works using pure JavaScript (even works on the iPhone).

For Internet Explorer (sigh) you need to do a little bit of server-side setup.

Basically, on the server-side, make sure you have PHP installed, with the iMagick extension, then make the ‘cache’ directory writable by the server.

To use, insert an image into your document:

<img id="image-id" src="an-image.png" alt="" />

And then apply the mask using jQuery:

$('#image-id').maskImage({src:"the-mask.png"});

Simple, innit! That’s a few hours of my own life dedicated to saving a few minutes of yours 😉

13 Aug

new API for WebME

As I said in the last post, an API would be required to make the system more testable and more consistent.

I started straight away and wrote up something quickly. Over the next week, it solidified into something that appears to cover any needs that I have.

So here’s how the API works:

Requests are sent to a URL which is generated like this:

/a
[/p=plugin-name]
/f=function-name
[/other-parameters]

The plugin name is optional. Leaving it out means you want to call a core function.

Parameters can be added by adding /key=value pairs to the URL.

An example URL might be this:

/a/f=login/email=kae@verens.com

Sending that, with a POST parameter for the password, will log me in.

To log out, I can use this URL:

/a/f=logout

Simple!

Function Names

mod_rewrite is used to direct a request through a script which tears the URL apart into parameters.

If a p parameter is given, the function is named after the plugin, rewritten to match the WebME coding standard.

For example, if the URL is /a/p=comments/f=editComment, then the “comments” part is rewritten as Comments, and ‘_’ and “editComment” are appended to form the function name “Comments_editComment”, which is called and the result returned to the browser.

For double-barrel plugin names, such as “image-gallery”, the name is rewritten to “ImageGallery”.

If no p parameter is given, then the request is a core function, and “Core_” is prepended to the function name.

For example, the login URL above, /a/p=login calls the function Core_login.

If a function name begins with “admin”, it is an admin function (see below for more on this).

File names

If no plugin name is supplied, then the core API file, /ww.incs/api-funcs.php is loaded. This contained common API functions that might be used by any core script or plugin.

If a plugin name is supplied, then the API file is expected to be located at /ww.plugins/plugin-name/api.php for common functions, and /ww.plugins/plugin-name/api-admin.php for admin functions.

For core functions, common functions are at /ww.incs/api-funcs.php and admin functions are at /ww.incs/api-admin.php

Security things

Having a central point for RPC means that we can apply security rules in one place and know that they cover all scripts. Before-hand, I would sometimes come across scripts and realise that they were open for abuse if someone knows that magic URL incantation. I would silently curse myself or whoever had written the script and fix it up. Now, though, having one single point of entry means I can secure everything at once.

If a function name starts with “admin”, then the script checks to see if the user is logged in and is a member of the administrators group. If not, the API will return an error. It’s as simple as that!

Of course, this doesn’t stop abuse by people that are logged in as admins or who are victims of XSS, but it helps stop a few problems caused by developers not noticing their scripts were open to use by anyone at all.

Conclusion

So now, when people are creating new plugins for WebME, the following could be used as a bare-bones directory structure:

/ww.plugins/plugin-name/plugin.php    details, server-side functions
/ww.plugins/plugin-name/api.php       common RPC functions
/ww.plugins/plugin-name/api-admin.php admin RPC functions
/ww.plugins/plugin-name/admin.js      admin scripts in JS
06 Aug

testing KV-WebME

I’ve been working on my CMS for about 10 years. It’s monstrously huge (41,000 lines, not including external libraries), and for most of those 10 years, I’ve been too busy building it to concentrate on niceties such as comments, testing, code formatting, etc.

This has caused problems in the past. As most programmers know, when you change any one thing, it has a ripple effect and can break things in places that don’t seem obvious at all.

Recently I’ve been remedying this. I’ve been religiously using PHPCS to make sure my code is neat and consistent, and I’ve started writing a test suite.

The most difficult part of the testing is that the CMS is composed of many separate technologies. If it was just a plain old HTML and PHP application, then PHPUnit would be enough, or maybe Selenium.

The problem is, though, that the system uses a large amount of AJAX – especially in the administration areas. No single testing system would do it all.

Another problem has to do with AJAX itself. In jQuery, you can speak to the server by writing something like this:

$.post('/a/server/script.php', {
  "id": 2
}, function(res) {
  // do stuff
}, 'json');

This makes it incredibly simple to speak to any server-side script at all on the server, and promotes it. It becomes tempting when writing new functionality to build new server-side scripts specifically for the new client-side stuff.

This has the effect that there is no single point for RPC (remote procedure calls) which can be tested, making it very difficult to be sure you have covered all potential problems.

To help solve this problem, I’ve recently started converting WebME’s coding style so all RPC is done through a single API (application programming interface) script.

This has a few extra effects which are beneficial:

  • Having a single point of entry into the system makes it easier to secure it.
  • Having an API promotes the construction of a solid method of adding functionality to it – there’s no need to start from scratch anymore, potentially building disparate scripts that are hard to abstract. Instead, it’s now easy to force the code to match a minimum spec.
  • APIs tend to have specific rules for how parameters are passed into it, making it easier to remember what the right parameters are when writing new client-side code. Also, it makes it easier to “guess” what the right parameters are if you’ve forgotten.

The main benefit, though, is that it makes it much easier to test. The URL of the API always stays the same, and the only thing that changes is the parameters sent to the URL. Previously, each separate script would have a different URL and could have any parameter scheme at all.

So, currently, I’m writing tests that use the API directly, speaking to the server directly through URL calls. After I’ve finished writing all of those (hah! if ever), I can get on to testing that JavaScript.

31 Dec

2010

I’ve the most awful memory.

While trying to remember what the hell I’d done in the last year, I came up with nothing.

Luckily, I have a spare brain in the form of my facebook friends, who came up with this list for me:

  • I started a new company, KV Sites, which will be up and running properly within a month or so, and will be selling affordable CMS websites and programming.
  • I got grade 2 in piano. I’m still waiting for an examiner for grade 3 (which I wanted to do in September). I’ll be doing grade 4 in March.
  • I got my first grading in Genbukan Ninjutsu.
  • I finished another book, CMS Design using PHP and jQuery. I hope it is as well-received as the previous book, jQuery 1.3 with PHP. btw, Packt would like me to remind people that the book “Mastering phpMyAdmin […] for effective mysql management” (reviewed here and here) has been updated to version 3.3.x.
  • I am building up to a new release of my CMS, WebME, which, despite the last downloadable version being from early 2009, has actually been very actively updated. It should be ready for release tomorrow, right on time for 2011!
  • I wrote and released two jQuery plugins: k3dCarousel, and SaorFM (which I hope to vastly improve in 2011).
  • I also built a first attempt at a clavichord made from plywood. I’ve got some new tuning pegs and redesigned the keyboard, so will hopefully be able to record on it soon.

I’m hoping 2011 turns out to be awesomer and that my head will be able to remember it all!

16 Nov

jQuery stars plugin

I was asked to replicate a “star” effect, where stars appear in various areas around a page and then disappear after a while. I won’t bother linking to the original site as it will be gone shortly, but this is what I came up with:

demo

To use this on your own site, simply download the script, link to it in your page, then add this piece of JavaScript.

$('body').stars();

If you want to use the star image I created, download it to the same directory and tell the plugin where it is:

$('body').stars({
  "i":"stars.png"
});
20 Oct

clavichord fretting

My clavichord project stalled when I realised it was just not going to work the way I’d done it.

This is partly because I’d naively gone for the full un-fretted design in the beginning, then later realised this would put too much pressure on the cheap bodywork and cause it to implode.

Changing the design afterwards to a fretted design wasn’t going to work either, because of how the keys were laid out.

So, the new plan is to rebuild the keyboard on the current clavichord, and hopefully get the thing finished as a triple-fretted, single-strung design.

Now, to explain…

If you have one string per note, this is called “unfretted”. In this design, every string is only ever hit by only one key.

The usual way to design a clavichord is “double-strung”, this means that every note actually has two strings for it. This makes double-strung clavichords louder than single-strung clavichords, because the combination of the two strings’ waves tends to alternately strengthen and dampen what’s happening at the soundboard.

Back to fretting – consider a guitar. Despite only having six strings, a guitar can play many more than only six notes. This is accomplished by “fretting” the strings. When you play a “G” on an “E” string, what happens is that you are shortening the wavelength of the overall string (with the fret and your finger), causing it to play a different note (G) than it would play if it was unfretted (E).

With a clavichord, the very act of striking the string with the key (or “tangent”, as the striking edge is called) causes fretting. The strings are damped at the ends with cloth or felt so when the key is not touching the string, the string doesn’t vibrate.

When you design your keyboard to multi-fret the strings, you need to do some calculation – let’s say you have a note, C, which is struck on the strings 100cm (let’s say) from the bridge. If your fretting involves the C# hitting the same string, then that key’s tangent must hit the string at about 94.4cm.

This is quite a small distance between the two tangents (5.6 mm), meaning that if you decide to triple-fret all your notes, then the keys for the high notes will be very close together, and the lower notes will be further apart (lower notes have larger wavelengths, so the distance between semi-tone frets increases as well as you get lower).

That explains the following image (a double-strung, triple-fretted clavichord – click for a larger image):

Note that the keys are all squashed together on the right side where the high notes are, and the spaces gradually increase as you move further left.

Notice as well that at the extreme left, the increase in spacing stops and all the keys are together again.

The reason for this is that when the notes get too low, there’s simply no more room for multi-fretting, so instead, the lower notes are all one per string.

There’s one more point to make about the keys.

Let’s say you create a key, which has its tangent 25cm from the fulcrum (a clavichord key is a lever). When the key is pressed, the tangent arcs up and strikes the string. It is still 25cm from the fulcrum in a 3D sense, but when measuring x/y from a top-down view of the clavichord, if the string is 4cm above the tangent (with key at rest), then the tangent strikes the string about 22.5cm from the fulcrum.

This must be taken into account when you design where the strings will contact the bridge and the hitchpins, as getting this wrong will cause the tangents to miss. Yes, you could just place the tangents after doing the strings, but my goal here is to be as perfect as possible. (there’s also the added problem that the tangent’s top is a certain height (3cm, say) above the level of the fulcrum, but you get the picture)

I’ve explained some of the problems to do with designing a fretted keyboard and string layout. Now, I’m off to write a program to design one automatically!

07 Oct

jQuery k3dCarousel plugin

I needed a “3D” carousel to rotate images. The currently available jQuery plugins for this purpose were either too large, too restricted (showing only 4 at a time is not good enough), or too old (not working in jQuery 1.4+).

So I wrote my own.


demo

In our CMS, WebME, this is available in the Image-Transition plugin. (If you’re interested in using WebME, you can either download it through SVN, or talk to us about our reseller deals.)

How the thing works, is that you add a list of images to an element like this:

<div id="k3dCarousel">
	<img src="images/concrawood.jpg" />
	<img src="images/fernheasty.jpg" />
	<img src="images/mcnallys.jpg" />
	<img src="images/northernstandard.jpg" />
	<img src="images/soccertours.jpg" />
	<img src="images/soundinsulation.jpg" />
	<img src="images/textaroom.jpg" />
	<img src="images/windhoist.jpg" />
</div>

Then link to the jQuery library and the jquery.k3dCarousel plugin:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="jquery.k3dCarousel.min.js"></script>

And then tell jQuery to run the plugin after all the images have loaded:

<script>
	$(window).load(function(){
		$('#k3dCarousel').k3dCarousel();
	});
</script>

If you want, you can vary the speed of the cycle by changing the sT (spin-time) variable, or the wT (wait time), which govern how long it takes for the images to move from point to point, and how long they pause once reaching there:

<script>
        $(window).load(function(){
                $('#k3dCarousel').k3dCarousel({
                        wT: 500,
                        sT: 100
                });
        });
</script>

Interested yet? Download it (tar.bz2, zip)

12 Sep

saorfm: first visible results

The first visible project using SaorFM is a jQuery file-selection widget:


demo

Here is the source of that page:

<html>
	<head>
	</head>
	<body>
		<p>Select a file</p>
		<input id="file-select" />

		<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" type="text/css" />
		<link rel="stylesheet" href="/saorfm/jquery-widgets/jquery.saorfm/jquery.saorfm.css" type="text/css" />

		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
		<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js"></script>
		<script src="/saorfm/jquery-widgets/jquery.saorfm/jquery.saorfm.js"></script>
		<script>
			$(function(){
				$('#file-select').saorfm({
					"rpc":"/saorfm/core/rpc.php"
				});
			});
		</script>
	</body>
</html>

In the above demo, we link in the jQuery and jQuery-UI scripts, and load up the widget’s script.

The only content elements are a <p> telling the user to choose a file, and a normal text <input> box which the user can use as a combobox.

The magic happens with this little bit of JavaScript:

$(function(){
	$('#file-select').saorfm({
		"rpc":"/saorfm/core/rpc.php"
	});
});

That tells jQuery to convert the #file-select input box into a saorfm widget. The only parameter in this demo is rpc, which tells the widget where the SaorFM server is to be found online.

To install this on your own server, all you need to do is download the SaorFM engine from Google Code, and add a config.php file to the core directory. Here’s mine:

<?php
$SaorFM_config='{"user_files_directory":"\/home\/verens\/domains\/demo.verens.com\/saorfm","language":"en","json_errors":false}';

In that, a JSON-encoded hash object contains the configuration. Change the user_files_directory parameter to your own files directory, and you are done with the configuration!

I’ll be adding this to my WebME project next week, after I’ve finished writing the tests (Selenium and PHPUnit).

27 Aug

keeping an admin session active

I had a call from a client who asked why, after logging into a CMS admin area and spending an hour or so writing a document, she was unable to submit it because it claimed she was not logged in.

The answer was that the session had expired.

On busy servers, one method of optimisation is to reduce the session-time. This makes it easier for the server to cope with a large number of visitors, but also has the undesired effect of logging people out if they take their time over anything.

One solution to this is to keep the admin session in a database table, tied to a cookie in the browser. Unfortunately, that means that every time the browser sends the cookie, it must be verified, whereas a session is usually trusted.

The workaround is to use some JavaScript to refresh the session every now and then.

I wrote a simple cyclical script which polled the server every minute to refresh the session.

Here it is, using jQuery to handle the AJAX:

function keep_session_alive(){
  setTimeout(keep_session_alive,60000);
  $.get('/ww.admin/keepalive.php');
}
setTimeout(keep_session_alive,60000);

And the server-side code is this:

<?php
session_start();

Very very simple trick. The polling could be enhanced, if you want, to alert the admin of anything interesting that’s happened on the server.