I really need to think of a clever name for my blog

Code samples, geeky links and other musings. Note this blog has recently moved from Posterous, so isn't fully back up to speed yet!

Dirtiest. Hack. Ever. iOS Event Delegation Solved(?)

So, iOS Safari has a problem with javascript event delegation.

Normally you click (or trigger any event) on an element, and the browser traverses back up the dom, triggering that event on each parent. Thus we can attach an event listener to a ul, and all it li’l children (and bastard offspring) will inherit the same listener.

Possibly for memory management reasons, this doesn’t happen in iOS Safari – unless the element is a link or input – an actual ‘clickable’ element. So there is some logic here, but we’re in a different age and this kind of behaviour is completely at odds with all other browsers, which screws us pretty bad as so much of our application behaviour today relies on event delegation.

There is a fix – if Safari thinks you want your element to be interactive, it will allow delegation – give the element the css property of cursor:pointer;

Ok, fine if you have a specific element which needs delegation, but what if you have an element with lots of children? What a waste, adding the cursor property to all that CSS.

And what if you need to do something very generic? We need to emulate rollover behaviour with touch sometimes, so we want to touch open a menu, and close on touch off. We can’t possibly know which element a user will touch off on. If a modal effect is desired, that’s easy – our modal layer is a single element we can add the cursor to. But if we want a touch off action to be able to trigger another element, as well as trigger our mouseout-like behaviour, that’s no good.

Greedy Bastard Ahoy!

Obviously we can’t simply give cursor:pointer; to everything, I mean, the cursor MEANS something.

Or can we? There IS no cursor on iDevices. All we need do is determine when we are on a device, say with Modernizr [new window], and away we go…

.touch *{    cursor:pointer;}

Dirty. Greedy. Lazy. Bastard.
But it works.
Now, touch isn’t a perfect answer here – there are touch devices that support input peripherals, and a touch PC with a mouse would be a bit borked, as they would have a constant pointer – but there are refinements. User Agent sniffing is a bit dodgy, but c’mon, iOS users changing their user agent? And frankly, if you change your user agent, you should expect things to behave oddly.

https://gist.github.com/855078

Of course, if memory usage was SUCH a problem that Apple engineers simply HAD to disable event delegation in the first place, then we have just reopened that can of worms – into our pants, before diving into a piranha pool – so it is probably best to excercise caution…

#BADA55 !important – Chrome Dev Tools

Freaking awesome developments in Chrome Dev Tools – putting FireBug on notice maybe?

From Paul Irish’s blog:

Pavel Feldman (Dev Tools engineering lead) and I just spoke at Google I/O about the Chrome Developer tools.

We covered a whole lot of enhancements to style manipulation, timeline inspection, script debugging, DOM and Event listener breakpoints.

We announced a few brand new features I’m really jazzed about:

For full text and comments got to
http://paulirish.com/2011/a-re-introduction-to-the-chrome-developer-tools/

7 Super Easy CSS Recipes to Copy and Paste

http://designshack.co.uk/articles/css/css3-cookbook-7-super-easy-css-recipes-to-copy-and-paste

Define your own colour names in CSS

Looking at my Posterous template, I notice the following:

h2 a:hover { color: {color:Accent}; }

WTF? Accent isn’t a standard CSS colour name.
Searching for Accent I find the following inside the head tag:

<meta name=”color:Accent” content=”#a98e2e”/>
<meta name=”color:Darker Accent” content=”#776421″/> 

Genius! I didn’t know you could do that. Now with this you can define a set of colours in an external file (possibly in a database for a CMS) and include that in your templates, and easily control and change all colour references in a site by only changing that file. What a fantastic time saver – no complex find and replace in multiple CSS files to update a colour scheme for a special occasion. BUT: Does this only work with Posterous’ template system? If so, it would be easy to write into your own systems but could be more of a pain to implement for say Joomla. I shall have to do some tests….

[UPDATE: 1436-08062010]
Haven’t gotten round to doing any testing, but my associate Bishop Dante tells me:

“the meta trick is pure HTML, it’s not specific to your blog platform.
It can be done to assign classic global control over most anything of value,
including the source of the HTML file itself.”

Well blow me! I’ve been doing HTML for over 10 years, and I have NEVER come across this before. Never seen it on a site, never found a reference in a manual or a guide online. Me still likey. Next question: Can you use this trick with external CSS or does it have to be inline?
[/UPDATE]

[UPDATE: 1641-12112010]
Well, I’ve finally tried it out, and it doesn’t seem to work either inline or external. Can’t find much of anything on Google relating to it, apart from mention of Tumblr profiles. It may be accomplished with Javascript perhaps, which is a real shame. I’d love to know more about it…
[/UPDATE] 

