Parallax 0.1 – Simple parallax effect for jQuery

I’ve seen some very cool parallax effect around lately, especially liking the Silverback site. But none of them are particularly interactive, so I thought I’d make a small implementation of the Parallax effect that interacts with the mouse.

Very early stages (and I haven’t tested it on IE yet… but you could just you conditional comments to exclude ‘those’ people anyway…) but it seems to be working ok. The options aren’t really simple, but they should be fairly self-explanatory…

Check out the demo (it is a very poor demo, please don’t look at the images, imagine it with a lovely hand drawn vector!) and get it here (minified).

Update: Created a quick demo of the silverback homepage with interactive parallax.

Update 2: Tested on IE8, seems to work fine!

Update 3: I have modified the script slightly, you can view the post here.

JSS – Nested CSS using Javascript

Update: I have worked on a newer version with more features and a PHP conversion, here.

Ever wanted nested stylesheets?

I have!

Now you can have them! If you code your stylesheets as JSON and parse them using JSS 0.1. You could have the following:

      JSS({
        'html': {
          'body': {
            background: '#fff',

            'div#header': {
              height: '100px',
              background: '#00f'
            },

            'div#footer': {
              height: '40px',

              'span#copyright': {
                color: '#0f0'
              },
              'span#testing': {
                color: 'black',
                background: '#eeccff'
              }
            }
          },
          width: '800px'
        }
      });

Turned into:

      html {
        width: 800px;
      }

      html body {
        background: #fff;
      }

      html body div#header {
        height: 100px;
        background: #00f;
      }

      html body div#footer {
        height: 40px;
      }

      html body div#footer span#copyright {
        color: #0f0;
      }

      html body div#footer span#testing {
        color: black;
        background: #eeccff;
      }

You can get it here or view the test page here.

jsDebug 0.1 – Dump javascript objects

There have been many times I’ve wanted to debug an object in various browsers, and see why that particular key is null in IE6 or whatever, so I’ve made this small independent ‘Debug()’ function for use in all the major browser

It’s not dependent on any frameworks and gives a simple interface listing all information about objects required. Each call to Debug() adds a new table at the top of the panel showing the information retrieved from the pass variable.

It’s only a first draft and the depth feature doesn’t actually work as object depth yet, but rather as the number of internal objects to dump before not doing any more… Any recursion experts feel free to add this, but please share it 🙂

Not so pretty, functional though...
Not so pretty, functional though...

You can get it here or see it in action too. Oh it’s free, do what you want with it.

jQuery – Automatic Image Captions

Lots of RTEs allow you to add images and float them, but not many allow for simple captions to be wrapped around the images…

This script in conjunction with jQuery allows just that… Very simple and fairly unobtrusive.

If you wanted to add captions to all images (from their longdesc, title or alt attributes) within <div class=”content”/> you could do:

$('div.content').addCaptions();

Which produces something like this:

jQuery Add Captions - Screenshot (Like this!)
jQuery Add Captions - Screenshot (Like this!)

No styling is carried out by the script itself, so you’ll have to add in some extra classes, but in the zip file should be everything you need to get started (including jQuery 1.3.2 minified).

Download

Edit: Added to the work blog too.

Update: I have updated the script, see this post.

Simple Inheritance on Javascript Objects

I’ve been playing a lot with javascript lately and needed to extend an object, retaining all the existing methods but also adding more.

This simple script allows exactly that:

Object.prototype.implement = Function.prototype.implement = function(props) {
  for (var key in props) {
    this[key] = props[key];
  }
  
  return true;
}

Object.prototype.extend = Function.prototype.extend = function(props) {
  var obj = new this.constructor();
  obj.prototype = this.prototype;
  obj.implement(this);
  
  if (props) {
    obj.implement(props);
  }

  return obj;
}

It should be used similar to how you would extend a class in PHP i guess:

var Class = function() {
}

Class.prototype.test = function() {
  alert('test');
}

var Class2 = Class.extend();

Class2.prototype.test2 = function() {
  alert('test2');
}

var obj = new Class();

var obj2 = new Class2();

obj.test();
// alerts test
obj.test2();
// throws an exception
obj2.test();
// alerts test
obj2.test2();
// alerts test2

I know there are many frameworks that probably already do this better, but if you just need a simple object extension method, this should work.

jsInflections – Ruby style inflections for Javascript

Small class, that handles inflections like ruby for javascript strings, eg:

alert('cow'.pluralize());  // alerts cows
alert('cows'.singularize()); // alerts cow

Pretty simple, all methods except constantize have been replicated.

