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.

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.

submitEvents – Javascript form submission handler

Something that I seem to be doing a lot lately, is writing a handler for processing the submission of a form, and since mootools is the JS framework of choice, I’ve written this little class that handles the onsubmit of a form and adds some useful features.

  • Confirmation – Provides an Ok, Cancel input box before proceeding further
  • Submit Button – Disable and change the text on a submit button
  • Information Div – Display a div that lets the user know something is happening
  • Undo – Undo the changes (re-enable a previously disabled submit button, change the information div) that have been carried out by the class
  • AJAX – Submit the form using AJAX instead of the ‘old fashioned’ way

All these should be easily implemented using the class.

Examples are provided in examples.html.

As previously, this work is released under the creative commons share alike license.

Download submitEvents 0.1 (31.9k) (Includes mootools 1.2)

Edit: I really do dislike internet exploder… The above version failed in IE6 (mootools’ form.toQueryString() function). I’ve updated the code to 0.11 which can be found here:

submitEvents 0.11 (32.8k) (Includes mootools 1.2)

Edit 2: Ok, so my hatred for IE, although deserved, was unnecessary in this situation…

I’ve updated the code to use mootools .bind(this) on the ajax onComplete function, this fixed the main problem with IE6 and makes the code look much cleaner. Also the examples file is now PHP instead of static HTML and returns a var_dump of $_POST when the form is submitted.

PS. This will be the final update to this post!

submitEvents 0.2 (32.3k) (Includes mootools 1.2)