


function showPopupDialog(params) {
	params = params || {
		url:'',
		windowName:'',
		xOffset:105,
		yOffset:-20,
		width:480, height:480
	}; 
	var top = Math.round((window.screenY||window.screenTop)+(window.outerHeight||document.body.clientHeight)/2-params.height/2)+params.yOffset;
	var left = Math.round((window.screenX||window.screenLeft)+(window.outerWidth||document.body.clientWidth)/2-params.width/2)+params.xOffset;
	var settings = 'top=%@,left=%@,height=%@,width=%@,resizable=yes,scrollbars=no,menubar=no,status=0,toolbar=0,location=0'.fmt(top,left,params.height,params.width);
	var uploadWin=window.open(params.url,params.windowName,settings);
	uploadWin.focus();
};

Array.prototype.replace = function(idx, amt, objects) {
  if (!objects || objects.length == 0) {
    this.splice(idx, amt) ;
  } else {
    var args = [idx, amt].concat(objects) ;
    this.splice.apply(this,args) ;
  }
  return this ;
};
Array.prototype.removeAt = function(idx) {
    if ((idx < 0) || (idx >= this.length)) throw "OUT_OF_RANGE_EXCEPTION: Array.removeAt";
    var ret = this[idx];
    this.replace(idx,1,[]);
    return ret;
};
Array.prototype.removeObject = function(obj) {
    var loc = this.length || 0;
    while(--loc >= 0) {
      	var curObject = this[loc];
      	if (curObject == obj) this.removeAt(loc) ;
    }
    return this;
};

String.prototype.fmt = function() {
	var args = arguments;
	var str = this.gsub(/%@([0-9]+)/, function(m) {
		return (args[parseInt(m[1],0)-1] || '').toString(); 
	});
	var ret = [] ;
	var idx = -1 ;
	var loc = 0 ;
	var argIdx = 0;
	while((idx = str.indexOf("%@",loc)) >= 0) {
		ret.push(str.slice(loc,idx)) ;
		loc = idx + 2 ; // 2 to skip '%@'.
		var value = args[argIdx++] ;
		if (value && value.toString) value = value.toString() ;
		ret.push(value) ;
	}

	if (loc < str.length) {
		ret.push(str.slice(loc,str.length)) ;
	}
	return (ret.length > 1) ? ret.join('') : ret[0] ;
};

String.prototype.oneOf = function() {
	if (arguments.length>0) {
	 	var arr = (arguments[0] instanceof Array) ? arguments[0] : arguments[0].toString().split(arguments[1] || ' ');
		var i = arr.length;
		while(--i>=0) if (arr[i]==this) return true;
	}		
	return false;
};

