Automatically Backup Trello lists, cards and other data

Posted: June 20th, 2012 | Author: | Filed under: General | Tags: , , , , | No Comments »

Trello is a great service by FogCreek for managing data, based around Kanban boards and commonly used for project/time management (tho useful for many other things, too). I’ve been using it lately to manage my software development projects (using Scrum-like methodology with lists for my Backlog, Sprints, WIP, etc).

After a while I realized I’d become quite dependent on the data I store on Trello and that losing it could be very problematic. So, I wanted to setup automatic backups to my server. How can we do that?

First of all, for non-automatic backups, Trello gives a really nice JSON export of all the data, which you can get at Options -> Share, Print and Export -> Export data -> JSON. However, this requires an active authentication cookie and can’t be set easily to automatically run. To download automatic backups, we can use their API which provides similar functionality.

First of all, we need an application key and a user token. Just go here to get an application key, than to https://trello.com/1/authorize?key=YOURKEY&name=Backups&expiration=never&response_type=token (while logged-in to a Trello account with access to the board) to get a lifetime user token.

After you have those two, you can get all the available data on your board from the following URL:

https://api.trello.com/1/boards/[board]?key=[key]&token=[token]&actions=all&actions_limit=1000&cards=all&lists=all&members=all&member_fields=all&checklists=all&fields=all

To automate it, just add that to your crontab for a daily backup (with wget):

0 0 * * * wget -O /path/to/backup/trello.`date +\%Y-\%m-\%d`.json --no-check-certificate 'https://api.trello.com/...'

Notice the query string arguments I’m adding there: actions=all&actions_limit=1000&cards=all&lists=all&members=all&member_fields=all&checklists=all&fields=all. I’ve set it to download as much information as possible, but you can play around with that to download whatever you need. You can see the list of available options and values in Trello’s API documentation for boards.


Selectivizr, Internet Explorer and IDN domains

Posted: March 4th, 2012 | Author: | Filed under: Javascript, Web Development | Tags: , , , | No Comments »

Selectivizr is a cool JavaScript library that adds support for CSS3 selectors on Internet Explorer 6-8, which can save (and saves me!) a lot of  development time. Remember having to add <input class=”text”>, class=”last”, etc? Now you can just use[type=text] and :last-child, just like you can on all modern browsers.

So, recently I had a problem when uploading it from the development server to the production server – Selectivizr just stopped working when uploaded to the server, while the exact same files works on my dev machine.

After much debugging, the issue seems to be caused because the production server has an IDN domain (a domain with non-English characters that’s translated into punycode by the browser). IE’s document.location (wrongly!) returns the domain with the non-English characters intact, while I was embedding my CSS files using the punycode encoding in the URL.

This caused Selectivizr, which tries to figure out if the CSS files are on the same protocol/host/port and can be fetched using an XmlHttpRequest (under the same-domain origin restrictions), to think its hosted on a different domain and therefore ignores the CSS files.

The fix? Selectivizr also looks for an <base href=”"> tag to determine the base URL, as an alternative to using document.location which is perfect for this purpose. Simply add an base href set to the punycode-encoded URL of your website (do note that if you’re setting it to the base URL, it effects how relative URIs are resolved. If you prefer, you can set it to the full current URL which shouldn’t change anything) and everything should start working.

Also, you must have an / after the domain in your <base href>, or Selectivizr won’t work properly (I submitted a pull request that should fix that). If you’re using WordPress, the URL configured in Setting (and usually outputted in the template with get_option(‘home’)) never ends with an /, so you must add it manually, e.g. <base href=”<?php echo get_option(‘home’); ?>/“>


Custom URL format in jQuery-UI autocomplete source

Posted: February 26th, 2012 | Author: | Filed under: jQuery | Tags: , , | No Comments »

The jQuery UI autocomplete widget takes an URL as the value for the source and adds the search term as an term query string argument. If you need a different URL format, you would usually have to fallback to defining a function that manually calls $.get with your custom format. Instead, you can create a small reusable function that takes the format and returns a function.

It looks like that (CoffeeScript):

(JavaScript version available in the Gist)


Editing Stylus source in Aptana Studio

Posted: February 15th, 2012 | Author: | Filed under: Web Development | Tags: , , , , , | No Comments »

Just a quick tip. While Aptana Studio doesn’t have an editor mode for Stylus (an awesome CSS dialect) yet, it seems to work quite well when configured to treat .styl files as CSS files. The syntax highlighting looks good, it can mostly auto-complete CSS properties and values (depending on how much you use Stylus radical syntax) and can even spot some errors (though it does obviously treat some of Stylus syntax as errors, but not as much as one would expect).

