﻿
/**
 * Selectable list
 */
(function(pkg, $){
	
	if($ == null){
		throw new Error('SelectableList Class requires jQuery 1.3.2');
		return;
	}
	pkg = pkg || {};
	
	
	// base Class structure
	pkg.SelectableList$Class = {
		onClass: 'selected',
		overClass: 'over',
		selectOnOver: false,
		doOver: false,
		_built: false, 
		allowDisabledItemSelection: false,
		
		selectedIndex: null,
		selectedElement: null,
		
		_jThis: null, 
		_jLiHolder: null, 
		_jLi: null, 
		_jA: null,
		_jRadio: null,
		_enabledItemsRule: null,
		_enabledItemsRuleMap: [],
		
		/*
		// LIST TEMPLATE
		<ul>
			<li>
				<input.../>
				<a href='...' ...>1</a>
			</li>
			<li>
				<input.../>
				<label ...>
					<a href='...' ...>2</a>
				</label>
			</li>
			...
		</ul>

		// USAGE EXAMPLE
		var list = new SelectableList($('.lstColor li'));
			list.allowDisabledItemSelection = true;
			list.setEnabledItemsRule(function(){
				return !$(this).hasClass('unavailable');
			});
			$(list).bind('change', function(type, extra){
				console.info(type, extra);
			})
			$(list).bind('disabledItem', function(type, extra){
				console.info(type, extra);
			})
			list.init();
		*/
		constructor: function(jLiHolder, doOver, allowDisabledItemSelection){
			$.extend(true, this, pkg.SelectableList$Class);
			this._jLiHolder = jLiHolder;
			this.doOver = doOver === true;
			this.allowDisabledItemSelection = allowDisabledItemSelection === true;
			this._jThis = $(this);
		},
		
		
		init: function(jLi){
			if(jLi){
				this.refresh(jLi);
			}
		},
		refresh: function(jLi){
			this._built = false;
			this._removeListeners();
			if(this._jLi != null){
				this._jLi.remove();
			}
			if(jLi){
				this._jLi = jLi;
				this._jA = $('a', this._jLi);
				this._jRadio = $('input[type=radio]', this._jLi);
			}
		},
		build: function(jLi){
			this.refresh(jLi);
			if(this._jLi == null || this._built) return;
			if(this._jLi.parent() != this._jLiHolder){
				this._jLiHolder
					.empty()
					.append(this._jLi);
			}
			this._addListeners();
			this._built = true;
		},
		reset: function(){
			if(this._jRadio){
				this._jRadio.attr('checked', false);
			}
			this._jLi
				.removeClass(this.onClass)
				.removeClass(this.overClass);
		},
		
		
		verifySelectedValues: function(){
			var _this = this;
			if(this._jRadio){
				_this._jRadio.each(function(){
					var _jNode = $(this);
					var _liParentIndex = $.inArray(_jNode.parents('li')[0], _this._jLi);
					var _liParent = _liParentIndex >= 0 ? _this._jLi[_liParentIndex] : null;
					if(_jNode.is(':checked') && _liParent){
						_this.selectElement(_liParent);
						return false;
					}
				});
			}
		},
		
		
		// add / remove listeners
		_addListeners: function(){
			var jLi = this.allowDisabledItemSelection ? this._jLi : this.getActiveJLi();
			if(!jLi){
				return;
			}
			if(!this.selectOnOver){
				jLi.bind('click', this, this._onItemClick);
				
				$(jLi).click(function(){
					var oLi = $(this).parent().find("li"); 
					if($(oLi).size() <= 1){
						
						var lilstSize = $('.lstSize').find("li")[0];
						var liInput =  $(lilstSize).find("input:radio")[0];
						
						$(lilstSize).addClass("selected");
						
						$(liInput).each(function() {
							$(this).attr("checked",true);
							$('.referenceID').text("Ref." + $(this).val());
						});
					}
				});
			}
			if(this.doOver){
				jLi
					.bind('mouseenter', this, this._onItemRollOver)
					.bind('mouseleave', this, this._onItemRollOut)
					.trigger('mouseleave');
			}
		},
		_removeListeners: function(){
			if(!this._jLi) return;
			this._jLi.unbind('click', this._onItemClick);
			if(this.doOver){
				this._jLi
					.unbind('mouseenter', this._onItemRollOver)
					.unbind('mouseleave', this._onItemRollOut);
			}
		},
		
		
		// element listeners
		_onItemClick: function(e){
			e.data.selectElement(this);
			return false;
		},
		_onItemRollOver: function(e){
			if(e.data.selectOnOver){
				e.data.selectElement(this);
			}
			e.data.overElement(this);
			return false;
		},
		_onItemRollOut: function(e){
			e.data.outElement(this);
			return false;
		},
		
		
		// do selection / over / out
		selectElement: function(selectedNode){
			var _this = this;
			var jLi = this.allowDisabledItemSelection ? this._jLi : this.getActiveJLi();
			jLi.each(function(index){
				var _jNode = $(this);
				if(this == selectedNode){
					_jNode.addClass(_this.onClass);
					_jNode.children('input[type=radio]').attr('checked', true);
					_this.selectedIndex = index;
					_this.selectedElement = this;
					_this._jThis.trigger('change', {
						node: this,
						index: index,
						isEnabled: _this.getItemEnabled(index)
					});
					if(!_this.getItemEnabled(index)){
						_this._jThis.trigger('disabledItem', {
							node: this,
							index: index
						});
					}
				}else{
					_jNode.removeClass(_this.onClass);
				}
			});
		},
		overElement: function(selectedNode){
			$(selectedNode).addClass(this.overClass);
		},
		outElement: function(selectedNode){
			$(selectedNode).removeClass(this.overClass);
		},
		
		
		// setters and getters
		setEnabledItemsRule: function(rule){
			var _this = this;
			switch(typeof(rule)){
				case 'function':
					_this.setAllItemsEnabled(false);
					_this._enabledItemsRule = rule;
					_this._jLi
						.filter(_this._enabledItemsRule)
						.each(function(){
							var itemIndex = $.inArray(this, _this._jLi);
							if(itemIndex >= 0){
								_this.setItemEnabled(itemIndex);
							}
						});
					break;
			}
		},
		getActiveJLi: function(){
			var jLi = this._enabledItemsRule != null ? jLi = this._jLi.filter(this._enabledItemsRule) : null;
				jLi = jLi != null ? jLi : jLi = this._jLi;
			return jLi;
		},
		setAllItemsEnabled: function(enabled){
			for (var i = this._jLi.length - 1; i >= 0; i--)
				this.setItemEnabled(i, enabled);
		},
		setItemEnabled: function(index, enabled){
			if(index < this._jLi.length)
				this._enabledItemsRuleMap[index] = !(enabled === false);
		},
		getItemEnabled: function(index){
			return this._enabledItemsRuleMap[index] === true;
		}
	};
	pkg.SelectableList = pkg.SelectableList$Class.constructor;
		
	
})(window, jQuery);


