Posted (Updated ) in Javascript, PHP

If you’re reading this page (or my blog in general) it’s a pretty safe bet you already have Google+. If you’ve uploaded any photos to Google+ from Chrome or FF, you would also have noticed its snazzy HTML5 file uploader at work. This weekend I took it upon myself to whip up a quick and dirty version of that uploader and share its inner workings with the world.

Google+ Image Uploader
Google+ Image Uploader

Here’s a short video of my uploader at work:

https://www.youtube.com/watch?v=AXx8cu6rxV4

Requirements:

  • PHP4+
  • HTML5-enabled browser (File API – including drag and drop, XHR2)
  • Some images to upload

Disclaimer: Currently only Firefox and Webkit based browsers meet the requirements above. Opera supports the File API and probably XHR2 (I haven’t tested), however it doesn’t have drag and drop so this tutorial won’t work with it. If you’re curious about whether or not IE will work with this tutorial, I’m already laughing at you.

Download the finished script here.

Read More »

Posted (Updated ) in Linux

Update 2011-10-26: Added support for Ubuntu 11.04+ which uses slightly different FTP folder names

Lack of FTP keepalive functionality in Nautilus has been one of my biggest gripes in Ubuntu for a long time now. It’s infuriating attempting to open a folder only to discover the session has timed out and I need to reconnect. Well that problem is now solved!

Run the following bash script in the background each time you boot and you’re good to go:

#!/bin/bash
 
while true
do
	#10.10 and earlier
	ls ~/.gvfs/ftp* &> /dev/null
	#11.04+
	ls ~/.gvfs/FTP* &> /dev/null
	sleep 15
done

Many thanks go to the user who originally posted this script in a mailing list here.

PS. If anyone knows how to integrate this into a nautilus script I’d much appreciate it!

Read More »

Posted (Updated ) in Linux, Uncategorized

I’m currently working on a mobile version of an existing website utilizing the Responsive Web Design paradigm. One problem I instantly came across was a perplexing page width issue on Android. Even with a blank, HTML5 webpage, the page width was appearing at almost twice the width of my phones native resolution (and 2.5x that of my browsers width). For the record, I’m using Android 2.3.3 vanilla with the default browser on a Nexus One.

Firstly an example:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' />
<script type='text/javascript'>
	$(document).ready(function() {
		document.body.innerHTML = $(window).width();
	});
</script>
</head>
<body>
</body>
</html>

The above code gives a blank, HTML5 webpage that will display the pages width on load. When loaded, it would print ‘800’ on the screen – indicating the page was set to an 800px width. This was clearly wrong.

I quickly noticed that using the following doctype:

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">

gave me the width I was expecting – 320px. Obviously this isn’t an acceptable solution for responsive web design and so another was needed. Meet viewports. With the addition of a simple META tag I was able to fix the issue (albeit losing the ability to zoom in the process). Simply add the following to your HEAD tag and you should be good to go:

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;" />

With this line added, my page now prints 320 to the screen as it should.

For more information, please see this StackOverflow post on the issue.

Read More »

Posted (Updated ) in Javascript

It appears JQuery Form Validation supports returning a string when using the remote validator but it’s not immediately clear how to do this and the examples tab doesn’t have an example for doing so. Getting this working is actually very easy. All you need to do is return a JavaScript string in your response. Here’s an example:

Firstly, the javascript:

$(document).ready(function() {
	$("#form").validate({
		rules: {
			username: {
				required: true,
				remote: "/your/url.php"
			}
		},
		messages: {
			username: "Username is required."
		}
	});
});

Pretty standard, nothing out of the ordinary here. Now for the server side response. As I’m sure you’re aware, you can return ‘true’ or ‘false’ however if you want a string, it needs to be formatted as a javascript string:

// /your/url.php
echo '"This username is already taken. Please enter a different username and try again."';

Read More »

Posted (Updated ) in Linux

Tonight I needed to transfer files directly between two servers via the terminal and figured this would be useful information for others, so here’s how to do it:

Upload to a remove server:

$ ssh username@remote_address cat < localfile ">" remote_file

Download to your server:

$ ssh username@remote_address cat remote_file > local_file

Source: the incomplete news project

Read More »

Posted (Updated ) in Uncategorized

I’ve been frustrated for a while now at Chromes lack of a decent Amazon S3 extension. Firefox has S3Fox but the closest Chrome users come is S3 which only lets you browse and not modify the files in your buckets. Well that’s just changed!

Over the weekend I finally gathered up enough free time to add support for creation and deletion of files/buckets. While I was in there I made a few other modifications to improve performance and clean things up a bit.

Download the latest version (and the source: Github repo)

Adding a bucket
Adding a bucket
Deleting a bucket
Delete link when hovering over buckets
Adding files
Multi-select file browser for uploading files
Uploading Files
The uploading window
File delete
The confirmation you see when deleting files
Deleting a bucket with files in it
Error you see when attempting to delete a bucket with files in it

Read More »

Posted (Updated ) in Database

Earlier today I completed my first project in Django and it came time to do some database optimization. I wanted to get a list of SQL queries executed for each page and a bit of Googling let me to this script on DjangoSnippets. It did everything I needed it to do, however I noticed it interfered with dynamically generated binary file outputs (such as the images made with django-simple-captcha). For this I needed to check if the output was in binary, and if so just return it without attempting to print the SQL log. I found what I was looking for here and after combining the two had the perfect SQL logger! Below is my finished code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from django.db import connection
from django.template import Template, Context
import string 
#http://djangosnippets.org/snippets/161/class SQLLogMiddleware:
    def process_response ( self, request, response ):
        #Don't print SQL queries for binary outputs!        if istext(response.content) == 0:            return response 
        time = 0.0
        for q in connection.queries:
            time += float(q['time'])
 
        t = Template('''
            <p><em>Total query count:</em> {{ count }}<br/>
            <em>Total execution time:</em> {{ time }}</p>
            <ul class="sqllog">
                {% for sql in sqllog %}
                    <li>{{ sql.time }}: {{ sql.sql }}</li>
                {% endfor %}
            </ul>
        ''')
 
        response.content = "%s%s" % ( response.content, t.render(Context({'sqllog':connection.queries,'count':len(connection.queries),'time':time})))
        return response
 
#http://code.activestate.com/recipes/173220-test-if-a-file-or-string-is-text-or-binary/def istext(s):
    if "\0" in s:
        return 0
 
    if not s:  # Empty files are considered text
        return 1
 
    # Get the non-text characters (maps a character to itself then
    # use the 'remove' option to get rid of the text characters.)
    t = s.translate(string.maketrans("", ""), "".join(map(chr, range(32, 127)) + list("\n\r\t\b"))) 
    # If more than 30% non-text characters, then
    # this is considered a binary file
    if float(len(t))/len(s) >= 0.30:        return 0

To get this working on your site just add it to your MIDDLEWARE_CLASSES in settings.py and make DEBUG is set to True.

Read More »

Posted (Updated ) in PHP

While aimlessly browsing my Twitter feed last night, I came across this tutorial on using CodeIgniter‘s Zip class. Kohana 3.1 doesn’t seem to come with similar functionality out of the box (at least from the brief glance I took), so I figured I’d write up a quick patch to get CI’s class working with it.

Download the module with example controller and test files here.

You can read up on how to use the class in CodeIgniter’s documentation or the tutorial linked to above. I’ve included a controller and 2 test files in the download above as a kind of ‘quick start guide’. To access them simply go to /koziptest and /koziptest/invalid for a successful and unsuccessful download respectively.

There isn’t really any more to say about this one other than the fact that I made the methods in my module chainable for convenience and consistency with other Kohana classes. Note that this means the read_file, read_dir and archive methods will now throw exceptions if you use an invalid file/directory path or your input or output files aren’t readable/writable – so remember to use a try..catch block! I’ve also made the download method take a Request variable as its first argument – simply pass your controllers current request to it like so:

