/*
 * jQuery Tools 1.2.5 - The missing UI library for the Web
 * 
 * [tooltip, tooltip.slide, scrollable, scrollable.autoscroll]
 * 
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 * 
 * http://flowplayer.org/tools/
 * 
 * File generated: Fri Sep 24 12:03:07 GMT 2010
 */
(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,d=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];d+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))h-=f(window).scrollTop();var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")d-=a/2;if(i=="left")d-=a;return{top:h,left:d}}function u(a,b){var c=this,h=a.add(c),d,i=0,j=
0,m=a.attr("title"),q=a.attr("data-tooltip"),r=o[b.effect],l,s=a.is(":input"),v=s&&a.is(":checkbox, :radio, select, :button, :submit"),t=a.attr("type"),k=b.events[t]||b.events[s?v?"widget":"input":"def"];if(!r)throw'Nonexistent effect "'+b.effect+'"';k=k.split(/,\s*/);if(k.length!=2)throw"Tooltip: bad events configuration for "+t;a.bind(k[0],function(e){clearTimeout(i);if(b.predelay)j=setTimeout(function(){c.show(e)},b.predelay);else c.show(e)}).bind(k[1],function(e){clearTimeout(j);if(b.delay)i=
setTimeout(function(){c.hide(e)},b.delay);else c.hide(e)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c,{show:function(e){if(!d){if(q)d=f(q);else if(b.tip)d=f(b.tip).eq(0);else if(m)d=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide().append(m);else{d=a.next();d.length||(d=a.parent().next())}if(!d.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;d.stop(true,true);var g=p(a,d,b);b.tip&&d.html(a.data("title"));e=e||f.Event();e.type="onBeforeShow";
h.trigger(e,[g]);if(e.isDefaultPrevented())return c;g=p(a,d,b);d.css({position:"absolute",top:g.top,left:g.left});l=true;r[0].call(c,function(){e.type="onShow";l="full";h.trigger(e)});g=b.events.tooltip.split(/,\s*/);if(!d.data("__set")){d.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&d.bind(g[1],function(n){n.relatedTarget!=a[0]&&a.trigger(k[1].split(" ")[0])});d.data("__set",true)}return c},hide:function(e){if(!d||!c.isShown())return c;
e=e||f.Event();e.type="onBeforeHide";h.trigger(e);if(!e.isDefaultPrevented()){l=false;o[b.effect][1].call(c,function(){e.type="onHide";h.trigger(e)});return c}},isShown:function(e){return e?l=="full":l},getConf:function(){return b},getTip:function(){return d},getTrigger:function(){return a}});f.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(e,g){f.isFunction(b[g])&&f(c).bind(g,b[g]);c[g]=function(n){n&&f(c).bind(g,n);return c}})}f.tools=f.tools||{version:"1.2.5"};f.tools.tooltip=
{conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:false,cancelDefault:true,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,b,c){o[a]=[b,c]}};var o={toggle:[function(a){var b=this.getConf(),c=this.getTip();b=b.opacity;b<1&&c.css({opacity:b});c.show();a.call()},function(a){this.getTip().hide();
a.call()}],fade:[function(a){var b=this.getConf();this.getTip().fadeTo(b.fadeInSpeed,b.opacity,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};f.fn.tooltip=function(a){var b=this.data("tooltip");if(b)return b;a=f.extend(true,{},f.tools.tooltip.conf,a);if(typeof a.position=="string")a.position=a.position.split(/,?\s/);this.each(function(){b=new u(f(this),a);f(this).data("tooltip",b)});return a.api?b:this}})(jQuery);
(function(d){var i=d.tools.tooltip;d.extend(i.conf,{direction:"up",bounce:false,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!d.browser.msie});var e={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};i.addEffect("slide",function(g){var a=this.getConf(),f=this.getTip(),b=a.slideFade?{opacity:a.opacity}:{},c=e[a.direction]||e.up;b[c[1]]=c[0]+"="+a.slideOffset;a.slideFade&&f.css({opacity:0});f.show().animate(b,a.slideInSpeed,g)},function(g){var a=this.getConf(),f=a.slideOffset,
b=a.slideFade?{opacity:0}:{},c=e[a.direction]||e.up,h=""+c[0];if(a.bounce)h=h=="+"?"-":"+";b[c[1]]=h+"="+f;this.getTip().animate(b,a.slideOutSpeed,function(){d(this).hide();g.call()})})})(jQuery);
(function(e){function p(f,c){var b=e(c);return b.length<2?b:f.parent().find(c)}function u(f,c){var b=this,n=f.add(b),g=f.children(),l=0,j=c.vertical;k||(k=b);if(g.length>1)g=e(c.items,f);e.extend(b,{getConf:function(){return c},getIndex:function(){return l},getSize:function(){return b.getItems().size()},getNaviButtons:function(){return o.add(q)},getRoot:function(){return f},getItemWrap:function(){return g},getItems:function(){return g.children(c.item).not("."+c.clonedClass)},move:function(a,d){return b.seekTo(l+
a,d)},next:function(a){return b.move(1,a)},prev:function(a){return b.move(-1,a)},begin:function(a){return b.seekTo(0,a)},end:function(a){return b.seekTo(b.getSize()-1,a)},focus:function(){return k=b},addItem:function(a){a=e(a);if(c.circular){g.children("."+c.clonedClass+":last").before(a);g.children("."+c.clonedClass+":first").replaceWith(a.clone().addClass(c.clonedClass))}else g.append(a);n.trigger("onAddItem",[a]);return b},seekTo:function(a,d,h){a.jquery||(a*=1);if(c.circular&&a===0&&l==-1&&d!==
0)return b;if(!c.circular&&a<0||a>b.getSize()||a<-1)return b;var i=a;if(a.jquery)a=b.getItems().index(a);else i=b.getItems().eq(a);var r=e.Event("onBeforeSeek");if(!h){n.trigger(r,[a,d]);if(r.isDefaultPrevented()||!i.length)return b}i=j?{top:-i.position().top}:{left:-i.position().left};l=a;k=b;if(d===undefined)d=c.speed;g.animate(i,d,c.easing,h||function(){n.trigger("onSeek",[a])});return b}});e.each(["onBeforeSeek","onSeek","onAddItem"],function(a,d){e.isFunction(c[d])&&e(b).bind(d,c[d]);b[d]=function(h){h&&
e(b).bind(d,h);return b}});if(c.circular){var s=b.getItems().slice(-1).clone().prependTo(g),t=b.getItems().eq(1).clone().appendTo(g);s.add(t).addClass(c.clonedClass);b.onBeforeSeek(function(a,d,h){if(!a.isDefaultPrevented())if(d==-1){b.seekTo(s,h,function(){b.end(0)});return a.preventDefault()}else d==b.getSize()&&b.seekTo(t,h,function(){b.begin(0)})});b.seekTo(0,0,function(){})}var o=p(f,c.prev).click(function(){b.prev()}),q=p(f,c.next).click(function(){b.next()});if(!c.circular&&b.getSize()>1){b.onBeforeSeek(function(a,
d){setTimeout(function(){if(!a.isDefaultPrevented()){o.toggleClass(c.disabledClass,d<=0);q.toggleClass(c.disabledClass,d>=b.getSize()-1)}},1)});c.initialIndex||o.addClass(c.disabledClass)}c.mousewheel&&e.fn.mousewheel&&f.mousewheel(function(a,d){if(c.mousewheel){b.move(d<0?1:-1,c.wheelSpeed||50);return false}});if(c.touch){var m={};g[0].ontouchstart=function(a){a=a.touches[0];m.x=a.clientX;m.y=a.clientY};g[0].ontouchmove=function(a){if(a.touches.length==1&&!g.is(":animated")){var d=a.touches[0],h=
m.x-d.clientX;d=m.y-d.clientY;b[j&&d>0||!j&&h>0?"next":"prev"]();a.preventDefault()}}}c.keyboard&&e(document).bind("keydown.scrollable",function(a){if(!(!c.keyboard||a.altKey||a.ctrlKey||e(a.target).is(":input")))if(!(c.keyboard!="static"&&k!=b)){var d=a.keyCode;if(j&&(d==38||d==40)){b.move(d==38?-1:1);return a.preventDefault()}if(!j&&(d==37||d==39)){b.move(d==37?-1:1);return a.preventDefault()}}});c.initialIndex&&b.seekTo(c.initialIndex,0,function(){})}e.tools=e.tools||{version:"1.2.5"};e.tools.scrollable=
{conf:{activeClass:"active",circular:false,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:true,mousewheel:false,next:".next",prev:".prev",speed:400,vertical:false,touch:true,wheelSpeed:0}};var k;e.fn.scrollable=function(f){var c=this.data("scrollable");if(c)return c;f=e.extend({},e.tools.scrollable.conf,f);this.each(function(){c=new u(e(this),f);e(this).data("scrollable",c)});return f.api?c:this}})(jQuery);
(function(b){var f=b.tools.scrollable;f.autoscroll={conf:{autoplay:true,interval:3E3,autopause:true}};b.fn.autoscroll=function(c){if(typeof c=="number")c={interval:c};var d=b.extend({},f.autoscroll.conf,c),g;this.each(function(){var a=b(this).data("scrollable");if(a)g=a;var e,h=true;a.play=function(){if(!e){h=false;e=setInterval(function(){a.next()},d.interval)}};a.pause=function(){e=clearInterval(e)};a.stop=function(){a.pause();h=true};d.autopause&&a.getRoot().add(a.getNaviButtons()).hover(a.pause,
a.play);d.autoplay&&a.play()});return d.api?g:this}})(jQuery);
/*!
 * jQuery Templates Plugin
 * http://github.com/jquery/jquery-tmpl
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */
(function( jQuery, undefined ){
	var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
		newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];

	function newTmplItem( options, parentItem, fn, data ) {
		// Returns a template item data structure for a new rendered instance of a template (a 'template item').
		// The content field is a hierarchical array of strings and nested items (to be
		// removed and replaced by nodes field of dom elements, once inserted in DOM).
		var newItem = {
			data: data || (parentItem ? parentItem.data : {}),
			_wrap: parentItem ? parentItem._wrap : null,
			tmpl: null,
			parent: parentItem || null,
			nodes: [],
			calls: tiCalls,
			nest: tiNest,
			wrap: tiWrap,
			html: tiHtml,
			update: tiUpdate
		};
		if ( options ) {
			jQuery.extend( newItem, options, { nodes: [], parent: parentItem } );
		}
		if ( fn ) {
			// Build the hierarchical content to be used during insertion into DOM
			newItem.tmpl = fn;
			newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
			newItem.key = ++itemKey;
			// Keep track of new template item, until it is stored as jQuery Data on DOM element
			(stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
		}
		return newItem;
	}

	// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
	jQuery.each({
		appendTo: "append",
		prependTo: "prepend",
		insertBefore: "before",
		insertAfter: "after",
		replaceAll: "replaceWith"
	}, function( name, original ) {
		jQuery.fn[ name ] = function( selector ) {
			var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
				parent = this.length === 1 && this[0].parentNode;

			appendToTmplItems = newTmplItems || {};
			if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
				insert[ original ]( this[0] );
				ret = this;
			} else {
				for ( i = 0, l = insert.length; i < l; i++ ) {
					cloneIndex = i;
					elems = (i > 0 ? this.clone(true) : this).get();
					jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
					ret = ret.concat( elems );
				}
				cloneIndex = 0;
				ret = this.pushStack( ret, name, insert.selector );
			}
			tmplItems = appendToTmplItems;
			appendToTmplItems = null;
			jQuery.tmpl.complete( tmplItems );
			return ret;
		};
	});

	jQuery.fn.extend({
		// Use first wrapped element as template markup.
		// Return wrapped set of template items, obtained by rendering template against data.
		tmpl: function( data, options, parentItem ) {
			return jQuery.tmpl( this[0], data, options, parentItem );
		},

		// Find which rendered template item the first wrapped DOM element belongs to
		tmplItem: function() {
			return jQuery.tmplItem( this[0] );
		},

		// Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
		template: function( name ) {
			return jQuery.template( name, this[0] );
		},

		domManip: function( args, table, callback, options ) {
			// This appears to be a bug in the appendTo, etc. implementation
			// it should be doing .call() instead of .apply(). See #6227
			if ( args[0] && args[0].nodeType ) {
				var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem;
				while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {}
				if ( argsLength > 1 ) {
					dmArgs[0] = [jQuery.makeArray( args )];
				}
				if ( tmplItem && cloneIndex ) {
					dmArgs[2] = function( fragClone ) {
						// Handler called by oldManip when rendered template has been inserted into DOM.
						jQuery.tmpl.afterManip( this, fragClone, callback );
					};
				}
				oldManip.apply( this, dmArgs );
			} else {
				oldManip.apply( this, arguments );
			}
			cloneIndex = 0;
			if ( !appendToTmplItems ) {
				jQuery.tmpl.complete( newTmplItems );
			}
			return this;
		}
	});

	jQuery.extend({
		// Return wrapped set of template items, obtained by rendering template against data.
		tmpl: function( tmpl, data, options, parentItem ) {
			var ret, topLevel = !parentItem;
			if ( topLevel ) {
				// This is a top-level tmpl call (not from a nested template using {{tmpl}})
				parentItem = topTmplItem;
				tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
				wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
			} else if ( !tmpl ) {
				// The template item is already associated with DOM - this is a refresh.
				// Re-evaluate rendered template for the parentItem
				tmpl = parentItem.tmpl;
				newTmplItems[parentItem.key] = parentItem;
				parentItem.nodes = [];
				if ( parentItem.wrapped ) {
					updateWrapped( parentItem, parentItem.wrapped );
				}
				// Rebuild, without creating a new template item
				return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
			}
			if ( !tmpl ) {
				return []; // Could throw...
			}
			if ( typeof data === "function" ) {
				data = data.call( parentItem || {} );
			}
			if ( options && options.wrapped ) {
				updateWrapped( options, options.wrapped );
			}
			ret = jQuery.isArray( data ) ? 
				jQuery.map( data, function( dataItem ) {
					return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
				}) :
				[ newTmplItem( options, parentItem, tmpl, data ) ];
			return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
		},

		// Return rendered template item for an element.
		tmplItem: function( elem ) {
			var tmplItem;
			if ( elem instanceof jQuery ) {
				elem = elem[0];
			}
			while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
			return tmplItem || topTmplItem;
		},

		// Set:
		// Use $.template( name, tmpl ) to cache a named template,
		// where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
		// Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.

		// Get:
		// Use $.template( name ) to access a cached template.
		// Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
		// will return the compiled template, without adding a name reference.
		// If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
		// to $.template( null, templateString )
		template: function( name, tmpl ) {
			if (tmpl) {
				// Compile template and associate with name
				if ( typeof tmpl === "string" ) {
					// This is an HTML string being passed directly in.
					tmpl = buildTmplFn( tmpl )
				} else if ( tmpl instanceof jQuery ) {
					tmpl = tmpl[0] || {};
				}
				if ( tmpl.nodeType ) {
					// If this is a template block, use cached copy, or generate tmpl function and cache.
					tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
				}
				return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
			}
			// Return named compiled template
			return name ? (typeof name !== "string" ? jQuery.template( null, name ): 
				(jQuery.template[name] || 
					// If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 
					jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 
		},

		encode: function( text ) {
			// Do HTML encoding replacing < > & and ' and " by corresponding entities.
			return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
		}
	});

	jQuery.extend( jQuery.tmpl, {
		tag: {
			"tmpl": {
				_default: { $2: "null" },
				open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
				// tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
				// This means that {{tmpl foo}} treats foo as a template (which IS a function). 
				// Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
			},
			"wrap": {
				_default: { $2: "null" },
				open: "$item.calls(_,$1,$2);_=[];",
				close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
			},
			"each": {
				_default: { $2: "$index, $value" },
				open: "if($notnull_1){$.each($1a,function($2){with(this){",
				close: "}});}"
			},
			"if": {
				open: "if(($notnull_1) && $1a){",
				close: "}"
			},
			"else": {
				_default: { $1: "true" },
				open: "}else if(($notnull_1) && $1a){"
			},
			"html": {
				// Unecoded expression evaluation. 
				open: "if($notnull_1){_.push($1a);}"
			},
			"=": {
				// Encoded expression evaluation. Abbreviated form is ${}.
				_default: { $1: "$data" },
				open: "if($notnull_1){_.push($.encode($1a));}"
			},
			"!": {
				// Comment tag. Skipped by parser
				open: ""
			}
		},

		// This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
		complete: function( items ) {
			newTmplItems = {};
		},

		// Call this from code which overrides domManip, or equivalent
		// Manage cloning/storing template items etc.
		afterManip: function afterManip( elem, fragClone, callback ) {
			// Provides cloned fragment ready for fixup prior to and after insertion into DOM
			var content = fragClone.nodeType === 11 ?
				jQuery.makeArray(fragClone.childNodes) :
				fragClone.nodeType === 1 ? [fragClone] : [];

			// Return fragment to original caller (e.g. append) for DOM insertion
			callback.call( elem, fragClone );

			// Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
			storeTmplItems( content );
			cloneIndex++;
		}
	});

	//========================== Private helper functions, used by code above ==========================

	function build( tmplItem, nested, content ) {
		// Convert hierarchical content into flat string array 
		// and finally return array of fragments ready for DOM insertion
		var frag, ret = content ? jQuery.map( content, function( item ) {
			return (typeof item === "string") ? 
				// Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
				(tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
				// This is a child template item. Build nested template.
				build( item, tmplItem, item._ctnt );
		}) : 
		// If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 
		tmplItem;
		if ( nested ) {
			return ret;
		}

		// top-level template
		ret = ret.join("");

		// Support templates which have initial or final text nodes, or consist only of text
		// Also support HTML entities within the HTML markup.
		ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
			frag = jQuery( middle ).get();

			storeTmplItems( frag );
			if ( before ) {
				frag = unencode( before ).concat(frag);
			}
			if ( after ) {
				frag = frag.concat(unencode( after ));
			}
		});
		return frag ? frag : unencode( ret );
	}

	function unencode( text ) {
		// Use createElement, since createTextNode will not render HTML entities correctly
		var el = document.createElement( "div" );
		el.innerHTML = text;
		return jQuery.makeArray(el.childNodes);
	}

	// Generate a reusable function that will serve to render a template against data
	function buildTmplFn( markup ) {
		return new Function("jQuery","$item",
			"var $=jQuery,call,_=[],$data=$item.data;" +

			// Introduce the data as local variables using with(){}
			"with($data){_.push('" +

			// Convert the template into pure JavaScript
			jQuery.trim(markup)
				.replace( /([\\'])/g, "\\$1" )
				.replace( /[\r\t\n]/g, " " )
				.replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
				.replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
				function( all, slash, type, fnargs, target, parens, args ) {
					var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
					if ( !tag ) {
						throw "Template command not found: " + type;
					}
					def = tag._default || [];
					if ( parens && !/\w$/.test(target)) {
						target += parens;
						parens = "";
					}
					if ( target ) {
						target = unescape( target ); 
						args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
						// Support for target being things like a.toLowerCase();
						// In that case don't call with template item as 'this' pointer. Just evaluate...
						expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target;
						exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
					} else {
						exprAutoFnDetect = expr = def.$1 || "null";
					}
					fnargs = unescape( fnargs );
					return "');" + 
						tag[ slash ? "close" : "open" ]
							.split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
							.split( "$1a" ).join( exprAutoFnDetect )
							.split( "$1" ).join( expr )
							.split( "$2" ).join( fnargs ?
								fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) {
									params = params ? ("," + params + ")") : (parens ? ")" : "");
									return params ? ("(" + name + ").call($item" + params) : all;
								})
								: (def.$2||"")
							) +
						"_.push('";
				}) +
			"');}return _;"
		);
	}
	function updateWrapped( options, wrapped ) {
		// Build the wrapped content. 
		options._wrap = build( options, true, 
			// Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
			jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
		).join("");
	}

	function unescape( args ) {
		return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
	}
	function outerHtml( elem ) {
		var div = document.createElement("div");
		div.appendChild( elem.cloneNode(true) );
		return div.innerHTML;
	}

	// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
	function storeTmplItems( content ) {
		var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
		for ( i = 0, l = content.length; i < l; i++ ) {
			if ( (elem = content[i]).nodeType !== 1 ) {
				continue;
			}
			elems = elem.getElementsByTagName("*");
			for ( m = elems.length - 1; m >= 0; m-- ) {
				processItemKey( elems[m] );
			}
			processItemKey( elem );
		}
		function processItemKey( el ) {
			var pntKey, pntNode = el, pntItem, tmplItem, key;
			// Ensure that each rendered template inserted into the DOM has its own template item,
			if ( (key = el.getAttribute( tmplItmAtt ))) {
				while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
				if ( pntKey !== key ) {
					// The next ancestor with a _tmplitem expando is on a different key than this one.
					// So this is a top-level element within this template item
					// Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
					pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
					if ( !(tmplItem = newTmplItems[key]) ) {
						// The item is for wrapped content, and was copied from the temporary parent wrappedItem.
						tmplItem = wrappedItems[key];
						tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true );
						tmplItem.key = ++itemKey;
						newTmplItems[itemKey] = tmplItem;
					}
					if ( cloneIndex ) {
						cloneTmplItem( key );
					}
				}
				el.removeAttribute( tmplItmAtt );
			} else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
				// This was a rendered element, cloned during append or appendTo etc.
				// TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
				cloneTmplItem( tmplItem.key );
				newTmplItems[tmplItem.key] = tmplItem;
				pntNode = jQuery.data( el.parentNode, "tmplItem" );
				pntNode = pntNode ? pntNode.key : 0;
			}
			if ( tmplItem ) {
				pntItem = tmplItem;
				// Find the template item of the parent element. 
				// (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
				while ( pntItem && pntItem.key != pntNode ) { 
					// Add this element as a top-level node for this rendered template item, as well as for any
					// ancestor items between this item and the item of its parent element
					pntItem.nodes.push( el );
					pntItem = pntItem.parent;
				}
				// Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
				delete tmplItem._ctnt;
				delete tmplItem._wrap;
				// Store template item as jQuery data on the element
				jQuery.data( el, "tmplItem", tmplItem );
			}
			function cloneTmplItem( key ) {
				key = key + keySuffix;
				tmplItem = newClonedItems[key] = 
					(newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true ));
			}
		}
	}

	//---- Helper functions for template item ----

	function tiCalls( content, tmpl, data, options ) {
		if ( !content ) {
			return stack.pop();
		}
		stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
	}

	function tiNest( tmpl, data, options ) {
		// nested template, using {{tmpl}} tag
		return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
	}

	function tiWrap( call, wrapped ) {
		// nested template, using {{wrap}} tag
		var options = call.options || {};
		options.wrapped = wrapped;
		// Apply the template, which may incorporate wrapped content, 
		return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
	}

	function tiHtml( filter, textOnly ) {
		var wrapped = this._wrap;
		return jQuery.map(
			jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
			function(e) {
				return textOnly ?
					e.innerText || e.textContent :
					e.outerHTML || outerHtml(e);
			});
	}

	function tiUpdate() {
		var coll = this.nodes;
		jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
		jQuery( coll ).remove();
	}
})( jQuery );
jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options.expires=-1;}var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;}expires='; expires='+date.toUTCString();}var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}}return cookieValue;}};
/*
 * jQuery validation plug-in 1.7
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.H($.2L,{17:7(d){l(!6.F){d&&d.2q&&2T.1z&&1z.52("3y 3p, 4L\'t 17, 64 3y");8}p c=$.19(6[0],\'v\');l(c){8 c}c=2w $.v(d,6[0]);$.19(6[0],\'v\',c);l(c.q.3x){6.3s("1w, 3i").1o(".4E").3e(7(){c.3b=w});l(c.q.35){6.3s("1w, 3i").1o(":2s").3e(7(){c.1Z=6})}6.2s(7(b){l(c.q.2q)b.5J();7 1T(){l(c.q.35){l(c.1Z){p a=$("<1w 1V=\'5r\'/>").1s("u",c.1Z.u).33(c.1Z.Z).51(c.U)}c.q.35.V(c,c.U);l(c.1Z){a.3D()}8 N}8 w}l(c.3b){c.3b=N;8 1T()}l(c.L()){l(c.1b){c.1l=w;8 N}8 1T()}12{c.2l();8 N}})}8 c},J:7(){l($(6[0]).2W(\'L\')){8 6.17().L()}12{p b=w;p a=$(6[0].L).17();6.P(7(){b&=a.I(6)});8 b}},4D:7(c){p d={},$I=6;$.P(c.1I(/\\s/),7(a,b){d[b]=$I.1s(b);$I.6d(b)});8 d},1i:7(h,k){p f=6[0];l(h){p i=$.19(f.L,\'v\').q;p d=i.1i;p c=$.v.36(f);23(h){1e"1d":$.H(c,$.v.1X(k));d[f.u]=c;l(k.G)i.G[f.u]=$.H(i.G[f.u],k.G);31;1e"3D":l(!k){T d[f.u];8 c}p e={};$.P(k.1I(/\\s/),7(a,b){e[b]=c[b];T c[b]});8 e}}p g=$.v.41($.H({},$.v.3Y(f),$.v.3V(f),$.v.3T(f),$.v.36(f)),f);l(g.15){p j=g.15;T g.15;g=$.H({15:j},g)}8 g}});$.H($.5p[":"],{5n:7(a){8!$.1p(""+a.Z)},5g:7(a){8!!$.1p(""+a.Z)},5f:7(a){8!a.4h}});$.v=7(b,a){6.q=$.H(w,{},$.v.3d,b);6.U=a;6.3I()};$.v.W=7(c,b){l(R.F==1)8 7(){p a=$.3F(R);a.4V(c);8 $.v.W.1Q(6,a)};l(R.F>2&&b.2c!=3B){b=$.3F(R).4Q(1)}l(b.2c!=3B){b=[b]}$.P(b,7(i,n){c=c.1u(2w 3t("\\\\{"+i+"\\\\}","g"),n)});8 c};$.H($.v,{3d:{G:{},2a:{},1i:{},1c:"3r",28:"J",2F:"4P",2l:w,3o:$([]),2D:$([]),3x:w,3l:[],3k:N,4O:7(a){6.3U=a;l(6.q.4K&&!6.4J){6.q.1K&&6.q.1K.V(6,a,6.q.1c,6.q.28);6.1M(a).2A()}},4C:7(a){l(!6.1E(a)&&(a.u 11 6.1a||!6.K(a))){6.I(a)}},6c:7(a){l(a.u 11 6.1a||a==6.4A){6.I(a)}},68:7(a){l(a.u 11 6.1a)6.I(a);12 l(a.4x.u 11 6.1a)6.I(a.4x)},39:7(a,c,b){$(a).22(c).2v(b)},1K:7(a,c,b){$(a).2v(c).22(b)}},63:7(a){$.H($.v.3d,a)},G:{15:"61 4r 2W 15.",1q:"M 2O 6 4r.",1J:"M O a J 1J 5X.",1B:"M O a J 5W.",1A:"M O a J 1A.",2j:"M O a J 1A (5Q).",1G:"M O a J 1G.",1P:"M O 5O 1P.",2f:"M O a J 5L 5I 1G.",2o:"M O 47 5F Z 5B.",43:"M O a Z 5z a J 5x.",18:$.v.W("M O 3K 5v 2X {0} 2V."),1y:$.v.W("M O 5t 5s {0} 2V."),2i:$.v.W("M O a Z 3W {0} 3O {1} 2V 5o."),2r:$.v.W("M O a Z 3W {0} 3O {1}."),1C:$.v.W("M O a Z 5j 2X 46 3M 3L {0}."),1t:$.v.W("M O a Z 5d 2X 46 3M 3L {0}.")},3J:N,5a:{3I:7(){6.24=$(6.q.2D);6.4t=6.24.F&&6.24||$(6.U);6.2x=$(6.q.3o).1d(6.q.2D);6.1a={};6.54={};6.1b=0;6.1h={};6.1f={};6.21();p f=(6.2a={});$.P(6.q.2a,7(d,c){$.P(c.1I(/\\s/),7(a,b){f[b]=d})});p e=6.q.1i;$.P(e,7(b,a){e[b]=$.v.1X(a)});7 2N(a){p b=$.19(6[0].L,"v"),3c="4W"+a.1V.1u(/^17/,"");b.q[3c]&&b.q[3c].V(b,6[0])}$(6.U).2K(":3E, :4U, :4T, 2e, 4S","2d 2J 4R",2N).2K(":3C, :3A, 2e, 3z","3e",2N);l(6.q.3w)$(6.U).2I("1f-L.17",6.q.3w)},L:7(){6.3v();$.H(6.1a,6.1v);6.1f=$.H({},6.1v);l(!6.J())$(6.U).3u("1f-L",[6]);6.1m();8 6.J()},3v:7(){6.2H();Q(p i=0,14=(6.2b=6.14());14[i];i++){6.29(14[i])}8 6.J()},I:7(a){a=6.2G(a);6.4A=a;6.2P(a);6.2b=$(a);p b=6.29(a);l(b){T 6.1f[a.u]}12{6.1f[a.u]=w}l(!6.3q()){6.13=6.13.1d(6.2x)}6.1m();8 b},1m:7(b){l(b){$.H(6.1v,b);6.S=[];Q(p c 11 b){6.S.27({1j:b[c],I:6.26(c)[0]})}6.1n=$.3n(6.1n,7(a){8!(a.u 11 b)})}6.q.1m?6.q.1m.V(6,6.1v,6.S):6.3m()},2S:7(){l($.2L.2S)$(6.U).2S();6.1a={};6.2H();6.2Q();6.14().2v(6.q.1c)},3q:7(){8 6.2k(6.1f)},2k:7(a){p b=0;Q(p i 11 a)b++;8 b},2Q:7(){6.2C(6.13).2A()},J:7(){8 6.3j()==0},3j:7(){8 6.S.F},2l:7(){l(6.q.2l){3Q{$(6.3h()||6.S.F&&6.S[0].I||[]).1o(":4N").3g().4M("2d")}3f(e){}}},3h:7(){p a=6.3U;8 a&&$.3n(6.S,7(n){8 n.I.u==a.u}).F==1&&a},14:7(){p a=6,2B={};8 $([]).1d(6.U.14).1o(":1w").1L(":2s, :21, :4I, [4H]").1L(6.q.3l).1o(7(){!6.u&&a.q.2q&&2T.1z&&1z.3r("%o 4G 3K u 4F",6);l(6.u 11 2B||!a.2k($(6).1i()))8 N;2B[6.u]=w;8 w})},2G:7(a){8 $(a)[0]},2z:7(){8 $(6.q.2F+"."+6.q.1c,6.4t)},21:7(){6.1n=[];6.S=[];6.1v={};6.1k=$([]);6.13=$([]);6.2b=$([])},2H:7(){6.21();6.13=6.2z().1d(6.2x)},2P:7(a){6.21();6.13=6.1M(a)},29:7(d){d=6.2G(d);l(6.1E(d)){d=6.26(d.u)[0]}p a=$(d).1i();p c=N;Q(Y 11 a){p b={Y:Y,2n:a[Y]};3Q{p f=$.v.1N[Y].V(6,d.Z.1u(/\\r/g,""),d,b.2n);l(f=="1S-1Y"){c=w;6g}c=N;l(f=="1h"){6.13=6.13.1L(6.1M(d));8}l(!f){6.4B(d,b);8 N}}3f(e){6.q.2q&&2T.1z&&1z.6f("6e 6b 6a 69 I "+d.4z+", 29 47 \'"+b.Y+"\' Y",e);67 e;}}l(c)8;l(6.2k(a))6.1n.27(d);8 w},4y:7(a,b){l(!$.1H)8;p c=6.q.3a?$(a).1H()[6.q.3a]:$(a).1H();8 c&&c.G&&c.G[b]},4w:7(a,b){p m=6.q.G[a];8 m&&(m.2c==4v?m:m[b])},4u:7(){Q(p i=0;i<R.F;i++){l(R[i]!==20)8 R[i]}8 20},2u:7(a,b){8 6.4u(6.4w(a.u,b),6.4y(a,b),!6.q.3k&&a.62||20,$.v.G[b],"<4s>60: 5Z 1j 5Y Q "+a.u+"</4s>")},4B:7(b,a){p c=6.2u(b,a.Y),37=/\\$?\\{(\\d+)\\}/g;l(1g c=="7"){c=c.V(6,a.2n,b)}12 l(37.16(c)){c=1F.W(c.1u(37,\'{$1}\'),a.2n)}6.S.27({1j:c,I:b});6.1v[b.u]=c;6.1a[b.u]=c},2C:7(a){l(6.q.2t)a=a.1d(a.4q(6.q.2t));8 a},3m:7(){Q(p i=0;6.S[i];i++){p a=6.S[i];6.q.39&&6.q.39.V(6,a.I,6.q.1c,6.q.28);6.2E(a.I,a.1j)}l(6.S.F){6.1k=6.1k.1d(6.2x)}l(6.q.1x){Q(p i=0;6.1n[i];i++){6.2E(6.1n[i])}}l(6.q.1K){Q(p i=0,14=6.4p();14[i];i++){6.q.1K.V(6,14[i],6.q.1c,6.q.28)}}6.13=6.13.1L(6.1k);6.2Q();6.2C(6.1k).4o()},4p:7(){8 6.2b.1L(6.4n())},4n:7(){8 $(6.S).4m(7(){8 6.I})},2E:7(a,c){p b=6.1M(a);l(b.F){b.2v().22(6.q.1c);b.1s("4l")&&b.4k(c)}12{b=$("<"+6.q.2F+"/>").1s({"Q":6.34(a),4l:w}).22(6.q.1c).4k(c||"");l(6.q.2t){b=b.2A().4o().5V("<"+6.q.2t+"/>").4q()}l(!6.24.5S(b).F)6.q.4j?6.q.4j(b,$(a)):b.5R(a)}l(!c&&6.q.1x){b.3E("");1g 6.q.1x=="1D"?b.22(6.q.1x):6.q.1x(b)}6.1k=6.1k.1d(b)},1M:7(a){p b=6.34(a);8 6.2z().1o(7(){8 $(6).1s(\'Q\')==b})},34:7(a){8 6.2a[a.u]||(6.1E(a)?a.u:a.4z||a.u)},1E:7(a){8/3C|3A/i.16(a.1V)},26:7(d){p c=6.U;8 $(4i.5P(d)).4m(7(a,b){8 b.L==c&&b.u==d&&b||4g})},1O:7(a,b){23(b.4f.4e()){1e\'2e\':8 $("3z:3p",b).F;1e\'1w\':l(6.1E(b))8 6.26(b.u).1o(\':4h\').F}8 a.F},4d:7(b,a){8 6.32[1g b]?6.32[1g b](b,a):w},32:{"5N":7(b,a){8 b},"1D":7(b,a){8!!$(b,a.L).F},"7":7(b,a){8 b(a)}},K:7(a){8!$.v.1N.15.V(6,$.1p(a.Z),a)&&"1S-1Y"},4c:7(a){l(!6.1h[a.u]){6.1b++;6.1h[a.u]=w}},4b:7(a,b){6.1b--;l(6.1b<0)6.1b=0;T 6.1h[a.u];l(b&&6.1b==0&&6.1l&&6.L()){$(6.U).2s();6.1l=N}12 l(!b&&6.1b==0&&6.1l){$(6.U).3u("1f-L",[6]);6.1l=N}},2h:7(a){8 $.19(a,"2h")||$.19(a,"2h",{2M:4g,J:w,1j:6.2u(a,"1q")})}},1R:{15:{15:w},1J:{1J:w},1B:{1B:w},1A:{1A:w},2j:{2j:w},4a:{4a:w},1G:{1G:w},49:{49:w},1P:{1P:w},2f:{2f:w}},48:7(a,b){a.2c==4v?6.1R[a]=b:$.H(6.1R,a)},3V:7(b){p a={};p c=$(b).1s(\'5H\');c&&$.P(c.1I(\' \'),7(){l(6 11 $.v.1R){$.H(a,$.v.1R[6])}});8 a},3T:7(c){p a={};p d=$(c);Q(Y 11 $.v.1N){p b=d.1s(Y);l(b){a[Y]=b}}l(a.18&&/-1|5G|5C/.16(a.18)){T a.18}8 a},3Y:7(a){l(!$.1H)8{};p b=$.19(a.L,\'v\').q.3a;8 b?$(a).1H()[b]:$(a).1H()},36:7(b){p a={};p c=$.19(b.L,\'v\');l(c.q.1i){a=$.v.1X(c.q.1i[b.u])||{}}8 a},41:7(d,e){$.P(d,7(c,b){l(b===N){T d[c];8}l(b.2R||b.2p){p a=w;23(1g b.2p){1e"1D":a=!!$(b.2p,e.L).F;31;1e"7":a=b.2p.V(e,e);31}l(a){d[c]=b.2R!==20?b.2R:w}12{T d[c]}}});$.P(d,7(a,b){d[a]=$.44(b)?b(e):b});$.P([\'1y\',\'18\',\'1t\',\'1C\'],7(){l(d[6]){d[6]=2Z(d[6])}});$.P([\'2i\',\'2r\'],7(){l(d[6]){d[6]=[2Z(d[6][0]),2Z(d[6][1])]}});l($.v.3J){l(d.1t&&d.1C){d.2r=[d.1t,d.1C];T d.1t;T d.1C}l(d.1y&&d.18){d.2i=[d.1y,d.18];T d.1y;T d.18}}l(d.G){T d.G}8 d},1X:7(a){l(1g a=="1D"){p b={};$.P(a.1I(/\\s/),7(){b[6]=w});a=b}8 a},5A:7(c,a,b){$.v.1N[c]=a;$.v.G[c]=b!=20?b:$.v.G[c];l(a.F<3){$.v.48(c,$.v.1X(c))}},1N:{15:7(c,d,a){l(!6.4d(a,d))8"1S-1Y";23(d.4f.4e()){1e\'2e\':p b=$(d).33();8 b&&b.F>0;1e\'1w\':l(6.1E(d))8 6.1O(c,d)>0;5y:8 $.1p(c).F>0}},1q:7(f,h,j){l(6.K(h))8"1S-1Y";p g=6.2h(h);l(!6.q.G[h.u])6.q.G[h.u]={};g.40=6.q.G[h.u].1q;6.q.G[h.u].1q=g.1j;j=1g j=="1D"&&{1B:j}||j;l(g.2M!==f){g.2M=f;p k=6;6.4c(h);p i={};i[h.u]=f;$.2U($.H(w,{1B:j,3Z:"2Y",3X:"17"+h.u,5w:"5u",19:i,1x:7(d){k.q.G[h.u].1q=g.40;p b=d===w;l(b){p e=k.1l;k.2P(h);k.1l=e;k.1n.27(h);k.1m()}12{p a={};p c=(g.1j=d||k.2u(h,"1q"));a[h.u]=$.44(c)?c(f):c;k.1m(a)}g.J=b;k.4b(h,b)}},j));8"1h"}12 l(6.1h[h.u]){8"1h"}8 g.J},1y:7(b,c,a){8 6.K(c)||6.1O($.1p(b),c)>=a},18:7(b,c,a){8 6.K(c)||6.1O($.1p(b),c)<=a},2i:7(b,d,a){p c=6.1O($.1p(b),d);8 6.K(d)||(c>=a[0]&&c<=a[1])},1t:7(b,c,a){8 6.K(c)||b>=a},1C:7(b,c,a){8 6.K(c)||b<=a},2r:7(b,c,a){8 6.K(c)||(b>=a[0]&&b<=a[1])},1J:7(a,b){8 6.K(b)||/^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\E-\\B\\C-\\x\\A-\\y])+(\\.([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\E-\\B\\C-\\x\\A-\\y])+)*)|((\\3S)((((\\2m|\\1W)*(\\30\\3R))?(\\2m|\\1W)+)?(([\\3P-\\5q\\45\\42\\5D-\\5E\\3N]|\\5m|[\\5l-\\5k]|[\\5i-\\5K]|[\\E-\\B\\C-\\x\\A-\\y])|(\\\\([\\3P-\\1W\\45\\42\\30-\\3N]|[\\E-\\B\\C-\\x\\A-\\y]))))*(((\\2m|\\1W)*(\\30\\3R))?(\\2m|\\1W)+)?(\\3S)))@((([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])))\\.)+(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|[\\E-\\B\\C-\\x\\A-\\y])))\\.?$/i.16(a)},1B:7(a,b){8 6.K(b)||/^(5h?|5M):\\/\\/(((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])))\\.)+(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|[\\E-\\B\\C-\\x\\A-\\y])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\5e-\\5T]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.16(a)},1A:7(a,b){8 6.K(b)||!/5U|5c/.16(2w 5b(a))},2j:7(a,b){8 6.K(b)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.16(a)},1G:7(a,b){8 6.K(b)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.16(a)},1P:7(a,b){8 6.K(b)||/^\\d+$/.16(a)},2f:7(b,e){l(6.K(e))8"1S-1Y";l(/[^0-9-]+/.16(b))8 N;p a=0,d=0,2g=N;b=b.1u(/\\D/g,"");Q(p n=b.F-1;n>=0;n--){p c=b.59(n);p d=58(c,10);l(2g){l((d*=2)>9)d-=9}a+=d;2g=!2g}8(a%10)==0},43:7(b,c,a){a=1g a=="1D"?a.1u(/,/g,\'|\'):"57|56?g|55";8 6.K(c)||b.65(2w 3t(".("+a+")$","i"))},2o:7(c,d,a){p b=$(a).66(".17-2o").2I("3H.17-2o",7(){$(d).J()});8 c==b.33()}}});$.W=$.v.W})(1F);(7($){p c=$.2U;p d={};$.2U=7(a){a=$.H(a,$.H({},$.53,a));p b=a.3X;l(a.3Z=="2Y"){l(d[b]){d[b].2Y()}8(d[b]=c.1Q(6,R))}8 c.1Q(6,R)}})(1F);(7($){l(!1F.1r.38.2d&&!1F.1r.38.2J&&4i.3G){$.P({3g:\'2d\',3H:\'2J\'},7(b,a){$.1r.38[a]={50:7(){6.3G(b,2y,w)},4Z:7(){6.4Y(b,2y,w)},2y:7(e){R[0]=$.1r.2O(e);R[0].1V=a;8 $.1r.1T.1Q(6,R)}};7 2y(e){e=$.1r.2O(e);e.1V=a;8 $.1r.1T.V(6,e)}})};$.H($.2L,{2K:7(d,e,c){8 6.2I(e,7(a){p b=$(a.4X);l(b.2W(d)){8 c.1Q(b,R)}})}})})(1F);',62,389,'||||||this|function|return|||||||||||||if||||var|settings||||name|validator|true|uFDCF|uFFEF||uFDF0|uD7FF|uF900||u00A0|length|messages|extend|element|valid|optional|form|Please|false|enter|each|for|arguments|errorList|delete|currentForm|call|format|_|method|value||in|else|toHide|elements|required|test|validate|maxlength|data|submitted|pendingRequest|errorClass|add|case|invalid|typeof|pending|rules|message|toShow|formSubmitted|showErrors|successList|filter|trim|remote|event|attr|min|replace|errorMap|input|success|minlength|console|date|url|max|string|checkable|jQuery|number|metadata|split|email|unhighlight|not|errorsFor|methods|getLength|digits|apply|classRuleSettings|dependency|handle|da|type|x09|normalizeRule|mismatch|submitButton|undefined|reset|addClass|switch|labelContainer||findByName|push|validClass|check|groups|currentElements|constructor|focusin|select|creditcard|bEven|previousValue|rangelength|dateISO|objectLength|focusInvalid|x20|parameters|equalTo|depends|debug|range|submit|wrapper|defaultMessage|removeClass|new|containers|handler|errors|hide|rulesCache|addWrapper|errorLabelContainer|showLabel|errorElement|clean|prepareForm|bind|focusout|validateDelegate|fn|old|delegate|fix|prepareElement|hideErrors|param|resetForm|window|ajax|characters|is|than|abort|Number|x0d|break|dependTypes|val|idOrName|submitHandler|staticRules|theregex|special|highlight|meta|cancelSubmit|eventType|defaults|click|catch|focus|findLastActive|button|size|ignoreTitle|ignore|defaultShowErrors|grep|errorContainer|selected|numberOfInvalids|error|find|RegExp|triggerHandler|checkForm|invalidHandler|onsubmit|nothing|option|checkbox|Array|radio|remove|text|makeArray|addEventListener|blur|init|autoCreateRanges|no|to|equal|x7f|and|x01|try|x0a|x22|attributeRules|lastActive|classRules|between|port|metadataRules|mode|originalMessage|normalizeRules|x0c|accept|isFunction|x0b|or|the|addClassRules|numberDE|dateDE|stopRequest|startRequest|depend|toLowerCase|nodeName|null|checked|document|errorPlacement|html|generated|map|invalidElements|show|validElements|parent|field|strong|errorContext|findDefined|String|customMessage|parentNode|customMetaMessage|id|lastElement|formatAndAdd|onfocusout|removeAttrs|cancel|assigned|has|disabled|image|blockFocusCleanup|focusCleanup|can|trigger|visible|onfocusin|label|slice|keyup|textarea|file|password|unshift|on|target|removeEventListener|teardown|setup|appendTo|warn|ajaxSettings|valueCache|gif|jpe|png|parseInt|charAt|prototype|Date|NaN|greater|uE000|unchecked|filled|https|x5d|less|x5b|x23|x21|blank|long|expr|x08|hidden|least|at|json|more|dataType|extension|default|with|addMethod|again|524288|x0e|x1f|same|2147483647|class|card|preventDefault|x7e|credit|ftp|boolean|only|getElementsByName|ISO|insertAfter|append|uF8FF|Invalid|wrap|URL|address|defined|No|Warning|This|title|setDefaults|returning|match|unbind|throw|onclick|checking|when|occured|onkeyup|removeAttr|exception|log|continue'.split('|'),0,{}))
/*jslint devel: true, browser: true, undef: true, white: false, maxerr: 2000 */
/*global jQuery:true, $:true, FB:true, window: true, swfobject:true */
//add jquery extension functions
jQuery.fn.enable = function() {
	this.each(function(n, item) {
		$(item).removeAttr('disabled');
	});
};
jQuery.fn.disable = function() {
	this.each(function(n, item) {
		$(item).attr('disabled', 'disabled');
	});
};