$egg.fn._collectFrame = function(func) {
	var el = this[0] ;
	// if view is not displayed, temporarily display it also
	var display = this.css('display') ;
	var isHidden = !(display != 'none' && display != null) ;

	// All *Width and *Height properties give 0 on elements with display none,
	// so enable the element temporarily
	if (isHidden) {
		var els = el.style;
		var originalVisibility = els.visibility;
		var originalPosition = els.position;
		var originalDisplay = els.display;
		els.visibility = 'hidden';
		els.position = 'absolute';
		els.display = 'block';
	}
	//var ret = func.call(this) ;
	var ret = func.call();

	if (isHidden) {
		els.display = originalDisplay;
		els.position = originalPosition;
		els.visibility = originalVisibility;
	}

	return ret;
};
$egg.fn.frame = function(value) {
	if (value !== undefined) {
		/*
		var f= value ;
		var style = {} ;
		var didResize = false ;

		if (value.x !== undefined) {
			style.left = Math.floor(f.x) + 'px';
			style.right = 'auto';
		}
		if (value.y !== undefined) {
			style.top = Math.floor(f.y) + 'px';
			style.bottom = 'auto';
		}
	    if (value.width !== undefined) {
	        didResize = true ;
	        var padding = 0 ;
	        var idx = SC.View.WIDTH_PADDING_STYLES.length;
	        while(--idx >= 0) {
	          	padding += parseInt(this.getStyle(SC.View.WIDTH_PADDING_STYLES[idx]), 0) || 0;
	        }
	        var width = Math.floor(f.width) - padding ;
	        if (!isNaN(width)) style.width = width.toString() + 'px' ;
	    }

		if (value.height !== undefined) {
			didResize = true ;
			var padding = 0 ;
			var idx = SC.View.HEIGHT_PADDING_STYLES.length;
			while(--idx >= 0) {
				padding += parseInt(this.getStyle(SC.View.HEIGHT_PADDING_STYLES[idx]), 0) || 0;
			}
			var height = Math.floor(f.height) - padding ;
			if(!isNaN(height)) style.height = height.toString() + 'px' ;
		}
		
	    this.css(style) ;
		*/
		$(this).css({left:"%@px".fmt(value.x), top:"%@px".fmt(value.y), width:"%@px".fmt(value.width), height:"%@px".fmt(value.height)});
		return $(this);
	}
	// if layoutMode == SC.MANUAL_MODE

	var el = this[0] ;
	var f = this._collectFrame(function() {
		return { 
			x: el.offsetLeft, 
			y: el.offsetTop, 
			width: el.offsetWidth, 
			height: el.offsetHeight 
		};
	}) ;
	// bizarely for FireFox if your offsetParent has a border, then it can impact the offset
	if (Prototype.Browser.Gecko) {
		var parent = el.offsetParent ;
		var overflow = (parent) ? Element.getStyle(parent, 'overflow') : 'visible' ;
		if (overflow && overflow !== 'visible') {
			var left = parseInt(Element.getStyle(parent, 'borderLeftWidth'),0) || 0 ;
			var top = parseInt(Element.getStyle(parent, 'borderTopWidth'),0) || 0 ;
			f.x += left; f.y += top ;
		}
	}
	return f ;
};

