Ext.namespace("dlr.cmp.flickr");
dlr.cmp.flickr.flickrMemberPanel = function(cfg){
	// ------------------------------------------------
	// private properties
	// ------------------------------------------------
	var that = this;
    var photoSetStore = new Ext.data.JsonStore({
		url: "flickrHelper.cfc",
		root: "data",
		totalProperty: "total",
		autoLoad: true,
		fields: [
			{name: "photoset_id"},
			{name: "title"},
			{name: "description"},
			{name: "photo_id"},
			{name: "secret"},
			{name: "server"},
			{name: "farm"}
		]
    });
    var resultTpl = new Ext.XTemplate(
        '<tpl for="."><div class="photoSet">',
            '<h3><img src="http://farm{farm}.static.flickr.com/{server}/{photo_id}_{secret}_s.jpg" width="30" height="30" align="left" /> {title}</h3><div style="clear:both;"></div>',
            '<p style="padding:3px;"><small>{description}</small></p>',
        '</div></tpl>'
    );
	var photoMemeberTbCfg = [{
			xtype: "tbtext",
			text: "Search For: "
		},{
			xtype: "textfield",
			name: "searchTerm"
		}," ",{
			xtype: "tbtext",
			text: "User Name: "
		},{
			xtype: "textfield",
			name: "flickrUser"
		}," ",{
			iconCls: "new-tab",
			icon: "assets/icons/photos.png",
			text: "Get Photos",
			handler: getMember
		},"-",{
			xtype: "tbtext",
			text: " <div ext:qtip='Checking this box will return photos licensed as All Rights Reserved.'> Include Restricted </div> "
		}," ",{
			xtype: "checkbox",
			checked: true,
			name: "resricted"
		},"-",{
			iconCls: "new-tab",
			icon: "assets/icons/pictures.png",
			text: "Get Photosets",
			disabled: true,
			handler: (function(){
				getCmps().photoSetViewCt.expand();
			})
		},"-"];
	var bBarDisplayText = " Items {1} to {2} of {3} ";
	var photoGroupBbCfg = [{
			cls: "x-btn-icon",
			icon: "../../extjs/2.2/resources/images/default/grid/page-first.gif",
			tooltip: "First Page",
			disabled: true,
			handler: first
		},{
			cls: "x-btn-icon",
			icon: "../../extjs/2.2/resources/images/default/grid/page-prev.gif",
			tooltip: "Previous Page",
			disabled: true,
			handler: prev
		},"-",{
			xtype: "tbtext",
			text: "-"
		},"-",{
			cls: "x-btn-icon",
			icon: "../../extjs/2.2/resources/images/default/grid/page-next.gif",
			tooltip: "Next Page",
			disabled: true,
			handler: next
		},{
			cls: "x-btn-icon",
			icon: "../../extjs/2.2/resources/images/default/grid/page-last.gif",
			tooltip: "Last Page",
			disabled: true,
			handler: last
	}];
	var photoViewTpl = new Ext.XTemplate(
		'<tpl for=".">',
			'<div class="thumb-wrap">',
			'<div class="thumb"><img src="http://farm{farm}.static.flickr.com/{server}/{id}_{secret}_s.jpg"  ext:qtip="{title}"></div>',
			'<div class="x-editable license{license}" style="overflow:hidden;width:80px;white-space:nowrap;">{title}</div></div>',
		'</tpl>',
		'<div class="x-clear"></div>'
	);
	var photoStore = new Ext.data.JsonStore({
		url: "flickrHelper.cfc",
		root: "photos.photo",
		totalProperty: "photos.total",
		fields: [
			{name: "id"},
			{name: "owner"},
			{name: "secret"},
			{name: "server"},
			{name: "farm"},
			{name: "title"},
			{name: "ispublic"},
			{name: "isfriend"},
			{name: "isfamily"},
			{name: "license"}
		]
	});
	var photoView = new Ext.DataView({
        store: photoStore,
        tpl: photoViewTpl,
        autoHeight:true,
        multiSelect: true,
        overClass:'x-view-over',
		frame: false,
		border: false,
        itemSelector:'div.thumb-wrap',
        emptyText: 'That member does not exist or there are no search results matching your criteria.',
		cls: "images-view",
		ddgroup: "photoViewDD",
		plugins: [
			new Ext.DataView.DragSelector({dragSafe:true})
		],
		listeners:{
			"mouseenter": function(dataView, idx, node, evt){
				//evt.preventDefault();
				var nodeEl = Ext.get(node);
				zoom.show();
				zoom.setPosition(nodeEl.getX() + 7, nodeEl.getY() + 7);
				zoom.nodeRecord = dataView.getRecord(node);
			},
			"mouseleave": function(dataView, idx, node, evt){
				if (zoom.isVisible() && evt.getTarget().tagName.toLowerCase() != "img")
					zoom.hide();
			},
			"render": function(){
				var queueGrid = that.queueOwnerCt.findByType("queueGrid")[0];
				that.dragZone = new ImageDragZone(photoView, {
					containerScroll:true,
					ddGroup: getCmps().poolPhotoViewCt.getId()
				});
				queueGrid.initDD(getCmps().poolPhotoViewCt.getId(), queueAddPool);
			}
		} // end listeners
    });
	var photoSetViewStore = new Ext.data.JsonStore({
		url: "flickrHelper.cfc",
		root: "photoset",
		totalProperty: "total",
		fields: [
			{name: "id"},
			{name: "owner"},
			{name: "secret"},
			{name: "server"},
			{name: "farm"},
			{name: "title"},
			{name: "ispublic"},
			{name: "isfriend"},
			{name: "isfamily"},
			{name: "license"}
		]
	});
	//var dragZonSet = null;
	var photoSetView = new Ext.DataView({
        store: photoSetViewStore,
        tpl: photoViewTpl,
        autoHeight:true,
		frame: false,
		border: false,
        multiSelect: true,
        overClass:'x-view-over',
        itemSelector:'div.thumb-wrap',
        emptyText: '',
		ddgroup: "photoViewDD",
		cls: "images-view",
		plugins: [
			new Ext.DataView.DragSelector({dragSafe:true})
		],
		listeners:{
			"mouseenter": function(dataView, idx, node, evt){
				//evt.preventDefault();
				var nodeEl = Ext.get(node);
				zoom.show();
				zoom.setPosition(nodeEl.getX() + 7, nodeEl.getY() + 7);
				zoom.nodeRecord = dataView.getRecord(node);
			},
			"mouseleave": function(dataView, idx, node, evt){
				if (zoom.isVisible() && evt.getTarget().tagName.toLowerCase() != "img")
					zoom.hide();
			},
			"render": function(){
				var queueGrid = that.queueOwnerCt.findByType("queueGrid")[0];
				dragZoneSet = new ImageDragZone(photoSetView, {
					containerScroll:true,
					ddGroup: getCmps().photoSetViewCt.getId() + "set"
				});
				queueGrid.initDD(getCmps().photoSetViewCt.getId() + "set", queueAddSet);
			}
		} // end listeners
    });
	var zoom = new Ext.Window({
		frame: false,
		border: false,
		resizable: false,
		closable: false,
		draggable: false,
		width: 22,
		height: 22,
		bodyStyle: "background:white;padding:2px;",
		html: "<a href='javascript:;' ext:qtip='View Larger Version'><img src='assets/icons/magnifier_zoom_in.png' /></a>"
	});
	var flickrPhotoWindowCfg = {
		ownnerCmp: that
	};
	var panelCfg = {
		xtype: "panel",
		layout: "border",
		frame: false,
		border: false,
		title: "Find Photos",
		closable: true,
		tbar: photoMemeberTbCfg,
		bbar: photoGroupBbCfg,
		autoScroll: true,
		keys: [{
			key: [Ext.EventObject.ENTER],
			fn: getMember
		}],
		items:[{
			xtype: "panel",
			region: "center",
			frame: false,
			border: false,
			anchor: "100% 0",
			autoScroll: true,
			tbar:[{
					cls: "x-btn-icon",
					icon: "assets/icons/arrow_left.png",
					tooltip: "Add Selected Pool Photos to Queue",
					handler: queueAddPool
				},{
					cls: "x-btn-icon",
					icon: "assets/icons/picture_add.png",
					tooltip: "Select All Pool Photos",
					handler: selectAllPool
			},"-"],
			items: [photoView]
		},{
			xtype: "panel",
			region: "east",
			anchor: "100% 0",
			frame: false,
			border: false,
			split: true,
			collapsed: true,
			collapsible: true,
			hidden: true,
			title: "Photo Sets",
			width: 340,
			autoScroll: true,
			tbar:[{
					cls: "x-btn-icon",
					icon: "assets/icons/arrow_left.png",
					tooltip: "Add Selected Set Photos to Queue",
					handler: queueAddSet
				},{
					cls: "x-btn-icon",
					icon: "assets/icons/picture_add.png",
					tooltip: "Select All Set Photos",
					handler: selectAllSet
			},"-"," ",{
				xtype: "combo",
				store: photoSetStore,
				displayField:'title',
				typeAhead: false,
				loadingText: 'Getting Photo Sets...',
				width: 220,
				pageSize:10,
				triggerAction: "all",
				tpl: resultTpl,
				itemSelector: 'div.photoSet',
				mode: "remote",
				disabled: true,
				listeners:{
					"select": function(combo, record, idx){
						getPhotoSet(combo, record, idx);
					},
					"expand": function(){
						if (!photoSetViewStore.getCount()){
							photoSetStore.removeAll();
							photoSetStore.load();
						}
					}
				}// end listeners
			}],
			items:[photoSetView]
		}]
	};
	var curUserName = "";
	// ------------------------------------------------
	// private functions
	// ------------------------------------------------
	function getCmps(){
		return {
			poolPhotoViewCt: that.items.get(0),
			poolPhotoViewBody: that.items.get(0).body,
			photoSetViewCt: that.items.get(1),
			searchTermTbBtn: that.getTopToolbar().items.get(1),
			flickrUserTbBtn: that.getTopToolbar().items.get(4), // really the textfield, bad naming
			restrictedChckbx: that.getTopToolbar().items.get(10),
			photoSetComboOpen: that.getTopToolbar().items.get(12),
			photoSetCombo: that.items.get(1).getTopToolbar().items.get(4),
			bBar: that.getBottomToolbar(),
			bBarFirstBtn: that.getBottomToolbar().items.get(0),
			bBarPrevBtn: that.getBottomToolbar().items.get(1),
			bBarDisplay: that.getBottomToolbar().items.get(3),
			bBarNextBtn: that.getBottomToolbar().items.get(5),
			bBarLastBtn: that.getBottomToolbar().items.get(6)
		};
	}; // end getCmps
	function getMember(){
		var flickrUser = getCmps().flickrUserTbBtn;
		var searchTerm = getCmps().searchTermTbBtn;
		var params = {method: "getMember"};
		var ldMsk = null;

		if (curUserName.length && flickrUser.getValue() != curUserName){
			photoSetViewStore.removeAll();
			//photoSetStore.removeAll();
			getCmps().photoSetCombo.setValue();
			getCmps().photoSetViewCt.setTitle("Photo Set: ");
		}
		if (!ldMsk){
			ldMsk = new Ext.LoadMask(getCmps().poolPhotoViewCt.body, {msg: "Searching..."});
		}
		if (flickrUser.getValue().length || searchTerm.getValue().length){
			ldMsk.show();
			params.data = {userId: flickrUser.getValue(), searchTerm: searchTerm.getValue()};
			if (getCmps().restrictedChckbx.getValue()){
				params.data.getRestricted = true;
			}
			params.data = Ext.encode(params.data);
			getCmps().poolPhotoViewBody.scrollTo("top", 0);
			photoStore.load({
				params: params,
				callback: (function(rec, opt, suc){
					if (!suc){
						photoStore.removeAll();
						photoView.refresh();
						getCmps().bBar.hide();
					}
					else{
						getCmps().bBar.show();
						if (photoStore.getCount() && flickrUser.getValue().length){
							getCmps().photoSetCombo.enable();
							getCmps().photoSetComboOpen.enable();
							photoSetStore.baseParams = {method: "getPhotoSets", data: Ext.encode({userId: photoStore.getAt(0).data.owner})};
							getCmps().photoSetViewCt.show();
						}
						else{
							getCmps().photoSetViewCt.hide();
							getCmps().photoSetCombo.disable();
							getCmps().photoSetComboOpen.disable();
						}
						that.doLayout();
						//fixTitle(getCmps().poolPhotoViewCt);
						//var tabPanel = that.workSpacePanel.items.get(2);
						fixTitle(that);
					}
					ldMsk.hide();
				})
			});
			that.doLayout();
		}
		curUserName = flickrUser.getValue();
	}; // end getMember
	function fixTitle(pnl){
		var flickrUser = getCmps().flickrUserTbBtn;
		var searchTerm = getCmps().searchTermTbBtn;
		var titleStrMember = "{0}'s Photos ";
		var titleStrSearch = "Matching: {0}";
		var title = "";

		if (flickrUser.getValue().length){
			title += titleStrMember.replace("{0}", flickrUser.getValue());
		}
		if (searchTerm.getValue().length){
			title += titleStrSearch.replace("{0}", searchTerm.getValue());
		}
		pnl.setTitle(title);
	};
	function getPhotoSet(combo, record, idx){
		var params = {method: "getPhotoSet"};
		var ldMsk = null;

		if (!ldMsk){
			ldMsk = new Ext.LoadMask(getCmps().photoSetViewCt.body, {msg: "Searching..."});
		}
		getCmps().photoSetViewCt.expand();
		ldMsk.show();
		params.data = Ext.encode({photoSetId: record.data.photoset_id.replace('"', '').replace('"', '')});
		photoSetViewStore.load({
			params: params,
			callback: (function(rec, opt, suc){
				getCmps().photoSetViewCt.setTitle("Photo Set: " + record.data.title + " (" + photoSetViewStore.getCount() + ")");
				ldMsk.hide();
			})
		});
		that.doLayout();
	}; // end getPhotoSet
	function toolbarUpdate(store, record, options){
		var cmps = getCmps();
		var display = cmps.bBarDisplay.getEl();
		var cnts = getPhotoStoreCnts(store);
		var newText = bBarDisplayText;

		newText = newText.replace("{1}", cnts.start);
		newText = newText.replace("{2}", cnts.end);
		newText = newText.replace("{3}", cnts.total);
		display.innerHTML = newText;
		if (cnts.start == 1){ // first record
			cmps.bBarFirstBtn.disable();
			cmps.bBarPrevBtn.disable();
			cmps.bBarNextBtn.enable();
			cmps.bBarLastBtn.enable();
		}
		if (cnts.start > cnts.limit){ // first record
			cmps.bBarFirstBtn.enable();
			cmps.bBarPrevBtn.enable();
			cmps.bBarNextBtn.enable();
			cmps.bBarLastBtn.enable();
		}
		if (cnts.page == cnts.pages){ // first record
			cmps.bBarFirstBtn.enable();
			cmps.bBarPrevBtn.enable();
			cmps.bBarNextBtn.disable();
			cmps.bBarLastBtn.disable();
		}
		//cmps.bBarFirstBtn.enable();
	}; // end toolbarUpdate
	function getPhotoStoreCnts(store){
		var store = store || photoStore;
		var jsonData = store.reader.meta.reader.jsonData;
		return {
			start: (jsonData.photos.page * jsonData.photos.perpage) - (jsonData.photos.perpage - 1),
			end: (jsonData.photos.page * jsonData.photos.perpage),
			limit: jsonData.photos.perpage,
			total: jsonData.photos.total,
			page: jsonData.photos.page,
			pages: jsonData.photos.pages
		};
	}; // end getPhotoStoreCnts
	function first(){
		var cnts = getPhotoStoreCnts();
		var params = photoStore.lastOptions.params;
		var data = Ext.decode(params.data);

		data.page = 1;
		params.data = Ext.encode(data);
		page(params);
	}; // end first
	function prev(){
		var cnts = getPhotoStoreCnts();
		var params = photoStore.lastOptions.params;
		var data = Ext.decode(params.data);

		data.page = cnts.page - 1;
		params.data = Ext.encode(data);
		page(params);
	}; // end prev
	function next(){
		var cnts = getPhotoStoreCnts();
		var params = photoStore.lastOptions.params;
		var data = Ext.decode(params.data);

		data.page = cnts.page + 1;
		params.data = Ext.encode(data);
		page(params);
	}; // end next
	function last(){
		var cnts = getPhotoStoreCnts();
		var params = photoStore.lastOptions.params;
		var data = Ext.decode(params.data);

		data.page = cnts.pages;
		params.data = Ext.encode(data);
		page(params);
	}; // end last
	function page(params){
		var ldMsk = null;

		if (!ldMsk){
			ldMsk = new Ext.LoadMask(getCmps().poolPhotoViewCt.body, {msg: "Searching..."});
		}
		getCmps().poolPhotoViewBody.scrollTo("top", 0);
		ldMsk.show();
		photoStore.load({
			params: params,
			callback: (function(){ldMsk.hide();})
		});
	}; // end page
	function queueAddPool(nodes){
		var queueGrid = that.queueOwnerCt.findByType("queueGrid")[0];
		if (!nodes) { nodes = {}; }
		var nodes = (nodes.type) ? false : photoView.getRecords(nodes);
		var sels = nodes || photoView.getSelectedRecords();
		var newCount = sels.length + queueGrid.getStore().getCount();
		if (newCount > 500){ 
			Ext.Msg.show({
				title: "",
				msg: "Only 500 items are allowed in the Queue at this time.",   
				buttons: Ext.Msg.OK,
				icon: Ext.MessageBox.WARNING
			});
			return; 
		}
		Ext.each(sels, (function(rec, recIdx, recLen){
			if (queueGrid.getStore().indexOf(rec) == -1){
				if (rec.get("license") > 0)
					queueGrid.getStore().add(rec);
			}
			photoView.deselect(photoStore.indexOf(rec));
		}));
	};// end queuAddPool
	function selectAllPool(){
		photoView.selectRange(0, 99);
		//queueAddPool();
	}; // end selectAllPool
	function queueAddSet(nodes){
		var queueGrid = that.queueOwnerCt.findByType("queueGrid")[0];
		if (!nodes) { nodes = {}; }
		var nodes = (nodes.type) ? false : photoSetView.getRecords(nodes);
		var sels = nodes || photoSetView.getSelectedRecords();
		var newCount = sels.length + queueGrid.getStore().getCount();
		if (newCount > 500){ 
			Ext.Msg.show({
				title: "",
				msg: "Only 500 items are allowed in the Queue at this time.",   
				buttons: Ext.Msg.OK,
				icon: Ext.MessageBox.WARNING
			});
			return; 
		}
		Ext.each(sels, (function(rec, recIdx, recLen){
			if (queueGrid.getStore().indexOf(rec) == -1){
				if (rec.get("license") > 0)
					queueGrid.getStore().add(rec);
			}
			photoSetView.deselect(photoSetViewStore.indexOf(rec));
		}));
	};// end queuAddSet
	function selectAllSet(){
		photoSetView.selectRange(0, 99);
		//queueAddSet();
	}; // end selectAllSet
	function zoomEvts(){
		zoom.body.un("click", zoomClick, zoom, zoom);
		zoom.body.on("click", zoomClick, zoom, zoom);
		Ext.getBody().on("click", (function(){
			if (zoom)
				zoom.hide();
		}));
	}; // end zoomEvts
	function zoomClick(){
		var id = "zoomWin-" + this.nodeRecord.data.id;
		var flickrPhotoWindow = Ext.getCmp(id) || new dlr.cmp.flickr.flickrPhotoWindow(Ext.apply(flickrPhotoWindowCfg, {id: id}));
		flickrPhotoWindow.loadPhoto(this.nodeRecord);
	}; // end zoomClick
	// ------------------------------------------------
	// public properties
	// ------------------------------------------------
	// ------------------------------------------------
	// public methods
	// ------------------------------------------------
	// ------------------------------------------------
	// constructor code
	// ------------------------------------------------
	Ext.apply(this, cfg);
	// apply private cfgs
	Ext.apply(this, panelCfg);
	dlr.cmp.flickr.flickrMemberPanel.superclass.constructor.call(this, cfg);
	// events
	photoStore.on("load", toolbarUpdate);
	zoom.on("render", zoomEvts);
};
Ext.extend(dlr.cmp.flickr.flickrMemberPanel, Ext.Panel);
Ext.reg("flickrMemberPanel", dlr.cmp.flickr.flickrMemberPanel);