/**
 * Image Loader
 */
(function(pkg, $){

	if($ == null){
		throw new Error('ImageLoader Class requires jQuery 1.3.2');
		return;
	}
	pkg = pkg || {};


	// base Class structure
	var STATUS_STOPPED = "stopped";
	var STATUS_LOADING = "loading";
	var STATUS_COMPLETE = "complete";
	var STATUS_ERROR = "error";
	
	pkg.ImageLoader$Class = {
		
		_jThis: null,
		_length: 0,
		_imagesToLoad: {},
		
		/*
			var image1 = new pkg.ImageLoader();
			$(image1).bind('error', function(type, extra){
				alert('error loading '+extra.url);
			});
			$(image1).bind('complete', function(type, extra){
				document.body.appendChild(extra.jImg);
			});
			image1.load('image.jpg');
		*/
		constructor: function(){
			$.extend(true, this, pkg.ImageLoader$Class);
			this._jThis = $(this);
		},
		
		
		load: function(id, url){
			if(!this._imagesToLoad[id]){
				this._imagesToLoad[id] = {
					id: id,
					url: url,
					jImg: $(document.createElement('img')),
					status: STATUS_STOPPED
				};
			}
			var jImg = this._imagesToLoad[id].jImg;
			var extra = {
				_this: this, 
				loader: this._imagesToLoad[id]
			};
			jImg
				.bind('error', extra, this._onError)
				.bind('load', extra, this._onComplete)
				.attr('src', extra.loader.url);
			
			extra.loader.status = STATUS_LOADING;
		},
		stop: function(id){
			var image = this._imagesToLoad[id];
			if(image){
				image.status = STATUS_STOPPED;
				image.jImg
					.attr('src', '')
					.unbind('error')
					.unbind('load');
			}
			this._jThis.trigger('abort', {
				id: image.id,
				url: image.url
			});
		},
		
		
		_onError: function(e){
			e.data.loader.status = STATUS_ERROR;
			$(e.data._this).trigger('error', {
				id: e.data.loader.id,
				url: e.data.loader.url
			});
 		},
		_onComplete: function(e){
			e.data.loader.status = STATUS_COMPLETE;
			$(e.data._this).trigger('complete', {
				id: e.data.loader.id,
				url: e.data.loader.url,
				jImg: e.data.loader.jImg.clone()
			});
		}
	}
	pkg.ImageLoader = pkg.ImageLoader$Class.constructor;
		
})(window, jQuery);

/**
 * Shortcuts
 */
(function(pkg){
	/*
		//Usage
		var sc = new Shortcut({
			name: 'marcelo miranda carneiro',
			age: '25'
		});
		
		sc.parseString('{name} has {age} years old.') // 'marcelo miranda carneiro has 25 years old.'
		
	*/
	pkg.Shortcut = function(shortcuts){
		
		var _this = this;
		this.shortcuts = shortcuts;
		
		var sortedShortcuts = [],
			matchedElement = [],
			currentShortcut,
			currentRegexp;

		for(var name in this.shortcuts){
			matchedElement = this.shortcuts[name].match(/\{.*?\}/g) || [];
			sortedShortcuts[sortedShortcuts.length] = matchedElement.length+'.'+name;
		}
		var sortNumber = function(a,b){;return a.split('.')[0]-b.split('.')[0];};
		sortedShortcuts.sort(sortNumber);

		for(var i=0; sortedShortcuts[i]; i++){
			currentShortcut = sortedShortcuts[i].split('.')[1];
			currentRegexp = new RegExp('\\{'+currentShortcut+'\\}', 'g');
			if(currentShortcut){
				for(var name in this.shortcuts){
					this.shortcuts[name] = this.shortcuts[name].replace(currentRegexp, this.shortcuts[currentShortcut]);
				}
			}
		}
		
		this.get = function(name){
			return _this.shortcuts[name];
		}
		this.parseString = function(value){
			if(!value) return '';
			var currentRegexp;
			for(var name in _this.shortcuts){
				currentRegexp = new RegExp('\\{'+name+'\\}', 'g');
				value = value.replace(currentRegexp, _this.shortcuts[name]);
			}
			return value;
		}
	};
	
	
})(window);

