09 Mar

CMS Design with jQuery and PHP: postage and packaging prices

This article is based on work which will be expanded more fully in the book, when I get to that chapter.

Every time we do an online store here in webworks, the postage/packaging is different. In one case, for example, postage is free over €50 euro, in another, it depends on where it’s going, and in the latest, it depends on a load of factors including where it’s going, what the weight of the products is, and what delivery option was chosen.

Up until now, hand-coded the postage rules. Everything else was handled by user-friendly parts of our CMS, but postage was such a random thing that we couldn’t find anything common enough that we could make a generic P&P handler.

The finished product is more complex than this example, but I’ll describe a cut-down version of what we’ve done, with countries and parcel-types removed.

admin demo – demo of UI for generating P&P rules

The first demo shows how the postage-and-packaging rule-set is created, using an “if-else” flow generator to build up the logic of the thing, and after each major action, convert the current state into a JSON string which can be saved.

The PHP is not really important in this one. The JavaScript handles everything. It translates a “seed” JSON string into a graphical representation of the rules, which can then be manipulated and finally translated back (automatically) into a JSON string to be saved in a DB (or session in this case). source for the PHP, source for the JS.

The frontend does its work in the background:

frontend demo – using those rules to evaluate P&P (visit admin first).

In this case, we enter values – total, weight – and run through the rule-set to find out what the P&P ends up as.

The source is suprisingly small, using a small recursive function to dig through the rules, no matter how deep and complex they go.

Here’s the recursive function (see source for rest of file):

function os_getPostageAndPackagingSubtotal($cstrs,$total,$weight){
  foreach($cstrs as $cstr){
    if($cstr->type=='total_weight_less_than_or_equal_to' && $weight<=$cstr->value)return os_getPostageAndPackagingSubtotal($cstr->constraints,$total,$weight);
    if($cstr->type=='total_weight_more_than_or_equal_to' && $weight>=$cstr->value)return os_getPostageAndPackagingSubtotal($cstr->constraints,$total,$weight);
    if($cstr->type=='total_less_than_or_equal_to' && $total<=$cstr->value)return os_getPostageAndPackagingSubtotal($cstr->constraints,$total,$weight);
    if($cstr->type=='total_more_than_or_equal_to' && $total>=$cstr->value)return os_getPostageAndPackagingSubtotal($cstr->constraints,$total,$weight);
  }
  $val=str_replace('weight',$weight,$cstr->value);
  $val=str_replace('total',$total,$val);
  $val=preg_replace('#[^0-9*/\-+.\(\)]#','',$val);
  if(preg_match('/[^0-9.]/',$val))eval('$val=('.$val.');');
  return (float)$val;
}

The switch block goes through the various “if” types that can exist in the flow model, handling each of them recursively and return their values to the caller.

If no “if”s are encountered, then the ruleset has found an answer, and we return that answer.

Before returning it, though, we parse the value of the answer. This is in case the answer is a math formula to do with the weight or total of the item.

For example, An Post have definite prices for packets to Europe up to 2kg (which is 10.75), and beyond that, it’s 3 euro extra for every extra kg.

That translates to a load of definite “if” statements, and an end value of “(weight-2)*3+10.75” for the final “else”.

So, we convert recognisable words such as “weight” or “total” to numbers, make sure that we’re only left with parseable characters (and not something that can be used to hack), and eval it to produce the result.

Obviously, the full product is more complete than this, with safeguards against faulty formulas, extras to handle countries and envelope types (parcel/packet/envelope), but this example should give you a few ideas if you’re building your own P&P handler.

27 Feb

new irish plans (a construction industry thing)

We’ve just released newirishplans.com, a site for finding commencement notices. This is extremely useful for people in the construction industry, as I’ll explain.

Companies that work in construction need to be constantly on the lookout for new projects that are starting up. If you find a project just before it starts, you can call up and advertise your business, instead of waiting for the project manager to get around to finding someone else when the time comes.

As an example, if you sell bricks, it is better to call the manager of a house-building project just before they start building the house, than to not call at all, and realised when the house is built that the manager found a different brick supplier and didn’t realise you even existed.

You need to time the call as well – if you call too late, it’s obviously too late, but if you call months before the project starts, then the manager may totally forget you exist by the time the build actually needs your wares.

One way to find these builds that are starting up is to go around to all the planning authorities in your area of interest, and inspect any “commencement notices” that have been submitted since the last time you visited. A “commencement notice” is notification that you are about to start work on your build. All planning applications have this as a requirement.

Obviously, this can take hours out of your working week (and therefore, money), and even after you have the notice, you need to match the notice to the application and see if you’re actually interested in it at all.

