Recursive Backbone.Model’s toJSON()

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

If you’re using collections and models as attributes for other models, calling toJSON() on Backbone.Model objects isn’t very useful as it returns the models and collections as-is. I’ve opened an issue requesting to make it recursive, but it seems like its not going to be added.

If anyone still wants this functionality, you can use that modified version of Backbone.Model.prototype.toJSON that I added to the issue:

Backbone.Model.prototype.toJSON = function() {
    if (this._isSerializing) {
        return this.id || this.cid;
    }
    this._isSerializing = true;
    var json = _.clone(this.attributes);
    _.each(json, function(value, name) {
        _.isFunction(value.toJSON) && (json[name] = value.toJSON());
    });
    this._isSerializing = false;
    return json;
}

akismet_recheck_queue returning a blank page / not found?

Posted: July 17th, 2011 | Author: | Filed under: Wordpress | Tags: , , , , , | No Comments »

If your blog has large number of comments in the moderation queue, akismet “check for spam” option that tries to filter out spam from your moderation queue could execute for too long, die, and return either a blank page or a ‘page not found’ error.

However, Akismet does manage to check some comments every time you run it, so if you’ll keep refreshing it you’ll see the number of comments in the moderation queue drop slowly.

As I have over 50K of comments in the moderation queue and no time to keep hitting refresh, I wrote a small hacky javascript code that does that automatically by refreshing an iframe. Just paste the following code in the address bar while you’re on any page (make sure you change YOUR-WORDPRESS_URL) and let it run for some time (make sure the page you wrote that in stays open):

javascript:(function(f,b){b.appendChild(f); f.style.display='none'; setInterval(function() { f.src='http://YOUR-WORDPRESS-URL/wp-admin/admin.php?action=akismet_recheck_queue&'+Math.random(); }, 15000);})(document.createElement('iframe'), document.body)

Or simply click here, input your base WordPress URL and let it run overnight (make sure to keep this post open until it finishes).


Create jQuery-UI widgets from HTML markup

Posted: April 19th, 2011 | Author: | Filed under: jQuery | 2 Comments »

Many times I add UI enhancements using jQuery UI, like buttons, datepickers, tabs, etc that requires very simple JavaScript code without much logic. Having to add JavaScript code for those small enhancements quickly became annoying for me. To overcome this, I’ve been using CSS classes like “jq-datepicker”, than execute $(‘.jq-datepicker’).datepicker() in a file that’s globally used on all pages of the website – a much better solution, but not quite perfect.

Today I thought on a very simple concept that makes is extremely easy to create jQuery UI widgets from HTML markup – why not simply add an attribute with the jQuery method to execute on the element?

Some examples would make it clearer: (only works on the single post page)

  • Button:

    <a href="#" data-jq="button">Hello, World</a>
    

    Hello, World

  • Date picker:

    <input type="text" data-jq="datepicker" />
    

Code:

Very simple. Looks for elements with ‘data-jq’ attribute, iterate over them and call the specified method on them:

(function($){ $(function() {
	$('[data-jq]').each(function() {$(this)[$(this).data('jq')]();});
}); })(jQuery);

Is adding custom attributes valid?

Technically? No. HTML5 does support custom attributes when their name is prefixed with ‘data-’. However, the HTML5 specs are not done yet and its not fully supported in all browsers.
That being said – it does currently work well on all the major browsers and you know it’ll continue working into the future when HTML5 is officially out. Also, if you’re use the HTML5 DOCTYPE (<!DOCTYPE html>), it’ll pass HTML5 validation.

What about arguments?

What if you need to pass arguments to that call? I personally think that those arguments doesn’t belong in HTML. The purpose of this isn’t to have your JavaScript logic in your HTML, but merely mark that an element should use a specific widget. If you need arguments, create a custom jQuery.fn method that wraps the call to the jQuery method with those arguments (or any other complex logic), than use that method. For example, if you want to use the datepicker widget with a different dateFormat, create jQuery.fn.mydatepicker() method:

$.fn.mydatepicker = function() {
	return this.datepicker({dateFormat: 'yy-mm-dd'});
};

Than use that method for the data-jq attribute:

<input type="text" data-jq="mydatepicker" />

However, it is possible to add support for custom arguments. Again, I do not recommend it, but its easily doable:

(function($){ $(function() {
	$('[data-jq]').each(function() {
		var $t = $(this), args = $t.data('jqa') ? $.parseJSON($t.data('jqa')) : [];
		$t[$t.data('jq')].apply($t, $.isArray(args)?args:[args]);
	});
}); })(jQuery);

Than you can define an ‘data-jqa’ attribute with a JSON string. It can either be a single argument, or an array of arguments. For example, to set the dateFormat using that attribute, you could this code which’ll produce the same result as above:

<input type="text" data-jq="datepicker" data-jqa="{&quot;dateFormat&quot;:&quot;yy-mm-dd&quot;}" />

Do note that it uses jQuery.parseJSON(), which requires a valid JSON string, so you must use double quotes for string literals and quote the object keys, which makes the HTML somewhat ugly, especially with the html encoding for the quotes.



Quick fix for Trac Babel/Locale issue

Posted: March 10th, 2011 | Author: | Filed under: Trac | Tags: , , | No Comments »

After installing Babel on our development machine, Trac died with that error:
OSError: [Errno 2] No such file or directory: '/usr/local/lib/python2.6/dist-packages/Trac-0.12-py2.6.egg/trac/locale'

The issue seems to be related to #9439: When installing Trac, it checks whether Babel is installed or not. When Babel is installed, Trac also installs the locale files. The problem occurs when Babel is installed after installing Trac, because Trac expects the locale files to exists when Babel is installed.

As I don’t use locale with Trac, I couldn’t delete Babel (because I do use it with other stuff) and I didn’t want to re-install Trac – I took the hacky solution and modified trac/web/main.py so it’ll ignore the fact that Babel is installed and won’t use it at all. This can be done by commenting out the part that tries to import babel and setting the Locale to None manually. Open trac/web/main.py, look for (should be at line 29):

try:
    from babel import Locale
except ImportError:
    Locale = None

and replace with:

#try:
#    from babel import Locale
#except ImportError:
#    Locale = None
Locale = None

Yes – very much hacky, but it works as a quick solution for now, as we must have Trac up and running. I will be looking for a better solution and update this post.


Backup all SVN repostiroes using a one-liner Shell script

Posted: March 9th, 2011 | Author: | Filed under: SVN | Tags: , , , | No Comments »

Just a quick one-liner to backup all your SVN repositories. It lists the directories under the main SVN directory, uses xargs to run the dump for every repository, gzip’s the dump and saves each dump to a file named according to the repository name and the current date.

In this example, the main SVN directory is /var/svn/ and the backup location is /backup/svn/. Change those to the paths used by you.

ls /var/svn/ | xargs -I {} sh -c "svnadmin dump /var/svn/{} | gzip -c > /backup/svn/{}.`date +'%F'`.dump.gz"

You can also SCP the backup to a remote server using this:

ls /var/svn/ | xargs -I {} sh -c "svnadmin dump /var/svn/{} | gzip -c > /backup/svn/{}.`date +'%F'`.dump.gz; scp -p /backup/svn/{}.`date +'%F'`.dump.gz username@hostname:/backup/svn/"

Generic PHP object wrapper for resources

Posted: March 7th, 2011 | Author: | Filed under: PHP | Tags: , , | No Comments »

I hate working with PHP’s resources. I hate the long function names, I hate repeating the function names prefix, I hate having to pass around the resource variable. It looks like hack that was used instead of real object and classes and it feels dirty compared to OOP code. I personally think it should’ve been replaced with real classes and objects a long time ago. </whining>

So, I thought on a simple way to wrap it with a class that lets you work with those resources as-if they were real objects. Basically, its a simple class that wraps the resource, configured with the functions prefix and has some __call() magic.

For example, when working with GD, that code:

$image = imagecreate(150, 50);
$bg = imagecolorallocate($image, 255, 255, 255);
$red = imagecolorallocate($image, 255, 0, 0);
imagestring($image, 2, 2, 2, 'Hello, world!', $red);
imagejpeg($image);

Can be written as:

$image = new ResourceWrapper('image', 'create', 150, 50);
$bg = $image->colorAllocate(255, 255, 255);
$red = $image->colorAllocate(255, 0, 0);
$image->string(2, 2, 2, 'Hello, world!', $red);
$image->jpeg();

The ResourceWrapper class constructor takes the function names prefix as its first argument (e.g. ‘image’ for GD, ‘mysql_’ for mysql, ‘bz’ for bzip, etc) and the function used to create the resource as the second argument (without the prefix). The rest of the argument are passed untouched to that method. In that example, it’ll call imagecreate(150, 150) and store the resource as a property on the object.

Than, every call on that object is handled using __call() magic. The function prefix is added to method that was called, the stored resource is passed along all the other arguments and the return value from that function is returned.

The resource is passed, by default, as the first argument to the function calls. In some cases, like mysql, it should be passed last. The can be changed using $object->_setPosition(ResourceWrapper::POS_LAST).

This is the code for the ResourceWrapper class:

/**
 * A wrapper class for PHP resourcse.
 * 
 * Used for wrapping PHP resources in an object, and working with them in an
 * Object-Oriented manner.
 * 
 * Some methods are prefixed with `_` even though they're public to avoid
 * clashes with resource-related functions.
 * 
 * @author Shesek <th[e]@RemoveMe.shesek.inf[o]>
 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
 * @see http://www.shesek.info/php/generic-php-object-wrapper-for-resources
 */

class ResourceWrapper {
	/**
	 * POS_FIRST and POS_LAST are used to set the correct position of the
	 * resource argument on function calls. 
	 */
	const POS_FIRST = 1;
	const POS_LAST = 2;

	/**
	 * Holds the PHP resource being wrapped 
	 * 
	 * @var resource
	 */
	protected $resource;
	
	/**
	 * The prefix for functions related to this resource
	 * 
	 * e.g. 'image' for GD, 'mysql_' for mysql, 'bz' for bzip, etc
	 * 
	 * @var string
	 */
	protected $prefix;
	
	/**
	 * The position of the resource argument on function calls
	 * 
	 * Either ResourceWrapper::POS_FIRST or ResourceWrapper::POS_LAST
	 * 
	 * @var integer
	 */
	protected $resource_position = 1;

	/**
	 * The constructor creates the PHP resource and stores it locally on the object.
	 * 
	 * The $prefix and $method arguments are used to determine the function name,
	 * and the rest of the arguments are passed untouced to it.
	 * 
	 * For example, passing 'mysql_' as the $prefix and 'connect' as the $method
	 * would cause it to call mysql_connect(), with the other parameters.
	 * 
	 * new ResourceWrapper('mysql_', 'connect', 'localhost', 'nadav')
	 * is translated to mysql_connect('localhost', 'nadav')
	 * 
	 * @param string $prefix
	 * @param string $method
	 */
	public function __construct($prefix, $method) {
		$this->prefix = $prefix;
		$args = func_get_args();
		$this->resource = $this->__call($method, array_slice($args, 2));
	}

	/**
	 * Delegates calls to the original PHP functions while passing the resource.
	 * 
	 * Adds the function prefix (as defined in the constructor) to the method name
	 * being called, passes the resource along with the other arguments, invokes
	 * the original function and return the return value from it. 
	 * 
	 * @param string $method
	 * @param array $args
	 * @return mixed
	 */
	public function __call($method, $args) {
		if (!is_null($this->resource)) {
			if ($this->resource_position === self::POS_FIRST) {
				array_unshift($args, $this->resource);
			}
			else {
				array_push($args, $this->resource);
			}
		}
		return call_user_func_array($this->prefix . $method, $args);
	}

