Here's a useful little code snippet if you're building a web application. It's a simple way of making the boundary between web-browser and platform a bit smaller. It allows you to create a file (text, html, whatever) in in your page which the user can drag onto their desktop (if their browser supports the dragstart event and dataTransfer methods).
document.getElementById('downloadElement').addEventListener("dragstart", function (e) {
e.dataTransfer.setData("DownloadURL", "text/html:filename.html:data:image/png;base64," + btoa(fileContent));
});
A description of the code:
attach an event listener to the draggable element you specify (downloadElement)
when you start to drag it (dragstart),
it creates a dataTransfer object (with the type DownloadURL)
and sets the content of that to be whatever you pass it (fileContent)
It uses btoa() to encode the string data as a base64-encoded string.
When you combine this with the MIME-type (text/html),
you can create a file with the specified name (filename.html) when the user releases the drag in their local file system.
The fake MIME-type (image/png) is there as part of the object data to convince the browser this is a binary file (which it is, even though it's not an image).
Credit goes to Paul Kinlan for using this in Appmator which is where I first saw this done this way. He actually uses it alongside some extremely clever JS zip-file creation stuff, too, it's definitely worth digging through the source there.
You can find out more about the drag events on the MDN.
When messing about with another little game idea, I found myself retyping (for the umpteenth time) the same little bit of value bounding code I use a lot:
var x = Math.max(0, Math.min(y, 1))
Which basically translates to:
"Set x to be the value of y as long as it's between 0 and 1.
If not, set it to
0 if it's smaller or
1 if it's larger."
Of course, 0 and 1 don't need to be the boundaries, I'm just using them for convenience.
Instead of continuing with the game, I decided to take a little tangent and see if there was any way I could rewrite this so that the syntax was a bit more obvious. I'd like to be able to use syntax like:
x = [0 < y < 1]
to mean the same. Written exactly as above, JS will try and evaluate left-to-right, changing the comparisons to booleans. The statement would become
y = 0.5
x = [0 < y < 1]
x = [0 < 0.5 < 1]
x = [true < 1]
x = [false]
Similarly:
y = -0.5
x = [0 < y < 1]
x = [0 < -0.5 < 1]
x = [false < 1]
x = [true]
My first thought was to be clever about it, I wanted to try and figure out how to partially evaluate the expression and take the different outcomes to figure out the logic required. If '0 < y' was false, then y is less than zero therefore outside our bounds, the return value should then be 0. If the first part is true and the second is false then we know the value is higher than our bounds....etc and so on.
This proved to be a logical dead-end as there was no good way to partially evaluate the statements. Not without preparsing the JS, anyway. Which leads me onto the second attempt...
Preparsing the JS
The next attack on the problem was the idea of reading the JS as a string, shuffling it around quickly and silently (not like a ninja, more like a speedy librarian in slippers) and put it back where it was.
So I began to look at ways to recreate that. I remembered from many, many years ago (two, actually) Alex Sexton creating the genius abomination that is goto.js and how that used some kind of preparsing. A quick skim through the code later and I ended up on James Padolsey's site looking at parseScripts.js.
In the end, all I needed to do was include parseScripts (which is a generalised form of the code I ended up using for the whitehat SEO question from last month) and provide a new parser function and script type.
I'm not saying parseScript isn't clever because it most definitely is but I am saying it's simple. There's not always a need to branch off into deep technical investigations of partial evaluation when a simple search-and-replace does the job better and faster.
For someone always going on about bringing simplicity and pragmatism into development, you'd think I'd have gotten there faster...
While I was making the 3D CSS Mario Kart, I needed a simple, drop-in bit of code to handle touch interfaces. I looked through some old experiments and found a rough version of the code below. It was based on this KeyboardController by Stack Overflow user Bob Ince.
It doesn't do anything clever. All it does is provide a simple way to attach functionality to touch events in different areas of the screen – top-left, top-center, top-right, middle-left, middle-center, middle-right, bottom-left, bottom-center, bottom-right. My apologies to any Brits for the spelling of centre as 'center'. It's the Internet, we have to.
How to use
Include this code:
function TouchController(areas, repeat) {
var touchtimer;
document.onmousedown = document.ontouchstart = document.ontouchmove = function(e) {
var position;
e.preventDefault();
e.touches = [{'clientX':e.pageX,'clientY':e.pageY}];
switch(true) {
case (e.touches[0].clientY<window.innerHeight/3) :
position = 'top';
break;
case (e.touches[0].clientY>(2*window.innerHeight)/3) :
position = 'bottom';
break;
default :
position = 'middle';
break;
}
position+='-';
switch(true) {
case (e.touches[0].clientX<window.innerWidth/3) :
position += 'left';
break;
case (e.touches[0].clientX>(2*window.innerWidth)/3) :
position += 'right';
break;
default :
position += 'center';
break;
}
if (!(position in areas)) {
return true;
}
areas[position]();
if (repeat!==0) {
clearInterval(touchtimer);
touchtimer= setInterval(areas[position], repeat);
}
return false;
};
// Cancel timeout
document.onmouseup = document.ontouchend= function(e) {
clearInterval(touchtimer);
};
};
Now, all you need to do to attach a function to a touch event in the top-left area of the screen is:
I use this for direction control in the Mario Kart experiment which maps exactly onto the cursor keys used for the normal control.
TouchController({
'top-left': function() { // UP + LEFT
drawMap.move({y: 2});
drawMap.move({z: drawMap.z + 2});
drawMap.sprite(-1)
},
'top-center': function() { // UP
drawMap.move({y: 2});
},
'top-right': function() { // UP + RIGHT
drawMap.move({y: 2});
drawMap.move({z: drawMap.z - 2});
drawMap.sprite(1)
},
'middle-left': function() { // LEFT
drawMap.move({z: drawMap.z + 2});
drawMap.sprite(-1)
},
'middle-right': function() { // RIGHT
drawMap.move({z: drawMap.z - 2});
drawMap.sprite(1)
},
'bottom-left': function() { // DOWN + LEFT
drawMap.move({y: - 2});
drawMap.move({z: drawMap.z + 2});
drawMap.sprite(-1)
},
'bottom-center': function() {
drawMap.move({y: - 2});
},
'bottom-right': function() { // DOWN + RIGHT
drawMap.move({y: - 2});
drawMap.move({z: drawMap.z - 2});
drawMap.sprite(1)
},
}, 20);
If you need anything clever or you need two or more touches, you should use something else. This is just a simple drop-in for when you're copy-paste coding and want to include touch-screen support.
Just in case you don’t know, a Version Control System (VCS) is pretty much the most important thing ever in the history of anything ever. Just think about it conceptually: the ability to stand back and look at everything you’ve ever done, choose the good bits, drop the bad bits, mop up the mistakes… it gives you the freedom to “Play with it ‘til it breaks” with the safety net that you can always go back and fix it again.
You Get To Play With Time Itself!
There are many, many debates about the different methodologies you can use with version control and which technologies are best suited to which methodologies and which interfaces are best suited to which technologies and so on ad nauseam. The main concepts of working with any VCS are essentially the same, however.
It must be almost invisible.
It must be completely reliable
You mustn’t rely on it
It must be almost invisible
If you have never used a VCS before, it must fit perfectly into your workflow otherwise you won’t do it. It isn’t until you’ve been saved from potential disaster by a system that you will truly appreciate it and see the value in working it into your process. If you have or are currently using a VCS, think about when and how you use it. Does it require launching a new application or does it run in the background? Do you have to manually check things in or is it seamless versioning? The more effort required to mark a version, the less often you’ll do it as it breaks the flow of development
On the other hand, if the process is completely invisible, you might forget it’s there. It’s exactly the same as assuming your changes are going live on the server – the moment you assume it happens, it doesn’t. You still need some level of manual checking.
It must be completely reliable
This is fairly obvious, hopefully. You need the security that your version system is working otherwise you might again be tempted to miss it out – why take the extra step required to version a file if it’s not going to be there when I need it?
If you’re hosting your own repositories internally to your organisation, don’t put it on a server older than you are. The safest route to go down is contracted external hosting. That way, it’s someone’s job to make sure your datums are secure.
You mustn’t rely on it
Always have a backup. Always have a copy. Always have an escape route. Or something. You should have picked up the theme by now. Version Control Systems are great but as soon as it is the only thing standing between you and a complete failure to deliver a project, it will fail. Or not. It’s funny like that.