
var jqWindowIndex = 0;
var lastFocusWindow = null;
var miniWindowStorage = new Array();
var minimizedHeight = 200;
var minimizedFont = 10;
$.window = function(options) {
var instance = new Window(null, options);
instance.init();
$.window.focus(instance); 
return instance;
};
$.fn.window = function(options) {
var caller = $(this);
var instance = new Window(caller, options);
instance.init();
$.window.focus(instance); 
return instance;
}
$.window.focus = function(windowIntance) {
if( lastFocusWindow != null ) {
lastFocusWindow.releaseFocus();
}
lastFocusWindow = windowIntance;
lastFocusWindow.setFocus();
};
$.window.getVersion = function() {
var version = "3.03";
return version;
};
function Window(caller, options) {
var ICON_WH = 16;
var ICON_MARGIN = 4;
var ICON_OFFSET = ICON_WH + ICON_MARGIN;
var me = this;
me.windowId = "window_" + (jqWindowIndex++);

var absolute = true;
var resizing = false;
var minimized = false;
var maximized = false;
var redirectCheck = false;
var pos = new Object(); 
var wh = new Object(); 
var orgPos = new Object(); 
var orgWh = new Object(); 
var targetCssStyle = {}; 
var funcBarWidth = 0; 

var container = null;
var header = null;
var frame = null;
var footer = null;
var options = $.extend({
title: "", 
url: null, 
content: "", 
x: -1, 
y: -1, 
z: 2000, 
width: 500, 
height: 500, 
minWidth: 200, 
minHeight: 150, 
maxWidth: 800, 
maxHeight: 600, 
closable: true, 
minimizable: true, 
maximizable: true, 
bookmarkable: false, 
draggable: true, 
resizable: true, 
scrollable: true, 
checkBoundary: false, 
custBtns: null, 
onOpen: null, 
onShow: null, 
onClose: null, 
onIframeStart: null, 
onIframeEnd: null, 
iframeRedirectCheckMsg: null, 
animationSpeed: 400, 
showLog: false 
}, options);

me.init = function() {

var realCaller = caller != null? caller:$("body");
realCaller.append("<div id='"+me.windowId+"' class='window_panel'></div>");
container = realCaller.children("div#"+me.windowId);

if( options.onOpen != null && $.isFunction(options.onOpen) ) {
options.onOpen(container);
}
wh.w = options.width;
wh.h = options.height;
container.width(options.width);
container.height(options.height);
container.css("position", absolute ? 'absolute' : 'fixed'); 
container.css("z-index", options.z);

if( options.x >= 0 || options.y >= 0 ) {
if( options.x >= 0 ) {
var pLeft = 0;
if( caller != null ) {
pLeft = options.x + caller.offset().left;
} else {
pLeft = options.x + jQuery(window).scrollLeft();
}
container.css("left", pLeft);
} else { 
me.alignHorizontalCenter();
}

if( options.y >= 0 ) {
var pTop = 0;
if( caller != null ) {
pTop = options.y + caller.offset().top;
} else {
pTop = options.y + jQuery(window).scrollTop();
}
container.css("top", pTop);
} else { 
me.alignVerticalCenter();
}
} else {
me.alignCenter();
}

var headerHtml = "<div class='window_header window_header_normal'>"+
"<div class='window_title_text'>"+options.title+"</div>"+
"<div class='window_function_bar'></div>"+
"</div>";
container.append(headerHtml);
header = container.children("div.window_header");
var headerFuncPanel = header.children("div.window_function_bar");

if( options.closable ) {
headerFuncPanel.append( "<div title='close window' class='closeImg window_icon_button no-draggable'></div>" );
headerFuncPanel.children(".closeImg").click(function() {
redirectCheck = false;

if( options.onClose != null && $.isFunction(options.onClose) ) {
options.onClose(container);
}
me.destroy();
});
funcBarWidth += ICON_OFFSET;
}

if( options.maximizable ) {
headerFuncPanel.append( "<div title='maximize window' class='maximizeImg window_icon_button no-draggable'></div>" );
headerFuncPanel.append( "<div title='cascade window' class='cascadeImg window_icon_button no-draggable' style='display:none;'></div>" );
headerFuncPanel.children(".maximizeImg").click(function() {
me.maximize();
});
headerFuncPanel.children(".cascadeImg").click(function() {
me.restore(true);
});
funcBarWidth += ICON_OFFSET;
}

if( options.minimizable ) {
headerFuncPanel.append( "<div title='minimize window' class='minimizeImg window_icon_button no-draggable'></div>" );
headerFuncPanel.children(".minimizeImg").click(function() {
me.minimize();
});
funcBarWidth += ICON_OFFSET;
}

if( options.bookmarkable && options.url != null ) {
headerFuncPanel.append( "<div title='bookmark this' class='bookmarkImg window_icon_button no-draggable'></div>" );
headerFuncPanel.children(".bookmarkImg").click(function() {
doBookmark(options.title, options.url);
});
funcBarWidth += ICON_OFFSET;
}

addCustomizedButtns(headerFuncPanel);

adjustHeaderTextPanelWidth();
headerFuncPanel.width( funcBarWidth );

var frameHeight = getFrameHeight(wh.h);
if( options.url != null ) {

if( options.onIframeStart != null && $.isFunction(options.onIframeStart) ) {
log("start connecting iframe: "+options.url);
options.onIframeStart(options.url);
}

if( options.iframeRedirectCheckMsg ) {
redirectCheck = true;
window.onbeforeunload = function() {
if( redirectCheck ) {
var msg = options.iframeRedirectCheckMsg.replace("{url}", options.url);
return msg;
}
}
}

container.append("<div class='frame_loading'>Loading...</div>");
var loading = container.children(".frame_loading");
loading.css("marginLeft",	'-' + (loading.outerWidth() / 2) - 20 + 'px');
loading.click(function() {
loading.remove();
});

var scrollingHtml = options.scrollable? "yes":"no";
container.append("<iframe style='display:none;' class='window_frame no-draggable' scrolling='"+scrollingHtml+"' src='"+options.url+"' width='100%' height='"+frameHeight+"px' frameborder='0'></iframe>");
frame = container.children(".window_frame");

frame.ready(function() {
frame.show();
});
frame.load(function() {
redirectCheck = false;
loading.remove();
log("load iframe finished: "+options.url);
if( options.onIframeEnd != null && $.isFunction(options.onIframeEnd) ) {
options.onIframeEnd(options.url);
}
});
} else {
container.append("<div class='window_frame no-draggable' style='width:100%; height:"+frameHeight+"px;'></div>");
frame = container.children(".window_frame");
frame.append(options.content);
var scrollingCss = options.scrollable? "auto":"hidden";
frame.css("overflow", scrollingCss);
}

container.append("<div class='window_footer no-draggable'></div>");
footer = container.children("div.window_footer");

container.mousedown(function() {
$.window.focus(me);
});

if( options.draggable ) {
container.draggable({
cancel: '.no-draggable',
start: function() {
log( "drag start" );
if( minimized || maximized ) { 
container.css("position", "fixed");
container.css(targetCssStyle);
}
hideContent();
},
stop: function() {
log( "drag stop" );
if( minimized || maximized ) { 
container.css("position", "fixed");
container.css(targetCssStyle);
}
showContent();
}
});

if( options.checkBoundary ) {
container.draggable('option', 'containment', 'parent');
}
}

if( options.resizable ) {
container.resizable({
alsoResize: frame,
start: function() { 
log( "resize start" );
if( minimized || maximized ) { 
container.css("position", "fixed");
container.css(targetCssStyle);
}
hideContent();
},
stop: function() {
log( "resize stop" );
if( minimized || maximized ) { 
container.css("position", "fixed");
container.css(targetCssStyle);
}
adjustHeaderTextPanelWidth();
showContent();
}
});

if( options.maxWidth >= 0 ) {
container.resizable('option', 'maxWidth', options.maxWidth);
}
if( options.maxHeight >= 0 ) {
container.resizable('option', 'maxHeight', options.maxHeight);
}
if( options.minWidth >= 0 ) {
container.resizable('option', 'minWidth', options.minWidth);
}
if( options.minHeight >= 0 ) {
container.resizable('option', 'minHeight', options.minHeight);
}
}

$(window).resize(function() {
if( maximized ) {
if( minimized ) {

var screenWH = getBrowserScreenWH();
orgWh.w = screenWH.width;
orgWh.h = screenWH.height;
} else {
me.maximize(true, true);
}
}
});

testing();

if( options.onShow != null && $.isFunction(options.onShow) ) {
options.onShow(container);
}
};
me.setFocus = function() {
container.css("z-index", options.z+1);
};
me.releaseFocus = function() {
container.css("z-index", options.z);
};
me.getContainer = function() {
return container;
};
me.getHeader = function() {
return header;
};
me.getFrame = function() {
return frame;
};
me.getFooter = function() {
return footer;
};
me.alignCenter = function() {
if( caller != null ) {
var pLeft = (caller.width() - container.width())/2 + caller.offset().left;
var pTop = (caller.height() - container.height())/2 + caller.offset().top;
container.css({
left: pLeft,
top: pTop
});
} else {
container.css({
left: '50%',
top: '50%'
}).css({
marginLeft:	'-' + (container.outerWidth() / 2) + 'px',
marginTop:	'-' + (container.outerHeight() / 2) + 'px'
});
if (absolute) {
container.css({
marginLeft:	parseInt(container.css('marginLeft'), 10) + jQuery(window).scrollLeft(),
marginTop:	parseInt(container.css('marginTop'), 10) + jQuery(window).scrollTop()
});
}
};
}
me.alignHorizontalCenter = function() {
if( caller != null ) {
var pLeft = (caller.width() - container.width())/2 + caller.offset().left;
container.css({
left: pLeft
});
} else {
container.css({
left: '50%'
}).css({
marginLeft:	'-' + (container.outerWidth() / 2) + 'px'
});
if (absolute) {
container.css({
marginLeft:	parseInt(container.css('marginLeft'), 10) + jQuery(window).scrollLeft()
});
}
}
};
me.alignVerticalCenter = function() {
if( caller != null ) {
var pTop = (caller.height() - container.height())/2 + caller.offset().top;
container.css({
top: pTop
});
} else {
container.css({
top: '50%'
}).css({
marginTop:	'-' + (container.outerHeight() / 2) + 'px'
});
if (absolute) {
container.css({
marginTop:	parseInt(container.css('marginTop'), 10) + jQuery(window).scrollTop()
});
}
}
};
me.maximize = function(bImmediately, bNoSaveDisplay) {
maximized = true;
container.draggable( 'disable' );
container.resizable( 'disable' );

if( bNoSaveDisplay != true ) {
pos.left = container.css("left");
pos.top = container.css("top");
pos.marginLeft = container.css("marginLeft");
pos.marginTop = container.css("marginTop");
wh.w = container.width();
wh.h = container.height();
}
var screenWH = getBrowserScreenWH();
targetCssStyle = {
left: 0,
top: 0,
marginLeft: 0,
marginTop: 0,
width: screenWH.width,
height: screenWH.height,
opacity: 1
};
transferToFixed(); 
if( bImmediately ) {
container.css(targetCssStyle);
adjustHeaderTextPanelWidth();
adjustFrameWH();

var headerFuncPanel = header.children("div.window_function_bar");
headerFuncPanel.children(".maximizeImg").hide();
headerFuncPanel.children(".cascadeImg").show();
} else {
frame.hide();
footer.hide();
container.animate(targetCssStyle, options.animationSpeed, 'swing', function() {
frame.show();
footer.show();
adjustHeaderTextPanelWidth();
adjustFrameWH();

var headerFuncPanel = header.children("div.window_function_bar");
headerFuncPanel.children(".maximizeImg").hide();
headerFuncPanel.children(".cascadeImg").show();
});
}



};
me.minimize = function() {
minimized = true;
frame.hide();
footer.hide();
container.draggable( 'disable' );
container.resizable( 'disable' );

orgPos.left = container.css("left");
orgPos.top = container.css("top");
orgPos.marginLeft = container.css("marginLeft");
orgPos.marginTop = container.css("marginTop");
orgWh.w = container.width();
orgWh.h = container.height();
var top = ( miniWindowStorage.length * minimizedHeight) + "px";
targetCssStyle = {
left: 0,
top: top,
marginLeft: 0,
marginTop: 0,
width: 24,
height: minimizedHeight,
opacity: 0.5
};
if( maximized == false ) { 
transferToFixed();
}
container.animate(targetCssStyle, options.animationSpeed, 'swing', function() {
header.children("div.window_title_text").width( "100%" );
transformTitleText();

header.click(function() {
me.restore();
});
});
container.mouseover(function() {
$(this).css("opacity", "1");
});
container.mouseout(function() {
$(this).css("opacity", "0.5");
});
header.attr("title", options.title);
header.removeClass('window_header_normal');
header.addClass('window_header_minimize');
header.children(".window_function_bar").hide();

miniWindowStorage[miniWindowStorage.length] = me;
};
me.restore = function(fromCascade) {
var rpos = null;
var rwh = null;
if( fromCascade ) {
maximized = false;
rpos = pos;
rwh = wh;
frame.hide();
footer.hide();
} else {
minimized = false;
rpos = orgPos;
rwh = orgWh;
}
header.removeAttr("title");
header.removeClass('window_header_minimize');
header.addClass('window_header_normal');
header.children(".window_function_bar").show();
container.unbind("mouseover");
container.unbind("mouseout");
restoreTitleText();
if( minimized == false && maximized == false ) { 
transferToAbsolute();
}
targetCssStyle = {
left: rpos.left,
top: rpos.top,
marginLeft: rpos.marginLeft,
marginTop: rpos.marginTop,
width: rwh.w,
height: rwh.h,
opacity: 1
};
container.animate(targetCssStyle, options.animationSpeed, 'swing', function() {
frame.show();
footer.show();
header.unbind('click');
adjustHeaderTextPanelWidth();
adjustFrameWH();

var headerFuncPanel = header.children("div.window_function_bar");
if( maximized ) {
headerFuncPanel.children(".maximizeImg").hide();
headerFuncPanel.children(".cascadeImg").show();
} else {
container.draggable( 'enable' );
container.resizable( 'enable' );
headerFuncPanel.children(".maximizeImg").show();
headerFuncPanel.children(".cascadeImg").hide();
}
});

adjustPosition();
};
me.destroy = function() {
container.remove();
};
me.getTargetCssStyle = function() {
return targetCssStyle;
};

var transferToFixed = function() {
var currPos = container.offset();
var scrollXY = getBrowserScrollXY();
container.css({
position: "fixed",
left: currPos.left - scrollXY[0],
top: currPos.top - scrollXY[1],
marginLeft: 0,
marginTop: 0
});
};
var transferToAbsolute = function() {
var currPos = container.offset();
container.css({
position: "absolute",
left: currPos.left,
top: currPos.top
});
};
var adjustPosition = function() {
var doAdjust = false;
for( var i=0; i<miniWindowStorage.length; i++ ) {
var wnd = miniWindowStorage[i];
if( wnd.windowId == me.windowId ) {
miniWindowStorage.splice(i--,1); 
doAdjust = true;
continue;
}
if( doAdjust ) {
var position = wnd.getContainer().position();

var top = i * minimizedHeight;
wnd.getContainer().animate({
top: top
}, options.animationSpeed);

wnd.getTargetCssStyle().top = top;
}
}
};
var addCustomizedButtns = function(headerFuncPanel) {
if( options.custBtns != null && typeof options.custBtns == 'object' ) {
for( var i=0; i<options.custBtns.length; i++ ) {
var btnData = options.custBtns[i];
if( btnData != null && typeof btnData == 'object' ) {
if( btnData.id != null && btnData.image != null && btnData.callback != null ) { 
var id = btnData.id != null? btnData.id:"";
var clazz = btnData.clazz != null? btnData.clazz:"";
var title = btnData.title != null? btnData.title:"";
var style = btnData.style != null? btnData.style:"";
var image = btnData.image != null? btnData.image:"";
var callback = btnData.callback != null? btnData.callback:"";
headerFuncPanel.append( "<img id='"+id+"' src='"+image+"' title='"+title+"' class='"+clazz+" window_icon_button no-draggable' style='"+style+"'/>" );
var btn = headerFuncPanel.children("img[id="+id+"]");
btn.get(0).clickCb = callback;
if( callback != null && $.isFunction(callback)) {
btn.click(function() {
this.clickCb(this);
});
}
} else { 
var btn = null;
if( btnData.get ) {
btn = btnData;
} else {
var btn = $(btnData);
}
headerFuncPanel.append( btn );
btn.show();
}
}
funcBarWidth += ICON_OFFSET;
}
}
};
var adjustHeaderTextPanelWidth = function() {
header.children("div.window_title_text").width( header.width() - funcBarWidth - 10 );
};
var adjustFrameWH = function() {
var width = container.width();
var height = container.height();
var frameHeight = getFrameHeight(height);
frame.width( width );
frame.height( frameHeight );
};
var getBrowserScreenWH = function() {
var width = document.documentElement.clientWidth;
var height = document.documentElement.clientHeight;
return {width:width, height:height};
};
function getBrowserScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {

scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {

scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {

scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return [ scrOfX, scrOfY ];
}
var doBookmark = function(title, url) {
var ua = navigator.userAgent.toLowerCase();
if ( $.browser.mozilla && window.sidebar ) { 
window.sidebar.addPanel(title, url, "");
} else if( $.browser.msie && window.external ) { 
window.external.AddFavorite( url, title);
} else if( ua.indexOf("chrome") >= 0 ) { 
alert("Sorry! Chrome doesn't support bookmark function currently.");

} else if($.browser.safari || ua.indexOf("safari") >= 0 ) { 
alert("Sorry! Safari doesn't support bookmark function currently.");

} else if($.browser.opera || ua.indexOf("opera") >= 0 ) { 
alert("Sorry! Opera doesn't support bookmark function currently.");

}
};
var hideContent = function() {
log("hideContent");
if( minimized == false ) {
frame.hide();
container.css("opacity", "0.5");
}
};
var showContent = function() {
log("showContent");
if( minimized == false ) {
frame.show();
container.css("opacity", "1");
}
};
var getFrameHeight = function(windowHeight) {
return windowHeight - 20 - 16 - 4; 
};

var transformTitleText = function() {
var textBlock = header.children("div.window_title_text");
var text = textBlock.text();
var buf = "";
var limitHeight = minimizedHeight - 7 - minimizedFont; 
for( var i=0; i<text.length; i++ ) {
var c = text.charAt(i);
if( c == "-" || c == "_" ) {
c = "<div style='height:2px; line-height:2px;'>&nbsp;</div>";
}
if( c == " " ) {
c = "<div style='height:2px; line-height:2px;'>&nbsp;</div>";
buf += c;
} else {
buf += c+"<br>";
}
textBlock.html(buf);

if( textBlock.outerHeight() + minimizedFont > limitHeight ) {
buf += ":";
textBlock.html(buf);
break;
}
}
};
var restoreTitleText = function() {
var textBlock = header.children("div.window_title_text");
textBlock.text(options.title);
};
var testing = function() {
};
var log = function(msg) {
if(options != null && options.showLog && window.console != null) {
console.log(msg);
}
};
}
