// SilverIPE: A simple In Place Editor Class
// By: Jean-Nicolas Jolivet (http://www.silverscripting.com)
// Released under the MIT License
// Version: 0.2

var SilverIPE = function (el, url, options) {
	this.url = url;
	var that = this;

	// If el is a string, we get the element by this id, if not, assume it's an element
	this.el = (typeof el === 'string') ? document.getElementById(el) : el;
	this.el.title = (this.el.title === '') ? 'Click to edit...' : this.el.title;
	// Remember the original BG color if it's not set, default to transparent
	this.originalBg = (this.el.style.backgroundColor === '') ? 'transparent' : this.el.style.backgroundColor;
	
	// define the default options...
	this.options = {
		parameterName: 'value',
		method: 'POST',
		highlightColor: '#FFFFBF',
		borderColor: '#000',
		imageLevel: '',
		savingText: 'Saving...',
		cancelButtonLabel: 'cancel',
		textWidth: 20,
		textHeight: 4,
		additionalParameters: {}
	};
	
	this.options = this.mergeObjects(this.options, options || {});
	this.options.method = this.options.method.toUpperCase();
	this.el.onmouseover = function () {
		that.el.style.backgroundColor = that.options.highlightColor;
	};
	
	this.el.onmouseout = function () {
		that.el.style.backgroundColor = that.originalBg;
	};
	
	this.el.onclick = function () {	
		that.elClicked.call(that);
	};
	this.buildElements();
};

SilverIPE.prototype.buildElements = function () {
	var parentEl = this.el.parentNode;
	var that = this;
	
	this.runscript = 0;
	
//ADD
	this.addbutton = document.createElement("img");
	this.addbutton.src =  this.options.imageLevel + "images/action_add.png";
	this.addbutton.style.display = 'none';
	this.addbutton.style.cursor = 'pointer';
	this.addbutton.onclick = function () {
		that.addClicked.call(that);
		return false;
	};
	
	
	//MINUS
	this.minusbutton = document.createElement("img");
	this.minusbutton.src =  this.options.imageLevel + "images/action_remove.png";
	this.minusbutton.style.display = 'none';
	this.minusbutton.style.cursor = 'pointer';
	this.minusbutton.onclick = function () {
		that.minusClicked.call(that);
		return false;
	};
	
	// For inline elements, we use a text input
	if (this.el.tagName.toLowerCase() === 'span' || ((this.el.tagName.toLowerCase() === 'div' || this.el.tagName.toLowerCase() === 'p') && this.el.style.display === 'inline')) {
		this.inputEl = document.createElement("input");
		this.inputEl.type = "text";
		this.inputEl.size = this.options.textWidth;
		this.originalDisplay = 'inline';
		this.inputEl.style.textAlign= 'center';
		
		this.inputEl.onkeydown = function (e) {
				if(e.keyCode==13)
				{
					that.saveClicked.call(that);
					return false;
				}
				else if (e.keyCode==27)
				{
					that.cancelClicked.call(that);
					return false;
				}
				else if (e.keyCode > 31 && (e.keyCode < 48 || e.keyCode > 57))
				{
					
					if (e.keyCode < 96 || e.keyCode > 105)
           				return false;
				}
			};
		
	}
	// For block elements, use a textarea
	else if ((this.el.tagName.toLowerCase() === 'div' || this.el.tagName.toLowerCase() === 'p') || 
	(this.el.tagName.toLowerCase() && this.el.style.display === 'block')) 
	{
		this.inputEl = document.createElement("textarea");
		this.inputEl.cols = this.options.textWidth;
		this.inputEl.rows = this.options.textHeight;
		this.originalDisplay = (this.el.style.display === '') ? 'block' : this.el.style.display;
	}
	
	this.inputEl.style.display = 'none';
	this.inputEl.style.border = '1px dashed ' + this.options.borderColor;
	this.inputEl.style.backgroundColor = this.options.highlightColor;
	parentEl.insertBefore(this.inputEl, this.el.nextSibling);
	this.saveButton = document.createElement('a');
//	this.saveButton.innerHTML = this.options.saveButtonLabel;
this.saveButton.innerHTML = '<img src="' +  this.options.imageLevel + 'images/action_check.png" border="0" alt=""/>';
	this.setCommonStyles(this.saveButton);
	this.saveButton.onclick = function () {
		that.saveClicked.call(that);
		return false;
	};


	
	
	parentEl.insertBefore(this.saveButton, this.inputEl.nextSibling);
	
	this.cancelButton = document.createElement('a');
	this.cancelButton.innerHTML = '<img src="'+   this.options.imageLevel + 'images/action_delete.png" border="0" alt=""/>';

	//this.cancelButton.innerHTML = this.options.cancelButtonLabel;
	this.setCommonStyles(this.cancelButton);
	this.cancelButton.onclick = function () {
		that.cancelClicked.call(that);
		return false;
	};
	parentEl.insertBefore(this.cancelButton, this.saveButton.nextSibling);
		parentEl.insertBefore(this.minusbutton, this.inputEl.nextSibling);
	parentEl.insertBefore(this.addbutton, this.el.nextSibling);

};

SilverIPE.prototype.cancelClicked = function () {
	this.hideIpe();

};

SilverIPE.prototype.addClicked = function () {
	var number = 0;
	var currentvalue = this.inputEl.value;
	currentvalue = currentvalue * 1;
	number = currentvalue + 1;
	this.inputEl.value = number;
	this.inputEl.focus();
	this.inputEl.select();
}

