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; };