	/**
	 * Set wheter the resource should be passed last or first in the arguments.
	 * 
	 * @param	integer	$position	ResourceWrapper::POS_FIRST or ResourceWrapper::POS_LAST
	 */
	public function _setPosition($position) {
		$this->resource_position = $position;
		return $this;
	}

	/**
	 * Returns the wrapped PHP resource.
	 * 
	 * @return resource
	 */
	public function _getResource() {
		return $this->resource;
	}

	/**
	 * Magic toString conversion
	 */
	public function __toString() {
		return 'ResourceWrapper for '.get_resource_type($this->resource);
	}
}

That’s about it. Its very simple – but makes the code more organized and look nicer. In my opinion, it feels much more natural that way.

You can also download it here. Released under CC-BY 3.0.


Transform a transparent PNG to white-background JPG using PHP GD

Posted: October 14th, 2010 | Author: | Filed under: PHP | Tags: , , , , , | No Comments »

It seems like Facebook doesn’t handle transparent PNG files very well (they’re transformed into JPG without handling the transparent background, which ends up as a weird black background), so we needed to transform it ourselves to a white-background JPG to make it display well:

function imagetranstowhite($trans) {
	// Create a new true color image with the same size
	$w = imagesx($trans);
	$h = imagesy($trans);
	$white = imagecreatetruecolor($w, $h);

	// Fill the new image with white background
	$bg = imagecolorallocate($white, 255, 255, 255);
	imagefill($white, 0, 0, $bg);

	// Copy original transparent image onto the new image
	imagecopy($white, $trans, 0, 0, 0, 0, $w, $h);
	return $white;
}

Can be used like that:

// Open original PNG image
$png = imagecreatefrompng($path);
// Transform to white-background JPEG
$jpg = imagetranstowhite($png);
// Save new image
imagejpeg($jpg, $new_path);

Clone an array of objects using jQuery

Posted: September 26th, 2010 | Author: | Filed under: jQuery | Tags: , , , , | No Comments »

Well, I guess most of you already know that cloning an object in jQuery is possible using jQuery.extend({}, obj) and jQuery.extend({}, obj) for deep copy. Combine it with map, and you can clone an object of arrays:

// Shallow copy of each object:
jQuery.map(arr, function(obj){return jQuery.extend({}, obj);});

// Deep copy of each object:
jQuery.map(arr, function(obj){return jQuery.extend(true, {}, obj);});

// Using the $ shortcut
$.map(arr, function(obj){return $.extend({}, obj);}); // shallow
$.map(arr, function(obj){return $.extend(true, {}, obj);}); // deep

Enjoy.


Submit forms when CTRL+Enter is pressed in a textarea using jQuery

Posted: September 22nd, 2010 | Author: | Filed under: jQuery, Web Development | Tags: , , | No Comments »

Many applications and websites support submitting a form when CTRL+Enter is pressed in a textarea, in the same way its submitted when enter is pressed on single-line input box.

This is how we added that functionality to our websites using jQuery:

$('textarea').keypress(function(e){
    if (e.ctrlKey && e.keyCode == 13) {
        $(this).closest('form').submit();
    }
});

Have fun.


jQuery :focus selector expression

Posted: September 22nd, 2010 | Author: | Filed under: Javascript, jQuery, Web Development | Tags: , , , , , | No Comments »

Just a quick code snippet I wrote for someone on IRC: (should work, but wasn’t really tested)

// Support for browsers that doesn't set document.activeElement
if (typeof document.activeElement === 'undefined') {
	$(document)
		.focusin(function(e){ document.activeElement = e.target; })
		.focusout(function(){ document.activeElement = null; });
}
// Adding a ':focus' expression
jQuery.expr[':'].focus = function(a){ return a === document.activeElement; }

You can use it like that:

$('input:focus'); // Find a focused input.
$(...).is(':focus'); // Test whether an element is focused or not.
$(document.activeElement); // Get the currently focused element as a jQuery object.
$(':focus'); // Same as last one, but MUCH MUCH slower and resource intensive.