var ImageDragZone = function(view, config){
    this.view = view;
    ImageDragZone.superclass.constructor.call(this, view.getEl(), config);
};
Ext.extend(ImageDragZone, Ext.dd.DragZone, {
    // We don't want to register our image elements, so let's
    // override the default registry lookup to fetch the image
    // from the event instead
    getDragData : function(e){
        var target = e.getTarget('.thumb-wrap');
		var imgNode;
        if(target){
            var view = this.view;
            if(!view.isSelected(target)){
                view.onClick(e);
            }
            var selNodes = view.getSelectedNodes();
            var dragData = {
                nodes: selNodes
            };
            if(selNodes.length == 1){
                dragData.ddel = target;
                dragData.single = true;
            }else{
                var div = document.createElement('div'); // create the multi element drag "ghost"
                div.className = 'multi-proxy';
                for(var i = 0, len = selNodes.length; i < len; i++){
                    imgNode = div.appendChild(selNodes[i].firstChild.firstChild.cloneNode(true)); // image nodes only
					imgNode.setAttribute("width", 35);
					imgNode.setAttribute("height", 35);
					imgNode.setAttribute("hspace", 5);
					imgNode.setAttribute("vspace", 5);
                    if((i+1) % 6 == 0){
                        div.appendChild(document.createElement('br'));
                    }
                }
                var count = document.createElement('div'); // selected image count
                count.innerHTML = i + ' images selected';
                div.appendChild(count);

                dragData.ddel = div;
                dragData.multi = true;
            }
            return dragData;
        }
        return false;
    },

    // this method is called by the TreeDropZone after a node drop
    // to get the new tree node (there are also other way, but this is easiest)
    getTreeNode : function(){
        alert("getTreeNode");
		/*
		var treeNodes = [];
        var nodeData = this.view.getRecords(this.dragData.nodes);
        for(var i = 0, len = nodeData.length; i < len; i++){
            var data = nodeData[i].data;
            treeNodes.push(new Ext.tree.TreeNode({
                text: data.name,
                icon: '../view/'+data.url,
                data: data,
                leaf:true,
                cls: 'image-node'
            }));
        }
        return treeNodes;
		*/
    },

    // the default action is to "highlight" after a bad drop
    // but since an image can't be highlighted, let's frame it
    afterRepair:function(){
        for(var i = 0, len = this.dragData.nodes.length; i < len; i++){
            Ext.fly(this.dragData.nodes[i]).frame('#8db2e3', 1);
        }
        this.dragging = false;
    },

    // override the default repairXY with one offset for the margins and padding
    getRepairXY : function(e){
        if(!this.dragData.multi){
            var xy = Ext.Element.fly(this.dragData.ddel).getXY();
            xy[0]+=3;xy[1]+=3;
            return xy;
        }
        return false;
    }
});