$egg.fn.submitForm = function(form_id, opts) {
	try { 
		var form = $(form_id);
		if (form) {
			//target = target || 'dialog_content'
			$egg(this).showSubmitSpinner(); 
			/*
			$egg.post(form.action, $egg("#"+form_id).serialize(), function() {
				$egg(this).hideSubmitSpinner();
			});
			*/
			console.log($egg(form).serializeArray());
			if ($egg(this).is('#dialog_content')) 
			{
				$egg(this).load(form.action, $egg(form).serializeArray(), function() {
					$egg(this).hideSubmitSpinner();
					if (opts && opts.closeOnDone===true) app.closeDialog();
				});
			}
			else
			{
				$egg(this).find('.content').load(form.action, $egg(form).serializeArray(), function() {
					$egg(this).hideSubmitSpinner();
					if (opts && opts.closeOnDone===true) app.closeDialog();
				});
			}
			
			
			/*
			new Ajax.Updater('dialog_content', form.action, {
				asynchronous:true, evalScripts:true, 
				parameters:Form.serialize(form), 
				onComplete: function() {
					$egg('#'+target).hideSubmitSpinner();
				}
			});
			*/
		}
	}catch(e){alert(e);} 
	return $egg(this);
};
$egg.fn.hideSubmitSpinner = function() {
	$egg(this).find(".buttons .button").show();
	$egg(this).find(".activity_indicator").hide();
	return $egg(this);
};
$egg.fn.showSubmitSpinner = function() {
	$egg(this).find(".buttons .button").hide();
	$egg(this).find(".activity_indicator").show();
	return $egg(this);
};
$egg.fn.idattr = function(prefix) {
	return $egg(this).attr('id').replace(prefix, '');
};
$egg.fn.setClass = function(classnames, flag) {
	return this.each(function() {
		if (flag) $egg(this).addClass(classnames);
		else $egg(this).removeClass(classnames);
	});
	
	
};
$egg.fn.setVisible = function(flag) {
	if (flag) $egg(this).show();
	else $egg(this).hide();
};
$egg.fn.ajaxReplace = function( url, params, callback ) {
	if ( typeof url !== "string" ) {
		return _load.call( this, url );

	} else if ( !this.length ) { return this; }

	var off = url.indexOf(" ");
	if ( off >= 0 ) {
		var selector = url.slice(off, url.length);
		url = url.slice(0, off);
	}
	var type = "GET";

	if ( params ) {
		if ( jQuery.isFunction( params ) ) {
			callback = params;
			params = null;
		} else if ( typeof params === "object" ) {
			params = jQuery.param( params, jQuery.ajaxSettings.traditional );
			type = "POST";
		}
	}
	var self = this;

	jQuery.ajax({
		url: url,
		type: type,
		dataType: "html",
		data: params,
		complete: function( res, status ) {
			if ( status === "success" || status === "notmodified" ) {
				self.replaceWith( selector ?
					// Create a dummy div to hold the results
					jQuery("<div />")
						.append(res.responseText.replace(rscript, ""))
						.find(selector) :
					res.responseText );
			}
			if ( callback ) {
				self.each( callback, [res.responseText, status, res] );
			}
		}
	});

	return this;
};
$egg.fn.ajaxAppend = function( url, params, callback ) {
	if ( typeof url !== "string" ) {
		return _load.call( this, url );

	} else if ( !this.length ) { return this; }

	var off = url.indexOf(" ");
	if ( off >= 0 ) {
		var selector = url.slice(off, url.length);
		url = url.slice(0, off);
	}
	var type = "GET";

	if ( params ) {
		if ( jQuery.isFunction( params ) ) {
			callback = params;
			params = null;
		} else if ( typeof params === "object" ) {
			params = jQuery.param( params, jQuery.ajaxSettings.traditional );
			type = "POST";
		}
	}
	var self = this;

	jQuery.ajax({
		url: url,
		type: type,
		dataType: "html",
		data: params,
		complete: function( res, status ) {
			if ( status === "success" || status === "notmodified" ) {
				self.append( selector ?
					// Create a dummy div to hold the results
					jQuery("<div />")
						.append(res.responseText.replace(rscript, ""))
						.find(selector) :
					res.responseText );
			}
			if ( callback ) {
				self.each( callback, [res.responseText, status, res] );
			}
		}
	});

	return this;
};

$egg.fn.lbText = function() {
	return $egg('<div></div>').html(this.html().gsub(/<br>/, '\n').gsub(/<br\/>/, '\n')).text();
};
$egg.fn.lbHtml = function(text) {
	this.html(text.gsub(/\n/, '<br>'));
};
$egg.extend({
	debug_frame: function(f, msg) {
		console.log("%@: %@,%@,%@,%@".fmt(msg, f.x, f.y, f.width, f.height));
	},
	pointInRect: function(loc, rect) {
		if (loc.x < rect.x || loc.x>rect.x+rect.width) return false;
		if (loc.y < rect.y || loc.y>rect.y+rect.height) return false;
		return true;
	}
});

var PLAIN_DIALOG_OPTIONS = {dialogClass:'plain', resizable:false, width:720, modal:true, position:['center',70]};


//$egg.listview = {
//};

