﻿/**
 * @author hooriza (ajaxUI) jindo1 version
 * @see http://wiki.nhncorp.com/display/lsuit/nhn.Clipboard
 */
if (typeof nhn == 'undefined') nhn = {};

nhn.Clipboard = (function() {

	function getOffset(oEl) {
	
		var oPhantom = null;
	
		// getter
		var bSafari = /Safari/.test(navigator.userAgent);
		var bIE = /MSIE/.test(navigator.userAgent);
	
		var fpSafari = function(oEl) {
	
			var oPos = { left : 0, top : 0 };
	
			for (var oParent = oEl, oOffsetParent = oParent.offsetParent; oParent = oParent.parentNode; ) {
	
				if (oParent.offsetParent) {
	
					oPos.left -= oParent.scrollLeft;
					oPos.top -= oParent.scrollTop;
	
				}
	
				if (oParent == oOffsetParent) {
	
					oPos.left += oEl.offsetLeft + oParent.clientLeft;
					oPos.top += oEl.offsetTop + oParent.clientTop ;
	
					if (!oParent.offsetParent) {
	
						oPos.left += oParent.offsetLeft;
						oPos.top += oParent.offsetTop;
	
					}
	
					oOffsetParent = oParent.offsetParent;
					oEl = oParent;
				}
			}
	
			return oPos;
	
		};
	
		var fpOthers = function(oEl) {
	
			var oPos = { left : 0, top : 0 };
	
			var oDoc = oEl.ownerDocument || oEl.document || document;
			var oHtml = oDoc.documentElement;
			var oBody = oDoc.body;
	
			if (oEl.getBoundingClientRect) { // has getBoundingClientRect
	
				if (!oPhantom) {
	
					if (bIE && window.external) {
						
						oPhantom = { left : 2, top : 2 };
						oBase = null;
	
					} else {
	
						oPhantom = { left : 0, top : 0 };
	
					}
	
				}
	
				var box = oEl.getBoundingClientRect();
				if (oEl !== oHtml && oEl !== oBody) {
	
					oPos.left = box.left - oPhantom.left;
					oPos.top = box.top - oPhantom.top;
					
					oPos.left += oHtml.scrollLeft || oBody.scrollLeft;
					oPos.top += oHtml.scrollTop || oBody.scrollTop;
					
				}
	
			} else if (oDoc.getBoxObjectFor) { // has getBoxObjectFor
	
				var box = oDoc.getBoxObjectFor(oEl);
				var vpBox = oDoc.getBoxObjectFor(oHtml || oBody);
	
				oPos.left = box.screenX - vpBox.screenX;
				oPos.top = box.screenY - vpBox.screenY;
	
			} else {
	
				for (var o = oEl; o; o = o.offsetParent) {
	
					oPos.left += o.offsetLeft;
					oPos.top += o.offsetTop;
	
				}
	
				for (var o = oEl.parentNode; o; o = o.parentNode) {
	
					if (o.tagName == 'BODY') break;
					if (o.tagName == 'TR') oPos.top += 2;
	
					oPos.left -= o.scrollLeft;
					oPos.top -= o.scrollTop;
	
				}
	
			}
			
			return oPos;
	
		};
	
		return (bSafari ? fpSafari : fpOthers)(oEl);
	};

	return Class({
	
		_elements : null,
		_datas : null,
		_overed : null,
		_failed: true,
		
		__init : function(sFlashURL, oOptions) {
	
			this._options = { };
			JINDO.extend(this._options, oOptions || {});
	
			this._flashURL = sFlashURL;
			
			var oStatic = nhn.Clipboard;
			
			var oEl = this._object = $(oEl);
			var nGap = /MSIE/.test(navigator.userAgent) && window.external ? 2 : 0;
			
			this._unique = 'S' + new Date().getTime() + parseInt(Math.random() * 1000000000);
			
			if (typeof oStatic._callbacks) oStatic._callbacks = {};
			oStatic._callbacks[this._unique] = this._flashCallback.owner(this);
			
			this._elements = [];
			this._datas = [];
			
			this._initFlash();
			
			this._handler = function(oEvent) {
				
				var oEvent = Event.ready(oEvent);
	
				this._initFlash();
				
				var oEl = null;
				for (oTmp = oEvent.element; oTmp; oTmp = oTmp.parentNode) {
					
					for (var i = 0, oTar; oTar = this._elements[i]; i++) {
						if (oTar == oTmp) {
							oEl = oTmp;
							break;
						}
					}
					
					if (oEl) break;
				}
	
				var oElPos = getOffset(oEl);
				this._setFlashPosSize(oElPos.left, oElPos.top, oEl.offsetWidth, oEl.offsetHeight);
			
				this._setClipboard(this._getData(oEl));
				this._overed = oEl;
				
			}.owner(this);
			
		},
		
		_initFlash : function() {
	
			if (this._dummy) return;
			var oDummy = this._dummy = $C('div');
			var sFlashUID = this._unique;
			
			oDummy.style.cssText = 'position:absolute !important; border:0 !important; padding:0 !important; margin:0 !important; overflow:visible !important; z-index:32000 !important;';
			document.body.insertBefore(oDummy, document.body.firstChild);
	
			oDummy.innerHTML = nhn.Flash.getCode(this._flashURL + '?' + new Date().getTime(), 'CLIPBOARD' + sFlashUID, 1, 1, 'transparent');
			Event.register(oDummy, 'click', this._checkFailed.owner(this));
	
			var oFlash = nhn.Flash.find('CLIPBOARD' + sFlashUID);
			oFlash.style.cssText = 'position:absolute !important; left:0 !important; top:0 !important; border:0 !important; padding:0 !important; margin:0 !important;';
			
		},

		_setFlashPosSize : function(nLeft, nTop, nWidth, nHeight) {
			
			var sFlashUID = this._unique;
	
			var oDummy = this._dummy;
			oDummy.style.left = nLeft + 'px';
			oDummy.style.top = nTop + 'px';
			
			var oFlash = nhn.Flash.find('CLIPBOARD' + sFlashUID);
			oFlash.width = nWidth;
			oFlash.height = nHeight;
			oFlash.style.width = nWidth + 'px';
			oFlash.style.height = nHeight + 'px';
	
		},
			
		setData : function(oEl, sData) {
			
			var oEl = $(oEl);
			
			var nIndex = this._elements.indexOf(oEl);
			var bExist = nIndex != -1;
			
			if (typeof sData == 'undefined' && bExist) { // 지워야 하는 상황이면
				
				Event.unregister(oEl, 'mousemove', this._handler);
				
				this._elements.splice(nIndex, 1);
				this._datas.splice(nIndex, 1);
				
				this._setFlashPosSize(0, 0, 1, 1);
				return;
				
			}
	
			if (oEl == this._overed) this._setClipboard(sData);
	
			if (bExist) { // 바꿔야 하는 상황
				this._datas[nIndex] = sData;
				return;
			}
			
			// 새로 만들어야 하는 상황
			Event.register(oEl, 'mousemove', this._handler);
			
			this._elements.push(oEl);
			this._datas.push(sData);
			
		},
		
		_getData : function(oEl) {
			
			var nIndex = this._elements.indexOf(oEl);
			return this._datas[nIndex];
			
		},
		
		_setClipboard : function(sData) {
			
			if (sData == this._applied) return;
			this._lastestData = sData;
	
			var sFlashUID = this._unique;
			var oFlash = nhn.Flash.find('CLIPBOARD' + sFlashUID);
			
			try {
	
				oFlash.setClipboardData(this._unique, sData);
				this._applied = sData;
				this._failed = false;
				
			} catch(e) {
				
				this._failed = true;
				
			}
			
		},
		
		_checkFailed : function() {
			
			if (this._failed) {
				
				if (typeof this._options.onFailure != 'undefined')
					this._options.onFailure.call(this, this._overed, this._lastestData);
				
			}
			
		},
	
		_flashCallback : function(sData) {
			
			if (typeof this._options.onCopy != 'undefined')
				this._options.onCopy.call(this, this._overed, sData);
		
		}
	
	});
	
})();