$Zip->download( $this->response )

Read More »

Posted (Updated ) in Uncategorized

If you’re paginating your data and have tens or hundreds of pages, chances are you’d prefer only a subset of these be displayed in your page number list (example – see page list at bottom). Django-paginator gets 90% of your work done for you however it doesn’t support this one very useful feature. To make a developers life easier, meet flynsarmy_paginator!

flynsarmy_pagination
flynsarmy_pagination in action

 

Download it here.

This app is a simple subclass of django’s built in Paginator and Page classes. The only changes I’ve made are to add an optional adjacent_pages parameter to FlynsarmyPaginator and a .page_range_data variable to the FlynsarmyPage object with the following contents:

  • page_range – same as Paginator.page_range – a list of page numbers but only showing a subset of pages if adjacent_pages was specified in the FlynsarmyPaginator constructor.
  • show_first – Boolean value set to True if ‘1’ isn’t present in the page_range list above.
  • show_last – Boolean vlaue set to True if the last page isn’t present in the page_range list above.

Read More »

Posted (Updated ) in Linux

Update 2011-11-20: Now working with Ubuntu 11.10+

I’ve always been pretty jealous of my Windows 7-using friends with their fancy rotating backgrounds so I thought I’d do a bit of research into adding similar functionality into Ubuntu. After a little investigation I found that sure enough, Ubuntu supported background lists through the use of XML files. The only problem now was: How do I automatically generate the XML file and set the active background to it?

Behold! My automatic rotating background generator! Below is the code, or you can download it here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/bin/bash
 
#
# Author: Flynsarmy
# Contributor: Ariel Barabas (ariel.baras atGmail)
#
 
#interval in seconds
INTERVAL=1800
OUTFILE=backgrounds.xml
DIR=$(pwd)
 
if [ $1 ]; then
	if [ $1 == "--help" ]; then
		echo "	Creates the background configuration xml file with 30min of delay between pictures with the images found in the same directory, you can modify that delay entering other number
Example:
	./createSlideShow.sh 15		makes the delay of 15 minutes"
		exit
	else
		INTERVAL=$(expr $1 \* 60)
	fi
fi
 
echo "<background>
  <starttime>
    <year>2009</year>
    <month>08</month>
    <day>04</day>
    <hour>00</hour>
    <minute>00</minute>
    <second>00</second>
  </starttime>
" > $OUTFILE
 
while read -r IMG;
do
	if [ "$FIRST_IMG" ]; then
		echo "<transition>
	<duration>5.0</duration>
	<from>$DIR/$LAST_IMG</from>
	<to>$DIR/$IMG</to>
</transition>" >> $OUTFILE
	else
		FIRST_IMG="$IMG"
	fi
 
	echo "<static>
	<duration>$INTERVAL</duration>
	<file>$DIR/$IMG</file>
</static>
 
" >> $OUTFILE
done < <(find -name "*.jpg" -o -name "*.png" -o -name "*.gif" | shuf)
 
echo "<transition>
	<duration>5.0</duration>
	<from>$DIR/$LAST_IMG</from>
	<to>$DIR/$FIRST_IMG</to>
</transition>
 
</background>" >> $OUTFILE
if hash gsettings &>/dev/null; then
	gsettings set org.gnome.desktop.background picture-uri "file://$DIR/$OUTFILE"
else
	gconftool-2 -t string --set /desktop/gnome/background/picture_filename "$DIR/$OUTFILE"
fi

Remember to chmod +x ./createSlideshow.sh to add execute permissions then ./createSlideshow.sh to run it.

Unlike the original script (written by Ariel Barabas), this version will search recursively from its location for jpg, png and gif files and will work with files/folders containing spaces in their names. It also shuffles the files in the slideshow so if you need to regenerate the background list you won’t get the same list every time.

It defaults to rotating every 3 minutes but you can change this by using ./createSlideshow.sh <minutes>.

Have fun with it!

Read More »