The source code

    var ImageChooser = function(config){
    	this.config = config;
    }

    ImageChooser.prototype = {
        // cache data by image name for easy lookup
        lookup : {},

    	show : function(el, callback){
    		if(!this.win){
    			this.initTemplates();

    			this.store = new Ext.data.JsonStore({
    			    url: this.config.url,
    			    root: 'images',
    			    fields: [
    			        'name', 'url',
    			        {name:'size', type: 'float'},
    			        {name:'lastmod', type:'date', dateFormat:'timestamp'}
    			    ],
    			    listeners: {
    			    	'load': {fn:function(){ this.view.select(0); }, scope:this, single:true}
    			    }
    			});
    			this.store.load();

    			var formatSize = function(data){
    		        if(data.size < 1024) {
    		            return data.size + " bytes";
    		        } else {
    		            return (Math.round(((data.size*10) / 1024))/10) + " KB";
    		        }
    		    };

    			var formatData = function(data){
    		    	data.shortName = data.name.ellipse(15);
    		    	data.sizeString = formatSize(data);
    		    	data.dateString = new Date(data.lastmod).format("m/d/Y g:i a");
    		    	this.lookup[data.name] = data;
    		    	return data;
    		    };

    		    this.view = new Ext.DataView({
    				tpl: this.thumbTemplate,
    				singleSelect: true,
    				overClass:'x-view-over',
    				itemSelector: 'div.thumb-wrap',
    				emptyText : 'No images match the specified filter',
    				store: this.store,
    				listeners: {
    					'selectionchange': {fn:this.showDetails, scope:this, buffer:100},
    					'dblclick'       : {fn:this.doCallback, scope:this},
    					'loadexception'  : {fn:this.onLoadException, scope:this},
    					'beforeselect'   : {fn:function(view){
    				        return view.store.getRange().length > 0;
    				    }}
    				},
    				prepareData: formatData.createDelegate(this)
    			});

    			var cfg = {
    		    	title: 'Choose an Image',
    		    	id: 'img-chooser-dlg',
    		    	layout: 'border',
    				minWidth: 500,
    				minHeight: 300,
    				modal: true,
    				closeAction: 'hide',
    				border: false,
    				items:[{
    					id: 'img-chooser-view',
    					region: 'center',
    					autoScroll: true,
    					items: this.view,
                        tbar:[{
                        	text: 'Filter:'
                        },{
                        	xtype: 'textfield',
                        	id: 'filter',
                        	selectOnFocus: true,
                        	width: 100,
                        	listeners: {
                        		'render': {fn:function(){
    						    	Ext.getCmp('filter').getEl().on('keyup', function(){
    						    		this.filter();
    						    	}, this, {buffer:500});
                        		}, scope:this}
                        	}
                        }, ' ', '-', {
                        	text: 'Sort By:'
                        }, {
                        	id: 'sortSelect',
                        	xtype: 'combo',
    				        typeAhead: true,
    				        triggerAction: 'all',
    				        width: 100,
    				        editable: false,
    				        mode: 'local',
    				        displayField: 'desc',
    				        valueField: 'name',
    				        lazyInit: false,
    				        value: 'name',
    				        store: new Ext.data.ArrayStore({
    					        fields: ['name', 'desc'],
    					        data : [['name', 'Name'],['size', 'File Size'],['lastmod', 'Last Modified']]
    					    }),
    					    listeners: {
    							'select': {fn:this.sortImages, scope:this}
    					    }
    				    }]
    				},{
    					id: 'img-detail-panel',
    					region: 'east',
    					split: true,
    					width: 150,
    					minWidth: 150,
    					maxWidth: 250
    				}],
    				buttons: [{
    					id: 'ok-btn',
    					text: 'OK',
    					handler: this.doCallback,
    					scope: this
    				},{
    					text: 'Cancel',
    					handler: function(){ this.win.hide(); },
    					scope: this
    				}],
    				keys: {
    					key: 27, // Esc key
    					handler: function(){ this.win.hide(); },
    					scope: this
    				}
    			};
    			Ext.apply(cfg, this.config);
    		    this.win = new Ext.Window(cfg);
    		}

    		this.reset();
    	    this.win.show(el);
    		this.callback = callback;
    		this.animateTarget = el;
    	},

    	initTemplates : function(){
    		this.thumbTemplate = new Ext.XTemplate(
    			'',
    				'',
    				'',
    				'{shortName}',
    			''
    		);
    		this.thumbTemplate.compile();

    		this.detailsTemplate = new Ext.XTemplate(
    			'',
    				'',
    					'',
    					'Image Name:',
    					'{name}',
    					'Size:',
    					'{sizeString}',
    					'Last Modified:',
    					'{dateString}',
    				'',
    			''
    		);
    		this.detailsTemplate.compile();
    	},

    	showDetails : function(){
    	    var selNode = this.view.getSelectedNodes();
    	    var detailEl = Ext.getCmp('img-detail-panel').body;
    		if(selNode && selNode.length > 0){
    			selNode = selNode[0];
    			Ext.getCmp('ok-btn').enable();
    		    var data = this.lookup[selNode.id];
                detailEl.hide();
                this.detailsTemplate.overwrite(detailEl, data);
                detailEl.slideIn('l', {stopFx:true,duration:.2});
    		}else{
    		    Ext.getCmp('ok-btn').disable();
    		    detailEl.update('');
    		}
    	},

    	filter : function(){
    		var filter = Ext.getCmp('filter');
    		this.view.store.filter('name', filter.getValue());
    		this.view.select(0);
    	},

    	sortImages : function(){
    		var v = Ext.getCmp('sortSelect').getValue();
        	this.view.store.sort(v, v == 'name' ? 'asc' : 'desc');
        	this.view.select(0);
        },

    	reset : function(){
    		if(this.win.rendered){
    			Ext.getCmp('filter').reset();
    			this.view.getEl().dom.scrollTop = 0;
    		}
    	    this.view.store.clearFilter();
    		this.view.select(0);
    	},

    	doCallback : function(){
            var selNode = this.view.getSelectedNodes()[0];
    		var callback = this.callback;
    		var lookup = this.lookup;
    		this.win.hide(this.animateTarget, function(){
                if(selNode && callback){
    				var data = lookup[selNode.id];
    				callback(data);
    			}
    		});
        },

    	onLoadException : function(v,o){
    	    this.view.getEl().update('Error loading images.');
    	}
    };

    String.prototype.ellipse = function(maxLength){
        if(this.length > maxLength){
            return this.substr(0, maxLength-3) + '...';
        }
        return this;
    };