Prism – JS/CSS Syntax Highlighting

Looks great.

Well, the dark theme is a bit, shall we say, chocolate-y, and the funky theme is a horrific 80′s headfuck (if slightly amusing), but hey, CSS is CSS so you can change that. The default theme is perfectly tasteful. More importantly it’s lightweight, fast and extensible. I should add it to this blog sometime.

http://prismjs.com/

CSS3 Active Cheatsheet

Here’s a very nicely put together cheatsheet for some of the fancy new CSS3 styles. Can’t really be printed, it being interactive and all, but an awesome illustration of the power of the new rules.

http://www.impressivewebs.com/css3-click-chart/

Rotating background image (or other PHP function) in CubeCart templates

I have a site where the main site picks an image from a particular folder for the background every time you hit a page, rotating through the available images in a loop. We also have a CubeCart store, which has had the template skinned to fit the main site, so obviously enough, I wanted to have the same background image feature for the shop.

The thing with CubeCart templates is that you can’t just add php to the .tpl files – you have to do all your PHP jiggery pokery in include files, and assign values to object properties, and include a placeholder in the tpl.

There are two key CubeCart files to make this change over the whole shop:

{www,yourdomain.com}/{shop_location}/includes/global/index.inc.php{www,yourdomain.com}/{shop_location}/skins/{your_skin}/styleTemplates/global/index.tpl

First off you want to get your functions together from the main site. Mine all live in a lib.php file, but as I don’t need to load all of them into CubeCart, I pulled the relevant ones into a new file, /lib/php/rotatebg_lib.php. Now I can include this file in my original lib.php as well as in CubeCart, and reduce unnecessary memory overheads.

The system relies on three functions:

files_in_dir($start_dir) creates an array of the files in a directory. This is one of my standard ‘off the shelf’ functions

index_background_images() checks for files with a .jpg extentsion, creates an array of them and stores it in a $_SESSION variable, called only when a session is started. There are other ways of checking for file types – the most reliable is to mime_content_type() function, but if you trust the files on your server, my method is fine. If you are dealing with user uploaded files, remember you should NEVER trust the file to be what it says it is!

rotate_background() checks for a session, calls the indexing function if necessary and otherwise increments the index counter.

rotatebg_lib.php

$background_image_path = '/img/backgrounds/';function rotate_background(){/* check for session - if none, index bg files, else increment counter */    if(isset($_SESSION['backgrounds'])){        $_SESSION['backgrounds']['index']++;        if($_SESSION['backgrounds']['index'] >= count($_SESSION['backgrounds']['files'])){            $_SESSION['backgrounds']['index'] = 0;        }        $background = $_SESSION['backgrounds']['index'];    }else{        $_SESSION['backgrounds']['files'] = index_background_images();        $_SESSION['backgrounds']['index'] = 0;        $background = 0;    }    return $background;}function index_background_images(){/* return array of files with .jpg extension */    global $background_image_path;    $files = files_in_dir($_SERVER['DOCUMENT_ROOT'] . $background_image_path);    foreach($files as $file){        if(substr($file,0,10) == 'background' && substr($file,-4,4) == '.jpg'){            $bg_images[]=$file;        }    }    return $bg_images;}function files_in_dir($start_dir){/* returns an array of files in $start_dir (not recursive) */    $files = array();    $dir = opendir($start_dir);    while(($myfile = readdir($dir)) !== false){        if($myfile != '.' && $myfile != '..' && !is_file($myfile) && $myfile != 'resource.frk' && !eregi('^Icon',$myfile) ){            $files[] = $myfile;        }    }    closedir($dir);    return $files;}

Now we need to include and run these functions in the CubeCart global index include.Line numbers may vary dependant on your template, but essentially you want to add this just after the $body template has been defined

{your_skin}/includes/global/index.inc.php

Replace:

$body = new XTemplate ("global".CC_DS."index.tpl");

With:

$body = new XTemplate ("global".CC_DS."index.tpl");include($_SERVER['DOCUMENT_ROOT'].'/inc/php/rotatebg_lib.php');$background = rotate_background();$body->assign('VAL_CUSTOM_BACKGROUND', $_SESSION['backgrounds']['files'][$background]);

And finally, insert VAL_CUSTOM_BACKGROUND into the index.tpl file. This needs to be added in the head section, I prefer the end of the head section as CSS latency will ensure that the rule is obeyed. Again, line numbers may vary.

{your_skin}/styleTemplates/global/index.tpl

Replace:

</head>

With

<style type="text/css">#pageSurround{    background-image:url("/img/backgrounds/{VAL_CUSTOM_BACKGROUND}");}</style></head>

Shazzamwhazzam. We are done.