jQuery.browser.mobileSafari = /webkit.*mobile/i.test(navigator.userAgent);

// add native javascription functions
String.prototype.trim = function() {
	return this.replace(/^\s*/, "").replace(/\s*$/, "");
};

String.prototype.startsWith = function(str) {
	return (this.match("^" + str) == str);
};

// localization error message for input validator
$.extend(jQuery.validator.messages, {
	required : "請輸入此欄位",
	email : "請輸入正確的電子郵件位址",
	url : "請輸入正確的網址",
	date : "請輸入正確的日期",
	dateISO : "請輸入符合ISO格式的日期",
	number : "請輸入數字",
	digits : "只能輸入整數",
	creditcard : "請輸入正確的卡號",
	equalTo : "請再次輸入相同的值",
	accept : "請輸入正確的格式",
	maxlength : jQuery.validator.format("請輸入長度最多為 {0} 的字"),
	minlength : jQuery.validator.format("請輸入長度最少為 {0} 的字"),
	rangelength : jQuery.validator.format("請輸入長度介於 {0} 和 {1} 之間的字"),
	range : jQuery.validator.format("請輸入一個介於 {0} 和 {1} 之間的值"),
	max : jQuery.validator.format("請輸入一個最大為 {0} 的值"),
	min : jQuery.validator.format("請輸入一個最小為 {0} 的值")
});

function log() {
	if (typeof (console) != 'undefined' && typeof (console.log) == 'function') {
		Array.prototype.unshift.call(arguments, '[pubu]');
		console.log(Array.prototype.join.call(arguments, ' '));
	}
}

// common api response mapping code
var pCommonConst = {
	SUCCESS : '0',
	EXISTED : '-1',
	NO_PERMISSION : '-2',
	BLOCKED : '-3',
	SELF : '-4',
	UNKONWN_ERROR : '-5',
    EXPIRED : '-6',
	QUOTA_OVER : '-7'
};

// pubu modules definition
var pu = {};
pu.modules = {};
pu.utils = {};
pu.core = {};

pu.core.config = {
	baseUrl : '/',
	siteUrl : '',
	bookbuffet : '/bookbuffet/',
	secureSiteUrl : '',
	apiUrl : '',
	secureApiUrl : '',
	staticUrl : '',
	resourceUrl : '',
	readerVersion : '2.0b2',
	fbAppId : '',
	init : function() {
		this.siteUrl = location.protocol + '//' + location.hostname + '/';
		this.secureSiteUrl = 'https://' + location.hostname + '/';
		this.apiUrl = this.siteUrl + 'flex/1.0';
		this.secureApiUrl = this.secureSiteUrl + 'flex/1.0';
		if (location.protocol == 'https:') {
			this.staticUrl = $('meta[name=webSiteSecureStaticUrl]').attr('content') || '/';
			this.resourceUrl = $('meta[name=webSiteSecureResourceUrl]').attr('content') || '/';
		} else {
			this.staticUrl = $('meta[name=webSiteStaticUrl]').attr('content') || '/';
			this.resourceUrl = $('meta[name=webSiteResourceUrl]').attr('content') || '/';
		}
		this.fbAppId = $('meta[property="fb:app_id"]').attr('content');
	}
};

pu.core.logger = {
	debugMode : false,
	log : function(url, line, msg) {
		var browser = "";
		$.each($.browser, function(key, val) {
			if (val === true) {
				browser += key + " ";
			}
			if (key == "version") {
				browser += val;
			}
		});
		$.post(pu.core.config.siteUrl + 'logger/js', {
			location : location.href,
			browser : browser,
			url : url,
			line : line,
			msg : msg
		});
	}
};
pu.core.auth = {
	mode : '',
	init : function(mode) {
		this.mode = mode;
		// log('pu.core.auth.init(' + mode + ')');
		var that = pu.core.auth;
		$(window).bind('user.login', that._processSuccessLogin);
		$(window).bind('user.logout', that._processSuccessLogout);
		that._attachLoginListener();
		that._attachLogoutListener();
		that._attachSecureCheck('js-secure', '您的連線已逾時，為保護您帳戶的安全，請重新登入!');
	},
	isLogged : function() {
		// log('pu.core.auth.isLogged');
		var authStatus = $.cookie('auth');
		if (authStatus == '1') {
			return true;
		} else {
			var isLogged = false;
			jQuery.ajax({
				url : '/user/logged',
				success : function(result) {
					isLogged = result;
				},
				async : false
			});
			return isLogged;
		}
	},
	isSessionTimeout : function() {
		// log('pu.core.auth.isSessionTimeout');
		// the cookie 'bl' that create by server when user login success.
		if ($.cookie('bl') == '1' && !pu.core.auth.isLogged()) {
			return true;
		} else {
			return false;
		}
	},
	_attachSecureCheck : function(cssClass, msg) {
		// log('pu.core.auth._attachSecureCheck');
		$('a.' + cssClass).click(function(evt) {
			if (pu.core.auth.isLogged()) {
				return true;
			} else {
				pu.core.auth._closeAllDialog();
				if (pu.core.auth.isSessionTimeout() && msg != null) {
					$('#login-panel span.errorMsg').text(msg);
				}
				$('#login-panel').dialog('open');

				$(window).queue('login', function() {
					var redirect = $(evt.currentTarget).attr('href');
					if (redirect == '/store') {
						if (!pu.modules.user.isTradeable()) {
							$('a.js-store').hide();
						} else {
							pu.utils.window.redirect(redirect);
						}
						// #issue: 1076
					} else if (redirect == '/library') {
						if (!pu.modules.user.isPurchasable()) {
							$('a.js-library').hide();
						} else {
							pu.utils.window.redirect(redirect);
						}
					} else {
						pu.utils.window.redirect(redirect);
					}
				});
				evt.stopImmediatePropagation();
				return false;
			}
		});

		$('form.' + cssClass).submit(function(evt) {
			if (pu.core.auth.isLogged()) {
				return true;
			} else {
				pu.core.auth._closeAllDialog();
				if (pu.core.auth.isSessionTimeout() && msg != null) {
					$('#login-panel span.errorMsg').text(msg);
				}
				$('#login-panel').dialog('open');
				$(window).queue('login', function() {
					$(evt.target).submit();
				});
				evt.stopImmediatePropagation();
				return false;
			}
		});

		$('input.' + cssClass + ' ,button.' + cssClass + ', img.' + cssClass).click(function(evt) {
			if (!pu.core.auth.isLogged()) {
				pu.core.auth._closeAllDialog();
				if (pu.core.auth.isSessionTimeout() && msg != null) {
					$('#login-panel span.errorMsg').text(msg);
				}
				$('#login-panel').dialog('open');
				evt.stopImmediatePropagation();
			}
		});

		$(window).bind('user.login', function() {
			$(window).dequeue('login');
		});

		$(window).bind('dialogclose', function() {
			$(window).clearQueue('login');
		});

		$('.' + cssClass).removeClass(cssClass);

	},
	_attachLoginListener : function() {
		// log('pu.core.auth._attachLoginListener');
		var that = pu.core.auth;
		$('#login-panel').dialog({
			autoOpen : false,
			width : 580,
			modal : true,
			resizable : false
		});
		$('a.login-link').click(function() {
			that._closeAllDialog();
			$('#login-panel').dialog('open');
			return false;
		});
		that._initFBLogin();
		that._initSiteLogin();
		pu.modules.signup._initResetSignupConfirmion();
	},
	_attachLogoutListener : function() {
		// log('pu.core.auth._attachLogoutListener');
		var that = pu.core.auth;
		$('a.logout-link').click(function() {
			that._processLogout();
			return false;
		});

	},

	_processLogout : function() {
		// log('pu.core.auth._processLogout');
		var that = pu.core.auth;
		if (pu.modules.fb.getStatus()) {
			FB.logout(function(evt) {
				that._processSiteLogout();
			});
		} else {
			that._processSiteLogout();
		}
	},
	_processSiteLogout : function() {
		// log('pu.core.auth._processSiteLogout');
		if(pu.core.auth.mode == 'main'){
			pu.utils.window.redirect('/logout');
		}else{
			pu.utils.window.redirect('/logout?targetUrl=bookbuffet');
		}
	},
	_initFBLogin : function() {
		log('pu.core.auth._initFBLogin');
		var that = pu.core.auth;
		$('a.fbLogin').click(function(evt) {
			FB.login(function(response) {
				if (response.authResponse) {
					jQuery.ajax({
						type : 'POST',
						url : '/signup/fb',
						success : function(data) {								
							if ($.inArray('0', data.types) != -1) {
								if (data.newUser) {
									jQuery.ajax({
										type : 'POST',
										url : '/signup/fb',
										async : false
									});
								}
								$(window).trigger('user.login');
								return;
							} else {
								that._closeAllDialog();
								pu.modules.signup._showaAcountConnectPanel(data);
							}
						},
						async : false
					});
				} else {
					// user is not logged in
				}
			}, {scope: 'email,offline_access,publish_stream'});
			return false;
		});
	},
	_initSiteLogin : function() {
		// log('pu.core.auth._initSiteLogin');
		pu.utils.form.setPlaceHolder();
		$('#loginForm').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				email : {
					required : true,
					email : true,
					maxlength : 60
				},
				password : {
					required : true
				}
			},
			messages : {
				email : {
					required : "請輸入電子郵件位址",
					email : "請輸入正確郵件位址",
					maxlength : "電子郵件位址最長為60個字元"
				},
				password : {
					required : "請填寫密碼"
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				log('location.protocol:' + location.protocol);
				if (location.protocol != 'https:') {
					$('#loginForm').attr('action', pu.core.config.secureSiteUrl + 'auth/site/check');
					if ($.browser.msie && $.browser.version == "6.0") {
						form.submit();
					} else {
						$('#loginForm').attr('target', 'secureLogin');
						if ($('#loginForm input[name=bg]').size() === 0) {
							$('#loginForm').append('<input type="hidden" name="bg" value="true" />');
						}
						form.submit();
					}
				}
				
				jQuery.ajax({
					type : "POST",
					data : $(form).serialize(),
					url : '/auth/site/check',
					success : function(code) {
						switch (parseInt(code, 10)) {
						case 0: 
						case 4:
						case 5:
							$(window).trigger('user.login');
							break;
						case 11:
							pu.utils.message.alert($('#loginForm span.errorMsg'), false, '本帳號已達最大同時登入人數上限，故無法登入。', false);
							break;
						default:
							pu.utils.message.alert($('#loginForm span.errorMsg'), false, '請正確輸入您的帳號與密碼', false);
							break;
						}
					},
					async : false
				});
			}
		});
	},

	_processSuccessLogin : function() {
		// log('pu.core.auth._processSuccessLogin');
		$('div.toolbar').load('/toolbar');
		pu.core.auth._closeAllDialog();
		
		var nav = '';
		if(pu.core.auth.mode == 'main'){
			nav = '/globalNav';
		}else{
			nav = '/bookbuffetGlobalNav';
		}
		
		jQuery.ajax({
			url : nav,
			success : function(fragment) {
				$('.utility').html(fragment);
				pu.core.auth._attachLogoutListener();
			},
			async : false
		});
		
		if(window.location.pathname == '/bookbuffet/opening-discount'){
			pu.utils.window.reload();
		}
	},
	_processSuccessLogout : function() {
		// log('pu.core.auth._processSuccessLogout');
		pu.utils.window.reload();
	},
	_closeAllDialog : function() {
		// log('pu.core.auth._closeAllDialog');
		$('#login-panel span.errorMsg').text("");
		$('#login-panel').dialog('close');
		$('#signup-panel').dialog('close');
		$('#account-connect-panel').dialog('close');
	}

};

