Element.implement({
	addClasses: function(classes) {
// mm.log(classes);		
		classes.each(function(cl) {
			this.addClass(cl);
		},this);
		return this;		
	},
	removeClasses: function(classes) {
		classes.each(function(cl) {
			this.removeClass(cl);
		},this);		
		return this;		
	}
	, removeStyles: function(styles) {
		styles.each(function(style) {
			this.setStyle(style,null);
		},this);		
		return this;
	}
});

/*
	http://cpojer.net/blog/Custom_outerClick_event
	usage:
	myElement.addEvent('outerClick', function(){ 	
	  console.log('You clicked outside the element'); 	
	 });	
*/
Element.Events.outerClick = {
	
	base : 'click',
	
	condition : function(event){
		event.stopPropagation();
		return false;
	},
	
	onAdd : function(fn){
		this.getDocument().addEvent('click', fn);
	},
	
	onRemove : function(fn){
		this.getDocument().removeEvent('click', fn);
	}
	
};

mm.random = function(min, max){
	if (min != undefined && max != undefined) {
		return Math.floor(Math.random() * (max - min + 1) + min);
	} else {
		if (min != undefined) {
			return Math.floor(Math.random() * (min - 0 + 1) + 0);
		} else {
			return Math.random();
		}
	}
};

/* toHTML creates element(s) from an html string */
String.implement({
	
	toHTML: function(){
		var wrapper =	this.test('^<the|^<tf|^<tb|^<colg|^<ca') && ['<table>', '</table>', 1] ||
						this.test('^<col') && ['<table><colgroup>', '</colgroup><tbody></tbody></table>',2] ||
						this.test('^<tr') && ['<table><tbody>', '</tbody></table>', 2] ||
						this.test('^<th|^<td') && ['<table><tbody><tr>', '</tr></tbody></table>', 3] ||
						this.test('^<li') && ['<ul>', '</ul>', 1] ||
						this.test('^<dt|^<dd') && ['<dl>', '</dl>', 1] ||
						this.test('^<le') && ['<fieldset>', '</fieldset>', 1] ||
						this.test('^<opt') && ['<select multiple="multiple">', '</select>', 1] ||
						['', '', 0];
		var el = new Element('div', {html: wrapper[0] + this + wrapper[1]}).getChildren();
		while(wrapper[2]--) el = el[0].getChildren();
		if (typeOf(el) == 'elements' && el.length == 1) {
			el = el[0];
		}
		return el;
	}

});

String.implement({	
	cleanFilename:function() {
		var str = this;
		str = str.tidy();
		str = str.standardize();
		str = str.replace(/[^a-zA-Z0-9\.\-\_]/g , '');
		return str;
	}
	, cleanUri:function(){ 
		var str = this;
		str = str.tidy();
		str = str.standardize();
		str = str.replace(/ /g,'-');
		str = str.replace(/[^a-zA-Z0-9\.\-\_\#\:\;\,\=\+\(\)\?\&\/]/g , '');
		return str;		
	}
	, stripAll:function() {
//dbug.log(name.test(/^[a-zA-Z0-9-_]+$/));
		var str = this;
		['\\*', '\\/', '>', '<','"', '\'', '&', '\\?','!','@','#','\\$','%','~','`','±','§','\\[','\\]','\\(','\\)','\\{','\\}','=','\\+','\\^'].each(function(c) {
			var reg = new RegExp(c,'g'); 
//dbug.log('cleanstr = '+str);			
			str.replace(reg,'');	
		},this); 
//dbug.log('clean name ='+name);		
		str = str.replace(/_+/g,'_');
		str = str.replace(/ +/g,'_');
		str = str.replace(/\.\.+/g,'-');
		str = str.replace(/\,+/g,'-');		
		str = str.replace(/-+/g,'-');		
		str = str.replace(/'+/g,'');		
		str = str.replace(/&+/g,'');				
		str = str.tidy();
		str = str.standardize();
		//str = str.toLowerCase();
		return str;		
	}
});


/*
Property: numberFormat
	Format a number with grouped thousands.

Arguments:
	decimals, optional - integer, number of decimal percision; default, 2
	dec_point, optional - string, decimal point notation; default, '.'
	thousands_sep, optional - string, grouped thousands notation; default, ','

Returns:
	a formatted version of number.

Example:
	>(36432.556).numberFormat()  // returns 36,432.56
	>(36432.556).numberFormat(2, '.', ',')  // returns 36,432.56
*/
Number.implement({
	numberFormat : function(decimals, dec_point, thousands_sep) {
		decimals = Math.abs(decimals) + 1 ? decimals : 2;
		dec_point = dec_point || '.';
		thousands_sep = thousands_sep || '';
	
		var matches = /(-)?(\d+)(\.\d+)?/.exec((isNaN(this) ? 0 : this) + ''); // returns matches[1] as sign, matches[2] as numbers and matches[3] as decimals
		var remainder = matches[2].length > 3 ? matches[2].length % 3 : 0;
		return (matches[1] ? matches[1] : '') + (remainder ? matches[2].substr(0, remainder) + thousands_sep : '') + matches[2].substr(remainder).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep) + 
				(decimals ? dec_point + (+matches[3] || 0).toFixed(decimals).substr(2) : '');
	}
});

/**
 * original from jan kassens http://github.com/kassens/mootools-snippets/blob/master/Number.js
 *
 * @author thierry bela <bntfr at yahoo dot fr>
 */
Number.implement({

  format: function(kSep, floatsep, decimals, fill){
      decimals = Array.pick(decimals, 2);
      floatsep = Array.pick(floatsep, '.');
      kSep = Array.pick(kSep, ' ');
      fill = Array.pick(fill, '');
 
      var parts = this.round(decimals).toString().split('.'),
		integer = parts[0];
      while (integer != (integer = integer.replace(/([0-9])(...($|[^0-9]))/, '$1' + kSep + '$2')));
      if (decimals === 0) return integer;
	  
	  var dec = parts[1] ? parts[1].substr(0, decimals) : '';
		  
	  if(fill) while(dec.length < decimals) dec += '0';
	  
	  return integer + (dec ? floatsep + dec : '')
  }
	, formatSize: function () {			
		if(this == 0) return this;
		if (this < 1024) return this + ' ' + 'Bytes';		
		if (this < 1024 * 1024) return (this / 1024.).format() + ' Kb';
		if (this < 1024 * 1024 * 1024) return (this / (1024 * 1024.)).format() + ' Mb';
		return (this / (1024 * 1024 * 1024.)).format() + ' Gb';
	}

});
