// packager build Class-Extras/* DynamicMatcher/*
/*
---

name: Class.Binds

description: A clean Class.Binds Implementation

authors: Scott Kyle (@appden), Christoph Pojer (@cpojer)

license: MIT-style license.

requires: [Core/Class, Core/Function]

provides: Class.Binds

...
*/

Class.Binds = new Class({

	$bound: {},

	bound: function(name){
		return this.$bound[name] ? this.$bound[name] : this.$bound[name] = this[name].bind(this);
	}

});

/*
---

name: Class.Instantiate

description: Simple Wrapper for Mass-Class-Instantiation

authors: Christoph Pojer (@cpojer)

license: MIT-style license.

requires: [Core/Class]

provides: Class.Instantiate

...
*/

Class.Instantiate = function(klass, options){
	var create = function(object){
		if (object.getInstanceOf && object.getInstanceOf(klass)) return;
		new klass(object, options);
	};
	
	return function(objects){
		objects.each(create);
	};
};

/*
---

name: Class.Singleton

description: Beautiful Singleton Implementation that is per-context or per-object/element

authors: Christoph Pojer (@cpojer)

license: MIT-style license.

requires: [Core/Class]

provides: Class.Singleton

...
*/

(function(){

var storage = {

	storage: {},

	store: function(key, value){
		this.storage[key] = value;
	},

	retrieve: function(key){
		return this.storage[key] || null;
	}

};

Class.Singleton = function(){
	this.$className = String.uniqueID();
};

Class.Singleton.prototype.check = function(item){
	if (!item) item = storage;

	var instance = item.retrieve('single:' + this.$className);
	if (!instance) item.store('single:' + this.$className, this);
	
	return instance;
};

var gIO = function(klass){

	var name = klass.prototype.$className;

	return name ? this.retrieve('single:' + name) : null;

};

if (('Element' in this) && Element.implement) Element.implement({getInstanceOf: gIO});

Class.getInstanceOf = gIO.bind(storage);

}).call(this);

/*
---

name: DynamicMatcher

description: Searches elements via complex selectors and executes functions on them

authors: Christoph Pojer (@cpojer)

license: MIT-style license.

requires: [Core/Events, Core/Element]

provides: DynamicMatcher

...
*/

(function(){

this.DynamicMatcher = new Class({

	Implements: Events,

	initialize: function(){
		this.expressions = [];
		this.handlers = [];
	},

	register: function(expression, fn){
		var index = this.handlers.indexOf(fn);
		if (index != -1 && this.expressions[index] == expression) return this;

		this.expressions.push(expression);
		this.handlers.push(fn);

		return this;
	}.overloadSetter(),

	unregister: function(expression, fn){
		var handlers = this.handlers,
			expressions = this.expressions;

		for (var i = 0, l = handlers.length; i < l; i++) if (expression == expressions[i] && fn == handlers[i]){
			delete handlers[i];
			delete expressions[i];
			break;
		}

		return this;
	}.overloadSetter(),

	update: function(element){
		element = document.id(element) || document;

		var isDocument = (element == document),
			handlers = this.handlers,
			expressions = this.expressions;

		for (var i = 0, l = handlers.length; i < l; i++){
			var expression = expressions[i];
			if (!expression) continue;

			var elements = element.getElements(expression);
			if (!isDocument && element.match(expression)) elements.push(element);

			if (elements.length) handlers[i](elements);
		}

		this.fireEvent('update', [element]);

		return this;
	}

});

}).call(this);