pu.modules.signup = {
	mode : '',
	init : function(mode) {
		this.mode = mode;
		// log('pu.modules.signup.init(' + mode + ')');
		var validator = $('#global-signup-form').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				nickname : {
					required : true,
					rangelength : [ 2, 16 ],
					remote : {
						url : "/user/nickname/available",
						type : "post",
						data : {
							target : function() {
								return $('#global-signup-form input[name=nickname]').val();
							}
						}
					}
				},
				password : {
					required : true,
					rangelength : [ 6, 20 ]
				},
				password_confirm : {
					required : true,
					rangelength : [ 6, 20 ],
					equalTo : '#global-signup-form input[name=password]'
				},
				email : {
					required : true,
					email : true,
					maxlength : 60,
					remote : {
						url : "/user/email/available",
						type : "post",
						data : {
							target : function() {
								return $('#global-signup-form input[name=email]').val();
							}
						}
					}
				},
				email_confirm : {
					required : true,
					email : true,
					maxlength : 60,
					equalTo : '#global-signup-form input[name=email]'
				},
				terms : "required"
			},
			messages : {
				nickname : {
					required : "請填寫暱稱",
					rangelength : "暱稱長度為{0}到{1}個字",
					remote : jQuery.format("已有人使用，請重新設定")
				},
				password : {
					required : "請填寫設定密碼",
					rangelength : jQuery.format("密碼為{0}到{1}個字")
				},
				password_confirm : {
					required : "請填寫確認密碼",
					rangelength : jQuery.format("密碼為{0}到{1}個字"),
					equalTo : "密碼不一致"
				},
				email : {
					required : "請輸入電子郵件位址",
					email : "請輸入正確郵件位址",
					maxlength : "電子郵件位址最長為60個字元",
					remote : jQuery.format("此郵件位址已被使用")
				},
				email_confirm : {
					required : "請輸入電子郵件位址",
					email : "請輸入正確郵件位址",
					maxlength : "電子郵件位址最長為60個字元",
					equalTo : "電子郵件不一致"
				},
				terms : "請詳細閱讀並且同意"
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				form.submit();
			}
		});

		$('#global-signup-form a.resetCaptcha, #global-signup-form input.checkAvailableNickname').unbind('click');
		$('#global-signup-form a.resetCaptcha').click(function() {
			$('#global-signup-form img.captchaImg').attr('src', pu.core.config.siteUrl + 'captcha/signup?' + Math.floor(Math.random() * 100));
			return false;
		});

		$('#global-signup-form input[name=nickname]').bind('keyup', function() {
			pu.utils.message.removeAlert(this);
		});

		var signup = pu.modules.signup;

		$('#global-signup-form input.checkAvailableNickname').click(function() {
			signup.checkAvailable($('#global-signup-form input[name=nickname]'), 'nickname');
		});
		
		$('#signup-panel').dialog({
			autoOpen : false,
			width : 780,
			modal : true
		});
		signup._switchSignupMode('normal');
		signup._attachSignupListener();

	},
	_attachSignupListener : function() {
		// log('pu.modules.signup._attachSignupListener');
		var that = pu.core.auth;
		$('a.signup-link').click(function() {
			that._closeAllDialog();
			$('#signup-panel').dialog('open');
			pu.modules.signup._switchSignupMode('normal');
			if ($('#global-signup-form  img.captchaImg').size() === 0) {
				$('<img alt="" class="captchaImg" src="/captcha/signup?' + Math.floor(Math.random() * 100) + '" />').appendTo('.js-resetCaptcha');
			}
			return false;
		});
		$('a.signup-corp-link').click(function() {
			that._closeAllDialog();
			$('#signup-panel').dialog('open');
			pu.modules.signup._switchSignupMode('corp');
			if ($('#global-signup-form  img.captchaImg').size() === 0) {
				$('<img alt="" class="captchaImg" src="/captcha/signup?' + Math.floor(Math.random() * 100) + '" />').appendTo('.js-resetCaptcha');
			}
			return false;
		});
	},
	_switchSignupMode : function(mode) {
		// log('pu.modules.signup._switchSignupMode(' + mode + ')');
		if (mode == 'corp') {
			$('#global-signup-form input[name=corporation]').val(true);
			$('#signup-panel .normal').hide();
			$('#signup-panel .corp').show();
			$('#global-signup-form input[name=profile.mobile]').rules("add", {
				required : true,
				digits : true,
				rangelength : [ 10, 10 ],
				messages : {
					required : "請填寫手機號碼",
					rangelength : "手機號碼為10碼數字",
					digits : "手機號碼為10碼數字"
				}
			});

			$('#global-signup-form input[name=profile.uniformSerialNumber]').rules("add", {
				required : true,

				digits : true,
				rangelength : [ 8, 8 ],
				messages : {
					required : "請填寫統一編號",
					rangelength : "統一編號為8碼數字",
					digits : "統一編號為8碼數字"
				}
			});

		} else {
			$('#global-signup-form input[name=corporation]').val(false);
			$('#signup-panel .corp').hide();
			$('#signup-panel .normal').show();
			if ($('#global-signup-form tr.corp input').size() > 0) {
				$('#global-signup-form tr.corp input').rules("remove");
			}
		}

	},
	_initResetSignupConfirmion : function() {
		// log('pu.modules.signup._initResetSignupConfirmion');
		$(':button.reset').click(function() {
			var email = $('input[name="email"]').val().trim();
			var pattern = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
			if (pattern.test(email)) {
				$.post(pu.core.config.siteUrl + 'signup/email/reset', {
					email : email
				}, function(code) {

					if (code == pCommonConst.SUCCESS) {
						pu.utils.window.redirect(pu.core.config.siteUrl + 'signup/enable?email=' + email);
					} else {
						alert('此帳號不適用於重發認證信功能，請使用客服中心與服務人員聯繫');
					}
				});
			} else {
				alert('請輸入電子郵件位址');
				$('input[name="password"]').focus();
			}
		});
	},
	_showaAcountConnectPanel : function(response) {
		// log('pu.modules.signup._showaAcountConnectPanel(' + response + ')');
		$(response.types).each(
				function(n, code) {
					switch (parseInt(code, 10)) {
					case -1:
					case -2:
						$('#account-connect-panel .detail, #account-connect-panel .nickname, #account-connect-panel .picture').show();
						$('#displayName').text(response.displayName);
						$('img.uiProfileImg-l').attr('src', pu.modules.fb.getPictureUrl('normal'));

						$('#checkFBNickname').click(function() {
							var target = $('#fbNickname');
							var value = target.val();
							if (value.length > 2 || value.length < 16) {
								pu.modules.signup.checkAvailable(target, 'nickname');
							} else {
								pu.utils.message.alert(target, false, '超出長度限制', false);
								$('#fbNickname').data('validate', false);
							}
						});

						break;
					case -3:
						$('#account-connect-panel .email').show();
						$('#fbEmail').bind(
								'change',
								function() {
									if (/^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/
											.test($('#fbEmail').val())) {
										pu.modules.signup.checkAvailable('fbEmail', 'email');
									} else {
										pu.utils.message.alert($('#fbEmail'), false, '錯誤的電子郵件格式', false);
										$('#fbEmail').data('validate', false);
									}
								});
						break;
					case -4:
						alert('此帳號已整合過Facebook帳號');
						break;
					}

				});
		$('#account-connect-panel').dialog({
			autoOpen : true,
			width : 560,
			modal : true
		});

		$('#account-connect-panel input.submit').unbind('click');
		
		// submit 註冊按鈕
		$('#account-connect-panel input.submit').click(function() {
			// log('click signup submit button...');
			var validate = true;
			var formData = "";

			$(response.types).each(function(n, code) {
				switch (parseInt(code, 10)) {
				case -1:
				case -2:
					validate = validate & $('#fbNickname').data('validate');
					if (formData != "") {
						formData += "&";
					}
					formData += "nickname=" + $('#fbNickname').val();
					break;
				case -3:
					validate = validate & $('#fbEmail').data('validate');
					if (formData !== "") {
						formData += "&";
					}
					formData += "email=" + $('#fbEmail').val();
				}
			});
			
			// log('signup validate...');
			if (validate) {
				var that = pu.core.auth;
				// $(this).disable();
				jQuery.ajax({
					type : 'POST',
					url : '/signup/fb',
					data : formData,
					success : function(data) {
						if ($.inArray('0', data.types) > -1) {
							if (data.newUser) {
								jQuery.ajax({
									type : 'POST',
									url : '/signup/fb',
									async : false
								});
							}
							$(window).trigger('user.login');
							return;
						} else {
							// $(this).enable();
							that._closeAllDialog();
							pu.modules.signup._showaAcountConnectPanel(data);
						}
					},
					async : false
				});
			}
			return false;
		});
	},
	checkAvailable : function(selector, name) {
		// log('pu.modules.signup.checkAvailable');
		var obj = selector instanceof Object ? $(selector) : $('#' + selector);
		if (obj.val() !== null) {
			$.post(pu.core.config.siteUrl + 'user/' + name + '/available', {
				target : obj.val()
			}, function(result) {
				obj.data('validate', result);
				if (result == true) {
					pu.utils.message.alert(obj, true, '可以使用', false);
				} else {
					var size = (obj.val()).length;
					if(size < 2 || size > 16){
						$('#global-signup-form').validate();
						return false;
					}
					pu.utils.message.alert(obj, false, '已有人使用，請重新設定', false);
				}
			});
		}
	}
};

pu.modules.fb = {
	getPictureUrl : function(type) {
		return 'http://graph.facebook.com/' + pu.modules.fb.getUid() + '/picture?type=' + type;
	},
	getUid : function() {

		var items = $.cookie('fbs_' + pu.core.config.fbAppId).replace(/^"|"$/g, '').split('&');
		for ( var i = 0; i < items.length; i++) {
			var values = items[i].split('=');
			if (values[0] == 'uid') {
				return values[1];
			}
		}
	},
	getStatus : function() {
		if ($.cookie('fbs_' + pu.core.config.fbAppId) !== null) {
			return true;

		} else {
			return false;
		}

	}

};

pu.utils.session = {
	poll : function() {
		window.setInterval(function() {
			$.post(pu.core.config.siteUrl + 'session/living', {}, null);
		}, 300000);
	}
};

pu.utils.window = {
	detectUrlCommand : function() {
		// TODO:語法分析(拆成 command 和 parameter)
		var commands = location.href.split('#');
		if (commands.length == 2 && !pu.core.auth.isLogged()) {
			var obj = pu.utils.parseCommand(commands[1]);
			switch (obj.command) {
			case 'signup':
				$('#signup-panel').dialog('open');
				break;
			case 'login':
				$('#login-panel').dialog('open');
				break;
			case 'reading':
				$(window).queue('login', function() {
					pu.utils.window.redirect("/library/magazine#" + obj.command + "?pid=" + obj.parameter.pid + "&did=" + obj.parameter.did + "");
				});
				$('#login-panel').dialog('open');
				break;
			case 'doDownload':
				$(window).queue('login', function() {
					pu.utils.window.redirect(obj.parameter.url);
				});
				$('#login-panel').dialog('open');
				break;
			}
		}
	},
	reload : function() {
		window.location = window.location.href;
	},
	redirect : function(url) {
		window.location = url;
	},
	redirectWithDelay : function(url, delay) {
		window.setTimeout(function() {
			pu.utils.window.redirect(url);
		}, delay);
	},
	back : function() {
		history.back();
	},
	close : function() {
		window.close();
	},
	scrollTo : function(element) {
		var target = element instanceof Object ? $(element) : $('#' + element);
		$('html,body').animate({
			scrollTop : target.offset().top - 50
		}, 500);
	},
	openNewWindow : function(w, h, nav, loc, sts, menu, scroll, resize, name, url) {
		var windowProperties = '';
		if (nav == false)
			windowProperties += 'toolbar=no,';
		else
			windowProperties += 'toolbar=yes,';
		if (loc == false)
			windowProperties += 'location=no,';
		else
			windowProperties += 'location=yes,';
		if (sts == false)
			windowProperties += 'status=no,';
		else
			windowProperties += 'status=yes,';
		if (menu == false)
			windowProperties += 'menubar=no,';
		else
			windowProperties += 'menubar=yes,';
		if (scroll == false)
			windowProperties += 'scrollbars=no,';
		else
			windowProperties += 'scrollbars=yes,';
		if (resize == false)
			windowProperties += 'resizable=no,';
		else
			windowProperties += 'resizable=yes,';
		if (w != "")
			windowProperties += 'width=' + w + ',';
		if (h != "")
			windowProperties += 'height=' + h;
		if (windowProperties != "") {
			if (windowProperties.charAt(windowProperties.length - 1) == ',')
				windowProperties = windowProperties.substring(0, windowProperties.length - 1);
		}
		window.open(url, name, windowProperties);

	}
};

pu.modules.contact = {
	init : function() {
		$('select.subjectOptions').change(pu.modules.contact.handler.changeSubject);
		$('a.js-cancel').click(function() {
			pu.utils.window.back();
		});
		$('#contactform').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				'subject' : "required",
				'message' : {
					required : true,
					maxlength : 500
				},
				'email' : {
					email : true
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				form.submit();
			}
		});

	},
	handler : {
		changeSubject : function(evt) {
			var target = $(evt.target);
			target.siblings('cite').remove();
			$('#subject').val('');
			var value = target.val();

			if (value == -1) {
				return false;
			} else {
				target.nextUntil('td').filter('select').remove();
			}

			switch (value) {
			case '11':
			case '14':
				$('#orderQuestionPanel').hide();
				break;
			case '18':
				if ($("#logged").val() == 'false') {
					if (confirm('您必須先登入才能執行此功能。')) {
						window.location = '/redirect?link=' + window.location;
					} else {
						target.val(-1);
						return false;
					}
				}
				$('#orderQuestionPanel').hide();
				break;

			case '3':
				if ($("#logged").val() == 'false') {
					if (confirm('您必須先登入才能執行此功能。')) {
						window.location = '/redirect?link=' + window.location;
					} else {
						target.val(-1);
						return false;
					}
				}
				$('#orderQuestionPanel').show();
				break;
			}
			if (target.find('option').hasClass('leaf')) {
				$('#subject').val(value);

			} else {
				$.get(pu.core.config.siteUrl + 'subject/' + value, "", function(data) {
					pu.utils.form.populateDropdown(target, data, pu.modules.contact.handler.changeSubject);
				});
			}

		}

	}
};

pu.modules.user = {
	login : function() {

	},
	temporaryTokenLogin : function (userId, accessToken){
		if(!pu.core.auth.isLogged() && accessToken != ''){
			$.post('/auth/temp/check', {'accessToken':accessToken, 'userId':userId}, function(data) {
				pu.core.auth._processSuccessLogin();
				return false;
			});
		}
		return false;
	},
	isLogged : function() {
		var isLogged = false;
		jQuery.ajax({
			url : '/user/logged',
			success : function(result) {
				isLogged = result;
			},
			async : false
		});
		return isLogged;
	},
	isPause : function() {
		var result = false;
		jQuery.ajax({
			url : '/user/status',
			success : function(code) {
				result = code == 2 ? false : true;
			},
			async : false
		});
		return result;
	},
	isPurchasable : function() {
		var isPurchasable = false;
		jQuery.ajax({
			url : '/user/purchasable',
			success : function(result) {
				isPurchasable = result;
			},
			async : false
		});
		return isPurchasable;
	},
	isTradeable : function() {
		var isTradeable = false;
		jQuery.ajax({
			url : '/user/tradeable',
			success : function(result) {
				isTradeable = result;
			},
			async : false
		});
		return isTradeable;
	},
	isBookbuffet : function() {
		var isBookbuffet = false;
		jQuery.ajax({
			url : '/user/bookbuffet_status',
			success : function(result) {
				isBookbuffet = result;
			},
			async : false
		});
		return isBookbuffet;
	},
	isCorporation : function() {
		var isCorporation = false;
		jQuery.ajax({
			url : '/user/corporation',
			success : function(result) {
				isCorporation = result;
			},
			async : false
		});
		return isCorporation;
	},
	isFacebookAccount : function() {
		var isFacebookAccount = false;
		jQuery.ajax({
			type : 'GET',
			url : '/user/facebook_account',
			success : function(result) {
				isFacebookAccount = result;
			},
			async : false
		});
		return isFacebookAccount;
	}
};

pu.modules.search = {
	init : function() {
		$('#searchBar').submit(function() {
			var queryString = pu.core.config.siteUrl + 'search?';
			var value = $('#global-search-input').val().trim();
			if (value == "") {
				return false;
			}
			switch ($('#searchOption').val()) {
			case '0':
				queryString += 'q=' + value;
				break;
			case '1':
				queryString += 'fl_title=' + value;
				break;
			case '2':
				queryString += 'fl_un=' + value;
				break;
			case '3':
				queryString += 'fl_id=' + value;
				break;
			}
			pu.utils.window.redirect(queryString);
			return false;
		});
	},
	handler : {

		changeCategory : function(evt) {

			var target = $(evt.target);
			var value = target.val();
			if (value == -1) {
				return false;
			} else {
				$('#category').val(value);
				target.nextUntil('td').filter('select').remove();
			}

			if (!target.find('option').hasClass('leaf')) {
				$.get(pu.core.config.siteUrl + 'category/' + value, "", function(data) {
					pu.utils.form.populateDropdown('category', target, data, pu.modules.search.handler.changeCategory);
				});
			}

		}

	}
};

pu.modules.bookshelf = {
	mode : '',
	init : function(mode) {
		this.mode = mode;
		
		var commands = location.href.split('#');
		if (commands.length == 2 && pu.core.auth.isLogged()) {
			var obj = pu.utils.parseCommand(commands[1]);
			if (obj != undefined) {
				if (obj.command == "reading" && pu.core.auth.isLogged()) {
					$.get(pu.core.config.apiUrl + '/docs/' + obj.parameter.did + '/progress?pid=' + obj.parameter.pid, function(pageId) {
						if (pageId == -1) {
							pu.modules.reader.launch(obj.parameter.pid, obj.parameter.did);
						} else {
							pu.modules.reader.launch(obj.parameter.pid, obj.parameter.did, pageId);
						}
					});
				}
			}
		}

		pu.utils.views.init();
		pu.utils.views.tooltip();

		$('img.thumbnail-m').each(function(n, item) {
			$(item).parent().addClass('js-launch-reader');
		});
		pu.modules.reader.init();
		
		$('.epub-reader').click(function(evt) {
			var idList = $(evt.target).attr('alt').split(',');
			
			jQuery.ajax({
				url : '/library/epub/' + idList[0] + '/' + idList[1] + '/accessToken',
				success : function(result) {
					var returnUrl = encodeURIComponent(window.location.pathname + window.location.search);
					
					window.location = '/index.php?productId=' + idList[0] + '&documentId=' + idList[1] + '&accessToken=' + result + '&returnUrl=' + returnUrl;
				},
				async : false
			});
			
			return false;
		});
		
		if (mode == 'column') {
			$('#product-chapter').accordion({
				header : 'h2.sub-title'
			});

			$('a.show-column-doc-link').click(function(evt) {
				$('#show-column-doc-panel').dialog({
					autoOpen : true,
					width : 560,
					buttons : {
						"關閉" : function() {
							$(this).dialog('close');
						}
					}
				});
				return false;
			});
		}

		$('.js-download').click(function(evt) {
			var idList = $(evt.target).attr('alt').split(',');
			$.post('/job/document/' + idList[0] + '/' + idList[1], {}, function(code) {
				switch (code) {
				case pCommonConst.SUCCESS:
					alert('下載請求已送出處理, 請稍後至您的註冊信箱收取下載連結');
					break;
				case pCommonConst.EXISTED:
					alert('此筆下載正在處理中');
					break;
				case pCommonConst.BLOCKED:
					alert('超出下載次數');
					break;
				case pCommonConst.NO_PERMISSION:
					alert('本書不提供下載');
					break;
				default:
					alert('系統維護');
				}
			});
			return false;
		});

		$('a.js-delete').click(function(evt) {
			var that = pu.modules.bookshelf;
			var askMessage = (pu.modules.bookshelf.mode == 'main') ? '刪除之後將無法復原！請問是否要繼續刪除？' : '您確定要從書櫃移除這本書?';
			if (confirm(askMessage)) {
				var elementId = $(evt.currentTarget).attr('code');
				$.post('/library/element/' + elementId, {
					_method : 'DELETE'
				}, null);
				
				switch (pu.modules.bookshelf.mode) {
				case 'main':
					$(evt.target).parentsUntil('ul.list-product-shelf').remove();
					break;
				case 'bookbuffet':
					$(evt.target).parentsUntil('ul.blockMyShelf').remove();
					that._reflashBookbuffetBookshelf();
					break;
				}
			}
			return false;
		});
	}, 
	_reflashBookbuffetBookshelf : function(){
		$('ul.blockMyShelf').find('hr').remove();
		
		$.each($('ul.blockMyShelf').children(), function(index, val) {
			if((index+1) % 4 == 0){
				$(this).parent().append('<hr>');
			}
		});
	}
};

pu.utils.message = {
	getMessage : function() {
		var message = this[arguments[0]] || '系統維護中';
		for ( var i = 1; i < arguments.length; i++) {
			message = message.replace('{' + (i - 1) + '}', arguments[i]);
		}
		return message.replace(/{\d}/, '');
	},
	alert : function(selector, isSucced, message, effect) {
		var node = selector instanceof Object ? $(selector) : $('#' + selector);
		node.siblings('cite').remove();
		var style = isSucced ? "safe" : "error";
		$('<cite class="' + style + '">' + message + '</cite>').appendTo(node.parent());
		if (effect) {
			node.siblings().last().fadeIn('slow');
		}
	},
	hint : function(selector, message) {
		var node = selector instanceof Object ? $(selector) : $('#' + selector);
		node.text(message);
	},
	removeAlert : function(selector) {
		var node = selector instanceof Object ? $(selector) : $('#' + selector);
		// http://bugs.jquery.com/ticket/4273
		node.siblings('cite').remove();
		// $('cite').nextAll().remove();
	}
};

pu.modules.login = {
	init : function() {
		pu.utils.form.setPlaceHolder();
		$('#loginForm').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				j_username : {
					required : true,
					email : true,
					maxlength : 60
				},
				j_password : {
					required : true
				}
			},
			messages : {
				j_username : {
					required : "請輸入電子郵件位址",
					email : "請輸入正確郵件位址",
					maxlength : "電子郵件位址最長為60個字元"
				},
				j_password : {
					required : "請填寫密碼"
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				form.submit();
			}

		});
		$(':button.reset').click(function() {
			var email = $('input[name="j_username"]').val().trim();
			var pattern = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
			if (pattern.test(email)) {
				$.post(pu.core.config.siteUrl + 'signup/email/reset', {
					email : email
				}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
						pu.utils.window.redirect(pu.core.config.siteUrl + 'signup/enable?email=' + email);
						break;
					default:
						alert('請確認此電子郵件位址是否未申請會員或已完成註冊');
						break;
					}
				});
			} else {
				alert('請輸入電子郵件位址');
				$('input[name="j_username"]').focus();
			}
		});
	}
};

