function Patchwork( jContainer, jItems ) {
	this.trigger	= function( name, context ) {
		if ( 'undefined' == typeof this.callbacks[ name ] ) {
			return false;
		}
		if ( 'array' != typeof context ) {
			context	= [ context ];
		}
		this.callbacks[ name ].apply( this, context );
	}
	this.getItemAt	= function( i ) {
		if ( i >= 0 && i < this.size() ) {
			return this.items[ i ];
		}
		return null;
	}
	this.size		= function() {
		return this.items.length;
	}
	this.bind		= function() {
		var max_width	= this.container.width();
		var max_height	= this.container.height();

		this.trigger( Patchwork.Events.Start, {
			target:	this
		} );

		this.container.css( {
			position:	'relative',
			overflow:	'hidden'
		} );

		var ref	= this;
		jQuery.each( this.items, function( i ) {
			var t			= jQuery(this);

			ref.trigger( Patchwork.Events.BeforeItemBound, {
				target:	t,
				index:	i
			} );

			if ( ref.current_y >= max_height ) {
				t.remove();
				ref.items.splice( i, 1 );
				return true;
			}

			t.css( {
				position:	'absolute',
				top:		ref.current_y,
				left:		ref.current_x
			} );

			ref.current_x	+= t.width();

			if ( ref.current_x > max_width ) {
				ref.current_x	= 0;
				ref.current_y	+= t.height();
			}

			ref.trigger( Patchwork.Events.AfterItemBound, {
				target:	t,
				index:	i
			} );
		} );

		this.trigger( Patchwork.Events.Complete, {
			target:	this
		} );

		return this;
	}

	this.container	= jContainer;
	this.items		= jItems;
	this.current_x	= 0;
	this.current_y	= 0;
	this.callbacks	= arguments.length > 2 ? arguments[ 2 ] : {};
}
Patchwork.Events	= {
	BeforeItemBound:	'onBeforeItemBound',
	AfterItemBound:		'onAfterItemBound',
	Start:				'onBindStart',
	Complete:			'onBindComplete'
}