1 /**
  2  * @class Monk.component.CollectionsRipperBrowserComponent
  3  * @description A {@link Worbench.component.Component} for browsing text chunks.
  4  * @extends Workbench.component.Component
  5  * @author Alejandro
  6  * @version 0.1
  7  * @since Monk 0.1
  8  */
  9 Monk.component.CollectionsRipperBrowserComponent = function (args) {
 10 	
 11 	this.options = arguments[0] || {};
 12 
 13 	// descriptiors
 14 	this.label = this.options.label || "Collections Rich Prospect Browser";
 15     this.description = this.options.description || "For Browsing Monk Text Collections.";
 16 	
 17 	// set containers
 18 	
 19 	this.collectionsBox =  jQuery('#crbBox');
 20 	this.deselectedTilesBox = jQuery('#desCrbBox');
 21 	this.collectionsControls = jQuery('#crbControlsPanel');
 22 	this.infoPanel = jQuery('#crbInfoPanel');
 23 	this.historyPanel = jQuery('#crbHistory ul');
 24 
 25 	//defaults
 26 	this.defaultTileSize = this.options.defaultTileSize || 3;
 27 	
 28 	//proxy
 29 	
 30 	this.api = this.options.api || 
 31 		{
 32 			proxy: Monk.data.PROXY_URL,
 33 			getAllWorks: 'get/CorpusManager.getWorkList'	
 34 		};
 35 	
 36 	//history
 37 	this.queue = [];
 38 	this.queuePos = undefined;
 39 	this.queueLock = false;
 40 
 41 	// xml work list
 42 	this.cachedData = null;
 43 
 44 	// has elements structure
 45 	
 46 	/*
 47 	variableId:
 48 				label: variable display name
 49 				values: value or values in tiles
 50 				addDetail: (boolean) is this a relevant detail for the user (eg. false for id, true for title)
 51 				display: (boolean) can user display this in every tile 
 52 				organize: (boolean) can user group by this detail
 53 				isDefault: (boolean) is this detail displayed by default
 54 	
 55 	*/
 56 
 57 	this.groupDetailHash = {
 58 		'title' : {
 59 			'label': 'title', 
 60 			'values': [],
 61 			'addDetail': true,
 62 			'display': true,
 63 			'organize': false
 64 		},
 65 		'shortTitle' : {
 66 			'label': 'short title', 
 67 			'values': [],
 68 			'addDetail': true,
 69 			'display': true,
 70 			'organize': false,
 71 			'isDefault': true
 72 		},
 73 		'alphabet' : {
 74 			'label': 'alphabet', 
 75 			'values': [],
 76 			'addDetail': false,
 77 			'display': false,
 78 			'organize': true
 79 		},
 80 		'id' : {
 81 			'label': 'id', 
 82 			'values': [],
 83 			'addDetail': false,
 84 			'display': false,
 85 			'grouping': false
 86 		},
 87 		'author' : {
 88 			'label': 'author', 
 89 			'values': [],
 90 			'addDetail': true,
 91 			'display': true,
 92 			'organize': true
 93 		},
 94 		'collection': {
 95 			'label': 'collection',
 96 			'values': [],
 97 			'addDetail': true,
 98 			'display': true,
 99 			'organize': true
100 		},
101 		'pubStart': {
102 			'label': 'publication start',
103 			'values': [],
104 			'addDetail': true,
105 			'display': true,
106 			'organize': true
107 		},
108 		'pubEnd': {
109 			'label': 'publication end',
110 			'values': [],
111 			'addDetail': true,
112 			'display': true,
113 			'organize': true
114 		},
115 		'authorBirth': {
116 			'label': 'author birthdate',
117 			'values': [],
118 			'addDetail': true,
119 			'display': true,
120 			'organize': true
121 		},
122 		'authorDeath': {
123 			'label': 'author death',
124 			'values': [],
125 			'addDetail': true,
126 			'display': true,
127 			'organize': true
128 		},
129 		'decade': {
130 			'label': 'decade',
131 			'values': [],
132 			'addDetail': false,
133 			'display': false,
134 			'organize': true
135 		}
136 	};
137     
138     
139     Monk.component.CollectionsRipperBrowserComponent.superclass.constructor.call(this, args);
140 };
141 
142 Workbench.extend(Monk.component.CollectionsRipperBrowserComponent, Workbench.component.Component, {
143 
144    label : "Collections Rich Prospect Browser",
145    description : "For Browsing Monk Text Collections.",
146    "window" : this.window,
147    handle : function(monkEvent, data){},
148 
149    init : function () {
150     	var rpr = this;
151             
152 		rpr.loadData();
153 		rpr.deselectedTilesBox.block(
154 			{css: 
155 				{cursor: 'auto'},
156 				overlayCSS: 
157 				{background: 'transparent', cursor: 'auto'}, 
158 				message: null
159 			}
160 		);
161 		
162 		
163 		rpr.initializeHistory();
164 	},
165 
166 	testData: function() {
167 
168 		var works = jQuery('works', this.cachedData);
169 
170 		return works.attr('totalCount') || false;
171 	},
172 
173 	loadData: function () {
174 		var rpr = this;
175 
176 		jQuery.ajax({
177 			type: 'GET',
178 			url: rpr.api.proxy + rpr.api.getAllWorks,
179 			beforeSend: function () {
180 				rpr.blockUI(0);
181 			},
182 			success: function (xml) {
183 				rpr.cachedData = xml;
184 			},
185 			complete : function () {
186 				if (!(rpr.testData())) {
187 					rpr.blockUI(0, {message: '<h1>Error loading Data</h1><h2>Please Reload the page</h2>', overlayCSS: {background: '#45443f'}});
188 					return false;
189 				}
190 				rpr.initializeTiles();
191 				rpr.unblockUI();
192 			}
193 		});
194 	},
195 
196 	blockUI: function() {
197 		var rpr = this;
198 		var inter = arguments[0] || 100;
199 		var options = arguments[1] || { message: '<img src="ajax-loader.gif" /> <h1> Just a moment...</h1>', overlayCSS: {background: '#45443f'}};
200 
201 		this.blocking = window.setTimeout( function () {
202 			jQuery.blockUI(options); 
203 		}, inter);
204 	},
205 
206 	unblockUI: function () {
207 		var rpr = this;
208 		if (this.blocking) {
209 			clearTimeout(this.blocking);
210 			this.blocking = false;
211 		}
212 		window.setTimeout( function() {
213 			jQuery.unblockUI();
214 			}, 100);
215 	},
216 
217 	initializeTiles: function () {
218 
219 
220 		var rpr = this;
221 		//select HTML elements
222 
223 
224 		jQuery('work', this.cachedData).each(function (chunkId, chunk) {
225 
226 			// get variables from XML
227 			//title
228 			var tileTitle = jQuery('label', chunk).text();
229 
230 			//shortTitle
231 			var shortTitle = tileTitle.split(' ');
232 			var stest = new RegExp("^((a)|(the)|(for)|(to)|(of)|(an)([\W]))$", 'gi');
233 			shortTitle = jQuery.grep(shortTitle, function(title, n){
234 				return !title.match(stest);
235 			});
236 			shortTitle = shortTitle[0];
237 			//id
238 			var tileId = jQuery(this).attr("id");
239 
240 			//collection
241 			var collection = jQuery(this).attr("collection_id");
242 
243 			// author, authorBirth & authorDeath
244 			var authors = [];
245 			var authorBirth = [];
246 			var authorDeath = [];
247 			jQuery('author', chunk).each(function () {
248 				authors.push(jQuery(this).text());
249 				authorBirth.push(jQuery(this).attr('birthdate'));
250 				authorDeath.push(jQuery(this).attr('enddate'));
251 			});
252 
253 			//pubStart & end
254 			var pubdate = jQuery('publication', chunk);
255 			
256 
257 			//decade
258 			var decades = [];
259 			decades.push(Math.floor(pubdate.attr('start') / 10) * 10);
260 			decades.push(Math.floor(pubdate.attr('end') / 10) * 10);
261 
262 			decades = (decades[0] === decades[1])? decades[0]: decades;
263 
264 
265 			rpr.createTile({
266 				'title' : tileTitle,
267 				'shortTitle': shortTitle,
268 				'alphabet' : tileTitle.toLowerCase().charAt(0),
269 				'id' : tileId,
270 				'author' : authors,
271 				'collection': collection,
272 				'pubStart': pubdate.attr('start'),
273 				'pubEnd':  pubdate.attr('end'),
274 				'authorBirth': authorBirth,
275 				'authorDeath': authorDeath,
276 				'decade': decades
277 			});
278 
279 		});
280 
281 		rpr.initializeTileEvents();
282 		rpr.initializeTileDetailEvents();
283 
284 		jQuery(window).bind('resize',  function () {
285 			rpr.resizeTiles();
286 		});
287 
288 		rpr.createControls();
289 		rpr.clearAll();
290 	},
291 	
292 	initializeHistory: function () {
293 		var rpr = this;
294 		var historyList = rpr.historyPanel.parent('#crbHistory')
295 		rpr.historySlider = jQuery('#crbHistorySlider.slider');
296 		rpr.historySlider.slider({
297 			slide: function (e, ui) {
298 				
299 				historyList.stop();
300 				var scrollPos = ui.value * (rpr.historyPanel.height() - 200) / 100;
301 				historyList.animate({scrollTop: scrollPos}, 500); 
302 			}
303 		})
304 	},
305 
306 	initializeTileEvents: function () {
307 		var rpr = this;
308 		// create hovertooltip
309 		var hoverIntentConfig = {    
310 			sensitivity: 3, 
311 			interval: 1000,
312 			timeout: 500,
313 			over: function () {
314 
315 				var tileClone = jQuery(this).clone();
316 
317 				var tilePos = jQuery(this).offset();
318 				var windowPos = {height: jQuery(window).height(), width: jQuery(window).width()};
319 				var tooltipPos = {};
320 
321 				if(tilePos.top < (windowPos.height / 2)) {
322 					tooltipPos.top = tilePos.top + jQuery(this).height();
323 				} else {
324 					tooltipPos.bottom = windowPos.height - tilePos.top;
325 				}
326 
327 				if (tilePos.left < (windowPos.width / 2)) {
328 					tooltipPos.left = tilePos.left;
329 				} else {
330 					tooltipPos.right = windowPos.width - tilePos.left - jQuery(this).width();
331 				}
332 				tooltipPos.position = 'absolute';
333 
334 				tileClone.css(tooltipPos)
335 				.attr('id', 'tooltipTile_' + tileClone.attr('id'))
336 				.removeClass('tile_size_1 tile_size_2 tile_size_3')
337 				.addClass('tile_size_4 tooltipTile');
338 
339 				var el = tileClone.appendTo(jQuery('body'));
340 
341 
342 				jQuery('.tile_box', tileClone).show();
343 
344 			},
345 			out: function () {
346 				jQuery('.tooltipTile').remove();
347 				return true;
348 			}  
349 		};
350 
351 		jQuery('.tile', rpr.collectionsBox).hoverIntent(hoverIntentConfig);
352 	},
353 
354 	initializeTileDetailEvents: function () {
355 		var rpr = this;
356 		jQuery('.tile_box > .tile_value', rpr.collectionsBox).bind('click', 
357 		function (e) {
358 			e.preventDefault();
359 			var dval = jQuery(this).text();
360 			var detailId = jQuery(this).attr('rel');
361 			window.setTimeout(
362 				function () {
363 					rpr.selectGroup({'detailId': detailId, 'value': dval});
364 				},
365 				10);
366 			}
367 		);
368 	},
369 
370 	now: function () {
371 		return +new Date();
372 	},
373 
374 	createTile: function (elementDetails, surrogate) {
375 
376 		var rpr = this;
377 
378 		// template for tile
379 		var tileTemplate = function (work) {
380 
381 			var tile = '<div id="work[' + work.id + ']" class="tile tile_size_' + work.size + '"  >';
382 
383 			tile += '<div class="tile_details">';
384 
385 			tile += '</div>'; // tile_details
386 			tile += '</div>'; // tile
387 
388 			return tile;
389 
390 		};
391 
392 		//template for tile detail
393 		var templateTileDetail = function (tileDetail) {
394 
395 			var tileDetailHtml = '';
396 
397 			tileDetailHtml += '<div class="tile_' + tileDetail.detailId + ' tile_box" style="display: none;" >';
398 			jQuery.each(tileDetail.value, function (i, sigleValue) {
399 				tileDetailHtml += '<a class="tile_value" href="#group all ' + sigleValue + '" rel="'+ tileDetail.detailId +'" >' + sigleValue + '</a>';
400 			});
401 			tileDetailHtml += '<span class="tile_label">' + rpr.groupDetailHash[tileDetail.detailId].label + '</span>';
402 			tileDetailHtml += '</div>';
403 
404 			return tileDetailHtml;
405 		};
406 
407 
408 		// create tile HTML Element
409 		var tileElement = jQuery(tileTemplate({
410 			'id': elementDetails.id,
411 			'size': rpr.defaultTileSize
412 		}));
413 
414 		//store element details
415 		tileElement.data('details', elementDetails);
416 
417 		//store initial size
418 		tileElement.data('size', rpr.defaultTileSize);
419 
420 		//select details container
421 		var tileDetailsElement = jQuery('.tile_details', tileElement);
422 
423 		jQuery.each(elementDetails, function (detailId, detail) {
424 			//determine if it is a single value
425 			var thisdetailvalues = (detail instanceof Array)? detail: [detail];
426 
427 			//hash each single value
428 			jQuery.each(thisdetailvalues, function (valueId, singleValue) {
429 				if (jQuery.inArray(singleValue, rpr.groupDetailHash[detailId].values) === -1) {
430 					rpr.groupDetailHash[detailId].values.push(singleValue);
431 				}
432 			});
433 
434 			if (rpr.groupDetailHash[detailId].addDetail !== false) {
435 				var newDetail = jQuery(templateTileDetail(
436 					{
437 						'detailId' : detailId,
438 						'value': thisdetailvalues
439 					}
440 				))
441 				.appendTo(tileDetailsElement);
442 
443 			}
444 		});
445 
446 
447 		//insert tile 
448 		tileElement.appendTo(rpr.collectionsBox);
449 
450 		return tileElement;
451 	},
452 
453 	selectGroup: function (groupParameter, context) {
454 		var rpr = this;
455 		
456 		rpr.clearOrganize();
457 		var selectedTiles = rpr.selectTiles(groupParameter, context);		
458 		rpr.makeSelection(selectedTiles);
459 		rpr.addToQueue('select', groupParameter);
460 
461 		window.setTimeout( function () {
462 			rpr.resizeTiles();
463 			}, 100);
464 	},
465 	
466 	makeSelection: function (selectedTiles) {
467 		var rpr = this;
468 		selectedTiles.addClass('selectedtiles');
469 		var tilesToRemove = jQuery('.tile:not(".selectedtiles")', rpr.collectionsBox);
470 		rpr.removeTiles(tilesToRemove);
471 		selectedTiles.removeClass('selectedtiles');
472 	},
473 
474 	removeTiles: function (tilesToRemove) {
475 		var rpr = this;
476 
477 		// save selection
478 		var selectedDisplay = jQuery('.control_display.selected:not(".default")');
479 
480 		rpr.clearDisplay();
481 
482 		tilesToRemove.appendTo(rpr.deselectedTilesBox);
483 
484 		window.setTimeout( 
485 			function () {
486 				selectedDisplay.click();
487 			}, 100);
488 
489 		rpr.countTiles();
490 
491 
492 	},
493 	
494 	groupBy: function (detailId, context) {
495 		var rpr = this;
496 	
497 		var withinContext = context || jQuery('.tile', rpr.collectionsBox);
498 		
499 		withinContext.each( function () {
500 			var tileToGroup = jQuery(this);
501 			
502 			var detailsInTile = (tileToGroup.data('details')[detailId] instanceof Array)? tileToGroup.data('details')[detailId]: [tileToGroup.data('details')[detailId]];
503 			
504 			jQuery.each(detailsInTile, function (i, value) {
505 				
506 				var groupDetails = {'detailId': detailId, 'value': value};
507 				var groupEl = rpr.createGroup(groupDetails);
508 				
509 				tileToGroup.hide().clone(true).addClass('surrogate').appendTo(groupEl).show();
510 			});
511 			
512 		});
513 		
514 		rpr.addToQueue('group', {'detailId': detailId});
515 	},
516 	
517 	groupDetailId: function (detail) {
518 		return 'group_' + detail.detailId + '--' + ( detail.value + '' ).replace(/[^\w]/gi, '-') + '--';
519 	},
520 
521 	createGroup: function (groupDetails) {
522 
523 		var rpr = this;
524 		
525 		var templateTileGroup = function (detail) {
526 			var groupHtml = '<div class="tile_group" id="' + rpr.groupDetailId(detail) + '" >';
527 			groupHtml += '<div class="tile_group_title tile_box">';
528 			groupHtml += '<a href="#' + detail.value + ' groupclass="tile_value">' + detail.value + '</a>';
529 			groupHtml += '<span class="tile_label">' + rpr.groupDetailHash[detail.detailId].label + '</span>';
530 			groupHtml += '</div>';
531 			groupHtml += '</div>';
532 			return groupHtml;
533 		};
534 	
535 		
536 		//check if exists group
537 		var groupEl = jQuery('#' + rpr.groupDetailId(groupDetails));
538 		
539 		if (groupEl.length !== 0) {
540 			return groupEl;
541 		}
542 		
543 		//create group
544 		groupEl = jQuery(templateTileGroup(groupDetails));
545 		
546 		//create handler
547 		jQuery('.tile_group_title', groupEl).bind('click', 
548 			function (e) {
549 				e.preventDefault();
550 				rpr.selectGroup(groupDetails);
551 			});
552 		
553 		//add data
554 		groupEl.data('details', groupDetails);
555 		
556 		groupEl.appendTo(rpr.collectionsBox);
557 		
558 		return groupEl;
559 
560 	},
561 	
562 	addToQueue: function (action, details){
563 		
564 		var rpr = this;
565 		// if locked don't log
566 		if (rpr.queueLock === true){
567 			return false;
568 		}
569 		
570 		var stateId = rpr.now();
571 		var state = {
572 			'stateId': stateId,
573 			'action': action,
574 			'details': details
575 		};
576 		var message = action + '';
577 		
578 		if (details instanceof Object) {
579 			message += ': ';
580 			message += details.detailId? rpr.groupDetailHash[details.detailId].label : '';
581 			message += details.value? ', ' + details.value: '';
582 		}
583 		//append history element
584 		var stateEl = jQuery('<li><a href="#" class="state" id="state_' + stateId + '" rel="' + stateId + '" >' + message + '</a></li>');
585 		stateEl.appendTo(rpr.historyPanel);
586 		
587 		//change this with real scroll
588 		rpr.historySlider.slider('moveTo', 100);
589 		
590 		//behaviour
591 		stateEl.click( function (e) {
592 			e.preventDefault();
593 			rpr.goToState(jQuery('a.state', this).attr('rel'));
594 		});
595 		
596 		if(rpr.queue.length > (rpr.queuePos + 1)){
597 			
598 			rpr.queue = rpr.queue.slice(0, (rpr.queuePos + 1));
599 			jQuery('.state.forward', rpr.historyPanel).parent('li').remove();
600 		}
601 		rpr.queuePos = rpr.queue.push(state) - 1;
602 	},
603 	
604 	goToState: function (stateId) {
605 		var rpr = this;
606 		rpr.queueLock = true;
607 		rpr.clearSelection();
608 		rpr.clearOrganize();
609 		
610 		jQuery('.control_display.selected').click().click();
611 		
612 		var stateTransStart = -1, stateTransEnd = -1;
613 		// get start and end of actions to recreate
614 		for (var i = rpr.queue.length - 1; i > -1; i--) {
615 			if(rpr.queue[i].stateId == stateId) {
616 				stateTransEnd = i;
617 			}
618 			
619 			if(rpr.queue[i].action == 'clear' && i <= stateTransEnd) {
620 				stateTransStart = i;
621 				break;
622 			}
623 		}
624 		
625 		var selectedTiles = jQuery('.tile', rpr.collectionsBox);
626 		
627 		// get results from selections and switches
628 		for (i = stateTransStart; i <= stateTransEnd; i++){
629 			if(rpr.queue[i].action == 'select') {
630 				selectedTiles = rpr.selectTiles(rpr.queue[i].details, selectedTiles);
631 			} else if (rpr.queue[i].action == 'switch') {
632 				selectedTiles = jQuery('.tile', rpr.collectionsBox).not(selectedTiles);
633 			}
634 		}
635 		
636 		// make the selection
637 		rpr.makeSelection(selectedTiles);
638 		rpr.resizeTiles();
639 		//if last action is group, do it
640 		if(rpr.queue[stateTransEnd].action == 'group') {
641 			rpr.groupBy(rpr.queue[stateTransEnd].details.detailId);
642 		}
643 		
644 		rpr.queuePos = stateTransEnd;
645 		// mark or unmark forward actions
646 		for (i = 0; i < rpr.queue.length; i++){
647 			if(i > rpr.queuePos) {
648 				jQuery('#state_' + rpr.queue[i].stateId, rpr.historyPanel).addClass('forward');
649 			} else {
650 				jQuery('#state_' + rpr.queue[i].stateId, rpr.historyPanel).removeClass('forward');
651 			}
652 		}
653 		rpr.queueLock = false;
654 	},
655 
656 	selectTiles: function (details, context) {
657 		var rpr = this;
658 		var withinContext = context || jQuery('.tile', rpr.collectionsBox);
659 		var detailsArray = (details instanceof Array)? details: [details];
660 		
661 		var selectedTiles = withinContext.filter(function(tile) {
662 			var tileData = jQuery(this).data('details');
663 			
664 			for (var i = 0; i < detailsArray.length; i++) {
665 				var indVal = tileData[detailsArray[i].detailId];
666 				if ((indVal !== detailsArray[i].value) && (jQuery.inArray(detailsArray[i].value, indVal) === -1)) {
667 					return false;
668 				}
669 			}
670 			return true;
671 		});
672 		
673 		return selectedTiles;
674 	},
675 
676 	createControls: function () {
677 		var rpr = this;
678 
679 		//control html template
680 		var templateControl = function (detailId) {
681 			var groupingDisabled = rpr.groupDetailHash[detailId].organize? '' : 'disabled';
682 			var displayDisabled = rpr.groupDetailHash[detailId].display? '' : 'disabled';
683 			var isDefault = rpr.groupDetailHash[detailId].isDefault? "default": '';
684 
685 			var controlhtml = '<tr>';
686 			controlhtml += '<td class="control_label">' + rpr.groupDetailHash[detailId].label + '</td>';
687 			controlhtml += '<td><a href="display" class="tile_control control_display ' + displayDisabled + ' ' + isDefault + '" rel="' + detailId + '"></a></td>';
688 			controlhtml += '<td><a href="organize" class="tile_control control_organize ' + groupingDisabled + '" rel="' + detailId + '"></a></td>';
689 			controlhtml += '<tr>';
690 
691 			return controlhtml;
692 		};
693 
694 		// ADD CONTROLS
695 		jQuery.each(rpr.groupDetailHash, function (detailId, detail) {
696 			if (detail.display || detail.organize) {
697 				var insertedControl = jQuery(templateControl(detailId)).appendTo(rpr.collectionsControls);
698 
699 				jQuery('.control_display', insertedControl).bind('click', function (e) {
700 					e.preventDefault();
701 					if ( rpr.groupDetailHash[detailId].display === false ) {
702 
703 						jQuery(this).addClass('disabled');
704 						return true;
705 					}
706 
707 					if (jQuery(this).hasClass('selected')) {
708 						jQuery(this).removeClass('selected');
709 						jQuery('.tile_details .tile_' + detailId, rpr.collectionsBox).fadeOut();
710 
711 					} else {
712 						jQuery(this).addClass('selected');
713 						jQuery('.tile_details .tile_' + detailId, rpr.collectionsBox).fadeIn();
714 					}
715 
716 
717 					rpr.resizeTiles();
718 				});
719 
720 				jQuery('.control_organize', insertedControl).bind('click', function(e){
721 					e.preventDefault();
722 					if ( rpr.groupDetailHash[detailId].detailId === false ) {
723 						jQuery(this).addClass('disabled');
724 						return true;
725 					}
726 
727 					if (jQuery(this).hasClass('selected')) {
728 						jQuery(this).removeClass('selected');
729 						rpr.clearOrganize();
730 					} else {
731 
732 						rpr.clearOrganize();
733 						jQuery(this).addClass('selected');
734 
735 						
736 						rpr.groupBy(detailId);
737 					}
738 
739 				});
740 			}
741 		});
742 
743 		// set control behavior
744 
745 		jQuery('#controlClear').bind('click', function (e) {
746 			e.preventDefault();
747 			rpr.clearAll();
748 		});
749 
750 		rpr.deselectedTilesBox.bind('click', function(e) {
751 			e.preventDefault();
752 			rpr.switchSelection();
753 		});
754 
755 	},
756 
757 	countTiles: function () {
758 		var rpr = this;
759 
760 		var selectedTiles = jQuery('.tile:not(".surrogate")', rpr.collectionsBox).length;
761 		var deselectedTiles = jQuery('.tile', rpr.deselectedTilesBox).length;
762 
763 		jQuery('.tileCount', rpr.infoPanel).text('[' + (selectedTiles + deselectedTiles) + ']');
764 		jQuery('.tileCount', rpr.collectionsBox).text('[' + selectedTiles + ']');
765 		jQuery('.tileCount', rpr.deselectedTilesBox).text('[' + deselectedTiles + ']');
766 
767 
768 	},
769 
770 	switchSelection: function () {
771 		var rpr= this;
772 
773 		rpr.clearOrganize();
774 		var selectedTiles = jQuery('.tile', rpr.collectionsBox);
775 		
776 		jQuery('.tile', rpr.deselectedTilesBox).appendTo(rpr.collectionsBox);
777 		rpr.removeTiles(selectedTiles);
778 
779 		window.setTimeout(
780 			function () {	
781 				rpr.resizeTiles();
782 			},
783 			100);
784 			rpr.countTiles();
785 		rpr.addToQueue('switch');
786 
787 	},
788 
789 	clearSelection: function () {
790 		var rpr = this;
791 		jQuery('.tile', rpr.deselectedTilesBox).appendTo(rpr.collectionsBox);
792 
793 		rpr.countTiles();
794 		
795 		rpr.addToQueue('clear');
796 
797 	},
798 
799 	clearAll: function () {
800 		var rpr = this;
801 		rpr.clearSelection();
802 		rpr.clearOrganize();
803 		rpr.clearDisplay();
804 		window.setTimeout(
805 			function () {	
806 				rpr.resizeTiles();
807 			},
808 			100);
809 	},
810 
811 	clearOrganize: function () {
812 		var rpr = this;
813 		jQuery('.control_organize').each(function () {
814 			jQuery(this).removeClass('selected');
815 		});
816 
817 		jQuery('.tile_group').remove();
818 		jQuery('.tile.surrogate').remove();
819 		jQuery('.tile').show();
820 	},
821 
822 	clearDisplay: function () {
823 		jQuery('.control_display.selected').click();
824 
825 		jQuery(".control_display.default").click();			
826 	},
827 
828 	resizeTiles: function () {
829 		var rpr = this;
830 		var thisWindow = jQuery(window);
831 
832 		// set collectionsbox height
833 		rpr.collectionsBox.height(thisWindow.height() - rpr.deselectedTilesBox.height());
834 
835 		//get count
836 		var totalTiles = jQuery('.tile:not("surrogate")', rpr.collectionsBox).length;
837 
838 		//sampleTile
839 		var sampleTile = jQuery('.tile:first', rpr.collectionsBox);
840 
841 		// calculate resize
842 		var maxNum = Math.floor(rpr.collectionsBox.height()/sampleTile.height()) * Math.floor(rpr.collectionsBox.width()/sampleTile.width());
843 		var ratio = maxNum / totalTiles;
844 		var delta = (ratio < 1)? Math.round(1 - 1/ratio) : (Math.round(Math.sqrt(ratio)) - 1);
845 
846 
847 		var tileSizes = [1,2,3,4];
848 		var currSize = sampleTile.data('size');
849 		var newSize = currSize + delta;
850 		newSize = (jQuery.inArray(newSize, tileSizes) === -1)? 
851 		((delta > 0)? tileSizes[tileSizes.length - 1] :  tileSizes[0]) : newSize;
852 
853 		jQuery('.tile', rpr.collectionsBox).removeClass('tile_size_' + tileSizes.join(' tile_size_')).addClass('tile_size_' + newSize).data('size', newSize);
854 
855 
856 	}
857     
858     
859 });
860