pu.utils.form = {

	init : function() {
		$('textarea.js-input-quota').bind('keyup keydown change blur mouseup mousedown mouseleave ', pu.utils.form.handler.checkTypingQuota);
		$('textarea.js-input-quota-cust').bind('keyup keydown change blur mouseup mousedown mouseleave ',
				pu.utils.form.handler.checkTypingQuotaWithId);
		$('input.digit').bind('keyup keydown change blur mouseup mouseleave', pu.utils.form.handler.checkDigit);
		$(':text').addClass('inputtext');
		$('select').addClass('select');
		$(':button.js-back').click(function() {
			pu.utils.window.back();
		});
	},
	setLocalizedDatePicker : function() {
		$.datepicker.regional['zh-TW'] = {
			closeText : '關閉',
			// prevText : '&#x3c;上月',
			// nextText : '下月&#x3e;',
			currentText : '今天',
			monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
			monthNamesShort : [ '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二' ],
			dayNames : [ '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六' ],
			dayNamesShort : [ '周日', '周一', '周二', '周三', '周四', '周五', '周六' ],
			dayNamesMin : [ '日', '一', '二', '三', '四', '五', '六' ],
			weekHeader : '周',
			dateFormat : 'yy-mm-dd',
			firstDay : 1,
			isRTL : false,
			showMonthAfterYear : true,
			yearSuffix : '年'
		};
		$.datepicker.setDefaults($.datepicker.regional['zh-TW']);
	},
	populateDropdown : function(target, data, onChange) {
		$('<select></select>').insertAfter(target);
		var node = target.next();
		node.change(onChange);
		var items = '<option value="-1">請選擇</option>';
		$.each(data.split(","), function(n, item) {
			var words = item.split(":");

			items += '<option value="' + words[0] + '" ' + (words[2] == 1 ? 'class="leaf"' : '') + '>' + words[1] + '</option>';
		});
		node.append(items);
	},
	bindingDropdown : function(target, data, onChange) {
		var node = target;// .next();
		var items = '';
		node.change(onChange);
		$.each(data.split(","), function(n, item) {
			var words = item.split(":");

			items += '<option value="' + words[0] + '" ' + (words[2] == 1 ? 'class="leaf"' : '') + '>' + words[1] + '</option>';
		});
		node.append(items);
	},
	setPlaceHolder : function() {
		$('input.js-placeholder').mousedown(function() {
			if ($(this).val() == $(this).attr('alt')) {
				$(this).val('');
			}
		}).blur(function() {
			if ($(this).val() == "") {
				$(this).val($(this).attr('alt'));
			}
		});

	},
	selectAll : function() {
		$('#selectAll').click(function() {
			if ($('#selectAll').attr('checked')) {
				$(':checkbox').each(function() {
					$(this).attr('checked', true);
				});
			} else {
				$(':checkbox').each(function() {
					$(this).attr('checked', false);
				});
			}

		});

	},
	handler : {
		checkDigit : function(evt) {
			return (((evt.which > 47) && (evt.which < 58) || (evt.which > 95) && (evt.which < 106)) || evt.which == 8 || evt.which == 9 || evt.which == 46);
		},
		checkTypingQuota : function(evt) {
			var target = $(evt.target);
			var quota = target.attr('alt') || 500;
			pu.utils.message.hint(target.next(), '剩餘的字元數：' + (quota - target.val().length));
		},
		checkTypingQuotaWithId : function(evt) {
			var target = $(evt.target);
			var quota = target.attr('alt') || 500;
			pu.utils.message.hint(target.attr('id') + "-hint", '剩餘的字元數：' + (quota - target.val().length));
		}

	}

};
pu.modules.magazine = {
	maximumKeywordQuota : 10,
	init : function(mode) {
		pu.utils.form.init();
		pu.utils.form.setLocalizedDatePicker();
		pu.modules.document.setKeywords();
		pu.modules.document.resetKeywords();

		switch (mode) {
		case 'serviceCreate':
			$('#plansIndex').val(1);
			this.setPlans();
			this.resetPlans();
			pu.modules.document.setUploadCover('svcCover', pu.core.config.siteUrl + 'upload/bundle/image');

			/** set default value * */
			$("input[name='rdo_frequency']")[0].checked = true;
			$("input[name='rdo_author']")[0].checked = true;
			$('#frequencyMode').val(0);

			$('#author').val($("input[name='rdo_author']").val());

			/** set control display * */
			if ($('#permanent').attr('checked') == true) {
				$('#autoPublish').hide();
			}

			/** append extension * */
			$('#onSellTime').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				minDate : '1d'
			});

			/** set control event * */
			$('#continueBtn').click(function() {
				$('#action').val('continue');
			});
			$('#saveBtn').click(function() {
				$('#action').val('save');
			});

			$('#permanent').click(function(evt) {
				$('#autoPublish').toggle();
			});

			$('#custom_frequency').keyup(function() {
				$("input[name='rdo_frequency']")[1].checked = true;
				$('#custom_frequency').blur(function() {
					$('#frequency').val($(this).val());
					$('#frequencyMode').val(4);
				});
			});
			$('#select_frequency').change(function() {
				$("input[name='rdo_frequency']")[0].checked = true;
				$('#custom_frequency').val("");
				$('#frequency').val(0);
				$('#frequencyMode').val($(this).val());
			});
			$("input[name='rdo_frequency']").click(function() {
				if ($(this).val() == "select") {
					$('#custom_frequency').val("");
					$('#frequency').val(0);
					$('#frequencyMode').val($("#select_frequency").val());
				} else if ($(this).val() == "custom") {
					$('#frequency').val($('#custom_frequency').val());
					$('#frequencyMode').val(4);
				}
			});

			$('#onSellTime').focus(function() {
				$("input[name='delegate.onSellMode']")[1].checked = true;
			});
			$("input[name='delegate.onSellMode']").click(function() {
				if ($(this).val() == "Immediately") {
					$('#onSellTime').val("");
				}
			});

			$('#custom_author').keyup(function() {
				$("input[name='rdo_author']")[1].checked = true;
				$('#custom_author').blur(function() {
					$('#author').val($(this).val());
				});
			});
			$("input[name='rdo_author']").click(function() {
				if ($(this).val() != "custom") {
					$('#custom_author').val("");
					$('#author').val($(this).val());
				} else {
					$('#author').val($('#custom_author').val());
				}
			});

			/*
			 * $('#word').keyup(function(e) { if(e.keyCode == 13) {
			 * $('#addKeyword').click(); } });
			 */

			$('select.categoryOptions').change(pu.modules.magazine.handler.changeCategory);
			break;

		case 'serviceUpdate':
			this.setPlans();
			this.resetPlans();
			pu.modules.document.setUploadCover('svcCover', pu.core.config.siteUrl + 'upload/bundle/image');

			/** set default value * */
			$('#onSellTime').val("");

			/** set control display * */
			if ($('#permanent').attr('checked') == true) {
				$('#autoPublish').hide();
			}

			/** append extension * */
			$('#onSellTime').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				minDate : '1d'
			});

			/** set control event * */
			$('#continueBtn').click(function() {
				$('#action').val('continue');
			});
			$('#saveBtn').click(function() {
				$('#action').val('save');
			});

			$('#permanent').click(function(evt) {
				$('#autoPublish').toggle();
			});

			$('#custom_frequency').keyup(function() {
				$("input[name='rdo_frequency']")[1].checked = true;
				$('#custom_frequency').blur(function() {
					$('#frequency').val($(this).val());
					$('#frequencyMode').val(4);
				});
			});
			$('#select_frequency').change(function() {
				$("input[name='rdo_frequency']")[0].checked = true;
				$('#custom_frequency').val("");
				$('#frequency').val(0);
				$('#frequencyMode').val($(this).val());
			});
			$("input[name='rdo_frequency']").click(function() {
				if ($(this).val() == "select") {
					$('#custom_frequency').val("");
					$('#frequency').val(0);
					$('#frequencyMode').val($("#select_frequency").val());
				} else if ($(this).val() == "custom") {
					$('#frequency').val($('#custom_frequency').val());
					$('#frequencyMode').val(4);
				}
			});

			$('#onSellTime').focus(function() {
				$("input[name='delegate.onSellMode']")[3].checked = true;
			});
			$("input[name='delegate.onSellMode']").click(function() {
				if ($(this).val() != "CustomTime") {
					$('#onSellTime').val("");
				}
			});

			$('select.categoryOptions').change(pu.modules.magazine.handler.changeCategory);

			break;

		case 'periodicalCreate':
			pu.modules.document.setUploadDoc('docFile', pu.core.config.siteUrl + 'upload/document');
			pu.modules.document.setUploadCover('docCover', pu.core.config.siteUrl + 'upload/document/image');
			pu.modules.document.setUploadAttach('docAttachFile', pu.core.config.siteUrl + 'upload/document_attach');
			$('#priceForOnline').change(function() {
				pu.modules.document.calculate('document');
			});
			$('#priceForOffline').change(function() {
				pu.modules.document.calculate('document');
			});
			if ($('#download').val() == 'false') {
				$(':checkbox.download').attr('checked', true);
			}
			if ($('#download').val() == 'false' && $('#charges').size() > 0) {
				$('#charges>p:nth-child(2)').hide();
			}

			pu.modules.document.calculate('document');

			/** set default value * */
			$("input[name='rdo_AddNewOption']")[1].checked = true;
			$("input[name='rdo_publishDate']")[0].checked = true;
			$('#publishDate').val($("input[name='rdo_publishDate']").val());
			$("#current").val('');

			/** set control display * */
			if ($('#permanent').attr('checked') == true) {
				$('#autoPublish').hide();
			}

			/** append extension * */
			$('#custom_publishDate').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				onSelect : function(dateText, inst) {
					$('#publishDate').val(dateText);
				}
			});
			$('#onSellTime').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				minDate : '1d'
			});

			/** set control event * */
			$('#cancelBtn').click(function() {
				location.href = "#";
			});
			$('#saveBtn').click(function() {
				$('#action').val('save');
			});

			$('#freeCondtion').click(function() {
				$('#charges').hide();
				$('#free').show();
				$('#download').val(!$('.download:checkbox:visible').attr('checked'));
			});
			$('#chargeCondtion').click(function() {
				$('#charges').show();
				$('#free').hide();
				$('#download').val(!$('.download:checkbox:visible').attr('checked'));
			});
			$('#chargeDownload').click(function() {
				$('#charges>p:nth-child(2)').toggle();
			});
			$('#permanent').click(function(evt) {
				$('#autoPublish').toggle();
			});
			$('.pricing-setting-block .download').click(function() {
				$('#download').val(!this.checked);
				if (this.checked) {
					$('#fee2').text(0);
				} else {
					pu.modules.document.calculate('document');
				}
			});

			$('#onSellTime').focus(function() {
				$("input[name='onSellMode']")[1].checked = true;
			});
			$("input[name='onSellMode']").click(function() {
				if ($(this).val() != "CustomTime") {
					$('#onSellTime').val("");
				}
			});

			$('#custom_publishDate').focus(function() {
				$("input[name='rdo_publishDate']")[1].checked = true;
			});
			$("input[name='rdo_publishDate']").click(function() {
				if ($(this).val() != "custom") {
					$('#custom_publishDate').val("");
					$('#publishDate').val($("input[name='rdo_publishDate']").val());
				} else {
					$('#publishDate').val($("#custom_publishDate").val());
				}
			});

			$('#sel_ExistingPeriodical').change(function() {
				$("input[name='rdo_AddNewOption']")[0].checked = true;
				$("#sel_ExistingPeriodical").rules("add", "selectExistingPeriodical_rule");

				$("#docUploaded").rules("remove");
				$("#title").rules("remove");
				$("#subtitle").rules("remove");
				$("#description").rules("remove");
				$("#keywords").rules("remove");
				$("#toc").rules("remove");
				$("#onSellTime").rules("remove");
				$("#priceForOnline").rules("remove");

				$('div .create-content').hide();
			});
			$("input[name='rdo_AddNewOption']").click(function() {
				var validator = $('#form').validate().resetForm();
				if ($(this).val() == "existing") {
					$("#sel_ExistingPeriodical").rules("add", "selectExistingPeriodical_rule");

					$("#docUploaded").rules("remove");
					$("#title").rules("remove");
					$("#subtitle").rules("remove");
					$("#description").rules("remove");
					$("#keywords").rules("remove");
					$("#toc").rules("remove");
					$("#onSellTime").rules("remove");
					$("#priceForOnline").rules("remove");

					$('div .create-content').hide();
				} else {
					$("#sel_ExistingPeriodical").rules("remove");

					$("#docUploaded").rules("add", "required");
					$("#title").rules("add", {
						required : true,
						rangelength : [ 2, 80 ]
					});
					$("#subtitle").rules("add", {
						maxlength : 12
					});
					$("#description").rules("add", {
						required : true,
						maxlength : 500
					});
					$("#keywords").rules("add", "required");
					$("#toc").rules("add", {
						required : true,
						maxlength : 800
					});
					$("#onSellTime").rules("add", "onSellTime_rule");
					$("#priceForOnline").rules("add", "minOnlinPrice");

					$('div .create-content').show();
				}
			});

			break;

		case 'periodicalUpdate':
			pu.modules.document.setUploadCover('docCover', pu.core.config.siteUrl + 'upload/document/image');
			pu.modules.document.setUploadAttach('docAttachFile', pu.core.config.siteUrl + 'upload/document_attach');
			/** set default value * */
			$('#onSellTime').val("");

			$('#priceForOnline').change(function() {
				pu.modules.document.calculate('document');
			});
			$('#priceForOffline').change(function() {
				pu.modules.document.calculate('document');
			});
			if ($('#download').val() == 'false') {
				$(':checkbox.download').attr('checked', true);
			}
			if ($('#download').val() == 'false' && $('#charges').size() > 0) {
				$('#charges>p:nth-child(2)').hide();
			}

			pu.modules.document.calculate('document');

			/** set control display * */
			if ($('#permanent').attr('checked') == true) {
				$('#autoPublish').hide();
			}

			/** append extension * */
			$('#publishDate').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true
			});
			$('#onSellTime').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				minDate : '1d'
			});

			/** set control event * */
			$('#cancelBtn').click(function() {
				location.href = "#";
			});
			$('#saveBtn').click(function() {
				$('#action').val('save');
			});

			$('#freeCondtion').click(function() {
				$('#charges').hide();
				$('#free').show();
				$('#download').val(!$('.download:checkbox:visible').attr('checked'));
			});
			$('#chargeCondtion').click(function() {
				$('#charges').show();
				$('#free').hide();
				$('#download').val(!$('.download:checkbox:visible').attr('checked'));
			});
			$('#chargeDownload').click(function() {
				$('#charges>p:nth-child(2)').toggle();
			});
			$('#permanent').click(function(evt) {
				$('#autoPublish').toggle();
			});
			$('.pricing-setting-block .download').click(function() {
				$('#download').val(!this.checked);
				if (this.checked) {
					$('#fee2').text(0);
				} else {
					pu.modules.document.calculate('document');
				}
			});

			$('#onSellTime').focus(function() {
				$("input[name='onSellMode']")[3].checked = true;
			});
			$("input[name='onSellMode']").click(function() {
				if ($(this).val() != "CustomTime") {
					$('#onSellTime').val("");
				}
			});

			$('#sel_ExistingPeriodical').change(function() {
				$("input[name='rdo_AddNewOption']")[0].checked = true;
				$('div .create-content').hide();
			});

			break;
		}

		pu.utils.session.poll();
	},
	setPlans : function() {
		$('#addPlan').click(
				function() {
					var volumeCount = $('#volumeCount').val().trim();
					var originalPrice = $('#originalPrice').val().trim();
					var price = $('#price').val().trim();
					var freeDownload = $('#freeDownload').attr("checked");
					if ((volumeCount.length === 0) || (price.length === 0)) {
						alert("方案設定請填寫完整");
						return false;
					} else {
						if (originalPrice.length == 0) {
							originalPrice = 0;
						}

						var plan = "0@" + volumeCount + "@" + originalPrice + "@" + price + "@" + freeDownload;
						if ($.inArray(plan, $('#plansValue').val().split(',')) == -1) {
							var text = volumeCount + "期  優惠價$" + price;
							if (freeDownload) {
								text += " 下載版";
							} else {
								text += " 線上閱讀版";
							}
							$('#plansValue').val(plan + "," + $('#plansValue').val());
							$(
									'<span><a class=\"addedlink\" href=\"javascript:void();\">' + text + '<span id="value" style="display:none">'
											+ plan + '</span></a><br /></span>').prependTo('#plans').click(pu.modules.magazine.handler.removePlan);
						}
						$('#plansValue').siblings('cite').remove();
					}
				});
	},
	resetPlans : function() {
		var plans = $('.addedlink1');
		plans.click(this.handler.removePlan);
	},
	handler : {
		removePlan : function(evt) {
			$('#plansValue').val($('#plansValue').val().replace($(this).find("#value").text() + ',', ''));
			$(evt.target).parent().remove();
			return false;
		},
		changeCategory : function(evt) {
			var target = $(evt.target);
			target.siblings('cite').remove();
			$('#category').val('');
			var value = target.val();
			if (value == -1) {
				return false;
			} else {
				target.nextUntil('td').filter('select').remove();
			}

			target.find('option').each(function(element) {
				if ($(this).val() == value) {
					if ($(this).hasClass('leaf')) {
						$('#category').val(value);
					} else {
						$.get(pu.core.config.siteUrl + 'category/' + value, "", function(data) {
							pu.utils.form.populateDropdown(target, data, pu.modules.magazine.handler.changeCategory);
						});
					}

					return false;
				}
			});
		}
	},
	updateDocPage : function() {

		var pid = $('meta[name=pid]').attr('content');

		if (pu.modules.user.isLogged()) {
			if (pu.modules.user.isPause()) {
				$('button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').show();
				$('.post, div.fs-12>a').hide();
			} else {
				$.getJSON('/product/' + pid + '/permission', function(data) {
					if (data.corporation) {
						$('.post, div.fs-12>a, button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').hide();
						if (!data.charge) {
							$('#all-read').show();
						}
						pu.modules.question.loadQA();
						return;
					}
					if (data.owner) {
						$('.post, div.fs-12>a, button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').hide();
						if (data.bookshelf) {
							if (!data.charge) {
								$('button.js-bookshelf-add, #all-read').show();
								if (data.download) {
									$('#download-read').show();
								}
							}
						} else {
							$('#download-read, #all-read').show();
							$('#try-read').hide();
						}

						pu.modules.question.loadQA();
						return;
					}

					if (!data.purchasable) {
						$('.post, div.fs-12>a').hide();
					} else {
						if (data.bookshelf) {
							$('button.js-cart-add, button.js-bookshelf-add').show();
							if (data.tracking) {
								$('button.js-tracking-add').show();
							}
						}
					}
					if (!data.bookshelf) {
						$('button.js-cart-add, button.js-tracking-add, #try-read').hide();
						$('#all-read').show();

						if (data.download) {
							$('#download-read').show();
						}
						if (data.rating) {
							pu.modules.product.addRatingLink();
						}
					} else {
						if (!data.charge) {
							if (data.download) {
								$('#download-read').show();
							}
						}
						$('button.js-tracking-add').show();
						// $('#product-comment>.post, #js-comment').hide();
					}

					$('#product-qa>.post, #js-question').show();
					if (data.isAsk) {
						pu.modules.question.loadQA();
					}
				});
			}
		} else {
			$('button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').show();
			$('.post, div.fs-12>a').hide();
		}

	}
};
pu.modules.document = {
	maximumKeywordQuota : 10,
	init : function(mode) {
		pu.utils.form.init();
		pu.utils.form.setLocalizedDatePicker();
		this.setKeywords();
		this.resetKeywords();

		$('#continueBtn').click(function() {
			$('#action').val('continue');
		});
		$('#saveBtn').click(function() {
			$('#action').val('save');
		});
		switch (mode) {
		case 'docCreate':
			this.setUploadDoc('docFile', pu.core.config.siteUrl + 'upload/document');
			this.setUploadAttach('docAttachFile', pu.core.config.siteUrl + 'upload/document_attach');

			/** append extension * */
			$('#custom_publishDate').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				onSelect : function(dateText, inst) {
					$('#publishDate').val(dateText);
				}
			});

			$('#custom_publishDate').focus(function() {
				$("input[name='rdo_publishDate']")[1].checked = true;
			});
			$("input[name='rdo_publishDate']").click(function() {
				if ($(this).val() != "custom") {
					$('#custom_publishDate').val("");
					$('#publishDate').val($("input[name='rdo_publishDate']").val());
				} else {
					$('#publishDate').val($("#custom_publishDate").val());
				}
			});
			$('#onSellTime').focus(function() {
				$("input[name='onSellMode']")[1].checked = true;
			});

		case 'docUpdate':			
			if (mode == 'docUpdate') {
				$('#onSellTime').val("");

				/** append extension * */
				$('#publishDate').datepicker({
					dateFormat : 'yy-mm-dd',
					changeMonth : true,
					changeYear : true
				});

				$('#onSellTime').focus(function() {
					$("input[name='onSellMode']")[3].checked = true;
				});
			}

			this.setUploadCover('docCover', pu.core.config.siteUrl + 'upload/document/image');
			this.setUploadAttach('docAttachFile', pu.core.config.siteUrl + 'upload/document_attach');
			$('#priceForOnline').change(function() {
				pu.modules.document.calculate('document');
			});
			$('#priceForOffline').change(function() {
				pu.modules.document.calculate('document');
			});
			if ($('#download').val() == 'false') {
				$(':checkbox.download').attr('checked', true);
			}
			if ($('#download').val() == 'false' && $('#charges').size() > 0) {
				$('#charges>p:nth-child(2)').hide();
			}
			if ($('#permanent').attr('checked') == true) {
				$('#autoPublish').hide();
			}

			$('#onSellTime').datepicker({
				dateFormat : 'yy-mm-dd',
				changeMonth : true,
				changeYear : true,
				minDate : '1d'
			});

			$("input[name='onSellMode']").click(function() {
				if ($(this).val() != "CustomTime") {
					$('#onSellTime').val("");
				}
			});

			pu.modules.document.calculate('document');
			break;
		case 'colCreate':
		case 'colUpdate':
			this.setUploadDoc('docFile', pu.core.config.siteUrl + 'upload/column');
			this.setUploadCover('docCover', pu.core.config.siteUrl + 'upload/bundle/image');
			$('#priceForOnline').change(function() {
				pu.modules.document.calculate('column');
			});
			break;
		case 'colDocCreate':
			this.setUploadDoc('docFile', pu.core.config.siteUrl + 'upload/column');
			return;
		}

		$('input[name="authorCondition"]').change(function(evt) {
			var target = $(evt.target);
			if (target.val() == "custom") {
				$('#author').val($('#custom').val());
			} else {
				$('#author').val(target.val());
			}
		});
		$('#custom').keyup(function() {
			$('#custom').prev().prev().attr('checked', true);
			$('#author').val($('#custom').val());
		});
		$('#freeCondtion').click(function() {
			$('#charges').hide();
			$('#free').show();
			$('#download').val(!$('.download:checkbox:visible').attr('checked'));
		});
		$('#chargeCondtion').click(function() {
			$('#charges').show();
			$('#free').hide();
			$('#download').val(!$('.download:checkbox:visible').attr('checked'));
		});
		$('#chargeDownload').click(function() {
			$('#charges>p:nth-child(2)').toggle();
		});
		$('#permanent').click(function(evt) {
			$('#autoPublish').toggle();
		});
		$('.pricing-setting-block .download').click(function() {
			$('#download').val(!this.checked);
			if (this.checked) {
				$('#fee2').text(0);
			} else {
				pu.modules.document.calculate('document');
			}
		});
		$('#type').change(pu.modules.document.handler.getCategory);
		$('select.categoryOptions').change(pu.modules.document.handler.changeCategory);
		pu.utils.session.poll();
	},
	setUploadCover : function(selector, uploadPath) {
		$('#upload-dialog-link').click(function() {
			$('#upload-dialog-panel').dialog({
				autoOpen : true,
				width : 380,
				buttons : {
					'確定' : function() {
						$(this).dialog('close');
					},
					'取消' : function() {
						// TODO 未實作
						$(this).dialog('close');
					}
				}
			});
			return false;
		});
		$('#' + selector).uploadify(
				{
					id : selector,
					uploader : pu.core.config.staticUrl + 'images/uploadify.swf',
					buttonImg : pu.core.config.staticUrl + 'images/docfileuploaderimg.jpg',
					script : uploadPath,
					expressInstall : pu.core.config.staticUrl + 'images/expressInstall.swf',
					scriptAccess : 'always',
					scriptData : {
						formId : $('#formId').val()
					},
					fileDataName : 'file',
					width : 185,
					height : 38,
					auto : true,
					multi : false,
					fileDesc : '請選擇檔案',
					buttonText : ' ',
					cancelImg : pu.core.config.staticUrl + 'images/empty.gif',
					fileExt : '*.jpg',
					sizeLimit : 2097152,
					onProgress : function() {
						$('#' + selector).next().width(1).height(1);
					},
					onComplete : function(event, queueID, fileObj, response) {
						var target = $('#' + selector).next();
						if (parseInt(response, 10) === 0) {
							$('#uploadPicturePriview').attr('src',
									uploadPath + '/preview?formId=' + $('#formId').val() + '&' + Math.floor(Math.random() * 100));
							$('#upload-dialog-panel').dialog('close');
							$('#upload-dialog-link').hide();
						} else {
							pu.utils.message.alert(target, false, pUploadMessage.getMessage(parseInt(response, 10)), true);
							target.width(185).height(38);
						}

					},
					onError : function() {
						$('#' + selector).next().width(185).height(38);
					}
				});

	},
	setUploadDoc : function(selector, uploadPath) {
		
		$('#' + selector).uploadify({
			id : selector,
			uploader : pu.core.config.staticUrl + 'images/uploadify.swf',
			buttonImg : pu.core.config.staticUrl + 'images/docfileuploaderimg.jpg',
			script : uploadPath,
			expressInstall : pu.core.config.staticUrl + 'images/expressInstall.swf',
			scriptAccess : 'always',
			scriptData : {
				formId : $('#formId').val(),
				userId : ($('#userId').val() == undefined) ? 0 : $('#userId').val()
			},
			fileDataName : 'file',
			width : 185,
			height : 38,
			auto : true,
			multi : false,
			fileDesc : '請選擇檔案',
			buttonText : ' ',
			cancelImg : pu.core.config.staticUrl + 'images/empty.gif',
			fileExt : '*.epub;*.pdf;*.doc;*.docx;*.ppt;*.pptx;*.txt;*.zip;',
			sizeLimit : 105906176,
			//sizeLimit : parseInt($("#uploadMaxSize").val()),
			onProgress : function() {
				$('#' + selector).next().width(1).height(1);
			},
			onComplete : function(event, queueID, fileObj, response) {
				var target = $('#' + selector).next();
				if (parseInt(response, 10) === 0) {
					$('#docUploaded').val('true');
					pu.utils.message.alert(target, true, fileObj.name + ' 上傳成功', true);
				} else {
					pu.utils.message.alert(target, false, pUploadMessage.getMessage(parseInt(response, 10)), true);
					target.width(185).height(38);
				}
				switch (parseInt(response, 10)) {
				case 0:
					$('#docUploaded').val('true');
					pu.utils.message.alert(target, true, fileObj.name + ' 上傳成功', true);
					break;
				case 1:
					
					break;
				default:
					break;
				}
			},
			onError : function() {
				$('#' + selector).next().width(185).height(38);
			}
		});
	},
	setUploadAttach : function(selector, uploadPath) {
		$('#' + selector).uploadify(
				{
					id : selector,
					uploader : pu.core.config.staticUrl + 'images/uploadify.swf',
					buttonImg : pu.core.config.staticUrl + 'images/docfileuploaderimg.jpg',
					script : uploadPath,
					expressInstall : pu.core.config.staticUrl + 'images/expressInstall.swf',
					scriptAccess : 'always',
					scriptData : {
						formId : $('#formId').val(),
						userId : ($('#userId').val() == undefined) ? 0 : $('#userId').val()
					},
					fileDataName : 'file',
					width : 185,
					height : 38,
					auto : true,
					multi : false,
					fileDesc : '請選擇檔案',
					buttonText : ' ',
					cancelImg : pu.core.config.staticUrl + 'images/empty.gif',
					fileExt : '*.zip',
					sizeLimit : 105906176,
					onProgress : function() {
						$('#' + selector).next().width(1).height(1);
					},
					onComplete : function(event, queueID, fileObj, response) {
						var target = $('#' + selector).next();
						if (parseInt(response, 10) === 0) {
							$('#docAttachUploaded').val('true'); 
							$('#docAttachUploadedMessage').html('<cite class="safe">' + fileObj.name + ' 上傳成功</cite>');
							$('#upload-attach-dialog-panel').dialog('close');
						} else {
							pu.utils.message.alert(target, false, pUploadMessage.getMessage(parseInt(response, 10)), true);
							target.width(185).height(38);
						}
					},
					onError : function() {
						$('#' + selector).next().width(185).height(38);
					}
				});

	},
	updateDocPage : function() {

		var pid = $('meta[name=pid]').attr('content');

		if (pu.modules.user.isLogged()) {
			if (pu.modules.user.isPause()) {
				$('button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').show();
				$('.post, div.fs-12>a').hide();
			} else {
				$.getJSON('/product/' + pid + '/permission', function(data) {
					if (data.corporation) {
						$('.post, div.fs-12>a, button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').hide();
						if (!data.charge) {
							$('#all-read').show();
						}
						pu.modules.question.loadQA();
						return;
					}
					if (data.owner) {
						$('.post, div.fs-12>a, button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').hide();
						if (data.bookshelf) {
							if (!data.charge) {
								$('button.js-bookshelf-add, #all-read').show();
								if (data.download) {
									$('#download-read').show();
								}
							}
						} else {
							$('#download-read, #all-read').show();
							$('#try-read').hide();
						}

						pu.modules.question.loadQA();
						return;
					}

					if (!data.purchasable) {
						$('.post, div.fs-12>a').hide();
					} else {
						if (data.bookshelf) {
							$('button.js-cart-add, button.js-bookshelf-add').show();
							if (data.tracking) {
								$('button.js-tracking-add').show();
							}
						}
					}
					if (!data.bookshelf) {
						$('button.js-cart-add, button.js-tracking-add, #try-read').hide();
						$('#all-read').show();
						$('#pro-thumb-img').attr("alt", $('#pro-thumb-img').attr("alt") + ",true");

						if (data.download) {
							$('#download-read').show();
						}
						if (data.rating) {
							pu.modules.product.addRatingLink();
						}
					} else {
						if (!data.charge) {
							if (data.download) {
								$('#download-read').show();
							}
						}
						$('button.js-tracking-add').show();
						$('#product-comment>.post, #js-comment').hide();
					}

					$('#product-qa>.post, #js-question').show();
					if (data.isAsk) {
						pu.modules.question.loadQA();
					}
				});
			}
		} else {
			$('button.js-cart-add, button.js-bookshelf-add, button.js-tracking-add').show();
			$('.post, div.fs-12>a').hide();
		}

	},
	resetKeywords : function() {
		var keywords = $('.addedlink');
		keywords.click(this.handler.removeKeyword);
		$('#keywordQuota').text(this.maximumKeywordQuota - keywords.size());
	},
	calculate : function(type) {
		var lowestHandleFee = 1;
		var revenueRate = parseFloat($('#revenueRate').val());
		var priceForOnline = parseInt($("#priceForOnline").val(), 10);

		if (priceForOnline == "" || isNaN(priceForOnline)) {
			$("#priceForOnline").val(priceForOnline);
		}
		var fee1 = parseInt(priceForOnline, 10) * revenueRate;
		fee1 = (fee1 < lowestHandleFee) ? lowestHandleFee : Math.round(fee1);
		$("#fee1").text(fee1);

		if (type == 'document') {
			var priceForOffline = parseInt($("#priceForOffline").val(), 10);
			if (priceForOffline == "" || isNaN(priceForOffline)) {
				priceForOffline = 0;
				$("#priceForOffline").val(priceForOffline);
			}
			if (!$('.download:checkbox:visible').attr('checked')) {
				var fee2 = (parseInt(priceForOnline, 10) + parseInt(priceForOffline, 10)) * revenueRate;
				fee2 = (fee2 < lowestHandleFee) ? lowestHandleFee : Math.round(fee2);
				$("#fee2").text(Math.ceil(fee2));
			}
		}
	},
	setKeywords : function() {
		$('#addKeyword').click(
				function() {
					var word = $('#word').val().trim();
					pu.modules.document.getSuggestKeywords(word);
					var keywordQuota = $('#keywordQuota').text();
					if (word.length === 0 || keywordQuota <= 0) {
						return false;
					} else {
						if ($.inArray(word, $('#keywords').val().split(',')) == -1) {
							$('#keywords').val(word + "," + $('#keywords').val());
							$('<span><a class=\"addedlink\" href=\"javascript:void();\">' + word + '</a></span>').prependTo('#words').click(
									pu.modules.document.handler.removeKeyword);
							$('#word').val('');
							$('#keywordQuota').text(keywordQuota - 1);
						}
						$('#keywords').siblings('cite').remove();
					}
				});
	},
	getSuggestKeywords : function(word) {
		$.get(pu.core.config.siteUrl + 'keyword/suggest?word=' + word, function(data) {
			$("#suggestKeywords").hide();
			$("#suggestKeywordsText").hide();
			$("#suggestKeywords").text("");
			if(data.length > 0) {
				$("#suggestKeywordsText").show("fast");
				$("#suggestKeywords").show("fast");
				var keywords = data.split(',');	
				for(var index = 0; index < keywords.length; index++) {
					$("<span><a class=\"addedlink2\" href=\"javascript:void(0);\">" + keywords[index] + "</a></span>").prependTo("#suggestKeywords").click(pu.modules.document.handler.keywordAddAndRemove);
				}
				$('#keywords').siblings('cite').remove();
			}
		});	
	},
	handler : {
		keywordAddAndRemove : function(evt) {
			var word =$(evt.target).text().trim();
			var keywordQuota = $('#keywordQuota').text();
			if (word.length === 0 || keywordQuota <= 0) {
				return false;
			} else {
				if ($.inArray(word, $('#keywords').val().split(',')) == -1) {
					$('#keywords').val(word + "," + $('#keywords').val());
					$('<span><a class=\"addedlink\" href=\"javascript:void();\">' + word + '</a></span>').prependTo('#words').click(pu.modules.document.handler.removeKeyword);
					$('#keywordQuota').text(keywordQuota - 1);
				}
				$("#keywords").siblings("cite").remove();
			}
			
			$(evt.target).remove();
			
			return false;
		},
		removeKeyword : function(evt) {
			$('#keywords').val($('#keywords').val().replace($(this).text() + ',', ''));
			$(evt.target).remove();
			$('#keywordQuota').text(parseInt($('#keywordQuota').text(), 10) + 1);
			return false;
		},
		changeCategory : function(evt) {
			var target = $(evt.target);
			target.siblings('cite').remove();
			$('#category').val('');
			var value = target.val();
			if (value == -1) {
				return false;
			} else {
				target.nextUntil('td').filter('select').remove();
			}
			if (target.find('option').hasClass('leaf')) {
				$('#category').val(value);
			} else {
				$.get(pu.core.config.siteUrl + 'category/' + value, "", function(data) {
					pu.utils.form.populateDropdown(target, data, pu.modules.document.handler.changeCategory);
				});
			}
		},
		getCategory : function(evt) {
			var target = $(evt.target);

			$('#category').val('');
			var value = target.val();
			if (value == -1) {
				return false;
			} else {
				$('select.categoryOptions').find('option').remove().end().append('<option value="-1">請選擇</option>').val('-1');
				$('select.categoryOptions').unbind('change');
				$('select.categoryOptions').nextUntil('td').filter('select').remove();
			}

			if (value == "PERIODICAL") {
				$.get(pu.core.config.siteUrl + 'category/3', "", function(data) {
					pu.utils.form.bindingDropdown($('select.categoryOptions'), data, pu.modules.magazine.handler.changeCategory);
				});
			} else if (value == "BOOK") {
				$.get(pu.core.config.siteUrl + 'category/1', "", function(data) {
					pu.utils.form.bindingDropdown($('select.categoryOptions'), data, pu.modules.document.handler.changeCategory);
				});
			}
		}

	}
};