To tell Aptana Studio to open Stylus files with the CSS editor, go to Window -> Preferences -> General -> Editors -> File Associations -> Under File types click Add… -> Under File type enter *.styl -> Click Ok -> Under Associated editors click Add… -> Select CSS Source Editor -> Click Ok.

If you want to see real Stylus support added to Aptana Studio, bug them about that in the ticket I opened :-)


Executing code in the webpage context from Chrome extensions

Posted: February 11th, 2012 | Author: | Filed under: Javascript | Tags: , , , | No Comments »

Content scripts on Chrome extensions run on a different context than the page they’re running on. They can access and manipulate the DOM, but they don’t have access to any variables of functions defined in the webpage.

It is, however, possible to inject new <script> tags into the page and execute code from there. Yet, passing data from the content script scope and getting data back isn’t very convenient – which is why I wrote a small function to make that easier.

To pass data into the webpage context, the inject function takes a function as its last arguments and passes all the arguments preceding it to that function. To get data back from the webpage context I’m taking advantage of the fact that appendChild is synchronous and blocks execution until the script is finished executing by replacing the <script> innerText with the return value.

Do note that all the data is exchanged in JSON format, so only primitive values and simple array/objects can be passed. When the code causes an exception, its stringified and thrown in the content script context (a magic isException property is used for that, so be careful not to use it for other purposes).

Here’s the function (written in CoffeeScript. For those of you still using JavaScript, the JavaScript version is available at the gist):

The usage:

Hope you found that useful. Enjoy.


PHP Benchmark: The array plus operator VS array_merge

Posted: August 13th, 2011 | Author: | Filed under: PHP | Tags: , , , | No Comments »

Just a quick post about a benchmark that quite surprised me. The array plus operator ($arr1 + $arr2) is over 6 times faster compared to array_merge. I did expect that to be faster, but not that much. This is the benchmark I used:

nadav@shesek:~$ time php -r '$x=array("x"=>1, "y"=>2); $y = array("y"=>3, "z"=>4);
> for ($i=1; $i<=500000; $i++) { $y + $x; }'

real	0m1.437s
user	0m1.392s
sys	0m0.024s


nadav@shesek:~$ time php -r '$x=array("x"=>1, "y"=>2); $y = array("y"=>3, "z"=>4);
> for ($i=1; $i<=500000; $i++) { array_merge($x, $y); }'

real	0m9.994s
user	0m7.472s
sys	0m2.400s

The results were about the same for several executions.

A couple of things should be be noted about the array plus operator:

  1. As opposed to array_merge, it overwrites numeric keys too. If you need to merge the values of two arrays with numeric keys, use array_merge instead
  2. If you need recursive merge, use array_merge_recursive instead.
  3. The values from the first array overwrites the values from the second, as opposed to array_merge. So the equivalent of array_merge($a, $b) is $b + $a, not $a + $b.
  4. Example:

    $arr = array('a' => 1, 'b' => 2, 'c' => 3);
    $arr = array('b' => 4) + $arr;
    // $arr is now array('a' => 1, 'b' => 4, 'c' => 3)
    

Chrome desktop notifications for GitHub

Posted: July 30th, 2011 | Author: | Filed under: General | Tags: , , , , , , | No Comments »

I’ve been looking for something to notify me about new GitHub notifications, and didn’t find anything. As I also wanted to take a look at the desktop notifications API, I decided to write a small Chrome extension that displays GitHub’s notifications as desktop notifications.

There’s no API or feed to get those notifications from, so I ended up scraping that data from the HTML page using XmlHttpRequest. The options page lets you set the interval for checking for new notifications.

You can browse the source at github.com/shesek/github-notifications, or download the packed extesntion here. Released under WTFPL 2.0.


Default arguments in JavaScript

Posted: July 30th, 2011 | Author: | Filed under: Javascript | Tags: , | No Comments »

Edit – Important: This will not work under ES5-strict, so you should probably not use that.

I’ve thought today on a nice and clean way of handling default function arguments in JavaScript. Because the arguments object in JavaScript defines getters and setters that also interact with the functions’s formal arguments, changing its values also changes the value of the local argument variables. For example:

function foo(bar) {
    arguments[0] = "baz";
    alert(bar); // bar is now "baz", not "qux"
}
foo("qux");

What that means is that we can pass the arguments object to another function, which can take care of setting default values and by that also modify our local argument variables:

window.setDefault = function (args) {
   for (var i = args.length + 1; i<arguments.length; i++) {
       args[i-1] = arguments[i];
   }
};
// Minified:
// window.setDefault=function(a){for(var b=a.length+1;b<arguments.length;b++)a[b-1]=arguments[b]}

(raw, minified(48 bytes))

Than, to use it:

function foo(bar, baz, qux) {
    setDefault(arguments, "bar", "baz", "qux");
    console.log(bar, baz, qux); // "a", "baz", "qux"
}
foo("a");