SilverIPE.prototype.minusClicked = function () {
	var number = 0;
	var currentvalue = this.inputEl.value;
	currentvalue = currentvalue * 1;
	number = currentvalue- 1;
	this.inputEl.value = number;
	this.inputEl.focus();
	this.inputEl.select();
}
SilverIPE.prototype.saveClicked = function () {
	if (this.inputEl.value !== this.lastValue)
	{
		this.el.innerHTML = this.options.savingText;
		this.hideIpe();
		this.request = this.requestFactory();
		var that = this;
		var additionalData = this.extractParams();
		var data = this.options.parameterName + '=' + this.inputEl.value + additionalData;
		var url = this.options.method === "POST" ? this.url : this.url + "?" + data;
		
		this.request.onreadystatechange = function () {
			that.handleRequest.call(that);
		};
		
		this.request.open(this.options.method, url, true);
		this.request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
		this.request.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
		if(this.options.method === "POST") {
			this.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
			this.request.setRequestHeader("Content-length", data.length);
			this.request.setRequestHeader("Connection", "close");
		}
		this.request.send(data);
		
		this.runscript = 0;
	}
	if (this.inputEl.value == 0)
	{
		this.el.innerHTML = this.options.savingText;
		this.hideIpe();
		this.request = this.requestFactory();
		var that = this;
		var additionalData = this.extractParams();
		var data = this.options.parameterName + '=' + this.inputEl.value + additionalData;
		var url = this.options.method === "POST" ? this.url : this.url + "?" + data;
		
		this.request.onreadystatechange = function () {
			that.handleRequest.call(that);
		};
		
		this.request.open(this.options.method, url, true);
		this.request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
		this.request.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
		if(this.options.method === "POST") {
			this.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
			this.request.setRequestHeader("Content-length", data.length);
			this.request.setRequestHeader("Connection", "close");
		}
		this.request.send(data);
		
		this.runscript = 1;
	}
	else {
		this.cancelClicked();
		this.runscript = 0;
	}
	
};

SilverIPE.prototype.extractParams = function() {
	var params = "";
	for(param in this.options.additionalParameters) {
		if(typeof param !== "function") {
			params = params + "&" + param + "=" + this.options.additionalParameters[param];
		}
	}
	return params;
}


SilverIPE.prototype.hideIpe = function () {
	this.inputEl.style.display = 'none';
	this.saveButton.style.display = 'none';
	this.cancelButton.style.display = 'none';
	this.addbutton.style.display = 'none';
	this.minusbutton.style.display = 'none';
	this.el.style.display = this.originalDisplay;
};


SilverIPE.prototype.setCommonStyles = function (el) {
	el.href = '#';
	el.style.fontFamily = 'arial, sans-serif';
	el.style.fontSize = '11px';
	el.style.display = 'none';
	el.style.margin = '0 4px';
};

SilverIPE.prototype.elClicked = function (test) {
	var strValue = this.trimString(this.el.innerHTML);
	this.inputEl.value = strValue;
	this.lastValue = this.inputEl.value;
	this.showIpe();
	this.inputEl.focus();
};

SilverIPE.prototype.showIpe = function () {
	this.el.style.display = 'none';
	this.inputEl.style.display = 'inline';
	this.inputEl.select();

	this.addbutton.style.display = 'inline';
	this.saveButton.style.display = 'inline';
	this.cancelButton.style.display = 'inline';
	this.minusbutton.style.display = 'inline';
};

SilverIPE.prototype.highlight = function (el, origColor, highColor) {
	var that = this;
	setTimeout(function () {
		that.doHighlight.call(that, el, highColor);
	}, 75);
	setTimeout(function () {
		that.doHighlight.call(that, el, origColor);
	}, 150);
	setTimeout(function () {
		that.doHighlight.call(that, el, highColor);
	}, 225);
	setTimeout(function () {
		that.doHighlight.call(that, el, origColor);
	}, 300);
};

SilverIPE.prototype.doHighlight = function (el, color) {
	el.style.backgroundColor = color;
};

// Internal function to merge 2 objects...
SilverIPE.prototype.mergeObjects = function (orig, ext) {
	var name;
	for (name in ext || {}) {
		if (typeof name !== "function") {
			orig[name] = ext[name];
		}
	}
	return orig;
};

SilverIPE.prototype.trimString = function(str) {
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
};


// XMLHttpRequest Related Functions
SilverIPE.prototype.requestFactory = function () {
	// Thanks to WikiPedia for the XMLHttpRequest factory snippet...
	if (typeof XMLHttpRequest === "undefined")
	{
		XMLHttpRequest = function () {
			try { 
				return new ActiveXObject("Msxml2.XMLHTTP.6.0"); 
			} 
			catch (e) {}
			try { 
				return new ActiveXObject("Msxml2.XMLHTTP.3.0"); 
			} catch (e) {}
			try { 
				return new ActiveXObject("Msxml2.XMLHTTP"); 
			} catch (e) {}
			try { 
				return new ActiveXObject("Microsoft.XMLHTTP"); 
			}  catch (e) {}
			throw new Error("This browser does not support XMLHttpRequest or XMLHTTP.");
		};
	}
	var request = new XMLHttpRequest();
	return request;
};

SilverIPE.prototype.handleRequest = function () {
	if (this.request.readyState === 4) {
		if (this.request.status === 200) {
			if (this.runscript)
				eval(this.request.responseText);
			else
			{
				// We got a successfull response...
				this.el.innerHTML = this.request.responseText;
				this.hideIpe();
				this.highlight(this.el, this.originalBg, this.options.highlightColor);
			}
		}
		else { // an error...
			this.el.innerHTML = 'Error ' + this.request.status + ": " + this.request.statusText;
			
			this.highlight(this.el, this.originalBg, '#FF8282');
		}
	}
};