pu.modules.question = {
	init : function() {
		$('#js-question').click(function() {
			$('#show-product-stats').tabs('select', 0);
			pu.utils.window.scrollTo('questionMessage');
			return false;
		});
		$('.js-reply').click(pu.modules.question.handler.reply);
		$('.js-cancelReply').click(pu.modules.question.handler.cancelReply);

		$('#questionForm').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				'message' : {
					required : true,
					rangelength : [ 2, 500 ]
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				var that = $('#questionForm');
				$.post(that.attr('action'), {
					message : that.find('textarea').val(),
					hide : that.find('input[name="hide"]').attr('checked')
				}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
						pu.utils.window.reload();
						break;
					case pCommonConst.BLOCKED:
						alert("無發問權限");
						break;
					case pCommonConst.SELF:
						alert("賣家無提問權限");
						break;
					default:
						alert("新增失敗，請洽客服人員");
						break;
					}
				});
				form.reset();
				// TODO dynamic html template
				// TODO hide non-answered questions
			}
		});
	},
	handler : {
		reply : function(evt) {
			// TODO common get id method
			var qid = pu.modules.comment.getQid(evt);
			$(evt.target)
					.parent()
					.replaceWith(
							'<form action="'
									+ pu.core.config.baseUrl
									+ 'product/question/'
									+ qid
									+ '/answer" method="post" id="answer'
									+ qid
									+ '"><textarea class="wd-fill js-input-quota-cust" id="answerMessage'
									+ qid
									+ '" name="message" rows="4"></textarea><div class="fc-gr push-t align-v">	<p class="float-r">		<a href="#" class="js-cancelReply">取消</a>		<input class="submit" type="submit" value="送出" />	</p><span id="answerMessage'
									+ qid + '-hint">剩餘的字元數：500</span></div></form>');
			$('.js-cancelReply').click(pu.modules.question.handler.cancelReply);
			pu.utils.form.init();
			$('#answer' + qid).validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					'message' : {
						required : true,
						rangelength : [ 1, 500 ]
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
				},
				submitHandler : function(form) {
					var that = $('#answer' + qid);
					$.post(that.attr('action'), {
						message : that.find('textarea').val(),
						hide : that.find('input[name="hide"]').attr('checked')
					}, function(code) {
						switch (code) {
						case pCommonConst.SUCCESS:
							pu.utils.window.reload();
							break;
						case pCommonConst.BLOCKED:
							alert("無回答權限");
							break;
						default:
							alert("新增失敗，請洽客服人員");
							break;
						}
					});
				}
			});
			return false;
		},
		cancelReply : function(evt) {
			$(evt.target).parents('form').replaceWith('<p class="border pull-l push-t js-reply"><a href="#" class="link">回應</a></p>');
			$('.js-reply').click(pu.modules.question.handler.reply);
			return false;
		}
	},
	loadQA : function() {
		var pid = $('meta[name=pid]').attr('content');
		$.getJSON('/product/' + pid + '/question/list', function(data) {
			$('#questionCount').text('(' + data.questionWrapper.size + ')');
			$('ul.qa-list').html('');
			data.questionWrapper.reply = 'js-reply';
			data.questionWrapper.owner.userStoreLink = pu.core.config.siteUrl + 'store/' + data.questionWrapper.owner.id;

			if (data.questionWrapper.owner.picture == 'NONE') {
				data.questionWrapper.owner.coverImageUrl = '/images/personimg.jpg';
			} else {
				data.questionWrapper.owner.coverImageUrl = pu.core.config.resourceUrl.replace(/{branch}/, data.questionWrapper.owner.id % 4 + 1)
						+ 'pics/' + data.questionWrapper.owner.id + '/' + data.questionWrapper.owner.resource + '_s.jpg';
			}

			$(data.questionWrapper.questions).each(
					function(n, item) {
						item.userStoreLink = pu.core.config.siteUrl + 'store/' + item.user.id;
						if (item.user.resource == 'undefined') {
							item.coverImageUrl = pu.core.config.resourceUrl.replace(/{branch}/, item.user.id % 4 + 1) + 'pics/' + item.user.id + '/'
									+ item.user.resource + '_s.jpg';
						} else {
							item.coverImageUrl = '/images/personimg.jpg';
						}
					});
			$("#qa-Area").tmpl(data.questionWrapper).appendTo("ul.qa-list");
			pu.modules.question.attachEvent();
		});
	},
	attachEvent : function() {
		$('.js-reply.unattached').click(pu.modules.question.handler.reply).removeClass('unattached');
	}

};

pu.modules.comment = {
	init : function() {
		$('#js-comment').click(function() {
			$('#show-product-stats').tabs('select', 1);
			pu.utils.window.scrollTo('commentMessage');
			return false;
		});
		$('.js-vote-good').click(pu.modules.comment.handler.voteGood);
		$('.js-vote-bad').click(pu.modules.comment.handler.voteBad);

		$('#commentForm').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				'message' : {
					required : true,
					rangelength : [ 2, 500 ]
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				var that = $('#commentForm');
				$.post(that.attr('action'), {
					message : that.find('textarea').val(),
					hide : that.find('input[name="hide"]').attr('checked')
				}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
						pu.utils.window.reload();
						break;
					case pCommonConst.BLOCKED:
						alert("無發問權限");
						break;
					case pCommonConst.SELF:
						alert("賣家無提問權限");
						break;
					default:
						alert("新增失敗，請洽客服人員");
						break;
					}
				});
				form.reset();
				// TODO dynamic html template
			}
		});
	},
	getCid : function(evt) {
		return $(evt.target).parents('li').attr('alt');
	},
	getQid : function(evt) {
		return $(evt.target).parents('li').attr('alt');
	},
	vote : function(evt, good) {
		var that = $(evt.target);
		$.post('/product/comment/' + this.getCid(evt) + '/rating', {
			good : good
		}, function(code) {
			switch (code) {
			case pCommonConst.SUCCESS:
				var cnt = $(evt.target).next().text();
				that.next().text(parseInt(cnt, 10) + 1);
				if (good) {
					that.addClass('vote-up-ck');
				} else {
					that.addClass('vote-down-ck');
				}
				break;
			case pCommonConst.BLOCKED:
				alert("無投票權限");
				break;
			case pCommonConst.EXISTED:
				alert("已投票");
				break;
			case pCommonConst.SELF:
				alert("賣家無投票權限");
				break;
			default:
				alert("新增失敗，請洽客服人員");
				break;
			}
		});
	},
	handler : {
		voteGood : function(evt) {
			pu.modules.comment.vote(evt, true);
		},
		voteBad : function(evt) {
			pu.modules.comment.vote(evt, false);
		}
	}
};

pu.utils.views = {
	init : function() {
		pu.utils.views.initSelectorMode();
		$('.view-select a').click(function(event) {
			// change icon status
			$('#result-view').attr('class', event.target.id);
			$('.view-select .selected').removeClass('selected');
			pu.utils.views.setSelectorMode($(event.target).attr('id'));
			$(event.target).toggleClass('selected');

			// clean tooltip effect
			$('.tooltip-vision').unbind().removeData('tooltip');
			$('.tooltip').unbind().removeAttr('style');

			if (event.target.id == 'mixed-view') {
				$('.flash-reader').show();
				$('.epub-reader').text('試試新的ePUB閱讀器 (Beta)');
			} else{
				$('.flash-reader').hide();
				$('.epub-reader').text('開啟ePUB閱讀器 (Beta)');
			}
			
			// set tooltip effect if necessary
			if (event.target.id == 'shelf-view') {
				pu.utils.views.tooltip();
			}
			return false;
		});
	},
	setSelectorMode : function(mode) {
		$.cookie('selector-mode', mode, {
			path : '/',
			expires : '3'
		});
	},
	initSelectorMode : function() {
		if ($.cookie('selector-mode') != null) {
			var mode = $.cookie('selector-mode');
			$('#result-view').attr('class', $('#' + mode).attr('id'));
			$('#' + mode).toggleClass('selected');
			
			if (mode != 'mixed-view') {
				$('.flash-reader').hide();
				$('.epub-reader').text('開啟ePUB閱讀器 (Beta)');
			}
		} else {
			$('#mixed-view').toggleClass('selected');
			$('#result-view').attr('class', 'mixed-view');
		}
	},
	tooltip : function() {
		$(".shelf-view .tooltip-vision").tooltip({
			delay : 150,
			relative : true,
			effect : 'slide',
			offset : [ 30, 0 ]
		});
	},
	bookbuffetTooltip : function() {
		$(".tooltip-vision").tooltip({
			delay : 150,
			relative : true,
			effect : 'slide',
			offset : [ 30, 0 ]
		});
	}
};

// common mapping message
var pCommonMessage = $.extend({
	'0' : '{0}完成',
	'-1' : '{0}已存在',
	'-2' : '{0}無權限',
	'-3' : '{0}黑名單',
	'-4' : '{0}個人商品',
	'-5' : '{0}失敗'
}, pu.utils.message);

var pUploadMessage = $.extend({
	'0' : '上傳完成',
	'-1' : '損壞的檔案',
	'-2' : '超出檔案大小限制',
	'-3' : '超出檔案次數上傳限制',
	'-4' : '系統維護中',
	'-5' : '檔案有毒'
}, pu.utils.message);