The new irish plans project does this all for you. At the moment, the project covers about 17 counties, but we are always adding to this. For example, I’m working on getting Fingal added to the mix at the moment.

An account on the site costs 35 euro a month, and with that, you get an email once a week telling you of any commencements that the system has uncovered during that week.

But anyway – €35 euro a month. Just over one euro a day, and it’s all emailed to you.

If you know anyone in construction (does windows, landscapes, roofs, electrics, etc.) that is looking for work, tell them to go to newirishplans.com – the information is handed to you on a plate.

On the programming side, we wanted to make the search engine stand out, so we used the inline multiselect jQuery plugin (with a few small modifications) to help make selection of features and dates easier.

When I first came across that plugin, I was surprised and kinda proud to find that it’s based on some of my own work from 5 years ago! Open source is brilliant – you write a small piece of code and give it away, then 5 years later you find that someone has taken it and improved it vastly.

Commencements go through a “vetting” process. When a commencement is found, details about it are placed in a system where someone reads through the planning application, and marks down any interesting features about it. Those that have been vetted are then imported once a day into the main site itself, where you can search for them online, filtered by whatever interests you.

The system has been very long in the building, and has changed quite a bit over time. We’re very happy to finally make it public!

There’s still a few things that need to be completed on it (for example, we’re still organising WorldPay integration, but in the meantime we have PayPal), but on the whole, it’s ready for public use.

27 Jan

what's up!

Short run-down of what I’m doing lately: nothing.

Less short: I’m trying to get work out the door, get a good run at some personal projects, pass grade 2 piano, get organised, and generally improve my lot.

None of this is working. I think the “get organised” bit is the most important, as it will help the rest of it fall into place.

I usually only post about web-development-related topics here, as that’s the only subject where I feel I can contribute something new and interesting, so I tend to not talk about other stuff. But sometimes, rattling off the current state of the head is good for clearing it.

In work, I can’t really complain – we have a number of largish projects which are slowly creeping towards completion. The hardest thing about them is getting information from the clients, and then a week or two later being told that half the information is not required. I guess my main complaint at work is the inexorably slow completion rate.

On the personal projects side:

There are still a number of small bugs in KFM 1.4, and either I don’t have the time to get to them, or there is no enough information to recreate the bug and the submitter doesn’t give me access to their copy so I can’t see it from their side.

KFM 2 has been halted for a while – the idea is huge, but I simply don’t have the time, and no-one is clambering for it. I’ll get to it when I have time, but I might have to approach it by evolving KFM 1.x into meeting what I wanted, instead of the original goal of building KFM 2 from scratch.

I started a new project, OddJobs4Locals two weeks back, and got a good two-day run at it, then time got ahead of me again. I think this will be a good one, when I can complete it. Useful for students, people with a little spare time, or simply people that just want to make a little extra cash. Not yet working, but it will be soon, I hope… This is doubly interesting to me, as it is done purely through AJAX, so it will be easy to do a smart-phone client or a desktop client when the time comes.

I’m in the back/forth stage of working with Packt publishing to see if they want me to do a second book (the first one has no bad reviews at all). We’ve mostly agreed on a table of contents, and I’m just trying to get the time to combine a few of the smaller chapters together.

On the piano, I’ve been ready for the grade 2 exam since November, and am still waiting to see if there will be an exam near me any time soon – I hate the effort that goes into travelling (I have a family, and no car). I was hoping to do a grade every 6 months. It looks like this might not be possible, despite me being ready for it… The tunes I’m doing for it are Beethoven’s Sonatina in G Major, a waltz by Bela Bartok, and Boys And Girls Come Out To Samba, by Terence Greaves – by the way, I don’t like those videos; there are no dynamics in any of them, and I can hear a number of mistakes as well. No video apparently of the Terence Greaves one.

As for organisation… well I guess I’d better start working with Mantis again.

My lot will have to wait – I’ve a load of work to get done before it can improve.

Meh. Depression taking hold again.

28 Dec

multiple file uploads using HTML5

As a response to a reported bug where Chrome was taking ages to load up a flash multiple-file uploader, I’ve updated KFM to use HTML5’s multiple-file input box where possible.

To do this, first create the element:

  var input=document.createElement('input');
  input.type='file'; // use old-style JavaScript method to make sure all browsers respect it
  input.name='kfm_file';

Notice that we’re not using setAttribute to set the type and name – that’s a DOM method which works in most browsers but not (of course…) in Internet Explorer 6, where it has bugs.

And now, we tell the input to use the multiple-upload method. We use .setAttribute in this case because we only expect newer browsers to succeed with it.

  input.setAttribute('multiple','multiple');
  if(input.multiple)input.name='kfm_file[]';

