/* Event Delegator */

// Introduces Event delegation (http://icant.co.uk/sandbox/eventdelegation)
Object.extend(Event, {
    delegate: function(element, eventName, targetSelector, handler) {
    var element = $(element);

    function selectorMatch(element) {
        return element.match(targetSelector);
    }

    function validateTarget(origin) {
        if ( origin.match(targetSelector) ) { return origin; }
        var ancestors = origin.ancestors();
        return ancestors.find(selectorMatch);
    }

    function createDelegation(_delegatedEvent) {
        var rawOrigin = _delegatedEvent.element();
        var origin = validateTarget(rawOrigin);
        if ( origin != null && (typeof handler == 'function') ){ 
            _delegatedEvent.element = function() { return origin; }
            return handler(_delegatedEvent);
        }
    };

    element.observe(eventName, createDelegation);
    return element;
    },

    delegators: function(element, eventName, rules) {
        var element = $(element);
        function delegateRule(rule) {
            element.delegate(eventName, rule.key, rule.value)
        }
        $H(rules).each(delegateRule)
        return element;
    }
})

Element.addMethods({
    delegate: Event.delegate,
    delegators: Event.delegators
})

Object.extend(document, {
    delegate: Event.delegate,
    delegators: Event.delegators
})
/* Event Delegator */

/* String Buffer */
var StringBuffer = function() {
	this.buffer = [];
	this.index = 0;
};

StringBuffer.prototype = {
	append: function(s) {
		this.buffer[this.index] = s;
		this.index += 1;
		return this;
	},

	toString: function() {
		return this.buffer.join("");
	}
};

/** Deep clone  **/

Object.clone = function(object, options) {
  options = options || { deep: false };
  if (typeof options !== 'object')
    options = { deep: !!options };
  if (!options.deep) {
    return object && Object.isFunction(object.clone) ?
      object.clone() : Object.extend({ }, object);
  }
  
  var value, useOwnClone,
   clone = { }, properties = Object.keys(object);
  
  if (!Object.keys({ toString: true }).length)
    properties.push("toString", "valueOf");
  
  properties._each(function(property) {
    value = object[property];
    if (value) {
      useOwnClone = Object.isFunction(value.clone);
      if (typeof value === 'object' && !useOwnClone)
        value = Object.clone(value, true);
      else if (useOwnClone)
        value = value.clone(true);
    }
    clone[property] = value;
  });
  
  return clone;
};
 
Array.prototype.clone = function(options) {
  options = options || { deep: false };
  if (typeof options !== 'object') options = { deep: !!options };
  if (!options.deep) return [].concat(this);
  
  var clone = [], length = this.length;
  while (length--)
    clone[length] = Object.clone(this[length], true);
  return clone;
};
 
Hash.prototype.clone = function(options) {
  var h = new Hash();
  h._object = Object.clone(this._object, options);
  return h;
};


/*** 
     Unused, so to save execution time the method is commented
     Also, there is a Error when 'element' doesn't exists
***/ 
// Element.addMethods({
//   clone: function(element, options) {
//     options = options || { deep: false, removeIds: false };
//     if (typeof options !== 'object')
//       options = { deep: !!options, removeIds: false };
//     alert("ele 1 : " + element);
    
//     var elements, clone = $(element).cloneNode(options.deep);
//     alert("ele 2");
//     if (options.removeIds) {
//       (elements = Element.select(clone, '*[id]')).push(clone);
//       elements._each(function(el) { el.removeAttribute('id') });
//     }
//     alert("ele 3");
//     return clone;
//   }
// });

String.prototype.namespace = function(separator){
  this.split(separator || '.').inject(window, function(parent, child) {
    var o = parent[child] = parent[child] || { }; return o;
  });
}