pu.modules.page = {
	init : function() {
		for ( var i = 0; i < arguments.length; i++) {
			eval('this.' + arguments[i] + '();');
		}
	},
	frontpage : function() {

		$('#showroom').scrollable({
			circular : true
		}).autoscroll();

		$("#ticker").scrollable({
			circular : true,
			vertical : true
		}).autoscroll();

		pu.utils.views.init();
		pu.utils.views.tooltip();
		/*
		 * column feature $('#recent-list').tabs({ event: 'mouseover' });
		 * 
		 * $('#popular-list').tabs({ event: 'mouseover' });
		 */
	},
	product : function() {
		$('#show-product-info').tabs({
			event : 'mouseover'
		});
		$('#show-product-stats').tabs({
			event : 'mouseover'
		});
		$('#product-description').accordion({
			header : 'h2.sub-title'
		});
	},
	profile : function() {
		pu.utils.form.init();
		pu.utils.form.setLocalizedDatePicker();
		$("#birthday").datepicker({
			yearRange : '1911:+0',
			changeMonth : true,
			changeYear : true,
			maxDate : '0',
			minDate : new Date(1910, 1 - 1, 1)
		});

		$('#resetCaptcha').click(function() {
			$('#captchaImg').attr("src", pu.core.config.siteUrl + "captcha/update-profile?" + Math.floor(Math.random() * 100));
			return false;
		});
		var selector = "picture";
		var uploadPath = pu.core.config.siteUrl + 'upload/user/image';

		$('#' + selector).uploadify({
			id : selector,
			uploader : pu.core.config.staticUrl + 'images/uploadify.swf',
			buttonImg : pu.core.config.staticUrl + 'images/docfileuploaderimg.jpg',
			script : uploadPath,
			expressInstall : pu.core.config.staticUrl + 'images/expressInstall.swf',
			scriptAccess : 'always',
			scriptData : {
				formId : $('#formId').val()
			},
			fileDataName : 'file',
			width : 185,
			height : 38,
			auto : true,
			multi : false,
			fileDesc : '請選擇檔案',
			buttonText : ' ',
			cancelImg : pu.core.config.staticUrl + 'images/empty.gif',
			fileExt : '*.jpg',
			sizeLimit : 2097152,
			onProgress : function() {
				$('#' + selector).next().width(1).height(1);
			},
			onComplete : function(event, queueID, fileObj, response) {
				var target = $('#' + selector).next();
				if (parseInt(response, 10) === 0) {
					var imgUrl = uploadPath + '/preview?formId=' + $('#formId').val() + '&' + Math.floor(Math.random() * 100);
					$('#uploadPicturePriview').attr('src', imgUrl);
					$('img.personimg-s:first').attr('src', imgUrl);
					$.post('/user/image', {
						formId : $('#formId').val()
					});
				} else {
					pu.utils.message.alert(target, false, pUploadMessage.getMessage(parseInt(response, 10)), true);
				}
				$('#' + selector).next().width(185).height(38);

			},
			onError : function(event, queueID, fileObj, response) {
				var target = $('#' + selector).next();
				pu.utils.message.alert(target, false, pUploadMessage.getMessage(parseInt(response, 10)), true);
				$('#' + selector).next().width(185).height(38);
			}
		});

	},
	bookbuffetDocument : function(mode) {
		switch (mode) {
		case "showDoc":		
			/** 線上試閱 * */
			$("#btn-try").bind('click', pu.modules.reader.handler.startup);

			/** 加入會員 * */
			$("#btn-join").click(function() {
				if(pu.core.auth.isLogged()) {
					location.href = pu.core.config.bookbuffet + "checkout";
				} else { 
					$("a.signup-link").trigger('click');
				}
			});
			
			/** 線上閱讀 * */
			/** 有飽讀資格，但該本書無加入書櫃，則線上閱讀的動作為先加入書櫃，在線上閱讀 * */
			$("#btn-read").click(function(evt) {
				var idArray = $(this).attr('alt').split(',');
				$.post(pu.core.config.bookbuffet + 'library', {
					id : idArray[0]
				}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
					case pCommonConst.EXISTED:
						if (pu.core.auth.isLogged() && idArray.length == 3) {
							$.get(pu.core.config.apiUrl + '/docs/' + idArray[1] + '/progress?pid=' + idArray[0], function(pageId) {
								if (pageId == -1) {
									pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
								} else {
									pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt), pageId);
								}
							});
						} else {
							pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
						}
						$("#btn-add").hide();
						break;
					case pCommonConst.BLOCKED:
						alert("立即成為Pubu飽讀會員看千本電子書+電子雜誌!");
						pu.utils.window.redirect(pu.core.config.bookbuffet + 'checkout');
						break;;
					case pCommonConst.UNKONWN_ERROR:
						alert('系統維護中');
						break;
					}
				});
				return false;
			});
			
			/** 加入書櫃 * */
			$("#btn-add").bind('click', pu.modules.bookbuffet.handler.arrangeBookshelf)
			
			/** 封面閱讀 * */
			/** 有飽讀資格，但該本書無加入書櫃，則線上閱讀的動作為先加入書櫃，在線上閱讀 * */
			$("#cover-read").click(function(evt) {
				var idArray = $(this).attr('alt').split(',');
				if (pu.modules.user.isBookbuffet()) {
					pu.modules.bookbuffet.handler.arrangeBookshelfCallback(evt, idArray, function(evt) {
						pu.modules.bookbuffet.handler.pornReader(evt, idArray);
					});
				} else {
					pu.modules.bookbuffet.handler.pornReader(evt, idArray);
				}
				return false;
			});
			
			$(window).bind('user.login', pu.modules.bookbuffet.updateDocPage);
			pu.modules.bookbuffet.updateDocPage();
			break;
		}
	},
	bookbuffetSearch : function(mode) {
		switch (mode) {
		case "list":
			var searchResultSelectMode = pu.modules.bookbuffet.getSearchResultSelectorMode();
			$("#search-list-content").removeClass().addClass(searchResultSelectMode);
			
			$("#mixed-view-view-a").click(function() {
				$("#search-list-content").removeClass().addClass("mixed-view");
				pu.modules.bookbuffet.setSearchResultSelectorMode("mixed-view");
			});
			
			$("#gallery-view-a").click(function() {
				$("#search-list-content").removeClass().addClass("gallery-view");
				pu.modules.bookbuffet.setSearchResultSelectorMode("gallery-view");
			});
			
			$("#dialog:ui-dialog").dialog("destroy");
			
			/** 線上試閱 * */
			$("a[name=btn-try]").click(function(evt) {
				var idArray = $(evt.target).attr('alt').split(',');
				if(idArray[2] == "true" && $.cookie('agree-porn') != "true") {
					pu.modules.bookbuffet.handler.pornDialog(evt, function(evt) {
						pu.modules.bookbuffet.handler.pornReader(evt, idArray);
					});
				} else {
					pu.modules.bookbuffet.handler.pornReader(evt, idArray);
				}
				return false;
			});

			/** 線上閱讀 * */
			/** 有飽讀資格，但該本書無加入書櫃，則線上閱讀的動作為先加入書櫃，在線上閱讀 * */
			$("a[name=btn-read]").click(function(evt) {
				var idArray = $(this).attr('alt').split(',');
				if(idArray[3] == "true" && $.cookie('agree-porn') != "true") {
					pu.modules.bookbuffet.handler.pornDialog(evt, function(evt) {
						pu.modules.bookbuffet.handler.arrangeBookshelfCallback(evt, idArray, function(evt) {
							pu.modules.bookbuffet.handler.pornReader(evt, idArray);
						});
					});
				} else {
					pu.modules.bookbuffet.handler.arrangeBookshelfCallback(evt, idArray, function(evt) {
						pu.modules.bookbuffet.handler.pornReader(evt, idArray);
					});
				}
				return false;
			});
			
			/** 加入書櫃 * */
			$("a[name=btn-add]").click(function(evt) {
				var $the =  $(this);
				var idArray = $(this).attr('alt').split(',');
				if(idArray[2] == "true" && $.cookie('agree-porn') != "true") {
					pu.modules.bookbuffet.handler.pornDialog(evt, function(evt) {
						if(pu.core.auth.isLogged()) {
							pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
						} else {
							$(window).queue('login', function() {
								pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
								return false;
							});
							$('#login-panel').dialog('open');
						}
					});
				} else {
					if(pu.core.auth.isLogged()) {
						pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
					} else {
						$(window).queue('login', function() {
							pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
							return false;
						});
						$('#login-panel').dialog('open');
					}
				}
			});
			
			$(window).bind('user.login', pu.modules.bookbuffet.updateSearchListPage);
			pu.modules.bookbuffet.updateSearchListPage();
			break;
		}
	},
	document : function(mode) {

		$.validator.addMethod("minOnlinPrice", function(value, element) {
			if ($('#chargeCondtion').attr('checked') || $('#free').size() === 0) {
				if (value == 0) {
					return false;
				}
				return true;
			}

			if ($('#freeCondtion').attr('checked')) {
				return true;
			}
			return false;
		}, '收費價格至少為1元');

		switch (mode) {
		case 'showDoc':
			var pid = $('meta[name=pid]').attr('content');
			var did = $('meta[name=did]').attr('content');
			$('.js-download').click(function() {
				$.post('/job/document/' + pid + '/' + did, {}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
						alert('下載請求已送出處理, 請稍後至您的電子郵件信箱收取下載連結。');
						break;
					case pCommonConst.EXISTED:
						alert('此筆下載正在處理中');
						break;
					case pCommonConst.BLOCKED:
						alert('超出下載次數');
						break;
					case pCommonConst.NO_PERMISSION:
						alert('本書不提供下載');
						break;
					default:
						alert('系統維護');
					}
				});
				return false;
			});

			if ($('strong.free').size() > 0) {
				$('#all-read').show();
			}
			$(window).bind('user.login', pu.modules.document.updateDocPage);
			pu.modules.document.updateDocPage();

			break;

		case 'docCreate':
			$.validator.addMethod("onSellTime_rule", function(value, element) {
				if (($("input[name='onSellMode']")[1].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入上架日期');

			$.validator.addMethod("publishDate_rule", function(value, element) {
				if (($("input[name='rdo_publishDate']")[1].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入出版日期');

			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					docUploaded : 'required',
					'document.title' : {
						required : true,
						rangelength : [ 2, 80 ]
					},
					'document.subtitle' : {
						maxlength : 12
					},
					'category' : "required",
					'document.detail.description' : {
						required : true,
						maxlength : 5000
					},
					'document.detail.toc' : {
						maxlength : 8000
					},
					'document.detail.aboutAuthor' : {
						maxlength : 1000
					},
					'document.keywords' : {
						required : true
					},
					'priceForOnline' : {
						minOnlinPrice : true
					},
					'onSellTime' : {
						onSellTime_rule : true
					},
					'custom_publishDate' : {
						publishDate_rule : true
					}
				},
				messages : {
					docUploaded : {
						required : "請選擇上傳檔案"
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
					pu.utils.window.scrollTo(element);
				}
			});

			break;
		case 'docUpdate':
			$.validator.addMethod("onSellTime_rule", function(value, element) {
				if (($("input[name='onSellMode']")[3].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入上架日期');
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					'document.subtitle' : {
						maxlength : 12
					},
					'category' : "required",
					'document.detail.description' : {
						required : true,
						maxlength : 5000
					},
					'document.detail.toc' : {
						maxlength : 8000
					},
					'document.detail.aboutAuthor' : {
						maxlength : 1000
					},
					'document.keywords' : {
						required : true
					},
					'priceForOnline' : {
						minOnlinPrice : true
					},
					'onSellTime' : {
						onSellTime_rule : true
					}
				},
				errorPlacement : function(error, element) {
					pu.utils.window.scrollTo(element);
					error.appendTo(element.parent());
				}
			});
			break;
		}

	},
	column : function(mode) {
		switch (mode) {
		case 'create':
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					docUploaded : 'required',
					name : {
						required : true,
						rangelength : [ 4, 80 ],
						remote : {
							url : pu.core.config.siteUrl + "/column/checkAvailableColumnName",
							type : "post",
							data : {
								name : function() {
									return $('#name').val();
								}
							}
						}
					},
					category : "required",
					description : {
						required : true,
						maxlength : 1000
					},
					keywords : {
						required : true
					},
					frequency : {
						min : 1
					}
				},
				messages : {
					docUploaded : {
						required : "請選擇上傳檔案"
					},
					name : {
						remote : jQuery.format("此名稱已被使用")
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
				}
			});
			break;
		case 'update':
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					category : "required",
					description : {
						required : true,
						maxlength : 1000
					},
					keywords : {
						required : true
					},
					frequency : {
						min : 1
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
				}

			});
			break;
		}

	},
	colDocument : function(mode) {
		switch (mode) {
		case 'create':
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					docUploaded : 'required',
					title : {
						required : true,
						rangelength : [ 4, 80 ]
					},
					keywords : {
						required : true
					}
				},
				messages : {
					docUploaded : {
						required : "請選擇上傳檔案"
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
				}

			});
			break;
		case 'update':
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					keywords : {
						required : true
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
				}

			});
			break;
		}
	},
	magazine : function(mode) {
		$.validator.addMethod("frequency_rule", function(value, element) {
			if (($("input[name='rdo_frequency']")[1].checked) && value.length === 0) {
				return false;
			} else {
				return true;
			}
		}, '請輸入出刊頻率');

		switch (mode) {
		case 'serviceShow':
			var pid = $('meta[name=pid]').attr('content');

			$(window).bind('user.login', pu.modules.document.updateDocPage);
			pu.modules.document.updateDocPage();

			break;

		case 'serviceCreate':
			$.validator.addMethod("onSellTime_rule", function(value, element) {
				if (($("input[name='delegate.onSellMode']")[1].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入上架日期');
			$.validator.addMethod("author_rule", function(value, element) {
				if (($("input[name='rdo_author']")[1].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入編輯名稱');

			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					'category' : {
						required : true
					},
					'name' : {
						required : true,
						rangelength : [ 2, 80 ]
					},
					'subtitle' : {
						maxlength : 12
					},
					'description' : {
						required : true,
						maxlength : 5000
					},
					'delegate.keywords' : {
						required : true
					},
					'frequency' : {
						frequency_rule : true
					},
					'plansValue' : {
						required : true
					},
					'delegate.onSellTime' : {
						onSellTime_rule : true
					},
					'author' : {
						author_rule : true
					},
					'aboutAuthor' : {
						maxlength : 1000
					}

				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
					pu.utils.window.scrollTo(element);
				}
			});
			break;
		case 'serviceUpdate':
			$.validator.addMethod("onSellTime_rule", function(value, element) {
				if (($("input[name='delegate.onSellMode']")[3].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入上架日期');
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					'category' : {
						required : true
					},
					'name' : {
						required : true,
						rangelength : [ 2, 80 ]
					},
					'subtitle' : {
						maxlength : 12
					},
					'description' : {
						required : true,
						maxlength : 5000
					},
					'delegate.keywords' : {
						required : true
					},
					'frequency' : {
						frequency_rule : true
					},
					'plansValue' : {
						required : true
					},
					'delegate.onSellTime' : {
						onSellTime_rule : true
					},
					'aboutAuthor' : {
						maxlength : 1000
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
					pu.utils.window.scrollTo(element);
				}
			});
			break;
		}

	},
	periodical : function(mode) {

		$.validator.addMethod("minOnlinPrice", function(value, element) {
			if ($('#chargeCondtion').attr('checked') || $('#free').size() === 0) {
				if (value == 0) {
					return false;
				}
				return true;
			}

			if ($('#freeCondtion').attr('checked')) {
				return true;
			}
			return false;
		}, '收費價格至少為1元');

		$.validator.addMethod("selectExistingPeriodical_rule", function(value, element) {
			if (($("input[name='rdo_AddNewOption']")[0].checked) && value == "-1") {
				return false;
			} else {
				return true;
			}
		}, '請選擇現有的雜誌');

		switch (mode) {
		case 'showDoc':
			var pid = $('meta[name=pid]').attr('content');
			var did = $('meta[name=did]').attr('content');
			$('.js-download').click(function() {
				$.post('/job/document/' + pid + '/' + did, {}, function(code) {
					switch (code) {
					case pCommonConst.SUCCESS:
						alert('下載請求已送出處理, 請稍後至您的電子郵件信箱收取下載連結。');
						break;
					case pCommonConst.EXISTED:
						alert('此筆下載正在處理中');
						break;
					case pCommonConst.BLOCKED:
						alert('超出下載次數');
						break;
					case pCommonConst.NO_PERMISSION:
						alert('本書不提供下載');
						break;
					default:
						alert('系統維護');
					}
				});
				return false;
			});

			if ($('strong.free').size() > 0) {
				$('#all-read').show();
			}
			$(window).bind('user.login', pu.modules.document.updateDocPage);
			pu.modules.document.updateDocPage();

			break;

		case 'periodicalCreate':
			if ($("input[name='rdo_AddNewOption']")[0].checked) {
				$('#form').validate({
					errorClass : "error",
					errorElement : "cite",
					rules : {
						'sel_ExistingPeriodical' : {
							selectExistingPeriodical_rule : true
						},
						'current' : {
							required : true
						}
					},
					messages : {
						current : {
							required : "請選擇當期雜誌或過期雜誌"
						}
					},
					errorPlacement : function(error, element) {
						error.appendTo(element.parent());
						pu.utils.window.scrollTo(element);
					}
				});
			} else {
				$.validator.addMethod("onSellTime_rule", function(value, element) {
					if (($("input[name='onSellMode']")[1].checked) && value.length === 0) {
						return false;
					} else {
						return true;
					}
				}, '請輸入上架日期');

				$.validator.addMethod("publishDate_rule", function(value, element) {
					if (($("input[name='rdo_publishDate']")[1].checked) && value.length === 0) {
						return false;
					} else {
						return true;
					}
				}, '請輸入出版日期');
				$('#form').validate({
					errorClass : "error",
					errorElement : "cite",
					rules : {
						docUploaded : 'required',
						'document.title' : {
							required : true,
							rangelength : [ 2, 80 ]
						},
						'document.subtitle' : {
							maxlength : 12
						},
						'document.detail.description' : {
							required : true,
							maxlength : 5000
						},
						'document.keywords' : {
							required : true
						},
						'document.detail.toc' : {
							maxlength : 8000
						},
						'onSellTime' : {
							onSellTime_rule : true
						},
						'priceForOnline' : {
							minOnlinPrice : true
						},
						'current' : {
							required : true
						},
						'custom_publishDate' : {
							publishDate_rule : true
						}

					},
					messages : {
						docUploaded : {
							required : "請選擇上傳檔案"
						},
						current : {
							required : "請選擇當期雜誌或過期雜誌"
						}
					},
					errorPlacement : function(error, element) {
						error.appendTo(element.parent());
						pu.utils.window.scrollTo(element);
					}
				});
			}
			break;

		case 'periodicalUpdate':
			$.validator.addMethod("onSellTime_rule", function(value, element) {
				if (($("input[name='onSellMode']")[3].checked) && value.length === 0) {
					return false;
				} else {
					return true;
				}
			}, '請輸入上架日期');
			$('#form').validate({
				errorClass : "error",
				errorElement : "cite",
				rules : {
					'document.title' : {
						required : true,
						rangelength : [ 2, 80 ]
					},
					'document.subtitle' : {
						maxlength : 12
					},
					'document.detail.description' : {
						required : true,
						maxlength : 5000
					},
					'document.keywords' : {
						required : true
					},
					'document.detail.toc' : {
						maxlength : 8000
					},
					'onSellTime' : {
						onSellTime_rule : true
					},
					'priceForOnline' : {
						minOnlinPrice : true
					}
				},
				errorPlacement : function(error, element) {
					error.appendTo(element.parent());
					pu.utils.window.scrollTo(element);
				}
			});
			break;

		}

	},
	blacklist : function() {
		var cache = {};
		$('#add-blacklist-panel').dialog(
				{
					autoOpen : false,
					width : 380,
					buttons : {
						"確定" : function() {
							$(this).dialog('close');
							$.post('/store/blacklist', {
								userId : $('#userId').val(),
								description : $('#add-blacklist-panel textarea').val()
							}, function(code) {
								var userId = $('#userId').val();
								var label = $('#term').val();
								switch (code) {
								case 0:
									var description = $('#add-blacklist-panel textarea').val();
									$(
											'<tr><th class="no"><input type="checkbox" /></th><td><a href="#">' + label
													+ '</a></td><td class="frame-title"><p class="title">' + description
													+ '</p></td><td class="frame-maintain"><a href="" class="js-delete" alt="' + userId + ',' + label
													+ '">刪除</a></td></tr>').prependTo('table.from-maintain tbody');
									$('#add-blacklist-panel textarea').val('');
									$('#userId').val('');
									$('#term').val('');
									alert(pCommonMessage.getMessage(code, '新增' + label));
									break;
								case -1:
									alert(pCommonMessage.getMessage(code, label));
									break;
								case -2:
									alert(pCommonMessage.getMessage(code, '新增' + label));
									break;
								}
							});
						},
						"取消" : function() {
							$(this).dialog('close');
						}
					}
				});
		$('#add-blacklist-link').click(function() {
			$('#add-blacklist-panel').dialog('open');
			return false;
		});
		$('#term').autocomplete({
			source : function(request, response) {
				if (cache.term == request.term && cache.content) {
					response(cache.content);
					return;
				}
				if (new RegExp(cache.term).test(request.term) && cache.content && cache.content.length < 13) {
					response($.ui.autocomplete.filter(cache.content, request.term));
					return;
				}
				$.post('/user/find', request, function(data) {
					cache.term = request.term;
					data.value = data.label;
					cache.content = data;
					response(data);
				});
			},
			minLength : 2,
			select : function(event, ui) {
				$('#term').val(ui.item.label);
				$('#userId').val(ui.item.id);
			}
		});
		$('.js-delete').click(function(evt) {
			var object = $(this).attr('alt').split(',');
			if (confirm('刪除此項目:' + object[1])) {
				$.post('/store/blacklist', {
					idList : object[0],
					_method : "DELETE"
				}, function(data) {
					if (data) {
						$(evt.target).parentsUntil('tbody').remove();
					}
				});
			}
			return false;
		});
	},
	payment : function(mode){
		switch (mode) {
		case 'atm':
			$('.js-print').click(function(evt){
				pu.modules.print.printScreen('payment-wrap');
			});
			break;
		default:
			break;
		}
	}
};

var CartItem = function() {
	this.id = 0;
	this.type = 0;
	this.option = 0;
	this.toString = function() {
		return this.id + ',' + this.type + ',' + this.option;
	};
};

pu.modules.cart = {
	init : function(mode) {
		switch (mode) {
		case 'global':
			this.calculate();
			$('div.clip-region').scrollable();
			var outer = this;
			var cart = $('#cart-slide');
			cart.tabs({
				cookie : {
					expires : 30
				},
				collapsible : true
			});

			// collapse panel
			var selected = cart.tabs('option', 'selected');
			if (selected != -1) {
				cart.tabs('select', selected);
			}

			$('#togglePanel').click(function() {
				var selected = cart.tabs('option', 'selected');
				if (selected == -1) {
					cart.tabs('select', 0);

				} else {
					cart.tabs('select', -1);
				}
			});

			cart.show();

			$('body').bind('trackingDeleted', {}, function(evt) {
				$(evt.target).parents('div.element').remove();
			});
			$('body').bind('trackingAdded', {}, function(evt, data) {
				$('#trackingList').prepend(outer.generate(data, 'tracking'));
				outer.attachEvent();
				if (cart.tabs('option', 'selected') != 1) {
					cart.tabs('select', 1);
				}
			});
			$('body').bind('cartDeleted', {}, function(evt) {
				$(evt.target).parents('div.element').remove();
				outer.calculate();
			});
			$('body').bind('cartAdded', {}, function(evt, data) {
				$('#cartList').prepend(outer.generate(data, 'cart'));
				outer.attachEvent();
				outer.calculate();
				if (cart.tabs('option', 'selected') !== 0) {
					cart.tabs('select', 0);
				}
				pu.core.auth._attachSecureCheck('js-secure');
			});
			$('body').bind('cartReplaced', {}, function(evt, item) {
				$('#cartList :button').each(function(n, node) {
					if ($(node).attr('alt').split(',')[0] == item.id) {
						$(node).parents('div.element').remove();
					}
				});
				outer.calculate();
			});
			$(window).bind('scroll resize', this.handler.snapShoppingCartToBottom);
			$('#cart-slide').bind('tabsshow tabsselect', this.handler.snapShoppingCartToBottom);
			$('#cart-slide').css({
				top : $(window).height() - $('#cart-slide').height()
			});

			break;

		}

		$(':button.js-tracking-add, button.js-tracking-add').click(this.handler.addTracking);
		$(':button.js-tracking-delete').click(this.handler.deleteTracking);
		$(':button.js-tracking-moveto-cart').click(this.handler.moveToCart);
		$(':button.js-cart-add, button.js-cart-add').click(this.handler.addCart);
		$(':button.js-cart-delete').click(this.handler.deleteCart);
		$(':button.js-cart-moveto-tracking').click(this.handler.moveToTracking);
		$(':button.js-bookshelf-add').click(this.handler.arrangeBookshelf);
	},
	calculate : function() {
		var cnt = 0;
		var total = 0;
		$('#cartList .price .sell').each(function(n, item) {
			total += parseInt($(item).text(), 10);
			cnt++;
		});
		$('strong.quantity').text(cnt);
		$('.sum-price').text(total);
	},
	addItem : function(name, item) {
		return item + ';' + this.removeItem(name, item);
	},
	removeItem : function(name, oldItem) {
		var items = this.getItems($.cookie(name));
		if (!items) {
			return '';
		}
		return $.grep(items, function(item, i) {
			return (oldItem.id != item.id);
		}).join(';');
	},
	isExistPid : function(name, pid) {
		var items = this.getItems($.cookie(name));
		if (!items) {
			return false;
		} else {
			for ( var i = 0; i < items.length; i++) {
				if (pid == items[i].id) {
					return true;
				}
			}
		}
		return false;
	},
	isExistOption : function(name, item) {
		var items = this.getItems($.cookie(name));
		if (!items) {
			return false;
		} else {
			return $.inArray(item, items) != -1;
		}
	},

	setCookie : function(name, value) {
		$.cookie(name, value, {
			path : '/',
			expires : 30
		});
	},
	generate : function(data, actionType) {
		switch (data.type) {
		case 'BOOK':
			data.link = pu.core.config.baseUrl + 'document/' + data.id;
			data.coverUrl = pu.core.config.resourceUrl.replace(/{branch}/, ((data.did % 4) + 1)) + 'docs/' + data.did + '/' + data.version + '/'
					+ data.resource + '_m.jpg';
			break;
		case 'DELEGATE':
			data.link = pu.core.config.baseUrl + 'bundle/dispatch/' + data.id;
			data.coverUrl = pu.core.config.resourceUrl.replace(/{branch}/, ((data.id % 4) + 1)) + 'bundle/' + data.id + '/' + data.version + '/'
					+ data.resource + '_m.jpg';
			break;
		case 'PERIODICAL':
			data.link = pu.core.config.baseUrl + 'periodical/' + data.id;
			data.coverUrl = pu.core.config.resourceUrl.replace(/{branch}/, ((data.did % 4) + 1)) + 'docs/' + data.did + '/' + data.version + '/'
					+ data.resource + '_m.jpg';
			break;
		case 'COLUMN_SUBSCRIPTION':
			data.link = pu.core.config.baseUrl + 'column/' + data.id;
			data.coverUrl = pu.core.config.resourceUrl.replace(/{branch}/, ((data.bid % 4) + 1)) + 'cols/' + data.bid + '/' + data.version + '/'
					+ data.resource + '_m.jpg';
			break;
		case 'MAGAZINE_SUBSCRIPTION':
			data.link = pu.core.config.baseUrl + 'magazine/subscription/' + data.id;
			data.coverUrl = pu.core.config.resourceUrl.replace(/{branch}/, ((data.bid % 4) + 1)) + 'bundle/' + data.bid + '/' + data.version + '/'
					+ data.resource + '_m.jpg';
			break;
		case 'COMBO':
			break;
		}

		if (data.cover == 'NONE') {
			data.coverUrl = pu.core.config.staticUrl + 'images/thumbnail.jpg';
		}

		switch (parseInt(data.cartItem.option, 10)) {
		case 1:
			data.price = parseInt(data.online, 10);
			data.priceDesc = '線上閱讀';
			break;
		case 3:
			data.price = parseInt(data.online, 10) + parseInt(data.offline, 10);
			data.priceDesc = '電子書下載';
			break;
		}

		if (data.charge) {
			if (actionType == 'tracking') {
				data.actionTypeCss = 'shoppinglist';
				data.moveToCss = 'js-tracking-moveto-cart';
				data.moveDesc = '移至購書清單';
				data.deleteItemCss = 'js-tracking-delete';
			} else {
				data.actionTypeCss = 'wishlist';
				data.moveToCss = 'js-cart-moveto-tracking';
				data.moveDesc = '移至追蹤清單';
				data.deleteItemCss = 'js-cart-delete';
			}
		}
		return $('#carItem').tmpl(data);
	},
	getOption : function(evt) {
		return this.getItem($(evt.currentTarget).attr('alt'));
	},

	getItems : function(str) {
		if (!str) {
			return null;
		}
		str = str.replace(/'/g, '');
		if (!str) {
			return null;
		}
		var items = [];
		var strItems = str.split(';');
		var cnt = 0;
		for ( var i = 0; i < strItems.length; i++) {
			var item = this.getItem(strItems[i]);
			if (item) {
				items[cnt++] = item;
			}
		}
		return items;

	},
	getItemByPid : function(name, pid) {
		var items = this.getItems($.cookie(name));
		for ( var i = 0; i < items.length; i++) {
			if (items[i].id == pid) {
				return items[i];
			}
		}
		return null;

	},
	getItem : function(str) {
		if (!str) {
			return null;
		}
		var slices = str.split(',');
		if (slices.length != 3) {
			return null;
		}
		var item = new CartItem();
		item.id = slices[0];
		item.type = slices[1];
		item.option = slices[2];
		return item;
	},
	showOption : function(item, callback, evt) {
		if (item.option == 3 && item.type != 1 && item.type != 4) {
			var target = $(evt.currentTarget);
			if (target.hasClass('downloadOption')) {
				callback(item);
				return;
			}
			$('<div id="dialog" />').insertAfter(target);
			$("#dialog").dialog({
				title : '請選擇版本',
				width : 300,
				height : 0,
				buttons : {
					'電子書下載' : function() {
						callback(item);
						$(this).dialog('close');
					},
					'線上閱讀' : function() {
						item.option = 1;
						callback(item);
						$(this).dialog('close');
					}
				},
				close : function() {
					$("#dialog").remove();
				}
			});
		} else {
			callback(item);
		}

	},
	handler : {
		addTracking : function(evt) {
			var item = pu.modules.cart.getOption(evt);
			if (!pu.modules.cart.isExistPid('tracking', item.id)) {
				$.post(pu.core.config.baseUrl + 'product/tracking', {
					id : item.id
				}, function(data) {
					data.cartItem = item;
					pu.modules.cart.setCookie('tracking', pu.modules.cart.addItem('tracking', item));
					$(evt.currentTarget).trigger('trackingAdded', data);
				});
			} else {
				alert('此商品已在追蹤清單');
			}
		},

		addCart : function(evt) {
			var item = pu.modules.cart.getOption(evt);
			var callback = function(item) {
				pu.modules.cart.setCookie('cart', pu.modules.cart.addItem('cart', item));
				$.get(pu.core.config.baseUrl + 'product/' + item.id, {}, function(data) {
					data.cartItem = item;
					$(evt.currentTarget).trigger('cartReplaced', item).trigger('cartAdded', data);
				});
			};
			pu.modules.cart.showOption(item, callback, evt);

		},
		moveToCart : function(evt) {
			var item = pu.modules.cart.getOption(evt);

			var callback = function(item) {
				$.post(pu.core.config.baseUrl + 'product/tracking/' + item.id + '/move', function(data) {
					data.cartItem = item;
					pu.modules.cart.setCookie('tracking', pu.modules.cart.removeItem('tracking', item));
					pu.modules.cart.setCookie('cart', pu.modules.cart.addItem('cart', item));
					$(evt.currentTarget).trigger('cartReplaced', item).trigger('cartAdded', data).trigger('trackingDeleted');
					// $(evt.currentTarget).trigger('cartDeleted',
					// data).trigger('cartAdded', data);
				});
			};
			pu.modules.cart.showOption(item, callback, evt);

		},
		moveToTracking : function(evt) {
			var item = pu.modules.cart.getOption(evt);
			if (!pu.modules.cart.isExistPid('tracking', item.id)) {
				$.post(pu.core.config.baseUrl + 'product/tracking', {
					id : item.id
				}, function(data) {
					data.cartItem = item;
					pu.modules.cart.setCookie('tracking', pu.modules.cart.addItem('tracking', item));
					pu.modules.cart.setCookie('cart', pu.modules.cart.removeItem('cart', item));
					$(evt.currentTarget).trigger('cartMoved').trigger('trackingAdded', data).trigger('cartDeleted');
				});
			} else {
				pu.modules.cart.setCookie('cart', pu.modules.cart.removeItem('cart', item));
				$(evt.currentTarget).trigger('cartDeleted');
			}
		},
		deleteTracking : function(evt) {
			var item = pu.modules.cart.getOption(evt);
			$.post(pu.core.config.baseUrl + 'product/tracking/' + item.id, {
				_method : 'DELETE'
			}, function(data) {
				pu.modules.cart.setCookie('tracking', pu.modules.cart.removeItem('tracking', item));
				$(evt.currentTarget).trigger('trackingDeleted');
			});
		},
		deleteCart : function(evt) {
			var item = pu.modules.cart.getOption(evt);
			pu.modules.cart.setCookie('cart', pu.modules.cart.removeItem('cart', item));
			$(evt.currentTarget).trigger('cartDeleted');
		},
		arrangeBookshelf : function(evt) {
			var object = $(this).attr('alt').split(',');
			$.post(pu.core.config.baseUrl + 'library', {
				id : object[0]
			}, function(code) {
				switch (code) {
				case pCommonConst.SUCCESS:
					alert('加入書櫃完成');

					$('button.js-bookshelf-add, #try-read').hide();
					$('#product-comment>.post, #all-read, #js-comment').show();
					if ($('cite.fc-r').size() === 0) {
						$('#download-read').show();
					}
					if ($('.pro-chief-box .rating-stars')) {
						pu.modules.product.addRatingLink();
					}
					break;
				case pCommonConst.BLOCKED:
					alert("無加入權限");
					break;
				case pCommonConst.EXISTED:
					alert('這本書已經在您書櫃中囉!');
					break;
				case pCommonConst.UNKONWN_ERROR:
					alert('系統維護中');
					break;
				}
			});
		},
		snapShoppingCartToBottom : function(evt) {
			var cartHeight = $('#cart-slide').height();

			if (evt.type == 'tabsselect') {
				if ($('#cart-slide').tabs('option', 'selected') != -1) {
					cartHeight = 25;
				}
			}

			var topPosition = 0;
			var topOffset = 0;
			if ($.browser.mobileSafari || ($.browser.msie && $.browser.version <= 6)) {
				// Ticket #6724 (pending bug) :wrong $(window).height() in
				// mobile safari (iphone)
				// http://bugs.jquery.com/ticket/6724
				topOffset = $(window).scrollTop() + (window.innerHeight ? window.innerHeight : $(window).height()) - cartHeight;
			} else {
				topOffset = $(window).height() - cartHeight;
			}
			$('#cart-slide').css('top', topOffset);
		}

	},
	attachEvent : function() {
		$(':button.js-tracking-delete.unattached').click(pu.modules.cart.handler.deleteTracking).removeClass('unattached');
		$(':button.js-tracking-moveto-cart.unattached').click(pu.modules.cart.handler.moveToCart).removeClass('unattached');
		$(':button.js-cart-delete.unattached').click(pu.modules.cart.handler.deleteCart).removeClass('unattached');
		$(':button.js-cart-moveto-tracking.unattached').click(pu.modules.cart.handler.moveToTracking).removeClass('unattached');
	}
};

pu.modules.reader = {
	init : function() {
		$(':button.js-launch-reader, img.js-launch-reader, a.js-launch-reader, div.js-launch-reader')
				.bind('click', pu.modules.reader.handler.startup);
	},
	launch : function(pid, docId, pageId) {
		if (navigator.userAgent.indexOf("iPhone") != -1 || navigator.userAgent.indexOf("iPad") != -1 || navigator.userAgent.indexOf("iPod") != -1) {
			if (window.location.pathname.indexOf("/bookbuffet/") != -1) {
				alert("iOS裝置不支援Pubu電子書城的線上閱讀功能，您可至AppSore下載Pubu電子書城專屬App\"飽讀電子書\"進行閱讀!");
			} else {
				alert("iOS裝置不支援Pubu電子書城的線上閱讀功能，您可至AppSore下載Pubu電子書城專屬App\"iPubu電子書\"進行閱讀!");	
			}
			
			return false;
		}
		
		$('<div id="reader-container"><div style="width: 100%; height: 100%"><div id="reader" /></div></div>').appendTo('body');
		var flashvars = {};
		flashvars.pid = pid;
		flashvars.docId = docId;
		if (pageId) {
			flashvars.pageId = pageId;
		}

		flashvars.host = pu.core.config.apiUrl;
		flashvars.apiHost = pu.core.config.apiUrl;
		flashvars.sslHost = pu.core.config.secureApiUrl;

		var params = {};
		params.quality = 'high';
		params.bgcolor = '#ffffff';
		params.allowfullscreen = 'true';
		params.allowscriptaccess = 'always';
		params.allownetworking = 'all';
		params.wmode = "opaque";
		var attributes = {};
		attributes.align = 'middle';
		$('#reader-container').show();
		$('body').css('overflow', 'hidden');
		swfobject.embedSWF(pu.core.config.staticUrl + 'reader/' + pu.core.config.readerVersion + '/pubu.swf', 'reader', '100%', '100%', '10.1',
				pu.core.config.staticUrl + 'images/expressInstall.swf', flashvars, params, attributes);
		pu.utils.session.poll();
	},
	getPid : function(evt) {
		return $(evt.target).attr('alt').split(',')[0];
	},
	getDid : function(evt) {
		return $(evt.target).attr('alt').split(',')[1];
	},
	handler : {
		startup : function(evt) {
			var idArray = $(evt.target).attr('alt').split(',');
			if (pu.core.auth.isLogged() && idArray.length == 3) {
				$.get(pu.core.config.apiUrl + '/docs/' + idArray[1] + '/progress?pid=' + idArray[0], function(pageId) {
					if (pageId == -1) {
						pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
					} else {
						pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt), pageId);
					}
				});
			} else {
				pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
			}
			return false;
		}
	},
	dispose : function(pageId, pid) {
		$('body').css('overflow', 'auto');
		$('#reader-container').remove();
		if (pu.modules.user.isLogged()) {
			if (pid !== undefined) {
				if (pageId !== undefined) {
					$.post(pu.core.config.apiUrl + '/pages/' + pageId + '/remember', {
						pid : pid
					});
				}
			} else if (pageId !== undefined) {
				$.post(pu.core.config.apiUrl + '/pages/' + pageId + '/remember');
			}
		}
	}

};

pu.modules.rating = {
	init : function() {
		$('#pro-rating-link').click(function() {
			$('.star-rating-live').click(function(){
				$('#comment-submit').attr('disabled','').removeClass('ui-state-disabled').show();
			});
			
			$('#pro-rating-panel').dialog({
				autoOpen : true,
				width : 560,
				buttons : [
					{
						id : "comment-submit",
						text : "送出",
						disabled : "disabled",
						click : function() {
							var pid = $('meta[name=pid]').attr('content');
							var star = $('.star-rating-on').size();
							// submit rating...
							$.post('/product/' + pid + '/rating', {
								value : star
							}, function(data) {
								switch (data.common) {
								case pCommonConst.SUCCESS:
									$('#pro-rating-link').remove();

									// submit comment ...
									if ($('#message2').val().length > 0) {
										$('#commentMessage').val($('#message2').val());
										$('#commentForm').submit();
									} else {
										$('.product-rating>dd').attr('style', 'width: ' + data.ratingAvg * 20 + '%;');
										$('.sum-rating').text(data.ratingAvg + '分，共' + data.ratingCount + '人評分。');
									}
									$('#pro-rating-panel').dialog("close");
									alert("新增評價成功");
									break;
								case pCommonConst.BLOCKED:
									alert("無評價權限");
									break;
								case pCommonConst.EXISTED:
									alert('已評價');
									break;
								case pCommonConst.SELF:
									alert("賣家無投票權限");
									break;
								default:
									alert('系統維護中');
									break;
								}
							});
						}
					},
					{
						id : "cancel",
						text : "取消",
						click : function() {
							$(this).dialog("close");
						}
					}
				]
			});

			if ($('.star-rating-on').size() > 0) {
				$('#comment-submit').attr('disabled','').removeClass('ui-state-disabled').show();
			}
			
			return false;
		});
	}
};

pu.modules.product = {
	pMode : '',
	init : function(mode) {
		pu.modules.product.pMode = mode;
		switch (mode) {
		case 'document':
			$('body').bind('productDeleted productPublished productUnpublished productSetRepublish', function(evt) {
				pu.utils.window.reload();
			});
			$('.js-remove').click(this.handler.remove);
			$('.js-unpublish').click(this.handler.unpublish);
			$('.js-publish').click(this.handler.publish);
			$('.js-setRepublish').click(this.handler.setRepublish);

			break;
		case 'subscription_magazine':
			$('body').bind('productDeleted productPublished productUnpublished productSetRepublish', function(evt) {
				pu.utils.window.reload();
			});
			$('.js-remove').click(this.handler.remove);
			$('.js-unpublish').click(this.handler.unpublish);
			$('.js-publish').click(this.handler.publish);
			$('.js-setRepublish').click(this.handler.setRepublish);

			break;
		case 'column':
			$('.js-remove').click(this.handler.remove);
			$('.js-unpublish').click(this.handler.unpublish);
			$('.js-publish').click(this.handler.publish);
			$('.js-setRepublish').click(this.handler.setRepublish);
			break;
		}
	},
	getPid : function(evt) {
		switch (pu.modules.product.pMode) {
		case 'document':
			return $(evt.currentTarget).parents('tr').attr('id');
		case 'subscription_magazine':
			return $(evt.currentTarget).parents('tr').attr('id');
		case 'column':
			return $(evt.currentTarget).attr('alt');
		}
	},
	addRatingLink : function() {
		$('strong.sum-rating').parent().append('<a class="link" href="#" id="pro-rating-link">我要評分</a>');
		pu.modules.rating.init();
	},

	isPurchasable : function(pid) {
		var isPurchasable = false;
		jQuery.ajax({
			url : '/product/' + pid + '/purchasable',
			success : function(result) {
				isPurchasable = result;
			},
			async : false
		});
		return isPurchasable;
	},
	handler : {
		remove : function(evt) {
			var pid = pu.modules.product.getPid(evt);
			if (confirm('刪除後不可回復，是否確定刪除？')) {
				$.post('/product/' + pid + '/remove', {
					_method : "DELETE"
				}, function() {
					$(evt.currentTarget).trigger('productDeleted', evt);
				});
			}
			return false;
		},
		publish : function(evt) {
			var pid = pu.modules.product.getPid(evt);
			$.post('/product/' + pid + '/publish', {}, function(data) {
				if (data) {
					$(evt.currentTarget).trigger('productPublished', evt);
				}
			});
			return false;

		},
		unpublish : function(evt, cnt) {
			var pid = pu.modules.product.getPid(evt);
			$.post('/product/' + pid + '/unpublish', {
				cnt : cnt
			}, function() {
				$(evt.currentTarget).trigger('productUnpublished', evt);
			});
			return false;
		},
		setRepublish : function(evt) {
			var cnt = $(evt.currentTarget).parent().prev().val();
			if (!isNaN(cnt)) {
				var pid = pu.modules.product.getPid(evt);
				$.post('/product/' + pid + '/countOfRepublish', {
					cnt : cnt
				}, function() {
					$(evt.currentTarget).trigger('productSetRepublish', evt);
				});
			}
			return false;
		}
	}

};

pu.modules.bankAccount = {
	init : function(mode) {
		switch (mode) {
		case 'independence':
			break;

		case 'dependence':
			$('#manage-account-link').click(function() {
				$('#manage-account-panel').dialog({
					autoOpen : true,
					width : 560,
					buttons : {
						"關閉" : function() {
							$(this).dialog("close");
						}
					}
				});
				return false;
			});
			$('#bankAccount').change(function() {
				$('input[name="bankAccount"]').val($('#bankAccount').val());
			});
			$("#applyWithdrawal").validate({
				errorElement : "cite",
				errorClass : "error",
				rules : {
					bankAccount : "required"
				},
				errorPlacement : function(error, element) {
					error.insertAfter(element);
					pu.utils.window.scrollTo(element);
				}
			});
			break;
		}
		pu.utils.form.init();
		pu.utils.form.setPlaceHolder();
		this.resetSeqNo();
		$("#manage-account").validate({
			errorElement : "cite",
			errorClass : "error",
			rules : {
				bankCode : {
					required : true,
					maxlength : 3
				},
				number : {
					required : function(element) {
						if ($(element).val() == "轉入帳號") {
							$(element).val("");
						}
						return true;
					},
					maxlength : 16
				},
				description : {
					maxlength : 20
				},
				branchBank : {
					maxlength : 10
				},
				accountName : {
					maxlength : 20
				}
			},
			errorPlacement : function(error, element) {
				error.insertAfter(element);
				pu.utils.window.scrollTo(element);
			}
		});
		$('input.js-saveOrUpdate').click(pu.modules.bankAccount.handler.addBankAccount);
		$('a.js-delete').click(pu.modules.bankAccount.handler.removeBankAccount);
		$('a.js-update').click(pu.modules.bankAccount.handler.updateBankAccount);
	},
	resetSeqNo : function() {
		$('.no').each(function(n, item) {
			$(item).text(n + 1);
		});
	},
	resetForm : function() {
		$('#manage-account')[0].reset();
		$('#identity').val("");
	},
	attachEvent : function() {
		$('a.js-delete.unattached').click(pu.modules.bankAccount.handler.removeBankAccount).removeClass('unattached');
		$('a.js-update.unattached').click(pu.modules.bankAccount.handler.updateBankAccount).removeClass('unattached');
		pu.modules.bankAccount.resetSeqNo();

	},
	handler : {
		addBankAccount : function(evt) {
			if (!$('#manage-account').valid()) {
				return;
			}
			var identity = $('#identity').val();
			if (!identity) {
				$.post('/user/bank-account', {
					'bankCode' : $('#bankCode').val(),
					'number' : $('#number').val(),
					'description' : $('#description').val(),
					'branchBank' : $('#branchBank').val(),
					'accountName' : $('#accountName').val()
				}, function(data) {
					if (data) {
						$('#bankAccountTPL').tmpl(data).appendTo('#bankAccountList');
						$('#shortAccountTPL').tmpl(data).appendTo('#bankAccount');
						pu.modules.bankAccount.resetForm();
						pu.modules.bankAccount.attachEvent();
						$('#bankAccount').change();
					}
				});
			} else {
				var element = {
					_method : "PUT",
					'id' : identity,
					'bankCode' : $('#bankCode').val(),
					'number' : $('#number').val(),
					'description' : $('#description').val(),
					'branchBank' : $('#branchBank').val(),
					'accountName' : $('#accountName').val()
				};
				$.post('/user/bank-account/' + identity, element, function(data) {
					if (data) {
						$('tr[alt=' + identity + ']').replaceWith($('#bankAccountTPL').tmpl(element));
						$('#bankAccount_' + identity).replaceWith($('#shortAccountTPL').tmpl(element));
						pu.modules.bankAccount.resetForm();
						pu.modules.bankAccount.attachEvent();
						$('#bankAccount').change();
					}
				});
			}
			return false;
		},
		removeBankAccount : function(evt) {
			var aid = $(evt.target).parents('tr').attr('alt');
			$.post('/user/bank-account/' + aid, {
				_method : "DELETE"
			}, function(code) {
				if (code == pCommonConst.SUCCESS) {
					$('tr[alt=' + aid + ']').slideUp('slow').remove();
					$('#bankAccount_' + aid).remove();
					pu.modules.bankAccount.resetSeqNo();
					$('#bankAccount').change();
				} else {
					alert(pCommonMessage.getMessage(code));
				}

			});
			return false;
		},
		updateBankAccount : function(evt) {
			var bankAccount = $(evt.target).parent().prev().prev().text().split('-');
			$('#bankCode').val(bankAccount[0]);
			$('#number').val(bankAccount[1]);
			$('#description').val($(evt.target).parent().prev().text());
			$('#branchBank').val($(evt.target).parent().next().text());
			$('#accountName').val($(evt.target).parent().next().next().text());
			$('#identity').val($(evt.target).parents('tr').attr('alt'));
			$('#bankAccount').change();
			pu.utils.window.scrollTo('manage-account');
			return false;
		}
	}
};

pu.modules.invoice = {
	init : function() {
		switch ($('#defaultMode').val()) {
		case 'NON_NECESSARY':
			$('#form1').show();
			$('#option1').attr('checked', true);
			break;
		case 'NECESSARY':
			$('#NECESSARY').show();
			$('#form2').parent().show();
			$('#option2').attr('checked', true);
			$('#option2-1').attr('checked', true);
			break;
		case 'NECESSARY_WITH_UN':
			$('#NECESSARY').show();
			$('#form3').parent().show();
			$('#option2-1').attr('checked', true);
			$('#option2-2').attr('checked', true);

			break;
		}
		$('input[name="option"]').change(function(evt) {
			var target = $(evt.target);
			if (target.val() == "NECESSARY") {
				$('#form1').parent().hide();
				$('#NECESSARY').show();
			} else {
				$('#form1').parent().show();
				$('#NECESSARY').hide();
			}
		});
		$('input[name="mode"]').change(function(evt) {
			var target = $(evt.target);
			if (target.val() == "NECESSARY") {
				$('#form2').parent().show();
				$('#form3').parent().hide();
			} else {
				$('#form2').parent().hide();
				$('#form3').parent().show();
			}
		});
		$('input.js-submit').click(function(evt) {
			var submitForm;
			if ($('input[name="option"]').val() == 'NON_NECESSARY') {
				submitForm = $('#form1');
			} else {
				if ($('input[name="mode"]').val() == 'NECESSARY') {
					submitForm = $('#form2');
				} else {
					submitForm = $('#form3');
				}
			}
			submitForm.submit();
		});

		$('input.js-cancel').click(function(evt) {
			pu.utils.window.back();
		});

		$('#form1, #form2').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				recipient : 'required',
				postCode : {
					required : true,
					minlength : 3
				},
				address : 'required'
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				form.submit();
			}
		});
		$('#form3').validate({
			errorClass : "error",
			errorElement : "cite",
			rules : {
				recipient : 'required',
				postCode : {
					required : true,
					minlength : 3
				},
				address : 'required',
				uniSN : {
					required : true,
					minlength : 8
				}
			},
			errorPlacement : function(error, element) {
				error.appendTo(element.parent());
			},
			submitHandler : function(form) {
				form.submit();
			}
		});
	}
};

pu.modules.advertisement = {
	init : function() {
		$('.js-buy-marketplace, .js-buy-feature-first, .js-buy-highlight, .js-buy-style-text').click(this.handler.buyAdvertisement);
		// $('.js-buy-keyword').click()
	},
	getPid : function(evt) {
		return $(evt.currentTarget).parents('tr').attr('alt');
	},
	handler : {
		buyAdvertisement : function(evt) {
			var pid = pu.advertisement.getPid(evt);
			var adType = $(evt.target).attr('alt');
			pu.utils.window.redirect(pu.core.config.siteUrl + 'advertisement/' + adType + '/checkout/' + pid);
		}
	}
};

pu.modules.banner = {
	show : function(list) {
		var round = Math.round(Math.random() * 100);
		var postions = list.split(",");
		$(postions).each(function(n, postion) {
			var banners = $("." + postion);
			$(banners[round % banners.length]).toggleClass('banner-hide');
		});
	},

	/*
	 * 浮動廣告 obj=廣告Element posX=顯示位置X posY=顯示位置Y
	 */
	floatingBanner : function(obj, posX, posY) {
		if (null != $(obj) && $(obj).length > 0 && $(obj).find("img").width() > 0) {
			$(obj).css({
				'z-index' : '100',
				'display' : 'none',
				'left' : posX,
				'top' : posY
			});

			$(obj).makeFloating({
				position : {
					x : posX,
					y : posY
				}
			});
		}
	}
};

pu.modules.porn = {
	init : function() {
		$(".agree-porn").attr("href", window.location.href);
		$('.agree-porn').click(function() {
			$.cookie('agree-porn', true, {
				path : '/',
				expires : '-1'
			});
		});
	}
};

pu.modules.subscription = {
	init : function() {
		$('.js-unSubscription').click(this.handler.unSubscription);
	},
	handler : {
		unSubscription : function(evt) {
			var deliveryId = $(evt.target).parent().parent().attr('id');
			$.post('/magazine/subscription/' + deliveryId, {
				_method : "DELETE"
			}, function(code) {
				if (code == pCommonConst.SUCCESS) {
					$('#' + deliveryId).slideUp('slow').remove();
				} else {
					alert('取消訂閱失敗');
				}
			});
			return false;
		}
	}
}

/**
 * 飽讀專用模組
 */
pu.modules.bookbuffet = {
	init : function() {
		$('.js-bookbuffet-bookshelf-add').click(this.handler.arrangeBookshelf);
	},
	handler : {
		arrangeBookshelf : function(evt) {
			log('arrangeBookshelf');
			var object = $(this).attr('alt').split(',');
			$.post(pu.core.config.bookbuffet + 'library', {
				id : object[0]
			}, function(code) {
				switch (code) {
				case pCommonConst.SUCCESS:
					alert('加入書櫃完成');
					break;
				case pCommonConst.BLOCKED:
					alert("立即成為Pubu飽讀會員看千本電子書+電子雜誌!");
					pu.utils.window.redirect(pu.core.config.bookbuffet + 'checkout');
					pu
					break;
				case pCommonConst.EXISTED:
					alert('這本書已經在您書櫃中囉!');
					break;
				case pCommonConst.UNKONWN_ERROR:
					alert('系統維護中');
					break;
				}
			});
			return false;
		},
		arrangeBookshelf2 : function(evt, idArray) {
			log('arrangeBookshelf2, id:' +  idArray[0]);
			$.post(pu.core.config.bookbuffet + 'library', {
				id : idArray[0]
			}, function(code) {
				switch (code) {
				case pCommonConst.SUCCESS:
					alert('加入書櫃完成');
					break;
				case pCommonConst.BLOCKED:
					alert("立即成為Pubu飽讀會員看千本電子書+電子雜誌!");
					pu.utils.window.redirect(pu.core.config.bookbuffet + 'checkout');
					pu
					break;
				case pCommonConst.EXISTED:
					alert('這本書已經在您書櫃中囉!');
					break;
				case pCommonConst.UNKONWN_ERROR:
					alert('系統維護中');
					break;
				}
			});
			return false;
		},
		arrangeBookshelf3 : function(evt) {
			log('arrangeBookshelf3');
			var $the =  $(this);
			var idArray = $(this).attr('alt').split(',');
			if(idArray[2] == "true" && $.cookie('agree-porn') != "true") {
				log('1-1');
				pu.modules.bookbuffet.handler.pornDialog(evt, function(evt) {
					log('1-1-1');
					if(pu.core.auth.isLogged()) {
						log('1-1-2');
						pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
					} else {
						log('1-1-3');
						$(window).queue('login', function() {
							pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
							return false;
						});
						$('#login-panel').dialog('open');
					}
				});
			} else {
				log('1-2');
				if(pu.core.auth.isLogged()) {
					log('1-2-1');
					pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
				} else {
					log('1-2-2');
					$(window).queue('login', function() {
						pu.modules.bookbuffet.handler.arrangeBookshelf2(evt, idArray);
						return false;
					});
					$('#login-panel').dialog('open');
				}
			}
			return false;
		},
		arrangeBookshelfCallback : function(evt, idArray, callbackFun) {
			$.post(pu.core.config.bookbuffet + 'library', {
				id : idArray[0]
			}, function(code) {
				switch (code) {
				case pCommonConst.SUCCESS:
				case pCommonConst.EXISTED:
					callbackFun(evt);
					break;
				case pCommonConst.BLOCKED:
					alert("無加入權限");
					break;;
				case pCommonConst.UNKONWN_ERROR:
					alert('系統維護中');
					break;
				}
			});
		},
		pornDialog : function(evt, agreeFun) {
			$("#dialog-confirm").dialog({
				resizable: false,
				height:200,
				width: 340,
				modal: true,
				open: function() {
				      $(this).parents('.ui-dialog-buttonpane button:eq(1)').focus(); 
				},
				buttons: {
					"我已滿18歲": function() {
						$(this).dialog("close");
						$.cookie('agree-porn', true, {
							path : '/',
							expires : '-1'
						});
						
						agreeFun(evt);
					},
					"我未滿18歲": function() {
						$(this).dialog("close");
					}
				}
			});
		},
		pornReader : function(evt, idArray) {
			if (pu.core.auth.isLogged() && idArray.length == 4) {
				$.get(pu.core.config.apiUrl + '/docs/' + idArray[1] + '/progress?pid=' + idArray[0], function(pageId) {
					if (pageId == -1) {
						pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
					} else {
						pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt), pageId);
					}
				});
			} else {
				pu.modules.reader.launch(pu.modules.reader.getPid(evt), pu.modules.reader.getDid(evt));
			}
		}

	},
	updateDocPage: function() {
		if (pu.modules.user.isLogged()) {
			if (pu.modules.user.isCorporation()) {
				$("#btn-try").show();
				$("#btn-join").hide();
				$("#btn-read").hide();
				$("#btn-add").hide();
			} else if (pu.modules.user.isBookbuffet()) {
				$("#btn-join").hide();

				$.getJSON(pu.core.config.bookbuffet + 'product/' + $("#pid").val() + '/permission', function(data) {			
					if (data.corporation) {
						$("#btn-add").show();
						$("#btn-read").show();
						$("#btn-try").hide();
						return;
					}
					if (data.owner) {
						$("#btn-add").show();
						$("#btn-read").show();
						$("#btn-try").hide();
						return;
					}
					if (data.bookshelf) {
						$("#btn-add").hide();
						$("#btn-read").show();
						$("#btn-try").hide();
						
						if (data.rating) {
							$('head').append('<meta name="pid" content="' + $("#pid").val() + '" />');
							pu.modules.product.addRatingLink();
						}
						
						$('#pro-thumb-img').attr("alt", $('#pro-thumb-img').attr("alt") + ",true");
					} else {
						$("#btn-add").show();
						$("#btn-read").show();
						$("#btn-try").hide();
					}
				});
			} else {
				$("#btn-try").show();
				$("#btn-join").show();
				$("#btn-read").hide();
				$("#btn-add").hide();
			}
		} else {
			$("#btn-try").show();
			$("#btn-join").show();
			$("#btn-read").hide();
			$("#btn-add").hide();
		}
	},
	updateSearchListPage: function() {
		$adds = $("a[name=btn-add]");
		$reads = $("a[name=btn-read]");
		$tries = $("a[name=btn-try]");
		$pids = $("input[name=pid]");
		
		if (pu.modules.user.isLogged()) {
			if (pu.modules.user.isCorporation()) {
				$adds.hide();
				$reads.hide();
				$tries.show();
			} else if (pu.modules.user.isBookbuffet()) {		
				var fields = $pids.serializeArray();
			    var pids = "";
			    jQuery.each(fields, function(i, field){
			    	pids +=field.value + ",";
			    });
			    pids = pids.substring(0, pids.length-1);
			    $.ajax({
			    	  	url: pu.core.config.bookbuffet + "product/permissions",
						type: "POST",
						data: "pids=" + pids,
						dataType: "json",
						success: function(data){
							for(var i = 0; i < data.length; i++) {
								if (data[i].corporation) {
									$reads.show();
									$tries.hide();
								} else if (data[i].owner) {
									$reads.show();
									$tries.hide();
								} else {
									if (data[i].bookshelf) {
										$reads.show();
										$tries.hide();
									} else {
										$reads.show();
										$tries.hide();
									}
								}
							}
						}
			    });
			} else {
				$tries.show();
				$reads.hide();
			}
		} else {
			$tries.show();
			$reads.hide();
		}
	},
	setSearchResultSelectorMode : function(mode) {
		$.cookie("bookbuffet-search-result-selector-mode", mode, {
			path : '/',
			expires : '3'
		});
	},
	getSearchResultSelectorMode : function() {
		if ($.cookie("bookbuffet-search-result-selector-mode") != null) {
			return $.cookie("bookbuffet-search-result-selector-mode");
		} else {
			return "mixed-view";
		}
	}
}