This file is probably mostly the work of the rails team, so the same license applies to this, as rails itself.

Download (3.3KB)

Webkit (Safari) – Speed Dial bookmarklet

Since chrome (well I know opera did it way back when… but anyway) the speed dial feature of a browser has become very popular and I thought that since bookmarklets are cool and webkit has a database engine, surely these ideas could all be combined, so I’ve built a simple speed dial page written totally in javascript with webkit’s SQL engine.

It’s not super pretty, surely has some bugs (if you load the bookmarklet from anything other than a new tab, you’ll have no favourites and also it can’t be your homepage, for some reason), and you need to sign up for a snapcasa.com account (it is free!) for the prettiness, but it’s mainly proof-of-concept.

speedDial bookmarklet for WebKit
speedDial bookmarklet for WebKit

To enjoy previews of the sites you’ve added, you’ll need to sign up for a free account at http://snapcasa.com/Register.aspx after which you will have to add your IP address (hopefully it’s static… sorry if not, but there are other solutions… http://www.webresourcesdepot.com/10-free-website-thumbnail-generation-services/)

You can download the package with a YUI compressed copy of the code and a fully expanded version below, or alternatively, you can copy this code, remembering to replace the SNAPCASA_CODE with your own code:

javascript:document.write('<html><head><title>Speed Dial</title></head><body><div id="body"></div></body></html>');window.speedDial={rows:3,cols:3,data:[""]};var body=document.getElementById("body");if(window.openDatabase){var database=window.openDatabase("SpeedDial","1.0","Speed Dial settings",200000);if(database){var loadSettings=function(){database.transaction(function(A){A.executeSql("SELECT rows, cols FROM SpeedDialSettings",[],function(C,B){for(var D=0;D<B.rows.length;++D){var E=B.rows.item(D);window.speedDial.rows=parseInt(E.rows);window.speedDial.cols=parseInt(E.cols)}},function(B,C){body.innerHTML=C.message;return})})};var loadData=function(){database.transaction(function(A){A.executeSql("SELECT * FROM SpeedDialSites",[],function(C,B){for(var D=0;D<B.rows.length;++D){var E=B.rows.item(D);window.speedDial.data[E.id]=E.url}},function(B,C){body.innerHTML=C.message;return})})};var changeSite=function(A){database.transaction(function(B){B.executeSql("SELECT * FROM SpeedDialSites WHERE id = ?",[A],function(D,C){if(C.rows.length==0){var E=checkURL(window.prompt("Enter the URL for cell "+A));if(E===false){return}if(E.length>0){D.executeSql("INSERT INTO SpeedDialSites (id, url) VALUES (?, ?)",[A,E],function(H,G){window.setTimeout(function(){render()},400)},function(G,H){alert(H.message)})}}else{if(C.rows.length==1){var F=C.rows.item(0);var E=checkURL(window.prompt("Enter the URL for cell "+A,F.url));if(E===false){return}if(E.length>0){D.executeSql("UPDATE SpeedDialSites SET id = ?, url = ?",[A,E],function(H,G){window.setTimeout(function(){render()},400)},function(G,H){alert(H.message)})}else{D.executeSql("DELETE FROM SpeedDialSites WHERE id = ?",[A],function(H,G){window.setTimeout(function(){render()},400)},function(G,H){alert(H.message)})}}else{alert("Too many rows!");return}}},function(C,D){alert("Error with SpeedDialSites table");return})})};var clearAll=function(){database.transaction(function(A){A.executeSql("DELETE FROM SpeedDialSites WHERE id > -1",[],function(C,B){},function(B,C){alert(C.message)})});window.setTimeout(function(){render()},400);return true};var changeSettings=function(){var A=parseInt(prompt("Please enter the number of rows you require"));var B=parseInt(prompt("Please enter the number of columns you require"));database.transaction(function(C){C.executeSql("UPDATE SpeedDialSettings SET rows = ?, cols = ? WHERE rows = ? AND cols = ?",[A,B,window.speedDial.rows,window.speedDial.cols],function(E,D){},function(D,E){alert(E.message)})});loadSettings();window.setTimeout(function(){render()},400)};var checkURL=function(A){if(A==null){return false}if(typeof A!="string"){return""}else{if(A.length>0){if(A.indexOf("http")==-1){return"http://"+A}else{return A}}else{return""}}};database.transaction(function(A){A.executeSql("SELECT * FROM SpeedDialSettings",[],function(C,B){if(B.rows.length==0){C.executeSql("INSERT INTO SpeedDialSettings (rows,cols) VALUES (?, ?)",[3,3])}else{}},function(B,C){B.executeSql("CREATE TABLE SpeedDialSettings (rows REAL, cols REAL)",[],function(E,D){E.executeSql("INSERT INTO SpeedDialSettings (rows,cols) VALUES (?, ?)",[3,3])})})});database.transaction(function(A){A.executeSql("SELECT COUNT(*) FROM SpeedDialSites",[],function(C,B){},function(B,C){B.executeSql("CREATE TABLE SpeedDialSites (id REAL UNIQUE, url TEXT)"),[],function(E,D){}})});var render=function(){loadSettings();loadData();body.innerHTML="";var G=document.createElement("table");G.cellSpacing="10px";G.style.width="90%";G.style.height="90%";G.style.marginTop="5%";G.style.marginLeft="5%";body.appendChild(G);for(var B=1;B<=window.speedDial.rows;B++){var I=document.createElement("tr");G.appendChild(I);for(var A=1;A<=window.speedDial.cols;A++){var C=(((B-1)*window.speedDial.cols)+A);var F=document.createElement("td");F.style.color="#ccc";F.style.border="8px solid #ccc";F.style.textAlign="center";F.style.fontFamily="Arial";F.style.width=parseInt(100/window.speedDial.cols)+"%";F.style.height=parseInt(100/window.speedDial.rows)+"%";F.num=C;F.onclick=function(){if(this.innerHTML==this.num||!this.url){changeSite(this.num)}else{if(event.altKey){changeSite(this.num)}else{window.location=this.url}}};F.onmouseover=function(){this.style.color="#999";this.style.border="8px solid #999"};F.onmouseout=function(){this.style.color="#ccc";this.style.border="8px solid #ccc"};if(typeof window.speedDial.data[C]=="undefined"){F.style.color="#ccc";F.style.fontSize="100px";F.innerHTML=C}else{F.url=window.speedDial.data[C];F.style.fontSize="15px";F.innerHTML='<img src="http://snapcasa.com/get.aspx?code=SNAPCASA_CODE&size=l&url='+F.url+'" alt=""/>'}I.appendChild(F)}}var D=document.createElement("a");D.href="#";D.onclick=function(){clearAll();return false};D.appendChild(document.createTextNode("Clear"));var E=document.createElement("a");E.href="#";E.onclick=function(){changeSettings();return false};E.appendChild(document.createTextNode("Settings"));D.style.color="#ccc";D.style.textDecoration="none";E.style.color="#ccc";E.style.textDecoration="none";var H=document.createElement("p");H.style.fontFamily="Arial";H.style.color="#ccc";H.appendChild(D);H.appendChild(document.createTextNode(" - "));H.appendChild(E);body.appendChild(H)};loadSettings();loadData();window.setTimeout(function(){render()},100)}else{body.innerHTML="Error opening database"}}else{body.innerHTML="Error accessing database"};