$egg.fn.extend({
	listview_create: function(options) {
		var defaults = {
			collection: [],
			//rowHeight: 'auto',
			rowHeight: 100,
			updateItem: function(item, view) {
				console.log("dummy updateItemFunc");
			},
			template: function(item, index) {
				//return '<div class="egg-list-item"><img class="thumbnail"/><span class="label"></span></div>'; 
				return '<div class="frame egg-list-item" style="position:absolute; top:%@px;"><img src="/images/app/blank.gif" class="thumbnail"/></div>'.fmt(index*100);
			}
		};
		var opts = $egg.extend(defaults, options);
		
		this.listview_destroy();
		
		this.bind('scroll', this.listview_update.bind(this));
		
		return this.each(function() {
			var elem = $egg(this);
			
			var lv = elem.children(".egg-list-view");
			elem.addClass('egg-list-container');
			if (lv.length == 0)  lv = elem.append('<div class="egg-list-view"></div>');
			
			elem.data('rowHeight', opts.rowHeight);
			elem.data('template', opts.template);
			elem.data('updateItem', opts.updateItem);
			
			
		});
	},
	listview_destroy: function() {
		this.listview_clear();
		this.unbind('scroll');
		
		return this.each(function() {
			$egg(this).data('updateItem', null);
			$egg(this).data('rowHeight', null);
			$egg(this).data('template', null);
		});
	},
	listview_collection: function(value) {
		if (value !== undefined) {
			if (this.data('collection') !== value) {
				this.data('collection', value);
				this.listview_prepareAllItem();
				this.listview_update();
			}
		}
		return $egg(this).data('collection');
	},
	listview_clear: function() {
		var lv = this.find(".egg-list-view");
		// clear
		lv.find(".egg-list-item").unbind('click');
		lv.empty();
	},
	listview_prepareAllItem: function() {
		var lv = this.find(".egg-list-view");
		this.listview_clear();

		var collection = $egg(this).data('collection');
		if (!collection) return;
		
		var templateFunc = $egg(this).data('template');
		
		var len = collection.length;
		var rowHeight = $egg(this).data('rowHeight');
		if (rowHeight=='auto')
		{
			var last = collection.last();
			if (last) lv.height(last.screen.top + last.screen.height + 10);
		}
		else
		{
			lv.height(len * rowHeight);
			console.log("%@,%@ = %@".fmt(len, rowHeight, len * rowHeight));
		}
		for (var i=0;i<len;i++) {
			lv.append(templateFunc(collection[i], i));
		}
	},
	listview_update: function(forceUpdate) {
		var collection = this.data('collection');
		if (!collection || collection.length==0) return;

		var top = this.scrollTop();

		var height = this.height();
		if (this.is('body')) height = document.documentElement.clientHeight;

		var rowHeight = this.data('rowHeight');
		var updateItemFunc = this.data('updateItem');
		
		var end=0, start=0;
		
		if (rowHeight=='auto') 
		{
			end = this.listview_binarySearch({top:top, height:height});
			start = end;
			while (--start >= 0) if (collection[start].screen.top + collection[start].screen.height < top) break; 
			start++; // 안보이는 것이므로
		} else {
			end = Math.min(collection.length-1, Math.round((top+height)/rowHeight));
			start = Math.max(0,Math.floor(top/rowHeight));
		}		

		//console.log("%@ ~ %@".fmt(start,end));
		
		if (forceUpdate) 
		{
			if (rowHeight=="auto")
			{
				var last = collection.last();
	    		this.find(".egg-list-view").height(last.screen.top + last.screen.height + 10);
			}
			else
			{
				this.find(".egg-list-view").height(collection.length * rowHeight);
			}
		}
		var itemviews = this.find(".egg-list-view .egg-list-item");
		for (var i=start; i<=end; i++) updateItemFunc(collection[i], $egg(itemviews[i]), {start:start, end:end, index:i});
		

		/*
			$egg(itemviews[i])
			//.children(".thumbnail")
			.attr('src', collection[i].thumbnail);
		*/
	},
	listview_inScope: function(viewport, itemrect) {
        if (viewport.top > itemrect.top+itemrect.bottom) return -1; // page가 viewport 위에 있음
        if (viewport.top+viewport.height < itemrect.top) return 1; // page가 viewport 아래에 있음
        else return 0;
    },
    listview_binarySearch: function(viewport) {
		var collection = this.data('collection');
        var low = -1, high = collection.length, probe;
        while (high-low>1) {
            probe = parseInt((low + high) / 2, 10);
            
            if (this.listview_inScope(viewport, {top: collection[probe].screen.top, height:collection[probe].screen.height})>0) high = probe;
            else low = probe;
        }
        if (low==-1 || this.listview_inScope(viewport, {top: collection[low].screen.top, height:collection[low].screen.height}) != 0) return -1;
        else return low;
    }

});