/**
 * 列印模組
 * 
 * @author alin.liou
 */
pu.modules.print = {
	printScreen : function(divBlockId) {
		// log('printScreen');
		var value = $('.' + divBlockId).html();
		log(value);
		var printPage = window.open("", "printPage", "");
		printPage.document.open();
		printPage.document.write("<HTML><head></head><BODY onload='window.print();window.close()'>");
		printPage.document.write("<PRE>");
		printPage.document.write(value);
		printPage.document.write("</PRE>");
		printPage.document.close("</BODY></HTML>");
	}
}

/**
 * 管理iPubu註冊裝置模組
 * 
 * @author alin.liou
 */
pu.modules.device = {
	init : function() {
		$('.js-delete').click(this.handler.deleteDevice);
	},
	handler : {
		deleteDevice : function(evt) {
			// log('pu.modules.device.deleteDevice');
			if (confirm('移除該裝置後您將不能夠使用該裝置登入iPubu閱讀電子書，確定移除?')) {
				var deviceId = $(evt.currentTarget).attr('code');
				$.post('/device/' + deviceId, {
					_method : 'DELETE'
				}, function(data) {
					$(evt.target).parentsUntil('tr').parent().remove();
				});
			}
			return false;
		}
	}	
}

// 付款模組
pu.modules.checkout = {
	init : function(mode, step) {
		var checkout = pu.modules.checkout;
		pu.utils.form.init();
		
		switch (mode) {
		case 'mobile': // 行動裝置
			break;
		case 'bookbuffet': // 飽讀
			switch (step) {
			case 'step1':
				pu.modules.user.temporaryTokenLogin($('#userId').html(), $('#accessToken').html());
				$('#charging li').click(this.handler._chooseBookbuffetProduct);
				$('#js-charging-button').click(this.handler._confirmBookbuffetProduct);
				break;
			case 'step2':
				$('.payment-detail-info').hide();
				$('#balance-tr').show();
				
				var bpId = this._getBookbuffetProductId();
				pu.utils.form.init();
				this._initInvoicelistForm();
				this._initBookbuffetPaymentMethod(bpId);
				this._getBookbuffetPaymentMethod();
				
				$('#shippingMode').click(this.handler._clickShippingMode);
				$('#showUniSNForm').click(this.handler._clickShowUniSNForm);
				$('.payment-method').click(this.handler._chooseBookbuffetPaymentMethod);
				$(':submit.payment-select').click(this.handler._confirmBookbuffetPayment);
				pu.utils.session.poll();
				break;
			}
			break;
		case 'main': // 主站
			$('.payment-detail-info').hide();
			$('.from-shopping-list th.no').each(function(n, item) { $(item).text(n + 1); });
			pu.utils.form.init();
			this._initInvoicelistForm();
			this._getRetailPaymentMethod();
			
			$('.payment-method').click(this.handler._chooseRetailPaymentMethod);
			$('#shippingMode').click(this.handler._clickShippingMode);
			$('#showUniSNForm').click(this.handler._clickShowUniSNForm);
			$('#acknowledged').click(this.handler._clickAcknowledged);
			$(':submit.payment-select').click(this.handler._confirmRetailPaymentButton);
			pu.utils.session.poll();
			break;
		}
	},
	/* 初始值預設付款方式(假如非自動扣款，且帳戶金額大於消費金額，則強制付款非是為帳戶扣款) */
	_initBookbuffetPaymentMethod : function(bpId) {
		log('_initBookbuffetPaymentMethod, bpId=' + bpId);
		
		// TODO: this hard code need modify
		if(bpId == '1') {
			$('#payment-method-type').children().not($('.payment-paypal-subscription')).remove();
		} else {
			$('.payment-paypal-subscription').remove();
			var method = this._getBookbuffetPaymentMethod();
			if(method == 0){
				$('#payment-method-type').hide();
				this._sum(0);
			}
		}
		return false;
	},
	/* 取得零售付款方式 */
	_getRetailPaymentMethod : function() {
		log('_getRetailPaymentMethod');
		var paymentMethod = 0;

		if ($('#payment-method-type .selected').size() > 0) {
			paymentMethod = parseInt($('#payment-method-type .selected').children().attr('alt'));
		}
		return paymentMethod;
	},
	/* 取得飽讀付款方式 */
	_getBookbuffetPaymentMethod : function() {
		log('_getBookbuffetPaymentMethod');
		var evaluateDecreasing = this._getBookbuffetEvaluateDecreasing();				
		var totalPrice = this._getBookbuffetTotalPrice();
		var bpId = this._getBookbuffetProductId();
		log('evaluateDecreasing:' + evaluateDecreasing + ',totalPrice:' + totalPrice + ', bpId:' + bpId);
		// 不是自動扣款 && 帳戶餘額 >= 消費總計
		
		if((bpId != 1) && evaluateDecreasing > 0 && (evaluateDecreasing >= totalPrice)){
			log('使用帳戶扣款');
			return 0;
		}
		if($('.payment-method-typeHover').size() > 0){
			return parseInt($('.payment-method-typeHover').attr('id'));
		}else{
			return -1;
		}
	},
	/* double check user */
	_checkPassword : function(paymentMethod) {
		log('_checkPassword, paymentMethod:' + paymentMethod);
		if (parseInt(paymentMethod) == 4) {
			return this.inputOneClickPaymentPassWord();
		}
		return true;
	},
	_getBookbuffetEvaluateDecreasing : function() {
		// log('_getBookbuffetEvaluateDecreasing');
		if($('#evaluateDecreasing').html()){
			return parseInt($('#evaluateDecreasing').html());
		}else{
			return 0;
		}
	},
	_getBookbuffetTotalPrice : function() {
		// log('_getBookbuffetTotalPrice');
		return parseInt($('#totalPrice').html());
	},
	_postRetailPaymentForm : function(method) {
		// log('_postRetailPaymentForm');
		var postData = $('#shippingInfo').serializeArray();
		
		if(!$('#shippingMode').attr('checked')){
			postData.splice(1,6);
		}
		else if(!$('#showUniSNForm').attr('checked')){
			postData.splice(5,2);
		}
		
		$('select[name="current"] option:selected').each(function(index, value){
			postData.push({name:'currents',value: $(value).val()});
		});
		
		postData.push({name:'method',value:method});
		postData.push({name:'mask',value:$('#maskShopping').attr('checked')});
		
		$.post('/cart/payment/form', postData, function(data) {
			var result = data.substring(0, 1);
			var type = data.substring(2, 3);

			if (data.substring(2, 4) == "10") {
				type = "a";
			}
			
			if (data.substring(2, 4) == "12") {
				type = "b";
			}

			switch (result) {
			case '0':
				alert('交易失敗，請重試');
				break;
			case '1':
				pu.modules.cart.setCookie('cart', '');
				switch (type) {
				case '0':
					window.location = '/order/succeed';
					break;
				case '2':
					var paymentId = data.substring(4, data.length);
					window.location = '/payment/' + paymentId + '/?mark=' + $('#maskShopping').attr('checked');
					break;
				case '1':
				case '3':
				case '4':
				case '8':
				case '9':
				case 'a':
					$('body').append(data.substring(3));
					$('#confirmForm').submit();
					break;
				case '7':
				case 'b':
					$('body').append(data.substring(3));
					$('form:last').submit();
					break;
				}
				break;
			}
			return false;
		});
		return false;
	},
	_postBookbuffetPaymentForm : function(paymentMethod, bpId) {
		log('_postBookbuffetPaymentForm, paymentMethod:' + paymentMethod + ',bpId:' + bpId);
		var method = parseInt(paymentMethod);
		var postData = $('#shippingInfo').serializeArray();
		postData.push({
			name : 'method',
			value : method
		});
		postData.push({
			name : 'bpId',
			value : bpId
		});
		
		$.post(pu.core.config.bookbuffet + 'payment/form', postData, function(data) {
			var result = data.substring(0, 1); // 1
			var type = data.substring(2, 3); // 0
			
            if (data.substring(2,4) == "10") {
                type = "a";
            }
            
            if (data.substring(2,4) == "12") {
                type = "b";
            }
			switch (result) {
			case '0':
				alert('交易失敗，請重試');
				break;
			case '1':
				pu.modules.checkout._setBookbuffetProductId('');
				switch (type) {
				case '0':
					pu.utils.window.redirect(pu.core.config.bookbuffet + 'checkout/success');
					break;
				case '2':
					var paymentId = data.substring(4, data.length);
					pu.utils.window.redirect(pu.core.config.bookbuffet + 'payment/' + paymentId);
					break;
				case '1':
				case '3':
				case '4':
				case '8':
				case '9':
				case 'a':
					$('body').append(data.substring(3));
					$('#confirmForm').submit();
					break;
				case '7':
				case 'b':
					$('body').append(data.substring(3));
					$('form:last').submit();
					break;
				}
				break;
			}
			return false;
		});
		return false;
	},
	_sum : function(paymentMethod) {
		// log('_sum');
		var sumPrice = parseInt($('#totalPrice').html()) + parseInt($('#handleFee').html());
		var balance = $('#evaluateDecreasing').text();
		var evaluateDecreasing = 0;

		if (paymentMethod == 7) {
			sumPrice += parseInt($('#paypal-handleFee').html());
		} else if (paymentMethod == 9) {
			sumPrice += parseInt($('#mmk-handleFee').html());
		} else if (paymentMethod == 10) {
			sumPrice += parseInt($('#alipay-handleFee').html());
		} else if (paymentMethod == 12) {
			sumPrice += parseInt($('#paypal-subscribe-handleFee').html())
		}

		if (balance < sumPrice) {
			evaluateDecreasing = balance;
		} else {
			evaluateDecreasing = sumPrice;
		}
		$('#evaluateDecreasing').text(evaluateDecreasing);
		$('#sum-price').text(sumPrice - evaluateDecreasing);

		if (parseInt($('#sum-price').text()) == 0) {
			$('#payment-method-type').hide();
		}
	},
	/* 初始化 one click payment dialog */
	_initOneClickPaymentPassword : function(paymentMethod) {
		// log('_initOneClickPaymentPassword');
		var method = parseInt(paymentMethod);
		if(method != 4){
			return true;
		}
		
		var checkPassword = false;
		$("#dialog").dialog({
			modal : true,
			title : '請輸入密碼',
			width : 300,
			height : 120,
			buttons : {
				'確定' : function() {
					$.post('/user/password/check', {
						'password' : $('#password').attr('value')
					}, function(data) {
						checkPassword = data;
						if (checkPassword == false) {
							$('#passwordError').remove();
							$('#password').parent().append('<span id="passwordError" style="color: red;">輸入密碼錯誤</span>');
						} else {
							$("#dialog").dialog('close');
						}
					});
				}
			},
			close : function() {
				if (checkPassword == false) {
					$('#passwordError').remove();
				}
				$(this).hide();
			}
		});
		$('#dialog').css('height', '');
		return checkPassword;
	},
	/* 更新_reflashPaymentMethodUI */
	_reflashPaymentMethodUI : function(paymentMethod) {
		// log('_reflashPaymentMethodUI - paymentMethod:' + paymentMethod);
		if (paymentMethod == 7) {
			$('#paypal-handleFee-tr').show();
		} else {
			$('#paypal-handleFee-tr').hide();
		}

		if (paymentMethod == 9) {
			$('#mmk-handleFee-tr').show();
		} else {
			$('#mmk-handleFee-tr').hide();
		}

		if (paymentMethod == 10) {
			$('#alipay-handleFee-tr').show();
		} else {
			$('#alipay-handleFee-tr').hide();
		}
		
		if (paymentMethod == 12 || paymentMethod == 12) {
			$('#paypal-subscribe-handleFee-tr').show();
		} else {
			$('#paypal-subscribe-handleFee-tr').hide();
		}
		
		pu.utils.message.removeAlert($('#acknowledged'));
		pu.utils.message.removeAlert($('.totalPrice'));
		
		return true;
	},
	checkAcknowledged : function() {
		log('checkAcknowledged');
		var target = $('#acknowledged');
		var check = target.attr('checked');
		log('check:' + check);
		if (!check) {
			pu.utils.window.scrollTo(target);
			pu.utils.message.alert(target, false, '請閱讀並勾選"同意電子商務約定條款"', true);
		}
		return check;
	},
	/* 這個應該是用於零售的PaymentMethod檢查 */
	checkPaymentMethod : function() {
		// log('checkPaymentMethod');
		var isChoosePaymentMethod = $('#payment-method-type .selected').size() == 1;
		var isNotNeedChoosePaymentMethod = $('#payment-method-type :visible').size() == 0;
		var check = isChoosePaymentMethod || isNotNeedChoosePaymentMethod;
		if(!check){
			pu.utils.window.scrollTo($('#payment-des'));
			pu.utils.message.alert($('#payment-des'), false, '請選擇"付款方式"', true);
			return false;
		}
		return check;
	},
	/* 檢查是否可用信用卡付款 */
	checkLimitUseCredit : function(paymentMethod) {
		// log('checkLimitUseCredit - paymentMethod:' + paymentMethod);
		var check = (paymentMethod == 4 || paymentMethod == 8) && $('#totalPrice').html() < 20;
		if(check){
			alert('購書未滿50元，恕不提供刷卡服務！');
		}
		return check
	},
	clearAllUI : function() {
		// log('clearAllUI');
		$('.payment-detail-info').hide();

		if ($('#invoicelist')) {
			$('#invoicelist').hide();
		}

		if ($('#payment-method-type .selected')) {
			$('#payment-method-type .selected').attr('class', 'payment-method');
		}
		if ($('#paypal-handleFee-tr')) {
			$('#paypal-handleFee-tr').hide();
		}
		if ($('#shippingMode')) {
			$('#shippingMode').attr('checked', false);
			$('#showUniSNForm').attr('checked', false);
		}
		if ($('#mmk-handleFee-tr')) {
			$('#mmk-handleFee-tr').hide();
		}
		if ($('#alipay-handleFee-tr')) {
			$('#alipay-handleFee-tr').hide();
		}
		if ($('#paypal-subscribe-handleFee-tr')) {
			$('#paypal-subscribe-handleFee-tr').hide();
		}
		
	},
	_setBookbuffetProductId : function(value) {
		$.cookie('bpId', value, {
			path : '/',
			expires : '1'
		});
		return false;
	},
	_getBookbuffetProductId : function() {
		return $.cookie('bpId');
	},
	/* 驗證選取飽讀方案 */
	_verifyStep1 : function(bpId) {
		// log('_verifyStep1');
		if(!pu.core.auth.isLogged()){
			$('#login-panel').dialog('open');
			return false;
		}
		if(pu.modules.user.isCorporation()){
			pu.utils.message.alert($('p'), false, '法人帳號不允許購買', true);
			return false;
		}
		if (!$('#js-sureBuy-checkbox').attr('checked')) {
			pu.utils.message.alert($('p'), false, '請閱讀並勾選"同意電子商務約定條款"', true);
			return false;
		}
		if (bpId == null) {
			pu.utils.message.alert($('p'), false, '請選擇飽讀方案', true);
			return false;
		}
		return true;
	},
	verifyStep2 : function(bpId, paymentMethod, checkPassword) {
		log('verifyStep2');
		var checkout = pu.modules.checkout;
		if(!pu.core.auth.isLogged()){
			$('#login-panel').dialog('open');
			return false;
		}
		if (bpId == '') {
			pu.utils.window.redirect(pu.core.config.bookbuffet + "checkout");
			return false;
		}
		if (paymentMethod == -1) {
			pu.utils.message.alert($('.totalPrice'), false, '請選擇付款方式', true);
			return false;
		}
		return checkout._verifyPayment(checkPassword, paymentMethod);
	},
	/* 驗證確認付款 */
	_verifyPayment : function(checkPassword, paymentMethod, mode) {
		log('_verifyPayment - checkPassword:' + checkPassword + ', paymentMethod:' + paymentMethod);
		
		// 表格填入值驗證
		if ($('#shippingMode').attr('checked')) {
			if (!$('#shippingInfo').valid()) {
				return false;
			}
		}
		switch (mode) {
		case 'bookbuffet':
			if(!this.checkPaymentMethod()){
				return false;
			}
			break;
		case 'main':
			if(!this.checkAcknowledged() || !this.checkPaymentMethod()){
				return false;
			}
			break;
		default:
			break;
		}
		return this._initOneClickPaymentPassword(paymentMethod);
	},
	/* 更新發票區塊顯示 */
	_reflashInvoiceUI : function(shippingMode, showUniSNForm) {
		// log('_reflashInvoiceUI - shippingMode:' + shippingMode + ',
		// showUniSNForm:' + showUniSNForm);
		if (shippingMode && showUniSNForm) {
			$('#invoicelist').show();
			$('.invoiceInfo').show();
		} else if (shippingMode && !showUniSNForm) {
			$('#invoicelist').show();
			$('.invoiceInfo').hide();
		} else {
			$('#invoicelist').hide();
		}
		return true;
	},
	/* 初始化發票Form */
	_initInvoicelistForm : function() {
		// log('initInvoicelistForm');
		
		$.validator.addMethod("needUniSN", function(value, element) {
			if ($('#showUniSNForm').attr('checked')) {
				return value.trim().length > 0;
			}
			return true;
		}, '請輸入此欄位');
		
		$.validator.addMethod("telephoneRule", function(value, element) {
			return (this.optional(element) || /^[0-9\#\-\(\)\ ]+$/.test(value));
		}, "格式有誤");
		
		$("#shippingInfo").validate({
			errorElement : "cite",
			errorClass : "error",
			rules : {
				invoiceTitle : {
					needUniSN : true
				},
				uniSN : {
					needUniSN : true,
					number : true
				},
				recipient : {
					required : true
				},
				postCode : {
					required : true,
					number : true
				},
				address : {
					required : true
				},
				telephone : {
					required : true,
					telephoneRule : true
				}
			},
			errorPlacement : function(error, element) {
				error.insertAfter(element);
				pu.utils.window.scrollTo(element);
			}
		});
	},
	handler : {
		/* 選擇付款方式 (零售) */
		_chooseRetailPaymentMethod : function(evt) {
			// log('_choosePaymentMethodByRetail event');
			var checkout = pu.modules.checkout;	
			var paymentMethod = parseInt($(evt.target).attr('alt'));
			
			if (checkout.checkLimitUseCredit(paymentMethod)) {
				return false;
			}

			$('#payment-method-type .selected').attr('class', 'payment-method');
			$(evt.target).parent().attr('class', 'payment-method selected');

			checkout._sum(paymentMethod);
			checkout._reflashPaymentMethodUI(paymentMethod);
			
			// alin fix me
			checkPassword = checkout._initOneClickPaymentPassword(paymentMethod);
			return false;
		},
		/* 選擇付款方式 (飽讀) */
		_chooseBookbuffetPaymentMethod : function(evt) {
			log('_chooseBookbuffetPaymentMethod event');
			var checkout = pu.modules.checkout;	
			var checkPassword = false;
			var paymentMethod = parseInt(evt.target.id);
			var paymentMethodName = $(evt.target).parent().attr('class');
				
			if (checkout.checkLimitUseCredit(paymentMethod)) {
				return false;
			}
			
			$('.payment-method-typeHover').removeClass('payment-method-typeHover');
			$('.' + paymentMethodName).children().addClass('payment-method-typeHover');
			
			checkout._sum(paymentMethod);
			checkout._reflashPaymentMethodUI(paymentMethod);

			checkPassword = checkout._initOneClickPaymentPassword(paymentMethod);
			checkout._checkPassword(paymentMethod);
			return false;
		},
		/* 決定付款 (零售) */
		_confirmRetailPaymentButton : function(evt) {
			log('_confirmRetailPaymentButton event');
			var checkout = pu.modules.checkout;
			var checkPassword = checkout._initOneClickPaymentPassword(paymentMethod);
			var paymentMethod = checkout._getRetailPaymentMethod();
			var verify = checkout._verifyPayment(checkPassword, paymentMethod, 'main');
			if(verify){
				log('submit success...');
				// lock payment button
				$(this).attr('disabled', 'disabled');
				checkout._postRetailPaymentForm(paymentMethod);
			}
			return false;
		},
		/* 決定付款 (飽讀) */
		_confirmBookbuffetPayment : function(evt) {
			log('_confirmBookbuffetPayment');
			var checkout = pu.modules.checkout;
			var method = checkout._getBookbuffetPaymentMethod();
			var bpId = checkout._getBookbuffetProductId();
			var checkPassword = checkout._checkPassword(method);
			var verify = checkout.verifyStep2(bpId, method, checkPassword);
			if (verify) {
				// lock payment button
				$(this).attr('disabled', 'disabled');
				checkout._postBookbuffetPaymentForm(method, bpId);
			}
			return false;
		},
		/* 選擇飽讀方案 */
		_chooseBookbuffetProduct : function(evt){
			log('_chooseBookbuffetProduct event');
			var checkout = pu.modules.checkout;
			var bpId = evt.currentTarget.id;
			$('.chargingHover').removeClass('chargingHover');
			$('#' + bpId).children().addClass('chargingHover');
			checkout._setBookbuffetProductId(bpId);
			return false;
		},
		/* 確認飽讀方案 */
		_confirmBookbuffetProduct : function(evt){
			log('_confirmBookbuffetProduct event');
			var checkout = pu.modules.checkout;
			var bpId =  checkout._getBookbuffetProductId();
			if (checkout._verifyStep1(bpId)) {
				pu.utils.window.redirect(pu.core.config.bookbuffet + "checkout/step2/" + bpId);
			}
			return false;
		},
		/* tigger 索取電子發票 button */
		_clickShippingMode : function(evt) {
			// log('_clickShippingMode event');
			var checkout = pu.modules.checkout;
			var shippingMode = $(this).attr('checked');
			var showUniSNForm = $('#showUniSNForm').attr('checked');
			checkout._reflashInvoiceUI(shippingMode, showUniSNForm);
		},
		/* tigger 需開立統編 button */
		_clickShowUniSNForm : function(evt) {
			// log('_clickShowUniSNForm event');
			var checkout = pu.modules.checkout;
			if (!$(this).attr('checked')) {
				$('#shippingMode').attr('checked', false);
			}
			var shippingMode = $('#shippingMode').attr('checked');
			var showUniSNForm = $(this).attr('checked')
			checkout._reflashInvoiceUI(shippingMode, showUniSNForm);
		},
		/* tigger 電子商務約定條款 button */
		_clickAcknowledged : function(evt){
			// log('_clickAcknowledged event');
			var checkout = pu.modules.checkout;
			checkout._sum(0);
			var check = $('#acknowledged').attr('checked');
			if (check) {
				pu.utils.message.removeAlert($('#acknowledged'));
				$('.payment-detail-info').show();
				$('#paypal-handleFee-tr').hide();
				$('#mmk-handleFee-tr').hide();
				$('#alipay-handleFee-tr').hide();
			} else {
				checkout.clearAllUI();
				checkout.checkAcknowledged();
			}
			return true;
		}
	}
}

/**
 * parse command
 */
pu.utils.parseCommand = function(str) {
	var ary = str.split('?');
	if (ary.length == 2) {
		return {
			command : ary[0],
			parameter : (function() {
				var ret = {};
				var seg = ary[1].split('&');
				var len = seg.length, i = 0, s;
				for (; i < len; i++) {
					if (!seg[i]) {
						continue;
					}
					var s = seg[i].split('=');
					ret[s[0]] = s[1];
				}

				return ret;
			})()
		};
	}
}

// exception handling
/*
 * window.onerror = function(msg, url, line){ if (!pu.core.logger.debugMode) {
 * pu.core.logger.log(url, line, msg); return true; } }
 */
$(window).ajaxError(function(event, xhr, settings) {
	switch (xhr.status) {
	case 401:
		pu.core.auth._closeAllDialog();
		$('#login-panel').dialog('open');
		break;
	default:
		// pu.core.logger.log(settings.url, xhr.status, xhr.responseText);
	}
});

// call by online reader when closing
var dismissAP = pu.modules.reader.dispose;

// global js entrance point
pu.core.config.init();
/*
 * jQuery Floating Layer Plugin 1.0
 *
 * http://renjin.blogspot.com/2009/07/jquery-floating-layer-plugin.html
 * Author: renjin
 * Date: 2009-7-19
 *
 * Dual licensed under the MIT and GPL licenses:
 *  http://www.opensource.org/licenses/mit-license.php
 *  http://www.gnu.org/licenses/gpl.html
 */
;(function($) {
    $.floatLayer = {
        defaults: {
            position: { x: 'left', y: 'center' },
            duration: 500,
            easing: 'swing',
            fixed: false
        }
    };

    $.extend($.support, { positionFixed: false });
    $(document).ready(function() {
        var element = $('<div></div>').css({
            'position': 'fixed',
            'left': '0px',
            'top': '0px'
        })
        .attr('id', '_divFixedPosition')
        .hide()
        .appendTo('body')[0];
        $.support.positionFixed = element.offsetLeft == null || isNaN(element.offsetLeft) || element.offsetLeft != 0 ? false : true;
        $(element).remove();
    });

    $.fn.extend({
        makeFloating: function(options) {
            return this.each(function() {
                options = $.extend({}, $.floatLayer.defaults, options);
                settings(this, options);
                $(this).css('position', options.fixed && $.support.positionFixed ? 'fixed' : 'absolute')
                .show();

                this.isFloating = true;
                initialize.call(this);

                var me = this;
                $(window)
                .resize(function() {
                    initialize.call(me);
                })
                .scroll(function() {
                    doFloat.call(me);
                });
            });
        },
        floatingPosition: function(position) {
            return this.each(function() {
                if (this.isFloating === true) {
                    settings(this, $.extend({}, settings(this), { position: position }));
                    initialize.call(this);
                }
            });
        }        
    });

    function initialize() {
        settings(this, $.extend({}, settings(this), { target: computePosition(this) }));
        
		if(!(($(window).width() - $(this).find("img").width()) > settings(this).target.x)) {
			settings(this).target.x = $(window).width() - $(this).find("img").width();
		}
		
        doFloat.call(this);
    }

    function doFloat() {
        var position = settings(this).target;
        var view = viewport();
        var x = position.x + view.x, y = position.y + view.y;
        if (!settings(this).fixed) {
            var duration = settings(this).duration;
            var easing = settings(this).easing;
            $(this).animate(
                { left: x + 'px', top: y + 'px' },
                { duration: duration, queue: false, easing: easing }
            );
        } else if (!$.support.positionFixed) {
            $(this).css({
                left: x + 'px',
                top: y + 'px'
            });
        } else {
            $(this).css({
                left: position.x + 'px',
                top: position.y + 'px'
            });
        }
    }

    function computePosition(element) {
        var view = viewport();
        var x = settings(element).position.x, y = settings(element).position.y;
        var elementWidth = parseInt($(element).outerWidth(true)), elementHeight = parseInt($(element).outerHeight(true));

        if (/^right$/i.test(x)) {
            x = view.x + view.width - elementWidth;
        } else if (/^center$/i.test(x)) {
            x = view.x + (view.width - elementWidth) / 2;
        } else if (/^left$/i.test(x)) {
            x = 0;
        }

        if (/^top$/i.test(y)) {
            y = 0;
        } else if (/^center$/i.test(y)) {
            y = view.y + (view.height - elementHeight) / 2;
        } else if (/^bottom$/i.test(y)) {
            y = view.y + view.height - elementHeight;
        }

        return {
            x: isNaN(x) ? 0 : x,
            y: isNaN(y) ? 0 : y
        };
    }

    function settings(element, value) {
        return value === undefined ? $.data(element, 'settings') :
            $.data(element, 'settings', value);
    }

    function viewport() {
        return {
            x: $(document).scrollLeft(),
            y: $(document).scrollTop(),
            width: $(window).width(),
            height: $(window).height()
        };
    }
})(jQuery);
(function($){
	/* hoverIntent by Brian Cherne */
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
	
})(jQuery);

/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);