Ext.DataView.LabelEditor = function(cfg, field){
    Ext.DataView.LabelEditor.superclass.constructor.call(this,
        field || new Ext.form.TextField({
            allowBlank: false,
            growMin:90,
            growMax:240,
            grow:true,
            selectOnFocus:true
        }), cfg
    );
}


Ext.DataView.DragSelector = function(cfg){
    cfg = cfg || {};
    var view, regions, proxy, tracker;
    var rs, bodyRegion, dragRegion = new Ext.lib.Region(0,0,0,0);
    var dragSafe = cfg.dragSafe === true;

    this.init = function(dataView){
        view = dataView;
        view.on('render', onRender);
    };

    function fillRegions(){
        rs = [];
        view.all.each(function(el){
            rs[rs.length] = el.getRegion();
        });
        bodyRegion = view.el.getRegion();
    }

    function cancelClick(){
        return false;
    }

    function onBeforeStart(e){
        return !dragSafe || e.target == view.el.dom;
    }

    function onStart(e){
        view.on('containerclick', cancelClick, view, {single:true});
        if(!proxy){
            proxy = view.el.createChild({cls:'x-view-selector'});
        }else{
            proxy.setDisplayed('block');
        }
        fillRegions();
        view.clearSelections();
    }

    function onDrag(e){
        var startXY = tracker.startXY;
        var xy = tracker.getXY();

        var x = Math.min(startXY[0], xy[0]);
        var y = Math.min(startXY[1], xy[1]);
        var w = Math.abs(startXY[0] - xy[0]);
        var h = Math.abs(startXY[1] - xy[1]);

        dragRegion.left = x;
        dragRegion.top = y;
        dragRegion.right = x+w;
        dragRegion.bottom = y+h;

        dragRegion.constrainTo(bodyRegion);
        proxy.setRegion(dragRegion);

        for(var i = 0, len = rs.length; i < len; i++){
            var r = rs[i], sel = dragRegion.intersect(r);
            if(sel && !r.selected){
                r.selected = true;
                view.select(i, true);
            }else if(!sel && r.selected){
                r.selected = false;
                view.deselect(i);
            }
        }
    }

    function onEnd(e){
        if(proxy){
            proxy.setDisplayed(false);
        }
    }

    function onRender(view){
        tracker = new Ext.dd.DragTracker({
            onBeforeStart: onBeforeStart,
            onStart: onStart,
            onDrag: onDrag,
            onEnd: onEnd
        });
        tracker.initEl(view.el);
    }
};