$egg.fn.listview = function(options) {
	if (arguments.length==0) {
		return this.listview_create({});
	}
	if (arguments.length==1 && typeof arguments[0] === "object") {
		return this.listview_create(options);
	} else if (typeof arguments[0] === "string") {
		return this["listview_"+arguments[0]](arguments[1]);
	}
};


(function($,window,undefined) {
  	'$:nomunge'; // Used by YUI compressor.

  	var str_hashchange = 'hashchange', // Reused string.
    
    // Method / object references.
    doc = document,
    fake_onhashchange,
    special = $.event.special,
    
    // Does the browser support window.onhashchange? Note that IE8 running in
    // IE7 compatibility mode reports true for 'onhashchange' in window, even
    // though the event isn't supported, so also test document.documentMode.
    doc_mode = doc.documentMode,
    supports_onhashchange = 'on' + str_hashchange in window && (doc_mode===undefined || doc_mode>7);
  
  	// Get location.hash (or what you'd expect location.hash to be) sans any
  	// leading #. Thanks for making this necessary, Firefox!
  	function get_fragment( url ) {
    	url = url || location.href;
    	return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
  	};
  
  	$.fn[ str_hashchange ] = function( fn ) {
    	return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
  	};
  
  	$.fn[ str_hashchange ].delay = 50;
  	/*
  	$.fn[ str_hashchange ].domain = null;
  	$.fn[ str_hashchange ].src = null;
  	*/
  
  	special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
    	// Called only when the first 'hashchange' event is bound to window.
    	setup: function() {
      		// If window.onhashchange is supported natively, there's nothing to do..
      		if ( supports_onhashchange ) { return false; }
      		$( fake_onhashchange.start );
    	},
    	teardown: function() {
      		if ( supports_onhashchange ) { return false; }
      		$( fake_onhashchange.stop );
    	}
  	});
    fake_onhashchange = (function(){
    	var self = {},
      	timeout_id,
      
      	// Remember the initial hash so it doesn't get triggered immediately.
      	last_hash = get_fragment(),
      
      	fn_retval = function(val){ return val; },
      	history_set = fn_retval,
      	history_get = fn_retval;
    
    	self.start = function() { timeout_id || poll(); };
 
    	self.stop = function() {
      		timeout_id && clearTimeout( timeout_id );
      		timeout_id = undefined;
    	};
    
    	function poll() {
      		var hash = get_fragment(),
        	history_hash = history_get( last_hash );
      
      		if ( hash !== last_hash ) {
        		history_set( last_hash = hash, history_hash );
        
        		$(window).trigger( str_hashchange );
        
      		} else if ( history_hash !== last_hash ) {
        		location.href = location.href.replace( /#.*/, '' ) + history_hash;
      		}
      		timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
    	};
    
    	// vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv
    	$.browser.msie && !supports_onhashchange && (function(){
      		var iframe, iframe_src;

      		self.start = function(){
        		if ( !iframe ) {
          			iframe_src = $.fn[ str_hashchange ].src;
          			iframe_src = iframe_src && iframe_src + get_fragment();
          
          			iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
            		.one( 'load', function(){
              			iframe_src || history_set( get_fragment() );
              			poll();
            		})
            		.attr( 'src', iframe_src || 'javascript:0' )
            		.insertAfter( 'body' )[0].contentWindow;
    
          			doc.onpropertychange = function(){
            			try {
              				if ( event.propertyName === 'title' ) iframe.document.title = doc.title;
            			} catch(e) {}
          			};
        		}
      		};
      		self.stop = fn_retval;
    
      		history_get = function() {
        		return get_fragment( iframe.location.href );
      		};
      		history_set = function( hash, history_hash ) {
        		var iframe_doc = iframe.document,
          		domain = $.fn[ str_hashchange ].domain;
        
        		if ( hash !== history_hash ) {
          			iframe_doc.title = doc.title;
          			iframe_doc.open();
          			domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
          			iframe_doc.close();
          			iframe.location.hash = hash;
        		}
      		};
    	})();
    	// ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^
    	return self;
  	})();
})(jQuery,this);