HTML escaping in Underscore.js templates

Posted: July 20th, 2011 | Author: | Filed under: Javascript | Tags: , , , | 1 Comment »

When displaying values in HTML templates, you would usually want to escape special HTML characters so that they’re displayed properly and to protect against XSS.

I’ve changed my local Underscore.js (and opened a pull request at Underscore.js’s github) to add support for _.escape() and a new <%== ... %> template syntax (notice the double equal signs) which escapes the value for displaying it in HTML.

Update 2011-10-05: The pull request has been merged to Underscore.js core.

If you want to add support for that, you can either apply my commit or simply use this code (make sure to load that after Underscore.js):

_.templateSettings.encode = /<%==([\s\S]+?)%>/g;
_.extend(_, {
	// Taken from Backbone.js's escapeHTML()
	escape: function(string) {
			return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
	},
	template: function(str, data) {
		var c  = _.templateSettings;
		var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
			'with(obj||{}){__p.push(\'' +
			str.replace(/\\/g, '\\\\')
				.replace(/'/g, "\\'")
				.replace(c.encode, function(match, code) {
					return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
				})
				.replace(c.interpolate, function(match, code) {
					return "'," + code.replace(/\\'/g, "'") + ",'";
				})
				.replace(c.evaluate || null, function(match, code) {
					return "');" + code.replace(/\\'/g, "'")
						.replace(/[\r\n\t]/g, ' ') + "__p.push('";
				})
				.replace(/\r/g, '\\r')
				.replace(/\n/g, '\\n')
				.replace(/\t/g, '\\t')
				+ "');}return __p.join('');";
		var func = new Function('obj', tmpl);
		return data ? func(data) : func;
	}
});

(raw, minified(835 bytes))

If you prefer and have no backward-compatibility issues with it, you can change the <%= ... %> syntax to be escaped by default, and use the double equal sign for cases you do want unescaped HTML. Use that code instead:

_.extend(_.templateSettings, {
	encode: /<%=([\s\S]+?)%>/g,
	interpolate : /<%==([\s\S]+?)%>/g
});
_.extend(_, {
	// Taken from Backbone.js's escapeHTML()
	escape: function(string) {
			return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
	},
	template: function(str, data) {
		var c  = _.templateSettings;
		var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
			'with(obj||{}){__p.push(\'' +
			str.replace(/\\/g, '\\\\')
				.replace(/'/g, "\\'")
				.replace(c.interpolate, function(match, code) {
					return "'," + code.replace(/\\'/g, "'") + ",'";
				})
				.replace(c.encode, function(match, code) {
					return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
				})
				.replace(c.evaluate || null, function(match, code) {
					return "');" + code.replace(/\\'/g, "'")
						.replace(/[\r\n\t]/g, ' ') + "__p.push('";
				})
				.replace(/\r/g, '\\r')
				.replace(/\n/g, '\\n')
				.replace(/\t/g, '\\t')
				+ "');}return __p.join('');";
		var func = new Function('obj', tmpl);
		return data ? func(data) : func;
	}
});

(raw, minified (878 bytes))

P.S. Can anyone think of a nicer syntax than <%== ... %>? I don’t really like it, but I didn’t come up with anything better…


“Singleton” initializer in Javascript

Posted: July 19th, 2011 | Author: | Filed under: Javascript, Web Development | Tags: , , | No Comments »

The nature of javascript makes it quite easy to have singleton-like behavior without actually using the singleton design pattern – simply define an object with some properties and use that. No need to do anything more than that, really – there’s no reason to create a prototyped function, create an instance and keep a reference to it when javascript gives you a much more natural and elegant solution.

For example:

var Foo = {
  bar: 123,
  a: function() { /* ... */ }
  /* ... */
};
// Simply use Foo as a "singleton"

However, one thing that is missing from the singleton pattern is that the constructor is called only once, and only at the moment someone requests an instance, so it doesn’t run any code to initialize the object unless actually necessary.

Here’s my way of doing that in javascript:

var ObjectInitializer = function(object) {
  var initialized = false;
  return function() {
    if (!initialized) {
      object.initialize();
      initialized = true;
    }
    return object;
  };
};

To use that, simply add an initialize property on the object with the code to execute when the object is requested the first time, and pass it to ObjectInitializer, which’ll return an anonymous function that calls the initialize method the first time its accessed and returns the object, or simply returns the object otherwise.

Example:

var Foo = ObjectInitializer({
  a: 3,
  b: 2,
  initialize: function() {
    this.b += this.a;
  },
  increase: function() {
    this.b++;
    return this;
  }
});

var foo = Foo();
alert(foo.b); // 5
foo.increase();
alert(foo.b); // 6
var bar = Foo();
alert(bar.increase().b); // 7
alert(Foo().increase().b); // 8