﻿var ColorPicker = (function() {
	var COLORS_TABLE = [
		["F4CCCC", "FCE5CD", "FFF2CC", "D9EAD3", "D0E0E3", "CFE2F3", "D9D2E9", "EAD1DC"],
		["EA9999", "F9CB9C", "FFE599", "B6D7A8", "A2C4C9", "9FC5E8", "B4A7D6", "D5A6BD"],
		["E06666", "F6B26B", "FFD966", "93C47D", "76A5AF", "6FA8DC", "8E7CC3", "C27BA0"],
		["CC0000", "E69138", "F1C232", "6AA84F", "45818E", "3D85C6", "674EA7", "A64D79"],
		["990000", "B45F06", "BF9000", "38761D", "134F5C", "0B5394", "351C75", "741B47"],
		["660000", "783F04", "7F6000", "274E13", "0C343D", "073763", "20124D", "4C1130"],
		["000000", "151515", "2E2E2E", "585858", "848484", "A4A4A4", "E6E6E6", "FFFFFF"]
	];

	var ColorPicker = new Class({
		Implements: [Options, Events],
		element: null,
		trigger: null,

		options: {
			addFocusEvent: false,
			addClickEvent: false,
			setValue: false
		},

		initialize: function(element, trigger, options) {
			this.element = $(element);
			this.trigger = $(trigger);

			this.setOptions(options);

			this.trigger.addEvent("click", this.toggle.bind(this));
			this.element.addEvent("keyup", function() {
				this.setColor(this.element.value);
			} .bind(this));

			if (this.options.addFocusEvent)
				this.element.addEvent("focus", function() {
					this.element.select();
				} .bind(this));
			if (this.options.addClickEvent)
				this.element.addEvent("click", function(e) {
					if (!e)
						return;
					var n_x = e.client.x;
					var n_this_x = this.element.getPosition().x;
					var n_width = this.element.getSize().x;

					if (n_x - n_this_x >= n_width - 30)
						this.show();
				} .bind(this));

			if (this.options.setValue)
				this.setColor(this.element.get("value"));
		},

		setColor: function(color) {
			try {
				color = color.toUpperCase();
				this.trigger.setStyle("background-color", color);
			} catch (ex) { return; }
			this.fireEvent("change", [color]);
			this.element.value = color;
		},

		buildTable: function() {
			var html = [];

			html.push('<div class="colorPicker" style="display: none">');
			html.push('<table cellpadding="0" cellspacing="0">');
			for (var i = 0; i < COLORS_TABLE.length; i++) {
				html.push("<tr>");
				for (var j = 0; j < COLORS_TABLE[i].length; j++) {
					html.push('<td style="background-color: #' + COLORS_TABLE[i][j] + ';" title="#' + COLORS_TABLE[i][j] + '">');
				}
				html.push("</tr>");
			}
			html.push("</table>");
			html.push("</div>");

			var table = new Element("div", { html: html.join("") }).getFirst();

			table.addEvent("mouseup", function(e) {
				var el = $(e.target);
				if (el.get("tag") == "td") {
					var color = el.getStyle("background-color");
					this.hide();
					this.setColor(color);
				}
			} .bind(this));

			this.colorTable = table;

			$(document.body).grab(table);
			var position = this.trigger.getPosition();
			table.setStyle("position", "absolute");
			position.y += this.trigger.getHeight();
			table.position(position);
		},

		show: function() {
			if (this.visible) return;
			if (!this.initialized) {
				this.buildTable();
				this.initialized = true;
			}
			this.colorTable.setStyle("display", "");
			this.visible = true;
			this.attachHideOnBodyClick();
		},

		hide: function() {
			if (!this.visible) return;
			this.colorTable.setStyle("display", "none");
			this.visible = false;
			this.detachHideOnBodyClick();
		},

		toggle: function(e) {
			if (this.visible) this.hide();
			else this.show();
		},

		attachHideOnBodyClick: function() {
			$(document.body).addEvent('mouseup', this.getHideOnBodyClick());
		},

		detachHideOnBodyClick: function() {
			$(document.body).removeEvent('mouseup', this.getHideOnBodyClick());
		},

		getHideOnBodyClick: function() {
			return this._hideOnBodyClick || (this._hideOnBodyClick = this.hideOnBodyClick.bind(this));
		},

		hideOnBodyClick: function(e) {
			//if mouseup on the colors table or on the trigger
			if (
				e.target == this.element ||         //mouseup on colors table
				this.element.hasChild(e.target) ||  //mouseup on childs of colors table
				e.target == this.trigger || 		//mouseup on trigger
				this.trigger.hasChild(e.target)		//mouseup on childs of trigger
			) return;
			this.hide();
		}
	});

	return ColorPicker;
})();