and paste in directly!

Download (3.2KB)

As ever, this snippet is under the Creative Commons ShareAlike Attribution license.

php-log: Process apache log files with PHP

I’ve recently had to quickly parse an Apache log file, to get basic usage statistics for a site over a month and wanted the ability to quickly process any general logs and store them in a MySQL table, so I’ve made a small package class.log.

Included in the package are:

  • class.log.php (the main class)
  • class.log.processor.php (an interface for a log processor, very basic!!)
  • class.log.output.php (a simple extension of the processor (outputs <p> tags with <span>s)
  • class.log.mysql.php (a simple mysql importer of the processed data)
  • parse.php (a simple implementation, bringing all the classes together)

The class is designed to use one line at a time from the log retrieved, and the regular expression specified in class.log.php can be modified to parse different types of logs as long as the matches array is also updated.

I’ve only used this for apache logs currently, which it managed quite well, I’m not sure if I’d use this script in an automated script, but I’ll leave that for you to decide.

As other scripts, this class is available under the Creative Commons Share Alike Attribution license.

Edit: Minor update, made class more generic and added more comments.

Download (3.7kB)

Conway’s Game of Life

So, thanks to xkcd I learnt about something cool today that’s been around for ages (wish I’d studied more maths….).

All the sites I found for playing with the simulation had Java applets on them, so I wanted to make a javascript one, I know it’s not a true implementation, because it goes a bit mental at the edges… but it was interesting anyway…

It’s here anyway if anyone wants to play… The timings might be a bit of a problem if you create a huge grid with small squares… so be prepared for Internet Exploder to give you some memory leak issues…

http://dom.hastin.gs/files/gameOfLife/gameOfLife.html

Edit: Updated links.