In the second line, we check to see if the element is now marked as a multiple-uploader (most current browsers will not succeed in this), and if it does, then rename the input element by adding a [] to the end. If this is not done, then the server will only see the first file which is uploaded.

That’s the client-side done. This will only be visible in newer browsers such as Chrome, Safari 4, Firefox 3.6. I expect Internet Explorer will eventually catch up by 2020 or so.

If you’re doing this in pure HTML, then I suppose this would be good enough for you:

<input type="file" multiple="multiple" name="kfm_file[]"/>

In this case, you must put the [] in the name in all cases.

On the server-side, you need to write your upload receiver to expect either a single element, or an array.

For some really goddamned stupid reason, when multiple files are uploaded to PHP, the results are interlaced in a really crappy and awkward manner (I don’t like it).

Instead of something logical and easy to use, like this:

array(
  [0] => array(
    'name'     => 'file1.txt',
    'tmp_name' => '/tmp/abcdef'
    ....
  ),
  [1] => array(
    'name'     => 'file2.txt',
    'tmp_name' => '/tmp/ghijkl'
    ....
  )
);

You get this…

array(
  'name' => array(
    [0] => 'file1.txt',
    [1] => 'file2.txt'
  ),
  'tmp_name' => array(
    [0] => '/tmp/abcdef',
    [1] => '/tmp/ghijkl'
  ),
  ...
);

While that looks at first glance to be easy to use, it’s not. You can’t do a simple “foreach($_FILES['kfm_file'] as $file)” and expect the above to be usable at all…

So, the first thing I do, is to check for the $_FILES[‘kfm_file’], and convert it into the first form above, which is very easy to work with:

$files=array();
$fdata=$_FILES['kfm_file'];
if(is_array($fdata['name'])){
 for($i=0;$i<count($fdata['name']);++$i){
  $files[]=array(
   'name'     => $fdata['name'][$i],
   'tmp_name' => $fdata['tmp_name'][$i],
  );
 }
}
else $files[]=$fdata;

In my own case, I’m only interested in the name and tmp_name variables, so that’s all I set up.

Now you can do a foreach on $files and treat them all individually.

foreach ($files as $file) {
  // uploaded location of file is $file['tmp_name']
  // original filename of file is $file['name']
}

If you want to see this in KFM, have a look at the nightly-updated demo tomorrow, or download from SVN right now.

oh – and buy my book!

17 Dec

novelrank

Because it’s difficult to know exactly how well my book is doing, I went looking for online apps that might be able to help.

I came across NovelRank a few weeks ago, which keeps track of your Amazon SalesRank and uses the fluctuations in the value to try figure out when a sale happens.

At first I was a bit disappointed, as my own ratings should not many sales going on, but I realised that this was because there were no reviews out there so people a) didn’t know about the book, and b) didn’t know if it was worth buying.

Since the reviews have started coming in, sales have picked up, as can be seen in the NovelRank graph for my book.

I like this application – it’s a simple idea, and the author has made it freely available (I assume he makes money from affiliate links).

Want to see it in action? Buy JQuery 1.3 with PHP and then view NovelRank graph for my book the graph a few hours later to see your very own blip appear on it.

It’s interesting to see that the book is not selling at all in Canada. What’s wrong with you Canadians?? 😉

On a very related note, I’m in talks with Packt to produce another book. More on this later when details are more concrete.

26 Oct

jQuery 1.3 With PHP: Datatables chapter is online

Packt have put another chapter of my book online. This time, it’s the datatables chapter, which discusses how to use the Datatables plugin to organise very large data tables.

The chapter discusses how to make a large (over two million rows) database usable through an ajaxified table.

The Datatables plugin supports search, sorting and pagination.

24 Oct

jQuery 1.3 With PHP: calendars chapter is online

Packt have put one of the chapters of my book, jQuery 1.3 with PHP, online as an article.

I mentioned this chapter in June, and provided a small demo and the source.

I’ve had a few requests for example code on how to do this using a real database. I’ve been meaning to make the time to do that. I’ll get that done hopefully tomorrow.

In the meantime, though, please enjoy the article.

By the way, the book went to the printer only a few days ago, so if you want to avail of the pre-order price, now’s the time.

18 Oct

kfm2: example widget

As an example of a front-end widget, I’ve whipped up a demo of file-tree navigation using the excellent jsTree widget.

here is the demo

You can see from the source how short it is – all it does is load up the jsTree library (and jQuery), then it connects directly to KFM2 to get data about the files on the server.

in fact… it’s so short I’ll just paste the demo into this page as well:

$(document).ready(function () {
$(“#tree_div”).tree({
data : {
type : “json”,
async : true,
opts : {
async : true,
method : “POST”,
url : “http://demo.verens.com/kfm2/trunk/?p=get_file_listing” // KFM LOCATION
}
},
callback : {
‘beforedata’:function(node){
var id=$(node).attr(‘id’);
if(!id)return {‘d’:’/’};
return {‘d’:$(node).attr(‘id’).replace(/^kfm2_node_/,”)};
},
‘ondata’:function(res){
var data=[],i;
for(i in res.files)data.push({‘data’:i,’attributes’:{‘id’:’kfm2_node_’+res.d+’/’+i}});
for(i in res.directories)data.push({‘data’:i,’state’:’closed’,’attributes’:{‘id’:’kfm2_node_’+res.d+’/’+i}});
return data;
}
}
});
});

You should see a list of files just above this paragraph.

No modification of jsTree was necessary, as it handily gives two event triggers which can be used to translate the request data to KFM’s request format, and the received data back into jsTree’s data format.

Here is the code used to attach the tree to the #tree_div element in this page:

$("#tree_div").tree({
	data : {
		type : "json",
		async : true,
		opts : {
			async : true,
			method : "POST",
			url : "http://demo.verens.com/kfm2/trunk/?p=get_file_listing" // KFM LOCATION
		}
	},
	callback : {
		'beforedata':function(node){
			var id=$(node).attr('id');
			if(!id)return {'d':'/'};
			return {'d':$(node).attr('id').replace(/^kfm2_node_/,'')};
		},
		'ondata':function(res){
			var data=[],i;
			for(i in res.files)data.push({'data':i,'attributes':{'id':'kfm2_node_'+res.d+'/'+i}});
			for(i in res.directories)data.push({'data':i,'state':'closed','attributes':{'id':'kfm2_node_'+res.d+'/'+i}});
			return data;
		}
	}
});

This is just an example of what can be built quickly with the new RPC-based KFM.

Further and more useful examples will come soon.

04 Oct

KFM2 has begun. requesting ideas of sample plugins to develop

As ye all know now, KFM1.x is finished. I’m not interested in struggling with it anymore. I’ve started a new project which will exceed KFM1.x’s capabilities.

The main problem with 1.x was that it was monolithic – there was one single codebase, which encompassed both the server-side and the client-side. The client-side code was useless without the server-side, and the server-side code had hooks specifically designed to be used by the client-side.

While it was possible to build a different client-side GUI that would hook into the server-side, it would be a large undertaking, and would involve changing a lot of the PHP – especially as the PHP wrote the “boot” JavaScript in the first place…

KFM2 is designed from the beginning to have a different architecture based specifically on plugins. The core code is a small plugin manager (mostly written already), written in PHP, but it will not be necessary that the client-side is in JavaScript – or even that there is any interaction with a browser at all!

The idea is this – if you want to do something incredibly simple, such as select an existing directory that will be used in your CMS to create an image gallery out-of (let’s say you need to choose from a number of existing directories full of images), then it is a total waste of bandwidth and CPU to load up a full-on file-manager.

In this case, and it’s the first I’ll be building to show how all this works, what should happen is that the browser will show something simple like this:

Choose the image directory

…and when that’s clicked, a small popup will appear which lets you choose the directory you want, in a tree-like manner – you open the branches until you find the one you want, then you click it. Afterwards, the form will change:

Choose the image directory /images/the-lads-2009/ selected

From the technical point of view, there’re a few things to explain about how this would be done.

jQuery would be used to attach an event to the button which would popup the selection window. This selection window will use Ajax to speak with the KFM2 server and retrieve the list of directories, one level at a time as the branches are expanded. When one is selected, a hidden input will be set to the name of the directory.

This sounds incredibly simple, and it is. What’s important, though, is that no-one is doing this at the moment!. Right now, if you go search for existing plugins to do this kind of thing, you’ll find either small widgets with both the server and client-side code ready for you, or full-on applications (such as KFM1.x) which can do the job, but which are overkill.

The problem with the applications is obvious – too much stuff going on, making it slow and cumbersome.

The problem with the small widgets is that each one is complete in itself, and therefore a lot of the functionality is repeated. This is a bad idea – what if you need to make a site-wide change? You’d need to go through every widget and change it!

What I’m proposing to make of KFM2 is that it will mostly be a server-side application, but which has a nice easy-to-use API which can be hooked into by lots of different jQuery widgets (or Mootools, or whatever you want, really – write it in Python or Delphi if you want…).

So, my first widget will be the one described above – a directory selector.

I’d like to know what other things people need to do with files online, which are simple and they’d prefer not to have to load a whole file-manager to do.

I’ll release the first widget and a demo of it some time over the next week. I intend to write a whole load of widgets, culminating in a full-on GUI similar to the present KFM1.x one, all hooking into the new engine.