// XXX: twitterのwidget.jsがwindow.defineを定義している．
//      それによって，jquery.cookieがdefineあるときはAMD形式のexportするので，jquery.cookieが定義されなくなる．
//      その対策として，先にwindow.define消しておく．
window.define = undefined;

/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
//@ sourceMappingURL=jquery.min.map
*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
/*! jQuery UI - v1.10.0 - 2013-01-18
* http://jqueryui.com
* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */

(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.10.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a={},f=t.split(".")[0];t=t.split(".")[1],i=f+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[f]=e[f]||{},s=e[f][t],o=e[f][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,r){if(!e.isFunction(r)){a[t]=r;return}a[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},i=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=i,s=r.apply(this,arguments),this._super=t,this._superApply=n,s}}()}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},a,{constructor:o,namespace:f,widgetName:t,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&e.effects.effect[u]?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(){n=!1}),e.widget("ui.mouse",{version:"1.10.0",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||document.documentMode<9)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}function d(t){var n=t[0];return n.nodeType===9?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(n)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:n.preventDefault?{width:0,height:0,offset:{top:n.pageY,left:n.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,v,m,g,y,b=e(t.of),w=e.position.getWithinInfo(t.within),E=e.position.getScrollInfo(w),S=(t.collision||"flip").split(" "),x={};return y=d(b),b[0].preventDefault&&(t.at="left top"),l=y.width,v=y.height,m=y.offset,g=e.extend({},m),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),x[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),S.length===1&&(S[1]=S[0]),t.at[0]==="right"?g.left+=l:t.at[0]==="center"&&(g.left+=l/2),t.at[1]==="bottom"?g.top+=v:t.at[1]==="center"&&(g.top+=v/2),n=h(x.at,l,v),g.left+=n[0],g.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),d=p(this,"marginLeft"),y=p(this,"marginTop"),T=f+d+p(this,"marginRight")+E.width,N=c+y+p(this,"marginBottom")+E.height,C=e.extend({},g),k=h(x.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:d,marginTop:y},e.each(["left","top"],function(r,i){e.ui.position[S[r]]&&e.ui.position[S[r]][i](C,{targetWidth:l,targetHeight:v,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:w,elem:a})}),t.using&&(u=function(e){var n=m.left-C.left,s=n+l-f,o=m.top-C.top,u=o+v-c,h={target:{element:b,left:m.left,top:m.top,width:l,height:v},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),v<c&&i(o+u)<v&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}()})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.0",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){this.options.helper==="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!=="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!=="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n,r=this,i=!1,s=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),n=this.element[0];while(n&&(n=n.parentNode))n===document&&(i=!0);return!i&&this.options.helper==="original"?!1:(this.options.revert==="invalid"&&!s||this.options.revert==="valid"&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){r._trigger("stop",t)!==!1&&r._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1)},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").addBack().each(function(){this===t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper==="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo==="parent"?this.element[0].parentNode:n.appendTo),r[0]!==this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition==="absolute"&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()==="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options;i.containment==="parent"&&(i.containment=this.helper[0].parentNode);if(i.containment==="document"||i.containment==="window")this.containment=[i.containment==="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,i.containment==="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(i.containment==="document"?0:e(window).scrollLeft())+e(i.containment==="document"?document:window).width()-this.helperProportions.width-this.margins.left,(i.containment==="document"?0:e(window).scrollTop())+(e(i.containment==="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(i.containment)&&i.containment.constructor!==Array){n=e(i.containment),r=n[0];if(!r)return;t=e(r).css("overflow")!=="hidden",this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(t?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else i.containment.constructor===Array&&(this.containment=i.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t==="absolute"?1:-1,i=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(i[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():s?0:i.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():s?0:i.scrollLeft())*r}},_generatePosition:function(t){var n,r,i,s,o=this.options,u=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(u[0].tagName),f=t.pageX,l=t.pageY;return this.originalPosition&&(this.containment&&(this.relative_container?(r=this.relative_container.offset(),n=[this.containment[0]+r.left,this.containment[1]+r.top,this.containment[2]+r.left,this.containment[3]+r.top]):n=this.containment,t.pageX-this.offset.click.left<n[0]&&(f=n[0]+this.offset.click.left),t.pageY-this.offset.click.top<n[1]&&(l=n[1]+this.offset.click.top),t.pageX-this.offset.click.left>n[2]&&(f=n[2]+this.offset.click.left),t.pageY-this.offset.click.top>n[3]&&(l=n[3]+this.offset.click.top)),o.grid&&(i=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=n?i-this.offset.click.top>=n[1]||i-this.offset.click.top>n[3]?i:i-this.offset.click.top>=n[1]?i-o.grid[1]:i+o.grid[1]:i,s=o.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,f=n?s-this.offset.click.left>=n[0]||s-this.offset.click.left>n[2]?s:s-this.offset.click.left>=n[0]?s-o.grid[0]:s+o.grid[0]:s)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!==this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t==="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("ui-draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"ui-sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("ui-draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper==="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("ui-draggable"),i=this;e.each(r.sortables,function(){var s=!1,o=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(s=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(o.instance.element[0],this.instance.element[0])&&(s=!1),s})),s?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),n=e(this).data("ui-draggable").options;t.css("cursor")&&(n._cursor=t.css("cursor")),t.css("cursor",n.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("ui-draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("ui-draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&t.scrollParent[0].tagName!=="HTML"&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var n=e(this).data("ui-draggable"),r=n.options,i=!1;if(n.scrollParent[0]!==document&&n.scrollParent[0].tagName!=="HTML"){if(!r.axis||r.axis!=="x")n.overflowOffset.top+n.scrollParent[0].offsetHeight-t.pageY<r.scrollSensitivity?n.scrollParent[0].scrollTop=i=n.scrollParent[0].scrollTop+r.scrollSpeed:t.pageY-n.overflowOffset.top<r.scrollSensitivity&&(n.scrollParent[0].scrollTop=i=n.scrollParent[0].scrollTop-r.scrollSpeed);if(!r.axis||r.axis!=="y")n.overflowOffset.left+n.scrollParent[0].offsetWidth-t.pageX<r.scrollSensitivity?n.scrollParent[0].scrollLeft=i=n.scrollParent[0].scrollLeft+r.scrollSpeed:t.pageX-n.overflowOffset.left<r.scrollSensitivity&&(n.scrollParent[0].scrollLeft=i=n.scrollParent[0].scrollLeft-r.scrollSpeed)}else{if(!r.axis||r.axis!=="x")t.pageY-e(document).scrollTop()<r.scrollSensitivity?i=e(document).scrollTop(e(document).scrollTop()-r.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<r.scrollSensitivity&&(i=e(document).scrollTop(e(document).scrollTop()+r.scrollSpeed));if(!r.axis||r.axis!=="y")t.pageX-e(document).scrollLeft()<r.scrollSensitivity?i=e(document).scrollLeft(e(document).scrollLeft()-r.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<r.scrollSensitivity&&(i=e(document).scrollLeft(e(document).scrollLeft()+r.scrollSpeed))}i!==!1&&e.ui.ddmanager&&!r.dropBehaviour&&e.ui.ddmanager.prepareOffsets(n,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),n=t.options;t.snapElements=[],e(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var n=e(this),r=n.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:n.outerWidth(),height:n.outerHeight(),top:r.top,left:r.left})})},drag:function(t,n){var r,i,s,o,u,a,f,l,c,h,p=e(this).data("ui-draggable"),d=p.options,v=d.snapTolerance,m=n.offset.left,g=m+p.helperProportions.width,y=n.offset.top,b=y+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--){u=p.snapElements[c].left,a=u+p.snapElements[c].width,f=p.snapElements[c].top,l=f+p.snapElements[c].height;if(!(u-v<m&&m<a+v&&f-v<y&&y<l+v||u-v<m&&m<a+v&&f-v<b&&b<l+v||u-v<g&&g<a+v&&f-v<y&&y<l+v||u-v<g&&g<a+v&&f-v<b&&b<l+v)){p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1;continue}d.snapMode!=="inner"&&(r=Math.abs(f-b)<=v,i=Math.abs(l-y)<=v,s=Math.abs(u-g)<=v,o=Math.abs(a-m)<=v,r&&(n.position.top=p._convertPositionTo("relative",{top:f-p.helperProportions.height,left:0}).top-p.margins.top),i&&(n.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),s&&(n.position.left=p._convertPositionTo("relative",{top:0,left:u-p.helperProportions.width}).left-p.margins.left),o&&(n.position.left=p._convertPositionTo("relative",{top:0,left:a}).left-p.margins.left)),h=r||i||s||o,d.snapMode!=="outer"&&(r=Math.abs(f-y)<=v,i=Math.abs(l-b)<=v,s=Math.abs(u-m)<=v,o=Math.abs(a-g)<=v,r&&(n.position.top=p._convertPositionTo("relative",{top:f,left:0}).top-p.margins.top),i&&(n.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),s&&(n.position.left=p._convertPositionTo("relative",{top:0,left:u}).left-p.margins.left),o&&(n.position.left=p._convertPositionTo("relative",{top:0,left:a-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(r||i||s||o||h)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=r||i||s||o||h}}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,n=e(this).data("ui-draggable").options,r=e.makeArray(e(n.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!r.length)return;t=parseInt(r[0].style.zIndex,10)||0,e(r).each(function(e){this.style.zIndex=t+e}),this[0].style.zIndex=t+r.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("ui-draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("ui-draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){function n(e,t,n){return e>t&&e<t+n}e.widget("ui.droppable",{version:"1.10.0",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t=this.options,n=t.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=0,n=e.ui.ddmanager.droppables[this.options.scope];for(;t<n.length;t++)n[t]===this&&n.splice(t,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t==="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]===this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]===this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current,i=!1;return!r||(r.currentItem||r.element)[0]===this.element[0]?!1:(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"ui-droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope===r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1)},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(e,t,r){if(!t.offset)return!1;var i,s,o=(e.positionAbs||e.position.absolute).left,u=o+e.helperProportions.width,a=(e.positionAbs||e.position.absolute).top,f=a+e.helperProportions.height,l=t.offset.left,c=l+t.proportions.width,h=t.offset.top,p=h+t.proportions.height;switch(r){case"fit":return l<=o&&u<=c&&h<=a&&f<=p;case"intersect":return l<o+e.helperProportions.width/2&&u-e.helperProportions.width/2<c&&h<a+e.helperProportions.height/2&&f-e.helperProportions.height/2<p;case"pointer":return i=(e.positionAbs||e.position.absolute).left+(e.clickOffset||e.offset.click).left,s=(e.positionAbs||e.position.absolute).top+(e.clickOffset||e.offset.click).top,n(s,h,t.proportions.height)&&n(i,l,t.proportions.width);case"touch":return(a>=h&&a<=p||f>=h&&f<=p||a<h&&f>p)&&(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r,i,s=e.ui.ddmanager.droppables[t.options.scope]||[],o=n?n.type:null,u=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(r=0;r<s.length;r++){if(s[r].options.disabled||t&&!s[r].accept.call(s[r].element[0],t.currentItem||t.element))continue;for(i=0;i<u.length;i++)if(u[i]===s[r].element[0]){s[r].proportions.height=0;continue e}s[r].visible=s[r].element.css("display")!=="none";if(!s[r].visible)continue;o==="mousedown"&&s[r]._activate.call(s[r],n),s[r].offset=s[r].element.offset(),s[r].proportions={width:s[r].element[0].offsetWidth,height:s[r].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r,i,s,o=e.ui.intersect(t,this,this.options.tolerance),u=!o&&this.isover?"isout":o&&!this.isover?"isover":null;if(!u)return;this.options.greedy&&(i=this.options.scope,s=this.element.parents(":data(ui-droppable)").filter(function(){return e.data(this,"ui-droppable").options.scope===i}),s.length&&(r=e.data(s[0],"ui-droppable"),r.greedyChild=u==="isover")),r&&u==="isover"&&(r.isover=!1,r.isout=!0,r._out.call(r,n)),this[u]=!0,this[u==="isout"?"isover":"isout"]=!1,this[u==="isover"?"_over":"_out"].call(this,n),r&&u==="isout"&&(r.isout=!1,r.isover=!0,r._over.call(r,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);(function(e,t){function n(e){return parseInt(e,10)||0}function r(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.0",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,n,r,i,s,o=this,u=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!u.aspectRatio,aspectRatio:u.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:u.helper||u.ghost||u.animate?u.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=u.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor===String){this.handles==="all"&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={};for(n=0;n<t.length;n++)r=e.trim(t[n]),s="ui-resizable-"+r,i=e("<div class='ui-resizable-handle "+s+"'></div>"),i.css({zIndex:u.zIndex}),"se"===r&&i.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[r]=".ui-resizable-"+r,this.element.append(i)}this._renderAxis=function(t){var n,r,i,s;t=t||this.element;for(n in this.handles){this.handles[n].constructor===String&&(this.handles[n]=e(this.handles[n],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(r=e(this.handles[n],this.element),s=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth(),i=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize());if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=i&&i[1]?i[1]:"se")}),u.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(u.disabled)return;e(this).removeClass("ui-resizable-autohide"),o._handles.show()}).mouseleave(function(){if(u.disabled)return;o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,n=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(n(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),n(this.originalElement),this},_mouseCapture:function(t){var n,r,i=!1;for(n in this.handles){r=e(this.handles[n])[0];if(r===t.target||e.contains(r,t.target))i=!0}return!this.options.disabled&&i},_mouseStart:function(t){var r,i,s,o=this.options,u=this.element.position(),a=this.element;return this.resizing=!0,/absolute/.test(a.css("position"))?a.css({position:"absolute",top:a.css("top"),left:a.css("left")}):a.is(".ui-draggable")&&a.css({position:"absolute",top:u.top,left:u.left}),this._renderProxy(),r=n(this.helper.css("left")),i=n(this.helper.css("top")),o.containment&&(r+=e(o.containment).scrollLeft()||0,i+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:r,top:i},this.size=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalPosition={left:r,top:i},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof o.aspectRatio=="number"?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor",s==="auto"?this.axis+"-resize":s),a.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var n,r=this.helper,i={},s=this.originalMousePosition,o=this.axis,u=this.position.top,a=this.position.left,f=this.size.width,l=this.size.height,c=t.pageX-s.left||0,h=t.pageY-s.top||0,p=this._change[o];if(!p)return!1;n=p.apply(this,[t,c,h]),this._updateVirtualBoundaries(t.shiftKey);if(this._aspectRatio||t.shiftKey)n=this._updateRatio(n,t);return n=this._respectSize(n,t),this._updateCache(n),this._propagate("resize",t),this.position.top!==u&&(i.top=this.position.top+"px"),this.position.left!==a&&(i.left=this.position.left+"px"),this.size.width!==f&&(i.width=this.size.width+"px"),this.size.height!==l&&(i.height=this.size.height+"px"),r.css(i),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(i)||this._trigger("resize",t,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n,r,i,s,o,u,a,f=this.options,l=this;return this._helper&&(n=this._proportionallyResizeElements,r=n.length&&/textarea/i.test(n[0].nodeName),i=r&&e.ui.hasScroll(n[0],"left")?0:l.sizeDiff.height,s=r?0:l.sizeDiff.width,o={width:l.helper.width()-s,height:l.helper.height()-i},u=parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left)||null,a=parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top)||null,f.animate||this.element.css(e.extend(o,{top:a,left:u})),l.helper.height(l.size.height),l.helper.width(l.size.width),this._helper&&!f.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,n,i,s,o,u=this.options;o={minWidth:r(u.minWidth)?u.minWidth:0,maxWidth:r(u.maxWidth)?u.maxWidth:Infinity,minHeight:r(u.minHeight)?u.minHeight:0,maxHeight:r(u.maxHeight)?u.maxHeight:Infinity};if(this._aspectRatio||e)t=o.minHeight*this.aspectRatio,i=o.minWidth/this.aspectRatio,n=o.maxHeight*this.aspectRatio,s=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),i>o.minHeight&&(o.minHeight=i),n<o.maxWidth&&(o.maxWidth=n),s<o.maxHeight&&(o.maxHeight=s);this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,n=this.size,i=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),i==="sw"&&(e.left=t.left+(n.width-e.width),e.top=null),i==="nw"&&(e.top=t.top+(n.height-e.height),e.left=t.left+(n.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,n=this.axis,i=r(e.width)&&t.maxWidth&&t.maxWidth<e.width,s=r(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=r(e.width)&&t.minWidth&&t.minWidth>e.width,u=r(e.height)&&t.minHeight&&t.minHeight>e.height,a=this.originalPosition.left+this.originalSize.width,f=this.position.top+this.size.height,l=/sw|nw|w/.test(n),c=/nw|ne|n/.test(n);return o&&(e.width=t.minWidth),u&&(e.height=t.minHeight),i&&(e.width=t.maxWidth),s&&(e.height=t.maxHeight),o&&l&&(e.left=a-t.minWidth),i&&l&&(e.left=a-t.maxWidth),u&&c&&(e.top=f-t.minHeight),s&&c&&(e.top=f-t.maxHeight),!e.width&&!e.height&&!e.left&&e.top?e.top=null:!e.width&&!e.height&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){if(!this._proportionallyResizeElements.length)return;var e,t,n,r,i,s=this.helper||this.element;for(e=0;e<this._proportionallyResizeElements.length;e++){i=this._proportionallyResizeElements[e];if(!this.borderDif){this.borderDif=[],n=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],r=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];for(t=0;t<n.length;t++)this.borderDif[t]=(parseInt(n[t],10)||0)+(parseInt(r[t],10)||0)}i.css({height:s.height()-this.borderDif[0]-this.borderDif[2]||0,width:s.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var n=this.originalSize,r=this.originalPosition;return{left:r.left+t,width:n.width-t}},n:function(e,t,n){var r=this.originalSize,i=this.originalPosition;return{top:i.top+n,height:r.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!=="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var n=e(this).data("ui-resizable"),r=n.options,i=n._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:n.sizeDiff.height,u=s?0:n.sizeDiff.width,a={width:n.size.width-u,height:n.size.height-o},f=parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left)||null,l=parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top)||null;n.element.animate(e.extend(a,l&&f?{top:l,left:f}:{}),{duration:r.animateDuration,easing:r.animateEasing,step:function(){var r={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};i&&i.length&&e(i[0]).css({width:r.width,height:r.height}),n._updateCache(r),n._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,r,i,s,o,u,a,f=e(this).data("ui-resizable"),l=f.options,c=f.element,h=l.containment,p=h instanceof e?h.get(0):/parent/.test(h)?c.parent().get(0):h;if(!p)return;f.containerElement=e(p),/document/.test(h)||h===document?(f.containerOffset={left:0,top:0},f.containerPosition={left:0,top:0},f.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(p),r=[],e(["Top","Right","Left","Bottom"]).each(function(e,i){r[e]=n(t.css("padding"+i))}),f.containerOffset=t.offset(),f.containerPosition=t.position(),f.containerSize={height:t.innerHeight()-r[3],width:t.innerWidth()-r[1]},i=f.containerOffset,s=f.containerSize.height,o=f.containerSize.width,u=e.ui.hasScroll(p,"left")?p.scrollWidth:o,a=e.ui.hasScroll(p)?p.scrollHeight:s,f.parentData={element:p,left:i.left,top:i.top,width:u,height:a})},resize:function(t){var n,r,i,s,o=e(this).data("ui-resizable"),u=o.options,a=o.containerOffset,f=o.position,l=o._aspectRatio||t.shiftKey,c={top:0,left:0},h=o.containerElement;h[0]!==document&&/static/.test(h.css("position"))&&(c=a),f.left<(o._helper?a.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-a.left:o.position.left-c.left),l&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=u.helper?a.left:0),f.top<(o._helper?a.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-a.top:o.position.top),l&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?a.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,n=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),r=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-a.top)+o.sizeDiff.height),i=o.containerElement.get(0)===o.element.parent().get(0),s=/relative|absolute/.test(o.containerElement.css("position")),i&&s&&(n-=o.parentData.left),n+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-n,l&&(o.size.height=o.size.width/o.aspectRatio)),r+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-r,l&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.containerOffset,i=t.containerPosition,s=t.containerElement,o=e(t.helper),u=o.offset(),a=o.outerWidth()-t.sizeDiff.width,f=o.outerHeight()-t.sizeDiff.height;t._helper&&!n.animate&&/relative/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f}),t._helper&&!n.animate&&/static/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof n.alsoResize=="object"&&!n.alsoResize.parentNode?n.alsoResize.length?(n.alsoResize=n.alsoResize[0],r(n.alsoResize)):e.each(n.alsoResize,function(e){r(e)}):r(n.alsoResize)},resize:function(t,n){var r=e(this).data("ui-resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("ui-resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:r.height,width:r.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof n.ghost=="string"?n.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size,i=t.originalSize,s=t.originalPosition,o=t.axis,u=typeof n.grid=="number"?[n.grid,n.grid]:n.grid,a=u[0]||1,f=u[1]||1,l=Math.round((r.width-i.width)/a)*a,c=Math.round((r.height-i.height)/f)*f,h=i.width+l,p=i.height+c,d=n.maxWidth&&n.maxWidth<h,v=n.maxHeight&&n.maxHeight<p,m=n.minWidth&&n.minWidth>h,g=n.minHeight&&n.minHeight>p;n.grid=u,m&&(h+=a),g&&(p+=f),d&&(h-=a),v&&(p-=f),/^(se|s|e)$/.test(o)?(t.size.width=h,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.top=s.top-c):/^(sw)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.left=s.left-l):(t.size.width=h,t.size.height=p,t.position.top=s.top-c,t.position.left=s.left-l)}})})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.0",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,n=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(n.options.filter,n.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this,r=this.options;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().addBack().each(function(){var r,i=e.data(this,"selectable-item");if(i)return r=!t.metaKey&&!t.ctrlKey||!i.$element.hasClass("ui-selected"),i.$element.removeClass(r?"ui-unselecting":"ui-selected").addClass(r?"ui-selecting":"ui-unselecting"),i.unselecting=!r,i.selecting=r,i.selected=r,r?n._trigger("selecting",t,{selecting:i.element}):n._trigger("unselecting",t,{unselecting:i.element}),!1})},_mouseDrag:function(t){this.dragged=!0;if(this.options.disabled)return;var n,r=this,i=this.options,s=this.opos[0],o=this.opos[1],u=t.pageX,a=t.pageY;return s>u&&(n=u,u=s,s=n),o>a&&(n=a,a=o,o=n),this.helper.css({left:s,top:o,width:u-s,height:a-o}),this.selectees.each(function(){var n=e.data(this,"selectable-item"),f=!1;if(!n||n.element===r.element[0])return;i.tolerance==="touch"?f=!(n.left>u||n.right<s||n.top>a||n.bottom<o):i.tolerance==="fit"&&(f=n.left>s&&n.right<u&&n.top>o&&n.bottom<a),f?(n.selected&&(n.$element.removeClass("ui-selected"),n.selected=!1),n.unselecting&&(n.$element.removeClass("ui-unselecting"),n.unselecting=!1),n.selecting||(n.$element.addClass("ui-selecting"),n.selecting=!0,r._trigger("selecting",t,{selecting:n.element}))):(n.selecting&&((t.metaKey||t.ctrlKey)&&n.startselected?(n.$element.removeClass("ui-selecting"),n.selecting=!1,n.$element.addClass("ui-selected"),n.selected=!0):(n.$element.removeClass("ui-selecting"),n.selecting=!1,n.startselected&&(n.$element.addClass("ui-unselecting"),n.unselecting=!0),r._trigger("unselecting",t,{unselecting:n.element}))),n.selected&&!t.metaKey&&!t.ctrlKey&&!n.startselected&&(n.$element.removeClass("ui-selected"),n.selected=!1,n.$element.addClass("ui-unselecting"),n.unselecting=!0,r._trigger("unselecting",t,{unselecting:n.element})))}),!1},_mouseStop:function(t){var n=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){function n(e,t,n){return e>t&&e<t+n}e.widget("ui.sortable",e.ui.mouse,{version:"1.10.0",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=null,i=!1,s=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type==="static")return!1;this._refreshItems(t),e(t.target).parents().each(function(){if(e.data(this,s.widgetName+"-item")===s)return r=e(this),!1}),e.data(t.target,s.widgetName+"-item")===s&&(r=e(t.target));if(!r)return!1;if(this.options.handle&&!n){e(this.options.handle,r).find("*").addBack().each(function(){this===t.target&&(i=!0)});if(!i)return!1}return this.currentItem=r,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i,s=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,s.cursorAt&&this._adjustOffsetFromHelper(s.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),s.containment&&this._setContainment(),s.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",s.cursor)),s.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",s.opacity)),s.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",s.zIndex)),this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(i=this.containers.length-1;i>=0;i--)this.containers[i]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var n,r,i,s,o=this.options,u=!1;this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=u=this.scrollParent[0].scrollTop+o.scrollSpeed:t.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=u=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=u=this.scrollParent[0].scrollLeft+o.scrollSpeed:t.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=u=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(t.pageY-e(document).scrollTop()<o.scrollSensitivity?u=e(document).scrollTop(e(document).scrollTop()-o.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<o.scrollSensitivity&&(u=e(document).scrollTop(e(document).scrollTop()+o.scrollSpeed)),t.pageX-e(document).scrollLeft()<o.scrollSensitivity?u=e(document).scrollLeft(e(document).scrollLeft()-o.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<o.scrollSensitivity&&(u=e(document).scrollLeft(e(document).scrollLeft()+o.scrollSpeed))),u!==!1&&e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)),this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!=="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!=="x")this.helper[0].style.top=this.position.top+"px";for(n=this.items.length-1;n>=0;n--){r=this.items[n],i=r.item[0],s=this._intersectsWithPointer(r);if(!s)continue;if(r.instance!==this.currentContainer)continue;if(i!==this.currentItem[0]&&this.placeholder[s===1?"next":"prev"]()[0]!==i&&!e.contains(this.placeholder[0],i)&&(this.options.type==="semi-dynamic"?!e.contains(this.element[0],i):!0)){this.direction=s===1?"down":"up";if(this.options.tolerance!=="pointer"&&!this._intersectsWithSides(r))break;this._rearrange(t,r),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper==="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!=="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance==="pointer"||this.options.forcePointerForContainers||this.options.tolerance!=="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(e){var t=this.options.axis==="x"||n(this.positionAbs.top+this.offset.click.top,e.top,e.height),r=this.options.axis==="y"||n(this.positionAbs.left+this.offset.click.left,e.left,e.width),i=t&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o==="right"||s==="down"?2:1:s&&(s==="down"?2:1):!1},_intersectsWithSides:function(e){var t=n(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),r=n(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s==="right"&&r||s==="left"&&!r:i&&(i==="down"&&t||i==="up"&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!==0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!==0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n,r,i,s,o=[],u=[],a=this._connectWith();if(a&&t)for(n=a.length-1;n>=0;n--){i=e(a[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&u.push([e.isFunction(s.options.items)?s.options.items.call(s.element):e(s.options.items,s.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),s])}u.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(n=u.length-1;n>=0;n--)u[n][0].each(function(){o.push(this)});return e(o)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n,r,i,s,o,u,a,f,l=this.items,c=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],h=this._connectWith();if(h&&this.ready)for(n=h.length-1;n>=0;n--){i=e(h[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&(c.push([e.isFunction(s.options.items)?s.options.items.call(s.element[0],t,{item:this.currentItem}):e(s.options.items,s.element),s]),this.containers.push(s))}for(n=c.length-1;n>=0;n--){o=c[n][1],u=c[n][0];for(r=0,f=u.length;r<f;r++)a=e(u[r]),a.data(this.widgetName+"-item",o),l.push({item:a,instance:o,width:0,height:0,left:0,top:0})}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var n,r,i,s;for(n=this.items.length-1;n>=0;n--){r=this.items[n];if(r.instance!==this.currentContainer&&this.currentContainer&&r.item[0]!==this.currentItem[0])continue;i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item,t||(r.width=i.outerWidth(),r.height=i.outerHeight()),s=i.offset(),r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(n=this.containers.length-1;n>=0;n--)s=this.containers[n].element.offset(),this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var n,r=t.options;if(!r.placeholder||r.placeholder.constructor===String)n=r.placeholder,r.placeholder={element:function(){var r=e(document.createElement(t.currentItem[0].nodeName)).addClass(n||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return n||(r.style.visibility="hidden"),r},update:function(e,i){if(n&&!r.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}};t.placeholder=e(r.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),r.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n,r,i,s,o,u,a,f,l,c=null,h=null;for(n=this.containers.length-1;n>=0;n--){if(e.contains(this.currentItem[0],this.containers[n].element[0]))continue;if(this._intersectsWith(this.containers[n].containerCache)){if(c&&e.contains(this.containers[n].element[0],c.element[0]))continue;c=this.containers[n],h=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",t,this._uiHash(this)),this.containers[n].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[h]._trigger("over",t,this._uiHash(this)),this.containers[h].containerCache.over=1;else{i=1e4,s=null,o=this.containers[h].floating?"left":"top",u=this.containers[h].floating?"width":"height",a=this.positionAbs[o]+this.offset.click[o];for(r=this.items.length-1;r>=0;r--){if(!e.contains(this.containers[h].element[0],this.items[r].item[0]))continue;if(this.items[r].item[0]===this.currentItem[0])continue;f=this.items[r].item.offset()[o],l=!1,Math.abs(f-a)>Math.abs(f+this.items[r][u]-a)&&(l=!0,f+=this.items[r][u]),Math.abs(f-a)<i&&(i=Math.abs(f-a),s=this.items[r],this.direction=l?"up":"down")}if(!s&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[h],s?this._rearrange(t,s,null,!0):this._rearrange(t,null,this.containers[h].element,!0),this._trigger("change",t,this._uiHash()),this.containers[h]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[h]._trigger("over",t,this._uiHash(this)),this.containers[h].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper==="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!=="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!r[0].style.width||n.forceHelperSize)&&r.width(this.currentItem.width()),(!r[0].style.height||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition==="absolute"&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()==="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options;i.containment==="parent"&&(i.containment=this.helper[0].parentNode);if(i.containment==="document"||i.containment==="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(i.containment==="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(i.containment==="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];/^(document|window|parent)$/.test(i.containment)||(t=e(i.containment)[0],n=e(i.containment).offset(),r=e(t).css("overflow")!=="hidden",this.containment=[n.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,n.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,n.left+(r?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,n.top+(r?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,n){n||(n=this.position);var r=t==="absolute"?1:-1,i=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(i[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():s?0:i.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():s?0:i.scrollLeft())*r}},_generatePosition:function(t){var n,r,i=this.options,s=t.pageX,o=t.pageY,u=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(u[0].tagName);return this.cssPosition==="relative"&&(this.scrollParent[0]===document||this.scrollParent[0]===this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),i.grid&&(n=this.originalPageY+Math.round((o-this.originalPageY)/i.grid[1])*i.grid[1],o=this.containment?n-this.offset.click.top>=this.containment[1]&&n-this.offset.click.top<=this.containment[3]?n:n-this.offset.click.top>=this.containment[1]?n-i.grid[1]:n+i.grid[1]:n,r=this.originalPageX+Math.round((s-this.originalPageX)/i.grid[0])*i.grid[0],s=this.containment?r-this.offset.click.left>=this.containment[0]&&r-this.offset.click.left<=this.containment[2]?r:r-this.offset.click.left>=this.containment[0]?r-i.grid[0]:r+i.grid[0]:r)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction==="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i===this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r,i=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]===this.currentItem[0]){for(r in this._storedCSS)if(this._storedCSS[r]==="auto"||this._storedCSS[r]==="static")this._storedCSS[r]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&i.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!==this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!==this.currentItem.parent()[0])&&!n&&i.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(i.push(function(e){this._trigger("remove",e,this._uiHash())}),i.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),i.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(r=this.containers.length-1;r>=0;r--)n||i.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over&&(i.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex==="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(r=0;r<i.length;r++)i[r].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(r=0;r<i.length;r++)i[r].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.10.0",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),!t.collapsible&&(t.active===!1||t.active==null)&&(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels();if(t.active===!1&&t.collapsible===!0||!this.headers.length)t.active=!1,this.active=e();t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var t,r=this.options,i=r.heightStyle,s=this.element.parent(),o=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n);this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var n=e(this),r=n.attr("id"),i=n.next(),s=i.attr("id");r||(r=o+"-header-"+t,n.attr("id",r)),s||(s=o+"-panel-"+t,i.attr("id",s)),n.attr("aria-controls",s),i.attr("aria-labelledby",r)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(r.event),i==="fill"?(t=s.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):i==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,n),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}})})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.10.0",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete").appendTo(this._appendTo()).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this._appendTo()),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(n=n.replace(/'/g,"\\'"),r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.10.0",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.0",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=o(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function o(t){var n="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(n,"mouseout",function(){e(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!==-1&&e(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!==-1&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(n,"mouseover",function(){e.datepicker._isDisabledDatepicker(i.inline?t.parent()[0]:i.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!==-1&&e(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!==-1&&e(this).addClass("ui-datepicker-next-hover"))})}function u(t,n){e.extend(t,n);for(var r in n)n[r]==null&&(t[r]=n[r]);return t}e.extend(e.ui,{datepicker:{version:"1.10.0"}});var n="datepicker",r=(new Date).getTime(),i;e.extend(s.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return u(this._defaults,e||{}),this},_attachDatepicker:function(t,n){var r,i,s;r=t.nodeName.toLowerCase(),i=r==="div"||r==="span",t.id||(this.uuid+=1,t.id="dp"+this.uuid),s=this._newInst(e(t),i),s.settings=e.extend({},n||{}),r==="input"?this._connectDatepicker(t,s):i&&this._inlineDatepicker(t,s)},_newInst:function(t,n){var r=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:r,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:n,dpDiv:n?o(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,r){var i=e(t);r.append=e([]),r.trigger=e([]);if(i.hasClass(this.markerClassName))return;this._attachments(i,r),i.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(r),e.data(t,n,r),r.settings.disabled&&this._disableDatepicker(t)},_attachments:function(t,n){var r,i,s,o=this._get(n,"appendText"),u=this._get(n,"isRTL");n.append&&n.append.remove(),o&&(n.append=e("<span class='"+this._appendClass+"'>"+o+"</span>"),t[u?"before":"after"](n.append)),t.unbind("focus",this._showDatepicker),n.trigger&&n.trigger.remove(),r=this._get(n,"showOn"),(r==="focus"||r==="both")&&t.focus(this._showDatepicker);if(r==="button"||r==="both")i=this._get(n,"buttonText"),s=this._get(n,"buttonImage"),n.trigger=e(this._get(n,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:s,alt:i,title:i}):e("<button type='button'></button>").addClass(this._triggerClass).html(s?e("<img/>").attr({src:s,alt:i,title:i}):i)),t[u?"before":"after"](n.trigger),n.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1})},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,n,r,i,s=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){n=0,r=0;for(i=0;i<e.length;i++)e[i].length>n&&(n=e[i].length,r=i);return r},s.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),s.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-s.getDay())),e.input.attr("size",this._formatDate(e,s).length)}},_inlineDatepicker:function(t,r){var i=e(t);if(i.hasClass(this.markerClassName))return;i.addClass(this.markerClassName).append(r.dpDiv),e.data(t,n,r),this._setDate(r,this._getDefaultDate(r),!0),this._updateDatepicker(r),this._updateAlternate(r),r.settings.disabled&&this._disableDatepicker(t),r.dpDiv.css("display","block")},_dialogDatepicker:function(t,r,i,s,o){var a,f,l,c,h,p=this._dialogInst;return p||(this.uuid+=1,a="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+a+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},e.data(this._dialogInput[0],n,p)),u(p.settings,s||{}),r=r&&r.constructor===Date?this._formatDate(p,r):r,this._dialogInput.val(r),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(f=document.documentElement.clientWidth,l=document.documentElement.clientHeight,c=document.documentElement.scrollLeft||document.body.scrollLeft,h=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[f/2-100+c,l/2-150+h]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=i,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],n,p),this},_destroyDatepicker:function(t){var r,i=e(t),s=e.data(t,n);if(!i.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase(),e.removeData(t,n),r==="input"?(s.append.remove(),s.trigger.remove(),i.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r==="div"||r==="span")&&i.removeClass(this.markerClassName).empty()},_enableDatepicker:function(t){var r,i,s=e(t),o=e.data(t,n);if(!s.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase();if(r==="input")t.disabled=!1,o.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r==="div"||r==="span")i=s.children("."+this._inlineClass),i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1);this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e})},_disableDatepicker:function(t){var r,i,s=e(t),o=e.data(t,n);if(!s.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase();if(r==="input")t.disabled=!0,o.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r==="div"||r==="span")i=s.children("."+this._inlineClass),i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0);this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,n)}catch(r){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(n,r,i){var s,o,a,f,l=this._getInst(n);if(arguments.length===2&&typeof r=="string")return r==="defaults"?e.extend({},e.datepicker._defaults):l?r==="all"?e.extend({},l.settings):this._get(l,r):null;s=r||{},typeof r=="string"&&(s={},s[r]=i),l&&(this._curInst===l&&this._hideDatepicker(),o=this._getDateDatepicker(n,!0),a=this._getMinMaxDate(l,"min"),f=this._getMinMaxDate(l,"max"),u(l.settings,s),a!==null&&s.dateFormat!==t&&s.minDate===t&&(l.settings.minDate=this._formatDate(l,a)),f!==null&&s.dateFormat!==t&&s.maxDate===t&&(l.settings.maxDate=this._formatDate(l,f)),"disabled"in s&&(s.disabled?this._disableDatepicker(n):this._enableDatepicker(n)),this._attachments(e(n),l),this._autoSize(l),this._setDate(l,o),this._updateAlternate(l),this._updateDatepicker(l))},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(t){var n,r,i,s=e.datepicker._getInst(t.target),o=!0,u=s.dpDiv.is(".ui-datepicker-rtl");s._keyEvent=!0;if(e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return i=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",s.dpDiv),i[0]&&e.datepicker._selectDay(t.target,s.selectedMonth,s.selectedYear,i[0]),n=e.datepicker._get(s,"onSelect"),n?(r=e.datepicker._formatDate(s),n.apply(s.input?s.input[0]:null,[r,s])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,u?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,u?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else t.keyCode===36&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var n,r,i=e.datepicker._getInst(t.target);if(e.datepicker._get(i,"constrainInput"))return n=e.datepicker._possibleChars(e.datepicker._get(i,"dateFormat")),r=String.fromCharCode(t.charCode==null?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||r<" "||!n||n.indexOf(r)>-1},_doKeyUp:function(t){var n,r=e.datepicker._getInst(t.target);if(r.input.val()!==r.lastVal)try{n=e.datepicker.parseDate(e.datepicker._get(r,"dateFormat"),r.input?r.input.val():null,e.datepicker._getFormatConfig(r)),n&&(e.datepicker._setDateFromField(r),e.datepicker._updateAlternate(r),e.datepicker._updateDatepicker(r))}catch(i){}return!0},_showDatepicker:function(t){t=t.target||t,t.nodeName.toLowerCase()!=="input"&&(t=e("input",t.parentNode)[0]);if(e.datepicker._isDisabledDatepicker(t)||e.datepicker._lastInput===t)return;var n,r,i,s,o,a,f;n=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==n&&(e.datepicker._curInst.dpDiv.stop(!0,!0),n&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),r=e.datepicker._get(n,"beforeShow"),i=r?r.apply(t,[t,n]):{};if(i===!1)return;u(n.settings,i),n.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(n),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),s=!1,e(t).parents().each(function(){return s|=e(this).css("position")==="fixed",!s}),o={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,n.dpDiv.empty(),n.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(n),o=e.datepicker._checkOffset(n,o,s),n.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":s?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),n.inline||(a=e.datepicker._get(n,"showAnim"),f=e.datepicker._get(n,"duration"),n.dpDiv.zIndex(e(t).zIndex()+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[a]?n.dpDiv.show(a,e.datepicker._get(n,"showOptions"),f):n.dpDiv[a||"show"](a?f:null),n.input.is(":visible")&&!n.input.is(":disabled")&&n.input.focus(),e.datepicker._curInst=n)},_updateDatepicker:function(t){this.maxRows=4,i=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a").mouseover();var n,r=this._getNumberOfMonths(t),s=r[1],o=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),s>1&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",o*s+"em"),t.dpDiv[(r[0]!==1||r[1]!==1?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&t.input[0]!==document.activeElement&&t.input.focus(),t.yearshtml&&(n=t.yearshtml,setTimeout(function(){n===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),n=t.yearshtml=null},0))},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(t,n,r){var i=t.dpDiv.outerWidth(),s=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,u=t.input?t.input.outerHeight():0,a=document.documentElement.clientWidth+(r?0:e(document).scrollLeft()),f=document.documentElement.clientHeight+(r?0:e(document).scrollTop());return n.left-=this._get(t,"isRTL")?i-o:0,n.left-=r&&n.left===t.input.offset().left?e(document).scrollLeft():0,n.top-=r&&n.top===t.input.offset().top+u?e(document).scrollTop():0,n.left-=Math.min(n.left,n.left+i>a&&a>i?Math.abs(n.left+i-a):0),n.top-=Math.min(n.top,n.top+s>f&&f>s?Math.abs(s+u):0),n},_findPos:function(t){var n,r=this._getInst(t),i=this._get(r,"isRTL");while(t&&(t.type==="hidden"||t.nodeType!==1||e.expr.filters.hidden(t)))t=t[i?"previousSibling":"nextSibling"];return n=e(t).offset(),[n.left,n.top]},_hideDatepicker:function(t){var r,i,s,o,u=this._curInst;if(!u||t&&u!==e.data(t,n))return;this._datepickerShowing&&(r=this._get(u,"showAnim"),i=this._get(u,"duration"),s=function(){e.datepicker._tidyDialog(u)},e.effects&&(e.effects.effect[r]||e.effects[r])?u.dpDiv.hide(r,e.datepicker._get(u,"showOptions"),i,s):u.dpDiv[r==="slideDown"?"slideUp":r==="fadeIn"?"fadeOut":"hide"](r?i:null,s),r||s(),this._datepickerShowing=!1,o=this._get(u,"onClose"),o&&o.apply(u.input?u.input[0]:null,[u.input?u.input.val():"",u]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(!e.datepicker._curInst)return;var n=e(t.target),r=e.datepicker._getInst(n[0]);(n[0].id!==e.datepicker._mainDivId&&n.parents("#"+e.datepicker._mainDivId).length===0&&!n.hasClass(e.datepicker.markerClassName)&&!n.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||n.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==r)&&e.datepicker._hideDatepicker()},_adjustDate:function(t,n,r){var i=e(t),s=this._getInst(i[0]);if(this._isDisabledDatepicker(i[0]))return;this._adjustInstDate(s,n+(r==="M"?this._get(s,"showCurrentAtPos"):0),r),this._updateDatepicker(s)},_gotoToday:function(t){var n,r=e(t),i=this._getInst(r[0]);this._get(i,"gotoCurrent")&&i.currentDay?(i.selectedDay=i.currentDay,i.drawMonth=i.selectedMonth=i.currentMonth,i.drawYear=i.selectedYear=i.currentYear):(n=new Date,i.selectedDay=n.getDate(),i.drawMonth=i.selectedMonth=n.getMonth(),i.drawYear=i.selectedYear=n.getFullYear()),this._notifyChange(i),this._adjustDate(r)},_selectMonthYear:function(t,n,r){var i=e(t),s=this._getInst(i[0]);s["selected"+(r==="M"?"Month":"Year")]=s["draw"+(r==="M"?"Month":"Year")]=parseInt(n.options[n.selectedIndex].value,10),this._notifyChange(s),this._adjustDate(i)},_selectDay:function(t,n,r,i){var s,o=e(t);if(e(i).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0]))return;s=this._getInst(o[0]),s.selectedDay=s.currentDay=e("a",i).html(),s.selectedMonth=s.currentMonth=n,s.selectedYear=s.currentYear=r,this._selectDate(t,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(t){var n=e(t);this._selectDate(n,"")},_selectDate:function(t,n){var r,i=e(t),s=this._getInst(i[0]);n=n!=null?n:this._formatDate(s),s.input&&s.input.val(n),this._updateAlternate(s),r=this._get(s,"onSelect"),r?r.apply(s.input?s.input[0]:null,[n,s]):s.input&&s.input.trigger("change"),s.inline?this._updateDatepicker(s):(this._hideDatepicker(),this._lastInput=s.input[0],typeof s.input[0]!="object"&&s.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var n,r,i,s=this._get(t,"altField");s&&(n=this._get(t,"altFormat")||this._get(t,"dateFormat"),r=this._getDate(t),i=this.formatDate(n,r,this._getFormatConfig(t)),e(s).each(function(){e(this).val(i)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t,n=new Date(e.getTime());return n.setDate(n.getDate()+4-(n.getDay()||7)),t=n.getTime(),n.setMonth(0),n.setDate(1),Math.floor(Math.round((t-n)/864e5)/7)+1},parseDate:function(t,n,r){if(t==null||n==null)throw"Invalid arguments";n=typeof n=="object"?n.toString():n+"";if(n==="")return null;var i,s,o,u=0,a=(r?r.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=typeof a!="string"?a:(new Date).getFullYear()%100+parseInt(a,10),l=(r?r.dayNamesShort:null)||this._defaults.dayNamesShort,c=(r?r.dayNames:null)||this._defaults.dayNames,h=(r?r.monthNamesShort:null)||this._defaults.monthNamesShort,p=(r?r.monthNames:null)||this._defaults.monthNames,d=-1,v=-1,m=-1,g=-1,y=!1,b,w=function(e){var n=i+1<t.length&&t.charAt(i+1)===e;return n&&i++,n},E=function(e){var t=w(e),r=e==="@"?14:e==="!"?20:e==="y"&&t?4:e==="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=n.substring(u).match(i);if(!s)throw"Missing number at position "+u;return u+=s[0].length,parseInt(s[0],10)},S=function(t,r,i){var s=-1,o=e.map(w(t)?i:r,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});e.each(o,function(e,t){var r=t[1];if(n.substr(u,r.length).toLowerCase()===r.toLowerCase())return s=t[0],u+=r.length,!1});if(s!==-1)return s+1;throw"Unknown name at position "+u},x=function(){if(n.charAt(u)!==t.charAt(i))throw"Unexpected literal at position "+u;u++};for(i=0;i<t.length;i++)if(y)t.charAt(i)==="'"&&!w("'")?y=!1:x();else switch(t.charAt(i)){case"d":m=E("d");break;case"D":S("D",l,c);break;case"o":g=E("o");break;case"m":v=E("m");break;case"M":v=S("M",h,p);break;case"y":d=E("y");break;case"@":b=new Date(E("@")),d=b.getFullYear(),v=b.getMonth()+1,m=b.getDate();break;case"!":b=new Date((E("!")-this._ticksTo1970)/1e4),d=b.getFullYear(),v=b.getMonth()+1,m=b.getDate();break;case"'":w("'")?x():y=!0;break;default:x()}if(u<n.length){o=n.substr(u);if(!/^\s+/.test(o))throw"Extra/unparsed characters found in date: "+o}d===-1?d=(new Date).getFullYear():d<100&&(d+=(new Date).getFullYear()-(new Date).getFullYear()%100+(d<=f?0:-100));if(g>-1){v=1,m=g;do{s=this._getDaysInMonth(d,v-1);if(m<=s)break;v++,m-=s}while(!0)}b=this._daylightSavingAdjust(new Date(d,v-1,m));if(b.getFullYear()!==d||b.getMonth()+1!==v||b.getDate()!==m)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r,i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=function(t){var n=r+1<e.length&&e.charAt(r+1)===t;return n&&r++,n},f=function(e,t,n){var r=""+t;if(a(e))while(r.length<n)r="0"+r;return r},l=function(e,t,n,r){return a(e)?r[t]:n[t]},c="",h=!1;if(t)for(r=0;r<e.length;r++)if(h)e.charAt(r)==="'"&&!a("'")?h=!1:c+=e.charAt(r);else switch(e.charAt(r)){case"d":c+=f("d",t.getDate(),2);break;case"D":c+=l("D",t.getDay(),i,s);break;case"o":c+=f("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":c+=f("m",t.getMonth()+1,2);break;case"M":c+=l("M",t.getMonth(),o,u);break;case"y":c+=a("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":c+=t.getTime();break;case"!":c+=t.getTime()*1e4+this._ticksTo1970;break;case"'":a("'")?c+="'":h=!0;break;default:c+=e.charAt(r)}return c},_possibleChars:function(e){var t,n="",r=!1,i=function(n){var r=t+1<e.length&&e.charAt(t+1)===n;return r&&t++,r};for(t=0;t<e.length;t++)if(r)e.charAt(t)==="'"&&!i("'")?r=!1:n+=e.charAt(t);else switch(e.charAt(t)){case"d":case"m":case"y":case"@":n+="0123456789";break;case"D":case"M":return null;case"'":i("'")?n+="'":r=!0;break;default:n+=e.charAt(t)}return n},_get:function(e,n){return e.settings[n]!==t?e.settings[n]:this._defaults[n]},_setDateFromField:function(e,t){if(e.input.val()===e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i=this._getDefaultDate(e),s=i,o=this._getFormatConfig(e);try{s=this.parseDate(n,r,o)||i}catch(u){r=t?"":r}e.selectedDay=s.getDate(),e.drawMonth=e.selectedMonth=s.getMonth(),e.drawYear=e.selectedYear=s.getFullYear(),e.currentDay=r?s.getDate():0,e.currentMonth=r?s.getMonth():0,e.currentYear=r?s.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,n,r){var i=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},s=function(n){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),n,e.datepicker._getFormatConfig(t))}catch(r){}var i=(n.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,s=i.getFullYear(),o=i.getMonth(),u=i.getDate(),a=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,f=a.exec(n);while(f){switch(f[2]||"d"){case"d":case"D":u+=parseInt(f[1],10);break;case"w":case"W":u+=parseInt(f[1],10)*7;break;case"m":case"M":o+=parseInt(f[1],10),u=Math.min(u,e.datepicker._getDaysInMonth(s,o));break;case"y":case"Y":s+=parseInt(f[1],10),u=Math.min(u,e.datepicker._getDaysInMonth(s,o))}f=a.exec(n)}return new Date(s,o,u)},o=n==null||n===""?r:typeof n=="string"?s(n):typeof n=="number"?isNaN(n)?r:i(n):new Date(n.getTime());return o=o&&o.toString()==="Invalid Date"?r:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!==e.selectedMonth||s!==e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()===""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var n=this._get(t,"stepMonths"),i="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){window["DP_jQuery_"+r].datepicker._adjustDate(i,-n,"M")},next:function(){window["DP_jQuery_"+r].datepicker._adjustDate(i,+n,"M")},hide:function(){window["DP_jQuery_"+r].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+r].datepicker._gotoToday(i)},selectDay:function(){return window["DP_jQuery_"+r].datepicker._selectDay(i,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+r].datepicker._selectMonthYear(i,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+r].datepicker._selectMonthYear(i,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q=new Date,R=this._daylightSavingAdjust(new Date(q.getFullYear(),q.getMonth(),q.getDate())),U=this._get(e,"isRTL"),z=this._get(e,"showButtonPanel"),W=this._get(e,"hideIfNoPrevNext"),X=this._get(e,"navigationAsDateFormat"),V=this._getNumberOfMonths(e),$=this._get(e,"showCurrentAtPos"),J=this._get(e,"stepMonths"),K=V[0]!==1||V[1]!==1,Q=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(e,"min"),Y=this._getMinMaxDate(e,"max"),Z=e.drawMonth-$,et=e.drawYear;Z<0&&(Z+=12,et--);if(Y){t=this._daylightSavingAdjust(new Date(Y.getFullYear(),Y.getMonth()-V[0]*V[1]+1,Y.getDate())),t=G&&t<G?G:t;while(this._daylightSavingAdjust(new Date(et,Z,1))>t)Z--,Z<0&&(Z=11,et--)}e.drawMonth=Z,e.drawYear=et,n=this._get(e,"prevText"),n=X?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z-J,1)),this._getFormatConfig(e)):n,r=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"e":"w")+"'>"+n+"</span></a>":W?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"e":"w")+"'>"+n+"</span></a>",i=this._get(e,"nextText"),i=X?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z+J,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"w":"e")+"'>"+i+"</span></a>":W?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"w":"e")+"'>"+i+"</span></a>",o=this._get(e,"currentText"),u=this._get(e,"gotoCurrent")&&e.currentDay?Q:R,o=X?this.formatDate(o,u,this._getFormatConfig(e)):o,a=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",f=z?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(U?a:"")+(this._isInRange(e,u)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+o+"</button>":"")+(U?"":a)+"</div>":"",l=parseInt(this._get(e,"firstDay"),10),l=isNaN(l)?0:l,c=this._get(e,"showWeek"),h=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),d=this._get(e,"monthNames"),v=this._get(e,"monthNamesShort"),m=this._get(e,"beforeShowDay"),g=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),w="",E;for(S=0;S<V[0];S++){x="",this.maxRows=4;for(T=0;T<V[1];T++){N=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),C=" ui-corner-all",k="";if(K){k+="<div class='ui-datepicker-group";if(V[1]>1)switch(T){case 0:k+=" ui-datepicker-group-first",C=" ui-corner-"+(U?"right":"left");break;case V[1]-1:k+=" ui-datepicker-group-last",C=" ui-corner-"+(U?"left":"right");break;default:k+=" ui-datepicker-group-middle",C=""}k+="'>"}k+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&S===0?U?s:r:"")+(/all|right/.test(C)&&S===0?U?r:s:"")+this._generateMonthYearHeader(e,Z,et,G,Y,S>0||T>0,d,v)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",L=c?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"";for(E=0;E<7;E++)A=(E+l)%7,L+="<th"+((E+l+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+h[A]+"'>"+p[A]+"</span></th>";k+=L+"</tr></thead><tbody>",O=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,O)),M=(this._getFirstDayOfMonth(et,Z)-l+7)%7,_=Math.ceil((M+O)/7),D=K?this.maxRows>_?this.maxRows:_:_,this.maxRows=D,P=this._daylightSavingAdjust(new Date(et,Z,1-M));for(H=0;H<D;H++){k+="<tr>",B=c?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(P)+"</td>":"";for(E=0;E<7;E++)j=m?m.apply(e.input?e.input[0]:null,[P]):[!0,""],F=P.getMonth()!==Z,I=F&&!y||!j[0]||G&&P<G||Y&&P>Y,B+="<td class='"+((E+l+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(P.getTime()===N.getTime()&&Z===e.selectedMonth&&e._keyEvent||b.getTime()===P.getTime()&&b.getTime()===N.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!g?"":" "+j[1]+(P.getTime()===Q.getTime()?" "+this._currentClass:"")+(P.getTime()===R.getTime()?" ui-datepicker-today":""))+"'"+((!F||g)&&j[2]?" title='"+j[2]+"'":"")+(I?"":" data-handler='selectDay' data-event='click' data-month='"+P.getMonth()+"' data-year='"+P.getFullYear()+"'")+">"+(F&&!g?"&#xa0;":I?"<span class='ui-state-default'>"+P.getDate()+"</span>":"<a class='ui-state-default"+(P.getTime()===R.getTime()?" ui-state-highlight":"")+(P.getTime()===Q.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+"' href='#'>"+P.getDate()+"</a>")+"</td>",P.setDate(P.getDate()+1),P=this._daylightSavingAdjust(P);k+=B+"</tr>"}Z++,Z>11&&(Z=0,et++),k+="</tbody></table>"+(K?"</div>"+(V[0]>0&&T===V[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),x+=k}w+=x}return w+=f,e._keyEvent=!1,w},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a,f,l,c,h,p,d,v,m=this._get(e,"changeMonth"),g=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",w="";if(s||!m)w+="<span class='ui-datepicker-month'>"+o[t]+"</span>";else{a=r&&r.getFullYear()===n,f=i&&i.getFullYear()===n,w+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";for(l=0;l<12;l++)(!a||l>=r.getMonth())&&(!f||l<=i.getMonth())&&(w+="<option value='"+l+"'"+(l===t?" selected='selected'":"")+">"+u[l]+"</option>");w+="</select>"}y||(b+=w+(s||!m||!g?"&#xa0;":""));if(!e.yearshtml){e.yearshtml="";if(s||!g)b+="<span class='ui-datepicker-year'>"+n+"</span>";else{c=this._get(e,"yearRange").split(":"),h=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?n+parseInt(e.substring(1),10):e.match(/[+\-].*/)?h+parseInt(e,10):parseInt(e,10);return isNaN(t)?h:t},d=p(c[0]),v=Math.max(d,p(c[1]||"")),d=r?Math.max(d,r.getFullYear()):d,v=i?Math.min(v,i.getFullYear()):v,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";for(;d<=v;d++)e.yearshtml+="<option value='"+d+"'"+(d===n?" selected='selected'":"")+">"+d+"</option>";e.yearshtml+="</select>",b+=e.yearshtml,e.yearshtml=null}}return b+=this._get(e,"yearSuffix"),y&&(b+=(s||!m||!g?"&#xa0;":"")+w),b+="</div>",b},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n==="Y"?t:0),i=e.drawMonth+(n==="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n==="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n==="M"||n==="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return r&&i>r?r:i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n,r,i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),o=null,u=null,a=this._get(e,"yearRange");return a&&(n=a.split(":"),r=(new Date).getFullYear(),o=parseInt(n[0],10)+r,u=parseInt(n[1],10)+r),(!i||t.getTime()>=i.getTime())&&(!s||t.getTime()<=s.getTime())&&(!o||t.getFullYear()>=o)&&(!u||t.getFullYear()<=u)},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),e("#"+e.datepicker._mainDivId).length===0&&e("body").append(e.datepicker.dpDiv);var n=Array.prototype.slice.call(arguments,1);return typeof t!="string"||t!=="isDisabled"&&t!=="getDate"&&t!=="widget"?t==="option"&&arguments.length===2&&typeof arguments[1]=="string"?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(n)):this.each(function(){typeof t=="string"?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(n)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(n))},e.datepicker=new s,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.10.0",window["DP_jQuery_"+r]=e})(jQuery);(function(e,t){var n={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},r={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.0",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var n=this;if(!this._isOpen||this._trigger("beforeClose",t)===!1)return;this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||e(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)})},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var n=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return n&&!t&&this._trigger("focus",e),n},open:function(){if(this._isOpen){this._moveToTop()&&this._focusTabbable();return}this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show),this._focusTabbable(),this._isOpen=!0,this._trigger("open"),this._trigger("focus")},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function n(){var t=this.document[0].activeElement,n=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);n||this._focusTabbable()}t.preventDefault(),n.call(this),this._delay(n)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE){t.preventDefault(),this.close(t);return}if(t.keyCode!==e.ui.keyCode.TAB)return;var n=this.uiDialog.find(":tabbable"),r=n.filter(":first"),i=n.filter(":last");t.target!==i[0]&&t.target!==this.uiDialog[0]||!!t.shiftKey?(t.target===r[0]||t.target===this.uiDialog[0])&&t.shiftKey&&(i.focus(1),t.preventDefault()):(r.focus(1),t.preventDefault())},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,n=this.options.buttons;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty();if(e.isEmptyObject(n)){this.uiDialog.removeClass("ui-dialog-buttons");return}e.each(n,function(n,r){var i,s;r=e.isFunction(r)?{click:r,text:n}:r,r=e.extend({type:"button"},r),i=r.click,r.click=function(){i.apply(t.element[0],arguments)},s={icons:r.icons,text:r.showText},delete r.icons,delete r.showText,e("<button></button>",r).button(s).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s))}})},_makeResizable:function(){function o(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var t=this,n=this.options,r=n.resizable,i=this.uiDialog.css("position"),s=typeof r=="string"?r:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:n.maxWidth,maxHeight:n.maxHeight,minWidth:n.minWidth,minHeight:this._minHeight(),handles:s,start:function(n,r){e(this).addClass("ui-dialog-resizing"),t._trigger("resizeStart",n,o(r))},resize:function(e,n){t._trigger("resize",e,o(n))},stop:function(r,i){n.height=e(this).height(),n.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),t._trigger("resizeStop",r,o(i))}}).css("position",i)},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,o={};e.each(t,function(e,t){i._setOption(e,t),e in n&&(s=!0),e in r&&(o[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",o)},_setOption:function(e,t){var n,r,i=this.uiDialog;e==="dialogClass"&&i.removeClass(this.options.dialogClass).addClass(t);if(e==="disabled")return;this._super(e,t),e==="appendTo"&&this.uiDialog.appendTo(this._appendTo()),e==="buttons"&&this._createButtons(),e==="closeText"&&this.uiDialogTitlebarClose.button({label:""+t}),e==="draggable"&&(n=i.is(":data(ui-draggable)"),n&&!t&&i.draggable("destroy"),!n&&t&&this._makeDraggable()),e==="position"&&this._position(),e==="resizable"&&(r=i.is(":data(ui-resizable)"),r&&!t&&i.resizable("destroy"),r&&typeof t=="string"&&i.resizable("option","handles",t),!r&&t!==!1&&this._makeResizable()),e==="title"&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title"))},_size:function(){var e,t,n,r=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),r.minWidth>r.width&&(r.width=r.minWidth),e=this.uiDialog.css({height:"auto",width:r.width}).outerHeight(),t=Math.max(0,r.minHeight-e),n=typeof r.maxHeight=="number"?Math.max(0,r.maxHeight-e):"none",r.height==="auto"?this.element.css({minHeight:t,maxHeight:n,height:"auto"}):this.element.height(Math.max(0,r.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_createOverlay:function(){if(!this.options.modal)return;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this._on(this.document,{focusin:function(t){e(t.target).closest(".ui-dialog").length||(t.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable())}})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this.document[0].body),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++},_destroyOverlay:function(){if(!this.options.modal)return;e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this._off(this.document,"focusin"),this.overlay.remove()}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t=this.options.position,n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()}})})(jQuery);(function(e,t){e.widget("ui.menu",{version:"1.10.0",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var n=e(t.target).closest(".ui-menu-item");!this.mouseHandled&&n.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(t),n.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){e==="icons"&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),this._super(e,t)},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){e.widget("ui.progressbar",{version:"1.10.0",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){if(e===t)return this.options.value;this.options.value=this._constrainedValue(e),this._refreshValue()},_constrainedValue:function(e){return e===t&&(e=this.options.value),this.indeterminate=e===!1,typeof e!="number"&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){e==="max"&&(t=Math.max(this.min,t)),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,n=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(n.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.10.0",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){var t,n,r=this.options,i=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),s="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this.range=e([]),r.range&&(r.range===!0&&(r.values?r.values.length&&r.values.length!==2?r.values=[r.values[0],r.values[0]]:e.isArray(r.values)&&(r.values=r.values.slice(0)):r.values=[this._valueMin(),this._valueMin()]),this.range=e("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(r.range==="min"||r.range==="max"?" ui-slider-range-"+r.range:""))),n=r.values&&r.values.length||1;for(t=i.length;t<n;t++)o.push(s);this.handles=i.add(e(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(e){e.preventDefault()}).mouseenter(function(){r.disabled||e(this).addClass("ui-state-hover")}).mouseleave(function(){e(this).removeClass("ui-state-hover")}).focus(function(){r.disabled?e(this).blur():(e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),e(this).addClass("ui-state-focus"))}).blur(function(){e(this).removeClass("ui-state-focus")}),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)}),this._setOption("disabled",r.disabled),this._on(this.handles,this._handleEvents),this._refreshValue(),this._animateOff=!1},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));if(i>n||i===n&&(t===l._lastChangedValue||l.values(t)===c.min))i=n,s=e(this),o=t}),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._lastChangedValue=t,this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"disabled":n?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.prop("disabled",!0)):this.handles.prop("disabled",!1);break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))},_handleEvents:{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.10.0",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e<r.min?r.min:e},_stop:function(e){if(!this.spinning)return;clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e)},_setOption:function(e,t){if(e==="culture"||e==="numberFormat"){var n=this._parse(this.element.val());this.options[e]=t,this.element.val(this._format(n));return}(e==="max"||e==="min"||e==="step")&&typeof t=="string"&&(t=this._parse(t)),e==="icons"&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),e==="disabled"&&(t?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:t(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return typeof e=="string"&&e!==""&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),e===""||isNaN(e)?null:e},_format:function(e){return e===""?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(e,t){var n;e!==""&&(n=this._parse(e),n!==null&&(t||(n=this._adjustValue(n)),e=this._format(n))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:t(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:t(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:t(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:t(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){if(!arguments.length)return this._parse(this.element.val());t(this._value).call(this,e)},widget:function(){return this.uiSpinner}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&decodeURIComponent(e.href.replace(r,""))===decodeURIComponent(location.href.replace(r,""))}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.10.0",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),n.active=this._initialActive(),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(n.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_initialActive:function(){var t=this.options.active,n=this.options.collapsible,r=location.hash.substring(1);if(t===null){r&&this.tabs.each(function(n,i){if(e(i).attr("aria-controls")===r)return t=n,!1}),t===null&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(t===null||t===-1)t=this.tabs.length?0:!1}return t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),t===-1&&(t=n?!1:0)),!n&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r=this.element.parent();t==="fill"?(n=r.height(),n-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}})})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.10.0",options:{content:function(){var t=e(this).attr("title")||"";return e("<a>").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=this.delayedShow=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;clearInterval(this.delayedShow),i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery);jQuery.effects||function(e,t){var n="ui-effects-";e.effects={effect:{}},function(e,t){function h(e,t,n){var r=u[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function p(t){var n=s(),r=n._rgba=[];return t=t.toLowerCase(),c(i,function(e,i){var s,u=i.re.exec(t),a=u&&i.parse(u),f=i.space||"rgba";if(a)return s=n[f](a),n[o[f].cache]=s[o[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&e.extend(r,l.transparent),n):l[t]}function d(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var n="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,i=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],s=e.Color=function(t,n,r,i){return new e.Color.fn.parse(t,n,r,i)},o={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},a=s.support={},f=e("<p>")[0],l,c=e.each;f.style.cssText="background-color:rgba(1,1,1,.5)",a.rgba=f.style.backgroundColor.indexOf("rgba")>-1,c(o,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),s.fn=e.extend(s.prototype,{parse:function(n,r,i,u){if(n===t)return this._rgba=[null,null,null,null],this;if(n.jquery||n.nodeType)n=e(n).css(r),r=t;var a=this,f=e.type(n),d=this._rgba=[];r!==t&&(n=[n,r,i,u],f="array");if(f==="string")return this.parse(p(n)||l._default);if(f==="array")return c(o.rgba.props,function(e,t){d[t.idx]=h(n[t.idx],t)}),this;if(f==="object")return n instanceof s?c(o,function(e,t){n[t.cache]&&(a[t.cache]=n[t.cache].slice())}):c(o,function(t,r){var i=r.cache;c(r.props,function(e,t){if(!a[i]&&r.to){if(e==="alpha"||n[e]==null)return;a[i]=r.to(a._rgba)}a[i][t.idx]=h(n[e],t,!0)}),a[i]&&e.inArray(null,a[i].slice(0,3))<0&&(a[i][3]=1,r.from&&(a._rgba=r.from(a[i])))}),this},is:function(e){var t=s(e),n=!0,r=this;return c(o,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],c(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return c(o,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=s(e),r=n._space(),i=o[r],a=this.alpha()===0?s("transparent"):this,f=a[i.cache]||i.to(a._rgba),l=f.slice();return n=n[i.cache],c(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],a=u[r.type]||{};if(o===null)return;s===null?l[i]=o:(a.mod&&(o-s>a.mod/2?s+=a.mod:s-o>a.mod/2&&(s-=a.mod)),l[i]=h((o-s)*t+s,r))}),this[r](l)},blend:function(t){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=s(t)._rgba;return s(e.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var t="rgba(",n=e.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),t="rgb("),t+n.join()+")"},toHslaString:function(){var t="hsla(",n=e.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),t="hsl("),t+n.join()+")"},toHexString:function(t){var n=this._rgba.slice(),r=n.pop();return t&&n.push(~~(r*255)),"#"+e.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),s.fn.parse.prototype=s.fn,o.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,u===0?c=0:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},o.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(d(o,s,t+1/3)*255),Math.round(d(o,s,t)*255),Math.round(d(o,s,t-1/3)*255),i]},c(o,function(n,i){var o=i.props,u=i.cache,a=i.to,f=i.from;s.fn[n]=function(n){a&&!this[u]&&(this[u]=a(this._rgba));if(n===t)return this[u].slice();var r,i=e.type(n),l=i==="array"||i==="object"?n:arguments,p=this[u].slice();return c(o,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=p[t.idx]),p[t.idx]=h(n,t)}),f?(r=s(f(p)),r[u]=p,r):s(p)},c(o,function(t,i){if(s.fn[t])return;s.fn[t]=function(s){var o=e.type(s),u=t==="alpha"?this._hsla?"hsla":"rgba":n,a=this[u](),f=a[i.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=e.type(s)),s==null&&i.empty?this:(o==="string"&&(l=r.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[i.idx]=s,this[u](a)))}})}),s.hook=function(t){var n=t.split(" ");c(n,function(t,n){e.cssHooks[n]={set:function(t,r){var i,o,u="";if(r!=="transparent"&&(e.type(r)!=="string"||(i=p(r)))){r=s(i||r);if(!a.rgba&&r._rgba[3]!==1){o=n==="backgroundColor"?t.parentNode:t;while((u===""||u==="transparent")&&o&&o.style)try{u=e.css(o,"backgroundColor"),o=o.parentNode}catch(f){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{t.style[n]=r}catch(f){}}},e.fx.step[n]=function(t){t.colorInit||(t.start=s(t.elem,n),t.end=s(t.end),t.colorInit=!0),e.cssHooks[n].set(t.elem,t.start.transition(t.end,t.pos))}})},s.hook(n),e.cssHooks.borderColor={expand:function(e){var t={};return c(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},l=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(t){var n,r,i=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,s={};if(i&&i.length&&i[0]&&i[i[0]]){r=i.length;while(r--)n=i[r],typeof i[n]=="string"&&(s[e.camelCase(n)]=i[n])}else for(n in i)typeof i[n]=="string"&&(s[n]=i[n]);return s}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").addBack():r;f=f.map(function(){var t=e(this);return{el:t,start:i(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=e.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function r(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function i(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]}e.extend(e.effects,{version:"1.10.0",save:function(e,t){for(var r=0;r<t.length;r++)t[r]!==null&&e.data(n+t[r],e[0].style[t[r]])},restore:function(e,r){var i,s;for(s=0;s<r.length;s++)r[s]!==null&&(i=e.data(n+r[s]),i===t&&(i=""),e.css(r[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function o(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,o=t.mode;(r.is(":hidden")?o==="hide":o==="show")?u():s.call(r[0],t,u)}var t=r.apply(this,arguments),n=t.mode,i=t.queue,s=e.effects.effect[t.effect];return e.fx.off||!s?n?this[n](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):i===!1?this.each(o):this.queue(i||"fx",o)},_show:e.fn.show,show:function(e){if(i(e))return this._show.apply(this,arguments);var t=r.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(i(e))return this._hide.apply(this,arguments);var t=r.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(i(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=r.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m<l;m++)g={},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p).animate(y,h,p),f=o?f*2:f/2;o&&(g={opacity:0},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p)),r.queue(function(){o&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),w>1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h<r;h++){v=a.top+h*l,g=h-(r-1)/2;for(p=0;p<i;p++)d=a.left+p*f,m=p-(i-1)/2,s.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m<a;m++)r.animate(d,l,t.easing).animate(v,l,t.easing);r.animate(d,l,t.easing).animate(p,l/2,t.easing).queue(function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),y>1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);
/*!
 * jQuery Cookie Plugin v1.4.0
 * https://github.com/carhartl/jquery-cookie
 *
 * Copyright 2013 Klaus Hartl
 * Released under the MIT license
 */
(function (factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as anonymous module.
		define(['jquery'], factory);
	} else {
		// Browser globals.
		factory(jQuery);
	}
}(function ($) {

	var pluses = /\+/g;

	function encode(s) {
		return config.raw ? s : encodeURIComponent(s);
	}

	function decode(s) {
		return config.raw ? s : decodeURIComponent(s);
	}

	function stringifyCookieValue(value) {
		return encode(config.json ? JSON.stringify(value) : String(value));
	}

	function parseCookieValue(s) {
		if (s.indexOf('"') === 0) {
			// This is a quoted cookie as according to RFC2068, unescape...
			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
		}

		try {
			// Replace server-side written pluses with spaces.
			// If we can't decode the cookie, ignore it, it's unusable.
			s = decodeURIComponent(s.replace(pluses, ' '));
		} catch(e) {
			return;
		}

		try {
			// If we can't parse the cookie, ignore it, it's unusable.
			return config.json ? JSON.parse(s) : s;
		} catch(e) {}
	}

	function read(s, converter) {
		var value = config.raw ? s : parseCookieValue(s);
		return $.isFunction(converter) ? converter(value) : value;
	}

	var config = $.cookie = function (key, value, options) {

		// Write
		if (value !== undefined && !$.isFunction(value)) {
			options = $.extend({}, config.defaults, options);

			if (typeof options.expires === 'number') {
				var days = options.expires, t = options.expires = new Date();
				t.setDate(t.getDate() + days);
			}

			return (document.cookie = [
				encode(key), '=', stringifyCookieValue(value),
				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
				options.path    ? '; path=' + options.path : '',
				options.domain  ? '; domain=' + options.domain : '',
				options.secure  ? '; secure' : ''
			].join(''));
		}

		// Read

		var result = key ? undefined : {};

		// To prevent the for loop in the first place assign an empty array
		// in case there are no cookies at all. Also prevents odd result when
		// calling $.cookie().
		var cookies = document.cookie ? document.cookie.split('; ') : [];

		for (var i = 0, l = cookies.length; i < l; i++) {
			var parts = cookies[i].split('=');
			var name = decode(parts.shift());
			var cookie = parts.join('=');

			if (key && key === name) {
				// If second argument (value) is a function it's a converter...
				result = read(cookie, value);
				break;
			}

			// Prevent storing a cookie that we couldn't decode.
			if (!key && (cookie = read(cookie)) !== undefined) {
				result[name] = cookie;
			}
		}

		return result;
	};

	config.defaults = {};

	$.removeCookie = function (key, options) {
		if ($.cookie(key) !== undefined) {
			// Must not alter options, thus extending a fresh object...
			$.cookie(key, '', $.extend({}, options, { expires: -1 }));
			return true;
		}
		return false;
	};

}));

(function ($) {
    var last = location.hash;

    $.fn.hashchange = function (fun) {
        if (fun) {
            arguments.callee.setup.apply(this);
            return this.bind('hashchange', fun);
        } else {
            return this.trigger('hashchange');
        }
    };

    var setuped;
    $.fn.hashchange.setup = function () {
        if (setuped) return; setuped = true;
        var self = this;
        (function () {
            if (location.hash != last) {
                self.trigger('hashchange');
            }
            setTimeout(arguments.callee, 500);
        })();
    };

    $(window).hashchange(function () {
        last = location.hash;
    });
})(jQuery);

/*!
	jQuery ColorBox v1.4.0 - 2013-02-12
	(c) 2013 Jack Moore - jacklmoore.com/colorbox
	license: http://www.opensource.org/licenses/mit-license.php
*/
(function(e,t,i){function o(i,o,n){var r=t.createElement(i);return o&&(r.id=Y+o),n&&(r.style.cssText=n),e(r)}function n(e){var t=T.length,i=(A+e)%t;return 0>i?t+i:i}function r(e,t){return Math.round((/%/.test(e)?("x"===t?k.width():k.height())/100:1)*parseInt(e,10))}function h(e){return _.photo||_.photoRegex.test(e)}function l(e){return _.retinaUrl&&i.devicePixelRatio>1?e.replace(_.photoRegex,_.retinaSuffix):e}function s(t){e.contains(w[0],t.target)||w[0]===t.target||(t.stopPropagation(),w.focus())}function a(){var t,i=e.data(N,V);null==i?(_=e.extend({},J),console&&console.log&&console.log("Error: cboxElement missing settings object")):_=e.extend({},i);for(t in _)e.isFunction(_[t])&&"on"!==t.slice(0,2)&&(_[t]=_[t].call(N));_.rel=_.rel||N.rel||e(N).data("rel")||"nofollow",_.href=_.href||e(N).attr("href"),_.title=_.title||N.title,"string"==typeof _.href&&(_.href=e.trim(_.href))}function d(i,o){e(t).trigger(i),at.trigger(i),e.isFunction(o)&&o.call(N)}function c(){var e,t,i,o,n,r=Y+"Slideshow_",h="click."+Y;_.slideshow&&T[1]?(t=function(){clearTimeout(e)},i=function(){(_.loop||T[A+1])&&(e=setTimeout(G.next,_.slideshowSpeed))},o=function(){M.html(_.slideshowStop).unbind(h).one(h,n),at.bind(it,i).bind(tt,t).bind(ot,n),w.removeClass(r+"off").addClass(r+"on")},n=function(){t(),at.unbind(it,i).unbind(tt,t).unbind(ot,n),M.html(_.slideshowStart).unbind(h).one(h,function(){G.next(),o()}),w.removeClass(r+"on").addClass(r+"off")},_.slideshowAuto?o():n()):w.removeClass(r+"off "+r+"on")}function u(i){U||(N=i,a(),T=e(N),A=0,"nofollow"!==_.rel&&(T=e("."+Z).filter(function(){var t,i=e.data(this,V);return i&&(t=e(this).data("rel")||i.rel||this.rel),t===_.rel}),A=T.index(N),-1===A&&(T=T.add(N),A=T.length-1)),j||(j=q=!0,w.css({visibility:"hidden",display:"block"}),E=o(dt,"LoadedContent","width:0; height:0; overflow:hidden").appendTo(v),K=x.height()+C.height()+v.outerHeight(!0)-v.height(),z=y.width()+b.width()+v.outerWidth(!0)-v.width(),D=E.outerHeight(!0),B=E.outerWidth(!0),m.css({opacity:parseFloat(_.opacity),cursor:_.overlayClose?"pointer":"auto",visibility:"visible"}).show(),_.w=r(_.initialWidth,"x"),_.h=r(_.initialHeight,"y"),G.position(),lt&&k.bind("resize."+st+" scroll."+st,function(){m.css({width:k.width(),height:k.height(),top:k.scrollTop(),left:k.scrollLeft()})}).trigger("resize."+st),c(),d(et,_.onOpen),P.add(W).hide(),R.html(_.close).show(),w.focus(),t.addEventListener&&(t.addEventListener("focus",s,!0),at.one(nt,function(){t.removeEventListener("focus",s,!0)})),_.returnFocus&&at.one(nt,function(){e(N).focus()})),G.load(!0))}function f(){!w&&t.body&&(X=!1,k=e(i),w=o(dt).attr({id:V,"class":ht?Y+(lt?"IE6":"IE"):"",role:"dialog",tabindex:"-1"}).hide(),m=o(dt,"Overlay",lt?"position:absolute":"").hide(),L=o(dt,"LoadingOverlay").add(o(dt,"LoadingGraphic")),g=o(dt,"Wrapper"),v=o(dt,"Content").append(W=o(dt,"Title"),H=o(dt,"Current"),F=o("button","Previous"),S=o("button","Next"),M=o("button","Slideshow"),L,R=o("button","Close")),g.append(o(dt).append(o(dt,"TopLeft"),x=o(dt,"TopCenter"),o(dt,"TopRight")),o(dt,!1,"clear:left").append(y=o(dt,"MiddleLeft"),v,b=o(dt,"MiddleRight")),o(dt,!1,"clear:left").append(o(dt,"BottomLeft"),C=o(dt,"BottomCenter"),o(dt,"BottomRight"))).find("div div").css({"float":"left"}),I=o(dt,!1,"position:absolute; width:9999px; visibility:hidden; display:none"),P=S.add(F).add(H).add(M),e(t.body).append(m,w.append(g,I)))}function p(){function i(e){e.which>1||e.shiftKey||e.altKey||e.metaKey||(e.preventDefault(),u(this))}return w?(X||(X=!0,S.click(function(){G.next()}),F.click(function(){G.prev()}),R.click(function(){G.close()}),m.click(function(){_.overlayClose&&G.close()}),e(t).bind("keydown."+Y,function(e){var t=e.keyCode;j&&_.escKey&&27===t&&(e.preventDefault(),G.close()),j&&_.arrowKey&&T[1]&&(37===t?(e.preventDefault(),F.click()):39===t&&(e.preventDefault(),S.click()))}),e.isFunction(e.fn.on)?e(t).on("click."+Y,"."+Z,i):e("."+Z).live("click."+Y,i)),!0):!1}var m,w,g,v,x,y,b,C,T,k,E,I,L,W,H,M,S,F,R,P,_,K,z,D,B,N,A,O,j,q,U,$,G,Q,X,J={transition:"elastic",speed:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,inline:!1,html:!1,iframe:!1,fastIframe:!0,photo:!1,href:!1,title:!1,rel:!1,opacity:.9,preloading:!0,className:!1,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",open:!1,returnFocus:!0,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico)((#|\?).*)?$/i,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0},V="colorbox",Y="cbox",Z=Y+"Element",et=Y+"_open",tt=Y+"_load",it=Y+"_complete",ot=Y+"_cleanup",nt=Y+"_closed",rt=Y+"_purge",ht=!e.support.leadingWhitespace,lt=ht&&!i.XMLHttpRequest,st=Y+"_IE6",at=e({}),dt="div";e.colorbox||(e(f),G=e.fn[V]=e[V]=function(t,i){var o=this;if(t=t||{},f(),p()){if(e.isFunction(o))o=e("<a/>"),t.open=!0;else if(!o[0])return o;i&&(t.onComplete=i),o.each(function(){e.data(this,V,e.extend({},e.data(this,V)||J,t))}).addClass(Z),(e.isFunction(t.open)&&t.open.call(o)||t.open)&&u(o[0])}return o},G.position=function(e,t){function i(e){x[0].style.width=C[0].style.width=v[0].style.width=parseInt(e.style.width,10)-z+"px",v[0].style.height=y[0].style.height=b[0].style.height=parseInt(e.style.height,10)-K+"px"}var o,n,h,l=0,s=0,a=w.offset();k.unbind("resize."+Y),w.css({top:-9e4,left:-9e4}),n=k.scrollTop(),h=k.scrollLeft(),_.fixed&&!lt?(a.top-=n,a.left-=h,w.css({position:"fixed"})):(l=n,s=h,w.css({position:"absolute"})),s+=_.right!==!1?Math.max(k.width()-_.w-B-z-r(_.right,"x"),0):_.left!==!1?r(_.left,"x"):Math.round(Math.max(k.width()-_.w-B-z,0)/2),l+=_.bottom!==!1?Math.max(k.height()-_.h-D-K-r(_.bottom,"y"),0):_.top!==!1?r(_.top,"y"):Math.round(Math.max(k.height()-_.h-D-K,0)/2),w.css({top:a.top,left:a.left,visibility:"visible"}),e=w.width()===_.w+B&&w.height()===_.h+D?0:e||0,g[0].style.width=g[0].style.height="9999px",o={width:_.w+B+z,height:_.h+D+K,top:l,left:s},0===e&&w.css(o),w.dequeue().animate(o,{duration:e,complete:function(){i(this),q=!1,g[0].style.width=_.w+B+z+"px",g[0].style.height=_.h+D+K+"px",_.reposition&&setTimeout(function(){k.bind("resize."+Y,G.position)},1),t&&t()},step:function(){i(this)}})},G.resize=function(e){j&&(e=e||{},e.width&&(_.w=r(e.width,"x")-B-z),e.innerWidth&&(_.w=r(e.innerWidth,"x")),E.css({width:_.w}),e.height&&(_.h=r(e.height,"y")-D-K),e.innerHeight&&(_.h=r(e.innerHeight,"y")),e.innerHeight||e.height||(E.css({height:"auto"}),_.h=E.height()),E.css({height:_.h}),G.position("none"===_.transition?0:_.speed))},G.prep=function(t){function i(){return _.w=_.w||E.width(),_.w=_.mw&&_.mw<_.w?_.mw:_.w,_.w}function r(){return _.h=_.h||E.height(),_.h=_.mh&&_.mh<_.h?_.mh:_.h,_.h}if(j){var l,s="none"===_.transition?0:_.speed;E.empty().remove(),E=o(dt,"LoadedContent").append(t),E.hide().appendTo(I.show()).css({width:i(),overflow:_.scrolling?"auto":"hidden"}).css({height:r()}).prependTo(v),I.hide(),e(O).css({"float":"none"}),l=function(){function t(){ht&&w[0].style.removeAttribute("filter")}var i,r,l=T.length,a="frameBorder",c="allowTransparency";j&&(r=function(){clearTimeout($),L.hide(),d(it,_.onComplete)},ht&&O&&E.fadeIn(100),W.html(_.title).add(E).show(),l>1?("string"==typeof _.current&&H.html(_.current.replace("{current}",A+1).replace("{total}",l)).show(),S[_.loop||l-1>A?"show":"hide"]().html(_.next),F[_.loop||A?"show":"hide"]().html(_.previous),_.slideshow&&M.show(),_.preloading&&e.each([n(-1),n(1)],function(){var t,i,o=T[this],n=e.data(o,V);n&&n.href?(t=n.href,e.isFunction(t)&&(t=t.call(o))):t=e(o).attr("href"),t&&(h(t)||n.photo)&&(i=new Image,i.src=t)})):P.hide(),_.iframe?(i=o("iframe")[0],a in i&&(i[a]=0),c in i&&(i[c]="true"),_.scrolling||(i.scrolling="no"),e(i).attr({src:_.href,name:(new Date).getTime(),"class":Y+"Iframe",allowFullScreen:!0,webkitAllowFullScreen:!0,mozallowfullscreen:!0}).one("load",r).appendTo(E),at.one(rt,function(){i.src="//about:blank"}),_.fastIframe&&e(i).trigger("load")):r(),"fade"===_.transition?w.fadeTo(s,1,t):t())},"fade"===_.transition?w.fadeTo(s,0,function(){G.position(0,l)}):G.position(s,l)}},G.load=function(t){var n,s,c,u=G.prep;q=!0,O=!1,N=T[A],t||a(),Q&&w.add(m).removeClass(Q),_.className&&w.add(m).addClass(_.className),Q=_.className,d(rt),d(tt,_.onLoad),_.h=_.height?r(_.height,"y")-D-K:_.innerHeight&&r(_.innerHeight,"y"),_.w=_.width?r(_.width,"x")-B-z:_.innerWidth&&r(_.innerWidth,"x"),_.mw=_.w,_.mh=_.h,_.maxWidth&&(_.mw=r(_.maxWidth,"x")-B-z,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.maxHeight&&(_.mh=r(_.maxHeight,"y")-D-K,_.mh=_.h&&_.h<_.mh?_.h:_.mh),n=_.href,$=setTimeout(function(){L.show()},100),_.inline?(c=o(dt).hide().insertBefore(e(n)[0]),at.one(rt,function(){c.replaceWith(E.children())}),u(e(n))):_.iframe?u(" "):_.html?u(_.html):h(n)?(n=l(n),e(O=new Image).addClass(Y+"Photo").bind("error",function(){_.title=!1,u(o(dt,"Error").html(_.imgError))}).one("load",function(){var e;_.retinaImage&&i.devicePixelRatio>1&&(O.height=O.height/i.devicePixelRatio,O.width=O.width/i.devicePixelRatio),_.scalePhotos&&(s=function(){O.height-=O.height*e,O.width-=O.width*e},_.mw&&O.width>_.mw&&(e=(O.width-_.mw)/O.width,s()),_.mh&&O.height>_.mh&&(e=(O.height-_.mh)/O.height,s())),_.h&&(O.style.marginTop=Math.max(_.mh-O.height,0)/2+"px"),T[1]&&(_.loop||T[A+1])&&(O.style.cursor="pointer",O.onclick=function(){G.next()}),ht&&(O.style.msInterpolationMode="bicubic"),setTimeout(function(){u(O)},1)}),setTimeout(function(){O.src=n},1)):n&&I.load(n,_.data,function(t,i){u("error"===i?o(dt,"Error").html(_.xhrError):e(this).contents())})},G.next=function(){!q&&T[1]&&(_.loop||T[A+1])&&(A=n(1),G.load())},G.prev=function(){!q&&T[1]&&(_.loop||A)&&(A=n(-1),G.load())},G.close=function(){j&&!U&&(U=!0,j=!1,d(ot,_.onCleanup),k.unbind("."+Y+" ."+st),m.fadeTo(200,0),w.stop().fadeTo(300,0,function(){w.add(m).css({opacity:1,cursor:"auto"}).hide(),d(rt),E.empty().remove(),setTimeout(function(){U=!1,d(nt,_.onClosed)},1)}))},G.remove=function(){e([]).add(w).add(m).remove(),w=null,e("."+Z).removeData(V).removeClass(Z),e(t).unbind("click."+Y)},G.element=function(){return e(N)},G.settings=J)})(jQuery,document,window);
/*! Javascript plotting library for jQuery, v. 0.7.
 *
 * Released under the MIT license by IOLA, December 2007.
 *
 */

// first an inline dependency, jquery.colorhelpers.js, we inline it here
// for convenience

/* Plugin for jQuery for working with colors.
 * 
 * Version 1.1.
 * 
 * Inspiration from jQuery color animation plugin by John Resig.
 *
 * Released under the MIT license by Ole Laursen, October 2009.
 *
 * Examples:
 *
 *   $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
 *   var c = $.color.extract($("#mydiv"), 'background-color');
 *   console.log(c.r, c.g, c.b, c.a);
 *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
 *
 * Note that .scale() and .add() return the same modified object
 * instead of making a new one.
 *
 * V. 1.1: Fix error handling so e.g. parsing an empty string does
 * produce a color rather than just crashing.
 */ 
(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);

// the actual Flot code
(function($) {
    function Plot(placeholder, data_, options_, plugins) {
        // data is on the form:
        //   [ series1, series2 ... ]
        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
        
        var series = [],
            options = {
                // the color theme used for graphs
                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
                legend: {
                    show: true,
                    noColumns: 1, // number of colums in legend table
                    labelFormatter: null, // fn: string -> string
                    labelBoxBorderColor: "#ccc", // border color for the little label boxes
                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph
                    position: "ne", // position of default legend container within plot
                    margin: 5, // distance from grid edge to default legend container within plot
                    backgroundColor: null, // null means auto-detect
                    backgroundOpacity: 0.85 // set to 0 to avoid background
                },
                xaxis: {
                    show: null, // null = auto-detect, true = always, false = never
                    position: "bottom", // or "top"
                    mode: null, // null or "time"
                    color: null, // base color, labels, ticks
                    tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
                    transform: null, // null or f: number -> number to transform axis
                    inverseTransform: null, // if transform is set, this should be the inverse function
                    min: null, // min. value to show, null means set automatically
                    max: null, // max. value to show, null means set automatically
                    autoscaleMargin: null, // margin in % to add if auto-setting min/max
                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
                    tickFormatter: null, // fn: number -> string
                    labelWidth: null, // size of tick labels in pixels
                    labelHeight: null,
                    reserveSpace: null, // whether to reserve space even if axis isn't shown
                    tickLength: null, // size in pixels of ticks, or "full" for whole line
                    alignTicksWithAxis: null, // axis number or null for no sync
                    
                    // mode specific options
                    tickDecimals: null, // no. of decimals, null means auto
                    tickSize: null, // number or [number, "unit"]
                    minTickSize: null, // number or [number, "unit"]
                    monthNames: null, // list of names of months
                    timeformat: null, // format string to use
                    twelveHourClock: false // 12 or 24 time in time mode
                },
                yaxis: {
                    autoscaleMargin: 0.02,
                    position: "left" // or "right"
                },
                xaxes: [],
                yaxes: [],
                series: {
                    points: {
                        show: false,
                        radius: 3,
                        lineWidth: 2, // in pixels
                        fill: true,
                        fillColor: "#ffffff",
                        symbol: "circle" // or callback
                    },
                    lines: {
                        // we don't put in show: false so we can see
                        // whether lines were actively disabled 
                        lineWidth: 2, // in pixels
                        fill: false,
                        fillColor: null,
                        steps: false
                    },
                    bars: {
                        show: false,
                        lineWidth: 2, // in pixels
                        barWidth: 1, // in units of the x axis
                        fill: true,
                        fillColor: null,
                        align: "left", // or "center" 
                        horizontal: false
                    },
                    shadowSize: 3
                },
                grid: {
                    show: true,
                    aboveData: false,
                    color: "#545454", // primary color used for outline and labels
                    backgroundColor: null, // null for transparent, else color
                    borderColor: null, // set if different from the grid color
                    tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"
                    labelMargin: 5, // in pixels
                    axisMargin: 8, // in pixels
                    borderWidth: 2, // in pixels
                    minBorderMargin: null, // in pixels, null means taken from points radius
                    markings: null, // array of ranges or fn: axes -> array of ranges
                    markingsColor: "#f4f4f4",
                    markingsLineWidth: 2,
                    // interactive stuff
                    clickable: false,
                    hoverable: false,
                    autoHighlight: true, // highlight in case mouse is near
                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item
                },
                hooks: {}
            },
        canvas = null,      // the canvas for the plot itself
        overlay = null,     // canvas for interactive stuff on top of plot
        eventHolder = null, // jQuery object that events should be bound to
        ctx = null, octx = null,
        xaxes = [], yaxes = [],
        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
        canvasWidth = 0, canvasHeight = 0,
        plotWidth = 0, plotHeight = 0,
        hooks = {
            processOptions: [],
            processRawData: [],
            processDatapoints: [],
            drawSeries: [],
            draw: [],
            bindEvents: [],
            drawOverlay: [],
            shutdown: []
        },
        plot = this;

        // public functions
        plot.setData = setData;
        plot.setupGrid = setupGrid;
        plot.draw = draw;
        plot.getPlaceholder = function() { return placeholder; };
        plot.getCanvas = function() { return canvas; };
        plot.getPlotOffset = function() { return plotOffset; };
        plot.width = function () { return plotWidth; };
        plot.height = function () { return plotHeight; };
        plot.offset = function () {
            var o = eventHolder.offset();
            o.left += plotOffset.left;
            o.top += plotOffset.top;
            return o;
        };
        plot.getData = function () { return series; };
        plot.getAxes = function () {
            var res = {}, i;
            $.each(xaxes.concat(yaxes), function (_, axis) {
                if (axis)
                    res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
            });
            return res;
        };
        plot.getXAxes = function () { return xaxes; };
        plot.getYAxes = function () { return yaxes; };
        plot.c2p = canvasToAxisCoords;
        plot.p2c = axisToCanvasCoords;
        plot.getOptions = function () { return options; };
        plot.highlight = highlight;
        plot.unhighlight = unhighlight;
        plot.triggerRedrawOverlay = triggerRedrawOverlay;
        plot.pointOffset = function(point) {
            return {
                left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left),
                top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top)
            };
        };
        plot.shutdown = shutdown;
        plot.resize = function () {
            getCanvasDimensions();
            resizeCanvas(canvas);
            resizeCanvas(overlay);
        };

        // public attributes
        plot.hooks = hooks;
        
        // initialize
        initPlugins(plot);
        parseOptions(options_);
        setupCanvases();
        setData(data_);
        setupGrid();
        draw();
        bindEvents();


        function executeHooks(hook, args) {
            args = [plot].concat(args);
            for (var i = 0; i < hook.length; ++i)
                hook[i].apply(this, args);
        }

        function initPlugins() {
            for (var i = 0; i < plugins.length; ++i) {
                var p = plugins[i];
                p.init(plot);
                if (p.options)
                    $.extend(true, options, p.options);
            }
        }
        
        function parseOptions(opts) {
            var i;
            
            $.extend(true, options, opts);
            
            if (options.xaxis.color == null)
                options.xaxis.color = options.grid.color;
            if (options.yaxis.color == null)
                options.yaxis.color = options.grid.color;
            
            if (options.xaxis.tickColor == null) // backwards-compatibility
                options.xaxis.tickColor = options.grid.tickColor;
            if (options.yaxis.tickColor == null) // backwards-compatibility
                options.yaxis.tickColor = options.grid.tickColor;

            if (options.grid.borderColor == null)
                options.grid.borderColor = options.grid.color;
            if (options.grid.tickColor == null)
                options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
            
            // fill in defaults in axes, copy at least always the
            // first as the rest of the code assumes it'll be there
            for (i = 0; i < Math.max(1, options.xaxes.length); ++i)
                options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);
            for (i = 0; i < Math.max(1, options.yaxes.length); ++i)
                options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);

            // backwards compatibility, to be removed in future
            if (options.xaxis.noTicks && options.xaxis.ticks == null)
                options.xaxis.ticks = options.xaxis.noTicks;
            if (options.yaxis.noTicks && options.yaxis.ticks == null)
                options.yaxis.ticks = options.yaxis.noTicks;
            if (options.x2axis) {
                options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
                options.xaxes[1].position = "top";
            }
            if (options.y2axis) {
                options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
                options.yaxes[1].position = "right";
            }
            if (options.grid.coloredAreas)
                options.grid.markings = options.grid.coloredAreas;
            if (options.grid.coloredAreasColor)
                options.grid.markingsColor = options.grid.coloredAreasColor;
            if (options.lines)
                $.extend(true, options.series.lines, options.lines);
            if (options.points)
                $.extend(true, options.series.points, options.points);
            if (options.bars)
                $.extend(true, options.series.bars, options.bars);
            if (options.shadowSize != null)
                options.series.shadowSize = options.shadowSize;

            // save options on axes for future reference
            for (i = 0; i < options.xaxes.length; ++i)
                getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
            for (i = 0; i < options.yaxes.length; ++i)
                getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];

            // add hooks from options
            for (var n in hooks)
                if (options.hooks[n] && options.hooks[n].length)
                    hooks[n] = hooks[n].concat(options.hooks[n]);

            executeHooks(hooks.processOptions, [options]);
        }

        function setData(d) {
            series = parseData(d);
            fillInSeriesOptions();
            processData();
        }
        
        function parseData(d) {
            var res = [];
            for (var i = 0; i < d.length; ++i) {
                var s = $.extend(true, {}, options.series);

                if (d[i].data != null) {
                    s.data = d[i].data; // move the data instead of deep-copy
                    delete d[i].data;

                    $.extend(true, s, d[i]);

                    d[i].data = s.data;
                }
                else
                    s.data = d[i];
                res.push(s);
            }

            return res;
        }
        
        function axisNumber(obj, coord) {
            var a = obj[coord + "axis"];
            if (typeof a == "object") // if we got a real axis, extract number
                a = a.n;
            if (typeof a != "number")
                a = 1; // default to first axis
            return a;
        }

        function allAxes() {
            // return flat array without annoying null entries
            return $.grep(xaxes.concat(yaxes), function (a) { return a; });
        }
        
        function canvasToAxisCoords(pos) {
            // return an object with x/y corresponding to all used axes 
            var res = {}, i, axis;
            for (i = 0; i < xaxes.length; ++i) {
                axis = xaxes[i];
                if (axis && axis.used)
                    res["x" + axis.n] = axis.c2p(pos.left);
            }

            for (i = 0; i < yaxes.length; ++i) {
                axis = yaxes[i];
                if (axis && axis.used)
                    res["y" + axis.n] = axis.c2p(pos.top);
            }
            
            if (res.x1 !== undefined)
                res.x = res.x1;
            if (res.y1 !== undefined)
                res.y = res.y1;

            return res;
        }
        
        function axisToCanvasCoords(pos) {
            // get canvas coords from the first pair of x/y found in pos
            var res = {}, i, axis, key;

            for (i = 0; i < xaxes.length; ++i) {
                axis = xaxes[i];
                if (axis && axis.used) {
                    key = "x" + axis.n;
                    if (pos[key] == null && axis.n == 1)
                        key = "x";

                    if (pos[key] != null) {
                        res.left = axis.p2c(pos[key]);
                        break;
                    }
                }
            }
            
            for (i = 0; i < yaxes.length; ++i) {
                axis = yaxes[i];
                if (axis && axis.used) {
                    key = "y" + axis.n;
                    if (pos[key] == null && axis.n == 1)
                        key = "y";

                    if (pos[key] != null) {
                        res.top = axis.p2c(pos[key]);
                        break;
                    }
                }
            }
            
            return res;
        }
        
        function getOrCreateAxis(axes, number) {
            if (!axes[number - 1])
                axes[number - 1] = {
                    n: number, // save the number for future reference
                    direction: axes == xaxes ? "x" : "y",
                    options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
                };
                
            return axes[number - 1];
        }

        function fillInSeriesOptions() {
            var i;
            
            // collect what we already got of colors
            var neededColors = series.length,
                usedColors = [],
                assignedColors = [];
            for (i = 0; i < series.length; ++i) {
                var sc = series[i].color;
                if (sc != null) {
                    --neededColors;
                    if (typeof sc == "number")
                        assignedColors.push(sc);
                    else
                        usedColors.push($.color.parse(series[i].color));
                }
            }
            
            // we might need to generate more colors if higher indices
            // are assigned
            for (i = 0; i < assignedColors.length; ++i) {
                neededColors = Math.max(neededColors, assignedColors[i] + 1);
            }

            // produce colors as needed
            var colors = [], variation = 0;
            i = 0;
            while (colors.length < neededColors) {
                var c;
                if (options.colors.length == i) // check degenerate case
                    c = $.color.make(100, 100, 100);
                else
                    c = $.color.parse(options.colors[i]);

                // vary color if needed
                var sign = variation % 2 == 1 ? -1 : 1;
                c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)

                // FIXME: if we're getting to close to something else,
                // we should probably skip this one
                colors.push(c);
                
                ++i;
                if (i >= options.colors.length) {
                    i = 0;
                    ++variation;
                }
            }

            // fill in the options
            var colori = 0, s;
            for (i = 0; i < series.length; ++i) {
                s = series[i];
                
                // assign colors
                if (s.color == null) {
                    s.color = colors[colori].toString();
                    ++colori;
                }
                else if (typeof s.color == "number")
                    s.color = colors[s.color].toString();

                // turn on lines automatically in case nothing is set
                if (s.lines.show == null) {
                    var v, show = true;
                    for (v in s)
                        if (s[v] && s[v].show) {
                            show = false;
                            break;
                        }
                    if (show)
                        s.lines.show = true;
                }

                // setup axes
                s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
                s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
            }
        }
        
        function processData() {
            var topSentry = Number.POSITIVE_INFINITY,
                bottomSentry = Number.NEGATIVE_INFINITY,
                fakeInfinity = Number.MAX_VALUE,
                i, j, k, m, length,
                s, points, ps, x, y, axis, val, f, p;

            function updateAxis(axis, min, max) {
                if (min < axis.datamin && min != -fakeInfinity)
                    axis.datamin = min;
                if (max > axis.datamax && max != fakeInfinity)
                    axis.datamax = max;
            }

            $.each(allAxes(), function (_, axis) {
                // init axis
                axis.datamin = topSentry;
                axis.datamax = bottomSentry;
                axis.used = false;
            });
            
            for (i = 0; i < series.length; ++i) {
                s = series[i];
                s.datapoints = { points: [] };
                
                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
            }
            
            // first pass: clean and copy data
            for (i = 0; i < series.length; ++i) {
                s = series[i];

                var data = s.data, format = s.datapoints.format;

                if (!format) {
                    format = [];
                    // find out how to copy
                    format.push({ x: true, number: true, required: true });
                    format.push({ y: true, number: true, required: true });

                    if (s.bars.show || (s.lines.show && s.lines.fill)) {
                        format.push({ y: true, number: true, required: false, defaultValue: 0 });
                        if (s.bars.horizontal) {
                            delete format[format.length - 1].y;
                            format[format.length - 1].x = true;
                        }
                    }
                    
                    s.datapoints.format = format;
                }

                if (s.datapoints.pointsize != null)
                    continue; // already filled in

                s.datapoints.pointsize = format.length;
                
                ps = s.datapoints.pointsize;
                points = s.datapoints.points;

                insertSteps = s.lines.show && s.lines.steps;
                s.xaxis.used = s.yaxis.used = true;
                
                for (j = k = 0; j < data.length; ++j, k += ps) {
                    p = data[j];

                    var nullify = p == null;
                    if (!nullify) {
                        for (m = 0; m < ps; ++m) {
                            val = p[m];
                            f = format[m];

                            if (f) {
                                if (f.number && val != null) {
                                    val = +val; // convert to number
                                    if (isNaN(val))
                                        val = null;
                                    else if (val == Infinity)
                                        val = fakeInfinity;
                                    else if (val == -Infinity)
                                        val = -fakeInfinity;
                                }

                                if (val == null) {
                                    if (f.required)
                                        nullify = true;
                                    
                                    if (f.defaultValue != null)
                                        val = f.defaultValue;
                                }
                            }
                            
                            points[k + m] = val;
                        }
                    }
                    
                    if (nullify) {
                        for (m = 0; m < ps; ++m) {
                            val = points[k + m];
                            if (val != null) {
                                f = format[m];
                                // extract min/max info
                                if (f.x)
                                    updateAxis(s.xaxis, val, val);
                                if (f.y)
                                    updateAxis(s.yaxis, val, val);
                            }
                            points[k + m] = null;
                        }
                    }
                    else {
                        // a little bit of line specific stuff that
                        // perhaps shouldn't be here, but lacking
                        // better means...
                        if (insertSteps && k > 0
                            && points[k - ps] != null
                            && points[k - ps] != points[k]
                            && points[k - ps + 1] != points[k + 1]) {
                            // copy the point to make room for a middle point
                            for (m = 0; m < ps; ++m)
                                points[k + ps + m] = points[k + m];

                            // middle point has same y
                            points[k + 1] = points[k - ps + 1];

                            // we've added a point, better reflect that
                            k += ps;
                        }
                    }
                }
            }

            // give the hooks a chance to run
            for (i = 0; i < series.length; ++i) {
                s = series[i];
                
                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
            }

            // second pass: find datamax/datamin for auto-scaling
            for (i = 0; i < series.length; ++i) {
                s = series[i];
                points = s.datapoints.points,
                ps = s.datapoints.pointsize;

                var xmin = topSentry, ymin = topSentry,
                    xmax = bottomSentry, ymax = bottomSentry;
                
                for (j = 0; j < points.length; j += ps) {
                    if (points[j] == null)
                        continue;

                    for (m = 0; m < ps; ++m) {
                        val = points[j + m];
                        f = format[m];
                        if (!f || val == fakeInfinity || val == -fakeInfinity)
                            continue;
                        
                        if (f.x) {
                            if (val < xmin)
                                xmin = val;
                            if (val > xmax)
                                xmax = val;
                        }
                        if (f.y) {
                            if (val < ymin)
                                ymin = val;
                            if (val > ymax)
                                ymax = val;
                        }
                    }
                }
                
                if (s.bars.show) {
                    // make sure we got room for the bar on the dancing floor
                    var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
                    if (s.bars.horizontal) {
                        ymin += delta;
                        ymax += delta + s.bars.barWidth;
                    }
                    else {
                        xmin += delta;
                        xmax += delta + s.bars.barWidth;
                    }
                }
                
                updateAxis(s.xaxis, xmin, xmax);
                updateAxis(s.yaxis, ymin, ymax);
            }

            $.each(allAxes(), function (_, axis) {
                if (axis.datamin == topSentry)
                    axis.datamin = null;
                if (axis.datamax == bottomSentry)
                    axis.datamax = null;
            });
        }

        function makeCanvas(skipPositioning, cls) {
            var c = document.createElement('canvas');
            c.className = cls;
            c.width = canvasWidth;
            c.height = canvasHeight;
                    
            if (!skipPositioning)
                $(c).css({ position: 'absolute', left: 0, top: 0 });
                
            $(c).appendTo(placeholder);
                
            if (!c.getContext) // excanvas hack
                c = window.G_vmlCanvasManager.initElement(c);

            // used for resetting in case we get replotted
            c.getContext("2d").save();
            
            return c;
        }

        function getCanvasDimensions() {
            canvasWidth = placeholder.width();
            canvasHeight = placeholder.height();
            
            if (canvasWidth <= 0 || canvasHeight <= 0)
                throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
        }

        function resizeCanvas(c) {
            // resizing should reset the state (excanvas seems to be
            // buggy though)
            if (c.width != canvasWidth)
                c.width = canvasWidth;

            if (c.height != canvasHeight)
                c.height = canvasHeight;

            // so try to get back to the initial state (even if it's
            // gone now, this should be safe according to the spec)
            var cctx = c.getContext("2d");
            cctx.restore();

            // and save again
            cctx.save();
        }
        
        function setupCanvases() {
            var reused,
                existingCanvas = placeholder.children("canvas.base"),
                existingOverlay = placeholder.children("canvas.overlay");

            if (existingCanvas.length == 0 || existingOverlay == 0) {
                // init everything
                
                placeholder.html(""); // make sure placeholder is clear
            
                placeholder.css({ padding: 0 }); // padding messes up the positioning
                
                if (placeholder.css("position") == 'static')
                    placeholder.css("position", "relative"); // for positioning labels and overlay

                getCanvasDimensions();
                
                canvas = makeCanvas(true, "base");
                overlay = makeCanvas(false, "overlay"); // overlay canvas for interactive features

                reused = false;
            }
            else {
                // reuse existing elements

                canvas = existingCanvas.get(0);
                overlay = existingOverlay.get(0);

                reused = true;
            }

            ctx = canvas.getContext("2d");
            octx = overlay.getContext("2d");

            // we include the canvas in the event holder too, because IE 7
            // sometimes has trouble with the stacking order
            eventHolder = $([overlay, canvas]);

            if (reused) {
                // run shutdown in the old plot object
                placeholder.data("plot").shutdown();

                // reset reused canvases
                plot.resize();
                
                // make sure overlay pixels are cleared (canvas is cleared when we redraw)
                octx.clearRect(0, 0, canvasWidth, canvasHeight);
                
                // then whack any remaining obvious garbage left
                eventHolder.unbind();
                placeholder.children().not([canvas, overlay]).remove();
            }

            // save in case we get replotted
            placeholder.data("plot", plot);
        }

        function bindEvents() {
            // bind events
            if (options.grid.hoverable) {
                eventHolder.mousemove(onMouseMove);
                eventHolder.mouseleave(onMouseLeave);
            }

            if (options.grid.clickable)
                eventHolder.click(onClick);

            executeHooks(hooks.bindEvents, [eventHolder]);
        }

        function shutdown() {
            if (redrawTimeout)
                clearTimeout(redrawTimeout);
            
            eventHolder.unbind("mousemove", onMouseMove);
            eventHolder.unbind("mouseleave", onMouseLeave);
            eventHolder.unbind("click", onClick);
            
            executeHooks(hooks.shutdown, [eventHolder]);
        }

        function setTransformationHelpers(axis) {
            // set helper functions on the axis, assumes plot area
            // has been computed already
            
            function identity(x) { return x; }
            
            var s, m, t = axis.options.transform || identity,
                it = axis.options.inverseTransform;
            
            // precompute how much the axis is scaling a point
            // in canvas space
            if (axis.direction == "x") {
                s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
                m = Math.min(t(axis.max), t(axis.min));
            }
            else {
                s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
                s = -s;
                m = Math.max(t(axis.max), t(axis.min));
            }

            // data point to canvas coordinate
            if (t == identity) // slight optimization
                axis.p2c = function (p) { return (p - m) * s; };
            else
                axis.p2c = function (p) { return (t(p) - m) * s; };
            // canvas coordinate to data point
            if (!it)
                axis.c2p = function (c) { return m + c / s; };
            else
                axis.c2p = function (c) { return it(m + c / s); };
        }

        function measureTickLabels(axis) {
            var opts = axis.options, i, ticks = axis.ticks || [], labels = [],
                l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv;

            function makeDummyDiv(labels, width) {
                return $('<div style="position:absolute;top:-10000px;' + width + 'font-size:smaller">' +
                         '<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">'
                         + labels.join("") + '</div></div>')
                    .appendTo(placeholder);
            }
            
            if (axis.direction == "x") {
                // to avoid measuring the widths of the labels (it's slow), we
                // construct fixed-size boxes and put the labels inside
                // them, we don't need the exact figures and the
                // fixed-size box content is easy to center
                if (w == null)
                    w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1));

                // measure x label heights
                if (h == null) {
                    labels = [];
                    for (i = 0; i < ticks.length; ++i) {
                        l = ticks[i].label;
                        if (l)
                            labels.push('<div class="tickLabel" style="float:left;width:' + w + 'px">' + l + '</div>');
                    }

                    if (labels.length > 0) {
                        // stick them all in the same div and measure
                        // collective height
                        labels.push('<div style="clear:left"></div>');
                        dummyDiv = makeDummyDiv(labels, "width:10000px;");
                        h = dummyDiv.height();
                        dummyDiv.remove();
                    }
                }
            }
            else if (w == null || h == null) {
                // calculate y label dimensions
                for (i = 0; i < ticks.length; ++i) {
                    l = ticks[i].label;
                    if (l)
                        labels.push('<div class="tickLabel">' + l + '</div>');
                }
                
                if (labels.length > 0) {
                    dummyDiv = makeDummyDiv(labels, "");
                    if (w == null)
                        w = dummyDiv.children().width();
                    if (h == null)
                        h = dummyDiv.find("div.tickLabel").height();
                    dummyDiv.remove();
                }
            }

            if (w == null)
                w = 0;
            if (h == null)
                h = 0;

            axis.labelWidth = w;
            axis.labelHeight = h;
        }

        function allocateAxisBoxFirstPhase(axis) {
            // find the bounding box of the axis by looking at label
            // widths/heights and ticks, make room by diminishing the
            // plotOffset

            var lw = axis.labelWidth,
                lh = axis.labelHeight,
                pos = axis.options.position,
                tickLength = axis.options.tickLength,
                axismargin = options.grid.axisMargin,
                padding = options.grid.labelMargin,
                all = axis.direction == "x" ? xaxes : yaxes,
                index;

            // determine axis margin
            var samePosition = $.grep(all, function (a) {
                return a && a.options.position == pos && a.reserveSpace;
            });
            if ($.inArray(axis, samePosition) == samePosition.length - 1)
                axismargin = 0; // outermost

            // determine tick length - if we're innermost, we can use "full"
            if (tickLength == null)
                tickLength = "full";

            var sameDirection = $.grep(all, function (a) {
                return a && a.reserveSpace;
            });

            var innermost = $.inArray(axis, sameDirection) == 0;
            if (!innermost && tickLength == "full")
                tickLength = 5;
                
            if (!isNaN(+tickLength))
                padding += +tickLength;

            // compute box
            if (axis.direction == "x") {
                lh += padding;
                
                if (pos == "bottom") {
                    plotOffset.bottom += lh + axismargin;
                    axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };
                }
                else {
                    axis.box = { top: plotOffset.top + axismargin, height: lh };
                    plotOffset.top += lh + axismargin;
                }
            }
            else {
                lw += padding;
                
                if (pos == "left") {
                    axis.box = { left: plotOffset.left + axismargin, width: lw };
                    plotOffset.left += lw + axismargin;
                }
                else {
                    plotOffset.right += lw + axismargin;
                    axis.box = { left: canvasWidth - plotOffset.right, width: lw };
                }
            }

             // save for future reference
            axis.position = pos;
            axis.tickLength = tickLength;
            axis.box.padding = padding;
            axis.innermost = innermost;
        }

        function allocateAxisBoxSecondPhase(axis) {
            // set remaining bounding box coordinates
            if (axis.direction == "x") {
                axis.box.left = plotOffset.left;
                axis.box.width = plotWidth;
            }
            else {
                axis.box.top = plotOffset.top;
                axis.box.height = plotHeight;
            }
        }
        
        function setupGrid() {
            var i, axes = allAxes();

            // first calculate the plot and axis box dimensions

            $.each(axes, function (_, axis) {
                axis.show = axis.options.show;
                if (axis.show == null)
                    axis.show = axis.used; // by default an axis is visible if it's got data
                
                axis.reserveSpace = axis.show || axis.options.reserveSpace;

                setRange(axis);
            });

            allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });

            plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;
            if (options.grid.show) {
                $.each(allocatedAxes, function (_, axis) {
                    // make the ticks
                    setupTickGeneration(axis);
                    setTicks(axis);
                    snapRangeToTicks(axis, axis.ticks);

                    // find labelWidth/Height for axis
                    measureTickLabels(axis);
                });

                // with all dimensions in house, we can compute the
                // axis boxes, start from the outside (reverse order)
                for (i = allocatedAxes.length - 1; i >= 0; --i)
                    allocateAxisBoxFirstPhase(allocatedAxes[i]);

                // make sure we've got enough space for things that
                // might stick out
                var minMargin = options.grid.minBorderMargin;
                if (minMargin == null) {
                    minMargin = 0;
                    for (i = 0; i < series.length; ++i)
                        minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2);
                }
                    
                for (var a in plotOffset) {
                    plotOffset[a] += options.grid.borderWidth;
                    plotOffset[a] = Math.max(minMargin, plotOffset[a]);
                }
            }
            
            plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
            plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;

            // now we got the proper plotWidth/Height, we can compute the scaling
            $.each(axes, function (_, axis) {
                setTransformationHelpers(axis);
            });

            if (options.grid.show) {
                $.each(allocatedAxes, function (_, axis) {
                    allocateAxisBoxSecondPhase(axis);
                });

                insertAxisLabels();
            }
            
            insertLegend();
        }
        
        function setRange(axis) {
            var opts = axis.options,
                min = +(opts.min != null ? opts.min : axis.datamin),
                max = +(opts.max != null ? opts.max : axis.datamax),
                delta = max - min;

            if (delta == 0.0) {
                // degenerate case
                var widen = max == 0 ? 1 : 0.01;

                if (opts.min == null)
                    min -= widen;
                // always widen max if we couldn't widen min to ensure we
                // don't fall into min == max which doesn't work
                if (opts.max == null || opts.min != null)
                    max += widen;
            }
            else {
                // consider autoscaling
                var margin = opts.autoscaleMargin;
                if (margin != null) {
                    if (opts.min == null) {
                        min -= delta * margin;
                        // make sure we don't go below zero if all values
                        // are positive
                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)
                            min = 0;
                    }
                    if (opts.max == null) {
                        max += delta * margin;
                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)
                            max = 0;
                    }
                }
            }
            axis.min = min;
            axis.max = max;
        }

        function setupTickGeneration(axis) {
            var opts = axis.options;
                
            // estimate number of ticks
            var noTicks;
            if (typeof opts.ticks == "number" && opts.ticks > 0)
                noTicks = opts.ticks;
            else
                // heuristic based on the model a*sqrt(x) fitted to
                // some data points that seemed reasonable
                noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight);

            var delta = (axis.max - axis.min) / noTicks,
                size, generator, unit, formatter, i, magn, norm;

            if (opts.mode == "time") {
                // pretty handling of time
                
                // map of app. size of time units in milliseconds
                var timeUnitSize = {
                    "second": 1000,
                    "minute": 60 * 1000,
                    "hour": 60 * 60 * 1000,
                    "day": 24 * 60 * 60 * 1000,
                    "month": 30 * 24 * 60 * 60 * 1000,
                    "year": 365.2425 * 24 * 60 * 60 * 1000
                };


                // the allowed tick sizes, after 1 year we use
                // an integer algorithm
                var spec = [
                    [1, "second"], [2, "second"], [5, "second"], [10, "second"],
                    [30, "second"], 
                    [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
                    [30, "minute"], 
                    [1, "hour"], [2, "hour"], [4, "hour"],
                    [8, "hour"], [12, "hour"],
                    [1, "day"], [2, "day"], [3, "day"],
                    [0.25, "month"], [0.5, "month"], [1, "month"],
                    [2, "month"], [3, "month"], [6, "month"],
                    [1, "year"]
                ];

                var minSize = 0;
                if (opts.minTickSize != null) {
                    if (typeof opts.tickSize == "number")
                        minSize = opts.tickSize;
                    else
                        minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
                }

                for (var i = 0; i < spec.length - 1; ++i)
                    if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
                                 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
                       && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
                        break;
                size = spec[i][0];
                unit = spec[i][1];
                
                // special-case the possibility of several years
                if (unit == "year") {
                    magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
                    norm = (delta / timeUnitSize.year) / magn;
                    if (norm < 1.5)
                        size = 1;
                    else if (norm < 3)
                        size = 2;
                    else if (norm < 7.5)
                        size = 5;
                    else
                        size = 10;

                    size *= magn;
                }

                axis.tickSize = opts.tickSize || [size, unit];
                
                generator = function(axis) {
                    var ticks = [],
                        tickSize = axis.tickSize[0], unit = axis.tickSize[1],
                        d = new Date(axis.min);
                    
                    var step = tickSize * timeUnitSize[unit];

                    if (unit == "second")
                        d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
                    if (unit == "minute")
                        d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
                    if (unit == "hour")
                        d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
                    if (unit == "month")
                        d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
                    if (unit == "year")
                        d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
                    
                    // reset smaller components
                    d.setUTCMilliseconds(0);
                    if (step >= timeUnitSize.minute)
                        d.setUTCSeconds(0);
                    if (step >= timeUnitSize.hour)
                        d.setUTCMinutes(0);
                    if (step >= timeUnitSize.day)
                        d.setUTCHours(0);
                    if (step >= timeUnitSize.day * 4)
                        d.setUTCDate(1);
                    if (step >= timeUnitSize.year)
                        d.setUTCMonth(0);


                    var carry = 0, v = Number.NaN, prev;
                    do {
                        prev = v;
                        v = d.getTime();
                        ticks.push(v);
                        if (unit == "month") {
                            if (tickSize < 1) {
                                // a bit complicated - we'll divide the month
                                // up but we need to take care of fractions
                                // so we don't end up in the middle of a day
                                d.setUTCDate(1);
                                var start = d.getTime();
                                d.setUTCMonth(d.getUTCMonth() + 1);
                                var end = d.getTime();
                                d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
                                carry = d.getUTCHours();
                                d.setUTCHours(0);
                            }
                            else
                                d.setUTCMonth(d.getUTCMonth() + tickSize);
                        }
                        else if (unit == "year") {
                            d.setUTCFullYear(d.getUTCFullYear() + tickSize);
                        }
                        else
                            d.setTime(v + step);
                    } while (v < axis.max && v != prev);

                    return ticks;
                };

                formatter = function (v, axis) {
                    var d = new Date(v);

                    // first check global format
                    if (opts.timeformat != null)
                        return $.plot.formatDate(d, opts.timeformat, opts.monthNames);
                    
                    var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
                    var span = axis.max - axis.min;
                    var suffix = (opts.twelveHourClock) ? " %p" : "";
                    
                    if (t < timeUnitSize.minute)
                        fmt = "%h:%M:%S" + suffix;
                    else if (t < timeUnitSize.day) {
                        if (span < 2 * timeUnitSize.day)
                            fmt = "%h:%M" + suffix;
                        else
                            fmt = "%b %d %h:%M" + suffix;
                    }
                    else if (t < timeUnitSize.month)
                        fmt = "%b %d";
                    else if (t < timeUnitSize.year) {
                        if (span < timeUnitSize.year)
                            fmt = "%b";
                        else
                            fmt = "%b %y";
                    }
                    else
                        fmt = "%y";
                    
                    return $.plot.formatDate(d, fmt, opts.monthNames);
                };
            }
            else {
                // pretty rounding of base-10 numbers
                var maxDec = opts.tickDecimals;
                var dec = -Math.floor(Math.log(delta) / Math.LN10);
                if (maxDec != null && dec > maxDec)
                    dec = maxDec;

                magn = Math.pow(10, -dec);
                norm = delta / magn; // norm is between 1.0 and 10.0
                
                if (norm < 1.5)
                    size = 1;
                else if (norm < 3) {
                    size = 2;
                    // special case for 2.5, requires an extra decimal
                    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
                        size = 2.5;
                        ++dec;
                    }
                }
                else if (norm < 7.5)
                    size = 5;
                else
                    size = 10;

                size *= magn;
                
                if (opts.minTickSize != null && size < opts.minTickSize)
                    size = opts.minTickSize;

                axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
                axis.tickSize = opts.tickSize || size;

                generator = function (axis) {
                    var ticks = [];

                    // spew out all possible ticks
                    var start = floorInBase(axis.min, axis.tickSize),
                        i = 0, v = Number.NaN, prev;
                    do {
                        prev = v;
                        v = start + i * axis.tickSize;
                        ticks.push(v);
                        ++i;
                    } while (v < axis.max && v != prev);
                    return ticks;
                };

                formatter = function (v, axis) {
                    return v.toFixed(axis.tickDecimals);
                };
            }

            if (opts.alignTicksWithAxis != null) {
                var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
                if (otherAxis && otherAxis.used && otherAxis != axis) {
                    // consider snapping min/max to outermost nice ticks
                    var niceTicks = generator(axis);
                    if (niceTicks.length > 0) {
                        if (opts.min == null)
                            axis.min = Math.min(axis.min, niceTicks[0]);
                        if (opts.max == null && niceTicks.length > 1)
                            axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
                    }
                    
                    generator = function (axis) {
                        // copy ticks, scaled to this axis
                        var ticks = [], v, i;
                        for (i = 0; i < otherAxis.ticks.length; ++i) {
                            v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
                            v = axis.min + v * (axis.max - axis.min);
                            ticks.push(v);
                        }
                        return ticks;
                    };
                    
                    // we might need an extra decimal since forced
                    // ticks don't necessarily fit naturally
                    if (axis.mode != "time" && opts.tickDecimals == null) {
                        var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),
                            ts = generator(axis);

                        // only proceed if the tick interval rounded
                        // with an extra decimal doesn't give us a
                        // zero at end
                        if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
                            axis.tickDecimals = extraDec;
                    }
                }
            }

            axis.tickGenerator = generator;
            if ($.isFunction(opts.tickFormatter))
                axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
            else
                axis.tickFormatter = formatter;
        }
        
        function setTicks(axis) {
            var oticks = axis.options.ticks, ticks = [];
            if (oticks == null || (typeof oticks == "number" && oticks > 0))
                ticks = axis.tickGenerator(axis);
            else if (oticks) {
                if ($.isFunction(oticks))
                    // generate the ticks
                    ticks = oticks({ min: axis.min, max: axis.max });
                else
                    ticks = oticks;
            }

            // clean up/labelify the supplied ticks, copy them over
            var i, v;
            axis.ticks = [];
            for (i = 0; i < ticks.length; ++i) {
                var label = null;
                var t = ticks[i];
                if (typeof t == "object") {
                    v = +t[0];
                    if (t.length > 1)
                        label = t[1];
                }
                else
                    v = +t;
                if (label == null)
                    label = axis.tickFormatter(v, axis);
                if (!isNaN(v))
                    axis.ticks.push({ v: v, label: label });
            }
        }

        function snapRangeToTicks(axis, ticks) {
            if (axis.options.autoscaleMargin && ticks.length > 0) {
                // snap to ticks
                if (axis.options.min == null)
                    axis.min = Math.min(axis.min, ticks[0].v);
                if (axis.options.max == null && ticks.length > 1)
                    axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
            }
        }
      
        function draw() {
            ctx.clearRect(0, 0, canvasWidth, canvasHeight);

            var grid = options.grid;

            // draw background, if any
            if (grid.show && grid.backgroundColor)
                drawBackground();
            
            if (grid.show && !grid.aboveData)
                drawGrid();

            for (var i = 0; i < series.length; ++i) {
                executeHooks(hooks.drawSeries, [ctx, series[i]]);
                drawSeries(series[i]);
            }

            executeHooks(hooks.draw, [ctx]);
            
            if (grid.show && grid.aboveData)
                drawGrid();
        }

        function extractRange(ranges, coord) {
            var axis, from, to, key, axes = allAxes();

            for (i = 0; i < axes.length; ++i) {
                axis = axes[i];
                if (axis.direction == coord) {
                    key = coord + axis.n + "axis";
                    if (!ranges[key] && axis.n == 1)
                        key = coord + "axis"; // support x1axis as xaxis
                    if (ranges[key]) {
                        from = ranges[key].from;
                        to = ranges[key].to;
                        break;
                    }
                }
            }

            // backwards-compat stuff - to be removed in future
            if (!ranges[key]) {
                axis = coord == "x" ? xaxes[0] : yaxes[0];
                from = ranges[coord + "1"];
                to = ranges[coord + "2"];
            }

            // auto-reverse as an added bonus
            if (from != null && to != null && from > to) {
                var tmp = from;
                from = to;
                to = tmp;
            }
            
            return { from: from, to: to, axis: axis };
        }
        
        function drawBackground() {
            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
            ctx.fillRect(0, 0, plotWidth, plotHeight);
            ctx.restore();
        }

        function drawGrid() {
            var i;
            
            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            // draw markings
            var markings = options.grid.markings;
            if (markings) {
                if ($.isFunction(markings)) {
                    var axes = plot.getAxes();
                    // xmin etc. is backwards compatibility, to be
                    // removed in the future
                    axes.xmin = axes.xaxis.min;
                    axes.xmax = axes.xaxis.max;
                    axes.ymin = axes.yaxis.min;
                    axes.ymax = axes.yaxis.max;
                    
                    markings = markings(axes);
                }

                for (i = 0; i < markings.length; ++i) {
                    var m = markings[i],
                        xrange = extractRange(m, "x"),
                        yrange = extractRange(m, "y");

                    // fill in missing
                    if (xrange.from == null)
                        xrange.from = xrange.axis.min;
                    if (xrange.to == null)
                        xrange.to = xrange.axis.max;
                    if (yrange.from == null)
                        yrange.from = yrange.axis.min;
                    if (yrange.to == null)
                        yrange.to = yrange.axis.max;

                    // clip
                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
                        continue;

                    xrange.from = Math.max(xrange.from, xrange.axis.min);
                    xrange.to = Math.min(xrange.to, xrange.axis.max);
                    yrange.from = Math.max(yrange.from, yrange.axis.min);
                    yrange.to = Math.min(yrange.to, yrange.axis.max);

                    if (xrange.from == xrange.to && yrange.from == yrange.to)
                        continue;

                    // then draw
                    xrange.from = xrange.axis.p2c(xrange.from);
                    xrange.to = xrange.axis.p2c(xrange.to);
                    yrange.from = yrange.axis.p2c(yrange.from);
                    yrange.to = yrange.axis.p2c(yrange.to);
                    
                    if (xrange.from == xrange.to || yrange.from == yrange.to) {
                        // draw line
                        ctx.beginPath();
                        ctx.strokeStyle = m.color || options.grid.markingsColor;
                        ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
                        ctx.moveTo(xrange.from, yrange.from);
                        ctx.lineTo(xrange.to, yrange.to);
                        ctx.stroke();
                    }
                    else {
                        // fill area
                        ctx.fillStyle = m.color || options.grid.markingsColor;
                        ctx.fillRect(xrange.from, yrange.to,
                                     xrange.to - xrange.from,
                                     yrange.from - yrange.to);
                    }
                }
            }
            
            // draw the ticks
            var axes = allAxes(), bw = options.grid.borderWidth;

            for (var j = 0; j < axes.length; ++j) {
                var axis = axes[j], box = axis.box,
                    t = axis.tickLength, x, y, xoff, yoff;
                if (!axis.show || axis.ticks.length == 0)
                    continue
                
                ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString();
                ctx.lineWidth = 1;

                // find the edges
                if (axis.direction == "x") {
                    x = 0;
                    if (t == "full")
                        y = (axis.position == "top" ? 0 : plotHeight);
                    else
                        y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
                }
                else {
                    y = 0;
                    if (t == "full")
                        x = (axis.position == "left" ? 0 : plotWidth);
                    else
                        x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
                }
                
                // draw tick bar
                if (!axis.innermost) {
                    ctx.beginPath();
                    xoff = yoff = 0;
                    if (axis.direction == "x")
                        xoff = plotWidth;
                    else
                        yoff = plotHeight;
                    
                    if (ctx.lineWidth == 1) {
                        x = Math.floor(x) + 0.5;
                        y = Math.floor(y) + 0.5;
                    }

                    ctx.moveTo(x, y);
                    ctx.lineTo(x + xoff, y + yoff);
                    ctx.stroke();
                }

                // draw ticks
                ctx.beginPath();
                for (i = 0; i < axis.ticks.length; ++i) {
                    var v = axis.ticks[i].v;
                    
                    xoff = yoff = 0;

                    if (v < axis.min || v > axis.max
                        // skip those lying on the axes if we got a border
                        || (t == "full" && bw > 0
                            && (v == axis.min || v == axis.max)))
                        continue;

                    if (axis.direction == "x") {
                        x = axis.p2c(v);
                        yoff = t == "full" ? -plotHeight : t;
                        
                        if (axis.position == "top")
                            yoff = -yoff;
                    }
                    else {
                        y = axis.p2c(v);
                        xoff = t == "full" ? -plotWidth : t;
                        
                        if (axis.position == "left")
                            xoff = -xoff;
                    }

                    if (ctx.lineWidth == 1) {
                        if (axis.direction == "x")
                            x = Math.floor(x) + 0.5;
                        else
                            y = Math.floor(y) + 0.5;
                    }

                    ctx.moveTo(x, y);
                    ctx.lineTo(x + xoff, y + yoff);
                }
                
                ctx.stroke();
            }
            
            
            // draw border
            if (bw) {
                ctx.lineWidth = bw;
                ctx.strokeStyle = options.grid.borderColor;
                ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
            }

            ctx.restore();
        }

        function insertAxisLabels() {
            placeholder.find(".tickLabels").remove();
            
            var html = ['<div class="tickLabels" style="font-size:smaller">'];

            var axes = allAxes();
            for (var j = 0; j < axes.length; ++j) {
                var axis = axes[j], box = axis.box;
                if (!axis.show)
                    continue;
                //debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width +  'px;height:' + box.height + 'px"></div>')
                html.push('<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis" style="color:' + axis.options.color + '">');
                for (var i = 0; i < axis.ticks.length; ++i) {
                    var tick = axis.ticks[i];
                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)
                        continue;

                    var pos = {}, align;
                    
                    if (axis.direction == "x") {
                        align = "center";
                        pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2);
                        if (axis.position == "bottom")
                            pos.top = box.top + box.padding;
                        else
                            pos.bottom = canvasHeight - (box.top + box.height - box.padding);
                    }
                    else {
                        pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2);
                        if (axis.position == "left") {
                            pos.right = canvasWidth - (box.left + box.width - box.padding)
                            align = "right";
                        }
                        else {
                            pos.left = box.left + box.padding;
                            align = "left";
                        }
                    }

                    pos.width = axis.labelWidth;

                    var style = ["position:absolute", "text-align:" + align ];
                    for (var a in pos)
                        style.push(a + ":" + pos[a] + "px")
                    
                    html.push('<div class="tickLabel" style="' + style.join(';') + '">' + tick.label + '</div>');
                }
                html.push('</div>');
            }

            html.push('</div>');

            placeholder.append(html.join(""));
        }

        function drawSeries(series) {
            if (series.lines.show)
                drawSeriesLines(series);
            if (series.bars.show)
                drawSeriesBars(series);
            if (series.points.show)
                drawSeriesPoints(series);
        }
        
        function drawSeriesLines(series) {
            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
                var points = datapoints.points,
                    ps = datapoints.pointsize,
                    prevx = null, prevy = null;
                
                ctx.beginPath();
                for (var i = ps; i < points.length; i += ps) {
                    var x1 = points[i - ps], y1 = points[i - ps + 1],
                        x2 = points[i], y2 = points[i + 1];
                    
                    if (x1 == null || x2 == null)
                        continue;

                    // clip with ymin
                    if (y1 <= y2 && y1 < axisy.min) {
                        if (y2 < axisy.min)
                            continue;   // line segment is outside
                        // compute new intersection point
                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y1 = axisy.min;
                    }
                    else if (y2 <= y1 && y2 < axisy.min) {
                        if (y1 < axisy.min)
                            continue;
                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y2 = axisy.min;
                    }

                    // clip with ymax
                    if (y1 >= y2 && y1 > axisy.max) {
                        if (y2 > axisy.max)
                            continue;
                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y1 = axisy.max;
                    }
                    else if (y2 >= y1 && y2 > axisy.max) {
                        if (y1 > axisy.max)
                            continue;
                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y2 = axisy.max;
                    }

                    // clip with xmin
                    if (x1 <= x2 && x1 < axisx.min) {
                        if (x2 < axisx.min)
                            continue;
                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x1 = axisx.min;
                    }
                    else if (x2 <= x1 && x2 < axisx.min) {
                        if (x1 < axisx.min)
                            continue;
                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x2 = axisx.min;
                    }

                    // clip with xmax
                    if (x1 >= x2 && x1 > axisx.max) {
                        if (x2 > axisx.max)
                            continue;
                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x1 = axisx.max;
                    }
                    else if (x2 >= x1 && x2 > axisx.max) {
                        if (x1 > axisx.max)
                            continue;
                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x2 = axisx.max;
                    }

                    if (x1 != prevx || y1 != prevy)
                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
                    
                    prevx = x2;
                    prevy = y2;
                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
                }
                ctx.stroke();
            }

            function plotLineArea(datapoints, axisx, axisy) {
                var points = datapoints.points,
                    ps = datapoints.pointsize,
                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),
                    i = 0, top, areaOpen = false,
                    ypos = 1, segmentStart = 0, segmentEnd = 0;

                // we process each segment in two turns, first forward
                // direction to sketch out top, then once we hit the
                // end we go backwards to sketch the bottom
                while (true) {
                    if (ps > 0 && i > points.length + ps)
                        break;

                    i += ps; // ps is negative if going backwards

                    var x1 = points[i - ps],
                        y1 = points[i - ps + ypos],
                        x2 = points[i], y2 = points[i + ypos];

                    if (areaOpen) {
                        if (ps > 0 && x1 != null && x2 == null) {
                            // at turning point
                            segmentEnd = i;
                            ps = -ps;
                            ypos = 2;
                            continue;
                        }

                        if (ps < 0 && i == segmentStart + ps) {
                            // done with the reverse sweep
                            ctx.fill();
                            areaOpen = false;
                            ps = -ps;
                            ypos = 1;
                            i = segmentStart = segmentEnd + ps;
                            continue;
                        }
                    }

                    if (x1 == null || x2 == null)
                        continue;

                    // clip x values
                    
                    // clip with xmin
                    if (x1 <= x2 && x1 < axisx.min) {
                        if (x2 < axisx.min)
                            continue;
                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x1 = axisx.min;
                    }
                    else if (x2 <= x1 && x2 < axisx.min) {
                        if (x1 < axisx.min)
                            continue;
                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x2 = axisx.min;
                    }

                    // clip with xmax
                    if (x1 >= x2 && x1 > axisx.max) {
                        if (x2 > axisx.max)
                            continue;
                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x1 = axisx.max;
                    }
                    else if (x2 >= x1 && x2 > axisx.max) {
                        if (x1 > axisx.max)
                            continue;
                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
                        x2 = axisx.max;
                    }

                    if (!areaOpen) {
                        // open area
                        ctx.beginPath();
                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
                        areaOpen = true;
                    }
                    
                    // now first check the case where both is outside
                    if (y1 >= axisy.max && y2 >= axisy.max) {
                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
                        continue;
                    }
                    else if (y1 <= axisy.min && y2 <= axisy.min) {
                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
                        continue;
                    }
                    
                    // else it's a bit more complicated, there might
                    // be a flat maxed out rectangle first, then a
                    // triangular cutout or reverse; to find these
                    // keep track of the current x values
                    var x1old = x1, x2old = x2;

                    // clip the y values, without shortcutting, we
                    // go through all cases in turn
                    
                    // clip with ymin
                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y1 = axisy.min;
                    }
                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y2 = axisy.min;
                    }

                    // clip with ymax
                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y1 = axisy.max;
                    }
                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
                        y2 = axisy.max;
                    }

                    // if the x value was changed we got a rectangle
                    // to fill
                    if (x1 != x1old) {
                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
                        // it goes to (x1, y1), but we fill that below
                    }
                    
                    // fill triangular section, this sometimes result
                    // in redundant points if (x1, y1) hasn't changed
                    // from previous line to, but we just ignore that
                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));

                    // fill the other rectangle if it's there
                    if (x2 != x2old) {
                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
                    }
                }
            }

            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);
            ctx.lineJoin = "round";

            var lw = series.lines.lineWidth,
                sw = series.shadowSize;
            // FIXME: consider another form of shadow when filling is turned on
            if (lw > 0 && sw > 0) {
                // draw shadow as a thick and thin line with transparency
                ctx.lineWidth = sw;
                ctx.strokeStyle = "rgba(0,0,0,0.1)";
                // position shadow at angle from the mid of line
                var angle = Math.PI/18;
                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
                ctx.lineWidth = sw/2;
                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
            }

            ctx.lineWidth = lw;
            ctx.strokeStyle = series.color;
            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
            if (fillStyle) {
                ctx.fillStyle = fillStyle;
                plotLineArea(series.datapoints, series.xaxis, series.yaxis);
            }

            if (lw > 0)
                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
            ctx.restore();
        }

        function drawSeriesPoints(series) {
            function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
                var points = datapoints.points, ps = datapoints.pointsize;

                for (var i = 0; i < points.length; i += ps) {
                    var x = points[i], y = points[i + 1];
                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
                        continue;
                    
                    ctx.beginPath();
                    x = axisx.p2c(x);
                    y = axisy.p2c(y) + offset;
                    if (symbol == "circle")
                        ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
                    else
                        symbol(ctx, x, y, radius, shadow);
                    ctx.closePath();
                    
                    if (fillStyle) {
                        ctx.fillStyle = fillStyle;
                        ctx.fill();
                    }
                    ctx.stroke();
                }
            }
            
            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            var lw = series.points.lineWidth,
                sw = series.shadowSize,
                radius = series.points.radius,
                symbol = series.points.symbol;
            if (lw > 0 && sw > 0) {
                // draw shadow in two steps
                var w = sw / 2;
                ctx.lineWidth = w;
                ctx.strokeStyle = "rgba(0,0,0,0.1)";
                plotPoints(series.datapoints, radius, null, w + w/2, true,
                           series.xaxis, series.yaxis, symbol);

                ctx.strokeStyle = "rgba(0,0,0,0.2)";
                plotPoints(series.datapoints, radius, null, w/2, true,
                           series.xaxis, series.yaxis, symbol);
            }

            ctx.lineWidth = lw;
            ctx.strokeStyle = series.color;
            plotPoints(series.datapoints, radius,
                       getFillStyle(series.points, series.color), 0, false,
                       series.xaxis, series.yaxis, symbol);
            ctx.restore();
        }

        function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
            var left, right, bottom, top,
                drawLeft, drawRight, drawTop, drawBottom,
                tmp;

            // in horizontal mode, we start the bar from the left
            // instead of from the bottom so it appears to be
            // horizontal rather than vertical
            if (horizontal) {
                drawBottom = drawRight = drawTop = true;
                drawLeft = false;
                left = b;
                right = x;
                top = y + barLeft;
                bottom = y + barRight;

                // account for negative bars
                if (right < left) {
                    tmp = right;
                    right = left;
                    left = tmp;
                    drawLeft = true;
                    drawRight = false;
                }
            }
            else {
                drawLeft = drawRight = drawTop = true;
                drawBottom = false;
                left = x + barLeft;
                right = x + barRight;
                bottom = b;
                top = y;

                // account for negative bars
                if (top < bottom) {
                    tmp = top;
                    top = bottom;
                    bottom = tmp;
                    drawBottom = true;
                    drawTop = false;
                }
            }
           
            // clip
            if (right < axisx.min || left > axisx.max ||
                top < axisy.min || bottom > axisy.max)
                return;
            
            if (left < axisx.min) {
                left = axisx.min;
                drawLeft = false;
            }

            if (right > axisx.max) {
                right = axisx.max;
                drawRight = false;
            }

            if (bottom < axisy.min) {
                bottom = axisy.min;
                drawBottom = false;
            }
            
            if (top > axisy.max) {
                top = axisy.max;
                drawTop = false;
            }

            left = axisx.p2c(left);
            bottom = axisy.p2c(bottom);
            right = axisx.p2c(right);
            top = axisy.p2c(top);
            
            // fill the bar
            if (fillStyleCallback) {
                c.beginPath();
                c.moveTo(left, bottom);
                c.lineTo(left, top);
                c.lineTo(right, top);
                c.lineTo(right, bottom);
                c.fillStyle = fillStyleCallback(bottom, top);
                c.fill();
            }

            // draw outline
            if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
                c.beginPath();

                // FIXME: inline moveTo is buggy with excanvas
                c.moveTo(left, bottom + offset);
                if (drawLeft)
                    c.lineTo(left, top + offset);
                else
                    c.moveTo(left, top + offset);
                if (drawTop)
                    c.lineTo(right, top + offset);
                else
                    c.moveTo(right, top + offset);
                if (drawRight)
                    c.lineTo(right, bottom + offset);
                else
                    c.moveTo(right, bottom + offset);
                if (drawBottom)
                    c.lineTo(left, bottom + offset);
                else
                    c.moveTo(left, bottom + offset);
                c.stroke();
            }
        }
        
        function drawSeriesBars(series) {
            function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
                var points = datapoints.points, ps = datapoints.pointsize;
                
                for (var i = 0; i < points.length; i += ps) {
                    if (points[i] == null)
                        continue;
                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
                }
            }

            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            // FIXME: figure out a way to add shadows (for instance along the right edge)
            ctx.lineWidth = series.bars.lineWidth;
            ctx.strokeStyle = series.color;
            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
            ctx.restore();
        }

        function getFillStyle(filloptions, seriesColor, bottom, top) {
            var fill = filloptions.fill;
            if (!fill)
                return null;

            if (filloptions.fillColor)
                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
            
            var c = $.color.parse(seriesColor);
            c.a = typeof fill == "number" ? fill : 0.4;
            c.normalize();
            return c.toString();
        }
        
        function insertLegend() {
            placeholder.find(".legend").remove();

            if (!options.legend.show)
                return;
            
            var fragments = [], rowStarted = false,
                lf = options.legend.labelFormatter, s, label;
            for (var i = 0; i < series.length; ++i) {
                s = series[i];
                label = s.label;
                if (!label)
                    continue;
                
                if (i % options.legend.noColumns == 0) {
                    if (rowStarted)
                        fragments.push('</tr>');
                    fragments.push('<tr>');
                    rowStarted = true;
                }

                if (lf)
                    label = lf(label, s);
                
                fragments.push(
                    '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' +
                    '<td class="legendLabel">' + label + '</td>');
            }
            if (rowStarted)
                fragments.push('</tr>');
            
            if (fragments.length == 0)
                return;

            var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
            if (options.legend.container != null)
                $(options.legend.container).html(table);
            else {
                var pos = "",
                    p = options.legend.position,
                    m = options.legend.margin;
                if (m[0] == null)
                    m = [m, m];
                if (p.charAt(0) == "n")
                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
                else if (p.charAt(0) == "s")
                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
                if (p.charAt(1) == "e")
                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
                else if (p.charAt(1) == "w")
                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
                var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
                if (options.legend.backgroundOpacity != 0.0) {
                    // put in the transparent background
                    // separately to avoid blended labels and
                    // label boxes
                    var c = options.legend.backgroundColor;
                    if (c == null) {
                        c = options.grid.backgroundColor;
                        if (c && typeof c == "string")
                            c = $.color.parse(c);
                        else
                            c = $.color.extract(legend, 'background-color');
                        c.a = 1;
                        c = c.toString();
                    }
                    var div = legend.children();
                    $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
                }
            }
        }


        // interactive features
        
        var highlights = [],
            redrawTimeout = null;
        
        // returns the data item the mouse is over, or null if none is found
        function findNearbyItem(mouseX, mouseY, seriesFilter) {
            var maxDistance = options.grid.mouseActiveRadius,
                smallestDistance = maxDistance * maxDistance + 1,
                item = null, foundPoint = false, i, j;

            for (i = series.length - 1; i >= 0; --i) {
                if (!seriesFilter(series[i]))
                    continue;
                
                var s = series[i],
                    axisx = s.xaxis,
                    axisy = s.yaxis,
                    points = s.datapoints.points,
                    ps = s.datapoints.pointsize,
                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
                    my = axisy.c2p(mouseY),
                    maxx = maxDistance / axisx.scale,
                    maxy = maxDistance / axisy.scale;

                // with inverse transforms, we can't use the maxx/maxy
                // optimization, sadly
                if (axisx.options.inverseTransform)
                    maxx = Number.MAX_VALUE;
                if (axisy.options.inverseTransform)
                    maxy = Number.MAX_VALUE;
                
                if (s.lines.show || s.points.show) {
                    for (j = 0; j < points.length; j += ps) {
                        var x = points[j], y = points[j + 1];
                        if (x == null)
                            continue;
                        
                        // For points and lines, the cursor must be within a
                        // certain distance to the data point
                        if (x - mx > maxx || x - mx < -maxx ||
                            y - my > maxy || y - my < -maxy)
                            continue;

                        // We have to calculate distances in pixels, not in
                        // data units, because the scales of the axes may be different
                        var dx = Math.abs(axisx.p2c(x) - mouseX),
                            dy = Math.abs(axisy.p2c(y) - mouseY),
                            dist = dx * dx + dy * dy; // we save the sqrt

                        // use <= to ensure last point takes precedence
                        // (last generally means on top of)
                        if (dist < smallestDistance) {
                            smallestDistance = dist;
                            item = [i, j / ps];
                        }
                    }
                }
                    
                if (s.bars.show && !item) { // no other point can be nearby
                    var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
                        barRight = barLeft + s.bars.barWidth;
                    
                    for (j = 0; j < points.length; j += ps) {
                        var x = points[j], y = points[j + 1], b = points[j + 2];
                        if (x == null)
                            continue;
  
                        // for a bar graph, the cursor must be inside the bar
                        if (series[i].bars.horizontal ? 
                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) && 
                             my >= y + barLeft && my <= y + barRight) :
                            (mx >= x + barLeft && mx <= x + barRight &&
                             my >= Math.min(b, y) && my <= Math.max(b, y)))
                                item = [i, j / ps];
                    }
                }
            }

            if (item) {
                i = item[0];
                j = item[1];
                ps = series[i].datapoints.pointsize;
                
                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
                         dataIndex: j,
                         series: series[i],
                         seriesIndex: i };
            }
            
            return null;
        }

        function onMouseMove(e) {
            if (options.grid.hoverable)
                triggerClickHoverEvent("plothover", e,
                                       function (s) { return s["hoverable"] != false; });
        }

        function onMouseLeave(e) {
            if (options.grid.hoverable)
                triggerClickHoverEvent("plothover", e,
                                       function (s) { return false; });
        }

        function onClick(e) {
            triggerClickHoverEvent("plotclick", e,
                                   function (s) { return s["clickable"] != false; });
        }

        // trigger click or hover event (they send the same parameters
        // so we share their code)
        function triggerClickHoverEvent(eventname, event, seriesFilter) {
            var offset = eventHolder.offset(),
                canvasX = event.pageX - offset.left - plotOffset.left,
                canvasY = event.pageY - offset.top - plotOffset.top,
            pos = canvasToAxisCoords({ left: canvasX, top: canvasY });

            pos.pageX = event.pageX;
            pos.pageY = event.pageY;

            var item = findNearbyItem(canvasX, canvasY, seriesFilter);

            if (item) {
                // fill in mouse pos for any listeners out there
                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);
                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);
            }

            if (options.grid.autoHighlight) {
                // clear auto-highlights
                for (var i = 0; i < highlights.length; ++i) {
                    var h = highlights[i];
                    if (h.auto == eventname &&
                        !(item && h.series == item.series &&
                          h.point[0] == item.datapoint[0] &&
                          h.point[1] == item.datapoint[1]))
                        unhighlight(h.series, h.point);
                }
                
                if (item)
                    highlight(item.series, item.datapoint, eventname);
            }
            
            placeholder.trigger(eventname, [ pos, item ]);
        }

        function triggerRedrawOverlay() {
            if (!redrawTimeout)
                redrawTimeout = setTimeout(drawOverlay, 30);
        }

        function drawOverlay() {
            redrawTimeout = null;

            // draw highlights
            octx.save();
            octx.clearRect(0, 0, canvasWidth, canvasHeight);
            octx.translate(plotOffset.left, plotOffset.top);
            
            var i, hi;
            for (i = 0; i < highlights.length; ++i) {
                hi = highlights[i];

                if (hi.series.bars.show)
                    drawBarHighlight(hi.series, hi.point);
                else
                    drawPointHighlight(hi.series, hi.point);
            }
            octx.restore();
            
            executeHooks(hooks.drawOverlay, [octx]);
        }
        
        function highlight(s, point, auto) {
            if (typeof s == "number")
                s = series[s];

            if (typeof point == "number") {
                var ps = s.datapoints.pointsize;
                point = s.datapoints.points.slice(ps * point, ps * (point + 1));
            }

            var i = indexOfHighlight(s, point);
            if (i == -1) {
                highlights.push({ series: s, point: point, auto: auto });

                triggerRedrawOverlay();
            }
            else if (!auto)
                highlights[i].auto = false;
        }
            
        function unhighlight(s, point) {
            if (s == null && point == null) {
                highlights = [];
                triggerRedrawOverlay();
            }
            
            if (typeof s == "number")
                s = series[s];

            if (typeof point == "number")
                point = s.data[point];

            var i = indexOfHighlight(s, point);
            if (i != -1) {
                highlights.splice(i, 1);

                triggerRedrawOverlay();
            }
        }
        
        function indexOfHighlight(s, p) {
            for (var i = 0; i < highlights.length; ++i) {
                var h = highlights[i];
                if (h.series == s && h.point[0] == p[0]
                    && h.point[1] == p[1])
                    return i;
            }
            return -1;
        }
        
        function drawPointHighlight(series, point) {
            var x = point[0], y = point[1],
                axisx = series.xaxis, axisy = series.yaxis;
            
            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
                return;
            
            var pointRadius = series.points.radius + series.points.lineWidth / 2;
            octx.lineWidth = pointRadius;
            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
            var radius = 1.5 * pointRadius,
                x = axisx.p2c(x),
                y = axisy.p2c(y);
            
            octx.beginPath();
            if (series.points.symbol == "circle")
                octx.arc(x, y, radius, 0, 2 * Math.PI, false);
            else
                series.points.symbol(octx, x, y, radius, false);
            octx.closePath();
            octx.stroke();
        }

        function drawBarHighlight(series, point) {
            octx.lineWidth = series.bars.lineWidth;
            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
            var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();
            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
                    0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
        }

        function getColorOrGradient(spec, bottom, top, defaultColor) {
            if (typeof spec == "string")
                return spec;
            else {
                // assume this is a gradient spec; IE currently only
                // supports a simple vertical gradient properly, so that's
                // what we support too
                var gradient = ctx.createLinearGradient(0, top, 0, bottom);
                
                for (var i = 0, l = spec.colors.length; i < l; ++i) {
                    var c = spec.colors[i];
                    if (typeof c != "string") {
                        var co = $.color.parse(defaultColor);
                        if (c.brightness != null)
                            co = co.scale('rgb', c.brightness)
                        if (c.opacity != null)
                            co.a *= c.opacity;
                        c = co.toString();
                    }
                    gradient.addColorStop(i / (l - 1), c);
                }
                
                return gradient;
            }
        }
    }

    $.plot = function(placeholder, data, options) {
        //var t0 = new Date();
        var plot = new Plot($(placeholder), data, options, $.plot.plugins);
        //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
        return plot;
    };

    $.plot.version = "0.7";
    
    $.plot.plugins = [];

    // returns a string with the date d formatted according to fmt
    $.plot.formatDate = function(d, fmt, monthNames) {
        var leftPad = function(n) {
            n = "" + n;
            return n.length == 1 ? "0" + n : n;
        };
        
        var r = [];
        var escape = false, padNext = false;
        var hours = d.getUTCHours();
        var isAM = hours < 12;
        if (monthNames == null)
            monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

        if (fmt.search(/%p|%P/) != -1) {
            if (hours > 12) {
                hours = hours - 12;
            } else if (hours == 0) {
                hours = 12;
            }
        }
        for (var i = 0; i < fmt.length; ++i) {
            var c = fmt.charAt(i);
            
            if (escape) {
                switch (c) {
                case 'h': c = "" + hours; break;
                case 'H': c = leftPad(hours); break;
                case 'M': c = leftPad(d.getUTCMinutes()); break;
                case 'S': c = leftPad(d.getUTCSeconds()); break;
                case 'd': c = "" + d.getUTCDate(); break;
                case 'm': c = "" + (d.getUTCMonth() + 1); break;
                case 'y': c = "" + d.getUTCFullYear(); break;
                case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
                case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
                case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
                case '0': c = ""; padNext = true; break;
                }
                if (c && padNext) {
                    c = leftPad(c);
                    padNext = false;
                }
                r.push(c);
                if (!padNext)
                    escape = false;
            }
            else {
                if (c == "%")
                    escape = true;
                else
                    r.push(c);
            }
        }
        return r.join("");
    };
    
    // round to nearby lower multiple of base
    function floorInBase(n, base) {
        return base * Math.floor(n / base);
    }
    
})(jQuery);

/*! jQuery UI - v1.10.0 - 2013-01-17
* http://jqueryui.com
* Includes: jquery.ui.datepicker-ja.js
* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
jQuery(function(e){e.datepicker.regional.ja={closeText:"閉じる",prevText:"&#x3C;前",nextText:"次&#x3E;",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"},e.datepicker.setDefaults(e.datepicker.regional.ja)});
// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// released under the MIT license

(function($, window, undefined) {

    function maybeCall(thing, ctx) {
        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
    }

    function isElementInDOM(ele) {
        while (ele = ele.parentNode) {
            if (ele == document) return true;
        }
        return false;
    }

	// Returns true if it is a DOM element
	// http://stackoverflow.com/a/384380/999
	function isElement(o){
		return (
			typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
			o && typeof o === "object" && o.nodeType === 1 && typeof o.nodeName==="string"
		);	
	}

    var tipsyIDcounter = 0;
    function tipsyID() {
        return "tipsyuid" + (tipsyIDcounter++);
    }

    function Tipsy(element, options) {
        this.$element = $(element);
        this.options = options;
        this.enabled = true;
        this.fixTitle();
    }

    Tipsy.prototype = {
        show: function() {
            if (!isElementInDOM(this.$element[0])) {
                return;
            }

            if (isElement(this.$element) && !this.$element.is(':visible')) { 
                return; 
            }
            
            var title;
            if (this.enabled && (title = this.getTitle())) {
                var $tip = this.tip();

                $tip.find('.tipsy-inner' + this.options.theme)[this.options.html ? 'html' : 'text'](title);

                $tip[0].className = 'tipsy' + this.options.theme; // reset classname in case of dynamic gravity
                if (this.options.className) {
                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
                }

                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);

                var pos = $.extend({}, this.$element.offset());

                // If the element is contained in a SVG object, use getBBox
                if (this.$element.parents('svg').size() > 0) {
                    pos = $.extend(pos, this.$element[0].getBBox());
                } else {
                    pos = $.extend(pos, {
                        width: this.$element[0].offsetWidth || 0,
                        height: this.$element[0].offsetHeight || 0
                    });
                }

                var actualWidth = $tip[0].offsetWidth,
                    actualHeight = $tip[0].offsetHeight,
                    gravity = maybeCall(this.options.gravity, this.$element[0]);

                var tp;
                switch (gravity.charAt(0)) {
                    case 'n':
                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 's':
                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 'e':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
                        break;
                    case 'w':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
                        break;
                    default:
                        break;
                }

                if (gravity.length == 2) {
                    if (gravity.charAt(1) == 'w') {
                        tp.left = pos.left + pos.width / 2 - 15;
                    } else {
                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
                    }
                }

                $tip.css(tp).addClass('tipsy-' + gravity + this.options.theme);
                $tip.find('.tipsy-arrow' + this.options.theme)[0].className = 'tipsy-arrow' + this.options.theme + ' tipsy-arrow-' + gravity.charAt(0) + this.options.theme;
                $tip.css({width: (actualWidth - 10) + 'px'});

                if (this.options.fade) {
                    if(this.options.shadow)
                        $(".tipsy-inner").css({'box-shadow': '0px 0px '+this.options.shadowBlur+'px '+this.options.shadowSpread+'px rgba(0, 0, 0, '+this.options.shadowOpacity+')', '-webkit-box-shadow': '0px 0px '+this.options.shadowBlur+'px '+this.options.shadowSpread+'px rgba(0, 0, 0, '+this.options.shadowOpacity+')'});
                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}, this.options.fadeInTime);
                } else {
                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
                }

                if (this.options.aria) {
                    var $tipID = tipsyID();
                    $tip.attr("id", $tipID);
                    this.$element.attr("aria-describedby", $tipID);
                }
            }
        },

        hide: function() {
            if (this.options.fade) {
                this.tip().stop().fadeOut(this.options.fadeOutTime, function() { $(this).remove(); });
            } else {
                this.tip().remove();
            }
            if (this.options.aria) {
                this.$element.removeAttr("aria-describedby");
            }
        },

        fixTitle: function() {
            var $e = this.$element;
            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
            }
        },

        getTitle: function() {
            var title, $e = this.$element, o = this.options;
            this.fixTitle();
            if (typeof o.title == 'string') {
                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
            } else if (typeof o.title == 'function') {
                title = o.title.call($e[0]);
            }
            title = ('' + title).replace(/(^\s*|\s*$)/, "");
            return title || o.fallback;
        },

        tip: function() {
            if (!this.$tip) {
                this.$tip = $('<div class="tipsy' + this.options.theme + '"></div>').html('<div class="tipsy-arrow' + this.options.theme + '"></div><div class="tipsy-inner' + this.options.theme + '"></div>').attr("role","tooltip");
                this.$tip.data('tipsy-pointee', this.$element[0]);
            }
            return this.$tip;
        },

        validate: function() {
            if (!this.$element[0].parentNode) {
                this.hide();
                this.$element = null;
                this.options = null;
            }
        },

        enable: function() { this.enabled = true; },
        disable: function() { this.enabled = false; },
        toggleEnabled: function() { this.enabled = !this.enabled; }
    };

    $.fn.tipsy = function(options) {

        $.fn.tipsy.enable();

        if (options === true) {
            return this.data('tipsy');
        } else if (typeof options == 'string') {
            var tipsy = this.data('tipsy');
            if (tipsy) tipsy[options]();
            return this;
        }

        options = $.extend({}, $.fn.tipsy.defaults, options);

        // Establish theme
        options.theme = (options.theme && options.theme !== '') ? '-' + options.theme : '';

        function get(ele) {
            var tipsy = $.data(ele, 'tipsy');
            if (!tipsy) {
                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
                $.data(ele, 'tipsy', tipsy);
            }
            return tipsy;
        }

        function enter() {
            if ($.fn.tipsy.enabled !== true) {
                return;
            }
            var tipsy = get(this);
            tipsy.hoverState = 'in';
            if (options.delayIn === 0) {
                tipsy.show();
            } else {
                tipsy.fixTitle();
                setTimeout(function() {
                    if (tipsy.hoverState == 'in' && isElementInDOM(tipsy.$element)) {
                        tipsy.show();
                    }
                }, options.delayIn);
            }
        }

        function leave() {
            var tipsy = get(this);
            tipsy.hoverState = 'out';
            if (options.delayOut === 0) {
                tipsy.hide();
            } else {
                setTimeout(function() { if (tipsy.hoverState == 'out' || !tipsy.$element || !tipsy.$element.is(':visible')) tipsy.hide(); }, options.delayOut);
            }
        }

        if (!options.live) this.each(function() { get(this); });

        if (options.trigger != 'manual') {
            var eventIn  = options.trigger == 'hover' ? 'mouseenter mouseover' : 'focus',
                eventOut = options.trigger == 'hover' ? 'mouseleave mouseout' : 'blur';

            if (options.live && options.live !== true) {
                $(this).on(eventIn, options.live, enter);
                $(this).on(eventOut, options.live, leave);
            } else {
                if (options.live && !$.live) {
                    //live === true and using jQuery >= 1.9
                    throw "Since jQuery 1.9, pass selector as live argument. eg. $(document).tipsy({live: 'a.live'});";
                }
                var binder = options.live ? 'live' : 'bind';
                this[binder](eventIn, enter)[binder](eventOut, leave);
            }
        }

        return this;

    };

    $.fn.tipsy.defaults = {
        aria: false,
        className: null,
        delayIn: 0,
        delayOut: 0,
        fade: false,
        fadeInTime: 400,
        fadeOutTime: 400, 
        shadow: false,
        shadowBlur: 8,
        shadowOpacity: 1,
        shadowSpread: 0,
        fallback: '',
        gravity: 'n',
        html: false,
        live: false,
        offset: 0,
        opacity: 0.8,
        title: 'title',
        trigger: 'hover',
        theme: ''
    };

    $.fn.tipsy.revalidate = function() {
      $('.tipsy').each(function() {
        var pointee = $.data(this, 'tipsy-pointee');
        if (!pointee || !isElementInDOM(pointee)) {
          $(this).remove();
        }
      });
    };

    $.fn.tipsy.enable = function() {
        $.fn.tipsy.enabled = true;
    };

    $.fn.tipsy.disable = function() {
        $.fn.tipsy.enabled = false;
    };

    // Overwrite this method to provide options on a per-element basis.
    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
    // (remember - do not modify 'options' in place!)
    $.fn.tipsy.elementOptions = function(ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };

    $.fn.tipsy.autoNS = function() {
        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
    };

    $.fn.tipsy.autoWE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
    };

    $.fn.tipsy.autoNWNE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'ne' : 'nw';
    };

    $.fn.tipsy.autoSWSE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'se' : 'sw';
    };

    /**
     * yields a closure of the supplied parameters, producing a function that takes
     * no arguments and is suitable for use as an autogravity function like so:
     *
     * @param margin (int) - distance from the viewable region edge that an
     *        element should be before setting its tooltip's gravity to be away
     *        from that edge.
     * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
     *        if there are no viewable region edges effecting the tooltip's
     *        gravity. It will try to vary from this minimally, for example,
     *        if 'sw' is preferred and an element is near the right viewable
     *        region edge, but not the top edge, it will set the gravity for
     *        that element's tooltip to be 'se', preserving the southern
     *        component.
     */
    $.fn.tipsy.autoBounds = function(marginNorth, marginEast, prefer) {
        return function() {
            var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
                boundTop = $(document).scrollTop() + marginNorth,
                boundLeft = $(document).scrollLeft() + marginEast,
                $this = $(this);

            if ($this.offset().top < boundTop) dir.ns = 'n';
            if ($this.offset().left < boundLeft) dir.ew = 'w';
            if ($(window).width() + $(document).scrollLeft() - $this.offset().left < marginEast) dir.ew = 'e';
            if ($(window).height() + $(document).scrollTop() - $this.offset().top < marginNorth) dir.ns = 's';

            return dir.ns + (dir.ew ? dir.ew : '');
        };
    };

    /**
     * Improved version of autoBounds for automatic placement of chunky tips
     * The original autoBounds failed in two regards: 1. it would never return a 'w' or 'e', gravity even if they
     * were preferred and/or optimal, 2. it only respected the margin between the left hand side of an element and
     * left hand side of the viewport, and the top of an element and the top of the viewport. This version checks
     * to see if the bottom of an element is too close to the bottom of the screen, similarly for the right hand side
     */
    $.fn.tipsy.autoBounds2 = function(margin, prefer) {
        return function() {
            var dir = {},
                boundTop = $(document).scrollTop() + margin,
                boundLeft = $(document).scrollLeft() + margin,
                $this = $(this);

            // bi-directional string (ne, se, sw, etc...)
            if (prefer.length > 1) {
                dir.ns = prefer[0];
                dir.ew = prefer[1];
            } else {
                // single direction string (e, w, n or s)
                if (prefer[0] == 'e' || prefer[0] == 'w') {
                    dir.ew = prefer[0];
                } else {
                    dir.ns = prefer[0];
                }
            }

            if ($this.offset().top < boundTop) dir.ns = 'n';
            if ($this.offset().left < boundLeft) dir.ew = 'w';
            if ($(window).width() + $(document).scrollLeft() - ($this.offset().left + $this.width()) < margin) dir.ew = 'e';
            if ($(window).height() + $(document).scrollTop() - ($this.offset().top + $this.height()) < margin) dir.ns = 's';

            if (dir.ns) {
                return dir.ns + (dir.ew ? dir.ew : '');
            }
            return dir.ew;
        }
    };
    
})(jQuery, window);
/**
 * jquery.Jcrop.min.js v0.9.12 (build:20130202)
 * jQuery Image Cropping Plugin - released under MIT License
 * Copyright (c) 2008-2013 Tapmodo Interactive LLC
 * https://github.com/tapmodo/Jcrop
 */
(function(a){a.Jcrop=function(b,c){function i(a){return Math.round(a)+"px"}function j(a){return d.baseClass+"-"+a}function k(){return a.fx.step.hasOwnProperty("backgroundColor")}function l(b){var c=a(b).offset();return[c.left,c.top]}function m(a){return[a.pageX-e[0],a.pageY-e[1]]}function n(b){typeof b!="object"&&(b={}),d=a.extend(d,b),a.each(["onChange","onSelect","onRelease","onDblClick"],function(a,b){typeof d[b]!="function"&&(d[b]=function(){})})}function o(a,b,c){e=l(D),bc.setCursor(a==="move"?a:a+"-resize");if(a==="move")return bc.activateHandlers(q(b),v,c);var d=_.getFixed(),f=r(a),g=_.getCorner(r(f));_.setPressed(_.getCorner(f)),_.setCurrent(g),bc.activateHandlers(p(a,d),v,c)}function p(a,b){return function(c){if(!d.aspectRatio)switch(a){case"e":c[1]=b.y2;break;case"w":c[1]=b.y2;break;case"n":c[0]=b.x2;break;case"s":c[0]=b.x2}else switch(a){case"e":c[1]=b.y+1;break;case"w":c[1]=b.y+1;break;case"n":c[0]=b.x+1;break;case"s":c[0]=b.x+1}_.setCurrent(c),bb.update()}}function q(a){var b=a;return bd.watchKeys
(),function(a){_.moveOffset([a[0]-b[0],a[1]-b[1]]),b=a,bb.update()}}function r(a){switch(a){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function s(a){return function(b){return d.disabled?!1:a==="move"&&!d.allowMove?!1:(e=l(D),W=!0,o(a,m(b)),b.stopPropagation(),b.preventDefault(),!1)}}function t(a,b,c){var d=a.width(),e=a.height();d>b&&b>0&&(d=b,e=b/a.width()*a.height()),e>c&&c>0&&(e=c,d=c/a.height()*a.width()),T=a.width()/d,U=a.height()/e,a.width(d).height(e)}function u(a){return{x:a.x*T,y:a.y*U,x2:a.x2*T,y2:a.y2*U,w:a.w*T,h:a.h*U}}function v(a){var b=_.getFixed();b.w>d.minSelect[0]&&b.h>d.minSelect[1]?(bb.enableHandles(),bb.done()):bb.release(),bc.setCursor(d.allowSelect?"crosshair":"default")}function w(a){if(d.disabled)return!1;if(!d.allowSelect)return!1;W=!0,e=l(D),bb.disableHandles(),bc.setCursor("crosshair");var b=m(a);return _.setPressed(b),bb.update(),bc.activateHandlers(x,v,a.type.substring
(0,5)==="touch"),bd.watchKeys(),a.stopPropagation(),a.preventDefault(),!1}function x(a){_.setCurrent(a),bb.update()}function y(){var b=a("<div></div>").addClass(j("tracker"));return g&&b.css({opacity:0,backgroundColor:"white"}),b}function be(a){G.removeClass().addClass(j("holder")).addClass(a)}function bf(a,b){function t(){window.setTimeout(u,l)}var c=a[0]/T,e=a[1]/U,f=a[2]/T,g=a[3]/U;if(X)return;var h=_.flipCoords(c,e,f,g),i=_.getFixed(),j=[i.x,i.y,i.x2,i.y2],k=j,l=d.animationDelay,m=h[0]-j[0],n=h[1]-j[1],o=h[2]-j[2],p=h[3]-j[3],q=0,r=d.swingSpeed;c=k[0],e=k[1],f=k[2],g=k[3],bb.animMode(!0);var s,u=function(){return function(){q+=(100-q)/r,k[0]=Math.round(c+q/100*m),k[1]=Math.round(e+q/100*n),k[2]=Math.round(f+q/100*o),k[3]=Math.round(g+q/100*p),q>=99.8&&(q=100),q<100?(bh(k),t()):(bb.done(),bb.animMode(!1),typeof b=="function"&&b.call(bs))}}();t()}function bg(a){bh([a[0]/T,a[1]/U,a[2]/T,a[3]/U]),d.onSelect.call(bs,u(_.getFixed())),bb.enableHandles()}function bh(a){_.setPressed([a[0],a[1]]),_.setCurrent([a[2],
a[3]]),bb.update()}function bi(){return u(_.getFixed())}function bj(){return _.getFixed()}function bk(a){n(a),br()}function bl(){d.disabled=!0,bb.disableHandles(),bb.setCursor("default"),bc.setCursor("default")}function bm(){d.disabled=!1,br()}function bn(){bb.done(),bc.activateHandlers(null,null)}function bo(){G.remove(),A.show(),A.css("visibility","visible"),a(b).removeData("Jcrop")}function bp(a,b){bb.release(),bl();var c=new Image;c.onload=function(){var e=c.width,f=c.height,g=d.boxWidth,h=d.boxHeight;D.width(e).height(f),D.attr("src",a),H.attr("src",a),t(D,g,h),E=D.width(),F=D.height(),H.width(E).height(F),M.width(E+L*2).height(F+L*2),G.width(E).height(F),ba.resize(E,F),bm(),typeof b=="function"&&b.call(bs)},c.src=a}function bq(a,b,c){var e=b||d.bgColor;d.bgFade&&k()&&d.fadeTime&&!c?a.animate({backgroundColor:e},{queue:!1,duration:d.fadeTime}):a.css("backgroundColor",e)}function br(a){d.allowResize?a?bb.enableOnly():bb.enableHandles():bb.disableHandles(),bc.setCursor(d.allowSelect?"crosshair":"default"),bb
.setCursor(d.allowMove?"move":"default"),d.hasOwnProperty("trueSize")&&(T=d.trueSize[0]/E,U=d.trueSize[1]/F),d.hasOwnProperty("setSelect")&&(bg(d.setSelect),bb.done(),delete d.setSelect),ba.refresh(),d.bgColor!=N&&(bq(d.shade?ba.getShades():G,d.shade?d.shadeColor||d.bgColor:d.bgColor),N=d.bgColor),O!=d.bgOpacity&&(O=d.bgOpacity,d.shade?ba.refresh():bb.setBgOpacity(O)),P=d.maxSize[0]||0,Q=d.maxSize[1]||0,R=d.minSize[0]||0,S=d.minSize[1]||0,d.hasOwnProperty("outerImage")&&(D.attr("src",d.outerImage),delete d.outerImage),bb.refresh()}var d=a.extend({},a.Jcrop.defaults),e,f=navigator.userAgent.toLowerCase(),g=/msie/.test(f),h=/msie [1-6]\./.test(f);typeof b!="object"&&(b=a(b)[0]),typeof c!="object"&&(c={}),n(c);var z={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},A=a(b),B=!0;if(b.tagName=="IMG"){if(A[0].width!=0&&A[0].height!=0)A.width(A[0].width),A.height(A[0].height);else{var C=new Image;C.src=A[0].src,A.width(C.width),A.height(C.height)}var D=A.clone().removeAttr("id").
css(z).show();D.width(A.width()),D.height(A.height()),A.after(D).hide()}else D=A.css(z).show(),B=!1,d.shade===null&&(d.shade=!0);t(D,d.boxWidth,d.boxHeight);var E=D.width(),F=D.height(),G=a("<div />").width(E).height(F).addClass(j("holder")).css({position:"relative",backgroundColor:d.bgColor}).insertAfter(A).append(D);d.addClass&&G.addClass(d.addClass);var H=a("<div />"),I=a("<div />").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),J=a("<div />").width("100%").height("100%").css("zIndex",320),K=a("<div />").css({position:"absolute",zIndex:600}).dblclick(function(){var a=_.getFixed();d.onDblClick.call(bs,a)}).insertBefore(D).append(I,J);B&&(H=a("<img />").attr("src",D.attr("src")).css(z).width(E).height(F),I.append(H)),h&&K.css({overflowY:"hidden"});var L=d.boundary,M=y().width(E+L*2).height(F+L*2).css({position:"absolute",top:i(-L),left:i(-L),zIndex:290}).mousedown(w),N=d.bgColor,O=d.bgOpacity,P,Q,R,S,T,U,V=!0,W,X,Y;e=l(D);var Z=function(){function a(){var a={},b=["touchstart"
,"touchmove","touchend"],c=document.createElement("div"),d;try{for(d=0;d<b.length;d++){var e=b[d];e="on"+e;var f=e in c;f||(c.setAttribute(e,"return;"),f=typeof c[e]=="function"),a[b[d]]=f}return a.touchstart&&a.touchend&&a.touchmove}catch(g){return!1}}function b(){return d.touchSupport===!0||d.touchSupport===!1?d.touchSupport:a()}return{createDragger:function(a){return function(b){return d.disabled?!1:a==="move"&&!d.allowMove?!1:(e=l(D),W=!0,o(a,m(Z.cfilter(b)),!0),b.stopPropagation(),b.preventDefault(),!1)}},newSelection:function(a){return w(Z.cfilter(a))},cfilter:function(a){return a.pageX=a.originalEvent.changedTouches[0].pageX,a.pageY=a.originalEvent.changedTouches[0].pageY,a},isSupported:a,support:b()}}(),_=function(){function h(d){d=n(d),c=a=d[0],e=b=d[1]}function i(a){a=n(a),f=a[0]-c,g=a[1]-e,c=a[0],e=a[1]}function j(){return[f,g]}function k(d){var f=d[0],g=d[1];0>a+f&&(f-=f+a),0>b+g&&(g-=g+b),F<e+g&&(g+=F-(e+g)),E<c+f&&(f+=E-(c+f)),a+=f,c+=f,b+=g,e+=g}function l(a){var b=m();switch(a){case"ne":return[
b.x2,b.y];case"nw":return[b.x,b.y];case"se":return[b.x2,b.y2];case"sw":return[b.x,b.y2]}}function m(){if(!d.aspectRatio)return p();var f=d.aspectRatio,g=d.minSize[0]/T,h=d.maxSize[0]/T,i=d.maxSize[1]/U,j=c-a,k=e-b,l=Math.abs(j),m=Math.abs(k),n=l/m,r,s,t,u;return h===0&&(h=E*10),i===0&&(i=F*10),n<f?(s=e,t=m*f,r=j<0?a-t:t+a,r<0?(r=0,u=Math.abs((r-a)/f),s=k<0?b-u:u+b):r>E&&(r=E,u=Math.abs((r-a)/f),s=k<0?b-u:u+b)):(r=c,u=l/f,s=k<0?b-u:b+u,s<0?(s=0,t=Math.abs((s-b)*f),r=j<0?a-t:t+a):s>F&&(s=F,t=Math.abs(s-b)*f,r=j<0?a-t:t+a)),r>a?(r-a<g?r=a+g:r-a>h&&(r=a+h),s>b?s=b+(r-a)/f:s=b-(r-a)/f):r<a&&(a-r<g?r=a-g:a-r>h&&(r=a-h),s>b?s=b+(a-r)/f:s=b-(a-r)/f),r<0?(a-=r,r=0):r>E&&(a-=r-E,r=E),s<0?(b-=s,s=0):s>F&&(b-=s-F,s=F),q(o(a,b,r,s))}function n(a){return a[0]<0&&(a[0]=0),a[1]<0&&(a[1]=0),a[0]>E&&(a[0]=E),a[1]>F&&(a[1]=F),[Math.round(a[0]),Math.round(a[1])]}function o(a,b,c,d){var e=a,f=c,g=b,h=d;return c<a&&(e=c,f=a),d<b&&(g=d,h=b),[e,g,f,h]}function p(){var d=c-a,f=e-b,g;return P&&Math.abs(d)>P&&(c=d>0?a+P:a-P),Q&&Math.abs
(f)>Q&&(e=f>0?b+Q:b-Q),S/U&&Math.abs(f)<S/U&&(e=f>0?b+S/U:b-S/U),R/T&&Math.abs(d)<R/T&&(c=d>0?a+R/T:a-R/T),a<0&&(c-=a,a-=a),b<0&&(e-=b,b-=b),c<0&&(a-=c,c-=c),e<0&&(b-=e,e-=e),c>E&&(g=c-E,a-=g,c-=g),e>F&&(g=e-F,b-=g,e-=g),a>E&&(g=a-F,e-=g,b-=g),b>F&&(g=b-F,e-=g,b-=g),q(o(a,b,c,e))}function q(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]}}var a=0,b=0,c=0,e=0,f,g;return{flipCoords:o,setPressed:h,setCurrent:i,getOffset:j,moveOffset:k,getCorner:l,getFixed:m}}(),ba=function(){function f(a,b){e.left.css({height:i(b)}),e.right.css({height:i(b)})}function g(){return h(_.getFixed())}function h(a){e.top.css({left:i(a.x),width:i(a.w),height:i(a.y)}),e.bottom.css({top:i(a.y2),left:i(a.x),width:i(a.w),height:i(F-a.y2)}),e.right.css({left:i(a.x2),width:i(E-a.x2)}),e.left.css({width:i(a.x)})}function j(){return a("<div />").css({position:"absolute",backgroundColor:d.shadeColor||d.bgColor}).appendTo(c)}function k(){b||(b=!0,c.insertBefore(D),g(),bb.setBgOpacity(1,0,1),H.hide(),l(d.shadeColor||d.bgColor,1),bb.
isAwake()?n(d.bgOpacity,1):n(1,1))}function l(a,b){bq(p(),a,b)}function m(){b&&(c.remove(),H.show(),b=!1,bb.isAwake()?bb.setBgOpacity(d.bgOpacity,1,1):(bb.setBgOpacity(1,1,1),bb.disableHandles()),bq(G,0,1))}function n(a,e){b&&(d.bgFade&&!e?c.animate({opacity:1-a},{queue:!1,duration:d.fadeTime}):c.css({opacity:1-a}))}function o(){d.shade?k():m(),bb.isAwake()&&n(d.bgOpacity)}function p(){return c.children()}var b=!1,c=a("<div />").css({position:"absolute",zIndex:240,opacity:0}),e={top:j(),left:j().height(F),right:j().height(F),bottom:j()};return{update:g,updateRaw:h,getShades:p,setBgColor:l,enable:k,disable:m,resize:f,refresh:o,opacity:n}}(),bb=function(){function k(b){var c=a("<div />").css({position:"absolute",opacity:d.borderOpacity}).addClass(j(b));return I.append(c),c}function l(b,c){var d=a("<div />").mousedown(s(b)).css({cursor:b+"-resize",position:"absolute",zIndex:c}).addClass("ord-"+b);return Z.support&&d.bind("touchstart.jcrop",Z.createDragger(b)),J.append(d),d}function m(a){var b=d.handleSize,e=l(a,c++
).css({opacity:d.handleOpacity}).addClass(j("handle"));return b&&e.width(b).height(b),e}function n(a){return l(a,c++).addClass("jcrop-dragbar")}function o(a){var b;for(b=0;b<a.length;b++)g[a[b]]=n(a[b])}function p(a){var b,c;for(c=0;c<a.length;c++){switch(a[c]){case"n":b="hline";break;case"s":b="hline bottom";break;case"e":b="vline right";break;case"w":b="vline"}e[a[c]]=k(b)}}function q(a){var b;for(b=0;b<a.length;b++)f[a[b]]=m(a[b])}function r(a,b){d.shade||H.css({top:i(-b),left:i(-a)}),K.css({top:i(b),left:i(a)})}function t(a,b){K.width(Math.round(a)).height(Math.round(b))}function v(){var a=_.getFixed();_.setPressed([a.x,a.y]),_.setCurrent([a.x2,a.y2]),w()}function w(a){if(b)return x(a)}function x(a){var c=_.getFixed();t(c.w,c.h),r(c.x,c.y),d.shade&&ba.updateRaw(c),b||A(),a?d.onSelect.call(bs,u(c)):d.onChange.call(bs,u(c))}function z(a,c,e){if(!b&&!c)return;d.bgFade&&!e?D.animate({opacity:a},{queue:!1,duration:d.fadeTime}):D.css("opacity",a)}function A(){K.show(),d.shade?ba.opacity(O):z(O,!0),b=!0}function B
(){F(),K.hide(),d.shade?ba.opacity(1):z(1),b=!1,d.onRelease.call(bs)}function C(){h&&J.show()}function E(){h=!0;if(d.allowResize)return J.show(),!0}function F(){h=!1,J.hide()}function G(a){a?(X=!0,F()):(X=!1,E())}function L(){G(!1),v()}var b,c=370,e={},f={},g={},h=!1;d.dragEdges&&a.isArray(d.createDragbars)&&o(d.createDragbars),a.isArray(d.createHandles)&&q(d.createHandles),d.drawBorders&&a.isArray(d.createBorders)&&p(d.createBorders),a(document).bind("touchstart.jcrop-ios",function(b){a(b.currentTarget).hasClass("jcrop-tracker")&&b.stopPropagation()});var M=y().mousedown(s("move")).css({cursor:"move",position:"absolute",zIndex:360});return Z.support&&M.bind("touchstart.jcrop",Z.createDragger("move")),I.append(M),F(),{updateVisible:w,update:x,release:B,refresh:v,isAwake:function(){return b},setCursor:function(a){M.css("cursor",a)},enableHandles:E,enableOnly:function(){h=!0},showHandles:C,disableHandles:F,animMode:G,setBgOpacity:z,done:L}}(),bc=function(){function f(b){M.css({zIndex:450}),b?a(document).bind("touchmove.jcrop"
,k).bind("touchend.jcrop",l):e&&a(document).bind("mousemove.jcrop",h).bind("mouseup.jcrop",i)}function g(){M.css({zIndex:290}),a(document).unbind(".jcrop")}function h(a){return b(m(a)),!1}function i(a){return a.preventDefault(),a.stopPropagation(),W&&(W=!1,c(m(a)),bb.isAwake()&&d.onSelect.call(bs,u(_.getFixed())),g(),b=function(){},c=function(){}),!1}function j(a,d,e){return W=!0,b=a,c=d,f(e),!1}function k(a){return b(m(Z.cfilter(a))),!1}function l(a){return i(Z.cfilter(a))}function n(a){M.css("cursor",a)}var b=function(){},c=function(){},e=d.trackDocument;return e||M.mousemove(h).mouseup(i).mouseout(i),D.before(M),{activateHandlers:j,setCursor:n}}(),bd=function(){function e(){d.keySupport&&(b.show(),b.focus())}function f(a){b.hide()}function g(a,b,c){d.allowMove&&(_.moveOffset([b,c]),bb.updateVisible(!0)),a.preventDefault(),a.stopPropagation()}function i(a){if(a.ctrlKey||a.metaKey)return!0;Y=a.shiftKey?!0:!1;var b=Y?10:1;switch(a.keyCode){case 37:g(a,-b,0);break;case 39:g(a,b,0);break;case 38:g(a,0,-b);break;
case 40:g(a,0,b);break;case 27:d.allowSelect&&bb.release();break;case 9:return!0}return!1}var b=a('<input type="radio" />').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),c=a("<div />").css({position:"absolute",overflow:"hidden"}).append(b);return d.keySupport&&(b.keydown(i).blur(f),h||!d.fixedSupport?(b.css({position:"absolute",left:"-20px"}),c.append(b).insertBefore(D)):b.insertBefore(D)),{watchKeys:e}}();Z.support&&M.bind("touchstart.jcrop",Z.newSelection),J.hide(),br(!0);var bs={setImage:bp,animateTo:bf,setSelect:bg,setOptions:bk,tellSelect:bi,tellScaled:bj,setClass:be,disable:bl,enable:bm,cancel:bn,release:bb.release,destroy:bo,focus:bd.watchKeys,getBounds:function(){return[E*T,F*U]},getWidgetSize:function(){return[E,F]},getScaleFactor:function(){return[T,U]},getOptions:function(){return d},ui:{holder:G,selection:K}};return g&&G.bind("selectstart",function(){return!1}),A.data("Jcrop",bs),bs},a.fn.Jcrop=function(b,c){var d;return this.each(function(){if(a(this).data("Jcrop")){if(
b==="api")return a(this).data("Jcrop");a(this).data("Jcrop").setOptions(b)}else this.tagName=="IMG"?a.Jcrop.Loader(this,function(){a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d)}):(a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d))}),this},a.Jcrop.Loader=function(b,c,d){function g(){f.complete?(e.unbind(".jcloader"),a.isFunction(c)&&c.call(f)):window.setTimeout(g,50)}var e=a(b),f=e[0];e.bind("load.jcloader",g).bind("error.jcloader",function(b){e.unbind(".jcloader"),a.isFunction(d)&&d.call(f)}),f.complete&&a.isFunction(c)&&(e.unbind(".jcloader"),c.call(f))},a.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:null,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges
:!0,fixedSupport:!0,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}})(jQuery);
/**
 * menu-aim is a jQuery plugin for dropdown menus that can differentiate
 * between a user trying hover over a dropdown item vs trying to navigate into
 * a submenu's contents.
 *
 * menu-aim assumes that you have are using a menu with submenus that expand
 * to the menu's right. It will fire events when the user's mouse enters a new
 * dropdown item *and* when that item is being intentionally hovered over.
 *
 * __________________________
 * | Monkeys  >|   Gorilla  |
 * | Gorillas >|   Content  |
 * | Chimps   >|   Here     |
 * |___________|____________|
 *
 * In the above example, "Gorillas" is selected and its submenu content is
 * being shown on the right. Imagine that the user's cursor is hovering over
 * "Gorillas." When they move their mouse into the "Gorilla Content" area, they
 * may briefly hover over "Chimps." This shouldn't close the "Gorilla Content"
 * area.
 *
 * This problem is normally solved using timeouts and delays. menu-aim tries to
 * solve this by detecting the direction of the user's mouse movement. This can
 * make for quicker transitions when navigating up and down the menu. The
 * experience is hopefully similar to amazon.com/'s "Shop by Department"
 * dropdown.
 *
 * Use like so:
 *
 *      $("#menu").menuAim({
 *          activate: $.noop,  // fired on row activation
 *          deactivate: $.noop  // fired on row deactivation
 *      });
 *
 *  ...to receive events when a menu's row has been purposefully (de)activated.
 *
 * The following options can be passed to menuAim. All functions execute with
 * the relevant row's HTML element as the execution context ('this'):
 *
 *      .menuAim({
 *          // Function to call when a row is purposefully activated. Use this
 *          // to show a submenu's content for the activated row.
 *          activate: function() {},
 *
 *          // Function to call when a row is deactivated.
 *          deactivate: function() {},
 *
 *          // Function to call when mouse enters a menu row. Entering a row
 *          // does not mean the row has been activated, as the user may be
 *          // mousing over to a submenu.
 *          enter: function() {},
 *
 *          // Function to call when mouse exits a menu row.
 *          exit: function() {},
 *
 *          // Selector for identifying which elements in the menu are rows
 *          // that can trigger the above events. Defaults to "> li".
 *          rowSelector: "> li",
 *
 *          // You may have some menu rows that aren't submenus and therefore
 *          // shouldn't ever need to "activate." If so, filter submenu rows w/
 *          // this selector. Defaults to "*" (all elements).
 *          submenuSelector: "*",
 *
 *          // Direction the submenu opens relative to the main menu. Can be
 *          // left, right, above, or below. Defaults to "right".
 *          submenuDirection: "right"
 *      });
 *
 * https://github.com/kamens/jQuery-menu-aim
*/
(function($) {

    $.fn.menuAim = function(opts) {
        // Initialize menu-aim for all elements in jQuery collection
        this.each(function() {
            init.call(this, opts);
        });

        return this;
    };

    function init(opts) {
        var $menu = $(this),
            activeRow = null,
            mouseLocs = [],
            lastDelayLoc = null,
            timeoutId = null,
            options = $.extend({
                rowSelector: "> li",
                submenuSelector: "*",
                submenuDirection: "right",
                tolerance: 75,  // bigger = more forgivey when entering submenu
                enter: $.noop,
                exit: $.noop,
                activate: $.noop,
                deactivate: $.noop,
                exitMenu: $.noop
            }, opts);

        var MOUSE_LOCS_TRACKED = 3,  // number of past mouse locations to track
            DELAY = 300;  // ms delay when user appears to be entering submenu

        /**
         * Keep track of the last few locations of the mouse.
         */
        var mousemoveDocument = function(e) {
                mouseLocs.push({x: e.pageX, y: e.pageY});

                if (mouseLocs.length > MOUSE_LOCS_TRACKED) {
                    mouseLocs.shift();
                }
            };

        /**
         * Cancel possible row activations when leaving the menu entirely
         */
        var mouseleaveMenu = function() {
                if (timeoutId) {
                    clearTimeout(timeoutId);
                }

                // If exitMenu is supplied and returns true, deactivate the
                // currently active row on menu exit.
                if (options.exitMenu(this)) {
                    if (activeRow) {
                        options.deactivate(activeRow);
                    }

                    activeRow = null;
                }
            };

        /**
         * Trigger a possible row activation whenever entering a new row.
         */
        var mouseenterRow = function() {
                if (timeoutId) {
                    // Cancel any previous activation delays
                    clearTimeout(timeoutId);
                }

                options.enter(this);
                possiblyActivate(this);
            },
            mouseleaveRow = function() {
                options.exit(this);
            };

        /*
         * Immediately activate a row if the user clicks on it.
         */
        var clickRow = function() {
                activate(this);
            };

        /**
         * Activate a menu row.
         */
        var activate = function(row) {
                if (row == activeRow) {
                    return;
                }

                if (activeRow) {
                    options.deactivate(activeRow);
                }

                options.activate(row);
                activeRow = row;
            };

        /**
         * Possibly activate a menu row. If mouse movement indicates that we
         * shouldn't activate yet because user may be trying to enter
         * a submenu's content, then delay and check again later.
         */
        var possiblyActivate = function(row) {
                var delay = activationDelay();

                if (delay) {
                    timeoutId = setTimeout(function() {
                        possiblyActivate(row);
                    }, delay);
                } else {
                    activate(row);
                }
            };

        /**
         * Return the amount of time that should be used as a delay before the
         * currently hovered row is activated.
         *
         * Returns 0 if the activation should happen immediately. Otherwise,
         * returns the number of milliseconds that should be delayed before
         * checking again to see if the row should be activated.
         */
        var activationDelay = function() {
                if (!activeRow || !$(activeRow).is(options.submenuSelector)) {
                    // If there is no other submenu row already active, then
                    // go ahead and activate immediately.
                    return 0;
                }

                var offset = $menu.offset(),
                    upperLeft = {
                        x: offset.left,
                        y: offset.top - options.tolerance
                    },
                    upperRight = {
                        x: offset.left + $menu.outerWidth(),
                        y: upperLeft.y
                    },
                    lowerLeft = {
                        x: offset.left,
                        y: offset.top + $menu.outerHeight() + options.tolerance
                    },
                    lowerRight = {
                        x: offset.left + $menu.outerWidth(),
                        y: lowerLeft.y
                    },
                    loc = mouseLocs[mouseLocs.length - 1],
                    prevLoc = mouseLocs[0];

                if (!loc) {
                    return 0;
                }

                if (!prevLoc) {
                    prevLoc = loc;
                }

                if (prevLoc.x < offset.left || prevLoc.x > lowerRight.x ||
                    prevLoc.y < offset.top || prevLoc.y > lowerRight.y) {
                    // If the previous mouse location was outside of the entire
                    // menu's bounds, immediately activate.
                    return 0;
                }

                if (lastDelayLoc &&
                        loc.x == lastDelayLoc.x && loc.y == lastDelayLoc.y) {
                    // If the mouse hasn't moved since the last time we checked
                    // for activation status, immediately activate.
                    return 0;
                }

                // Detect if the user is moving towards the currently activated
                // submenu.
                //
                // If the mouse is heading relatively clearly towards
                // the submenu's content, we should wait and give the user more
                // time before activating a new row. If the mouse is heading
                // elsewhere, we can immediately activate a new row.
                //
                // We detect this by calculating the slope formed between the
                // current mouse location and the upper/lower right points of
                // the menu. We do the same for the previous mouse location.
                // If the current mouse location's slopes are
                // increasing/decreasing appropriately compared to the
                // previous's, we know the user is moving toward the submenu.
                //
                // Note that since the y-axis increases as the cursor moves
                // down the screen, we are looking for the slope between the
                // cursor and the upper right corner to decrease over time, not
                // increase (somewhat counterintuitively).
                function slope(a, b) {
                    return (b.y - a.y) / (b.x - a.x);
                };

                var decreasingCorner = upperRight,
                    increasingCorner = lowerRight;

                // Our expectations for decreasing or increasing slope values
                // depends on which direction the submenu opens relative to the
                // main menu. By default, if the menu opens on the right, we
                // expect the slope between the cursor and the upper right
                // corner to decrease over time, as explained above. If the
                // submenu opens in a different direction, we change our slope
                // expectations.
                if (options.submenuDirection == "left") {
                    decreasingCorner = lowerLeft;
                    increasingCorner = upperLeft;
                } else if (options.submenuDirection == "below") {
                    decreasingCorner = lowerRight;
                    increasingCorner = lowerLeft;
                } else if (options.submenuDirection == "above") {
                    decreasingCorner = upperLeft;
                    increasingCorner = upperRight;
                }

                var decreasingSlope = slope(loc, decreasingCorner),
                    increasingSlope = slope(loc, increasingCorner),
                    prevDecreasingSlope = slope(prevLoc, decreasingCorner),
                    prevIncreasingSlope = slope(prevLoc, increasingCorner);

                if (decreasingSlope < prevDecreasingSlope &&
                        increasingSlope > prevIncreasingSlope) {
                    // Mouse is moving from previous location towards the
                    // currently activated submenu. Delay before activating a
                    // new menu row, because user may be moving into submenu.
                    lastDelayLoc = loc;
                    return DELAY;
                }

                lastDelayLoc = null;
                return 0;
            };

        /**
         * Hook up initial menu events
         */
        $menu
            .mouseleave(mouseleaveMenu)
            .find(options.rowSelector)
                .mouseenter(mouseenterRow)
                .mouseleave(mouseleaveRow)
                .click(clickRow);

        $(document).mousemove(mousemoveDocument);

    };
})(jQuery);


/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node/CommonJS
        factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function (jQuery) {
    jQuery.extend({
        highlight: function (node, re, nodeName, className) {
            if (node.nodeType === 3) {
                var match = node.data.match(re);
                if (match) {
                    var highlight = document.createElement(nodeName || 'span');
                    highlight.className = className || 'highlight';
                    var wordNode = node.splitText(match.index);
                    wordNode.splitText(match[0].length);
                    var wordClone = wordNode.cloneNode(true);
                    highlight.appendChild(wordClone);
                    wordNode.parentNode.replaceChild(highlight, wordNode);
                    return 1; //skip added node in parent
                }
            } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                    !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                    !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
                for (var i = 0; i < node.childNodes.length; i++) {
                    i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
                }
            }
            return 0;
        }
    });

    jQuery.fn.unhighlight = function (options) {
        var settings = { className: 'highlight', element: 'span' };
        jQuery.extend(settings, options);

        return this.find(settings.element + "." + settings.className).each(function () {
            var parent = this.parentNode;
            parent.replaceChild(this.firstChild, this);
            parent.normalize();
        }).end();
    };

    jQuery.fn.highlight = function (words, options) {
        var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
        jQuery.extend(settings, options);
        
        if (words.constructor === String) {
            words = [words];
        }
        words = jQuery.grep(words, function(word, i){
          return word != '';
        });
        words = jQuery.map(words, function(word, i) {
          return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        });
        if (words.length == 0) { return this; };

        var flag = settings.caseSensitive ? "" : "i";
        var pattern = "(" + words.join("|") + ")";
        if (settings.wordsOnly) {
            pattern = "\\b" + pattern + "\\b";
        }
        var re = new RegExp(pattern, flag);
        
        return this.each(function () {
            jQuery.highlight(this, re, settings.element, settings.className);
        });
    };
}));

/*! overthrow - An overflow:auto polyfill for responsive design. - v0.7.0 - 2013-11-04
* Copyright (c) 2013 Scott Jehl, Filament Group, Inc.; Licensed MIT */
/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, undefined ){
	
	var doc = w.document,
		docElem = doc.documentElement,
		enabledClassName = "overthrow-enabled",

		// Touch events are used in the polyfill, and thus are a prerequisite
		canBeFilledWithPoly = "ontouchmove" in doc,
		
		// The following attempts to determine whether the browser has native overflow support
		// so we can enable it but not polyfill
		nativeOverflow = 
			// Features-first. iOS5 overflow scrolling property check - no UA needed here. thanks Apple :)
			"WebkitOverflowScrolling" in docElem.style ||
			// Test the windows scrolling property as well
			"msOverflowStyle" in docElem.style ||
			// Touch events aren't supported and screen width is greater than X
			// ...basically, this is a loose "desktop browser" check. 
			// It may wrongly opt-in very large tablets with no touch support.
			( !canBeFilledWithPoly && w.screen.width > 800 ) ||
			// Hang on to your hats.
			// Whitelist some popular, overflow-supporting mobile browsers for now and the future
			// These browsers are known to get overlow support right, but give us no way of detecting it.
			(function(){
				var ua = w.navigator.userAgent,
					// Webkit crosses platforms, and the browsers on our list run at least version 534
					webkit = ua.match( /AppleWebKit\/([0-9]+)/ ),
					wkversion = webkit && webkit[1],
					wkLte534 = webkit && wkversion >= 534;
					
				return (
					/* Android 3+ with webkit gte 534
					~: Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13 */
					ua.match( /Android ([0-9]+)/ ) && RegExp.$1 >= 3 && wkLte534 ||
					/* Blackberry 7+ with webkit gte 534
					~: Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0 Mobile Safari/534.11+ */
					ua.match( / Version\/([0-9]+)/ ) && RegExp.$1 >= 0 && w.blackberry && wkLte534 ||
					/* Blackberry Playbook with webkit gte 534
					~: Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+ */   
					ua.indexOf( "PlayBook" ) > -1 && wkLte534 && !ua.indexOf( "Android 2" ) === -1 ||
					/* Firefox Mobile (Fennec) 4 and up
					~: Mozilla/5.0 (Mobile; rv:15.0) Gecko/15.0 Firefox/15.0 */
					ua.match(/Firefox\/([0-9]+)/) && RegExp.$1 >= 4 ||
					/* WebOS 3 and up (TouchPad too)
					~: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.48 Safari/534.6 TouchPad/1.0 */
					ua.match( /wOSBrowser\/([0-9]+)/ ) && RegExp.$1 >= 233 && wkLte534 ||
					/* Nokia Browser N8
					~: Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/012.002; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.0 Mobile Safari/533.4 3gpp-gba 
					~: Note: the N9 doesn't have native overflow with one-finger touch. wtf */
					ua.match( /NokiaBrowser\/([0-9\.]+)/ ) && parseFloat(RegExp.$1) === 7.3 && webkit && wkversion >= 533
				);
			})();

	// Expose overthrow API
	w.overthrow = {};

	w.overthrow.enabledClassName = enabledClassName;

	w.overthrow.addClass = function(){
		if( docElem.className.indexOf( w.overthrow.enabledClassName ) === -1 ){
			docElem.className += " " + w.overthrow.enabledClassName;
		}
	};

	w.overthrow.removeClass = function(){
		docElem.className = docElem.className.replace( w.overthrow.enabledClassName, "" );
	};

	// Enable and potentially polyfill overflow
	w.overthrow.set = function(){
			
		// If nativeOverflow or at least the element canBeFilledWithPoly, add a class to cue CSS that assumes overflow scrolling will work (setting height on elements and such)
		if( nativeOverflow ){
			w.overthrow.addClass();
		}

	};

	// expose polyfillable 
	w.overthrow.canBeFilledWithPoly = canBeFilledWithPoly;

	// Destroy everything later. If you want to.
	w.overthrow.forget = function(){

		w.overthrow.removeClass();
		
	};
		
	// Expose overthrow API
	w.overthrow.support = nativeOverflow ? "native" : "none";
		
})( this );

/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, o, undefined ){

	// o is overthrow reference from overthrow-polyfill.js
	if( o === undefined ){
		return;
	}

	// Easing can use any of Robert Penner's equations (http://www.robertpenner.com/easing_terms_of_use.html). By default, overthrow includes ease-out-cubic
	// arguments: t = current iteration, b = initial value, c = end value, d = total iterations
	// use w.overthrow.easing to provide a custom function externally, or pass an easing function as a callback to the toss method
	o.easing = function (t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	};

	// tossing property is true during a programatic scroll
	o.tossing = false;

	// Keeper of intervals
	var timeKeeper;

	/* toss scrolls and element with easing

	// elem is the element to scroll
	// options hash:
		* left is the desired horizontal scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* top is the desired vertical scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front.
		* duration is the number of milliseconds the throw will take. Default is 100.
		* easing is an optional custom easing function. Default is w.overthrow.easing. Must follow the easing function signature

	*/
	o.toss = function( elem, options ){
		o.intercept();
		var i = 0,
			sLeft = elem.scrollLeft,
			sTop = elem.scrollTop,
			// Toss defaults
			op = {
				top: "+0",
				left: "+0",
				duration: 50,
				easing: o.easing,
				finished: function() {}
			},
			endLeft, endTop, finished = false;

		// Mixin based on predefined defaults
		if( options ){
			for( var j in op ){
				if( options[ j ] !== undefined ){
					op[ j ] = options[ j ];
				}
			}
		}

		// Convert relative values to ints
		// First the left val
		if( typeof op.left === "string" ){
			op.left = parseFloat( op.left );
			endLeft = op.left + sLeft;
		}
		else {
			endLeft = op.left;
			op.left = op.left - sLeft;
		}
		// Then the top val
		if( typeof op.top === "string" ){

			op.top = parseFloat( op.top );
			endTop = op.top + sTop;
		}
		else {
			endTop = op.top;
			op.top = op.top - sTop;
		}

		o.tossing = true;
		timeKeeper = setInterval(function(){
			if( i++ < op.duration ){
				elem.scrollLeft = op.easing( i, sLeft, op.left, op.duration );
				elem.scrollTop = op.easing( i, sTop, op.top, op.duration );
			}
			else{
				if( endLeft !== elem.scrollLeft ){
					elem.scrollLeft = endLeft;
				} else {
					// if the end of the vertical scrolling has taken place
					// we know that we're done here call the callback
					// otherwise signal that horizontal scrolling is complete
					if( finished ) {
						op.finished();
					}
					finished = true;
				}

				if( endTop !== elem.scrollTop ){
					elem.scrollTop = endTop;
				} else {
					// if the end of the horizontal scrolling has taken place
					// we know that we're done here call the callback
					if( finished ) {
						op.finished();
					}
					finished = true;
				}

				o.intercept();
			}
		}, 1 );

		// Return the values, post-mixin, with end values specified
		return { top: endTop, left: endLeft, duration: o.duration, easing: o.easing };
	};

	// Intercept any throw in progress
	o.intercept = function(){
		clearInterval( timeKeeper );
		o.tossing = false;
	};

})( this, this.overthrow );

/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, o, undefined ){

	// o is overthrow reference from overthrow-polyfill.js
	if( o === undefined ){
		return;
	}

	o.scrollIndicatorClassName = "overthrow";
	
	var doc = w.document,
		docElem = doc.documentElement,
		// o api
		nativeOverflow = o.support === "native",
		canBeFilledWithPoly = o.canBeFilledWithPoly,
		configure = o.configure,
		set = o.set,
		forget = o.forget,
		scrollIndicatorClassName = o.scrollIndicatorClassName;

	// find closest overthrow (elem or a parent)
	o.closest = function( target, ascend ){
		return !ascend && target.className && target.className.indexOf( scrollIndicatorClassName ) > -1 && target || o.closest( target.parentNode );
	};
		
	// polyfill overflow
	var enabled = false;
	o.set = function(){
			
		set();

		// If nativeOverflow or it doesn't look like the browser canBeFilledWithPoly, our job is done here. Exit viewport left.
		if( enabled || nativeOverflow || !canBeFilledWithPoly ){
			return;
		}

		w.overthrow.addClass();

		enabled = true;

		o.support = "polyfilled";

		o.forget = function(){
			forget();
			enabled = false;
			// Remove touch binding (check for method support since this part isn't qualified by touch support like the rest)
			if( doc.removeEventListener ){
				doc.removeEventListener( "touchstart", start, false );
			}
		};

		// Fill 'er up!
		// From here down, all logic is associated with touch scroll handling
			// elem references the overthrow element in use
		var elem,
			
			// The last several Y values are kept here
			lastTops = [],
	
			// The last several X values are kept here
			lastLefts = [],
			
			// lastDown will be true if the last scroll direction was down, false if it was up
			lastDown,
			
			// lastRight will be true if the last scroll direction was right, false if it was left
			lastRight,
			
			// For a new gesture, or change in direction, reset the values from last scroll
			resetVertTracking = function(){
				lastTops = [];
				lastDown = null;
			},
			
			resetHorTracking = function(){
				lastLefts = [];
				lastRight = null;
			},
		
			// On webkit, touch events hardly trickle through textareas and inputs
			// Disabling CSS pointer events makes sure they do, but it also makes the controls innaccessible
			// Toggling pointer events at the right moments seems to do the trick
			// Thanks Thomas Bachem http://stackoverflow.com/a/5798681 for the following
			inputs,
			setPointers = function( val ){
				inputs = elem.querySelectorAll( "textarea, input" );
				for( var i = 0, il = inputs.length; i < il; i++ ) {
					inputs[ i ].style.pointerEvents = val;
				}
			},
			
			// For nested overthrows, changeScrollTarget restarts a touch event cycle on a parent or child overthrow
			changeScrollTarget = function( startEvent, ascend ){
				if( doc.createEvent ){
					var newTarget = ( !ascend || ascend === undefined ) && elem.parentNode || elem.touchchild || elem,
						tEnd;
							
					if( newTarget !== elem ){
						tEnd = doc.createEvent( "HTMLEvents" );
						tEnd.initEvent( "touchend", true, true );
						elem.dispatchEvent( tEnd );
						newTarget.touchchild = elem;
						elem = newTarget;
						newTarget.dispatchEvent( startEvent );
					}
				}
			},
			
			// Touchstart handler
			// On touchstart, touchmove and touchend are freshly bound, and all three share a bunch of vars set by touchstart
			// Touchend unbinds them again, until next time
			start = function( e ){

				// Stop any throw in progress
				if( o.intercept ){
					o.intercept();
				}
				
				// Reset the distance and direction tracking
				resetVertTracking();
				resetHorTracking();
				
				elem = o.closest( e.target );
					
				if( !elem || elem === docElem || e.touches.length > 1 ){
					return;
				}			

				setPointers( "none" );
				var touchStartE = e,
					scrollT = elem.scrollTop,
					scrollL = elem.scrollLeft,
					height = elem.offsetHeight,
					width = elem.offsetWidth,
					startY = e.touches[ 0 ].pageY,
					startX = e.touches[ 0 ].pageX,
					scrollHeight = elem.scrollHeight,
					scrollWidth = elem.scrollWidth,
				
					// Touchmove handler
					move = function( e ){
					
						var ty = scrollT + startY - e.touches[ 0 ].pageY,
							tx = scrollL + startX - e.touches[ 0 ].pageX,
							down = ty >= ( lastTops.length ? lastTops[ 0 ] : 0 ),
							right = tx >= ( lastLefts.length ? lastLefts[ 0 ] : 0 );
							
						// If there's room to scroll the current container, prevent the default window scroll
						if( ( ty > 0 && ty < scrollHeight - height ) || ( tx > 0 && tx < scrollWidth - width ) ){
							e.preventDefault();
						}
						// This bubbling is dumb. Needs a rethink.
						else {
							changeScrollTarget( touchStartE );
						}
						
						// If down and lastDown are inequal, the y scroll has changed direction. Reset tracking.
						if( lastDown && down !== lastDown ){
							resetVertTracking();
						}
						
						// If right and lastRight are inequal, the x scroll has changed direction. Reset tracking.
						if( lastRight && right !== lastRight ){
							resetHorTracking();
						}
						
						// remember the last direction in which we were headed
						lastDown = down;
						lastRight = right;							
						
						// set the container's scroll
						elem.scrollTop = ty;
						elem.scrollLeft = tx;
					
						lastTops.unshift( ty );
						lastLefts.unshift( tx );
					
						if( lastTops.length > 3 ){
							lastTops.pop();
						}
						if( lastLefts.length > 3 ){
							lastLefts.pop();
						}
					},
				
					// Touchend handler
					end = function( e ){

						// Bring the pointers back
						setPointers( "auto" );
						setTimeout( function(){
							setPointers( "none" );
						}, 450 );
						elem.removeEventListener( "touchmove", move, false );
						elem.removeEventListener( "touchend", end, false );
					};
				
				elem.addEventListener( "touchmove", move, false );
				elem.addEventListener( "touchend", end, false );
			};
			
		// Bind to touch, handle move and end within
		doc.addEventListener( "touchstart", start, false );
	};
		
})( this, this.overthrow );

/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */
(function( w, undefined ){
	
	// Auto-init
	w.overthrow.set();

}( this ));
/*
    json2.js
    2014-02-04

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html


    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.


    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the value

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint evil: true, regexp: true */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== 'object') {
    JSON = {};
}

(function () {
    'use strict';

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function () {

            return isFinite(this.valueOf())
                ? this.getUTCFullYear()     + '-' +
                    f(this.getUTCMonth() + 1) + '-' +
                    f(this.getUTCDate())      + 'T' +
                    f(this.getUTCHours())     + ':' +
                    f(this.getUTCMinutes())   + ':' +
                    f(this.getUTCSeconds())   + 'Z'
                : null;
        };

        String.prototype.toJSON      =
            Number.prototype.toJSON  =
            Boolean.prototype.toJSON = function () {
                return this.valueOf();
            };
    }

    var cx,
        escapable,
        gap,
        indent,
        meta,
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string'
                ? c
                : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0
                    ? '[]'
                    : gap
                    ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                    : '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === 'string') {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0
                ? '{}'
                : gap
                ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
                : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function'
                    ? walk({'': j}, '')
                    : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
}());


var Messenger = function () { this.init.apply(this, arguments) };
Messenger.SIGNATURE = 'MZ';

if (window.postMessage) {
    Messenger.createForParent = function () {
        var key    = window.name;
        return new this({
            key   : key,
            window : window.opener || window.parent
        });
    };

    Messenger.createForFrame = function (frame, url) {
        return this.createForWindow(frame.contentWindow, url);
    };

    Messenger.createForWindow = function (window, url) {
        var key    = Messenger.SIGNATURE + Math.floor(Math.random() * 2821109907456 + 2821109907456).toString(36).substring(1) + '@';
        window.name = key;
        window.location.replace(url);
        return new this({
            key : key,
            window : window
        });
    };

    Messenger.prototype = {
        init : function (opts) {
            var self = this;
            self.window = opts.window;
            self.key    = opts.key;
            self._eventListeners = {};

            self.observeEvent();
        },

        send : function (type, obj) {
            var self = this;
            this.window.postMessage(JSON.stringify({
                key  : this.key,
                type : type,
                data : obj
            }), '*');
        },

        observeEvent : function () {
            var self = this;
            self.messageListener = function (e) {
                var data;
                try {
                    data = JSON.parse(e.data);
                } catch (err) {
                    if (Messenger.ENABLE_DEBUG && window.console && window.console.log) console.log(err.name + ': ' + err.message);
                    return;
                }
                if (data.key != self.key) return;
                self.dispatchEvent(data.type, data.data);
            };
            if (window.attachEvent) {
                window.attachEvent("onmessage", self.messageListener, false);
            } else {
                window.addEventListener("message", self.messageListener, false);
            }
        },

        destroy : function () {
            var self = this;
            if (window.detachEvent) {
                window.detachEvent("onmessage", self.messageListener, false);
            } else {
                window.removeEventListener("message", self.messageListener, false); 
            }
        },

        hasEventListener: function (type) {
            return !!(this._eventListeners[type] instanceof Array && this._eventListeners[type].length);
        },

        addEventListener: function (type, listener) {
            if (!listener) return;
            if (!this.hasEventListener(type)) {
                this._eventListeners[type] = [];
            }
            var listeners = this._eventListeners[type];
            for (var i = 0, it; (it = listeners[i]); i++) {
                if (listener == it) {
                    return;
                }
            }
            listeners.push(listener);
        },

        removeEventListener: function (type, listener) {
            if (this.hasEventListener(type)) {
                var listeners = this._eventListeners[type];
                for (var i = 0, it; (it = listeners[i]); i++) {
                    if (listener == it) {
                        listeners.splice(i, 1);
                        return;
                    }
                }
            }
        },

        dispatchEvent: function (type, opt) {
            if (!this.hasEventListener(type)) return false;
            var listeners = this._eventListeners[type];
            for (var i = 0, it; (it = listeners[i]); i++) {
                it.call(this, opt);
            }
            return true; // preventDefault is not implemented
        }
    };
} else {
    Messenger.createForParent = function () {
        if (window.parent == window && !window.opener) return null;
        var iframe = document.createElement('iframe');
        var opts   = window.name.split('|', 2);
        var key    = opts[0];
        var url    = opts[1];
        document.body.appendChild(iframe);
        var output = iframe.contentWindow;
        output.name = key;
        iframe.width = 1;
        iframe.height = 1;
        iframe.setAttribute('style', 'height:1px;width:1px;visibility:hidden;');
        output.location.replace(url);
        return new this({
            key : key,
            url : url,
            input : window,
            output : output
        });
    };
    Messenger.createForFrame = function (frame, url) {
        return this.createForWindow(frame.contentWindow, url);
    };
    Messenger.createForWindow = function (window, url) {
        // 2821109907456 = 36 ** 8
        var key    = Messenger.SIGNATURE + Math.floor(Math.random() * 2821109907456 + 2821109907456).toString(36).substring(1) + '@';
        var empty  = this.findEmptyResource();
        if (!empty) return null;
        window.name  = key + '|' + empty;
        window.location.replace(url);
        return new this({
            key : key,
            url : url,
            input : function () { return window[0] },
            output : window
        });
    };
    Messenger.findEmptyResource = function () {
        var origin = location.protocol + '//' + location.host;
        var imgs = document.getElementsByTagName('img');
        for (var i = 0, it; (it = imgs[i]); i++) {
            if (it.src.indexOf(origin) === 0) return it.src;
        }

        var links = document.getElementsByTagName('link');
        for (var i = 0, it; (it = links[i]); i++) {
            if (it.href.indexOf(origin) === 0) return it.href;
        }
        
        return null;
    };
    Messenger.absolute = function (url) {
        var img = new Image();
        img.src = url;
        var ret = img.src;
        img.src = '';
        img = null;
        return ret;
    };
    Messenger.prototype = {
        init : function (opts) {
            var self = this;
            self._eventListeners	 = {};
            self.key = opts.key;
            self.url = opts.url;
            self.input = typeof(opts.input) == 'function' ? opts.input : function () { return opts.input };
            self.output = typeof(opts.output) == 'function' ? opts.output : function () { return opts.output };
            /** read buffer */
            self.buffer = [];
            /** received msg sequence id */
            self.ack   = 0;
            /** write queue */
            self.queue = [];
            /** sent messages */
            self.sent  = [];
            /** sent msg sequence id */
            self.msgid = 0;
            self.regexp = new RegExp('^(' + Messenger.SIGNATURE + '[A-Za-z0-9]{8}@)([A-Za-z0-9]{4})([A-Za-z0-9]{4})([A-Za-z0-9]{2})(.+)');
            self.setupTimer();
        },

        send : function (type, obj) {
            var self = this;

            if (typeof data === 'undefined') data = null;
            var body = encodeURIComponent(JSON.stringify({
                type : type,
                data : obj
            }));

            /*
             * Data Structure
             * message : '#' + header (20bytes) + data (rest)
             * header  : key (11bytes) + msgid (4bytes) + ack (4bytes) + msg rest (2byte)
             * key	   : 'XX' + random (8bytes) + '@'
             */

            var dataLimit = 2083 - (this.url.length) - 22;
            var sequence  = [];
            while (body.length) {
                sequence.push(body.substring(0, dataLimit));
                body = body.substring(dataLimit);
            }

            var msglen = sequence.length;
            for (var i = 0, data; (data = sequence[i]); i++) {
                var msgseq = i.toString(36);
                self.queue.push({
                    msgid   : self.msgid++,
                    msgrest : msglen - i - 1,
                    data    : data
                });
            }

            self.exhaust();
        },

        setupTimer : function () {
            var self = this;
            if (self.timer) return;
            self.timer = setInterval(function () {
                var data;
                try {
                    var input  = self.input();
                    data = input.location.hash.substring(1);
                    if (!data || data == '_') return;
                    var base  = input.location.protocol + '//' + input.location.host + input.location.pathname + input.location.search;
                    input.location.replace(base + '#_');
                } catch (_) { return }

                var match = data.match(self.regexp);
                if (!match) return;

                var message = {
                    key      : match[1],
                    msgidraw : match[2],
                    msgid    : parseInt(match[2], 36),
                    ack      : parseInt(match[3], 36),
                    msgrest  : parseInt(match[4], 36),
                    data     : match[5]
                };

                for (var i = 0, it; (it = self.sent[i]); i++) {
                    if (it.msgid < message.ack) self.sent.splice(i--, 1);
                }

                for (var i = 0, it; (it = self.queue[i]); i++) {
                    if (it.msgid < message.ack) self.queue.splice(i--, 1);
                }

                // log(['ack', self.ack + '=' + message.msgid, message.data == 'ACK', message.ack, self.sent]);

                if (message.data == 'ACK') return;

                if (self.ack != message.msgid) return;

                self.ack = message.msgid + 1;

                // log(['recv', message]);

                self.buffer.push(message);

                if (message.msgrest !== 0) return;

                data = '';
                for (var i = 0, it; (it = self.buffer[i]); i++) {
                    data += it.data;
                }
                self.buffer = [];

                var obj;
                try {
                    obj = JSON.parse(decodeURIComponent(data));
                } catch (e) {
                    if (Messenger.ENABLE_DEBUG && window.console && window.console.log) console.log(e.name + ': ' + e.message);
                    return;
                }

                if (!self.queue.length) {
                    self.queue.push({
                        msgid   : 0,
                        msgrest : 0,
                        data    : 'ACK'
                    });
                    self.exhaust();
                }

                self.dispatchEvent(obj.type, obj.data);
            }, 10);
        },

        destroy : function () {
        },

        exhaust : function () {
            var self = this;
            if (!self.queue.length) return;

            var now  = new Date().getTime();
            if (now < self.lastSent + 50) {
                setTimeout(function () {
                    self.exhaust();
                }, 50);
                return;
            }

            var message = self.queue.shift();
            var ack     = (self.ack % 1679616 + 1679616).toString(36).substring(1);
            var msgid   = (message.msgid % 1679616 + 1679616).toString(36).substring(1);
            var msgrest = (message.msgrest % 1296 + 1296).toString(36).substring(1);

            // log(['send', message]);
            var url = self.url + '#' + self.key + msgid + ack + msgrest + message.data;
            self.output().location.replace(url);
            self.lastSent = new Date().getTime();
            if (message.data != 'ACK') self.sent.push(message);

            clearTimeout(self.ackTimer);
            self.ackTimer = setTimeout(function () {
                if (self.sent.length) {
                    self.queue = self.sent.concat(self.queue).sort(function (a, b) {
                        return a.msgid - b.msgid;
                    });
                    // log(['resend', self.queue]);
                    self.sent  = [];
                    setTimeout(function () {
                        self.exhaust();
                    }, Math.random() * 200);
                }
            }, 500);

            setTimeout(function () {
                self.exhaust();
            }, 50);
        },

        hasEventListener: function (type) {
            return !!(this._eventListeners[type] instanceof Array && this._eventListeners[type].length);
        },

        addEventListener: function (type, listener) {
            if (!listener) return;
            if (!this.hasEventListener(type)) {
                this._eventListeners[type] = [];
            }
            var listeners = this._eventListeners[type];
            for (var i = 0, it; (it = listeners[i]); i++) {
                if (listener == it) {
                    return;
                }
            }
            listeners.push(listener);
        },

        removeEventListener: function (type, listener) {
            if (this.hasEventListener(type)) {
                var listeners = this._eventListeners[type];
                for (var i = 0, it; (it = listeners[i]); i++) {
                    if (listener == it) {
                        listeners.splice(i, 1);
                        return;
                    }
                }
            }
        },

        dispatchEvent: function (type, opt) {
            if (!this.hasEventListener(type)) return false;
            var listeners = this._eventListeners[type];
            for (var i = 0, it; (it = listeners[i]); i++) {
                it.call(this, opt);
            }
            return true; // preventDefault is not implemented
        }
    };
}

// Epic
Messenger.findEmptyResource = function () {
    var img = new Image();
    img.src = "/images/spacer.gif";
    var ret = img.src;
    img = null;
    return ret;
};


function keyString (e) {
	var ret = '';
	if (e.ctrlKey) ret += 'C-';
	if (e.altKey)  ret += 'M-';
	if (e.metaKey) ret += 'W-';
	if (e.which === 0) {
		if (e.shiftKey) ret += 'S-';
		ret += arguments.callee.table1[e.keyCode];
	} else {
		var key = arguments.callee.table2[e.which];
		if (typeof key == "string") {
			if (e.shiftKey) ret += 'S-';
			ret += key;
		} else {
			if (e.ctrlKey && e.which <= 26) {
				e.which += 64;
			}
			if ((65 <= e.which && e.which <= 90) || (97 <= e.which && e.which <= 122)) {
				ret += String.fromCharCode(e.which)[e.shiftKey ? 'toUpperCase' : 'toLowerCase']();
			} else {
				if (e.keyCode && e.shiftKey) ret += 'S-';
				ret += String.fromCharCode(e.which);
			}
		}
	}
	return ret;
}
keyString.table1 = { 9 : "TAB", 27 : "ESC", 33 : "PageUp", 34 : "PageDown", 35 : "End", 36 : "Home", 37 : "Left", 38 : "Up", 39 : "Right", 40 : "Down", 45 : "Insert", 46 : "Delete", 112 : "F1", 113 : "F2", 114 : "F3", 115 : "F4", 116 : "F5", 117 : "F6", 118 : "F7", 119 : "F8", 120 : "F9", 121 : "F10", 122 : "F11", 123 : "F12" };
keyString.table2 = { 8 : "BS", 9 : "TAB", 16:"", 17:"", 18:"", 27 : "ESC", 13 : "RET", 32 : "SPC", 224: "" };

this.keyString = keyString;

// Usage (with jQuery):
// var keyConfig = {
//     'M-1' : function () {},
//     'M-2' : function () {},
//     'M-3' : function () {},
//     'M-4' : function () {},
//     'M-0' : function () {},
//     '.'   : function () {},
//     'ESC' : function () {},
// };
// $(window).keydown(function (e) {
//     if (!e.altKey) return;
//     var key = keyString(e);
//     var handler = keyConfig[key];
//     handler && handler();
// });
// $(window).keypress(function (e) {
//     var key = keyString(e);
//     var handler = keyConfig[key];
//     handler && handler();
// });
//

var EditDesign = function () { this.init.apply(this, arguments) };
EditDesign.prototype = {
    init : function (css) {
        var self = this;
        self.data = {};
        self.setCSS(css);
    },

    setCSS : function (css) {
        var self = this;
        self.css = css;
        self.scanCSS(function (attrs, content) {
            var section = attrs['section'];
            delete attrs['section'];
            attrs.content = content;
            self.data[section] = attrs;
        });
    },

    getCSS : function () {
        var self = this;
        var done = {};
        var css =  this.scanCSS(function (attrs, content) {
            var section = attrs.section;
            if (done[section]) return '';

            var index  = self.indexOf(section);

            var ret = self.getSectionAsCSS(section);
            done[section] = true;

            for (var i = 0, len = index || EditDesign.sections.length; i < len; i++) { 
                section = EditDesign.sections[i];
                if (done[section]) continue;
                ret = self.getSectionAsCSS(section) + ret;
                done[section] = true;
            }

            return ret;
        });

        var rest = [];
        for (var key in self.data) if (self.data.hasOwnProperty(key)) rest.push(key);
        rest.sort(function (a, b) { return self.indexOf(a) - self.indexOf(b) });

        for (var i = 0, it; (it = rest[i]); i++) {
            var section = it;
            if (!done[section]) {
                css += self.getSectionAsCSS(section);
            }
        }

        return css.replace(/^\s+|\s+$/g, '');
    },

    getSectionAsCSS : function (section) {
        var self = this;
        if ( ! self.data[section] ) return '';
        var selected = self.data[section].selected;
        content = self.data[section].content;
        return '\n/* <system section="' + section + '" selected="' + selected + '"> */\n' + content + '\n/* </system> */\n';
    },

    indexOf : function me (section) {
        if (!me.map) {
            me.map = {};
            for (var i = 0, len = EditDesign.sections.length; i < len; i++) {
                me.map[section] = i;
            }
        }
        return me.map[section];
    },

    scanCSS : function (callback) {
        return this.css.replace(/\n?\/\* <system([^>]+)> \*\/\n*([\s\S]+?)\n*\/\* <\/system> \*\/\n?/g, function (_, attributes, content) {
            var attrs = {}; attributes.replace(/(\S+)="([^"]+)"/g, function (_, key, val) { attrs[key] = val });
            var ret = callback(attrs, content);
            return typeof(ret) == 'undefined' ? _ : ret;
        });
    },

    getData : function (section) {
        return this.data[section] || {};
    },

    setData : function (section, selected, content) {
        this.data[section] = {
            selected : selected,
            content  : content
        };
        delete this.indexOf.me;
    }
};
EditDesign.sections = [ ];

this.EditDesign = EditDesign;


//     Underscore.js 1.5.2
//     http://underscorejs.org
//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.
(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?(this._wrapped=n,void 0):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.5.2";var A=j.each=j.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a<e.computed&&(e={value:n,computed:a})}),e.value},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return arguments.length<2||r?n[j.random(n.length-1)]:j.shuffle(n).slice(0,Math.max(0,t))};var k=function(n){return j.isFunction(n)?n:function(t){return t[n]}};j.sortBy=function(n,t,r){var e=k(t);return j.pluck(j.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={},i=null==r?j.identity:k(r);return A(t,function(r,a){var o=i.call(e,r,a,t);n(u,o,r)}),u}};j.groupBy=F(function(n,t,r){(j.has(n,t)?n[t]:n[t]=[]).push(r)}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=null==r?j.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])<u?i=o+1:a=o}return i},j.toArray=function(n){return n?j.isArray(n)?o.call(n):n.length===+n.length?j.map(n,j.identity):j.values(n):[]},j.size=function(n){return null==n?0:n.length===+n.length?n.length:j.keys(n).length},j.first=j.head=j.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.indexOf(t,n)>=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o;return function(){i=this,u=arguments,a=new Date;var c=function(){var l=new Date-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u)))},l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u)),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=w||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n","	":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
//# sourceMappingURL=underscore-min.map
var AccessLog = {
    showGraph: function (counts, opts) {
        var offset = new Date().getTimezoneOffset() * 60 * 1000;
        var unit   = opts.unit;
        var end    = Math.floor(new Date().getTime() / unit) * unit + unit;
        var start  = end - (unit * opts.number);

        var graphAreaMarginRight = opts.graphAreaMarginRight || 50;
        var barWidth = opts.barWidth || 15;

        var data = [];
        var n = 0;
        while (start <= end) {
            n += counts[start] || 0;
            if ( (start - offset) % unit === 0) {
                // jQuery flot は UTC で表示してしまうので、
                // あらかじめ offset を計算して epoch をズラす
                data.push([ start - offset - unit, n ]);
                n = 0;
            }
            start += 60 * 15 * 1000; // アクセスログは15分ごとに記録されている
        }

        opts.parent.show();
        opts.parent.
            height(+opts.parent.attr('data-graph-height')).
            width(opts.parent.parent().width() - graphAreaMarginRight);

        var plot = $.plot(opts.parent, [
            {
                label : '',
                data  : data,
                bars   : { show: true, lineWidth: barWidth },
                legend : { show: false }
            }
        ], {
            xaxis : {
                mode: "time",
                minTickSize: opts.minTickSize,
                timeformat : opts.timeformat
            },
            yaxis : {
                min: 0,
                minTickSize: 1,
                autoscaleMargin: 0.5,
                labelWidth: +opts.parent.attr('data-yaxis-width'),
                tickFormatter : function (number) {
                    return number.toString();
                }
            },
            grid : {
                axisMargin : 5,
                labelMargin : 5,
                minBorderMargin : 0,
                borderWidth : 1,
                borderColor : "#CCCCCC",
                hoverable: true
            }
        });

        var tooltip = $('.tooltip', opts.parent);
        if (tooltip.length === 0) {
            tooltip = $('<div class="tooltip"></div>').appendTo(opts.parent).hide();
        }
        opts.parent.bind('plothover', function (e, pos, item) {
            var axes = plot.getAxes();
            if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max || pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) return;

            var series = plot.getData()[0];

            for (var n = 0; n < series.data.length; ++n) if (series.data[n][0] > pos.x) break;

            var p1 = series.data[n - 1], p2 = series.data[n];
            var p  = (p1 === null) ? p2:
                     (p2 === null) ? p1:
                     (pos.x - p1[0] < p2[0] - pos.x) ? p1 : p2;

            tooltip.show();
            showTooltip(
                tooltip,
                axes.xaxis.p2c(p[0]),
                axes.yaxis.p2c(p[1]),
                p[1]
            );
        });

        function showTooltip (tooltip, x, y, contents) {
            tooltip.css({
                    position: 'absolute',
                    top: y - 25,
                    left: x + 13
                }).text(contents);
        }
    }
};
(function($){

if (!window.Hatena) window.Hatena = {};
if (!Hatena.Diary) Hatena.Diary = {};

Hatena.Diary.BUG = function (error, append) {
    $.ajax({
        type: 'get',
        url: Hatena.Diary.URLGenerator.static_url('/js/vendor/stacktrace/stacktrace.js'),
        cache: true,
        dataType: 'script'
    }).done(function () {
        var trace;
        try {
            trace = printStackTrace({ e: error });
            trace.pop();        // printStackTraceを除く
        } catch (e) {
            trace = null;
        }
        var msg = '[BUG] ' + (append || '') + ' ' + error;

        var content = [
            location.href,
            msg,
            trace
        ];

        var img = new Image();
        img.src = (Hatena.Diary.data('admin-domain') || '') + '/api/bug?content=' + encodeURIComponent(JSON.stringify(content));
        Hatena.Diary.LOG(msg);
        Hatena.Diary.LOG(trace);
    });
};

/**
 * Ajax の onerror とかにいれる
 */
Hatena.Diary.REPORT_BUG = function (name) {
    return function (error) {
        Hatena.Diary.BUG(error, name);
    };
};

Hatena.Diary.LOG = (function() {
    if (window.console && window.console.log) {
        if (console.log.bind) {
            return console.log.bind(console);
        } else {
            return function(obj) { console.log(obj) };
        }
    } else {
        return function() {};
    }
})();

Hatena.Diary.data = function (name) {
    var html = document.documentElement;
    return html.getAttribute('data-' + name);
};

Hatena.Diary.SpeedTrack = {
    init: function () {
        if (this.initialized === true) return;

        // 送信は100分の1にしたい
        this.enabled = Math.floor(Math.random() * 100) === 0;

        var now = new Date();
        this.startTime = now;
        this.data = {};
        this.checkpoints = [];
        this.elapsedTimes = [];

        this.initialized = true;
    },
    setDomain: function (domain) {
        this.domain = domain;
    },
    setPage: function (page) {
        this.page = page;
    },
    record: function (name) {
        var endTime = new Date();
        var elapsed = endTime.getTime() - this.startTime.getTime();
        this.checkpoints.push(name);
        this.elapsedTimes.push(elapsed);

        this.send();
    },
    send: function () {
        if (this._send) return this._send();

        // 1秒に1回まで送信する
        this._send = _.throttle(function () {
            if (!this.enabled) return;

            var img = new Image();
            img.src = (Hatena.Diary.data('admin-domain') || '') + '/api/track/speed?' + $.param({
                track_domain: this.domain,
                track_page: this.page,
                track_speed_checkpoints: this.checkpoints,
                track_speed_elapsed_times: this.elapsedTimes,
                blog : Hatena.Diary.data('blogs-uri-base') || ('http://' + Hatena.Diary.data('blog'))
            });

            this.checkpoints = [];
            this.elapsedTimes = [];
        }, 1000);

        this._send();
    }
};
Hatena.Diary.SpeedTrack.init();

Hatena.Diary.Dropdown = {
    id : 'hatena-diary-dropdown',

    /*
     * options:
     * - show       [Boolean] dropdown の表示非表示を明示的に指定 (無指定でトグル)
     * - key        [String]  すでに dropdown が表示されていてもこの値が違っていたら破棄して作りなおす
     * - parent     [String]  親 dropdown の id を指定する。親が消えたら自分も消える
     * - className  [String]  container要素に指定するクラス。スペース区切りで複数指定 ("a-class b-class")
     * - callback   [function(dropdown, messenger)]
     */
    toggle : function (uri, init, id, options) {
        id = Hatena.Diary.Dropdown.id + (id ? '-' + id : uri.replace(/\//, '-'));
        options = options || {};

        if (typeof options !== 'object') {
            Hatena.Diary.BUG('Wrong type of options given: ' + options);
        }

        var $container = $(document.getElementById(id));

        if (options.key) {
            if ($container.length && $container.attr('data-dropdown-key') !== options.key) {
                $container.remove();
                $container = $();
            }
        }

        if ($container.length) {
            var show;
            if ('show' in options) {
                show = !!options.show;
            } else {
                show = !$container.is(':visible');
            }
            $container[ show ? 'fadeIn' : 'fadeOut' ]('fast');
            $container.trigger('dropdown:' + (show ? 'show' : 'hide') + ':start');
        } else if ('show' in options && options.show === false) {
            // nop
        } else {
            $container = $('<div class="hatena-globalheader-window"></div>').
                hide().
                attr('id', id).
                appendTo(document.body);

            if (options.key) {
                $container.attr('data-dropdown-key', options.key);
            }

            if (options.parent) {
                var parent = document.getElementById(Hatena.Diary.Dropdown.id + '-' + options.parent);
                $(parent).on('dropdown:hide:start', function () {
                    $container.fadeOut('fast');
                });
            }

            if (options.className) {
                $container.addClass(options.className);
            }

            var iframe = $('<iframe frameborder="0" width="150" height="300"></iframe>').appendTo($container);

            var dropdown = iframe[0];

            if (!/^https?:/.test(uri)) {
                uri = Hatena.Diary.data('admin-domain') + uri;
            }

            var messenger = Messenger.createForFrame(dropdown, uri);
            messenger.addEventListener('close', function () {
                Hatena.Diary.Window.hide(iframe);
            });

            messenger.addEventListener('init', function (css) {
                if (css) $container.css(css);
                messenger.send('init', init);
            });

            messenger.addEventListener('resize', function (css) {
                if (css) $container.css(css);
            });

            messenger.addEventListener('reload', function (data) {
                location.reload(true);
            });

            if (options.callback) {
                options.callback(dropdown, messenger);
            }

            Hatena.Diary.Window.show($container, {
                destroy : function () {
                    $container.remove();
                    messenger.destroy();
                },
                keepOthers: !!options.parent || false
            });

            if (init) {
                if ('left' in init || 'right' in init || 'top' in init) {
                    var offset = $container.offset();
                    if ('left' in init) {
                        offset.left = init.left;
                    } else if ('right' in init) {
                        offset.left = init.right - $container.width();
                    }
                    if ('top' in init) {
                        offset.top = init.top;
                    }
                    $container.offset(offset);
                }

                if ('height' in init) {
                    $container.height(init.height);
                }
            }
        }
    }
};

Hatena.Diary.Feedback = {
    id : 'hatena-diary-feedback',

    toggle : function (uri) {
        var feedback = document.getElementById(Hatena.Diary.Feedback.id);
        if (feedback) {
            $(feedback).fadeToggle('fast');
        } else {
            var iframe = $('<iframe frameborder="0" width="320" height="320"></iframe>').
                hide().
                attr('id', Hatena.Diary.Feedback.id).
                appendTo(document.body);

            feedback = iframe[0];

            var messenger = Messenger.createForFrame(feedback, uri + '?uri=' + encodeURIComponent(location.href) + '&page_id=' + encodeURIComponent(Hatena.Diary.data('page')));
            messenger.addEventListener('close', function () {
                Hatena.Diary.Window.hide(iframe);
            });

            messenger.addEventListener('resize', function (css) {
                if (css) iframe.css(css);
            });

            Hatena.Diary.Window.show(iframe, {
                destroy : function () {
                    iframe.remove();
                    messenger.destroy();
                },
                fixScroll : true
            });
       }
    }
};

Hatena.Diary.Util = {
    canonicalizeColor : function (color) {
        if (color.match(/#([0-9a-f]{6})/i)) {
            color = RegExp.$1;
        } else
        if (color.match(/#([0-9a-f])([0-9a-f])([0-9a-f])/i)) {
            color = RegExp.$1 + RegExp.$1 + RegExp.$2 + RegExp.$2 + RegExp.$3 + RegExp.$3;
        } else
        if (color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+)\s*)?/)) {
            var transparent = (RegExp.$4.length && +RegExp.$4 === 0);
            color =
                transparent ? null :
                ("0" + (+RegExp.$1).toString(16)).slice(-2) +
                ("0" + (+RegExp.$2).toString(16)).slice(-2) +
                ("0" + (+RegExp.$3).toString(16)).slice(-2);
        } else {
            color = null;
        }
        return color ? color.toLowerCase() : null;
    },

    updateDynamicPieces : function (container) {
        container = $(container[0]);
        Hatena.Locale.updateTimestamps(container[0]);
        if (Hatena.Star && Hatena.Star.WindowObserver.loaded) {
            container.find('span.hatena-star-comment-container, span.hatena-star-star-container').remove();
            Hatena.Star.EntryLoader.loadNewEntries(container[0]);
        }
        Hatena.Diary.Util.loadNicknames(container);
        Hatena.Diary.setupMathJax(container);
    },

    // iframeの高さがdocument.body.heightになるようメッセージを送る
    // OperaのJSON.stringifyがバグってるので，ここで吸収 詳しくはRedmineのチケット615参照
    // Operaのバグが直ったら*1は消してよい
    sendResizeRequest : function  () {
        Hatena.Diary.Pages.send('resize', {
            height: $(document.body).height() * 1
        });
    },
    backupTab: function (args) {
        var $container = args.$container;
        var key = args.key;
        var onchange = args.onchange;

        var isAvailable;

        try {
            isAvailable = localStorage;
        } catch(ignore) {}

        if (!isAvailable) return;

        var localStorageKey = 'Hatena.Diary.Util.backupTab.' + key;

        var getValue = function() {
            return localStorage[localStorageKey];
        };

        var setValue = function(value) {
            localStorage[localStorageKey] = value;
        };

        var restoreLastValue = function() {
            var lastValue = getValue();
            if (lastValue === undefined) return;

            var $input = $container.find('input[value="' + lastValue + '"]');
            $input.trigger('click');
            onchange($input);
        };

        restoreLastValue();

        $container.delegate('input', 'change', function() {
            var $input = $(this);

            setValue($input.val());

            onchange($input);
        });
    },
    preventDuplicateSubmit: function($form) {
        // 二重submit対策
        // submitボタンが複数あるときsubmit前にdisabledにすると値自体送られなくなってしまう対策で，submitが済んでからdisabledにしています
        _.defer(function() {
            $form.find(':submit').prop('disabled', true);
        });
    },
    extend: function(target, parent) {
        // parentのプロパティを順にtargetに移していく
        // targetにすでに存在するときは移さない
        for (var key in parent) if (parent.hasOwnProperty(key) && ! target.hasOwnProperty(key)) {
            target[key] = parent[key];
        }

    },
    // get_resource()が真になったら一度だけmain_fun()する
    // 一度同期的にチェックし，その後はpolling
    // intervalが指定されていなければ500msごと
    waitForResource: function(get_resource, main_fun, interval) {
        if (!interval) interval = 500;
        var role = function() {
            if (get_resource()) {
                main_fun();
                return true;
            }
            return false;
        };
        if (role()) return;
        var timer = setInterval(function() {
            if (role()) clearInterval(timer);
        }, interval);
    },
    setupTipsy: function() {
        // touchデバイスでは一度タップしないとtipsy出ない，使い勝手下がるのでtipsy無効化
        if (Hatena.Diary.Browser.isTouch) return;

        if ( ! $.fn.tipsy ) return;

         // n
        // w e
        //  s

        var rules = {
            left: 'e',
            right: 'w',
            bottom: 'n',
            top: 's',
            northwest: 'nw',
            southwest: 'sw',
            northeast: 'ne',
            southeast: 'se'
        };
        var $body = $(document.body);

        for (var rule in rules) if (rules.hasOwnProperty(rule)) {
            var selector = '.tipsy-' + rule;
            var gravity = rules[rule];

            $body.tipsy({
                gravity: gravity,
                fade: false,
                opacity: 1.0,
                live: selector
            });
        }
    },
    // $.paramの逆
    // input: key=value1&key=value2 形式のString
    // output: { key: [value1, value2] }
    decodeParam : function (data) {
        var params = {};
        var values = data.split('&');
        for (var i = 0, len = values.length; i < len; i++) {
            if (!values[i].match(/[=]/)) continue;
            var kv = values[i].split('=');
            var key = decodeURIComponent(kv[0]);
            var val = kv[1].replace(/\+/g, ' ');
            if (!params[key]) params[key] = [];
            params[key].push(decodeURIComponent(val));
        }

        return params;
    },
    // decodeParamで配列になったクエリパラメータをlocationに変換する
    // decodeParamでは値が1つのときも配列を返すので, 配列の要素が1つのときはキーを変更しない
    // input: { key: value1, key1: [value1], key2: [value1,value2] }
    // output: location?key=value1&key1=value1&key2[]=value1&key2[]=value2
    locationWithParam: function (params) {
        _.each(params, function(value, key){
            if ( _.isArray(value) && value.length == 1) params[key] = value[0];
        });
        return location.pathname + '?' + $.param(params);
    },
    replaceYoutubeURL: function ($entry) {
        // 以前貼り付けたyoutube動画が再生されないのでiframeのsrcのURLを表示時に書き換える
        $entry.find('iframe[src*="youtube.com/"],iframe[src*="youtube.googleapis.com/"]').each(function() {
            var $iframe = $(this);
            var src = $iframe.attr('src');
            $iframe.attr('src', Hatena.Diary.Util.migrateOldStyleYoutubeURL(src));
        });
    },
    migrateOldStyleYoutubeURL: function (url) {
        // XXX: /v/以下のURLはiframeに入れられなくなった．/embed/にしたら再生できる．パラメータも消す必要ある．
        // 旧: https://www.youtube.com/v/***&aaa=bbbb&
        // 新: https://www.youtube.com/embed/***
        // /embed/ でプレイリストを貼り付ける場合は?list= というパラメータが来るので，/v/じゃないときはパラメータ消してはいけない
        if (url.match(/\/v\//i)) {
            url = url.split(/[?&]/)[0];
            url = url.replace(/\/v\//i, '/embed/');
        }

        // XXX: youtube.googleapis.com はiPhoneで再生できなくなった．www.youtube.com/embed/ なら再生できる．
        url = url.replace('youtube.googleapis.com', 'www.youtube.com');

        // XXX: httpsも貼れなくなったので//で貼って現在のプロトコルと一致させる
        url = url.replace(/^https:/, '');
        return url;
    },
    showFlashMessage: function (message) {
        var $container = $(
            '<div class="hatena-globalheader-window message">' +
              '<div class="message">' + message + '</div>' +
            '</div>')
            .css({
                width: 200,
                height: 'auto',
                right: 'auto',
                left: ($(window).width() - 200) / 2
            })
            .appendTo(document.body);

        Hatena.Diary.Window.show($container, {
            destroy : function () {
                $container.remove();
            }
        });
    },
    // windowの座標を表すhashをwindow.openに指定できる文字列に変換
    // position: { width, height, left, top } valueはint
    // return: "width=\d,height=\d,left=\d,top=\d"
    positionToPositionString: function(position) {
        return _.map(_.keys(position), function(key) {
            return key + '=' + position[key];
        }).join(',');
    },
    // 利用規約再同意 notices.count.jsonの返り値を受け取る
    needComrule2013: function(data) {
        if (!data.need_comrule2013) return;
        _.defer(function() {
            var BASE     = location.hostname.match(/\.hatena\.[^:]+/)[0];
            window.top.location.href = 'http://www' + BASE + '/login?need_comrule2013=1';
        });
    },

    // スクロールについてくる要素のセットアップ
    // $container: 直下に子要素要素を1つだけ含む要素 先頭の1つだけ監視するので，複数の要素を監視したい場合は，この関数を複数回呼んでください
    // enable_bottom: #containerの下に合わせて止めるときtrue
    initScrollFollowedElement: function ($container, enable_bottom) {
        var $target = $($container.children()[0]);

        if ($target.length === 0) {
            Hatena.Diary.BUG("ad element not found: " + $container.html(), 'followedAd');
            return;
        }

        var $document = $(document);
        var $page_container = $('#container');

        var onScroll = function() {
            var container_offset = $container.offset();
            var scroll_top = $document.scrollTop();
            var target_height = $target.height();
            var page_container_top = $page_container.offset().top;
            var page_container_height = $page_container.height();

            if (scroll_top + page_container_top < container_offset.top) {
                // 上で固定
                $target.css({
                    position: 'static'
                });
            } else if (!enable_bottom || (scroll_top <  page_container_height - target_height)) {
                // 真ん中 ついてくる

                $target.css({
                    position: 'fixed',
                    top: page_container_top,
                    left: container_offset.left
                });
            } else {
                // 下で固定 #containerの底辺に合わせる
                $target.css({
                    position: 'absolute',
                    top: page_container_top + page_container_height - target_height,
                    left: container_offset.left
                });

            }
        };

        var onResize = function() {

            var container_offset = $container.offset();

            $target.css({
                left: container_offset.left
            });
        };

        $(window).scroll(onScroll).resize(onResize);
        onScroll();

    },

    // $container 内の data-load-nicknames のニックネームを取ってきて要素のテキストを差し替える
    loadNicknames: function($container) {
        var template = _.template('<span class="user-name-nickname"><%- nickname %></span> <span class="user-name-paren">(</span><span class="user-name-hatena-id">id:<%- hatena_id %></span><span class="user-name-paren">)</span>');
        var $elements = $container.find('[data-load-nickname]');
        var user_names = [];
        $elements.each(function() {
            var $element = $(this);
            var user_name = $element.attr('data-user-name');
            user_names.push(user_name);
        });
        user_names = _.uniq(user_names);
        if (user_names.length === 0) return;
        if (user_names.length === 1) user_names.push('hatenablog'); // APIの仕様上user_namesは2つ以上必要

        var displayNicknames = function(friendships) {
            $elements.each(function() {
                $element = $(this);
                var user_name = $element.attr('data-user-name');
                if (friendships[user_name] && user_name != friendships[user_name].name) {
                    var html = template({
                        nickname: friendships[user_name].name,
                        hatena_id: user_name
                    });
                    $element.html(html);
                }
            });
        };

        // JSONPの上限に逹しないため小分けにして通信
        var request = function() {
            var user_names_current = user_names.splice(0, 20);
            $.ajax({
                url: 'http://h.hatena.com/api/friendships/show.json',
                dataType: 'jsonp',
                data: {
                    url_name: user_names_current
                },
                traditional: true
            }).done(function(friendships) {
                displayNicknames(friendships);
                if(user_names.length > 0) {
                    request();
                }
            });
        };

        request();

    },

    // W3CDTF形式のStringをパースしてDateを返す
    // IE8以前はnew Date( )でこの形式をパースできないので正規表現でなんとかする
    // datetime: YYYY-MM-DDThh:mm:ss 形式のString
    // returns: Date | null
    parseW3CDTF: function(datetime) {
        var matched = datetime.match(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/);
        if (!matched) return null;
        return new Date(+matched[1], +matched[2] - 1, +matched[3], +matched[4], +matched[5], +matched[6]);
    },

    // グローバルヘッダ固定時にid指定のリンクを踏むとターゲットの要素がグローバルヘッダに隠れる問題の対応
    // スクロール終わったあと，グローバルヘッダ分スクロールをちょっと戻す
    // 他のJSがイベント見てるとかでスクロール位置変わらないこともあるので
    // しばらくして変化なければあきらめる
    setupScrollAdjustForFixedGlobalHeader: function() {
        var $header = $('#globalheader-container');
        if ($header.css('position') !== 'fixed') return;

        var headerHeight = $('#globalheader-container').height();
        var $document = $(document);

        $document.on('click', 'a[href^="#"]', function() {
            var positionBefore = $document.scrollTop();
            var checkCount = 0;
            var check = function() {
                if ($document.scrollTop() !== positionBefore) {
                    window.scrollBy(0, -headerHeight);
                } else if (checkCount++ < 10) {
                    setTimeout(check, 0);
                }
            };
            setTimeout(check, 0);
        });
    },
    // 指定したURLの画像リソースをロードするまで待つ
    // ロードできたらresolve, 失敗するとrejectされるDeferredを返す
    loadImages: function(urls) {
        var loaded = $.Deferred();
        var images;

        var count = 0;
        var onload = function() {
            count++;
            if (count === urls.length) {
                loaded.resolve(images);
            }
        };
        var onerror = function() {
            loaded.reject(images);
        };

        images = _.map(urls, function(url) {
            var $img = $('<img>');
            $img.on('load', onload)
                .on('error', onerror)
                .attr('src', url);
            return $img[0];
        });

        return loaded.promise();
    }
};

// Google Image Charts APIはdeprecatedなのでmathjaxで置き換える
// 全てのブログで必要になるわけではないので，必要になってから読み込む
// TeX記法生成するとaltにTeXのソースが入ってるので，altがあったら置き換える
// 参考： http://docs.mathjax.org/en/latest/typeset.html
Hatena.Diary.setupMathJax = (function() {
    var loaded;

    return function($root) {
        var $imgs = $root.find('img[src*="chart.apis.google.com/chart?cht=tx&chl="]');
        if (!$imgs.length) return;

        if (!loaded) {
            loaded = $.getScript("https://cdn.mathjax.org/mathjax/2.3-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML");
        }

        loaded.done(function() {
            $imgs.each(function() {
                var $img = $(this);
                var source = $img.attr('alt');
                if (!source) return;
                var $script = $('<script type="math/tex">');
                $img.replaceWith($script);
                MathJax.HTML.setScript($script[0], source);
            });
            MathJax.Hub.Queue(["Typeset", MathJax.Hub, $root[0]]);
        });
    };
})();

Hatena.Diary.Location = {
    setup : function () {
        var data = location.search.slice(1);

        Hatena.Diary.Location._params = Hatena.Diary.Util.decodeParam(data);
    },

    param : function (name) {
        return this.params()[name] ? this.params()[name][0] : null;
    },

    params : function () {
        if (!this._params) this.setup();
        return this._params;
    }
};

Hatena.Diary.Window = {
    shown : [],

    init : function () {
        var self = this;

        $(document.body).click(function (event) {
            var windowClicked = _.any(self.shown, function(win) {
                return win.win[0] === event.target || $.contains(win.win[0], event.target);
            });
            // 表示中のwindowがクリックされたときは閉じない
            if (windowClicked) {
                return;
            }

            self.hideAll();
        });

        self.init = function () { };
    },

    /**
     * opts.closeExplicitlyがtrueだとポップアップウィンドウ以外をクリックしても閉じられない
     * その場合、明示的にポップアップウィンドウを閉じる必要がある
     * opts.keepOthers が真値だと他のポップアップを自動的に閉じない
     */
    show : function (win, opts) {
        var self = this;
        if (!opts) opts = {};
        self.init();
        if (opts.keepOthers) {
             // nop
        } else {
            self.hideAll();
        }
        if (opts.fixScroll) {
            Hatena.Diary.FixScroll.enable();
        }
        if (opts.center) {
            Hatena.Diary.Window._setCenter(win);
        }
        if (opts.showBackground) {
            Hatena.Diary.Window._showBackground();
        }
        self.shown.push({
            closeExplicitly : !!opts.closeExplicitly,
            win : win,
            destroy : opts.destroy || function () {},
            fixScroll: !!opts.fixScroll,
            showBackground: !!opts.showBackground
        });
        win.fadeIn('fast');
    },

    hide : function (win) {
        var self = this;
        for (var i = 0, len = self.shown.length; i < len; i++) {
            var obj = self.shown[i];
            if (obj.win === win) {
                win.fadeOut('fast', obj.destroy);
                $('.modal-window-background').fadeOut('fast');
                if (obj.fixScroll) {
                    Hatena.Diary.FixScroll.disable();
                }
                break;
            }
        }
    },

    hideAll : function () {
        var self = this, restWindows = [];
        for (var i = 0, len = self.shown.length; i < len; i++) {
            if (self.shown[i].closeExplicitly) {
                restWindows.push(self.shown[i]);
            } else {
                self.hide(self.shown[i].win);
            }
        }
        self.shown = restWindows;
    },

    toggle: function (win, option) {
        if (win.is(':visible')) {
            this.hide(win);
            return false;
        } else {
            this.show(win, option);
            return true;
        }
    },

    _setCenter: function (win) {
        var setSize = _.throttle(function() {
            if (!$(win).is(':visible')) {
                $(window).off('resize', setSize);
                return;
            }
            var margin_top = ($(window).height()-$(win).height())/2;
            var margin_left = ($(window).width()-$(win).width())/2;
            $(win).css({
                top:  margin_top,
                left: margin_left
            });
        }, 100);

        $(window).on('resize', setSize);

        setSize();
    },

    _showBackground: function() {
        var $screen = $('<div>').addClass('modal-window-background');
        $screen.appendTo(document.body);
    }
};

Hatena.Diary.FixScroll = {
    enabled: false,
    enable: function() {
        if (this.enabled) return;

        this._top = $(window).scrollTop();
        $(window).bind('scroll', this._scrollHandler);
        this.enabled = true;
    },
    disable: function() {
        if (!this.enabled) return;

        $(window).unbind('scroll', this._scrollHandler);
        this.enabled = false;
    },

    _top: 0,
    _scrollHandler: function(event) {
        if ($(window).scrollTop() == Hatena.Diary.FixScroll._top) return;

        $(window).scrollTop(Hatena.Diary.FixScroll._top);
    }
};

Hatena.Diary.Pages = {
    Blogs      : {},
    Admin      : {},
    BlogsTouch : {},
    AdminTouch : {},

    // グローバルヘッダがロードされて，通信が完了するとresolveされるdeferred
    // loadGlobalHeader内で再代入される
    // ここで定義したdeferredはダミーで，即座にrejectしている
    // 呼び出し元で定義済かどうかをチェックする手間を省くため．
    infoLoaded : (function() {
        var nullObject = $.Deferred();
        nullObject.reject();
        return nullObject.promise();
    })(),

    // init.jsonを呼び出す
    // グローバルヘッダから利用する
    // 完了すると，info, privateInfo をresolveするDeferredを返す
    loadInfo: function() {
        var blogUri = decodeURIComponent(location.hash.substring(1));
        var circleId = Hatena.Diary.Location.param('circle_id');

        var init;
        if (circleId) {
            init = $.ajax({
                url: '/api/init/circle',
                type: 'get',
                dataType: 'json',
                data: {
                    circle_id: circleId
                }
            });
        } else {
            init = $.ajax({
                url : '/api/init',
                type : "get",
                dataType : 'json',
                data : {
                    name : Hatena.Diary.data('name'),
                    blog : blogUri
                }
            });
        }

        var loaded = $.Deferred();
        init.done(function(info) {
            var privateInfo = info['private'];

            // privateに入ってる情報は外側に配信しない．ここで削除しておく
            delete info['private'];

            // 外のフレームに情報送る
            Hatena.Diary.Pages.send('init', info);

            // グローバルヘッダに情報送る．こっちはprivateInfoも一緒に渡す
            loaded.resolve(info, privateInfo);
        });

        return loaded.promise();
    },

    messenger : null,

    createForParent : function () {
        this.messenger = Messenger.createForParent();

        if (Hatena.Diary.data('page') != 'globalheader') {
            $('.close').on('click', function (e) {
                Hatena.Diary.Pages.send('close', { name : window.name });
                return false;
            });

            $(window).keyup(function (e) {
                if (keyString(e) == 'S-ESC') {
                    Hatena.Diary.Pages.send('close', { name : window.name });
                }
            });
        }
    },

    createForFrame : function (iframe, url) {
        this.messenger = Messenger.createForFrame(iframe, url);
    },

    send : function (type, obj) {
        Hatena.Diary.LOG(['send', type, obj]);
        try {
            this.messenger.send(type, obj);
        } catch(error) {
            Hatena.Diary.BUG(error, 'Pages.send(' + type + ')');
        }
    },

    message : function (type, func) {
        this.messenger.addEventListener(type, func);
    },

    // 表示中のテンプレートのデバイスを返す
    // pc | touch
    device: function() {
        var device = Hatena.Diary.data('device');

        if (!device) {
            var message = "device is undefined, page: " + Hatena.Diary.data('page') + ", location: " + location.href;
            Hatena.Diary.BUG(message);
        }

        return device || 'pc';
    }
};

Hatena.Diary.Devices = {
    /*
     * PC で見てるユーザには何もしない
     * touch で見てるユーザは
     *   cookie があればそれを見てリダイレクト
     *   UA があればそれを見てリダイレクト
     */

    use : function (device) {
        if (this.userAgent() == device) {
            document.cookie = 'device=' + encodeURIComponent(device) + '; expires=' + new Date(0).toUTCString() + '; path=/';
        } else {
            var expires = new Date();
            expires.setFullYear(expires.getFullYear() + 1);
            document.cookie = 'device=' + encodeURIComponent(device) + '; expires=' + expires.toUTCString() + '; path=/';
        }
        location.reload();
    },

    userAgent : function () {
        // adminドメインのヘッダーにも同じものがあります
        if (Hatena.Diary.Browser.isTouch) {
            return 'touch';
        } else {
            return 'pc';
        }
    }
};

// https://github.com/wakaba/opentenjs/blob/master/src/Ten.base.js
Hatena.Diary.Browser = {
    isIE: navigator.userAgent.indexOf('MSIE') != -1 || navigator.userAgent.indexOf('Trident/') != -1,
    isIE6 : navigator.userAgent.indexOf('MSIE 6.') != -1,
    isIE7 : navigator.userAgent.indexOf('MSIE 7.') != -1,
    isIE8 : navigator.userAgent.indexOf('MSIE 8.') != -1,
    isIE9 : navigator.userAgent.indexOf('MSIE 9.') != -1,
    isIE10 : navigator.userAgent.indexOf('MSIE 10.') != -1,
    isIE11: navigator.userAgent.indexOf('Trident/') != -1 && navigator.userAgent.indexOf('rv:11.') != -1,
    isMozilla: navigator.userAgent.indexOf('Mozilla') != -1 && !/compatible|WebKit/.test(navigator.userAgent),
    isOpera: !!window.opera,
    isSafari: navigator.userAgent.indexOf('WebKit') != -1 && navigator.userAgent.indexOf('Chrome/') == -1,
    isChrome : navigator.userAgent.indexOf('Chrome/') != -1,
    isFirefox : navigator.userAgent.indexOf('Firefox/') != -1,
    isDSi : navigator.userAgent.indexOf('Nintendo DSi') != -1,
    is3DS : navigator.userAgent.indexOf('Nintendo 3DS') != -1,
    isWii : navigator.userAgent.indexOf('Nintendo Wii') != -1,
    isAndroid : navigator.userAgent.indexOf('Android') != -1,
    isAndroidMobile : navigator.userAgent.indexOf('Android') != -1 && navigator.userAgent.indexOf('Mobile') != -1,
    isAndroidTablet : navigator.userAgent.indexOf('Android') != -1 && navigator.userAgent.indexOf('Mobile') == -1,
    isIPhone : (navigator.userAgent.indexOf('iPod;') != -1 || navigator.userAgent.indexOf('iPhone;') != -1 || navigator.userAgent.indexOf('iPhone Simulator;') != -1),
    isWindowsPhone: navigator.userAgent.indexOf('Windows Phone') != -1,
    isIPad : navigator.userAgent.indexOf('iPad') != -1,
    isSupportsXPath : !!document.evaluate,
    version: {
        string: (/(?:Firefox\/|MSIE |Opera\/|Chrome\/|Version\/)([\d.]+)/.exec(navigator.userAgent) || []).pop(),
        valueOf: function() { return parseFloat(this.string) },
        toString: function() { return this.string }
    }
};
Hatena.Diary.Browser.isTouch = Hatena.Diary.Browser.isIPhone || Hatena.Diary.Browser.isAndroidMobile || Hatena.Diary.Browser.isDSi || Hatena.Diary.Browser.is3DS || Hatena.Diary.Browser.isWindowsPhone;
Hatena.Diary.Browser.isSmartPhone = Hatena.Diary.Browser.isIPhone || Hatena.Diary.Browser.isAndroidMobile || Hatena.Diary.Browser.isWindowsPhone;
Hatena.Diary.Browser.isTablet = Hatena.Diary.Browser.isAndroidTablet || Hatena.Diary.Browser.isIPad;

Hatena.Diary.Browser.thirdPartyCookiesBlocked = $.Deferred(); // ブロックされてるか分かったら Hatena.Diary.Pages.Blogs['*'].init で resolveされる ブロックされてたらtrue

// はてな記法展開
// hatena_syntax: String or [String]，Arrayのとき，各行が<p>で囲まれる
// 成功したとき { html } を返すDeferredを返す
Hatena.Diary.extractSyntax = function(hatena_syntax) {
    var dfd = $.Deferred();
    if (_.isArray(hatena_syntax)) {
        hatena_syntax = hatena_syntax.join("\n\n");
    }

    $.ajax({
        url: "/api/support.expand",
        type : "POST",
        data : {
            syntax: hatena_syntax,
            rkm: Hatena.Diary.data('rkm'),
            rkc: Hatena.Diary.data('rkc')
        },
        dataType: 'json'
    }).done(function(data) {
        dfd.resolve({
            html : data.html
        });
    }).fail(function(error) {
        dfd.reject(error);
    });

    return dfd;
};

// fotolifeにアップロード完了すると返されるfotolife記法を:plain形式のHTMLに展開
// 成功したとき { image, syntax, html } を返すDeferredを返す
Hatena.Diary.extractFotolifeSyntax = function (string) {
    var ret   = $.Deferred();
    var match = string.match(/f:id:([^:]+):(\d+)([jpg]):image/);
    if (match) {
        var syntax = '[' + match[0].replace(':image', ':plain') + ']';
        var name  = match[1];
        var id    = match[2];
        var type  = match[3];
        var path  = [ name.substring(0, 1), name, id.substring(0, 8), id ].join('/');
        var image = 'http://cdn-ak.f.st-hatena.com/images/fotolife/' + path + '_120.jpg';

        Hatena.Diary.extractSyntax(syntax).done(function(data) {
            ret.resolve({
                image : image,
                syntax : syntax,
                html : data.html
            });
        }).fail(function(error) {
            ret.reject(error);
        });
    } else {
        _.defer(function() {
            ret.reject('Invalid format? ' + string);
        });
    }
    return ret.promise();
};

Hatena.Diary.AccessLog = {
    ping : function () {
        var adminDomain = $('html').attr('data-admin-domain');
        if (!adminDomain) return;

        var url = adminDomain + '/api/log';
        var data = {
            uri : location.href,
            referer : document.referrer
        };
        $.ajax({
            url   : url,
            type  : "get",
            cache : false,
            data  : data,
            xhrFields: {
                withCredentials: true
            }
        }).fail(function (e) {
            data._ = new Date().getTime();
            new Image().src = url + '?' + $.param(data);
        });
    }
};

// 最大で1秒に1回だけトラック
Hatena.Diary.trackEvent = (function() {
    var trackNamesQueue = [];
    var timer = null;

    var postTrackNames = function () {
        timer = null;
        var img = new Image();
        img.src = (Hatena.Diary.data('admin-domain') || '') + '/api/track?' + $.param({
            track_name: trackNamesQueue,
            blog : Hatena.Diary.data('blogs-uri-base') || ('http://' + Hatena.Diary.data('blog'))
        });
        trackNamesQueue = [];
    };

    return function(trackNames) {
        if (!timer) {
            timer = setTimeout(postTrackNames, 1000);
        }
        _.each($.makeArray(trackNames), function(name) {
            trackNamesQueue.push(name);
        });
    };
})();

// トラッキングは，data-track-selectorにCSSセレクタを書くことによって特定の要素のみでフィルタできる．
// 1つの要素内に複数のaタグがあるが，クリックされた件数の関係で，複数data-track-nameを設定できない場合に有用．
// returns: セレクタがないか，または，セレクタがあるときマッチしたか
Hatena.Diary.trackEvent.checkSelector = function($container, $clicked) {
    var selector = $container.attr('data-track-selector');
    if (!selector) return true;

    // クリックされたとき反応する要素たち
    var $candicates = $container.find(selector);

    // クリックされた要素が，反応して良い要素たち自身か，反応して良い要素たちに含まれる？
    return !!($candicates.is($clicked) || $candicates.find($clicked).get(0));
};

// 指定した要素のdata-track-nameを配列で返す
Hatena.Diary.trackEvent.getDataTrackNames = function($element) {
    var dataTrackAttr = $element.attr('data-track-name');
    var trackNames = dataTrackAttr.split(/\s+/);
    return trackNames;
};

// 今すぐトラック
// イベント名か、イベント名のArrayを渡す
// returns: dfd.promiseオブジェクト。画像の読み込みが成功したらresolve、失敗したらrejectする。
Hatena.Diary.trackEventNow = function(trackNames) {
    var dfd = $.Deferred();

    var img = new Image();
    img.onload  = function () {
        dfd.resolve();
    };
    img.onerror = function () {
        dfd.reject();
    };

    img.src = (Hatena.Diary.data('admin-domain') || '') + '/api/track?' + $.param({
        track_name: $.makeArray(trackNames),
        blog : Hatena.Diary.data('blogs-uri-base') || ('http://' + Hatena.Diary.data('blog'))
    });

    // ずっと読み込みが終わらなかったら、rejectする
    setTimeout(function () {
        dfd.reject();
    }, 5000);

    return dfd.promise();
};

Hatena.Diary.setupTrack = function () {
    $(document).on('mousedown', '[data-track-name]:not([data-track-once])', function(event) {
        if (event.which !== 1) return; // 左クリックのみ
        var $element = $(this);
        if (!Hatena.Diary.trackEvent.checkSelector($element, $(event.target))) return;

        var trackNames = Hatena.Diary.trackEvent.getDataTrackNames($element);
        Hatena.Diary.trackEvent(trackNames);
    });

    $(document).on('mousedown', '[data-track-name][data-track-once]:not([data-track-once-tracked])', function(event) {
        if (event.which !== 1) return; // 左クリックのみ
        var $element = $(this);
        if (!Hatena.Diary.trackEvent.checkSelector($element, $(event.target))) return;

        var trackNames = Hatena.Diary.trackEvent.getDataTrackNames($element);
        Hatena.Diary.trackEventNow(trackNames);

        // これ以降トラッキングしない
        $element.attr('data-track-once-tracked', '');
    });
};

// jQuery Deferredを使った遅延リスト
Hatena.Diary.LazyList = function () { this.init.apply(this, arguments) };
Hatena.Diary.LazyList.prototype = {
    // generator
    //   前のLazyListを受け取る
    //   Deferred Objectを返す
    //   値をresolveするかrejectする関数
    // prevは前のLazyList 普通は渡さない 途中で分岐させる場合は渡してもよい
    init: function (generator, prev) {
        if (!$.isFunction(generator)) {
            throw("generator must be a function (" + generator + ")");
        }
        this.generator = generator;

        if (prev) {
            if (!(prev instanceof Hatena.Diary.LazyList)) {
                throw("prev must be a instance of LazyList");
            }
            this._prev = prev;
        }
    },
    // 値の読み込み，deferredを返す
    promise: function() {
        if (!this._promise) {
            var dfd = this.generator(this.prev());
            if (!$.isFunction(dfd.promise)) {
                throw("generator must return a Deferred Object (" + dfd + ")");
            }
            this._promise = dfd.promise();
        }

        return this._promise;
    },
    // 前のノードを得る
    prev: function() {
        return this._prev;
    },
    // 次のノードを得る
    next: function() {
        if (!this._next) {
            this._next = new Hatena.Diary.LazyList(this.generator, this);
        }
        return this._next;
    },
    // 最初のノードを得る
    root: function() {
        if (this._prev) {
            return this._prev.root();
        } else {
            return this;
        }
    }
};

Hatena.Diary.EditorConnector = {
    // 指定された文字列をエディタに挿入する
    // PC，touch，iOSに対応
    // 全記法向きのテキストが必要
    // Arrayの各行が各要素
    // data: { hatena: [], html: [], markdown: [] }
    insertLines: function(data) {
        this._validate(data);
        this._setup();
        this._insertLinesImplement(data);

    },

    // iOSアプリから開かれているかどうか
    // 基本的にはEditorConnectorに任せるべきだが, いろいろあってうまくいかないときのため用意
    isiOS: function() {
        return Hatena.Diary.Util.decodeParam(location.search.substr(1))['ios'];
    },

    // Androidアプリから開かれているかどうか
    isAndroid: function() {
        return Hatena.Diary.Util.decodeParam(location.search.substr(1))['android'];
    },

    // 指定されたURLをwindow.openして通信を待つ
    loadServiceOnChildWindow: function(url) {
        var self = this;
        var curationWindow = window.open();
        var messenger = Messenger.createForWindow(curationWindow, url);

        messenger.addEventListener('insertLines', function(data) {
            self.insertLines(data);
        });
    },

    _validate: function(data) {
        _.each(['html', 'hatena', 'markdown'], function(mode) {
            if (!data[mode]) throw "missing " + mode;
        });
    },

    _setup: function() {
        if (this._insertLinesImplement) return;

        // モードに合わせて実装の関数を設定
        var isPC = Hatena.Diary && Hatena.Diary.Pages.device() === 'pc' && Hatena.Diary.Editor.Support && Hatena.Diary.Editor.Support.currentEditor;

        var isTouchEditor = Hatena.Diary && Hatena.Diary.Pages.device() === 'touch';

        var isChildFrame = window.opener;

        // ?ios=1というパラメータついてるときiOS
        var isiOS = this.isiOS();
        // ?android=1というパラメーターのときAndroid
        var isAndroid = this.isAndroid();

        if (isiOS || isAndroid) {
            // 規定のURL開く
            this._insertLinesImplement = this._insertLinesOpenURL;
        } else if (isPC) {
            // PC編集画面
            this._insertLinesImplement = this._insertLinesPC;
        } else if (isTouchEditor) {
            // touch編集画面
            this._insertLinesImplement = this._insertLinesTouch;
        } else if (isChildFrame) {
            // 親フレームにpostMessageで送信
            this._insertLinesImplement = this._insertLinesMessenger;
        } else {
            throw "handling failed";
        }

    },

    _insertLinesPC: function(data) {
        var editor = Hatena.Diary.Editor.Support.currentEditor;
        var mode = editor.mode;
        var lines = data[mode];
        editor.insertLines(lines);
    },
    _insertLinesTouch: function(data) {
        var syntax = $('#edit-entry').attr('data-entry-syntax');

        // HTMLモードで，contentEditable無効のとき(Androidのデフォルトブラウザなど)，ただのtextareaなので，はてな記法を使う
        if (syntax === 'html' && ! Hatena.Diary.Pages.AdminTouch['user-blog-edit'].contentEditableEnabledAndEditorModeIsHTML()) {
            syntax = 'hatena';
        }

        var lines = (data[syntax] || data['hatena'] || data['markdown']);

        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText(lines.join("\n"));
    },
    _insertLinesMessenger: function(data) {
        var messenger = Messenger.createForParent();
        messenger.send('insertLines', data);
        window.close();
    },
    _insertLinesOpenURL: function(data) {
        var html_lines = _.map(data.html, function(line) {
            return '<p>' + line + '</p>';
        });
        location.href = 'hatenablog:/entry/body/insert?' + $.param({
            hatena:   data.hatena.join("\n"),
            html:     html_lines.join(''),
            markdown: data.markdown.join("\n\n"),
            version: 1
        });
    }
};

// フォームを監視し，ページ閉じるときにconfirm出すためのオブジェクト
// フォームなくても使える
Hatena.Diary.FormState = function() {
    var self = this;
    self.confirmEnabled = false;

    var pageLeaveEvent = window.onbeforeunload !== undefined ? 'beforeunload' : 'unload';

    $(window).on(pageLeaveEvent, function() {
        $(window).triggerHandler('close-preview-window');
        if (self.confirmEnabled) return Hatena.Locale.text('form.confirm.changed');
    });
};

Hatena.Diary.FormState.prototype = {
    // ページ閉じるときにconfirm出すモードを有効にする
    enableConfirm: function() {
        this.confirmEnabled = true;
    },
    // ページ閉じるときにconfirm出すモードを無効にする
    disableConfirm: function() {
        this.confirmEnabled = false;
    },
    // formを監視する 初期状態をセットし，送信を監視
    observeForm: function($form) {
        var self = this;
        this.$form = $form;
        this.setFormInitialState();

        $form.on('submit', function() {
            self.disableConfirm();
        });
    },
    // formのchangeイベントを監視
    observeFormChange: function() {
        var self = this;
        self.$form.on('change', function() {
            self.checkFormState();
        });
    },
    // formの状態を確認
    checkFormState: function() {
        if (this.$form.serialize() !== this.initialState) {
            this.enableConfirm();
        } else {
            this.disableConfirm();
        }
    },
    // 有効かどうかを返す
    isConfirmEnabled: function() {
        return this.confirmEnabled;
    },
    // 現在のformの値を初期状態とする
    // ここから変わったらconfirmが出る
    // ページロード時にJSで値を差し替えたときに呼ぶ
    setFormInitialState: function() {
        this.initialState = this.$form.serialize();
        this.disableConfirm();
    }
};

Hatena.Diary.setupProModal = function() {
    var openProModal = function(modalURL) {
        var iframeContainer = $('<div class="hatena-iframe-container pro-modal-container">').appendTo(document.body);
        var iframe = $('<iframe frameborder="0"></iframe>').appendTo(iframeContainer);

        var messenger = Messenger.createForFrame(iframe[0], modalURL);
        messenger.addEventListener('close', function () {
            Hatena.Diary.Window.hide(iframeContainer);
        });

        Hatena.Diary.Window.show(iframeContainer, {
            destroy : function () {
                iframe.remove();
                messenger.destroy();
            },
            fixScroll: true,
            center: true,
            showBackground: true
        });
    };

    $('.open-pro-modal').css('visibility', 'visible');
    $(document.body).on('click', '.open-pro-modal', function() {
        var $self = $(this);
        var modalURL = $self.attr('data-guide-pro-modal-ad-url');
        openProModal(modalURL);
        return false;
    });

};

Hatena.Diary.loadGlobalHeader = function () {
    var globalheader = document.getElementById('globalheader');

    // スマフォの企業ブログではglobalheader消されてることがあるので，ここで非表示でくっつける
    if (!globalheader) {
        var $globalheader = $('<iframe id="globalheader" style="display: none"></iframe>');
        $globalheader.appendTo(document.body);
        globalheader = $globalheader[0];
    }
    var color = Hatena.Diary.Util.canonicalizeColor($(globalheader).css('color')) || '000000';

    var backgroundColor = null;
    var target = globalheader;
    while (!backgroundColor && target && target != document.documentElement) {
        var css = $(target).css('backgroundColor');
        backgroundColor = Hatena.Diary.Util.canonicalizeColor(css);
        target = target.parentNode;
    }
    if (!backgroundColor) backgroundColor = 'ffffff';

    var params = {};

    var globalheaderType = $('html').data('globalheaderType');
    if (!globalheaderType) globalheaderType = 'auto';
    if (globalheaderType === 'auto') {
        params['device'] = Hatena.Diary.Devices.userAgent();
    }
    else {
        params['device'] = globalheaderType;
    }

    var circleId = Hatena.Diary.data('circle-id');
    if (circleId) {
        params['circle_id'] = circleId;
    }

    var pageCategory = 'global';
    if (/\.hatena\.ne\.jp(:\d+)?$/.test(location.host)) {
        pageCategory = 'admin';
    } else if (Hatena.Diary.data('blog')) {
        pageCategory = 'blogs';
    } else if (circleId) {
        pageCategory = 'circle';
    }

    if (
        pageCategory === 'admin' &&
        Hatena.Diary.data('pro') &&
        Hatena.Diary.data('pro') === 'false'
    ) {
        params['show_upgrade_pro'] = 'yes';
    }

    if (Hatena.Diary.data('brand')) {
        params['brand'] = Hatena.Diary.data('brand');
    }

    Hatena.Diary.Pages.createForFrame(
        globalheader,
        Hatena.Diary.data('admin-domain') + '/-/globalheader/' + encodeURIComponent(color) + '/' + encodeURIComponent(backgroundColor) + '/' + pageCategory + '?' + $.param(params) + '#' + encodeURIComponent(location.href)
    );

    Hatena.Diary.Pages.infoLoaded = $.Deferred();

    Hatena.Diary.Pages.message('init', function (info) {
        $(function() {
            Hatena.Diary.LOG(['init', info]);
            Hatena.Diary.Pages.infoLoaded.resolve(info);
        });
    });

    Hatena.Diary.SpeedTrack.record("loadGlobalHeader");
};

// スマートフォンアプリから使うエンドポイントです
Hatena.Diary.AppAPI = {
    _setup: function () {
        if (this._reloadStarImplement) return;

        // 1秒に1回までしか実行しない
        this._reloadStarImplement = _.throttle(function () {
            // スターを再読み込みする
            $body = $(document.body);
            $starContainer = $body.find('span.hatena-star-comment-container, span.hatena-star-star-container');
            if ($starContainer.length > 0) {
                $starContainer.remove();
                Hatena.Star.EntryLoader.loadNewEntries($body[0]);
            }
        }, 1000);
    },
    reloadStar: function () {
        this._setup();
        this._reloadStarImplement();
    }
};

// JS用URL生成
Hatena.Diary.URLGenerator = {
    // path指定でユーザブログのURLを返す。APIのURLを作るときなどは必ずこれを利用すること
    user_blog_url: function (path) {
        var blog_url_base = Hatena.Diary.data('blogs-uri-base');
        return blog_url_base + path;
    },
    static_url: function (path) {
        var static_base = Hatena.Diary.data('static-domain');
        return static_base + path;
    }
};


$(function() {
    if (arguments.callee.called) return; arguments.callee.called = true;

    var domain = /\.hatena\.ne\.jp(:\d+)?$/.test(location.host) ? "Admin" : "Blogs";
    var deviceSuffix = Hatena.Diary.Pages.device() === 'pc' ? '' : 'Touch';
    var namespace = domain + deviceSuffix;

    var page = Hatena.Diary.data('page');

    Hatena.Diary.SpeedTrack.setDomain(domain);
    Hatena.Diary.SpeedTrack.setPage(page);

    var func;
    try {
        Hatena.Diary.LOG('Pages["' + namespace + '"]["*"]');
        if ((func = Hatena.Diary.Pages[namespace]["*"])) {
            func();
        }
        Hatena.Diary.LOG('Pages["' + namespace + '"]["*"] done');

        Hatena.Diary.SpeedTrack.record('Pages["' + namespace + '"]["*"]');

        Hatena.Diary.LOG('Pages["' + namespace + '"]["' + page + '"]');
        if ((func = Hatena.Diary.Pages[namespace][page])) {
            func();
        }
        Hatena.Diary.LOG('Pages["' + namespace + '"]["' + page + '"] done');

        Hatena.Diary.SpeedTrack.record('Pages["' + namespace + '"]["' + page + '"]');
    } catch (e) {
        Hatena.Diary.BUG(e, 'toplevel');
    }

    Hatena.Diary.setupTrack();

    Hatena.Diary.Util.setupTipsy();

    Hatena.Diary.Util.setupScrollAdjustForFixedGlobalHeader();

    if (window != window.parent) {
        // クリックジャッキング対策
        //   iframe で読みこまれて・そのままクリックして送信されてしまうのが問題なので
        //   iframe の中で読みこまれたときは、submit 時に値の変更チェックをして、変更されてないなら submit できないようにする
        $('form').each(function () {
            var $this    = $(this);

            // リスクを承知で、あるいは別の手段によってクリックジャッキング対策が施されており、
            // なおかつ、クリックジャッキング対策の実装が衝突する場合に迂回することができる
            if ($this.attr('data-pass-through-click-jacking-validation')) return;

            var $buttons = $this.find('input[type=submit][name!=delete][name!=draft]');
            var $delete_button = $this.find('input[type=submit][name=delete], input[type=submit][name=draft]');
            var disable = function() {
                $this.addClass('unedited');
                $buttons.attr('disabled', 'disabled');
            };
            var enable = function() {
                $this.removeClass('unedited');
                $buttons.removeAttr('disabled');
            };
            var serialize = function($form) {
                return $({
                    elements: $form.find(':input:not([data-ignore-click-jacking])')
                }).serialize();
            };

            disable();
            $delete_button.attr('disabled', 'disabled');
            var init = serialize($this);
            var timer = setInterval(function () {
                $delete_button.removeAttr('disabled');
                if (init != serialize($this)) {
                    clearInterval(timer);
                    enable();
                }
            }, 1500);
        });
    }

    if (page != 'globalheader') $('a.feedback').on('click', function () {
        Hatena.Diary.Feedback.toggle(Hatena.Diary.data('feedback'));
        return false;
    });
});

// locationのviaをリンクに引き継ぐ
Hatena.Diary.inheritVia = function(via) {
    if (!via) return;

    $('a[data-inherit-via]').each(function () {
        var $self = $(this);
        var href  = $self.attr('href').split(/\?/);
        var query = href[1] || '';

        var params = Hatena.Diary.Util.decodeParam(query);
        params['via'] = via;

        $self.attr('href', href[0] + '?' + $.param(params));
    });
};

})(jQuery);

(function($) {

    Hatena.Diary.Circle = {
        updateMembershipCategory: function($select) {
            var circleId = $select.attr('data-circle-id');
            var blogId = $select.attr('data-blog-id');
            var selection = $select.find('option:selected').val();

            var $indSuccess = $select;

            var operation, categoryId;
            if (selection === 'delete') {
                operation = 'delete';
            }
            else {
                operation = 'update';
                categoryId = selection;
            }

            return $.ajax({
                url  : '/api/circle/membership/category',
                type : 'POST',
                data : {
                    rkm         : Hatena.Diary.data('rkm'),
                    rkc         : Hatena.Diary.data('rkc'),
                    operation   : operation,
                    circle_id   : circleId,
                    blog_id     : blogId,
                    category_id : categoryId
                }
            });
        }
    };

})(jQuery);

(function($){

Hatena.Diary.Backup = {

    // data: {
    //   modified: epoch,
    //   data: serializeされたデータ,
    //   id: formのid
    // }

    UI: 'default', // or 'touch'
    setup: function () {
        var self = this;

        // サーバーでbackupするのは廃止になったので
        // ローカルストレージに対応していないブラウザの場合は即returnする
        if (!self.localStorageEnabled()) return;

        var target = $('form[data-backup-id]');

        self.clearPreviousBackup();

        target.each(function () {
            var $form = $(this);

            self.load($form).done(function(res) {
                self.loadDone($form, res);
            });

            setInterval(function () {
                var data = self.save($form);
                if (data) {
                    self.saveDone($form, data);
                }
            }, +$form.attr('data-backup-interval') * 1000 || self.defaultInterval());
        });
    },

    defaultInterval: function() {
        // localStorage使えたら頻繁に，使えなかったら通信発生するので頻度低く
        return this.localStorageEnabled() ? 3000 : 9000;
    },

    localStorageEnabled: function() {
        // localStorageが使えて，かつ，デザイン設定画面でないとき有効
        // デザイン設定のプレビューはバックアップを通してやってるため
        var enabled = false;
        try {
            enabled = window.localStorage && Hatena.Diary.data('page') !== 'user-blog-config-design-detail';
        } catch(ignore_error) { }
        return enabled;
    },

    localStorageKey: 'backup',

    clearBackup: function () {
        localStorage.removeItem(this.localStorageKey);
    },

    clearPreviousBackup: function() {
        // 以前のバックアップを消すようにというあれがあればlocalStorageのバックアップをリセット
        // このcookieは記事投稿成功時にセットされ，クリアしたらクライアント側で消す

        if (!$.cookie('clear_backup')) return;

        this.clearBackup();
        $.removeCookie('clear_backup', { path: '/' });
    },

    // ロードに成功したらresolveされるDeferredを返す
    load : function ($form) {
        var self = this;

        var id   = $form.attr('data-backup-id');
        $form.data('backup', self.serialize($form));

        var loaded = $.Deferred();

        _.defer(function() {
            var backup;
            try {
                backup = JSON.parse(localStorage.getItem(self.localStorageKey));
            } catch (ignore_error) { }

            if (backup && backup.id === id) {
                // バックアップがあり，formのidが一致
                loaded.resolve(backup);
            } else {
                // 失敗
                loaded.reject();
            }
        });

        return loaded.promise();
    },

    // ロード完了時のコールバック
    loadDone: function ($form, res) {
        var self = this;

        if (!res) return;

        Hatena.Diary.LOG(['backup.load', res]);
        var backupTime = new Date(+res.modified * 1000);

        // 古すぎるとき捨てる
        if (new Date() - backupTime > 1000 * 60 * 60) return;

        // touchではとりあえず手動復元
        if (self.shouldAutoRestore[Hatena.Diary.Backup.UI]($form)) {
            var prev = self.serialize($form);

            self.restoreBackup($form, res.data);
            self.promptAutoRestored($form, backupTime, function () {
                self.clearRestore($form, prev);
            });
        } else {
            self.promptRestore[Hatena.Diary.Backup.UI]($form, backupTime, function () {
                self.restoreBackup($form, res.data);
            });
        }
    },

    // 保存に成功したら保存したデータを返す
    save : function ($form, force) {
        var self = this;

        var id   = $form.attr('data-backup-id');
        var prev = $form.data('backup');
        var now  = self.serialize($form);
        if (prev == now && !force) {
            // フォームの状態が変化していないとき何もしない
            return false;
        }

        $form.trigger('backup-presave');

        $form.data('backup', now);

        var backupTime = Math.floor(new Date().getTime() / 1000);

        backup = {
            id: id,
            modified: backupTime,
            data:     now
        };
        localStorage.setItem(self.localStorageKey, JSON.stringify(backup));

        return backup;
    },

    // 保存完了時のコールバック
    saveDone : function ($form, res) {
        Hatena.Diary.LOG(['backup.save', res]);
        $form.trigger('backup-save');
    },

    serialize : function ($form) {
        var values = [];
        var inputs = $form.find('input[type="text"], textarea, input[data-with-backup], input[type="hidden"].backup, input[type="radio"].backup, input[type="checkbox"].backup-button');
        for (var i = 0, it; (it = inputs[i]); i++) {
            if (!it.name) continue;
            if (it.type == 'radio' && !it.checked) continue;
            // selectされてない場合は0を送る
            if (it.type == 'checkbox' && !it.checked) {
                values.push(encodeURIComponent(it.name) + '=0');
                continue;
            }
            values.push(encodeURIComponent(it.name) + '=' + encodeURIComponent(it.value));
        }
        $form.find('select').each( function () {
            var select  = this;
            var $select = $(select);
            if (select.getAttribute('data-without-backup') !== null) return;
            var selectItem = $select.find('option:selected');
            if ( selectItem.length === 0 ) return;
            values.push(encodeURIComponent(select.name) + '=' + encodeURIComponent($(selectItem[0]).val()));
        });
        return values.join('&');
    },

    shouldAutoRestore: {
        'default': function ($form) {
            // 新規投稿かつタイトルと本文が空のとき自動で復元
            var newEntryBackupIDRegex = new RegExp("user/blog/edit-\\d+-new");
            var isNewEntry = newEntryBackupIDRegex.test($form.attr('data-backup-id'));

            var $title = $form.find(':input[name="title"]');
            var titleIsEmpty = $title[0] && $title.val().length === 0;

            var $body = $form.find(':input[name="body"]');
            var bodyIsEmpty = $body[0] && $body.val().length === 0;

            return isNewEntry && titleIsEmpty && bodyIsEmpty;
        },
        'touch': function () {
            // touch版では自動的に復元せずに、手動で復元する
            return false;
        }
    },

    restoreBackup : function ($form, data) {
        var self = this;

        Hatena.Diary.LOG('restore backup');

        self.assignData($form, data);
    },

    clearRestore : function ($form, prev) {
        var self = this;

        Hatena.Diary.LOG('clear restore');

        self.assignData($form, prev);
    },

    assignData : function ($form, data) {
        var params = Hatena.Diary.Util.decodeParam(data);
        for (var name in params) if (params.hasOwnProperty(name)) {
            $form.find('input[name="' + name + '"], textarea[name="' + name + '"]').val(params[name]);
        }

        $form.data('backup', data);
        $form.trigger('backup-restore', data);
        $form.trigger('backup-restore-params', [ params ]);
    },

    promptRestore : {
        'default' : function ($form, backupTime, callback) {
            var $message = Hatena.Diary.Backup.initMessage($form);
            $message.prepend(
                $(Hatena.Locale.text('backup.notice', '<time data-relative data-epoch="' + backupTime.getTime() + '"></time>') +
                ' <a href="javascript:void(0)">(' + Hatena.Locale.text('backup.restore') + ')</a>')
            ).show();

            Hatena.Locale.updateTimestamps($message[0]);

            $message.find('a').click(callback);
        },


        'touch' : function ($form, backupTime, callback) {
            if (confirm(Hatena.Locale.text('backup.notice.ask_restore', backupTime))) {
                callback();
            }
        }
    },

    promptAutoRestored : function ($form, backupTime, callback) {
        var self = this;

        var $message = self.initMessage($form);

        $message.prepend(
            $(Hatena.Locale.text('backup.notice.auto_restored', '<time data-relative data-epoch="' + backupTime.getTime() + '"></time>') +
            ' <a href="javascript:void(0)">(' + Hatena.Locale.text('backup.clear_restore') + ')</a>')
        ).show();

        Hatena.Locale.updateTimestamps($message[0]);

        $message.find('a').click(callback);
    },

    initMessage : function ($form) {
        var $message = $('<div class="backup-message"></div>').hide()
            .appendTo($form.find('#editor-main .body'));

        var $editarea = $('#editor .editarea');

        $message.append($('<div class="backup-message-close"><img src="http://s.hatena.ne.jp/images/close.gif"></div>'));

        // 下部のボーダーをeditareaのボーダーに重ねるために,
        // 上部のボーダーを含み, 下部のボーダーを含まないように計算する
        var message_height = $message.outerHeight() - (parseInt($message.css('border-width'), 10) || 1);

        $message.css('top', parseInt($editarea.css('top'), 10));
        $editarea.css('top', '+=' + message_height);

        $form.data('backup-message', $message);

        var clearMessage = _.once(function () {
            $message.remove();
            $editarea.css('top', '-=' + message_height);
        });

        $form.on('backup-restore', function () {
            clearMessage();
        });

        $form.on('backup-presave', function () {
            clearMessage();
        });

        $('.backup-message-close').click(function () {
            clearMessage();
        });

        // 編集タブ以外では隠す
        $('#editor-main .ui-tabs').on('tabsactivate', function (event, ui) {
            if (ui.newPanel.attr('aria-labelledby') === 'ui-id-1') {
                $message.show();
            } else {
                $message.hide();
            }
        });

        return $message;
    }
};

})(jQuery);

(function ($) {
    if (!Hatena.Epic) Hatena.Epic = {};

    /*
    * 特定の DOM ツリーと関連付けられた関数を集めるための名前空間
    * 複数のページで使われる処理をまとめるために存在する
    * DOM ノードをラップした jQuery オブジェクトを渡すことが強く推奨される
    */
    Hatena.Epic.Component = {
        // <div id="preview" data-uri="[% uri %]?preview=1">
        //   <iframe></iframe>
        // </div>
        // 子要素の iframe で表示する URL を $preview の data-uri に設定する
        setupPreviewFrameLocation: function ($preview) {
            var locationURI = $preview.attr('data-uri');
            var iframeNode = $preview.find('iframe')[0];
            iframeNode.contentWindow.location.replace(locationURI);
        },

        setupTouchViewSuggest: function () {
            var suggest_touch_view = !Hatena.Diary.data('no-suggest-touch-view');
            var has_touch_view     = Hatena.Diary.data('has-touch-view');
            var is_touch_agent     = Hatena.Diary.Devices.userAgent() === 'touch';

            if (suggest_touch_view && has_touch_view && is_touch_agent) {
                $('#sp-suggest-link').on('click', function () {
                    Hatena.Diary.Devices.use('touch');
                    return false;
                });
                $('#sp-suggest').show();
            }
        }
    };
})(jQuery);

(function($){
    var setupStar = function() {
        if (!Hatena.Star) return;

        var entryConfig = {
            entryNodes: {
                // PC, article
                'article.entry' : {
                    uri: '.hatena-star-metadata .hatena-star-permalink',
                    title: '.hatena-star-metadata .hatena-star-permalink',
                    container: 'div.hatena-star-container'
                },
                // PC, archive
                'section.archive-entry' : {
                    uri: '.hatena-star-metadata .hatena-star-permalink',
                    title: '.hatena-star-metadata .hatena-star-permalink',
                    container: 'span.star-container'
                },
                // touch, article
                '.entry-article' : {
                    uri: '.hatena-star-metadata .hatena-star-permalink',
                    title: '.hatena-star-metadata .hatena-star-permalink',
                    container: 'div.hatena-star-container'
                },
                // touch, comment
                'li.entry-comment' : {
                    uri: 'p.comment-metadata a.permalink',
                    title: 'div.comment-content',
                    container: '.comment-metadata'
                }
            }
        };

        var commentConfig = {
            entryNodes: {
                'li.entry-comment' : {
                    uri: 'p.comment-metadata a.permalink',
                    title: 'div.comment-content::-ten-truncate',
                    container: '.comment-metadata'
                }
            }
        };

        Hatena.Star.SiteConfig = entryConfig;

        Hatena.Star.EntryLoader.intoCommentScope = function (func) {
            Hatena.Star.SiteConfig = commentConfig;
            func();
            Hatena.Star.SiteConfig = entryConfig;
        };

        Hatena.Star.User.prototype.userPage = function() {
            var uri = Hatena.Diary.data('admin-domain') + '/' + this.name + '/';
            return uri;
        };

        var img_src = Hatena.Diary.URLGenerator.static_url('/images/theme/star/hatena-star-add-button.png');
        Hatena.Star.AddButton.ImgSrc            = img_src;
        Hatena.Star.AddButton.SmartPhone.ImgSrc = img_src;
    };

    setupStar();

    Hatena.Diary.Star = {
        // スター大きくしてプロフィールアイコン重ねる
        initBigStar: function () {
            if (!Hatena.Star) return;

            // 体裁変更
            Hatena.Star.Star.prototype.generateImg = function () {
                var img, star_img, user_img, span, user_icon;

                user_icon = function (name) {
                    return "http://cdn1.www.st-hatena.com/users/" + (encodeURI(name.slice(0, 2))) + "/" + (encodeURI(name)) + "/profile.gif";
                };

                star_img = Hatena.Star.Star.getImage(this.container);
                star_img.alt = this.screen_name;
                star_img.title = '';

                if (this.color && this.color != 'yellow' && this.color != 'temp') {
                    star_img.alt = star_img.alt + ' (' + this.color  + ')';
                }

                this.img = star_img;

                if (this.screen_name) {
                    if (!Hatena.Star.Star.gotImage[this.screen_name]) {
                        Hatena.Star.Star.gotImage[this.screen_name] = {};
                    }

                    if (!Hatena.Star.Star.gotImage[this.screen_name][this.color]) {
                        span = document.createElement('span');
                        span.className = 'hatena-big-star-star-container';
                        user_img = document.createElement('img');
                        user_img.src = user_icon(this.screen_name);
                        user_img.setAttribute('tabIndex', 0);
                        user_img.className = 'hatena-star-user';
                        user_img.style.padding = '0';
                        user_img.style.border = 'none';

                        span.appendChild(user_img);
                        span.appendChild(star_img);

                        Hatena.Star.Star.gotImage[this.screen_name][this.color] = span;
                    }

                    this.img = Hatena.Star.Star.gotImage[this.screen_name][this.color].cloneNode(true);
                }
            };

            // posの値の調整
            Hatena.Star.AddButton.prototype.showColorPallet = function (e) {
                this.clearSelectedColorTimer();
                if (!this.pallet) this.pallet = new Hatena.Star.Pallet();
                var pos = Ten.Geometry.getElementPosition(this.img);
                pos.x += 2;
                pos.y += 22;
                this.pallet.showPallet(pos, this);
            };

            Hatena.Star.AddButton.SmartPhone.prototype.showColorPallet = function (e) {
                this.clearSelectedColorTimer();

                if (!this.pallet) {
                    this.pallet = new Hatena.Star.Pallet.SmartPhone();
                }

                var pos = Ten.Geometry.getElementPosition(this.img);
                pos.x = Ten.Browser.isDSi ? 5 : 15;
                pos.y += 30;
                this.pallet.showPallet(pos, this);
                this.pallet.show(Hatena.Star.UseAnimation ? { x: 0, y: 0 } : pos);
            };

            // スターボタン押されたら必要な情報をはてなブログのサーバーに送る
            Hatena.Star.AddButton.prototype.addStar = _.wrap(Hatena.Star.AddButton.prototype.addStar, function(fun, e) {
                fun.apply(this, [e]);
                Hatena.Diary.trackEvent('hatena-star-add');
            });

            Hatena.Star.AddButton.SmartPhone.prototype.addStar = _.wrap(Hatena.Star.AddButton.SmartPhone.prototype.addStar, function(fun, e) {
                fun.apply(this, [e]);
                Hatena.Diary.trackEvent('hatena-star-add-smartphone');
            });
        },

        // スター付けたことない場合、ツールチップを表示する
        initStarNavigation: function() {

            if (!Hatena.Star) return;

            var TIPSY_ALLOW_OFFSET = 8;
            var $tipsy_arrow = $('<div>').addClass('tipsy-arrow blue'),
                $star_navigation_tooltip = $('<div>').addClass('star-navigation-tooltip tipsy-n')
                .append($('<p>').text(Hatena.Locale.text('star-navigation-message')))
                .prepend($tipsy_arrow);

            $.getJSON("https://www.hatena.ne.jp/notify/notices.count.json?services=1&callback=?", function (res) {

                // スター利用中ならなにもしない
                if (res.services.s) return;

                // はてなスター利用中ではないけどスターつけた
                Hatena.Star.AddButton.prototype.addStar = _.wrap(Hatena.Star.AddButton.prototype.addStar, function(fun, e) {
                    fun.apply(this, [e]);
                    Hatena.Diary.trackEvent('hatena-star-add-first');
                });

                // 既読かどうかを localStorage に保存する
                var localStorageKey = 'Hatena.Diary.Blogs.StarNavigation.Read';

                var isRead = function () {
                    try {
                        return localStorage[localStorageKey] === 'already';
                    } catch(ignore) {}
                };

                var setIsRead = function (isRead) {
                    try {
                        localStorage[localStorageKey] = isRead ? 'already' : 'not yet';
                    } catch(ignore) {}
                };

                // 既読のとき tipsy 出す必要ない
                if (isRead()) return;

                var wait_for_star_load = function (func) {
                    setTimeout(function () {
                        var $star_button = $('.hatena-star-add-button');

                        if ($star_button.length !== 0) {
                            func();
                            return;
                        }

                        wait_for_star_load(func);
                    }, 200);
                };

                wait_for_star_load(function () {
                    $('.hatena-star-container').after($star_navigation_tooltip);

                    $('.tipsy-arrow.blue').each(function () {
                        $(this).css({ left: $(this).parent().siblings().find('.hatena-star-add-button').offset().left - $star_navigation_tooltip.offset().left + TIPSY_ALLOW_OFFSET });
                    });

                    $('.star-navigation-tooltip').click(function () {
                        setIsRead(true);
                        $(this).fadeOut(1000);
                    });

                    $('.hatena-star-add-button').click(function () {
                        setIsRead(true);
                        $('.star-navigation-tooltip').fadeOut(1000);
                    });
                });
            });
        },

        initDeleteStar: function () {
            if (!Hatena.Star) return;

            Hatena.Star.Star.prototype.setImgObservers = function () {
                var self = this;
                new Ten.Observer(self.img,'onmouseover',self,'showName');
                new Ten.Observer(self.img,'onmouseout',self,'hideName');
            };

            Hatena.Star.Star.prototype.asElement = _.wrap(Hatena.Star.Star.prototype.asElement, function(func) {
                var self = this;
                var element = func.call(self);

                if ( !Hatena.Star.Config.isStarDeletable ) return element;

                // 以下はスターがdocumentにappendされてから実行

                // スター削除できるとき成功するDeferredを返す
                var checkCanDelete = _.once(function() {
                    var dfd = $.Deferred();

                    var uri = Hatena.Star.BaseURL.replace(/^http:/, Hatena.Star.BaseURLProtocol) + 'star.deletable.json';
                    var data = {
                        name: self.name,
                        uri: self.entry.uri
                    };
                    if (self.color) data.color = self.color;
                    if (self.quote) data.quote = self.quote;

                    $.ajax({
                        type: 'get',
                        dataType: 'jsonp',
                        url: uri,
                        data: data
                    }).done(function(res) {
                        var can_delete = res.result && (res.message || res.confirm_html);
                        if (can_delete) {
                            dfd.resolve(res);
                        } else {
                            dfd.reject(res);
                        }
                    });

                    return dfd;
                });

                var $star_container = $(self.anchor);

                $star_container.hover(
                    function () {
                        // 削除可能なとき，右上に削除ボタンを表示
                        checkCanDelete().done(function(deletion_info) {
                            var $delete_button =  $("<img>").addClass('star-delete-button').attr(
                                "src", Hatena.Diary.URLGenerator.static_url('/images/theme/star/star-delete.png')
                            );
                            $star_container.append($delete_button);
                            var button_position = $delete_button.position();
                            $delete_button.css({
                                left: button_position.left - 9,
                                top : button_position.top
                            });

                            //クリックされたら削除確認
                            $delete_button.click(function () {
                                if (deletion_info.confirm_html) {
                                    var pos = Ten.Geometry.getElementPosition(self.anchor);
                                    var scr = new Hatena.Star.DeleteConfirmScreen();
                                    scr.showConfirm(deletion_info.confirm_html, self, pos);
                                } else if (confirm(deletion_info.message)) {
                                    self.deleteStar();
                                }

                                return false;
                            });
                        });
                    },
                    function () {
                        $(this).find(".star-delete-button").remove();
                    });

                return element;
            });
        },

        initSelectStar: function () {
            if (!Hatena.Star) return;

            var SELECT_STAR_OPACITY = 0.6, SELECT_STAR_OFFSET = 60, SELECT_STAR_SIZE = 32, GET_BIGGER_SIZE = 24.0;

            var $target_article;
            var $select_star = $('.select_star_button_container');
            var $message_box = $('#select-star-message-box');
            var using_select_star = false;
            var message_fadeout_timer;

            // スターボタンをクリックしたとき
            Hatena.Star.AddButton.prototype.addStar = _.wrap(Hatena.Star.AddButton.prototype.addStar, function (func, e) {
                this.copySelectedText();

                func.call(this, e);

                if (this.selectedText !== '') {
                    Hatena.Diary.trackEvent('hatena-star-add-quote');
                }
            });

            // スター投稿の結果が返ってきたとき
            Hatena.Star.AddButton.prototype.receiveResult = _.wrap(Hatena.Star.AddButton.prototype.receiveResult, function (func, args) {
                // メッセージを出す位置
                var message_box_offset = {
                    top: $select_star.offset().top,
                    left: $select_star.offset().left + SELECT_STAR_SIZE
                };

                if (using_select_star) {
                    // ログインしてるときのみメッセージを出す
                    if (args.is_guest) {
                        var pos = { x: message_box_offset.left, y: message_box_offset.top };

                        // HatenaStar.js本体でウィンドウ出す位置を調整されるので, その分足し引きして調整を打ち消す
                        pos.x += 10;
                        pos.y -= 25;

                        this.lastPosition = pos;
                    } else {
                        $message_box
                            .stop()
                            .css(_.extend(message_box_offset, { opacity: 1.0 }))
                            .show();

                        if (message_fadeout_timer) {
                            clearTimeout(message_fadeout_timer);
                        }
                        message_fadeout_timer = setTimeout(function () { $message_box.fadeOut(1000); }, 1000);

                        Hatena.Diary.trackEvent('hatena-star-add-select');
                    }
                }

                using_select_star = false;

                func.call(this, args);
            });

            // テキストを選択したとき
            $(document).mouseup(function (e) {
                var $target = $(e.target);

                // deferしないとタイミング的にうまく選択領域を取得できない
                _.defer(function () {
                    var selected_text = Ten.DOM.getSelectedText();
                    var selection_is_blank = (selected_text === '');
                    var is_article = $target.closest('article').length > 0;
                    var is_comment = $target.closest('.comment').length > 0;
                    var is_select_star = $target.closest('.select_star_button_container').length > 0;

                    if (is_select_star) {
                        return;
                    }

                    if (!is_article || is_comment || selection_is_blank) {
                        $select_star.hide();
                        return;
                    }

                    $target_article = $target.closest('article');

                    $select_star.css({ top: e.pageY, left: $target_article.offset().left - SELECT_STAR_OFFSET });
                    $select_star.show();
                });
            });

            $select_star.on('mouseenter', function () {
                $(this).css({ opacity: 1.0 });
            });

            $select_star.on('mouseleave', function () {
                $(this).css({ opacity: SELECT_STAR_OPACITY });
            });

            $('.select_star_button').on('click', function (e) {
                using_select_star = true;

                $(this)
                    .stop()
                    .animate({
                        width: SELECT_STAR_SIZE + GET_BIGGER_SIZE, height: SELECT_STAR_SIZE + GET_BIGGER_SIZE,
                        top: -GET_BIGGER_SIZE/2, left: -GET_BIGGER_SIZE/2
                    }, 80)
                    .animate({width: SELECT_STAR_SIZE, height: SELECT_STAR_SIZE, top: 0, left: 0 }, 400);
            });

            // HatenaStarから引用スターボタンにクリックハンドラをたてる
            Hatena.Star.AddButton.prototype.setupObservers = _.wrap(Hatena.Star.AddButton.prototype.setupObservers, function (func) {
                func.call(this);

                new Ten.Observer($select_star[0], 'onclick', this, 'beforeAddStar');
            });

            Hatena.Star.AddButton.prototype.beforeAddStar = function (e) {
                if ($target_article.attr('data-uuid') === $(this.entry.entryNode).attr('data-uuid')) {
                    this.addStar(e);
                }
            };
        },

        // サードパーティクッキー送信されてないときmobile用のエントリページを新しいウィンドウで開く
        initStarForThirdPartyCookiesDisabled: function (info) {
            Hatena.Diary.Util.waitForResource(function() {
                return Hatena.Star;
            }, function() {
                _.extend(Hatena.Star.AddButton.prototype, {
                    addStar: function() {
                        var self = this;

                        // uri:      エントリのURI
                        // location: スターつけたあとのリダイレクト先
                        var url = 'http://s.hatena.ne.jp/star.add?' + $.param({
                            uri:      self.entry.uri,
                            location: Hatena.Diary.data('admin-domain') + '/-/close'
                        });

                        var position = {
                            width:  500,
                            height: 200
                        };
                        position.left = Math.floor((screen.width - position.width) / 2);
                        position.top = Math.floor((screen.height - position.height) / 2);

                        var position_string = Hatena.Diary.Util.positionToPositionString(position);

                        var star_window = window.open(url, 'add_star', position_string);

                        // window閉じられたら読み込みなおす
                        Hatena.Diary.Util.waitForResource(function() {
                            return star_window.closed;
                        }, function() {
                            Hatena.Diary.Util.updateDynamicPieces([self.entry.entryNode.parentNode]);
                        });
                    },
                    // カラースターつけられないのでパレット開かなくする
                    showColorPallet: function() {
                    },
                    showColorPalletDelay: function() {
                    }
                });
            });
        }
    };
})(jQuery);

(function($){

Hatena.Diary.Subscribe = {

    // 購読者数バルーン
    showSubscribe: function ($countbox, subscribes) {
        if (subscribes >= 1) {
            $countbox.show();
            $countbox.find('.subscription-count').text(Hatena.Locale.textN('epic.subscriber_count', subscribes, subscribes));
        }
    },

    getSubscribeButtons: function () {
        return $('.btn-subscribe a.hatena-follow-button');
    },

    toggleSubscribeState: function (option) {
        var $button = Hatena.Diary.Subscribe.getSubscribeButtons();

        if ($button.hasClass('subscribing')) {
            $button.removeClass('subscribing');
            $button.addClass('unsubscribing');
        } else {
            $button.removeClass('unsubscribing');
            $button.addClass('subscribing');
        }

        // グローバルヘッダのほうも変更する
        if(option && option.updateGlobalHeader){
            // 'subscribed' or 'unsubscribed'
            var action = $button.hasClass('unsubscribing') ? 'unsubscribed' : 'subscribed';
            Hatena.Diary.Pages.send('subscribe', { action: action });
        }
    },

    subscribeButtonHandlerIframe: function (uri, offset, option) {
        var container = $('<div class="hatena-iframe-container popup"></div>');
        var loading   = $(
            '<div class="loading">' +
                '<img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt="loading"/>' +
                Hatena.Locale.text('loading') +
                '</div>'
        );
        var iframe    = $('<iframe frameborder="0"></iframe>');

        if (option && option.className) {
            container.addClass(option.className);
        }

        var maxWidth = $(window).width();
        var winWidth = 300;
        var padding  = 20;
        if ((maxWidth - offset.left) < (winWidth + padding)) {
            offset.left = maxWidth - (winWidth + padding);
        }

        container.
            hide().
            appendTo(document.body).
            css({
                width:  winWidth,
                height: 155,
                position: 'absolute'
            }).offset(offset);
        loading.appendTo(container).hide();
        iframe.appendTo(container);
        iframe.load(function () { loading.remove() });
        setTimeout(function () { loading.show() }, 250);

        var messenger = Messenger.createForFrame(iframe[0], uri);

        messenger.addEventListener('resize', function (data) {
            if (data) {
                container.css(data);
            }
        });

        messenger.addEventListener('close', function () {
            Hatena.Diary.Window.hide(container);
        });

        messenger.addEventListener('done', function () {
            if (option && option.updateGlobalHeader) {
                Hatena.Diary.Subscribe.toggleSubscribeState({ updateGlobalHeader: true});
            } else {
                Hatena.Diary.Subscribe.toggleSubscribeState();
            }
        });
        Hatena.Diary.Window.show(container, {
            destroy : function () {
                iframe.remove();
                messenger.destroy();
            }
        });
    },

    subscribeButtonHandlerWindow: function (uri, option) {
        var position = {
            width:  300,
            height: 150
        };
        position.left = Math.floor((screen.width - position.width) / 2);
        position.top = Math.floor((screen.height - position.height) / 2);

        var position_string = Hatena.Diary.Util.positionToPositionString(position);

        var subscribe_window = window.open('', 'subscribe', position_string);

        var messenger = Messenger.createForWindow(subscribe_window, uri);

        var close = function() {
            messenger.destroy();
            subscribe_window.close();
        };

        messenger.addEventListener('close', close);

        messenger.addEventListener('done', function() {
            var updateGlobalHeader = option && option.updateGlobalHeader ? true : false;
            if (option && option.updateGlobalHeader) {
                Hatena.Diary.Subscribe.toggleSubscribeState({ updateGlobalHeader: true});
            } else {
                Hatena.Diary.Subscribe.toggleSubscribeState();
            }
            close();
        });

        $(document.body).one('focus', close);
    },

    openSubscribeWindow: function (offset) {
        var uri = '' +
            Hatena.Diary.data('admin-domain') + '/' +
            Hatena.Diary.data('author')       + '/' +
            Hatena.Diary.data('blog')         + '/subscribe?iframe=1';

        Hatena.Diary.Browser.thirdPartyCookiesBlocked.done(function(blocked) {
            if (blocked) {
                Hatena.Diary.Subscribe.subscribeButtonHandlerWindow(uri, { updateGlobalHeader: true });
            } else {
                Hatena.Diary.Subscribe.subscribeButtonHandlerIframe(uri, offset, { updateGlobalHeader: true });
            }
        });
    }
};

})(jQuery);

(function($){

Hatena.Diary.EntryModuleCarousel = function($container) {
    this.init($container);
};

Hatena.Diary.EntryModuleCarousel.prototype = {
    init: function($container) {
        var self = this;
        self.moveInProgress = false;
        self.$containerElem = $container;
        self.$goBackElem = $($.parseHTML('<a class="module-entries-carousel-button back"><span>Back</span<</a>'));
        self.$goForwardElem = $($.parseHTML('<a class="module-entries-carousel-button forward"><span>Forward</span></a>'));

        self.$containerElem.on('click', '.module-entries-carousel-button.back.active',    function() { self.goBack(); });
        self.$containerElem.on('click', '.module-entries-carousel-button.forward.active', function() { self.goForward(); });
        self.currentPosition = 0;

        var $carouselBodyElem = self.getCarouselBodyElem();
        self.carouselList = $carouselBodyElem.find('.urllist-item');
        self.carouselElementsSize = self.carouselList.length;
        self.carouselSize = self.carouselElementsSize - 1;

        self.$directNavigationListElem = $($.parseHTML('<ol class="module-entries-carousel-navigation">'));
        var counter = 0;
        while ( counter < self.carouselSize) {
            self.$directNavigationListElem.append($($.parseHTML('<li><a data-carousel-index="' + counter + '"><span>' + counter + '</span></a></li>')));
            counter++;
        }
        self.$containerElem.on('click', '.module-entries-carousel-navigation a.active', function(event) {
            self.goToIndex($(this).attr('data-carousel-index'));
        });

        self.updateNavigationElementsClass();

        self.$containerElem.append(self.$goBackElem);
        self.$containerElem.append(self.$goForwardElem);
        self.$containerElem.append(self.$directNavigationListElem);
    },
    canGoBack: function() {
        var self = this;
        if (self.currentPosition > 0 ) { return true; }
        return false;
    },
    // 要素が6個の時はCarouselは5項目しかない
    canGoForward: function() {
        var self = this;
        if (self.currentPosition < self.carouselSize - 1 ) { return true; }
        return false;
    },
    updateNavigationElementsClass: function() {
        var self = this;
        self.$goBackElem.toggleClass('active', self.canGoBack() );
        self.$goForwardElem.toggleClass('active', self.canGoForward() );

        self.$directNavigationListElem.find('a').removeClass('current');
        self.$directNavigationListElem.find('a[data-carousel-index="'+ self.currentPosition +'"]').addClass('current');

        self.$directNavigationListElem.find('a').addClass('active');
        self.$directNavigationListElem.find('a.current').removeClass('active');
    },
    // marginが設定されてる可能性があるので.width()とかではなく、隣の要素とのoffset違いを見る
    getUnitWidth: function() {
        var self = this;
        var $bodyElem = self.getCarouselBodyElem();
        var $unitElem = $bodyElem.find('.urllist-item');
        if ( $unitElem.length === 0 ) { Hatena.Diary.BUG("Can't get unit width"); return 200; }
        else if ( $unitElem.length === 1 ) { return $unitElem.width(); }
        return $($unitElem[1]).offset().left - $($unitElem[0]).offset().left;
    },
    getCarouselBodyElem: function() {
        var self = this;
        return $(self.$containerElem).find('.urllist-with-thumbnails');
    },
    goToIndex: function(index) {
        var self = this;
        if ( index < 0 || index >= self.carouselSize ) { return; }
        if ( self.moveInProgress ) { return; }
        self.moveInProgress = true;

        var $bodyElem = self.getCarouselBodyElem();
        var originalOffset = $bodyElem.offset();

        var moveSize = self.getUnitWidth() * (index - self.currentPosition);
        var relativeOffset = '-='+moveSize+'px';
        $bodyElem.animate( {
            left: relativeOffset
        }, 300, function() {
            self.currentPosition = index;
            self.updateNavigationElementsClass();
            self.moveInProgress = false;
        });
    },
    goBack: function() { this.goToIndex( this.currentPosition - 1 ) },
    goForward: function() { this.goToIndex( this.currentPosition + 1 ) }
};

})(jQuery);

(function($){

    Hatena.Diary.Editor = {
        id : 'hatena-diary-edit-in-place',

        showEditInPlace : function (entry, opts) {
            var editinplace = document.getElementById(Hatena.Diary.Editor.id);
            if (editinplace) {
                editinplace.parentNode.removeChild(editinplace);
            }

            var $container = $(
                '<div class="hatena-iframe-container">' +
                    '<div class="loading"><img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt=""/>' + Hatena.Locale.text('loading') + '</div>' +
                    '</div>').
                attr({
                    id: Hatena.Diary.Editor.id
                }).
                hide().
                appendTo(document.body);

            var iframe = $('<iframe frameborder="0"></iframe>').appendTo($container);

            var loading = $container.find('.loading').hide().click(function () {
                return false;
            });

            setTimeout(function () {
                loading.show();
            }, 250);

            var CONTAINER_MARGIN_LEFT = 10;
            var CONTAINER_MARGIN_TOP  = 37;

            var resizeContainer = function() {
                $container.
                    css({
                        width : $(window).width() - (CONTAINER_MARGIN_LEFT * 2),
                        height: $(window).height() - (CONTAINER_MARGIN_TOP * 2)
                    }).
                    css({
                        left: ($(window).width() - $container.width()) / 2
                    });
            };

            resizeContainer();
            $(window).resize(_.throttle(function() {
                resizeContainer();
            }, 100));

            editinplace = iframe[0];

            var uri = Hatena.Diary.data('admin-domain') +
                '/' + Hatena.Diary.data('author') + '/' + Hatena.Diary.data('blog') + '/edit?' +
                'editinplace=1';

            if (entry) uri += '&entry=' + encodeURIComponent(entry.attr('data-uuid'));
            if (opts.title) uri += '&title=' + encodeURIComponent(opts.title);
            if (opts.body)  uri += '&body='  + encodeURIComponent(opts.body);

            var updated;
            var messenger = Messenger.createForFrame(editinplace, uri);

            var closeContainerWindow = function () {
                Hatena.Diary.Window.hide($container);
            };

            var onClose = function () {
                if (updated && !confirm(Hatena.Locale.text('form.confirm.changed'))) {
                    return false; // 編集画面を閉じるイベントをキャンセルする
                } else {
                    closeContainerWindow();
                    messenger.send('close-preview-window'); // 新窓プレビューを閉じる
                }
            };
            messenger.addEventListener('close', onClose);

            messenger.addEventListener('ready', function () {
                loading.remove();
            });
            messenger.addEventListener('update', function (data) {
                messenger.removeEventListener('close', onClose);
                messenger.addEventListener('close', closeContainerWindow); // submitされたらconfirmを出す必要はない
                opts.update(data);
            });

            messenger.addEventListener('change', function (_updated) {
                updated = !!_updated;
            });

            Hatena.Diary.Window.show($container, {
                closeExplicitly: true,
                destroy : function () {
                    iframe.remove();
                    messenger.destroy();
                },
                fixScroll: true
            });

        }
    };

    Hatena.Diary.Pages.Admin['*'] = function () {
        Hatena.Locale.setupTimestampUpdater();
        Hatena.Diary.Backup.setup();

        Hatena.Diary.Pages.Blogs['*'].prepareForGlobalHeader();

        Hatena.Epic.Component.setupTouchViewSuggest();

        $('.js-admin-menu-myblog-btn').click(function() {
            var $blog_list = $('.js-admin-menu-myblog-list');

            if ($blog_list.size() === 0) {
                return true;
            }

            if ($blog_list.is(":visible") === false) {
                $blog_list.show();
            } else {
                $blog_list.hide();
            }
            return false;
        });

        $(document).click(function(e) {
            var $blog_list = $(".js-admin-menu-myblog-list");
            if (!$.contains($blog_list, e.target)) {
                $blog_list.hide();
            }
        });
    };

    Hatena.Diary.Pages.Admin['*'].saveBlogConfig = function(key, value) {
        $.ajax({
            url : "config/param",
            type : "post",
            cache: false,
            dataType : 'json',
            data : {
                key : key,
                val : value,
                rkm : Hatena.Diary.data('rkm'),
                rkc : Hatena.Diary.data('rkc')
            },
            success : function (res) {
                Hatena.Diary.LOG(['config/param', res]);
            }
        });
    };

    EditDesign.sections = [
        'theme',
        'background'
    ];

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-amazon'] = function () {
        new Hatena.Diary.Pages.Admin['user-blog-edit'].AmazonSearch({
            container: $('#editor-amazon-search')
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-itunes'] = function () {
        new Hatena.Diary.Pages.Admin['user-blog-edit'].Itunes({
            container: $('#editor-itunes')
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['antenna'] = function () {

        var setupEntryBox = function ($recentEntryBox) {
            var $recentEntries = $recentEntryBox.find('li[class!="more"]');
            var $moreButton = $recentEntryBox.find('li[class="more"]');
            if ($recentEntries.length <= 3) {
                $moreButton.hide();
            }
            else {
                $recentEntryBox.find('li[class!="more"]:gt(2)').hide();
            }
        };

        var $recentEntryBoxes = $('.entry-unit-older-post');
        $recentEntryBoxes.each(function () {
            setupEntryBox($(this));
        });

        $('.entry-unit').on('click', '.more', function (e) {
            var $button = $(this);
            var $recentEntries = $button.siblings('li[class!="more"]:gt(2)');
            $recentEntries.slideToggle('fast');
            $button.hide();
        });

        var $closedBlogs = $('.closed-blog');
        $closedBlogs.each(function () {
            var $closedBlog = $(this);
            var antennaUrl = $closedBlog.data("antennaUrl");
            $.ajax({
                type: 'GET',
                url: antennaUrl,
                data: { device: 'pc' },
                dataType: 'html',
                crossDomain: true,
                xhrFields: {
                    withCredentials: true
                }
            }).done(function (res) {
                $closedBlog.empty();
                $closedBlog.append(res);
                setupEntryBox($closedBlog);
                var $blogContents = $closedBlog.find('.js-blog-content');
                Hatena.Locale.updateTimestamps($blogContents[0]);
            });
        });
    };

})(jQuery);

(function($) {

    Hatena.Diary.Pages.Admin['circle'] = function() {
        $('.membership-category').each(function(i, container) {
            var $container = $(container);
            var $select = $container.find('.membership-category-select');
            var current = $select.find('option:selected').val();
            var $indicator = $container.find('.indicator');

            $select.change(function(e) {
                Hatena.Diary.Circle.updateMembershipCategory($select).done(function(data) {
                    $indicator.find('.success').show();
                    $indicator.find('.fail').hide();
                }).error(function(data) {
                    $select.val( current );
                    $indicator.find('.success').hide();
                    $indicator.find('.fail').show();
                });
            });
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['circle-create'] = function () {
        var $form   = $('form#create-circle-form');

        $form.submit(function () {
            Hatena.Diary.Util.preventDuplicateSubmit($form);
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['circle-membership-done'] = function () {
        Hatena.Diary.Pages.createForParent();

        Hatena.Diary.Pages.send('resize', {
            // iframeの高さがうまくとれず、やむなく+50している..
            // *1はOpera対策 see also Hatena.Diary.Util.sendresizerequest
            height: ($(document.body).height() + 50) * 1
        });

        Hatena.Diary.Pages.send('done');

        $('.close').on('click', function (e) {
            Hatena.Diary.Pages.send('close', { name : window.name });
            return false;
        });

        var $container = $('.options');
        var $select = $container.find('.membership-category-select');
        var current = $select.find('option:selected').val();
        var $indicator = $container.find('.indicator');

        $select.change(function(e) {
            Hatena.Diary.Circle.updateMembershipCategory($select).done(function(data) {
                $indicator.find('.success').show();
                $indicator.find('.fail').hide();
            }).error(function(data) {
                $select.val( current );
                $indicator.find('.success').hide();
                $indicator.find('.fail').show();
            });
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['circle-membership'] = function () {
        Hatena.Diary.Pages.createForParent();

        $('.close').on('click', function (e) {
            Hatena.Diary.Pages.send('close', { name : window.name });
            return false;
        });

        $('form').submit(function (e) {
            var $form = $(this);
            if (!confirm($form.attr('data-confirm-message'))) {
                return false;
            }
        });

        Hatena.Diary.Util.sendResizeRequest();
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-gourmet'] = function () {
        if ($('#editor-gourmet.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet({
                container: $('#editor-gourmet')
            });
        }
    };


})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-instagram'] = function () {
        if ($('#editor-instagram.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Instagram({
                container: $('#editor-instagram')
            });
        }
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-promotion'] = function () {
        var PromotionEntriesManager = {
            entries: null,
            index: 0,
            init: function ($container) {
                this.entries = _.map($container.find('.promotion-entry'), function(entry) {
                    return new PromotionEntry({ $element: $(entry) });
                });
                $container.on('click', '.pager .prev', $.proxy(this, 'onPrevPagerClick'));
                $container.on('click', '.pager .next', $.proxy(this, 'onNextPagerClick'));
                this.update();
            },
            update: function () {
                var index = this.index;
                _.each(this.entries, function (entry, i) {
                    if (i === index) {
                        entry.show();
                    }
                    else {
                        entry.hide();
                    }
                });
            },
            onPrevPagerClick: function () {
                this.index--;
                this.update();
            },
            onNextPagerClick: function () {
                this.index++;
                this.update();
            }
        };

        var PromotionEntry = function () { this.init.apply(this, arguments); };
        PromotionEntry.prototype = {
            init: function (args) {
                var self = this;
                self.$element = args.$element;
                self.bindEvents();
            },
            bindEvents: function () {
                var self = this;
                self.$element.on('click', '[data-keyword]', function (button) {
                    var $entry = $(this);

                    // trackEventが終わるのを確認して、エディタへのinsertLinesをする
                    Hatena.Diary.trackEventNow('Promotion.Entry.Insert.' + self.entryID()).always(function () {
                        var keyword = $entry.attr('data-keyword');
                        var lines = [ keyword ];
                        Hatena.Diary.EditorConnector.insertLines({
                            html:     lines,
                            hatena:   lines,
                            markdown: lines
                        });
                    });
                });
            },
            show: function () {
                var self = this;
                self.$element.show();
                Hatena.Diary.trackEvent('Promotion.Entry.Show.' + self.entryID());
            },
            hide: function () {
                var self = this;
                self.$element.hide();
            },
            entryID: function () {
                var self = this;
                return self.$element.attr('data-promotion-entry-id');
            }
        };

        PromotionEntriesManager.init($('.promotion-entries'));
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-twitter'] = function () {
        if ($('#editor-twitter.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Twitter({
                container: $('#editor-twitter')
            });
        }
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['curation-flickr'] = function () {
        if ($('#editor-flickr.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr({
                container: $('#editor-flickr')
            });
        }
    };


})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['feedback-iframe'] = function () {
        Hatena.Diary.Pages.createForParent();

        $('.close').on('click', function (e) {
            Hatena.Diary.Pages.send('close', { name : window.name });
            return false;
        });

        $('#button-feedback').on('click', function (e) {
            $('.js-show-on-send-feedback').show();
            $('#body').focus();
            $('.js-hide-on-send-feedback').hide();
            Hatena.Diary.Util.sendResizeRequest();
        });

        if(!!Hatena.Diary.Location.param('thankyou')){
            setTimeout(function () {
                $('#button-close').click();
            }, 3000);
        }

    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['globalheader'] = function () {
        Hatena.Diary.Pages.createForParent();

        var BASE     = location.hostname.match(/\.hatena\.[^:]+/)[0];

        var header         = $(document.getElementById('header'));
        var headerServices = $(document.getElementById('header-services'));
        var headerNotify   = $(document.getElementById('header-notify'));
        var headerLocale   = $(document.getElementById('header-locale'));

        var blogUri = decodeURIComponent(location.hash.substring(1));
        var loc = Hatena.Diary.data('admin-domain') + '/go?blog=' + encodeURIComponent(blogUri);

        var publicUserInfo = $.ajax({
            type: 'get',
            dataType: 'jsonp',
            url: "https://www" + BASE + "/notify/notices.count.json",
            data: {
                services: 1
            }
        });

        if (!Hatena.Diary.Browser.isIE) {
            // IE以外のときはcanvasでドロップダウン画像を合成したりする
            var dropdownColor = document.body.getAttribute('data-color');
            Hatena.Diary.Pages.Admin['globalheader'].renderDropdown(dropdownColor);
        }

        header.delegate('.header-dropdown', {
            keypress: function (event) {
                if (event.which !== 13) return;
                $(event.currentTarget).click();
                event.preventDefault();
                event.stopPropagation();
            },
            mouseup: function (event) {
                event.currentTarget.blur();
            }
        });

        header.find('a.new-entry').click(function () {
            Hatena.Diary.Pages.send('new-entry', {});
            return false;
        });

        header.find('a.feedback').click(function () {
            Hatena.Diary.Pages.send('feedback', {
                left : $(this).offset().left,
                uri : Hatena.Diary.data('feedback')
            });
            return false;
        });

        header.find('.units').find('a').click(function () {
            Hatena.Diary.Pages.send('units', {
                left: $(this).offset().left,
                uri: '/-/units'
            });
            return false;
        });

        headerLocale.find('.header-dropdown').click(function () {
            var self = this;
            Hatena.Diary.Pages.send('locale', { });
            return false;
        });

        headerServices.find('.header-dropdown').click(function () {
            var self = this;
            publicUserInfo.done(function (info) {
                Hatena.Diary.Pages.send('servicesmenu', {
                    BASE : BASE,
                    right : $(self).offset().left + $(self).width(),
                    info : info,
                    location : loc
                });
            });
            return false;
        });

        headerNotify.find('.header-dropdown').click(function () {
            Hatena.Diary.Pages.send('notify', {
                BASE : BASE,
                left : $(this).offset().left
            });
            headerNotify.find(".notify-count").text('').hide();
            return false;
        });

        $('.locale .header-dropdown').click(function () {
            Hatena.Diary.Pages.send('locale', {
                height: +$(this).attr('data-height-hint'),
                right : $(this).offset().left + $(this).width()
            });
            return false;
        });

        publicUserInfo.done(function (data) {
            if (data.count > 0) {
                headerNotify.find(".notify-count").text(data.count).show();
            } else {
                headerNotify.find(".notify-count").text('').hide();
            }
        });

        publicUserInfo.done(Hatena.Diary.Util.needComrule2013);

        var params = Hatena.Diary.Location.params();

        Hatena.Diary.Pages.loadInfo().done(function (info, privateInfo) {
            // グローバルヘッダに購読ボタン
            // 購読済なら出さない
            // 自分のブログ購読しても仕方ないので，このブログになんか書ける人にも出さない
            if (!info.subscribe && !info.can_open_editor) {
                Hatena.Diary.Pages.Admin['globalheader'].initSubscribe();
            }

            // 非公開ブログなら鍵を表示
            // ブログタイトルはそのあとにappendする
            if (!info.is_public) {
                $('.js-blog-private-badge').show();
            }

            $('#current-blog .current-blog-title').append(document.createTextNode(info.blog_name));

            Hatena.Diary.Pages.Admin['globalheader'].initBlogDropdown(BASE);
            Hatena.Diary.Pages.Admin['globalheader'].initAdminDropdown(BASE);
        });

        $('.login').attr('href', 'https://www.hatena.ne.jp/login?location=' + encodeURIComponent(loc));

        // globalheaderはキャッシュされているので、jsでviaの引き継ぎをする
        Hatena.Diary.Pages.message('inheritVia', function (via) {
            Hatena.Diary.LOG(['inheritVia', via]);
            Hatena.Diary.inheritVia(via);
        });

        Hatena.Diary.Pages.message('newEntryGeometry', function() {
            var $newEntry = $('a.new-entry');
            var offset = $newEntry.offset();
            Hatena.Diary.Pages.send('newEntryGeometry', {
                top    : offset.top,
                left   : offset.left,
                height : $newEntry.height(),
                width  : $newEntry.width()
            });
        });
    };

    Hatena.Diary.Pages.Admin['globalheader'].coloring = function (img) {
        img.onload = null; // ここまでに複数のeventがfireしてることがある?
        try {
            var width = $(img).attr('data-natural-width') || img.width,
                height = $(img).attr('data-natural-height') || img.height;
            var canvas = document.createElement('canvas');
            canvas.setAttribute('width', width);
            canvas.setAttribute('height', height);
            if (!canvas.getContext) return;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            ctx.globalCompositeOperation = 'source-in';
            ctx.fillStyle = document.body.getAttribute('data-color');
            ctx.fillRect(0, 0, width, height);
            if (!canvas.toDataURL) return;
            img.src = canvas.toDataURL();
        } catch (e) { Hatena.Diary.BUG(e, 'render logo') }
    };

    Hatena.Diary.Pages.Admin['globalheader'].renderDropdown = function (color) {
        var img = new Image();
        img.src = '/images/header/dropdown@2x.png';
        img.onload = function () { try {
            img.onload = null;
            var canvas = document.createElement('canvas');
            canvas.setAttribute('width', 24);
            canvas.setAttribute('height', 24);
            if (!canvas.getContext) return;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            ctx.globalCompositeOperation = 'source-in';
            ctx.fillStyle = color;
            ctx.fillRect(0, 0, 24, 24);
            if (!canvas.toDataURL) return;
            var data = canvas.toDataURL();

            var style = document.createElement('style');
            style.setAttribute('type', 'text/css');
            style.appendChild(document.createTextNode('#header span.header-dropdown, #header span.header-dropdown-custom { background: url(' + data + ') center right no-repeat; background-size: 12px 12px; }'));
            document.body.appendChild(style);
        } catch (e) {
            Hatena.Diary.BUG(e, 'render logo dropdown');
            img.src = '/images/header/dropdown.gif';
        } };
    };

    Hatena.Diary.Pages.Admin['globalheader'].initAdminDropdown = function (BASE) {
        var $mymenu = $('#header-my');
        $mymenu.click(function () {
            Hatena.Diary.Pages.send('mymenu', {
                BASE: BASE,
                right: $mymenu.offset().left + $mymenu.width()
            });
            return false;
        });
    };

    Hatena.Diary.Pages.Admin['globalheader'].initBlogDropdown = function (BASE) {
        $('#current-blog, #my-blogs').click(function () {
            Hatena.Diary.Pages.send('blogmenu', {
                BASE: BASE,
                left: $(this).offset().left
            });
            return false;
        });
    };

    Hatena.Diary.Pages.Admin['globalheader'].initSubscribe = function (BASE) {
        var $subscribe = $('.js-globalheader-subscribe');
        var $done = $('.js-globalheader-subscribed-message');

        $subscribe.show();

        $subscribe.click(function () {
            Hatena.Diary.Pages.send('subscribe', {
                left: $subscribe.offset().left
            });
            return false;
        });

        // 購読完了したら「購読中です」出す
        Hatena.Diary.Pages.message('subscribe', function (data) {
            if (data.action !== 'subscribed') return;
            $subscribe.hide();
            $done.show();
            setTimeout(function() {
                $done.fadeOut('slow');
            }, 3000);
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['index'] = function () {
        $('.access-graph[itemscope]').each(function () {
            var $this = $(this);
            var i = 0; var data  = $this.find('meta').map(function () {
                return [ [i++, +this.getAttribute('content')] ];
            });

            $.plot($this, [
                {
                    data : data,
                    bars: { show: true, lineWidth: 0.7 },
                    points : { show: false },
                    legend : { show: false },
                    shadowSize : 0
                }
            ], {
                xaxis : {
                    min: 0,
                    ticks: []
                },
                yaxis : {
                    min: 1,
                    autoscaleMargin: 0.1,
                    ticks: []
                },
                grid : {
                    show: false
                }
            });
        });
        $(document.body).click(function () {
            $('.config-dropdown-window').removeClass('open');
        });
        $('.dropdown-toggle').click(function () {
            var dropdown = $(this).closest('.myblog-box').find('.config-dropdown-window');
            if (dropdown.hasClass('open')) {
                dropdown.removeClass('open');
            } else {
                $('.config-dropdown-window').removeClass('open');
                dropdown.addClass('open');
            }
            return false;
        });

        // cookieもってたら非公開ブログの情報も表示するアンテナ
        var $closedBlogs = $('.closed-blog');
        $closedBlogs.each(function(){
            var $closedBlog = $(this);
            var antennaUrl = $closedBlog.data("antennaUrl");
            $.ajax({
                type: 'GET',
                url: antennaUrl,
                data: { lite: 1, device: 'pc' },
                dataType: 'html',
                crossDomain: true,
                xhrFields: {
                    withCredentials: true
                }
            }).done(function(res){
                var $res = $($.parseHTML(res));
                $closedBlog = $closedBlog.replaceWith($res);
                var $blogContents = $res.find('.js-blog-content');
                Hatena.Locale.updateTimestamps($blogContents[0]);
            });
        });

        Hatena.Diary.Pages.Admin['index'].getDashboardData();
    };

    Hatena.Diary.Pages.Admin['index'].getDashboardData = function () {
        $.ajax({
            type: 'GET',
            url: '/-/dashboard_data'
        }).done(function(data) {
            if ($('section.js-hot-entries-section').length) {
              $('section.js-hot-entries-section').append(data.hot_entries);
            }

            if ($('section.js-hot-blogs-section').length) {
              $('section.js-hot-blogs-section').append(data.hot_blogs);
            }

            if ($('section.js-recent-blogs-section').length) {
              $('section.js-recent-blogs-section').append(data.recent_blogs);
            }

            if ($('section.js-subscribing-blogs-section').length) {
              $('section.js-subscribing-blogs-section').append(data.subscribing_blogs);
            }

            Hatena.Locale.updateTimestamps();
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['invite-new'] = function () {
        Hatena.Locale.setupTimestampUpdater();
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['locale'] = function () {
        Hatena.Diary.Pages.createForParent();

        $('#locale-window a').on('click', function () {
            var $this = $(this);
            var lang = $this.attr('data-lang');
            Hatena.Locale.setAcceptLang(lang);
            Hatena.Diary.Pages.send('reload');
            return false;
        });

        Hatena.Diary.Util.sendResizeRequest();
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['menu-blogmenu'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Util.sendResizeRequest();

        Hatena.Diary.Pages.send('init');
        Hatena.Diary.Pages.message('init', function(init) {
            $('.subscribe').click(function () {
                Hatena.Diary.Pages.send('subscribe', {
                    left: init.left ? init.left : 0
                });
                return false;
            });
        });
        $('.edit-this-entry').click(function () {
            Hatena.Diary.Pages.send('edit-this-entry');
            return false;
        });
        $('.new-entry').click(function () {
            Hatena.Diary.Pages.send('new-entry');
            return false;
        });

    };

})(jQuery);

(function($){
    Hatena.Diary.Pages.Admin['menu-myblogmenu'] = function () {
        Hatena.Diary.Pages.createForParent();

        // myblogmenuは初め非表示の状態であり、
        // 非表示要素のサイズをとるとFirefox等でおかしくなる．
        // 実際に表示されるのを待ってからresizeする

        Hatena.Diary.Util.waitForResource(function() {
            return $(document.body).is(':visible');
        }, function() {
            Hatena.Diary.Util.sendResizeRequest();
        }, 100);

        $(document.body).mouseenter(function () {
            Hatena.Diary.Pages.send('mouseenter');
        });
    };
})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['menu-mymenu'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Util.sendResizeRequest();

        $('.new-entry').click(function () {
            Hatena.Diary.Pages.send('new-entry');
            return false;
        });

        var $help = $('#help');
        $help.click(function () {
            Hatena.Diary.Pages.send('feedback', {
                uri: $help.attr('data-feedback-url')
            });
            return false;
        });

        // iPadなどのタブレットデバイスのときは、
        if (Hatena.Diary.Browser.isTablet) {
            var last_submenu_blog_uri;

            $('a.myblog').on('touchstart touchmove', function () {
                return false;
            });

            $('a.myblog').on('touchend', function () {
                var blog_uri = $(this).attr('href');

                if (last_submenu_blog_uri) {
                    Hatena.Diary.Pages.send('myblogmenu.close', { blogUri: last_submenu_blog_uri });
                }

                Hatena.Diary.Pages.send('myblogmenu.open', { blogUri: blog_uri });

                last_submenu_blog_uri = blog_uri;
                return false;
            });
        } else {
            $('.dropdown-mymenu').menuAim({
                activate: function (li) {
                    var has_submenu = $(li).hasClass('dropdown-mymenu-submenu');
                    if(!has_submenu) return;

                    var blog_uri = $(li).find('a').attr('href');

                    Hatena.Diary.Pages.send('myblogmenu.open', { blogUri: blog_uri });
                },
                deactivate: function (li) {
                    var has_submenu = $(li).hasClass('dropdown-mymenu-submenu');
                    if(!has_submenu) return;

                    var blog_uri = $(li).find('a').attr('href');

                    Hatena.Diary.Pages.send('myblogmenu.close', { blogUri: blog_uri });
                },
                submenuDirection: 'left'
            });
        }

        $('a.myblog').each(function () {
            var top = $(this).position().top;
            var blog_uri = $(this).attr('href');
            Hatena.Diary.Pages.send('myblogmenu.init', { top: top, blogUri: blog_uri });
        });
    };
})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['menu-services'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Pages.message('init', function (data) {

            // data は危険な内容である可能性がある
            var BASE = data.BASE;
            var servicesInUse = data.info.services;

            var usernameWindow = $('#username-window');

            $('<dt class="label"><span>Services in Use</span></dt>').
                find('span').text(Hatena.Locale.text('services_in_use')).end().
                appendTo(usernameWindow);

            // global headerに出すリストを作る
            var subdomainsForShow = [];
            for (var s in servicesInUse) {
                if (servicesInUse[s].is_beta) continue;
                if (!servicesInUse[s].portal_top_priority) continue;
                subdomainsForShow.push(s);
            }
            subdomainsForShow.sort(function (a, b) {
                return servicesInUse[b].portal_top_priority -
                    servicesInUse[a].portal_top_priority;
            });

            for (var i = 0, length = subdomainsForShow.length; i < length; i++) {
                var subdomain = subdomainsForShow[i];
                var service = servicesInUse[subdomain];
                if (!service) continue;
                var url = 'http://www' + BASE + '/me/' + service.name + '/';
                var favicon = '//www.hatena.com/images/favicon/' + service.name + '.png';
                $('<dd><a href="" rel="noreferrer" target="_blank"><img alt="" width="16" height="16"/></a></dd>').
                    find('a').
                    find('img').attr('src', favicon).end().
                    attr('href', url).append(document.createTextNode(service.text)).
                    end().
                    appendTo(usernameWindow);
            }

            $('<dt class="label"><span>Lang</span></td>').
                find('span').text(Hatena.Locale.text('lang')).end().
                appendTo(usernameWindow);

            var langs = Hatena.Locale.getAvailLangs();
            for (var i = 0; i < langs.length; i++) {
                var lang = langs[i];
                if (langs[i] == Hatena.Locale.getTextLang()) {
                    $('<dd><span class="selected">lang</span></dd>').
                        find('span').
                        text(Hatena.Locale.text('lang.' + lang + '.native')).
                        end().
                        appendTo(usernameWindow);
                } else {
                    $('<dd><a href="#">lang</a></dd>').
                        find('a').
                        attr('data-lang', lang).
                        text(Hatena.Locale.text('lang.' + lang + '.native')).
                        end().
                        appendTo(usernameWindow);
                }
            }
            usernameWindow.find('a[data-lang]').click(function () {
                var lang = $(this).attr('data-lang');
                Hatena.Locale.setAcceptLang(lang);
                Hatena.Diary.Pages.send('reload');
                return false;
            });

            $('<dt class="label"><span>My Hatena</span></dt>').
                find('span').text(Hatena.Locale.text('my_hatena')).end().
                appendTo(usernameWindow);

            $('<dd><a href="" rel="noreferrer" target="_blank"><img src="/images/favicon/my.png" width="16" height="16" alt=""></a></dd>').
                find('a').attr('href', 'http://www' + BASE + '/my/').append(Hatena.Locale.text('profile')).end().
                appendTo(usernameWindow);

            $('<dd><a href="" rel="noreferrer" class="logout" target="_parent"><img width="16" height="16" src="/images/favicon/logout.gif"></a></dd>').
                find('a').
                attr('href', 'http://www' + BASE + '/logout?location=' + encodeURIComponent(data.location)).append(Hatena.Locale.text('logout')).
                click(function () {
                    return confirm(Hatena.Locale.text('really_want_to_logout'));
                }).
                end().
                appendTo(usernameWindow);

            Hatena.Diary.Util.sendResizeRequest();
        });

        Hatena.Diary.Pages.send('init');
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['plus-quit'] = function () {
        $('form').submit(function () {
            $(this).find('input:submit').attr('disabled', 'disabled');
        });
    };

})(jQuery);
(function ($) {
    Hatena.Diary.Pages.Admin['refusal'] = function () {
        var RefusedUser = function(name) {
            if (name.length < 2) throw "invalid name";
            this.name = name;
        };
        RefusedUser.prototype = {
            getName: function(){
               return this.name;
            },
            getProfileImage: function() {
                return 'http://cdn1.www.st-hatena.com/users/' + this.getName().substr(0, 2) + '/' + this.getName() + '/profile.gif';
            },
            getURL: function() {
                return 'http://profile.hatena.ne.jp/' + this.getName() + '/';
            },
            getHatenaID: function() {
                return 'id:' + this.getName();
            },
            equals: function(user) {
                return this.name === user.name;
            }
        };
        RefusedUser.loadUserNames = function(userNames) {
            return _.map(userNames, function(name) {
                return new RefusedUser(name);
            });
        };

        var RefusalManager = function() { this.init.apply(this, arguments); };
        RefusalManager.prototype = {
            init: function() {
                this.refusals = [];
            },
            load: function(refusals) {
                this.refusals = refusals;
                $(this).trigger('refusalsChanged');
            },
            add: function(refusal){
                var self = this;
                if (self.isRefused(refusal)) return;

                var refusals = self.refusals.concat(refusal);
                this._save(refusals).done(function() {
                    $(self).trigger('refusalAdded');
                }).fail(function() {
                    $(self).trigger('refusalSaveFailed');
                });
            },
            remove: function(refusal){
                var self = this;
                if (!self.isRefused(refusal)) return;

                var refusals = _.reject(self.refusals, function(target) { return self.isEqual(refusal, target); });
                this._save(refusals).done(function() {
                    $(self).trigger('refusalRemoved');
                }).fail(function() {
                    $(self).trigger('refusalSaveFailed');
                });
            },
            isEqual: function(refusal, other) {
                return refusal === other;
            },
            isRefused: function(refusal){
                var self = this;
                return _.find(this.refusals, function (target) { return self.isEqual(refusal, target); });
            },
            getRefusals: function() {
                return this.refusals;
            },
            _save_url: 'specify this',
            _getSaveParams: function(refusals) {
                throw new Error('implement this');
            },
            _save: function(refusals) {
                var self = this;
                var saved = $.Deferred();
                $.ajax({
                    url: self._save_url,
                    type: 'POST',
                    data: _.extend(self._getSaveParams(refusals), {
                        rkm: Hatena.Diary.data('rkm'),
                        rkc: Hatena.Diary.data('rkc')
                    }),
                    traditional: true,
                    dataType: 'json'
                }).done(function() {
                    self.refusals = refusals;
                    $(self).trigger('refusalsChanged');
                    saved.resolve();
                }).fail(function() {
                    saved.reject();
                });
                return saved;
            }
        };

        var UserRefusalManager = function () { this.init.apply(this, arguments) };
        UserRefusalManager.prototype = {
            getUserNames: function() {
                return _.map(this.refusals, function(user) { return user.getName() });
            },
            isEqual: function(user, other) {
                return user.equals(other);
            },
            _save_url: '/-/refusal/save',
            _getSaveParams: function(users) {
                return {
                    user_names: _.map(users, function(user) { return user.getName() })
                };
            }
        };
        Hatena.Diary.Util.extend(UserRefusalManager.prototype, RefusalManager.prototype);
        

        var IpRefusalManager = function () { this.init.apply(this, arguments); };
        IpRefusalManager.prototype = {
            _save_url: '/-/refusal/save_refused_ips',
            _getSaveParams: function(ips) {
                return { ips: ips };
            }
        };
        Hatena.Diary.Util.extend(IpRefusalManager.prototype, RefusalManager.prototype);
        
        RefusalManagerView = function($container) {
            this.$refusalsContainer = $container.find('.js-refusals-container');
            this.refusalsTemplate = _.template($container.find('.js-refusals-template').html());
            this.$alertAdded = $container.find('.js-alert-added');
            this.$alertRemoved = $container.find('.js-alert-removed');
            this.$alertNotFound = $container.find('.js-alert-not-found');
        };
        RefusalManagerView.prototype = {
            onChanged: function(manager){
                this.$refusalsContainer.html(this.refusalsTemplate({ refusals: manager.getRefusals() }));
            },
            onAdded: function(manager) {
                this.showAlert(this.$alertAdded);
            },
            onRemoved: function(manager) {
                this.showAlert(this.$alertRemoved);
            },
            onNotFound: function(manager) {
                this.showAlert(this.$alertNotFound);
            },
            showAlert: function($alert) {
                _.each([this.$alertAdded, this.$alertRemoved, this.$alertNotFound], function($elem) {
                    $elem.hide();
                });
                $alert.show();
                setTimeout(function() {
                    $alert.fadeOut('slow');
                }, 3000);
            }
        };

        var user_manager = new UserRefusalManager();
        var ip_manager = new IpRefusalManager();
        var user_manager_view = new RefusalManagerView($('.js-refuse-users'));
        var ip_manager_view = new RefusalManagerView($('.js-refuse-ips'));

        $(user_manager).on('refusalsChanged', function() {
            user_manager_view.onChanged(this);
        }).on('refusalAdded', function() {
            user_manager_view.onAdded(this);
        }).on('refusalRemoved', function() {
            user_manager_view.onRemoved(this);
        }).on('refusalSaveFailed', function() {
            user_manager_view.onNotFound(this);
        });

        $(ip_manager).on('refusalsChanged', function() {
            ip_manager_view.onChanged(this);
        }).on('refusalAdded', function() {
            ip_manager_view.onAdded(this);
        }).on('refusalRemoved', function() {
            ip_manager_view.onRemoved(this);
        }).on('refusalSaveFailed', function() {
            ip_manager_view.onNotFound(this);
        });

        // 読み込み
        var userNames = $('.js-refused-users-container').data('user-names');
        if (userNames.length > 0) {
            var users = RefusedUser.loadUserNames(userNames.split(','));
            user_manager.load(users);
        }

        var ips = $('.js-refused-ips-container').data('ips');
        if (ips.length > 0) {
            ip_manager.load(ips.split(','));
        }

        var isLikeIpAddress = function (target) {
            // ipv6っぽいのにも一応マッチするが、厳密ではない
            return (/^(\d{1,3}(\.\d{1,3}){3})|([0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4})+)$/).test(target);
        };

        // 追加
        $('.js-refuse-users').on('submit', function (event) {
            event.preventDefault();
            var $input = $('input[name="refusal_input"]');
            var name = $input.val();

            // IPアドレスには必ず':' '.'などの区切り記号が含まれるので, はてなIDとはぶつからない
            if (isLikeIpAddress(name)) {
                ip_manager.add(name);
            } else {
                var user;
                try {
                    user = new RefusedUser(name);
                } catch(ignore) {}
                if (user) user_manager.add(user);
            }
            $input.val('').focus();
            return false;
        });

        // 削除
        $('.js-refuse-users').on('click', '.js-delete-refused-user', function () {
            var name = $(this).closest('.refused-user').data('user-name');
            user_manager.remove(new RefusedUser(name));
        });

        $('.js-refuse-ips').on('click', '.js-delete-refusal', function () {
            var ip = $(this).closest('.refused-ip').data('ip');
            ip_manager.remove(ip);
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['register'] = function () {
        if (!Hatena.Diary.data('name')) return; // guest

        var dispatcher = Hatena.Diary.Pages.Admin['register'];
        dispatcher.submitButton = $('input[type=submit]');

        var $domain = $(':input[name="domain"]');
        var $blogIdInput = $('input[name="id"]');
        var requestThreshold = 1000;
        dispatcher.STATES = {
            progress: {
                className: 'progress',
                message: $('.domain-check-message.progress')
            },
            available: {
                className: 'check',
                message: $('.domain-check-message.check')
            },
            unavailable: {
                className: 'error',
                message: $('.domain-check-message.error')
            },
            invalid: {
                className: 'invalid',
                message: $('.domain-check-message.invalid')
            },
            invalidLength: {
                className: 'invalid-length',
                message: $('.domain-check-message.invalid-length')
            }
        };

        // このStateを見てsubmitButtonの有効化無効化を行う
        dispatcher.inputValidStates = {
            "id" : true,
            "import" : true
        };

        var fetchBlogIdAvailability = function () {
            var blogID = $blogIdInput.val();
            var topdomain = $domain.val();

            if ( ! blogID ) {
                return;
            } else if (blogID.length < 2 || blogID.length > 32) {
                Hatena.Diary.Pages.Admin['register'].changeAvailabilityState({
                    nextState: 'invalidLength'
                });
                return;
            } else if (! /^[a-zA-Z0-9][a-zA-Z0-9\-]+$/.test(blogID)) {
                Hatena.Diary.Pages.Admin['register'].changeAvailabilityState({
                    nextState: 'invalid'
                });
                return;
            }

            var brand_name = $('[data-brand-name]').attr('data-brand-name');
            $.ajax({
                url: '/api/blog/domain_registry',
                dataType: 'json',
                data: {
                    blog_ids: JSON.stringify([blogID]),
                    brand_name: brand_name
                }
            }).done(function (data) {
                var domain_statuses = data[blogID];

                if (domain_statuses !== undefined) {
                    dispatcher.checkBlogIdAvailability({
                        blogID: blogID,
                        topdomain: topdomain,
                        statuses: domain_statuses
                    });
                }
            });
        };

        fetchBlogIdAvailability();

        $domain.change(fetchBlogIdAvailability);
        $blogIdInput.
            keyup(_.debounce(fetchBlogIdAvailability, requestThreshold)).
            keyup(function () {
                dispatcher.changeAvailabilityState({
                    nextState: 'progress'
                });
            });

        var fillinDefault = function() {
            var user_name = Hatena.Diary.data('name').toLowerCase().replace(/_/, '-');
            var brand_name = $('[data-brand-name]').attr('data-brand-name');
            $.ajax({
                url: '/api/blog/domain_registry',
                dataType: 'json',
                data: {
                    blog_ids: JSON.stringify([user_name]),
                    brand_name: brand_name
                }
            }).done(function (data) {
                var domain_statuses = data[user_name];

                if (typeof domain_statuses === 'undefined' || typeof domain_statuses === null) {
                    domain_statuses = {};
                }

                var available_domains = Hatena.Diary.Pages.Admin['register'].availableDomains(domain_statuses);

                if (_.any(available_domains)) {
                    var $domain = $(':input[name="domain"]');
                    var current_domain = $domain.val();
                    if (! _.include(available_domains, current_domain)) {
                        $domain.val(available_domains[0]);
                    }

                    var idInput = $('input[name=id]');
                    if (idInput.val() === '') {
                        // idが空のときuser名からフィルイン
                        idInput.val(user_name);
                        Hatena.Diary.Pages.Admin['register'].changeAvailabilityState({
                            nextState: 'available'
                        });
                    }
                }
            });
        };

        fillinDefault();

        if ($('input[name=import]').length) {
            $('input[name=permission],input[name=import]').change(function () {
                dispatcher.changeImportAvailabilityState();
            });
            $('.import-error').hide();
            dispatcher.changeImportAvailabilityState();
        }
    };

    Hatena.Diary.Pages.Admin['register'].changeAvailabilityState = function (args) {
        var dispatcher = Hatena.Diary.Pages.Admin['register'];
        var nextState = args.nextState;

        if (nextState == 'unavailable' || nextState == 'invalid' || nextState == 'invalidLength') {
            dispatcher.inputValidStates['id'] = false;
        }
        else {
            dispatcher.inputValidStates['id'] = true;
        }
        dispatcher.changeSubmitButtonState();

        _.each(Hatena.Diary.Pages.Admin['register'].STATES, function (value, key) {
            if (key === nextState) {
                value.message.show();
            } else {
                value.message.hide();
            }
        });
    };

    Hatena.Diary.Pages.Admin['register'].checkBlogIdAvailability = function (args) {
        var topdomain = args.topdomain;
        var blogID    = args.blogID;
        var statuses  = args.statuses;

        var inputState = statuses[topdomain];
        var availableDomains = Hatena.Diary.Pages.Admin['register'].availableDomains(statuses);

        if (inputState === 'unavailable' && _.any(availableDomains)) {
            Hatena.Diary.Pages.Admin['register'].suggestAlternativeDomainNames({
                blogID: blogID,
                availableDomains: availableDomains
            });
        }

        Hatena.Diary.Pages.Admin['register'].changeAvailabilityState({
            nextState: inputState
        });
    };

    Hatena.Diary.Pages.Admin['register'].suggestAlternativeDomainNames = function (args) {
        var blogID = args.blogID;
        var availableDomains = args.availableDomains;
        var $message = $('.domain-recommend');
        var $domain = $(':input[name="domain"]');

        $('.requested-blog-id').text(blogID);

        $message.find('ul').detach();
        var $alternatives = $('<ul/>');
        _.each(availableDomains, function (domain) {
            $('<li/>').
                text(blogID + '.' + domain).
                click(function () { $domain.val(domain).change() }).
                appendTo($alternatives);
        });
        $message.append($alternatives).show();
    };

    // domain_statuses = {
    //   $domain: 'available' || 'unavailable' || 'invalid'
    //   ...
    // }
    Hatena.Diary.Pages.Admin['register'].availableDomains = function (domain_statuses) {
        var domains = _.keys(domain_statuses);
        var availableDomains = _.select(domains, function (domain) { return domain_statuses[domain] === 'available'; });

        return availableDomains;
    };

    Hatena.Diary.Pages.Admin['register'].changeImportAvailabilityState = function (args) {
        var dispatcher = Hatena.Diary.Pages.Admin['register'];

        var $checkedPermission = $('input[name=permission]:checked');
        var $selectedImport    = $('input[name=import]:checked');

        var blogPermission  = $checkedPermission.val();
        var diaryPermission = $selectedImport.attr('data-permission');

        var $errorMessage = $('.import-error');
        if (diaryPermission == 'private' && blogPermission == 'public') {
            $errorMessage.show();
            dispatcher.inputValidStates['import'] = false;
            dispatcher.changeSubmitButtonState();
        }
        else {
            $errorMessage.hide();
            dispatcher.inputValidStates['import'] = true;
            dispatcher.changeSubmitButtonState();
        }
    };

    Hatena.Diary.Pages.Admin['register'].changeSubmitButtonState = function (args) {
        var dispatcher = Hatena.Diary.Pages.Admin['register'];
        var submitButton = dispatcher.submitButton;

        var shouldEnabled = _.every(dispatcher.inputValidStates, function (valid) {
            return valid;
        });

        if (shouldEnabled) {
            submitButton.attr('disabled', false);
            submitButton.removeClass('disabled');
            submitButton.addClass('btn-blue');
        }
        else {
            submitButton.attr('disabled', true);
            submitButton.removeClass('btn-blue');
            submitButton.addClass('disabled');
        }
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['register-iframe'] = function () {
        if (!Hatena.Diary.data('name')) return; // guest

        var fillinDefault = function() {
            var user_name = Hatena.Diary.data('name').toLowerCase().replace(/_/, '-');
            var idInput = $('input[name=id]');
            if (idInput.val() === '') {
                // idが空のときuser名からフィルイン
                idInput.val(user_name);
            }
        };

        fillinDefault();
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['store-theme-new'] = function () {
        var $availableLicenses = $('.available-licenses');
        var $showAvailableLicenses = $('.show-more').find('a');
        var expandAvailableLicenses = function () {
            $availableLicenses.show();
            $availableLicenses.attr('data-collapsed', 0);
            $showAvailableLicenses.text($showAvailableLicenses.attr('data-collapse-message'));
        };
        var collapseAvailableLicenses = function () {
            $availableLicenses.hide();
            $availableLicenses.attr('data-collapsed', 1);
            $showAvailableLicenses.text($showAvailableLicenses.attr('data-expand-message'));
        };

        $availableLicenses.hide();

        $showAvailableLicenses.on('click', function (e) {
            if ($availableLicenses.attr('data-collapsed') === '1') {
                expandAvailableLicenses();
            } else {
                collapseAvailableLicenses();
            }
            e.preventDefault();
        });

        $('.deed').hide();
        $('.show-deed').on('click', function (e) {
            $($(this).attr('data-target-selector')).toggle();
            return false;
        });

        // 選択してるやつが隠れてたら見せる
        if ($('input[name=license]:checked').is(':visible') === false) {
            $showAvailableLicenses.click();
        }
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['store-theme-theme_id'] = function () {
        if (Hatena.Star) {
            Hatena.Star.SiteConfig = {
                entryNodes: {
                    '#container' : {
                        uri: 'a.permalink',
                        title: 'h1.theme-name',
                        container: '.star-container'
                    }
                }
            };
        }

        var self = Hatena.Diary.Pages.Admin['store-theme-theme_id'];
        self.$themeContainer = $('#store-container');
        self.$installDialog = $('.blog-title-dropdown-window');
        self.$installButton = $('#sidebar').find('.install-theme-btn');

        self.$installDialog.hide();
        self.$installButton.click(function () {
            self.$installDialog.slideToggle();
        });

        $('#theme-detail-tabs').tabs({ active : 0});
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['topic-show'] = function () {
        $('#topic-entries-tabs').tabs({ active : 0 });
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['user-blog-about_config'] = function () {
        var table = $('#about-config');
        var form  = $('#form-edit');
        var key   = $('#key');
        var value = $('#value');
        var del   = $('#delete-button');

        function update (key, value) {
            var tr = table.find('tr[data-key="' + key + '"]');
            if (!tr.length) {
                tr = $('<tr><th></th><td></td></tr>');
            }

            tr.attr({
                'data-key' : key,
                'data-value' : value
            });
            tr.find('th').text(key);
            tr.find('td').text(value);

            if (!tr.parent().length) table.find('tbody').append(tr);
        }

        form.submit(function (e) {
            e.preventDefault();

            $.ajax({
                url : form.attr('action'),
                type : 'post',
                dataType : 'json',
                data: form.serialize(),
                success : function (data) {
                    update(data.key, data.value);
                    form.hide();
                }
            });
        });

        del.click(function (e) {
            $.ajax({
                url : form.attr('action'),
                type : 'post',
                dataType : 'json',
                data: form.serialize() + '&delete=1',
                success : function (data) {
                    update(data.key, data.value);
                    form.hide();
                }
            });
        });

        $('#button-new-value').click(function () {
            key.val('');
            value.val('');
            del.hide();
            form.show();
            key.focus();
        });

        table.find('td').on('click', function () {
            var tr = $(this).parent();

            key.val(tr.attr('data-key'));
            value.val(tr.attr('data-value'));
            del.show();
            form.show();
            value.focus();
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-accesslog'] = function () {
        var table = $('#access-counts').remove();
        var counts = {};
        table.find('tr').each(function () {
            var $this = $(this);
            var time  = +$this.find('td[data-time]').attr('data-time');
            var count = +$this.find('td[data-count]').attr('data-count');
            counts[time] = count;
        });

        AccessLog.showGraph(counts, {
            parent : $('#access-counts-daily'),
            timeformat : '%m/%d',
            minTickSize : [1, 'day'],
            unit   : 24 * 60 * 60 * 1000,
            number : 31
        });

        AccessLog.showGraph(counts, {
            parent : $('#access-counts-hourly'),
            timeformat : '%d %H:%M',
            minTickSize : [1, 'hour'],
            unit   : 60 * 60 * 1000,
            number : 48
        });

        $('#access-counts-tabs').tabs({ active : 0 });

        $('#summary-detail-tabs').tabs({ active : 0 });

        $('.summary-box .hosts').delegate('.host', 'click', function() {
            $('.summary-box .hosts .selected').removeClass('selected');
            $(this).addClass('selected');

            var host = $(this).attr('data-site-host');
            $('.summary-box .site.selected').removeClass('selected');
            $('.summary-box .sites').find('*[data-site-host="' + host + '"]').addClass('selected');
            return false;
        });
    };
})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-categories'] = function () {
        var openRenameModalWindow = function(category_name) {
            var $modal = $('.js-rename-modal-window[data-category-name="' + category_name + '"]');
            if ($modal.is(':visible')) return;
            Hatena.Diary.Window.show($modal, {});
            $modal.find(':text').val(category_name).focus()[0].select();
        };
        $(document).on('click', '.js-show-rename-modal-window', function(event) {
            var category_name = $(event.target).attr('data-category-name');
            openRenameModalWindow(category_name);
        });

        // Hatena.Diary.Windowは，documentをclickすると，hideAllする．
        // .js-rename-modal-windowから外にclickイベントを伝播させないため，ここで止める．
        // モーダルウィンドウ内のclickイベントをdocument.on とかで待っていても，ここで止めているので，
        // 非効率ではあるが，closeボタンなど個別にイベントハンドラを設定している．
        // ボタンの数はあとから増えないので，これで問題ない．
        $('.js-rename-modal-window .js-icon-close').on('click', function() {
            Hatena.Diary.Window.hideAll();
        });
        $('.js-rename-modal-window').on('click', function(event) {
            event.stopPropagation();
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-comment-delete-deleted'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Pages.send('delete');
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-comment-delete'] = function () {
        Hatena.Diary.Pages.createForParent();
    };

})(jQuery);
(function($){

Hatena.Diary.Pages.Admin['user-blog-comment-done'] = function () {
    Hatena.Diary.Pages.createForParent();

    var comment = document.getElementById('posted').value;

    Hatena.Diary.Pages.send('update', { comment : comment });

    Hatena.Diary.Pages.send('close');
};

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-comment'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Pages.Admin['user-blog-comment'].focusTextArea();
        Hatena.Diary.Util.sendResizeRequest();
    };

    Hatena.Diary.Pages.Admin['user-blog-comment'].focusTextArea = function () {
        // IE9でfocusできないことがあるので時間を置いて何度も試す
        try {
            $('#body').focus();
        } catch (e) {
            setTimeout(Hatena.Diary.Pages.Admin['user-blog-comment'].focusTextArea, 100);
        }
    };

})(jQuery);

(function($){
    Hatena.Diary.Pages.Admin['user-blog-comments'] = function () {
        $('button[name="mode"][value="delete"]').click(function () {
            return confirm(Hatena.Locale.text('admin.comments.delete.confirm'));
        });

        Hatena.Diary.Util.updateDynamicPieces($('.js-comments-table'));
    };

})(jQuery);
(function($){
    Hatena.Diary.Pages.Admin['user-blog-config'] = function () {
        Hatena.Diary.Util.loadNicknames($('.profile'));
    };
})(jQuery);

(function($){

    // モジュール置き場(全体のサイドバー、トップページのメインカラムなど)に付きひとつできる
    // $elementはdiv[data-modules-type="sidebar"].sidebar-boxなど
    // editorは ModuleEditorのインスタンス
    var Modules = function($element, editor) {
        var self = this;
        self.$element = $element;
        self.editor = editor;
        self.init();
    };

    Modules.prototype = {
        init: function() {
            var self = this;

            // "sidebar"など，このモジュール置き場の位置
            self.position = self.$element.attr('data-modules-type');

            self.modules = [];

            // 追加ボタン押したらモジュール追加
            self.$element.on('click', '.js-add-module', function() {
                self.addNewModule();
                return false;
            });

            self.$element.find('.module').each(function() {
                self.addModuleFromElement($(this));
            });

            // 並べ替え可能にする．終わったらupdate
            self.$element.find('.modules').sortable({
                containment: 'parent',
                stop: function() {
                    self.onSorted();
                }
            });
        },
        // 既存のDOM要素からモジュールを作り監視を始める
        addModuleFromElement: function($element) {
            var self = this;
            var module = new Module($element);
            self.awareModule(module);
            module.render();
        },
        // モジュールのイベントを監視する
        awareModule: function(module) {
            var self = this;
            self.modules.push(module);
            $(module).on('removed', function() {
                self.onModuleRemoved(module);
            }).on('updated', function() {
                self.onUpdated();
            }).on('edit', function() {
                self.editModule(module);
            });
        },
        // 並び順が変わったらself.modulesも追従する．DOMから.modulesを取ってきて，getElementして要素が一致したものを選ぶ．
        onSorted: function() {
            var self = this;

            var sortedModules = self.$element.find('.module').map(function() {
                var element = this;

                var matchedModule = _.find(self.modules, function(module) {
                    return module.getElement()[0] === element;
                });

                return matchedModule;
            }).toArray();

            self.modules = sortedModules;

            self.onUpdated();
        },
        // モジュールが消えたら，modulesから消して，updatedメソッドを発行
        onModuleRemoved: function(module) {
            var self = this;
            self.modules = _.difference(self.modules, [module]);
            self.onUpdated();
        },
        // 既存のモジュールの編集．editorの呼び出し，完了時に更新，失敗したら何もしない
        editModule: function(module) {
            var self = this;
            var session = self.editor.editModule(module);
            module.setAsSelected();
            session.done(function(data) {
                // data の更新
                module.update(data.type, data.title, data.value);
            }).always(function() {
                module.unsetAsSelected();
            });
        },
        // 新しいモジュールを追加する．DOMの追加，editorの呼び出し，完了時に更新，失敗したら消す
        addNewModule: function() {
            var self = this;
            var module = Module.initializeWithModulesPosition(self.position);
            module.setAsNewModule();
            module.setAsSelected();
            self.$element.find('.modules').append(module.getElement());
            var session = self.editor.editNewModule(module);
            session.done(function(data) {
                self.awareModule(module);
                module.update(data.type, data.title, data.value);
                module.unsetAsNewModule();
                module.unsetAsSelected();
            }).fail(function() {
                module.remove();
            });
        },
        // updatedイベントを発行する．外で待ち構えてプレビューの更新などを行う
        onUpdated: function() {
            var self = this;
            $(self).triggerHandler('updated');
        }
    };

    // モジュール1つを表す．$elementは.module
    var Module = function($element) {
        var self = this;
        self.$element = $element;
        self.init();
    };

    Module.prototype = {
        init: function() {
            var self = this;

            // モジュールは，type, title, valueの組で表される．
            // typeは，"profile"とか．
            // titleはモジュールのタイトル
            // valueはObject

            self.type = self.$element.find('input.js-module-type').val();
            self.title = self.$element.find('input.js-module-title').val();
            self.value = {};
            try {
                self.value = JSON.parse(self.$element.find('input.js-module-value').val());
            } catch(ignore) {}

            self.$element.on('click', '.js-edit-module', function() {
                self.edit();
                return false;
            }).on('click', '.js-remove-module', function() {
                if ( confirm(Hatena.Locale.text('blog.confirm.delete')) ) {
                    self.remove();
                }
                return false;
            });
        },
        // editイベントを発行する
        // modulesがこのイベントを見て編集UIを出す
        edit: function() {
            var self = this;
            $(self).trigger('edit');
        },
        // elementを消し，removedイベントを発行する
        // modulesがこのイベントを見てプレビュー更新してくれる
        remove: function() {
            var self = this;
            self.$element.remove();
            $(self).triggerHandler('removed');
        },
        // 指定された値に更新し描画
        update: function(type, title, value) {
            var self = this;
            self.type = type;
            self.title = title;
            self.value = value;
            self.render();
            $(self).trigger('updated');
        },
        // 新たに追加中のモジュール？
        isNewModule: function() {
            return this.isNew;
        },
        // 新たに追加中のモジュール状態にする
        setAsNewModule: function() {
            this.isNew = true;
            this.$element.addClass('created');
        },
        // 新たに追加中のモジュール状態を解除する
        unsetAsNewModule: function() {
            this.isNew = false;
            this.$element.removeClass('created');
        },
        // 編集中(選択中)のモジュール状態にする
        setAsSelected: function() {
            this.$element.addClass('selected');
        },
        // 編集中(選択中)のモジュール状態を解除する
        unsetAsSelected: function() {
            this.$element.removeClass('selected');
        },
        // 描画．既存のelementを書き換える．
        // inputの設定，クラスの追加，表示用のラベルの設定
        render: function() {
            var self = this;
            self.$element.find('input.js-module-type').val(self.getType());
            self.$element.find('input.js-module-title').val(self.getTitle());
            self.$element.find('input.js-module-value').val(self.getValueAsJSON());
            self.$element.addClass(self.getType()); // このクラスは何のために使っている？
            self.$element.find('.title, .clipped-content').text(self.getTitleForPreview());
        },
        getType: function() {
            return this.type;
        },
        getTitle: function() {
            return this.title;
        },
        getValue: function() {
            return this.value;
        },
        getElement: function() {
            return this.$element;
        },
        // 表示用のタイトル．タイトルか，HTMLモジュールのときは本文の先頭か，HTMLモジュールのときは"HTML"
        getTitleForPreview: function() {
            var self = this;
            var title = self.getTitle();
            if (!title && self.getType() === 'html') {
                title = self.removeTag(self.value['module-value'] || '') || Hatena.Locale.text('blog.module.html');
            }
            return title;
        },
        // valueは，inputにはJSON化して格納する
        getValueAsJSON: function() {
            var self = this;
            return JSON.stringify(self.value);
        },
        // HTMLモジュールのタイトルがないとき本文を表示する
        removeTag: function(html) {
            return html.replace(/<.*?>/g, '');
        }
    };

    // DOMに属さない新たなモジュールを作って返す
    // modulesType: "sidebar"など，モジュールの配置される場所
    Module.initializeWithModulesPosition = function(position) {
        var template = $('.new-module-template').html();
        var module_html = _.template(template, {position: position});
        var $element = $($.parseHTML(module_html));
        var self = new Module($element);
        return self;
    };

    // moduleの編集モーダルウィンドウ
    // 編集と追加でDOMは共通で，hide-radiosというクラスを付与すると，パネル選択UIが消える
    var ModuleEditor = function($modalWindow) {
        var self = this;
        self.$modalWindow = $modalWindow;

        // $modalWindowはposition: relative内に入ってる．overlayは画面全体を覆ってほしいので，bodyの末尾にappendし直す
        self.$modalWindow.appendTo(document.body);

        self.$dialogBox     = self.$modalWindow.find('.dialog-box'); // モーダルで出てくるboxの本体
        self.$dialogOverray = self.$modalWindow.find('.dialog-overray');
        self.$applyButton   = self.$modalWindow.find('.submit button.apply');
        self.$cancelButton  = self.$modalWindow.find('.submit button.cancel');
        self.$radios        = self.$modalWindow.find('.radios');

        // sessionはモーダル表示中に有効．保存でresolve，キャンセルでreject
        // 初回だけsessionないと難しいので，ダミーの値を入れておく
        self.session = $.Deferred();
        self.session.reject();

        self.init();
    };

    ModuleEditor.prototype = {
        init: function() {
            var self = this;

            // 新規モジュール追加時はモジュールのタイプを選べるので，changeイベントを見る
            self.$radios.find('input:radio').change(function() {
                var $checked = self.$radios.find('input:radio:checked');
                var type    = $checked.val();
                self.selectPanelByType(type);
            });

            // IEではchangeイベントが発行されないので，clickイベントを見る
            self.$modalWindow.find('.radio').click(function() {
                var type = $(this).find('input:radio').val();
                self.selectPanelByType(type);
            });

            // リンクモジュール，リンクを1行追加
            self.$modalWindow.find('#module-value-component-link').each(function() {
                var $linkModule = $(this);
                $linkModule.find('#add-link-input-button').click(function() {
                    var $linkInput = $linkModule.find('.link-input').eq(0).clone();
                    $linkInput.find(':input').val('');
                    $linkInput.insertAfter($linkModule.find('.link-input').eq(-1));

                    var $scrolled = self.$modalWindow.find('.module-value-box-inner');
                    $scrolled.scrollTop($scrolled[0].scrollHeight);
                });
            });

            // リンクを削除
            self.$modalWindow.delegate('.delete-link-input-button', 'click', function() {
                // 追加するとき，1件目をcloneするので，最後の1件だけは消せないようになってる．
                if (self.$modalWindow.find('.link-input').length > 1) {
                    $(this).closest('.link-input').remove();
                }
                return false;
            });

            // セッション終了イベントの監視
            self.$applyButton.click(function() { self.applyEdit() });
            self.$dialogOverray.click(function() { self.cancelEdit() });
            self.$cancelButton.click(function() { self.cancelEdit() });
            $(window).keyup(function (e) {
                if (keyString(e) == 'S-ESC') { self.cancelEdit() }
            });

            // カテゴリーモジュール
            self.$modalWindow.find('.js-categories-order-type').change(function () {
                $(self).triggerHandler('change-category-order-type');
            });
        },
        // 新規モジュール追加
        editNewModule: function(module) {
            var self = this;
            self.session.reject();
            self.session = $.Deferred();
            self.editingModule = module;

            self.setupValues();

            // 追加のときはcreatedクラスを足し，hide-radiosクラスを消し，キャンセルボタンを隠す
            self.$modalWindow.addClass('created').removeClass('hide-radios');
            self.$cancelButton.show();

            self.show();

            return self.session.promise();
        },
        // 既存のモジュールの編集
        editModule: function(module) {
            var self = this;
            self.session.reject();
            self.session = $.Deferred();
            self.editingModule = module;

            self.setupValues();

            // 編集のときはcreatedクラスを消し，hide-radiosクラスを足し，キャンセルボタンを隠す
            self.$modalWindow.removeClass('created').addClass('hide-radios');
            self.$cancelButton.hide();

            self.selectPanelByType(module.getType());

            self.show();

            self.fillValuesFromModule(module);

            // カテゴリモジュールは既定のorder_typeでプレビューをセット
            // module.value['order_type']
            $(self).triggerHandler('edit-new-module');

            return self.session.promise();
        },
        // 指定されたtypeのパネルを選択し，表示する
        // type: "profile", "html"など
        selectPanelByType: function(type) {
            var self = this;

            self.$radios.find('.radio').removeClass('selected');
            var $selected_label = self.$radios.find('.radio.module-' + type).closest('.radio');
            $selected_label.addClass('selected');
            // propではchangeイベントが発火しないことによって無限ループせずに済んでる
            $selected_label.find('input:radio').prop('checked', true);

            self.$modalWindow.find('.module-value-component').hide();
            self.$modalWindow.find('#module-value-component-' + type).show();
        },
        // 現在選択中のパネルのtypeを返す．未選択ならnull
        getSelectedPanelType: function() {
            var self = this;
            var $selected = self.$radios.find('input:enabled:checked');
            if ($selected.length) {
                return $selected.val();
            } else {
                return null;
            }
        },
        // モーダルウィンドウ内のinputを初期状態に戻す．
        // モーダルウィンドウは1つだけ存在し，使い回されるので，初期化しないと，前回のモジュールの編集内容が出てくることになる．
        setupValues: function() {
            var self = this;

            // textを空にする
            self.$modalWindow.find('textarea, input[type=text], input[type=number]').val('');
            // チェックボックスのチェックを外す
            self.$modalWindow.find('input[type=checkbox]').prop('checked', false);

            // セレクトボックスの値をデフォルトに初期化する
            // もしも「data-default-option」属性でデフォルトの値が指定されている場合はそれに従う
            self.$modalWindow.find('select').each(function () {
                if( $(this).attr('data-default-option') ) {
                    // デフォルト値が設定されていた場合
                    $(this).val( $(this).attr('data-default-option') );
                } else {
                    // デフォルト値の設定がない場合は，一番初めの要素を選択状態にする
                    $(this).find('option:first').prop('selected', true);
                }
            });

            // なにも選択されていなかったら，最初のペインを選択
            if (!self.getSelectedPanelType()) {
                self.selectPanelByType('profile');
            }
        },
        // ウィンドウを表示する
        show: function() {
            var self = this;

            // サイドバー内を下までスクロールして追加した要素を見せる
            var $scrolled = $('#tab-customize');
            $scrolled.scrollTop($scrolled[0].scrollHeight);

            self.$modalWindow.show();
            self.setPosition();
            self.$dialogBox.find('input[type=text]:visible:first').focus();
        },
        // モーダルウィンドウを中央揃えにする
        setPosition: function() {
            var self = this;
            var winHeight  = $(document).height();
            var winWidth   = $(window).width();
            var dialogTop  = winHeight / 2 - self.$dialogBox.height() / 2;
            var dialogLeft = (winWidth / 2) - (self.$dialogBox.width() / 2);
            self.$dialogBox.css({ top: dialogTop, left: dialogLeft });
            self.$dialogOverray.css({ height: winHeight, width:  winWidth });
        },
        // 変更を適応する．inputからモジュールを表す表現を作り，sessionをresolveする．
        applyEdit: function() {
            var self = this;
            var data = self.extractInputToModuleValues();
            self.session.resolve(data);
            self.hide();
        },
        // 編集セッションを終了してウィンドウを隠す
        cancelEdit: function() {
            var self = this;
            self.session.reject();
            self.hide();
        },
        // モーダルウィンドウを隠す
        hide: function() {
            var self = this;
            self.$modalWindow.hide();
        },
        // モジュール編集のとき，モジュールの値をウィンドウにコピー
        // :visibleを見てるのでshow()したあとに呼ぶ必要がある
        fillValuesFromModule: function(module) {
            var self = this;
            var val = module.getValue();
            var moduleType = module.getType();
            for(var name in val) {

                if ( moduleType === 'link' &&
                     (name === 'link_title' || name === 'link_url')) {
                    self.setLinkInput(self.$dialogBox, val, name);
                } else {
                    var $inputs = self.$dialogBox.find(':input:visible').filter(function() {
                        return $(this).attr('name') == name;
                    });
                    $inputs.eq(0).val(val[name]);
                    if ( $inputs.eq(0).attr('type') == 'checkbox' && val[name]) {
                        $inputs.eq(0).prop('checked', true);
                    }
                }
            }
            // module-valueにmodule-titleが入っていることもあるのでタイトルは後から設定
            self.$dialogBox.find('input[name=module-title]:visible').val(module.getTitle());
        },
        extractInputToModuleValues: function() {
            // ウィンドウ内のinputの値をモジュール用の表現に変換して返す
            var self = this;

            var moduleTitle = self.$dialogBox.find('input[name=module-title]:visible').val();

            // モジュールタイプは，新しいモジュール追加するときはDOMから拾う
            // 編集時は，編集中のmoduleオブジェクトのtypeを引き継ぐ
            var moduleType;
            if (self.editingModule.isNewModule()) {
                moduleType = self.getSelectedPanelType();
            } else {
                moduleType = self.editingModule.getType();
            }
            var moduleValue = {};

            // タイトルが未記入の場合、初期値を埋める(HTMLモジュールは埋めない)
            if ( ! moduleTitle && moduleType !== 'html' ) {
                var defaultTitle = self.$radios.find('input:checked').attr('data-default-module-title');
                moduleTitle = defaultTitle;
            }

            self.$dialogBox.find(':input:visible').each(function() {
                var $input = $(this);
                var name  = $input.attr('name');
                var val   = $input.val();

                // module-titleのinputもdialogBox内に存在するが，
                // タイトルは別のinputに保存するため，ここではスキップする
                if (name === 'module-title') {
                    return;
                }

                if ($input.attr('type') == 'checkbox') {
                    if ( $input.prop('checked') ) {
                        val = 1;
                    } else {
                        val = 0;
                    }
                }

                if (!name) {
                    return;
                }
                // 同じ名前の値が複数来たらarrayにする
                if (typeof moduleValue[name] === 'undefined') {
                    moduleValue[name] = val;
                } else if (moduleValue[name] instanceof Array) {
                    moduleValue[name].push(val);
                } else {
                    moduleValue[name] = [moduleValue[name], val];
                }
            });

            return {
                type:  moduleType,
                title: moduleTitle,
                value: moduleValue
            };
        },
        // リンクモジュールのフィルイン
        // リンクモジュールはフィールド一つでタイトル全部 / URL全部を表す．link-titleとlink-value．
        setLinkInput: function ($dialogBox, val, name) {
            var $inputs = $dialogBox.find(':input:visible').filter(function() {
                return $(this).attr('name') == name;
            });
            var $linkInput;
            if (val[name] instanceof Array) {
                var addInput = val[name].length > $inputs.length ? true : false;
                var diff = addInput ? val[name].length - $inputs.length : $inputs.length - val[name].length;

                for (var i = 0; i < diff; i++) {
                    if ( addInput ) {
                        $linkInput = $dialogBox.find('.link-input:visible').eq(0).clone();
                        $linkInput.find(':input').val('');
                        $linkInput.insertAfter($dialogBox.find('.link-input').eq(-1));
                    } else {
                        $linkInput = $dialogBox.find('.link-input:visible').eq(-1);
                        $linkInput.remove();
                    }
                }
                $inputs = $dialogBox.find(':input:visible').filter(function() {
                    return $(this).attr('name') == name;
                });
                $inputs.each(function() { $(this).val(val[name].shift()) });
            } else {
                // 1つしか要素がない場合、inputを１つにする
                while ( $inputs.length > 1 ) {
                    $linkInput = $dialogBox.find('.link-input:visible').eq(-1);
                    $linkInput.remove();
                    $inputs = $dialogBox.find(':input:visible').filter(function() {
                        return $(this).attr('name') == name;
                    });
                }
                $inputs.eq(0).val(val[name]);
            }
        }
    };

    // カテゴリモジュールの更新, sortable要素のセットアップ
    var CategoryEditor = function() {
        var self = this;
        self.categoryTemplate =  _.template($('.js-categories-template').html());
        self.$categoryContainer = $('.js-categories-container');
    };
    CategoryEditor.prototype = {
        updateCategoryPreview: function () {
            var self = this;
            var $categoryContainer = self.$categoryContainer;
            var url = $categoryContainer.data('getUrl');
            var order_type = $('.js-categories-order-type option:selected').val();

            // 並び順プレビュー
            $.ajax({
                url: url,
                data: {
                    order_type: order_type
                }
            }).done(function(data) {
                var categories = data.categories; // { count: entry_count, name: category_name }
                sortable_container_class = order_type == 'user' ? 'module-category-sortable-container' : '';
                sortable_item_class = order_type == 'user' ? 'module-category-sortable-item' : '';

                $categoryContainer.html(self.categoryTemplate({ categories:                 categories,
                                                                sortable_container_class:   sortable_container_class,
                                                                sortable_item_class:        sortable_item_class }));
                if ( order_type == 'user' ) self.setupSortable();
            });
        },
        setupSortable: function () {
            var self = this;
            var $categoryContainer = self.$categoryContainer;

            var $sortableContainer = $categoryContainer.find('.js-categories-sortable');
            var $sortableItem = $categoryContainer.find('.js-categories-sortable-item');

            $sortableContainer.sortable({
                stop: function () {
                    var $sortedItems = $categoryContainer.find('.js-categories-sortable-item');
                    var sortedCategoryNames = $sortedItems.map(function(idx, element){
                        var categoryName = $(element).data("categoryName");
                        return categoryName;
                    }).get();

                    var url = $sortableContainer.data('sortUrl');
                    $.ajax({
                        type: 'POST',
                        url: url,
                        data: {
                            category_names  : sortedCategoryNames,
                            rkm             : Hatena.Diary.data('rkm'),
                            rkc             : Hatena.Diary.data('rkc')
                        },
                        traditional: true
                    });
                }
            });
        }
    };

    var PreviewUpdater = function(args) {
        var self = this;
        self.$form = args.$form;
        self.$loading = args.$loading;
        self.$preview = args.$preview;
        self.formState = args.formState;
        self.$deviceInput = self.$form.find(':input[name=device]');
        self.device = self.$deviceInput.val();
        self.pageType = 'index';
        self.failedCount = 0;
    };

    PreviewUpdater.prototype = {
        // トップページをプレビューする状態にする
        setAsIndexPreview: function() {
            var self = this;
            self.pageType = 'index';
        },
        // エントリページをプレビューする状態にする
        setAsPermalinkPreview: function() {
            var self = this;
            self.pageType = 'permalink';
        },
        getPageType: function() {
            var self = this;
            return self.pageType;
        },
        // PC版プレビュー状態にする
        setDeviceAsPC: function() {
            var self = this;
            self._setDevice('pc');
        },
        // touch版プレビュー状態にする
        setDeviceAsTouch: function() {
            var self = this;
            self._setDevice('touch');
        },
        // 内部的なプレビュー状態切り替え
        // inputの値設定，プレビュー更新を依頼
        _setDevice: function(device) {
            var self = this;
            self.device = device;
            self.$deviceInput.val(self.device);
            self.requestPreview();

            // touchのとき，iframeに.device=touchクラス追加
            self.$preview.toggleClass('device-touch', device === 'touch');
        },
        // previewの更新を依頼する．formの状態が変わっていなければ何もしない
        requestPreview: function() {
            var self = this;

            var serialized = self.$form.serialize();
            if (serialized === self.serialized) return;
            self.serialized = serialized;

            self.preview();
        },
        // previewを更新する．失敗したらやり直し．あまりに失敗したらもうなにもしない．
        preview: function() {
            var self = this;

            if (self.failedCount > 10) return;

            self.showEffect();

            if (!self.serialized) {
                self.serialized = self.$form.serialize();
            }
            var serialized = self.serialized;

            var getSignature = self.getSignature(serialized);
            getSignature.done(function(signature) {
                self.onGotSignature(signature);
                self.failedCount = 0;
            }).fail(function() {
                self.failedCount++;
                self.requestPreview();
            });
        },
        // signatureゲットしたらresolveするDeferredを返す
        getSignature: function(serialized) {
            var self = this;

            var got = $.Deferred();

            $.ajax({
                url : '../../preview/design',
                type : "post",
                dataType : 'json',
                data : serialized
            }).done(function(data) {
                // 通信してる間に状態が変わっていなければ成功，変わってたら失敗
                if (serialized === self.$form.serialize()) {
                    got.resolve(data.signature);
                } else {
                    got.reject();
                }
            }).fail(function() {
                got.reject();
            });

            return got.promise();
        },
        // signature揃ったので実際にプレビュー
        // formのactionとtargetを書き換えて，signatureを追加してsubmitし，即座に元の状態に戻している．
        onGotSignature: function(signature) {
            var self = this;

            var $form = self.$form;

            var actionBefore = $form.attr('action');
            var targetBefore = $form.attr('target');
            var confirmEnabledBefore = self.formState.isConfirmEnabled();

            $form.attr('action', self.getAction());
            $form.attr('target', self.$preview.attr('name'));
            var $signature = $('<textarea/>').attr('name', 'signature').val(signature);
            $signature.appendTo($form);

            self.formState.disableConfirm();
            $form.submit();

            $signature.remove();
            $form.attr('action', actionBefore);
            $form.attr('target', targetBefore);

            if (confirmEnabledBefore) {
                self.formState.enableConfirm();
            } else {
                self.formState.disableConfirm();
            }
        },
        // 読み込み中出してしばらく知たら消す(雑)
        showEffect: function() {
            var self = this;
            self.$loading.fadeIn('fast');
            setTimeout(function () { self.$loading.fadeOut('fast') }, 1000);
        },
        // プレビューエンドポイント．indexとpermalinkのどちらか．
        getAction: function() {
            var self = this;
            var base = Hatena.Diary.data('blogs-uri-base');
            return base + '/preview/' + self.pageType + '_design';
        }
    };


    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'] = function () {
        var css       = $('#css');
        var form      = $('#form-design');
        var preview   = $('#preview');
        var loading   = $('#preview-loading');
        var $tabs      = $('#tabs');
        var $foldButton = $('#form-design-fold-button');

        var formState = new Hatena.Diary.FormState();
        formState.observeForm(form);
        formState.observeFormChange();

        var previewUpdater = new PreviewUpdater({
            $form: form,
            $preview: $('#preview-iframe'),
            $loading: loading,
            formState: formState
        });
        previewUpdater.requestPreview();

        form.on('change', function() {
            previewUpdater.requestPreview();
        });

        Hatena.Diary.Pages.Admin['user-blog-config-design']();
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTabs({
            $tabs: $tabs,
            previewUpdater: previewUpdater
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupFoldButton({
            $form: form,
            $preview: preview,
            $foldButton: $foldButton
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupPreviewTypeButton(previewUpdater);

        _.each([
            'header-html',
            'entry-header-html',
            'entry-footer-html',
            'footer-html',

            'header-touch-html',
            'entry-touch-header-html',
            'entry-touch-footer-html',
            'footer-touch-html'
        ], function(name) {
            var selector = ':input[name="' + name + '"]';
            var $target = $(selector);
            if (!$target.length) return;
            if ($target.prop('disabled')) return;
            Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupEditor({
                form:     form,
                syntax:   'html',
                textarea: $target
            });
        });

        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupEditor({
            form:     form,
            syntax:   'css',
            textarea: css
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupBackgroundComponent({
            css: css,
            form: form,
            loading : loading,
            preview: preview
        });
        var trimmingWindow = new TrimmingWindow($('.js-header-modal-window'));
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupHeaderImageComponent({
            $container: $('.js-design-header .js-header-image-container'),
            previewUpdater: previewUpdater,
            trimmingWindow: trimmingWindow
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTouchHeaderImageComponent({
            $container: $('.js-design-header-touch .js-header-image-container'),
            previewUpdater: previewUpdater
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupEntryComponent({
            css: css,
            form: form,
            loading : loading,
            preview: preview
        });

        var moduleEditor = new ModuleEditor($('.js-module-edit-modal-window'));
        var categoryEditor = new CategoryEditor();
        // 新規編集時とorder_type選択毎に更新
        $(moduleEditor).on('edit-new-module change-category-order-type', function () {
            categoryEditor.updateCategoryPreview();
        });

        _.each(['sidebar', 'top-page-main-column', 'top-page-header', 'top-page-sidebar'], function (type) {
            var $element = $('div[data-modules-type="' + type + '"].sidebar-box');
            if (!$element.length) return;
            var modules = new Modules($element, moduleEditor);
            $(modules).on('updated', function() {
                // FormState(ページ閉じる前にconfirm出すやつ)がformのchangeイベントを見ている
                form.trigger('change');
            });
        });
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupAccordion('.accordion-title');

        // プロフィールとサークルは通信してformを書き換える，書き換え終わった状態のフォームの値を初期状態としてセットする
        var profileUpdated = Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].updateProfileModule();
        var circlesUpdated = Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].updateCirclesModule();
        // カテゴリモジュール order_typeプレビュー初期状態
        categoryEditor.updateCategoryPreview();

        $.when(profileUpdated, circlesUpdated).always(function() {
            formState.setFormInitialState();
        });

        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupThemesListSwitcher();

        // スマフォ用テキストエリア，不要なときには隠しておく
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTextareaHider();

        // 背景画像もっと見る
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupSeeMoreBackgrounds();

        // スマフォ用アクセントカラー
        Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTouchAccentColor({
            $form: form
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupAccordion = function (selector) {
        var accordionTitle = $(selector);
        accordionTitle.next().hide();
        accordionTitle.click(function () {
            var $title   = $(this);
            var $content = $title.next();
            if ($content.is(':visible')) {
                $content.hide();
                $title.removeClass('open');
            } else {
                $content.show();
                $title.addClass('open');
            }
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTabs = function (args) {
        var $tabs      = args.$tabs;
        var previewUpdater = args.previewUpdater;
        var $forcePcView = $('#force-pc-view');

        if (!$tabs[0]) return;

        // タブ切り替えたらプレビューするデバイス切り替える
        // ただし，スマフォにPCのデザインを仕様するときは表示が崩れるので，PC版をプレビュー
        var updateDevice = function (event, ui) {
            var panelID = (ui.newPanel || ui.panel).attr('id');
            if (panelID === 'tab-customize-touch' && ! $forcePcView.is(':checked')) {
                previewUpdater.setDeviceAsTouch();
            } else {
                previewUpdater.setDeviceAsPC();
            }
        };

        $tabs.on('tabsactivate', updateDevice)
             .on('tabscreate', updateDevice);

        // PCのデザイン表示するかチェックボックスも監視する
        $forcePcView.on('change', function() {
            if ($forcePcView.is(':checked')) {
                previewUpdater.setDeviceAsPC();
            } else {
                previewUpdater.setDeviceAsTouch();
            }
        }).triggerHandler('change');

        $tabs.tabs();
    };

    // サイドバーを畳む機能
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupFoldButton = function (args) {
        var $form      = args.$form;
        var $preview   = args.$preview;
        var $foldButton = args.$foldButton;

        if (!$foldButton[0]) return;

        $foldButton.click( function () {
            if ($foldButton.hasClass('open')) {
                $foldButton.removeClass('open').addClass('close');
                $form.hide();
                $preview.addClass('fold-form');
            } else {
                $foldButton.removeClass('close').addClass('open');
                $form.show();
                $preview.removeClass('fold-form');
            }
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].fadeInLoading = function ($loading) {
        $loading.fadeIn('fast');
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].fadeOutLoading = function ($loading) {
        setTimeout(function () { $loading.fadeOut('fast') }, 1000);
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupPreviewTypeButton = function (previewUpdater) {
        var switchButton = $('.switch-button');

        switchButton.click ( function () {
            if (previewUpdater.getPageType() === 'index') {
                switchButton.addClass('permalink').removeClass('index');
                switchButton.text(Hatena.Locale.text('admin.design.quit_preview_entry_page'));
                previewUpdater.setAsPermalinkPreview();
                previewUpdater.preview();
            } else {
                switchButton.addClass('index').removeClass('permalink');
                switchButton.text(Hatena.Locale.text('admin.design.preview_entry_page'));
                previewUpdater.setAsIndexPreview();
                previewUpdater.preview();
            }

        });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupBackgroundComponent = function (args) {
        var css = args.css;
        var form = args.form;
        var preview = args.preview;

        var fileinput = $('input[type="file"].background-image');
        var bgImage = $('#background-image');
        var imageThumbnail = $('#background-image-thumbnail');
        var deleteBgImage = $('a.delete-background-image');
        var imageSrc = $('input[name="bg-image-src"]');
        var imageId = $('input[name="bg-image-id"]');
        var imageSelected = $('input[name="bg-image-selected"]');
        var styletemplate = _.template("body{ background-image: url('<%= image %>'); background-repeat: <%= repeat %>; background-color:<%= backgroundColor %>; background-attachment: <%= attachment %>; background-position: <%= position %> top;}");

        var bgPosition = $('select[name="background-position"]');
        var bgRepeat = $('select[name="background-repeat"]');
        var bgAttachment = $('select[name="background-attachment"]');

        var showBackgroundImage = function () {
            bgImage.show();
        };
        var hideBackgroundImage = function () {
            bgImage.hide();
        };

        deleteBgImage.click ( function () {
            if ( confirm(Hatena.Locale.text('admin.design.stop_header_image_confirm')) ) {
                imageId.val('');
                imageSrc.val('');
                imageSelected.val(0);
                setDesignCSS();

                hideBackgroundImage();
            }
            return false;
        });

        imageThumbnail.click ( function () {
            setDesignCSS();
            if ( ! imageThumbnail.hasClass('ui-selected') ) {
                // 背景画像の選択をはずす
                var backgroundListItems = $('#backgrounds li');
                backgroundListItems.removeClass('ui-selected');
                imageThumbnail.addClass('ui-selected');
                imageSelected.val(1);
            }
        });

        bgPosition.change ( function () {
            setDesignCSS();
        });

        bgAttachment.change ( function () {
            setDesignCSS();
        });

        bgRepeat.change ( function () {
            setDesignCSS();
        });

        // 背景画像のセット
        var setBackgroundImage = function (fid) {
            imageId.val(fid);
            var match = fid.match(/f:id:([^:]+):(\d+)([jpg]):image/);
            if (!match) return;

            var name  = match[1];
            var id    = match[2];
            var type  = match[3];
            var extension = { j : '.jpg', p : '.png', g : '.gif' };
            var path  = [ name.substring(0, 1), name, id.substring(0, 8), id ].join('/');
            var image = 'http://cdn-ak.f.st-hatena.com/images/fotolife/' + path + extension[type];
            var thumbnail_src = 'http://cdn-ak.f.st-hatena.com/images/fotolife/' + path + '_120.jpg';
            imageSrc.val(image);
            imageThumbnail.attr('src', thumbnail_src);
            showBackgroundImage();
            fileinput.prop('disabled', false);
            imageThumbnail.trigger('click');

            // fileinput.change契機でアップロードしている場合、fileinput.valueを空にしておかないと同じファイルを選択した時にchangeイベントが発火しないため、がんばって空にする
            var isSupportedFile = (typeof FormData != 'undefined');
            if (isSupportedFile) {
                var new_fileinput = fileinput.clone(true);
                fileinput.replaceWith(new_fileinput);
                fileinput = new_fileinput;
            }
        };

        var setDesignCSS = function () {
            var image = imageSrc.val();
            var design = new EditDesign(css.val());

            var id;
            var style;
            if ( image ) {
                var backgroundColorItem = $('#background-colors li.ui-selected');
                var backgroundColor = 'transparent';
                // 背景色が選択されていない場合はデフォルトを選択
                if ( backgroundColorItem.length === 0 ) {
                    $('#background-colors li[data-css=""]').addClass('ui-selected');
                } else if ( backgroundColorItem.attr('data-id') !== undefined ) {
                    backgroundColor = '#' + backgroundColorItem.attr('data-id');
                }
                id = 'custom';
                var repeat = bgRepeat.find('option:selected').val();
                var position = bgPosition.find('option:selected').val();
                var attachment = bgAttachment.find('option:selected').val();
                style = styletemplate({
                    image : image,
                    backgroundColor : backgroundColor,
                    repeat : repeat,
                    position : position,
                    attachment : attachment
                });
            } else { // 画像外したときはデフォルトに戻す
                id = 'default';
                style = $('li[data-id="default"]').attr('data-css');
            }

            design.setData('background', id, style);
            css.val(design.getCSS());
            css.trigger('change');
        };

        var isSupportedFile = (typeof FormData != 'undefined');
        if ( isSupportedFile ) {
            fileinput.change ( function () {
                if ( ! this.files.length ) return;
                hideBackgroundImage();
                Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].uploadImage({
                    file     : this,
                    folder   : "Hatena Blog",
                    fotosize : 3000,
                    input    : fileinput,
                    callback : setBackgroundImage
                });
            });
        } else {
            Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setIframeUploader({
                fileinput : fileinput,
                fotosize  : 3000,
                callback  : setBackgroundImage
            });
        }
    };

    // ヘッダ画像トリミングするモーダルウィンドウ
    var TrimmingWindow = function($container) {
        this.$container = $container;
        this.init();
    };
    TrimmingWindow.prototype = {
        init: function() {
            var self = this;
            // ページの末尾に移動する
            self.$container.appendTo(document.body);

            // sessionはトリミング中有効なDeferred，doneでトリミング成功，rejectで失敗
            self.session = $.Deferred();
            self.session.reject();

            self.jcrop = $.Jcrop(self.$container.find('.js-header-image-resizer'), {
                bgOpacity   :   '0.4',
                addClass    : 'jcrop-dark',
                allowSelect : false,
                keySupport  : false,
                allowResize : false
            });

            self.$container.on('click', '.js-header-image-apply-button', function() {
                self.save();
                return false;
            }).on('click', '.js-header-image-cancel-button', function() {
                self.cancel();
                return false;
            });
        },
        // 指定したURLの画像をトリミングする
        // returns: トリミング成功したらdone, キャンセルされたらrejectされるDeferred
        trim: function(url, area) {
            var self = this;
            self.cancel();
            self.session = $.Deferred();
            self.session.always(function() {
                self._hide();
            });

            self.jcrop.setImage(url, function() {
                self.jcrop.setSelect(area);
                self._show();
            });

            return self.session.promise();
        },
        // 以下は直接呼ぶことはないであろう
        save: function() {
            var self = this;
            self.session.resolve(self.jcrop.tellSelect());
        },
        cancel: function() {
            var self = this;
            self.session.reject(self.jcrop.tellSelect());
        },
        _show: function() {
            var self = this;
            Hatena.Diary.Window.show(self.$container, {
                center: true,
                showBackground: true,
                closeExplicitly: true
            });
        },
        _hide: function() {
            var self = this;
            Hatena.Diary.Window.hide(self.$container);
        }
    };

    var HeaderImagePreview = function($container) {
        this.$container = $container;
        this.jcrop = $.Jcrop(this.$container.find('.js-header-image-thumbnail'), {
            bgOpacity   :   '0.4',
            addClass    : 'jcrop-dark',
            allowSelect : false,
            allowResize : false,
            allowMove   : false
        });
    };

    HeaderImagePreview.prototype = {
        // url: オリジナル画像のURL
        // thumbnailUrl: サムネイルのURL
        // (area): トリミング位置 {x, y, x2, y2}
        render: function(url, thumbnailUrl, area) {
            var self = this;
            if (url) {
                self.jcrop.setImage(thumbnailUrl, function () {
                    if (area) {
                        self.setArea(url, thumbnailUrl, area);
                    }
                });
            } else if (area) {
                self.setArea(url, thumbnailUrl,  area);
            }
            self.$container.show();
        },
        clear: function() {
            var self = this;
            self.$container.hide();
        },
        // 元画像とサムネイルのサイズからサムネイルの表示位置を決める
        setArea: function(url, thumbnailUrl, area) {
            var self = this;

            Hatena.Diary.Util.loadImages([url, thumbnailUrl]).done(function(imgs) {
                var image = imgs[0];
                var thumbnail = imgs[1];

                var rateY = thumbnail.height / image.height;

                var thumbnailArea = [0, area.y * rateY, area.w, area.y2* rateY];
                self.jcrop.setSelect(thumbnailArea);
            });
        }
    };

    // ヘッダのinputの操作，更新するとupdatedイベント発行
    // display_areaはPC版のみに存在し，touch版にはない．
    // imageSize: {width, height}
    var HeaderImage = function($container, imageSize) {
        var self = this;
        self.imageSize = imageSize;
        self.$container = $container;
        self.$image_src = $container.find('.js-image-src');
        self.$image_id = $container.find('.js-image-id');
        self.$display_area = $container.find('.js-display-area');
        _.defer(function() {
            // 初回，observeまだかもしれないので，ちょっと待つ
            self.updated();
        });
    };
    HeaderImage.prototype = {
        setImage: function(src, id) {
            this.$image_src.val(src);
            this.$image_id.val(id);
            this.$display_area.val('');
            if (this.$display_area.length) {
                // トリミング位置あるときは，displayAreaが揃うまでは不完全な状態なのでupdateしない
            } else {
                // トリミング位置ないときはこの時点で完成なのでupdate
                this.updated();
            }
        },
        // displayArea: { x, y, x2, y2 }
        setDisplayArea: function(area) {
            this.$display_area.val(JSON.stringify(area));
            this.updated();
        },
        // 画像を外す
        clear: function() {
            this.$image_src.val('');
            this.$image_id.val('');
            this.$display_area.val('');
            this.updated();
        },
        getImageSrc: function() {
            return this.$image_src.val();
        },
        getThumbnailSrc: function() {
            return this.getImageSrc().replace(/\.(jpg|png|gif)$/, '_120.jpg');
        },
        getImageId: function() {
            return this.$image_id.val();
        },
        // displayArea: { x, y, x2, y2 }
        getDisplayArea: function() {
            var value;
            try {
                value = JSON.parse(this.$display_area.val());
            } catch(ignore) { }
            return value;
        },
        // trimmingArea: [ x, y, x2, y2 ] TrimmingWindowに渡す形式
        // 指定されていないときは左上からコンストラクタで指定されたサイズ
        getTrimmingArea: function() {
            var area = this.getDisplayArea();
            if (area) {
                return [ area.x, area.y, area.x2, area.y2 ];
            } else {
                return [0, 0, this.imageSize.width, this.imageSize.height];
            }
        },
        updated: function() {
            var self = this;
            $(self).triggerHandler('updated');
        }
    };

    // args: { $container, previewUpdater, trimmingWindow, imageSize: {width, height} }
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupHeaderImageComponent = function(args) {
        var $container = args.$container;
        var previewUpdater = args.previewUpdater;
        var trimmingWindow = args.trimmingWindow;
        var imageSize = {
            width:  + $container.attr('data-max-width'),
            height: + $container.attr('data-max-height')
        };

        var image = new HeaderImage($container, imageSize);
        var thumbnail = new HeaderImagePreview($container.find('.js-header-image-item'));

        $(image).on('updated', function() {
            if (image.getImageSrc()) {
                thumbnail.render(image.getImageSrc(), image.getThumbnailSrc(), image.getDisplayArea());
            } else if (!image.getImageSrc()) {
                thumbnail.clear();
            }
            previewUpdater.requestPreview();
        });

        var uploaded = Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupFotoUpload({
            $input: $container.find('.js-header-image-input'),
            size: imageSize.width
        });

        // アップロードされたら値設定，トリミングはキャンセルされても初回は必ずエリア設定する
        uploaded.progress(function(foto) {
            image.setImage(foto.url, foto.fid);
            trimmingWindow.trim(image.getImageSrc(), image.getTrimmingArea()).always(function(area) {
                image.setDisplayArea(area);
            });
        });

        $container.on('click', '.js-header-image-thumbnail, .jcrop-holder, .js-resizer', function() {
            // アップロード済の画像のトリミング位置変更
            trimmingWindow.trim(image.getImageSrc(), image.getTrimmingArea()).done(function(area) {
                image.setDisplayArea(area);
            });
            return false;
        }).on('click', '.js-delete-header-image', function() {
            // 画像外す
            if (!confirm(Hatena.Locale.text('admin.design.stop_header_image_confirm'))) return false;
            image.clear();
            return false;
        });
    };

    // スマフォ版のヘッダ画像，トリミング機構がないので単純
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTouchHeaderImageComponent = function(args) {
        var $container = args.$container;
        var previewUpdater = args.previewUpdater;
        var imageSize = {
            width:  + $container.attr('data-max-width'),
            height: + $container.attr('data-max-height')
        };

        var image = new HeaderImage($container, imageSize);

        var $imageItem = $container.find('.js-header-image-item');
        var $thumbnail = $container.find('.js-header-image-thumbnail');

        $(image).on('updated', function() {
            if (image.getImageSrc()) {
                $thumbnail.attr('src', image.getThumbnailSrc())
                          .show();
                $imageItem.show();
            } else {
                $thumbnail.hide();
                $imageItem.hide();
            }
            previewUpdater.requestPreview();
        });

        var uploaded = Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupFotoUpload({
            $input: $container.find('.js-header-image-input'),
            size: imageSize.width
        });

        // アップロードされたら値設定
        uploaded.progress(function(foto) {
            image.setImage(foto.url, foto.fid);
        });

        $container.on('click', '.js-delete-header-image', function() {
            // 画像外す
            if (!confirm(Hatena.Locale.text('admin.design.stop_header_image_confirm'))) return false;
            image.clear();
            return false;
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupEntryComponent = function (args) {
        var css = args.css;
        var form = args.form;
        var preview = args.preview;

        // 変数のヘルプ
        $('.js-variable-toggle').click(function(){
            $(this).siblings('.js-variable-help').slideToggle();
            return false;
        });
    };

    // フォトライフへ画像をアップロードの準備，コピペされまくってたののインターフェイス整理したやつ
    // args:
    //   $input: input type=fileのinput
    //   size: 画像の長辺
    // returns: アップロードが完了すると { syntax, url, thumbnail_url } がnotifyされるDeferred
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupFotoUpload = function(args) {
        var $input = args.$input;
        var size = args.size;

        var uploaded = $.Deferred();
        var isSupportedFile = (typeof FormData != 'undefined');

        var callback = function(fid) {
            var match = fid.match(/f:id:([^:]+):(\d+)([jpg]):image/);
            if (!match) return;
            var name  = match[1];
            var id    = match[2];
            var type  = match[3];
            var extension = { j : '.jpg', p : '.png', g : '.gif' };
            var path  = [ name.substring(0, 1), name, id.substring(0, 8), id ].join('/');
            var url = 'http://cdn-ak.f.st-hatena.com/images/fotolife/' + path + extension[type];
            var thumbnail_url = 'http://cdn-ak.f.st-hatena.com/images/fotolife/' + path + '_120.jpg';
            uploaded.notify({
                fid: fid,
                url: url,
                thumbnail_url: thumbnail_url
            });
        };

        if ( isSupportedFile ) {
            $input.on('change', function() {
                var input = this;
                if ( ! this.files.length ) return;
                Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].uploadImage({
                    file     : $input[0],
                    input    : $input,
                    folder   : "Hatena Blog",
                    fotosize : size,
                    callback : callback
                });
                return false;
            });
        } else {
            Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setIframeUploader({
                fileinput : $input,
                fotosize  : size,
                callback  : callback
            });
        }

        return uploaded.promise();
     };

    // フォトライフへ画像をアップロード
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].uploadImage = function (args) {
        var file = args.file;
        var folder = args.folder;
        var fotosize = args.fotosize;
        var input = args.input;
        var callback = args.callback;

        input.prop('disabled', true);

        var data = new FormData();
        data.append('rkm', Hatena.Diary.data('rkm'));
        data.append('append', 1);
        data.append('fototitle', "");
        data.append('folder', folder);
        data.append('fotosize', fotosize);
        data.append('image', file.files[0]);

        var grandparent = $(file).parent().parent();
        var progress = grandparent.find('.progress');
        progress.show();
        var bar = progress.find('div.bar');
        bar.width('0%');
        var percent = progress.find('div.percent');
        var updateProgress = function (progress) {
            if (progress > 100) progress = 100;
            bar.width(progress + '%');
            percent.text(Hatena.Locale.text('uploading'));
        };

        var xhr = new XMLHttpRequest();

        xhr.upload.addEventListener("progress", function (e) {
            var percent = e.lengthComputable ? (e.loaded / e.total * 100) : NaN;
            updateProgress( percent );
        }, false);

        xhr.addEventListener("load", function (e) {
            input.prop('disabled', false);
            input.val('');
            updateProgress( 100 );
            callback(xhr.responseText);
            progress.hide();
            _.defer(function() {
                updateProgress(0);
            });
        }, false);

        xhr.addEventListener("error", function (e) {
            progress.addClass('error');
            input.val('');
            percent.text('error');
            input.prop('disabled', false);
        }, false);

        xhr.open("POST", "/f/" + Hatena.Diary.data('name') + "/upbysmart");
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.send(data);
    };

    // IE用にiframeを設置
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setIframeUploader = function (args) {
        var fileinput = args.fileinput;
        var fotosize = args.fotosize;
        var callback = args.callback;

        var iframe = $('<iframe/>');
        fileinput.replaceWith(iframe);
        var src = "/api/upload/fotolife_smart";
        iframe.attr('src', src);
        iframe.addClass('uploader');
        iframe.load(function () {
            var document;
            if (iframe[0].contentDocument) {
                document = iframe[0].contentDocument;
            } else if (iframe[0].contentWindow) {
                document = iframe[0].contentWindow.document;
            } else {
                return;
            }
            if (document.body.innerHTML.match(/^\s*(f:id:\S+)/)) {
                iframe[0].contentWindow.location.replace(src);
            }
            callback(document.body.innerHTML);

            $(document).find('input[name="fotosize"]').val(fotosize);
            var images = $(document).find('input[type="file"]');
            $(images[0]).change ( function () {
                $(document).find('#fotolife-upload-form').submit();
                $(images[0]).replaceWith($('<h5>').text(Hatena.Locale.text('uploading')));
            });
        });
    };

    // FacebookやTwitterとの連携をしているかを確認し、プロフィールモジュールを更新
    // 更新が終わるとresolveされるDeferredを返す
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].updateProfileModule = function () {
        var updated = $.Deferred();

        $.ajax({
            type: 'GET',
            url: '/api/applications_data',
            dataType: 'json'
        }).done(function (res) {
            var data = res;
            var $profile_modules = $('.js-module-value-component-profile');

            $profile_modules.each(function() {
                var $profile_module = $(this);

                if ( data.twitter ) {
                    $profile_module.find('.cannot-twitter-button').remove();
                } else {
                    $profile_module.find('.can-twitter-button').remove();
                    $profile_module.find('.cannot-twitter-button').removeClass('cannot-twitter-button').addClass('cannot-twitter-button-display');
                }

                if ( data.facebook ) {
                    $profile_module.find('.cannot-facebook-follow').remove();
                    $profile_module.find('.cannot-facebook-subscribe').remove();
                } else {
                    $profile_module.find('.can-facebook-follow').remove();
                    $profile_module.find('.can-facebook-subscribe').remove();
                    $profile_module.find('.note').remove();
                    $profile_module.find('.cannot-facebook-follow').removeClass('.cannot-facebook-follow').addClass('.cannot-facebook-follow-display');
                    $profile_module.find('.cannot-facebook-subscribe').removeClass('cannot-facebook-subscribe').addClass('cannot-facebook-subscribe-display');
                }
            });

            updated.resolve();
        }).fail(function() {
            updated.reject();
        });

        return updated.promise();
    };

    // サークルモジュールを更新
    // 更新が終わるとresolveされるDeferredを返す
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].updateCirclesModule = function () {
        var updated = $.Deferred();
        if ($('#module-value-component-circles').length === 0) {
            updated.resolve();
            return updated.promise();
        }

        $.ajax({
            type: 'GET',
            url: '/api/circles',
            data: { blog: Hatena.Diary.data('blogs-uri-base')  },
            dataType: 'json'
        }).done(function (res) {
            var mkSelectCircle = _.template($('.js-module-circles-select-circles-template').html().replace(/^\s+|\s+$/g, ''));
            _.each(res.circles, function (circle) {
                $('.js-select-circles-container').each(function() {
                    $(this).append($(mkSelectCircle({ circle: circle })));
                });
            });
            updated.resolve();
        }).fail(function() {
            updated.reject();
        });

        return updated.promise();
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupEditor = function (args) {
        var form     = args.form;
        var syntax   = args.syntax;
        var textarea = args.textarea;

        if (!textarea[0]) return;

        var container = document.createElement('div');
        $(container)
            .css({
                position: 'absolute',
                top: 'auto',
                left: 0,
                bottom: 50,
                padding: 0,
                margin: 0,
                borderTop: '1px solid #ccc',
                borderBottom: '1px solid #ccc',
                width: '500px',
                height: '400px',
                zIndex: 9999,
                background: '#fff'
            }).
            appendTo(document.body).
            hide();

        textarea.css({
            'font-size': '11px',
            'white-space': 'nowrap',
            'overflow': 'hidden'
        });

        var editor = ace.edit(container);
        editor.commands.removeCommand('gotoline'); // fucking default keybinding of ace
        editor.commands.removeCommand('indent');
        editor.commands.removeCommand('outdent');

        // editor.renderer.setShowGutter(false);
        editor.renderer.setHScrollBarAlwaysVisible(false);
        editor.renderer.setPadding(5);
        editor.renderer.setShowPrintMargin(false);

        editor.setFontSize("10px");
        editor.setHighlightActiveLine(false);

        var Mode = require('ace/mode/' + syntax).Mode;
        var mode = new Mode();

        var session = editor.getSession();
        session.setMode(mode);
        session.setUseWrapMode(true);

        var editorState = new Hatena.Diary.FormState();

        textarea.focus(function () {
            $(container).show();
            editor.resize();
            editor.focus();
            editorState.enableConfirm();
        });

        editor.on('blur', function () {
            textarea.val(session.getValue());
            textarea.trigger('change');
            $(container).hide();
            editorState.disableConfirm();
        });

        $(container).mousedown(function () { return false });

        session.setValue(textarea.val());

        textarea.change(function () {
            session.setValue(textarea.val());
        });

        $('#tabs').on('tabsactivate', function () {
            setTimeout(function () { editor.resize() }, 0);
        });

        $(window).resize(function () { editor.resize() });
    };

    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupThemesListSwitcher = function () {
        $('.switch-theme-list-types').on('blog:dropdown:selected', '[data-theme-list-type]', function () {
            var listType = $(this).attr('data-theme-list-type');
            $('#themes .themes-container').each(function () {
                $(this).toggle($(this).attr('data-theme-list-type') === listType);
            });
        });

        // 以下は同じような構造だったら使えるので
        // そのまま ['*'] に置いてもいいです。
        var $dropdown     = $('.dropdown-container'),
            $dropdownList = $dropdown.find('.dropdown-list').hide();
        $dropdown
            .on('click', '.dropdown-button, .dropdown-selected', function () {
                var isShown = Hatena.Diary.Window.toggle($dropdownList);
                $dropdownList.toggleClass('opened', isShown);
                return false;
            })
            .on('click', '.dropdown-list-item', function () {
                $dropdown.find('.dropdown-selected').text($(this).text());
                $(this).trigger('blog:dropdown:selected');
            })
            .find('.dropdown-list-item').eq(0).click();
    };

    // スマフォ用HTML編集欄の制御，設定によっては書ける，PC版と同じ内容を表示するモードのときはテキストエリア出さない
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTextareaHider = function () {
        _.each([
            ['header-touch-show-html-for-pc' , '.js-hide-on-header-touch-show-html-for-pc'],
            ['display-touch'                 , '.js-hide-on-display-touch'],
            ['footer-touch-show-html-for-pc' , '.js-hide-on-footer-touch-show-html-for-pc'],
            ['header-touch-show-image-for-pc' , '.js-hide-on-header-touch-show-image-for-pc']
        ], function(rule) {
            var input_selector = rule[0];
            var target_selector = rule[1];

            var $input = $(':input[name=' + input_selector + ']');
            if (!$input.length) return;

            var $target = $(target_selector);
            if (!$target.length) return;

            var updateVisibility = function() {
                var $checked_input = $(':checked[name=' + input_selector + ']');
                if (!$checked_input.length) return;
                if (+$checked_input.val()) {
                    $target.hide();
                } else {
                    $target.show();
                }
            };

            // 変更を監視
            // IEではchangeイベントの直後に見ると古い値が取れることがあるのでちょっと待ってる
            $input.on('change', function() {
                _.defer(updateVisibility);
            });

            // 初期状態のセットアップ
            updateVisibility();
        });
    };

    // 昔の背景画像，最初は隠しておいて，もっと読む押したら見せる
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupSeeMoreBackgrounds = function() {
        var $button = $('.js-show-more-background-images');
        $button.one('click', function() {
            $button.remove();
            $('#backgrounds li:hidden').show();
        });
    };

    // アクセントカラー設定UI
    Hatena.Diary.Pages.Admin['user-blog-config-design-detail'].setupTouchAccentColor = function(args) {
        var $form = args.$form;
        var $accent_color_input = $form.find(':input[name="touch-accent-color"]');

        var $colors = $('#touch-accent-colors');

        var select = function($color) {
            $colors.find('.selected').removeClass('selected');
            $color.addClass('selected');
            var color = $color.attr('data-color');
            $accent_color_input.val(color);
            $form.trigger('change');
        };

        $colors.on('click', '[data-color]', function() {
            select($(this));
        });

        var first_value = $accent_color_input.val();
        select($colors.find('[data-color="' + first_value + '"]'));
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-config-design'] = function () {
        var css     = $('#css');
        var form    = $('#form-design');

        // themes
        var themeListItems = $('#themes li');
        themeListItems.addClass('ui-selectee').click(function (e) {
            var link = $(this).attr('data-css').replace(/\s+/g, ' ');
            var id   = $(this).attr('data-id');

            var design = new EditDesign(css.val());
            design.setData('theme', id, '@import "' + link + '";');
            css.val(design.getCSS());
            css.trigger('change');

            themeListItems.removeClass('ui-selected');
            $(this).addClass('ui-selected');
        });

        var bgImageThumbnail = $('#background-image-thumbnail');
        // background-image
        var backgroundListItems = $('#backgrounds li');
        // background-color
        var backgroundColorListItems = $('#background-colors li');

        backgroundListItems.addClass('ui-selectee').click(function (e) {
            var style = $(this).attr('data-css').replace(/\s+/g, ' ');
            var id    = $(this).attr('data-id');

            var design = new EditDesign(css.val());
            design.setData('background', id, style);
            css.val(design.getCSS());
            css.trigger('change');

            backgroundListItems.removeClass('ui-selected');
            backgroundColorListItems.removeClass('ui-selected');
            $(this).addClass('ui-selected');
            // アップロードした背景画像からもクラスを外す
            bgImageThumbnail.removeClass('ui-selected');
            $('input[name="bg-image-selected"]').val(0);
        });

        backgroundColorListItems.addClass('ui-selectee').click(function (e) {
            var style = $(this).attr('data-css').replace(/\s+/g, ' ');
            var id    = $(this).attr('data-id');
            var design = new EditDesign(css.val());

            // カスタム背景画像が選択されていて，かつ，CSSに，背景画像の設定が書かれている場合は、background-colorだけ変える
            // CSSに既存の背景画像の設定が書かれていないときは単に背景色を設定する
            var backgroundContent = design.getData('background').content;
            if ( bgImageThumbnail.hasClass('ui-selected') && backgroundContent ) {
                style = backgroundContent.replace(/background-color:(.*?);/, 'background-color:#' + id + ';');

                id = "custom";
            }
            backgroundListItems.removeClass('ui-selected');

            design.setData('background', id, style);
            css.val(design.getCSS());
            css.trigger('change');

            backgroundColorListItems.removeClass('ui-selected');
            $(this).addClass('ui-selected');
        });

        var design = new EditDesign(css.val());

        // for backward compatibility :: delete later
        new function () {
            if (/<system/.test(design.css)) return;

            var changed = false;

            design.css = design.css.replace(/@import "\/css\/theme\/([^\/]+)\/\1.css";/, function (_, id) {
                changed = true;
                return '/* <system section="theme" selected="' + id + '"> */\n' + _ + '\n/* </system> */\n';
            });

            design.css = design.css.replace(RegExp('\n?/\\*system:background\\*/(.*)'), function (_, style) {
                changed = true;
                design.setData('background', 'unknown', style);
                return '';
            });

            if (changed) {
                design.setCSS(design.css);
                css.val(design.getCSS());
                css.trigger('change');
            }
        } ();

        var currentTheme = design.getData('theme').selected;
        if (currentTheme) {
            themeListItems.filter('[data-id="' + currentTheme + '"]').addClass('ui-selected');
        } else {
            themeListItems.removeClass('ui-selected');
        }

        var currentBackground = design.getData('background').selected;
        if (currentBackground) {
            $('#backgrounds, #background-colors').find('[data-id="'+currentBackground+'"]').addClass('ui-selected');
        } else {
            backgroundListItems.removeClass('ui-selected');
        }

    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-config-detail'] = function () {
        $('.main-tab').find('.user-blog-config-detail').addClass('current-tab');

        $('#blog-config-custom-domain .check-validity').click(function (e) {
            var $this = $(this);
            $this.attr('disabled', 'disabled').addClass('disabled');
            $('#blog-config-custom-domain .validity-status').text('-');
            $.ajax({
                type: 'POST',
                url: '/api/custom_domain.check',
                data: $this.closest('form').serialize(),
                dataType: 'json',
                success: function (data) {
                    $('#blog-config-custom-domain .validity-status').text(data.message);
                    $('#blog-config-custom-domain .validity-status.detail').text(data.detail || '');
                },
                complete: function () {
                    $this.removeAttr('disabled').removeClass('disabled');
                }
            });
            return false;
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-config-external'] = function () {
        var withParentWindow = Hatena.Diary.Location.param('with_parent_window');
        var callback = Hatena.Diary.Location.param('callback');

        // 親windowがあって、OAuth認証から戻ってきた時はwindowを閉じる
        if (withParentWindow && callback) {
            window.close();
        }
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-config-permission'] = function () {
        var $authconfigs = $('.permission-authconfigs');
        var $permission_custom = $('#permission-custom');
        $('#new-authconfig').click(function () { $('#create-authconfig').submit(); });

        if ($('#viewable-id-select').length > 0) {
            // 既存の認証セットあるとき選択にあわせて対応する編集リンクなどを出したり消したりする
            $('#viewable-id-select').change(function () {
                var selected = $(this).find('option:selected');
                var detail_id = selected.attr('data-ac');
                $authconfigs.find('.authconfig-detail').addClass('hide');
                $authconfigs.find('.' + detail_id).removeClass('hide');
            }).change();
        } else {
            // 既存の認証セットないときは新しい公開範囲を作成ボタンだけ表示
            $('.authconfig-detail-new').show();
        }

        $('[name="permission"]').change(function () {
            if ($('#permission-public').prop('checked')) {
                $('.config-private-overlay').show();
            } else {
                $('.config-private-overlay').hide();
            }

            // 公開範囲設定を隠すのは，カスタムが選択可能で，かつ，チェックされていないとき
            if (!$permission_custom.attr('disabled') && !$permission_custom.prop('checked')) {
                $('#permission-custom-viewable-id').hide();
            } else {
                $('#permission-custom-viewable-id').show();
            }
        }).change();
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-config-theme-theme_id-preview'] = function () {
        var $previewForm = $('#theme-preview-form');
        var $saveForm     = $('#theme-install-form');
        var noticeMessage = $saveForm.find('.notice').text();

        $saveForm.on('submit', function () {
            return confirm(noticeMessage);
        });

        $previewForm.submit();
    };

})(jQuery);

// 投稿時の共有するボタンに関連した処理を扱う
(function($) {
    Hatena.Diary.SocializeBox = {
        setup: function() {
            var self = this;

            // 外部連携設定用
            self.setupExternalAuthLink();

            // SNS投稿input 変化したらlabelにクラス設定
            $('.js-social-buttons input').on('change', function () {
                var $input = $(this);
                var $label = $input.closest('label');
                $label.toggleClass('checked', $input.prop('checked'));
                // 諸事情あって無効化
                // self.saveConfig($input.attr('name'), $input.prop('checked'));
            });
            // 初期状態
            $('.js-social-buttons input').trigger('change');
        },
        // シェアするサービスが変化したら保存する
        saveConfig: function(name, checked) {
            // socializeにPOSTする場合はinputのnameがpost_to_twitterではなくtwitter
            if (!name.match(/^post_to/)) {
                name = 'post_to_' + name;
            }
            Hatena.Diary.Pages.Admin['*'].saveBlogConfig(name, checked ? '1' :  '0');
        },
        setupExternalAuthLink: function() {
            var self = this;

            // Bパターンのみ、連携リンクやボタンクリックで新しいwindowが開くように
            var external_auth_href = $('.js-socialize-box .js-link-to-settings a').attr('href') || $('.js-socialize-modal').attr('data-external-auth-href');
            var $external_auth_message = $('.js-socialize-box .js-external-auth-message');
            var $external_auth_finish_message = $('.js-socialize-box .js-external-auth-finish-message');

            $('[data-open-external-auth-link=1]').on('click', function (e) {
                e.preventDefault();

                var options = { width:900, height:600, scrollbars: 'yes' };
                options.left = Math.floor((screen.width - options.width) / 2);
                options.top  = Math.floor((screen.height - options.height) / 2);
                var external_auth_window = window.open(
                    external_auth_href,
                    'external_auth',
                    Hatena.Diary.Util.positionToPositionString(options)
                );

                // 連携完了したらwindowが閉じられるので監視
                // ソーシャルボタンの状態更新をする
                Hatena.Diary.Util.waitForResource(function () {
                    return external_auth_window.closed;
                }, function () {
                    var $modal = $('.js-socialize-modal');
                    // modalがあったら閉じる
                    if ($modal.length > 0) {
                        $modal.hide();
                        $('.modal-window-background').fadeOut('fast');
                    }

                    // 連携情報を再取得し、更新
                    self.getExternalAuthStatus().done(function (data) {
                        var isAuthorized = self.isExternalAuthorizeFinished(data);
                        if (isAuthorized) {
                            // 連携完了したら適切なメッセージを表示
                            $external_auth_message.hide();
                            $external_auth_finish_message.show();
                        }

                        self.updateSocialButtonsAvailable(data);
                    });
                });

                return false;
            });
        },
        updateSocialButtonsAvailable: function (externalAuthStatus) {
            var changeButtonStatus = function ($button, isEnabled) {
                var $input = $button.find('input');
                var prevIsDisabled = $button.hasClass('disable');

                if (isEnabled) {
                    $button.removeClass('disable');
                    $input.removeAttr('disabled');

                    // 新しく認証された場合はチェックを付ける
                    if (prevIsDisabled) {
                        $input.prop('checked', true);
                    }
                }
                else {
                    $button.addClass('disable');
                    $input.attr('disabled', 'disabled');
                    $input.prop('checked', false);
                }

                $input.trigger('change');
            };

            var $twitter   = $('.js-social-buttons li.twitter');
            var $facebook  = $('.js-social-buttons li.facebook');
            var $mixiCheck = $('.js-social-buttons li.mixi-check');

            changeButtonStatus($twitter, externalAuthStatus.twitter);
            changeButtonStatus($facebook, externalAuthStatus.facebook);
            changeButtonStatus($mixiCheck, externalAuthStatus.mixi_check);
        },

        // 外部連携情報を受け取って、連携完了したか調べる
        isExternalAuthorizeFinished: function (externalAuthStatus) {
            var $twitter   = $('.js-social-buttons li.twitter');
            var $facebook  = $('.js-social-buttons li.facebook');
            var $mixiCheck = $('.js-social-buttons li.mixi-check');

            // ボタンがdisableのものが有効になれば連携完了
            return ($twitter.hasClass('disable') && externalAuthStatus.twitter) ||
                   ($facebook.hasClass('disable') && externalAuthStatus.facebook) ||
                   ($mixiCheck.hasClass('disable') && externalAuthStatus.mixi_check);
        },

        // 外部連携情報を取得する
        getExternalAuthStatus: function () {
            var dfd = $.Deferred();
            $.ajax({
                url: '/api/applications_data',
                type: 'GET',
                dataType: 'json'
            }).done(function (data) {
                dfd.resolve(data);
            }).fail(function () {
                dfd.reject();
            });

            return dfd.promise();
        }
    };
})(jQuery);

(function($){
    Hatena.Diary.Pages.Admin['user-blog-edit-done'] = function () {
        Hatena.Diary.Pages.createForParent();

        var entry = document.getElementById('posted').value;
        Hatena.Diary.Pages.send('update', { entry : entry });

        $('.js-button-focus-this').focus();

        Hatena.Diary.SocializeBox.setup();

        // deactivate click-jacking-escape in 1000msec
        setTimeout(function () {
            $('form').each(function () {
                var $this    = $(this);
                var $buttons = $this.find('input[type=submit]');
                $this.removeClass('unedited');
                $buttons.removeAttr('disabled');
            });
        }, 1000);
        // proになりませんかモーダル
        Hatena.Diary.setupProModal();

        var modal = new ExternalAuthModalHandler($('.js-socialize-modal'));
    };

    var ExternalAuthModal = function() {};
    ExternalAuthModal.prototype = {
        setModalDisabled: function () {
            try {
              localStorage['Hatena.Diary.Admin.User.Blog.Edit.Done.ExternalAuthModal.disabled'] = true;
            } catch(ignore) {}
        },

        isModalDisabled: function () {
            try {
                var is_disabled = localStorage['Hatena.Diary.Admin.User.Blog.Edit.Done.ExternalAuthModal.disabled'];
                return is_disabled === 'true' ? true : false;
            } catch(ignore) {}
        }
    };

    var ExternalAuthModalHandler = function($el) {
        this.init($el);
    };
    ExternalAuthModalHandler.prototype = {
        init: function ($el) {
            var self = this;

            self.$el   = $el;
            self.modal = new ExternalAuthModal();

            // modalがあるかつ非表示にしていなかったら表示する
            if (self.$el.length && !self.modal.isModalDisabled()) {
                self.showModal();
            }

            // modal内をclickすると閉じてしまうため止めている
            // checkboxとか押した瞬間閉じられると困る
            self.$el.on('click', function(event) {
               event.stopPropagation();
            });

            // スキップボタン押されたら閉じる
            self.$el.on('click', '.js-skip-button', function () {
                // 次回から表示しないにチェックが入っていたら
                // ローカルストレージに値をセットする
                if (self.$el.find('.js-non-display-checkbox').prop('checked')) {
                    self.modal.setModalDisabled();
                }
                self.hideModal();
                return false;
            });
        },

        showModal: function () {
            Hatena.Diary.Window.show(this.$el, { center: 1, showBackground: true });
        },

        hideModal: function () {
            Hatena.Diary.Window.hide(this.$el);
        }

    };




})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-edit'] = function () {
        if (window.parent != window) {
            Hatena.Diary.Pages.createForParent();
            Hatena.Diary.Pages.send('ready');
        }

        var title            = $('#title');
        var count            = $('#character-count');
        var container        = $('#editor');
        var form             = $('#edit-form');
        var main             = $('#editor-main');
        var supportContainer = $('#editor-support-container');
        var supportItems     = $('#items');
        var curations        = $('#editor .curation-tab-content');

        var formState = new Hatena.Diary.FormState();
        formState.observeForm(form);

        var editor = new Hatena.Diary.Editor(form);
        editor.bind('initialize', function () {
            formState.setFormInitialState();
        });
        editor.trigger('initialize');

        editor.bind('change', function () {
            formState.checkFormState();
            var c = editor.getCharacterCount();
            count.text(Hatena.Locale.textN('edit_form.character_count_unit', c, c));

            if (window.parent != window) Hatena.Diary.Pages.send('change', formState.isConfirmEnabled());
        });
        setTimeout(function () { editor.focus() }, 100);

        title.on('keydown', function(event) {
            if(keyString(event) === 'RET') {
                editor.focus();
                return false;
            }
        });

        editor.form.submit(function() {
            var submitButton = editor.form.find(':submit');
            var disable = function() {
                editor.form.addClass('unedited');
                submitButton.attr('disable', 'disable');
            };
            var enable = function() {
                editor.form.removeClass('unedited');
                submitButton.removeAttr('disable');
            };

            var maxLength = 655360; // 2^16 * 10 までとする
            if (editor.getByteCount() > maxLength) {
                disable();
                editor.bind('change', enable);
                alert(Hatena.Locale.text('edit_form.body_length_exceeded_error'));
                return false;
            } else { // 文字数制限にひっかからず、投稿に成功する場合
                Hatena.Diary.Util.preventDuplicateSubmit($(editor.form));

                if (window.parent != window) Hatena.Diary.Pages.send('change', false);
            }
        });

        Hatena.Diary.Editor.Support.currentEditor = editor;
        Hatena.Diary.currentCategoryEditor =
            new Hatena.Diary.Pages.Admin['user-blog-edit'].CategoryEditor(form, '#entry-categories');

        new Hatena.Diary.Pages.Admin['user-blog-edit'].OgImageEditor(form, '#og-image');

        var datetimeEditor = new Hatena.Diary.Pages.Admin['user-blog-edit'].DateTimeEditor(form, '#datetime-input');
        Hatena.Diary.Pages.Admin['user-blog-edit'].observeForScheduledEntry(datetimeEditor);

        // setupGooglePicker()では，EditorSidebar.setup()で呼ばれるtriggerイベントをDOMに設定しているので，
        // EditorSidebar.setup()よりも前に呼ばれる必要がある．
        Hatena.Diary.Pages.Admin['user-blog-edit'].setupGooglePicker();

        Hatena.Diary.Pages.Admin['user-blog-edit'].EditorSidebar.setup();

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupResizeEditor({
            main: main,
            editor: editor,
            curations: curations,
            supportItems: supportItems
        });

        new Hatena.Diary.Pages.Admin['user-blog-edit'].AmazonSearch({
            container: $('#editor-amazon-search')
        });

        // 初心者タブがあるなら、自動的に初心者タブを表示する
        var $beginnerTab = $('.curation-bar-itemlist .beginner');
        if ( $beginnerTab.length > 0 ) {
            if ( ! $beginnerTab.hasClass('active') ) {
                $beginnerTab.trigger('click');
            }
            $('.twitter-open-button').click ( function () {
                $('.curation-bar-itemlist .twitter').trigger('click');
                return false;
            });
        }

        if ($('#editor-twitter').hasClass('enabled')) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Twitter({
                container: $('#editor-twitter')
            });
        }

        new Hatena.Diary.Pages.Admin['user-blog-edit'].HatenaBookmark({
            container: $('#editor-hatena-bookmark')
        });

        Hatena.Diary.Pages.Admin['user-blog-edit'].Fotolife.init();
        Hatena.Diary.Pages.Admin['user-blog-edit'].Paint.init();

        if ($('#editor-itunes.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Itunes({
                container: $('#editor-itunes')
            });
        }

        if ($('#editor-archive.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Archive({
                container: $('#editor-archive')
            });
        }

        if ($('#editor-instagram.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Instagram({
                container: $('#editor-instagram')
            });
        }

        if ($('#editor-evernote.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Evernote({
                container: $('#editor-evernote')
            });
        }

        if ($('#editor-pixiv.enabled').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Pixiv({
                container: $('#editor-pixiv')
            });
        }

        new Hatena.Diary.Pages.Admin['user-blog-edit'].Miil({
            container: $('#editor-miil')
        });

        new Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet({
            container: $('#editor-gourmet')
        });

        new Hatena.Diary.Pages.Admin['user-blog-edit'].Nicovideo({
            container: $('#editor-nicovideo')
        });

        new Hatena.Diary.Pages.Admin['user-blog-edit'].Gist({
            container: $('#editor-gist')
        });

        new Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr({
            container: $('#editor-flickr')
        });

        if ($('.promotion-entry').get(0)) {
            new Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion({
                $element: $('.promotion-entry-container'),
                $buttons: $('.promotion-button'),
                $cancelButtons: $('.promotion-cancel-button'),
                $pager: $('.promotion-pager-markers')
            });
        }

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome();

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupOgDescriptionInput(editor);

        var embedBox = new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox({
            $container: $('.js-editor-embed-box')
        });

        // URLがpasteされるとイベント発生する
        // イベント拾ってURL貼り付けボックスを開く
        // キャンセルされたらURLをエディタに挿入
        // オプトアウトされてるときも，そのままURLをエディタに挿入
        $(editor).on('paste-url', function(event, url) {
            if (embedBox.isEnabledOnPasteURL()) {
                embedBox.setURL(url);
                var session = embedBox.show();
                embedBox.requestPreview();
                session.fail(function() {
                    editor.insert(url);
                });
                Hatena.Diary.trackEvent('EmbedBox.showFromPaste');
            } else {
                editor.insert(url);
            }
        });

        Hatena.Diary.SocializeBox.setup();
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome = function() {

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupEditMode();

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupButtons();

        Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupButtonActive();
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupEditMode = function() {
        var $home = $('#editor-home');

        $home.on('click', 'button.toggle-edit-mode', function(event) {
            var $button = $(this);

            if ($button.text().match(Hatena.Locale.text('edit_tab'))) {
                $button.text(Hatena.Locale.text('done'));
            } else {
                $button.text(Hatena.Locale.text('edit_tab'));
            }

            $home.find('.config').slideToggle(300);
        });
    };

    // ショートカットボタンを配置するチェックボックスが変化したら記録
    Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupButtons = function () {

        var $home = $('#editor-home');
        $home.on('change', 'input', function(event) {
            var $input = $(this);
            var $service = $input.closest('.service');
            var service_id = $service.attr('data-service-id');

            var show = $input.prop('checked') ? 1 : 0;

            $.ajax({
                url: 'edit_sidebar_button',
                type: 'POST',
                data: {
                    service_id: service_id,
                    show: show,
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                }
            }).done(function(res) {
                $('.curation-bar-itemlist').replaceWith(res);
            });
        });
    };

    // サービス名にホバーしたときアイコンにも色つける
    Hatena.Diary.Pages.Admin['user-blog-edit'].setupEditorSidebarHome.setupButtonActive = function () {
        var $home = $('#editor-home');
        $home.on('mouseenter', '.about', function() {
            var $about = $(this);
            $about.find('.curation-itemlist').addClass('active');
        }).on('mouseleave', '.about', function() {
            var $about = $(this);
            $about.find('.curation-itemlist').removeClass('active');
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].setupResizeEditor = function (args) {
        var main         = args.main;
        var editor       = args.editor;
        var supportItems = args.supportItems;
        var curations    = args.curations;
        if (!main) { return }

        $(window).resize(_.throttle(function () {
            var mainHeight = $(window).height() - main.offset().top;
            var buttonsHeight = 100;
            editor.setHeight(mainHeight - buttonsHeight);

            curations.height(mainHeight);
        })).resize();
    };

    // 編集サイドバーの開閉，サービスの切り替え，configに保存
    // publicなメソッドは外から呼んでもよい
    Hatena.Diary.Pages.Admin['user-blog-edit'].EditorSidebar = {
        setup: function() {         // public
            this.$editor = $('#editor');
            this.$container = $('#editor-support-container');
            this.$services = this.$container.find('.services');
            this.$header = this.$container.find('.header');
            this.$footer = this.$container.find('.footer');

            this.bindEvents();
            this.restoreLastStatus();
        },
        bindEvents: function() {
            var self = this;

            self.$container.on('click', '.curation-bar-toggle', function(event) {
                self.toggle();
                return false;
            });

            self.$container.on('click', '[data-support-type]', function(event) {
                var clickedType = $(this).attr('data-support-type');
                self.openByType(clickedType);
                return false;
            });

            $(window).resize(_.throttle(function () {
                var mainHeight = $(window).height() - $('#editor-main').offset().top;
                self.$services.height(
                    mainHeight -
                        self.$header.outerHeight(true) -
                        (self.$services.outerHeight(true) - self.$services.height()) * 2
                );
            })).resize();

        },
        restoreLastStatus: function() {
            var lastStatus = this.$editor.attr('data-support-type');

            this.openByType(lastStatus);
        },
        isOpening: function() {
            return $(document.body).hasClass('support-shown');
        },
        toggle: function() {        // public
            if (this.isOpening()) {
                this.close();
            } else {
                this.openByType('editor-home');
            }
        },
        openByType: function(type) { // public
            if (!type) {
                this.close();
                return;
            }
            var $content = this.$container.find('#' + type);
            if (!$content.get(0)) return this.close();

            // 表示中の要素消す
            var $previous_button = this.$container.find('.curation-itemlist.active');
            $previous_button.removeClass('active');
            $previous_button.removeClass($previous_button.attr('data-icon-class-when-active'));
            $previous_button.addClass($previous_button.attr('data-icon-class'));

            this.$container.find('.curation-tab-content').hide();

            // 表示
            $(document.body).addClass('support-shown');

            var $button = this.$container.find('.curation-itemlist[data-support-type=' + type + ']');
            $button.addClass('active');
            $button.removeClass($button.attr('data-icon-class'));
            $button.addClass($button.attr('data-icon-class-when-active'));

            $content.show();
            $content.triggerHandler('show');

            this.save(type);
        },
        close: function() {         // public
            $(document.body).removeClass('support-shown');

            var $previous_button = this.$container.find('.curation-itemlist.active');
            $previous_button.removeClass('active');
            $previous_button.removeClass($previous_button.attr('data-icon-class-when-active'));
            $previous_button.addClass($previous_button.attr('data-icon-class'));

            this.save('0');
        },
        save: function(value) {
            $(window).trigger('resize');

            Hatena.Diary.Pages.Admin['*'].saveBlogConfig('support', value);
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].setupGooglePicker = function() {
        var developerKey    = 'AIzaSyBT5jC9eFqTXg7df8nRpVEd-oRuOm5nfHA';
        var clientId        = '900568370540-qrvm1v1gtndg5krpn3mgjvfm28rontj0.apps.googleusercontent.com';
        var scope           = ['https://www.googleapis.com/auth/photos'];
        var pickerApiLoaded = false;
        var oauthToken;

        // googlePickerApiをロードする．googlePickerを利用するには，まずこれでApiをロードする必要がある．
        // oauth認証が必要ないpickerであれば，これを呼ぶだけで利用できる．
        var googlePickerApiLoad = function () {
            var d = new $.Deferred();

            // 既にロード済みの場合は再びロードしない
            if (pickerApiLoaded) {
                d.resolve();
            } else {
                gapi.load( 'picker', {'callback': function() {
                    pickerApiLoaded = true;
                    d.resolve();
                }});
            }

            return d.promise();
        };
        // googlePickerのoAuth認証が必要な場合はこれを呼ぶ．
        var googlePickerApiAuth = function () {
            var d = new $.Deferred();

            // 既にアクセストークンを得ている場合は再び認証しない．
            if (oauthToken) {
                d.resolve();
            } else {
                gapi.load( 'auth', {'callback': d.resolve} );
            }

            return d.promise();
        };
        // ユーザ認証画面を出す場合にこれを呼ぶ．
        var googlePickerUserAuth = function () {
            var d = new $.Deferred();

            // 既にアクセストークンを得ている場合は再び認証しない．
            if (oauthToken) {
                d.resolve(oauthToken, developerKey);
            } else {
                window.gapi.auth.authorize(
                    {
                        'client_id' : clientId,
                        'scope'     : scope,
                        'immediate' : false
                    },
                    function (authResult) {
                        if (authResult && !authResult.error) {
                            oauthToken = authResult.access_token;
                            d.resolve(oauthToken, developerKey);
                        }
                });
            }

            return d.promise();
        };

        // picker開くボタン押されるとこれが呼ばれます
        // $self: クリックされたボタン
        // createBuilder: builderを作って返す ボタンごとに有効にするサービス切り替えるためにここをコールバックみたいにしてる
        var clicked = function($self, createBuilder) {
            $self.prop('disabled', true);

            var googlePickerCallback = function (res) {
                $self.prop('disabled', false);
                Hatena.Diary.LOG([ 'googlePickerCallback', res ]);
                if (res.action !== google.picker.Action.PICKED) return;

                var editor = Hatena.Diary.Editor.Support.currentEditor;

                var lines = [];
                for (var i = 0, len = res.docs.length; i < len; i++) {
                    var doc = res.docs[i];

                    var html;
                    var div;
                    if (doc.type === 'video') {
                        html = $('<div/>').append(
                            $('<iframe width="420" height="315" frameborder="0" allowfullscreen></iframe>').
                                attr('src', doc.embedUrl),
                            $('<br/>'),
                            $('<a/>').attr('href', doc.url).text(doc.name)
                        ).html();
                    } else if (doc.type === 'photo') {
                        div = $('<div/>');

                        var url = doc.thumbnails[doc.thumbnails.length - 1].url;
                        // if (url.match(/\/s\d+\/[^\/+]$/)) {
                        //     // URL内にs+数字
                        //     // /s400/ → /s1280/
                        //     url = url.replace(/\/s\d+\//, '/s1280/');
                        // } else {
                        //     // /s1280/aaa.jpg
                        //     var fragments = url.split(/\//);
                        //     fragments.splice(fragments.length - 1, 0, 's1280');
                        //     url = fragments.join('/');
                        // }

                        var img = $('<img/>').addClass('magnifiable').attr({src: url, itemprop: 'image'});
                        var span = $('<span/>').attr({itemtype: 'http://schema.org/Photograph', itemscope: 'itemscope'});
                        div.append(span.append(img));

                        html = div.html();
                    } else if (doc.embedUrl) {
                        html = $('<div/>').append(
                            $('<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>').
                                attr('src', doc.embedUrl),
                            $('<br/>'),
                            $('<a/>').attr('href', doc.url).text(doc.name)
                        ).html();
                    } else {
                        div = $('<div/>');
                        var thumbnail, icon, link;
                        var thumbnailUrl = doc.thumbnails && doc.thumbnails[doc.thumbnails.length - 1].url;
                        if (thumbnailUrl) {
                            thumbnail = $('<img/>').attr({ src: thumbnailUrl, alt: doc.name || '' });
                            if (doc.url) {
                                thumbnail = $('<a/>').attr('href', doc.url).append(thumbnail);
                            }
                        } else if (doc.iconUrl) {
                            icon = $('<img/>').attr({ src: doc.iconUrl, alt: '' });
                        }
                        if (doc.name && doc.url) {
                            link = $('<a/>').attr('href', doc.url).text(doc.name);
                        }

                        if (thumbnail) div.append(thumbnail);
                        if (thumbnail && link) div.append($('<br/>'));
                        if (icon) div.append(icon);
                        if (link) div.append(link);

                        html = div.html();
                    }

                    lines.push(html);
                }
                // IE9でGoogle Pickerから挿入しようとすると
                // 「internet exploreはクロスサイトスクリプトを防止するために、このページを変更しました」
                // と表示されて挿入できないので (tinymce.focus()できなくて、doc.selection.createRange()で落ちる)
                // 一旦bodyにfocusを当ててから挿入する
                if (navigator.userAgent.indexOf('MSIE') >= 0 && $('#syntax').val() === 'html') {
                    $('body').trigger('focus');
                }
                editor.insertLines(lines);
            };

            var launchGooglePicker = function () {
                var builder = createBuilder();
                    builder.setCallback(googlePickerCallback);
                    builder.setOrigin( (Hatena.Diary.Location.param('editinplace')) ?
                            Hatena.Diary.data('blogs-uri-base') : Hatena.Diary.data('admin-domain') );

                var picker = builder.build();
                picker.setVisible(true);
            };

            if (typeof google === 'undefined') {
                $('<script src="http://www.google.com/jsapi"></script>').appendTo(document.getElementsByTagName('head')[0]);
                var googleTimer = setInterval(function () {
                    if (typeof google === 'undefined') return;
                    clearTimeout(googleTimer);

                    launchGooglePicker();
                }, 20);
            } else {
                launchGooglePicker();
            }
        };

        // タブを表示した時に，google picker apiのロードを行う．
        $('#editor-google-picker').on('show', function() {
            googlePickerApiLoad()
                .done( googlePickerApiAuth ); // ユーザの情報を利用するのでauth必要
        });

        // ピッカー表示ボタンがクリックされた時に，ユーザの認証を行う．
        $('#launch-google-picker button').click(function () {
            googlePickerUserAuth()
                .done( function(oauthToken, developerKey) {
                    clicked($(this), function() {
                        var builder;
                        builder = new google.picker.PickerBuilder().
                            enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
                            addView(google.picker.ViewId.PHOTOS).
                            addView(new google.picker.PhotosView().setType('camerasync')).
                            addView(google.picker.ViewId.PHOTO_UPLOAD).
                            addView(google.picker.ViewId.YOUTUBE).
                            addView(google.picker.ViewId.WEBCAM).
                            addView(google.picker.ViewId.VIDEO_SEARCH).
                            addView(google.picker.ViewId.MAPS).
                            addView(google.picker.ViewId.RECENTLY_PICKED).
                            setLocale('ja').
                            setOAuthToken(oauthToken).
                            setDeveloperKey(developerKey);
                        return builder;
                    });
                });
        });

        $('#launch-youtube button').click(function () {
            googlePickerApiLoad()
                .done( function () {
                    clicked($(this), function() {
                        var builder = new google.picker.PickerBuilder().
                            enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
                            setLocale('ja').
                            addView(google.picker.ViewId.VIDEO_SEARCH);
                        return builder;
                    });
                });
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Fotolife = {

        defaultFolder: 'Hatena Blog',

        _setupElements : function() {
            this.items                   = this.$container.find('#items');
            this.pasteButton             = this.$container.find('.paste-button');
            this.footerButtons           = this.$container.find('#footer-buttons');
            this.upload                  = this.$container.find('#upload');
            this.editorSupportOperations = this.$container.find('#editor-support-operations');
        },

        _setupUploader : function(upload, uploaderHandler, afterinit) {
            Hatena.Diary.Editor.Uploader.setup(upload, uploaderHandler, afterinit);
        },

        init : function () {
            var self = this;
            if (self.initialized) return;
            self.initialized = true;

            self.$container = $('#editor-fotolife');

            var editor = Hatena.Diary.Editor.Support.currentEditor;

            self._setupElements();
            self.editor = editor;
            self.syntax = $('#syntax').val();

            self.items.delegate('.item', 'click', function (e) {
                $(this).toggleClass('selected');

                if (self.items.find('.selected').length) {
                    self.pasteButton.removeClass('disable').addClass('enable');
                } else {
                    self.pasteButton.removeClass('enable').addClass('disable');
                }
            });

            self.items.delegate('.item', 'dblclick', function (e) {
                $(this).removeClass('selected');

                var attr = (self.syntax == 'html') ? 'data-html' : 'data-syntax';
                var syntax = $(this).attr(attr);

                Hatena.Diary.trackEvent(self.pasteButton.attr('data-track-name'));

                self.editor.insert(syntax);
            });

            self.pasteButton.addClass('disable').click(function () {
                var syntax = self.items.find('.item.selected').map(function () {
                    if (self.syntax == 'hatena') {
                        return $(this).removeClass('selected').attr('data-syntax');
                    } else {
                        return $(this).removeClass('selected').attr('data-html');
                    }
                }).get().reverse().join("");

                self.editor.insert(syntax);
            });

            function uploaderHandler(uploader) {
                var item = self.createItem({
                    syntax : '',
                    html   : '',
                    image  : '/images/loading.gif'
                });

                var progress = $('<div class="progress"></div>').appendTo(item);
                var percent = $('<div class="percent">0%</div>').appendTo(progress);
                var bar = $('<div class="bar"></div>').appendTo(progress);

                var lastProgressTimer, lastProgress = 0, updateProgress = function (progress) {
                    if (progress > 100) progress = 100;
                    bar.width(progress + '%');
                    percent.text(Hatena.Locale.text('uploading'));
                };

                uploader.on('error', function (e) {
                    clearInterval(lastProgressTimer);
                    item.addClass('error');
                });

                uploader.on('disk_full', function (e) {
                    self.showDiskFullAlert();
                });

                uploader.on('progress', function (e) {
                    // success が発生するまで 100% にしない
                    var progress = e.percent * 0.9;
                    if (e.percent == 100) {
                        clearInterval(lastProgressTimer);
                        lastProgressTimer = setInterval(function () {
                            lastProgress += 0.1;
                            updateProgress(progress + lastProgress);
                        }, 100);
                    } else {
                        updateProgress(progress);
                    }
                });

                uploader.on('success', function (data) {
                    clearInterval(lastProgressTimer);
                    item.replaceWith(self.createItem(data));
                    self.editor.insert(
                        self.syntax == 'hatena' ? data.syntax : data.html
                    );
                    self.loadInfo();
                });

                self.items.prepend(item);
            }

            function afterinit() {
                self.loadInfo();
            }

            self._setupUploader(self.upload, uploaderHandler, afterinit);

            $(window).resize(_.throttle(function () {
                var mainHeight = $(window).height() - $('#editor-main').offset().top;
                self.items.height(
                    mainHeight -
                        self.editorSupportOperations.outerHeight(true) -
                        self.footerButtons.outerHeight(true) -
                        (self.items.outerHeight(true) - self.items.height()) * 2
                );
            })).resize();

            self.load();
        },

        loadInfo : function () {
            var self = this;

            $.ajax({
                url : "/f/" + Hatena.Diary.data('name') + "/api/info?mode=detail",
                type : "get",
                cache: false,
                dataType : 'json',
                success : function (res) {
                    if (res.error) return Hatena.Diary.BUG(res.error);

                    res.folder_list.push({ status : 'private', folder : 'Hatena Blog' });
                    res.folder_list.push({ status : res.is_private ? 'private' : 'public', folder : ''  });

                    var folderMap = {};
                    var folderList = [];
                    for (var i = 0, it; (it = res.folder_list[i]); i++) {
                        folderMap[it.folder] = it;
                        folderList.push(it.folder);
                    }

                    folderList.sort();

                    var select = $('.js-folder-selector', Hatena.Diary.Editor.Uploader.document).empty();

                    for (var i = 0, len = folderList.length; i < len; i++) {
                        if (folderList[i] === folderList[i-1]) continue;
                        var it = folderMap[ folderList[i] ];

                        var is_private = res.is_private || it.status == 'private';
                        var option = $('<option/>').
                                attr('value', it.folder).
                                text( (it.folder || Hatena.Locale.text('fotolife.folder.top')) + (is_private ? ' (private)' : '')).
                                appendTo(select);

                        if (it.folder == 'Hatena Blog') {
                            option.prop('selected', true);
                        }
                    }

                    select.change(function () {
                        self.load({
                            folder : $(this).val()
                        });
                    });

                    select.parent().show();

                    self.renderDiskSizeGraph(+res.disksize, +res.maxdisksize);
                    $(window).resize();
                },

                error : Hatena.Diary.REPORT_BUG('/api/support/fotolife')
            });
        },
        renderDiskSizeGraph: function(size, maxsize) {
            var self = this;
            var $container = self.$container.find('.js-disksize-container');
            var $box = $container.find('.js-box');
            var $bar = $container.find('.js-bar');
            var $rate = $container.find('.js-rate');

            var rate = size / maxsize;
            var rate_string = Math.floor(rate * 100) + '%';

            $rate.text(rate_string);

            $bar.css('width', rate_string);

            var label = $box.attr('data-label') + rate_string;
            $box.attr('original-title', label);

            $container.show();
        },
        showDiskFullAlert: function(){
            var self = this;
            var $container = self.$container.find('.js-disksize-container');
            var $alert = $container.find('.js-alert');
            $alert.show();
            $(window).resize();
            Hatena.Diary.trackEvent('fotolife.full_alert.show');
        },

        createItem : function (it) {
            return $('<div class="item"/>').attr({
                'data-syntax' : it.syntax.replace(/:image/, ':plain'),
                'data-html'   : it.html,
                'style'       : 'background-image: url("' + it.image + '")'
            });
        },

        load : function (opts) {
            var self = this;
            if (!opts) opts = {};
            if (!opts.page) opts.page = 1;
            if (typeof opts.folder != 'string') opts.folder = self.defaultFolder;

            Hatena.Diary.LOG(['load', opts.folder, opts.page]);

            var container = self.items;

            if (opts.page == 1) {
                container.empty();
            }

            $.ajax({
                url : '/api/support/fotolife',
                type : "get",
                cache: false,
                dataType : 'json',
                data : {
                    folder : opts.folder,
                    page   : opts.page
                },
                success : function (res) {
                    Hatena.Diary.LOG(res);
                    if (res.error) return Hatena.Diary.BUG(res.error);

                    var items = res.items;

                    for (var i = 0, it; (it = items[i]); i++) {
                        self.createItem(it).appendTo(container);
                    }

                    if (!res.last) {
                        $('<div class="item pager-next"/>').
                            click(function () {
                                $(this).remove();
                                self.load({
                                    folder : opts.folder,
                                    page : opts.page + 1
                                });
                                return false;
                            }).
                            appendTo(container);
                    }
                },

                error : Hatena.Diary.REPORT_BUG('/api/support/fotolife')
            });
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Paint = {
        defaultFolder: 'Hatena Blog Illust',
        _setupElements: function() {
            this.items                   = $('#paint-items');
            this.pasteButton             = $('#paint-button-paste');
            this.footerButtons           = $('#paint-footer-buttons');
            this.upload                  = $('#paint-upload');
            this.editorSupportOperations = $('#paint-editor-support-operations');
        },
        _setupUploader : function(upload, uploaderHandler, afterinit) {
            Hatena.Diary.Editor.Uploader.setupForPaint(upload, uploaderHandler, afterinit);
        },
        isSupportedCanvas: function() {
            return !!document.createElement('canvas').getContext;
        },
        init: function() {
            if (!this.isSupportedCanvas()) {
                $('#editor-paint').children().toggle();
                return;
            }
            Hatena.Diary.Pages.Admin['user-blog-edit'].Fotolife.init.call(this);
        },
        load: Hatena.Diary.Pages.Admin['user-blog-edit'].Fotolife.load,
        loadInfo: function() { /* Do nothing. */ },
        createItem: Hatena.Diary.Pages.Admin['user-blog-edit'].Fotolife.createItem
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].CategoryEditor = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].CategoryEditor.prototype = {
        init: function (form, element) {
            this.form = $(form);
            this.element = $(element);
            this.input = this.element.find('input[type="text"]');
            this.bind();
        },
        bind: function () {
            var categoryEditor = this;

            this.form.bind('backup-restore-params', function (e, params) {
                if (params['category']) {
                    $.each(params['category'], function () {
                        categoryEditor.append('' + this);
                    });
                }
            });

            this.element.delegate('.remove-category', 'click', function () {
                $(this).closest('[data-category-name]').remove();
                categoryEditor.updateExistingCategories();
            });

            this.element.click(function (e) {
                if ($(e.target).is(categoryEditor.element)) {
                    categoryEditor.input.focus();
                }
            });

            $('#existing-categories').delegate('[data-category-name]', 'click', function() {
                var func = $(this).hasClass('selected') ? 'remove' : 'append';
                categoryEditor[func]($(this).attr('data-category-name'));
            });

            $('#new-category').click(function() {
                var category = prompt(categoryEditor.element.attr('data-new-category-prompt'));
                categoryEditor.append(category);
            });

            this.input.autocomplete({
                source: function (request, response) {
                    var term = request.term;

                    var categories = $('#existing-categories [data-category-name]')
                            .map(function () { return $(this).attr('data-category-name') })
                            .filter(function () { return this.indexOf(term) === 0 });

                    var newCategory = {
                        value: null,
                        label: categoryEditor.element.attr('data-new-category-label')
                    };

                    response(
                        categories.toArray().concat(term.length > 0 ? [] : [ newCategory ])
                    );
                },
                select: function (e, ui) {
                    var category;

                    if (ui.item.value) {
                        category = ui.item.value;
                    } else if (ui.item.value === null) {
                        category = prompt(categoryEditor.element.attr('data-new-category-prompt'));
                    }

                    if (category) {
                        categoryEditor.append(category);
                        $(e.target).val('');
                        e.stopPropagation();
                        e.preventDefault();
                    }
                },
                minLength: 1,
                appendTo: this.element.parent()
            });

            this.input.keydown(function (e) {
                var input = $(this);
                if (keyString(e) == 'RET') {
                    if (input.val().length) {
                        categoryEditor.input.autocomplete('close');
                        categoryEditor.append(input.val());
                        input.val('');
                    }
                    return false;
                } else if (keyString(e) == 'BS' && input.val().length === 0) {
                    categoryEditor.remove();
                }
            });

            this.form.submit(function (e) {
                if (categoryEditor.input.val()) {
                    categoryEditor.append(categoryEditor.input.val());
                    categoryEditor.input.val('');
                }
            });

            $(window).resize(_.throttle(function () {
                categoryEditor.resize();
            }, 100));
            categoryEditor.resize();
        },
        resize: function () {
            $("#existing-categories").height(
                $("#editor-category").outerHeight(true) - $('.entry-categories-top').outerHeight(true) - 16
            );
        },
        append: function (name) {
            if (!name) return;

            var existing = this.element.find('[data-category-name]').filter(
                function () { return $(this).attr('data-category-name') == name }
            );
            if (existing.length) {
                existing.insertBefore('#select-category');
            } else {
                var html = this.element.attr('data-category-html');
                var elem = $(html).attr('data-category-name', name);
                elem.find('.name').text(name);
                elem.append($('<input type="hidden" name="category" data-with-backup>').val(name));
                elem.insertBefore('#select-category');
            }
            this.appendToExistingCategories(name);
            this.updateExistingCategories();

        },
        appendToExistingCategories: function (name) {
            var isDuplicated = $('#existing-categories [data-category-name]').filter(
                function() { return $(this).attr('data-category-name') == name }
            ).length;
            if (!isDuplicated) {
                $('<li/>')
                    .attr('data-category-name', name)
                    .text(name)
                    .appendTo('#existing-categories');
            }
        },
        updateExistingCategories: function() {
            var categoryMap = {};
            this.element.find('[data-category-name]').each(function() {
                categoryMap[$(this).attr('data-category-name')] = 1;
            });
            $('#existing-categories [data-category-name]').each(function() {
                $(this).toggleClass(
                    'selected',
                    !!categoryMap[$(this).attr('data-category-name')]
                );
            });
        },
        remove: function (dataCategoryName) {
            var targetToDelete = (typeof dataCategoryName === 'undefined') ?
                    this.element.find('[data-category-name]:last') :
                    this.element.find('[data-category-name]')
                    .filter(function() {
                        return $(this).attr('data-category-name') == dataCategoryName;
                    });
            targetToDelete.remove();
            this.updateExistingCategories();
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].DateTimeEditor = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].DateTimeEditor.prototype = {
        init: function (form, element) {
            this.form = $(form);
            this.element = $(element);
            this.element.hide();
            this.datetimepicker = $('<div class="datetime-input">' +
                                    '<input type="text" id="datetime-input-date" > ' +
                                    '<input type="text" id="datetime-input-time" ></div>');
            this.datepicker = this.datetimepicker.find('#datetime-input-date').attr('placeholder', this.todayString());
            this.timepicker = this.datetimepicker.find('#datetime-input-time').attr('placeholder', '00:00');

            this.element.after(this.datetimepicker);

            this.bind();
            this.load();
        },
        bind: function () {
            var self = this;

            this.form.bind('backup-restore-params', function (e, params) {
                self.load();
            });

            var lang = document.documentElement.getAttribute('lang');
            $.datepicker.setDefaults($.datepicker.regional[lang == 'en' ? '' : lang]);
            this.datepicker.datepicker({
                dateFormat: $.datepicker.W3C,
                onSelect: function () {
                    self.datepicker.change();
                    if (self.timepicker.val() === '') {
                        self.timepicker.val('00:00').focus().change();
                    }
                }
            });

            var timeOptions = [];
            for (var i = 0; i < 24; ++i) {
                timeOptions.push(('0' + i.toString()).slice(-2) + ':00');
                timeOptions.push(('0' + i.toString()).slice(-2) + ':30');
            }
            this.timepicker.autocomplete({
                source: function (request, response) {
                    if (!request.term.match(/^\d{1,2}:\d{1,2}:(\d{1,2})?$/)) {
                        response(timeOptions);
                    }
                },
                select: function (e, ui) {
                    if (ui.item.value) {
                        self.timepicker.val(ui.item.value).change();
                        if (self.datepicker.val() === '') {
                            self.datepicker.val(self.todayString());
                        }
                    }
                },
                minLength: 0,
                appendTo: this.element.parent()
            });
            this.timepicker.focus(function () {
                $(this).autocomplete('search', '');
            });

            this.datepicker.change(function () {
                self.date = $(this).val();
                self.updateValue();
            });

            this.timepicker.change(function () {
                var time = $(this).val();

                if (self.checkTime(time)) {
                    var m = time.match(/^(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/);
                    self.time = $([1, 2, 3]).map(function () {
                        return ('0' + (m[this] || '00')).slice(-2);
                    }).toArray().join(':');
                } else {
                    self.time = null;
                }

                self.updateValue();
            });

            this.form.submit(function (e) {
                self.updateValue();
            });
        },
        load: function () {
            var self = this;
            var m = this.element.val().match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})\+(\d{2}:\d{2})$/);
            if (m) {
                this.datepicker.val(this.date = m[1]);
                this.time = m[2];
                var time = this.time.replace(/:00$/, '');
                this.timepicker.val(time);
                this.timezone = m[3];
            }
        },
        todayString: function () {
            var now = new Date();
            var date = [];
            date.push((1900 + now.getYear()).toString());
            date.push(('0' + (1 + now.getMonth()).toString()).slice(-2));
            date.push(('0' + now.getDate().toString()).slice(-2));
            return date.join('-');
        },
        checkTime: function (time) {
            var match = time.match(/^(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/);
            if (match) {
                var h = parseInt(match[1], 10);
                var m = parseInt(match[2], 10);
                var s = parseInt(match[3] || '0', 10);
                return 0 <= h && h < 24 && 0 <= m && m < 60 && 0 <= s && s < 60;
            }
            return false;
        },
        updateValue: function () {
            if (this.date) {
                // 時刻が設定されていないとき 00:00 にする
                if (!this.time) this.time = '00:00';

                // timezone があったら設定する
                var timezone = '';
                if (this.timezone) timezone = '+' + this.timezone;

                this.element.val(this.date + 'T' + this.time + timezone);
            } else {
                this.element.val('');
            }

            $(this).triggerHandler('updated');
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].observeForScheduledEntry = function(datetimeEditor) {
        var $input = $('#datetime-input');
        var $checkbox = $('.js-scheduled-entry-checkbox');
        var $defaultButtons = $('.buttons .js-default-button');
        var $scheduledButtons = $('.buttons .js-scheduled-button');
        var $socializeBox = $('.js-socialize-box');

        // 日付あるとき，チェックボックス出す
        // チェックついてるとき，予約投稿ボタンとシェア設定出す
        var watch = function() {
            if ($input.val()) {
                $checkbox.prop('disabled', false);
            } else {
                $checkbox.prop('disabled', true);
            }

            if ($input.val() && $checkbox.prop('checked')) {
                $defaultButtons.hide();
                $scheduledButtons.show();
                $socializeBox.show();
            } else {
                $defaultButtons.show();
                $scheduledButtons.hide();
                $socializeBox.hide();
            }
        };
        $(datetimeEditor).on('updated', watch);
        $checkbox.on('change', watch);
        watch();
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].OgImageEditor = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].OgImageEditor.prototype = {
        init: function (form, element) {
            this.$form    = $(form);
            this.$element = $(element);
            this.$input   = this.$element.find('#ogimage-input');
            this.$imgContainer = this.$element.find('#ogimage-img-container');
            this.$current = this.$element.find('.current-og-image');
            this.$remove  = this.$element.find('.remove-og-image');
            this.$items   = this.$form.find('.image-items');
            this.itemTemplate = _.template(this.$form.find('.ogimage-item-template').html());
            this.$indicator = this.$element.find('.indicator');
            this.$reload = this.$element.find('.reload');
            this.$errorMessage = this.$element.find('.error');
            this.isLoading = false;
            this.defaultOgImageURL = this.$element.data('default-ogimage-url');

            this.bindEvents();
            this.getImageSrcs();
        },
        bindEvents: function () {
            var self = this;

            $(window).resize(_.throttle(function () {
                self.reloadItems();
            }, 100));

            self.$element.change( function () {
                self.setOgImage();
            });

            self.$element.on('click', '.image-item', function () {
                self.setOgImageInput(this);
                self.setOgImage();
            });

            self.$input.keydown(function (e) {
                if (keyString(e) === 'RET') {
                    self.setOgImage();
                    return false;
                }
            });

            self.$reload.click( function () {
                self.reloadItems();
            });

            self.$remove.click( function () {
                self.removeCurrentImage();
            });
        },
        setOgImage: function (src) {
            var self = this;
            self.$current.attr('src', self.$input.val());
        },
        removeCurrentImage: function () {
            var self = this;

            // chromeだとsrc=""にしても画像が残ってしまうのでimgタグ作りなおす
            var $image = $('<img>').addClass('current-og-image');
            self.$input.val("");
            self.$current.remove();
            self.$current = $image;
            self.$imgContainer.append($image);
            self.$items.find('.selected').removeClass('selected');
        },
        setOgImageInput: function (item) {
            var self = this;
            var $item = $(item);

            self.$items.find('.selected').removeClass('selected');
            $item.addClass('selected');

            var src = $item.attr('data-image-src');
            self.$input.val(src);
        },
        showItems : function (items) {
            var self = this;
            var source = "";
            _.each(items, function (item) {
                source += self.itemTemplate({
                    item: { image_src: item }
                });
            });
            self.$indicator.before(source);
        },
        reloadItems: function () {
            var self = this;
            if (! self.$element.is(':visible')) return;
            self.removeImageItems();
            self.getImageSrcs();
        },
        getImageSrcs: function () {
            var self   = this;
            var editor = Hatena.Diary.Editor.Support.currentEditor;
            var body   = editor.body.val();

            // 本文空でもデフォルト画像は候補として出す
            if (!body) {
                self.showItems([self.defaultOgImageURL]);
                return;
            }

            if (self.isLoading) return;

            self.isLoading = true;
            self.$indicator.show();

            $.ajax({
                url: '/api/entry/images',
                type: 'POST',
                dataType: 'json',
                data: {
                    body: body,
                    syntax: $('#syntax').val(),
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                }
            }).done(function (items) {
                // デフォルト画像末尾に出す
                items.push(self.defaultOgImageURL);

                self.showItems(items);
                self.$errorMessage.hide();

                self.setSelectedImage();
            }).fail(function (res) {
                self.failed = true;
                self.$errorMessage.show();
            }).always(function () {
                self.isLoading = false;
                self.$indicator.hide();
            });

        },
        removeImageItems: function () {
            var self = this;
            self.$items.find('.image-item').remove();
        },
        // アイキャッチ画像が設定されていたら、selectedクラスを当てる
        setSelectedImage: function () {
            var self = this;
            var inputSrc = self.$input.val();
            if ( ! inputSrc ) return;
            if ( self.$items.find('.selected').length > 0 ) return;

            self.$items.find('.image-item').each( function () {
                var $item = $(this);
                var $img = $item.find('.image-container img');
                if ( $img.attr('src') === inputSrc ) {
                    $item.addClass('selected');
                    return false;
                }
            });
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].AmazonSearch = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].AmazonSearch.prototype = {
        // args: { container }
        init: function (args) {
            var self = this;

            self.$container = args.container;
            if (!self.$container.get(0)) return;
            self.$categorySelect = self.$container.find('.amazon-search-category');
            self.$keywordInput = self.$container.find('.amazon-search-keyword');
            self.$keywordSubmit = self.$container.find('.amazon-search-keyword-submit');
            self.$itemsContainer = self.$container.find('.amazon-search-items');
            self.itemTemplate = _.template($('.amazon-search-item-template').html());
            self.$indicator = self.$container.find('.indicator');
            self.$pasteButton = self.$container.find('.amazon-search-paste-button');
            self.$layoutType = self.$container.find('.amazon-search-layout-type');
            self.$layoutTypeContainer = self.$container.find('.amazon-search-layout-type-container');
            self.$resultIsEmpty = self.$container.find('.amazon-search-result-is-empty');
            self.$formats = self.$container.find('.amazon-search-formats input[name="amazon-search-format"]');
            self.$formatsContainer = self.$container.find('.amazon-search-formats');
            self.$welcomeMessage = self.$container.find('.amazon-search-welcome');

            self.$header = self.$container.find('.amazon-search-header');
            self.$footer = self.$container.find('.amazon-search-footer');

            self.bindEvents();
            self.resize();

            // 検索クエリ指定されていたら検索する
            if ( self.$keywordInput.val() ) {
                self.$keywordSubmit.click();
            }
        },
        bindEvents: function () {
            var self = this;

            self.$keywordSubmit.click(function (event) {
                self.searchByInput();
                return false;
            });

            self.$categorySelect.change(function (event) {
                self.searchByInput();
                return false;
            });

            self.$keywordInput.keydown(function (event) {
                if (keyString(event) == 'RET') {
                    self.searchByInput();
                    return false;
                }
            });

            self.$keywordInput.focus(function() {
                // 下の貼り付けボタン表示されないことがある
                // 原因わからないけどリサイズしたらボタン出てくる
                // 検索ボックスにフォーカスしたときにダメ押しでもう1回リサイズ
                setTimeout(function() {
                    self.resize();
                }, 0);
            });

            self.$itemsContainer.delegate('.amazon-search-item', 'click', function (event) {
                if ($(event.target).is('a')) return;
                $(this).toggleClass('selected');

                self.selectedItemsChanged();
            });

            self.$container.delegate('.amazon-search-item', 'dblclick', function (event) {
                if ($(event.target).is('a')) return;
                self.insertAsins([$(this).attr('data-asin')]);
                $(this).removeClass('selected');
                self.selectedItemsChanged();
                Hatena.Diary.trackEvent(self.$pasteButton.attr('data-track-name'));
                return false;
            });

            self.$pasteButton.click(function (event) {
                var asins = [];
                self.$itemsContainer.find('.selected').each(function () {
                    asins.push($(this).attr('data-asin'));
                    $(this).removeClass('selected');
                });
                self.insertAsins(asins);
                self.selectedItemsChanged();
            });

            Hatena.Diary.Util.backupTab({
                $container: self.$formatsContainer,
                key: 'amazon-formats',
                onchange: function($input) {
                    self.$formatsContainer.find('label.selected').removeClass('selected');
                    $input.closest('label').addClass('selected');
                }
            });

            Hatena.Diary.Util.backupTab({
                $container: self.$layoutTypeContainer,
                key: 'amazon-layout',
                onchange: function($input) {
                    self.$itemsContainer.removeClass('layout-thumbnail');
                    self.$itemsContainer.removeClass('layout-list');

                    var layout = $input.val();
                    self.$itemsContainer.addClass('layout-' + layout);

                    // label class
                    self.$layoutTypeContainer.find('label.selected').removeClass('selected');
                    $input.closest('label').addClass('selected');

                    // リスト表示のときだけtipsy有効，サムネイル表示のときは出さない
                    self.setTipsyEnabled(layout == 'thumbnail');
                }
            });

            $(window).resize(_.throttle(function () {
                self.resize();
            }, 100));
        },
        setTipsyEnabled: function (enable) {
            var self = this;

            // tipsy-southwestクラスを付けたり外したりします

            var $items = self.$itemsContainer.find('.amazon-search-item');
            var className = 'tipsy-southeast';

            if (enable) {
                $items.addClass(className);
            } else {
                $items.removeClass(className);
            }
        },
        resize: function () {
            var self = this;

            var mainHeight = $(window).height();

            var padding = 0;
            padding += parseInt(self.$itemsContainer.css('padding-top'), 10) || 0;
            padding += parseInt(self.$itemsContainer.css('padding-bottom'), 10) || 0;
            self.$itemsContainer.height(
                mainHeight -
                    self.$container.offset().top   -
                    self.$header.outerHeight(true) -
                    self.$footer.outerHeight(true) -
                    padding
            );
        },
        selectedItemsChanged: function() {
            var self = this;

            if (self.$itemsContainer.find('.selected').length > 0) {
                self.$pasteButton.removeClass('disabled').addClass('enabled').prop('disabled', false);
            } else {
                self.$pasteButton.removeClass('enabled').addClass('disabled').prop('disabled', true);
            }
        },
        searchByInput: function() {
            var self = this;

            self.search(self.$keywordInput.val(), self.$categorySelect.find('option:selected').val());
        },
        search: function (keyword, category) {
            var self = this;

            if (typeof keyword != 'string') return false;

            keyword = keyword.replace(/^\s*/, '');
            keyword = keyword.replace(/\s*$/, '');

            if (keyword.length === 0) return false;

            if (self._searchingKeyword == keyword && self._searchingCategory == category) return false;

            // ここまで来たら検索開始

            self.$welcomeMessage.addClass('disable');

            if (self._searchDeferred) {
                self._searchDeferred.reject();
            }

            self.ajaxStarted();

            self._searchingKeyword = keyword;
            self._searchingCategory = category;

            var currentAjax;
            var dfd = $.Deferred().done(function() {
            }).fail(function() {
                if (currentAjax) {
                    // セッション終了時に前のajaxをキャンセル
                    currentAjax.abort();
                }
            }).always(function() {
                self.ajaxFinished();
            });

            self.$itemsContainer.find('.amazon-search-item').remove();

            var searchPage = function(page) {
                self.ajaxStarted();

                currentAjax = $.ajax({
                    url: '/api/amazon',
                    data: {
                        keyword: keyword,
                        category: category,
                        page: page
                    }
                }).done(function (res) {
                    self.showItems(res.items);

                    if (res.page === 1 && res.items.length === 0) {
                        self.$resultIsEmpty.show();
                    } else {
                        self.$resultIsEmpty.hide();
                    }

                    if (!res.has_next) {
                        dfd.resolve();
                        return;
                    }

                    if (res.page >= 5) {
                        dfd.resolve();
                        return;
                    } else {
                        searchPage(res.page + 1);
                    }
                }).fail(function (res) {
                    dfd.reject(res);
                });
            };
            searchPage(1);

            self._searchDeferred = dfd;
        },
        showItems: function (items) {
            var self = this;

            var source = '';
            _.each(items, function (item) {
                source += self.itemTemplate({
                    item: item
                });
            });
            self.$indicator.before(source);

            self.setTipsyEnabled(self.$itemsContainer.hasClass('layout-thumbnail'));
        },
        insertAsins: function (asins) {
            var self = this;

            var suffix = self.$container.find('[name="amazon-search-format"]:checked').val();

            var hatena_syntaxes = _.map(asins, function(asin) {
                return '[asin:' + asin + (suffix.length > 0 ? ':' + suffix : '') + ']';
            });

            var lines = {
                html: hatena_syntaxes,
                hatena: hatena_syntaxes,
                markdown: hatena_syntaxes
            };

            Hatena.Diary.extractSyntax(hatena_syntaxes).done(function(data) {
                if (suffix === 'detail') {
                    lines.html = ['', '<div class="freezed">' + data.html + '</div>', ''];
                } else {
                    lines.html = [data.html];
                }
                Hatena.Diary.EditorConnector.insertLines(lines);
            }).fail(function(error) {
                Hatena.Diary.BUG(error);
                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        },
        ajaxStarted: function () {
            var self = this;

            self.isAjaxing = true;

            self.$keywordSubmit.prop('disabled', true);
            self.$indicator.show();
            self.$resultIsEmpty.hide();
        },
        ajaxFinished: function () {
            var self = this;

            self.isAjaxing = false;

            self.$keywordSubmit.prop('disabled', false);
            self.$indicator.hide();
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Twitter = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Twitter.prototype = {
        pasteReverseOrder: true,
        // args: { container }
        init: function (args) {
            var self = this;

            self.$container = args.container;
            if (!self.$container.get(0)) return;
            self.$itemsContainer = self.$container.find('.twitter-items');
            self.$indicator = self.$container.find('.indicator');
            self.itemTemplate = _.template($('.twitter-item-template').html());
            self.$pasteButton = self.$container.find('.twitter-paste-button');
            self.$listTypeContainer = self.$container.find('.twitter-list-type-container');
            self.$formatsContainer = self.$container.find('.twitter-formats');
            self.$reloadButton = self.$container.find('.reload');
            self.$errorMessage = self.$container.find('.error');
            self.$detailOnlyMessage = self.$container.find('.twitter-formats-detail-only');
            self.$header = self.$container.find('.twitter-header');
            self.$footer = self.$container.find('.twitter-footer');

            self.bindEvents();
            self.resize();

            self.loadTweets();
        },
        bindEvents: function () {
            var self = this;

            $(window).resize(_.throttle(function () {
                self.resize();
                self.loadTweets();
            }, 100));

            self.$itemsContainer.delegate('.twitter-item', 'click', function (event) {
                if ($(event.target).is('a')) return;
                if ($(this).is('.private')) return;
                $(this).toggleClass('selected');

                self.selectedItemsChanged();
            });

            self.$container.delegate('.twitter-item', 'dblclick', function (event) {
                if ($(event.target).is('a')) return;
                if ($(this).is('.private')) return;
                self.insertSyntaxes([{
                    id_str: $(this).attr('data-id-str'),
                    screen_name: $(this).attr('data-screen-name'),
                    text: $(this).attr('data-text')
                }]);
                $(this).removeClass('selected');
                self.selectedItemsChanged();
                Hatena.Diary.trackEvent(self.$pasteButton.attr('data-track-name'));
                return false;
            });

            self.$pasteButton.click(function (event) {
                var id_strs = [];
                self.$itemsContainer.find('.selected').each(function () {
                    id_strs.push({
                        id_str: $(this).attr('data-id-str'),
                        screen_name: $(this).attr('data-screen-name'),
                        text: $(this).attr('data-text')
                    });
                    $(this).removeClass('selected');
                });
                self.insertSyntaxes(id_strs);
                self.selectedItemsChanged();
            });

            // list type
            self.$listTypeContainer.delegate('input', 'change', function () {
                if (self.getListType == $(this).val()) return;
                self.setListType($(this).val());
                self.$listTypeContainer.find('label.selected').removeClass('selected');
                $(this).closest('label').addClass('selected');
                self.loadTweets();
            });

            Hatena.Diary.Util.backupTab({
                $container: self.$formatsContainer,
                key: 'twitter-format',
                onchange: function($input) {
                    self.$formatsContainer.find('label.selected').removeClass('selected');
                    $input.closest('label').addClass('selected');
                }
            });

            Hatena.Diary.Util.backupTab({
                $container: self.$listTypeContainer,
                key: 'twitter-list-type',
                onchange: function($input) {
                    self.setListType($input.val());
                    self.$listTypeContainer.find('label.selected').removeClass('selected');
                    $input.closest('label').addClass('selected');
                    self.loadTweets();

                    // 自分のツイートのときだけ貼り付けフォーマット選べる
                    if ($input.val() == 'tweets') {
                        self.$formatsContainer.css('visibility', 'visible');
                        self.$detailOnlyMessage.hide();
                    } else {
                        self.$formatsContainer.css('visibility', 'hidden');
                        self.$detailOnlyMessage.show();
                    }
                }
            });

            self.$reloadButton.click(function (event) {
                self.loadTweets(null, true);
            });

            // オートページャ
            self.$itemsContainer.scroll(_.throttle(function() {
                var rate = ( self.$itemsContainer.scrollTop() + self.$itemsContainer.height() ) / self.$itemsContainer[0].scrollHeight;
                if (rate > 0.7) { // 下のほうに行ったらもっと読む
                    self.loadMore();
                }
            }, 100));

        },
        resize: function() {
            var self = this;

            var mainHeight = $(window).height();

            var padding = 0;
            padding += parseInt(self.$itemsContainer.css('padding-top'), 10) || 0;
            padding += parseInt(self.$itemsContainer.css('padding-bottom'), 10) || 0;
            self.$itemsContainer.height(
                mainHeight -
                    self.$container.offset().top   -
                    self.$header.outerHeight(true) -
                    self.$footer.outerHeight(true) -
                    padding
            );
        },
        setListType: function(type) {
            if (! type.match(/^(tweets|favorites|timeline)$/)) return;
            this.listType = type;
        },
        getListType: function() {
            // さっき設定された？
            if (this.listType) {
                return this.listType;
            }
            // デフォルト値
            return 'tweets';
        },
        selectedItemsChanged: function() {
            var self = this;

            if (self.$itemsContainer.find('.selected').length > 0) {
                self.$pasteButton.removeClass('disabled').addClass('enabled').prop('disabled', false);
            } else {
                self.$pasteButton.removeClass('enabled').addClass('disabled').prop('disabled', true);
            }
        },
        loadTweets: function (max_id, force) {
            var self = this;

            if (self.isLoading) return;
            if (! self.$container.is(':visible')) return;

            self.isLoading = true;
            self.$indicator.show();

            if (!max_id) {
                self.$itemsContainer.find('.twitter-item').remove();
            }

            var data = {};

            if (max_id) {
                data.max_id = max_id;
            }

            var list_type = self.getListType();

            var url = '/api/twitter/' + list_type + (max_id ? '?max_id=' + max_id : '');

            self.ajaxGetOrCache(url, force).done(function (items) {
                // 通信中にタブ切り替えられてたら結果を捨てて再度通信する
                // _.deferしてるのはalwaysが終了してから実行するため
                if (self.getListType() != list_type) {
                    _.defer(function() {
                        self.loadTweets();
                    });
                    return;
                }
                if (max_id) {
                    // 1件目は重複
                    items.shift();
                }
                self.showItems(items);

                self.$errorMessage.hide();
            }).fail(function (res) {
                self.$errorMessage.show();
            }).always(function () {
                self.$indicator.hide();
                self.isLoading = false;
            });

        },
        showItems: function (items) {
            var self = this;

            var source = '';
            _.each(items, function (item) {
                source += self.itemTemplate({
                    item: item
                });
            });
            self.$indicator.before(source);
        },
        loadMore: function() {
            var self = this;

            var $lastItem =  self.$itemsContainer.find('.twitter-item:last');
            if (!$lastItem.length) return;

            var maxId = $lastItem.attr('data-id-str');

            self.loadTweets(maxId);
        },
        // tweet: { screen_name, id_str, text }
        insertSyntaxes: function (tweets) {
            var self = this;

            var format = self.getFormat();

            // markdownモード時はscreen_nameをescapeする必要があるので別に作っている
            var syntaxes = [];
            var syntaxes_for_markdown = [];
            _.each(tweets.reverse(), function(tweet) {
                syntaxes.push(self.createSyntax(tweet, format, false));
                syntaxes_for_markdown.push(self.createSyntax(tweet, format, true));
            });

            Hatena.Diary.EditorConnector.insertLines({
                html:     syntaxes,
                hatena:   syntaxes,
                markdown: syntaxes_for_markdown
            });
        },
        createSyntax: function(tweet, format, is_markdown) {
            if (format == "detail") {
                var screen_name = tweet.screen_name;

                // __hoge__みたいな名前だとmarkdownの強調表示に引っかかって崩れるので
                // markdownモードの時はエスケープするようにしてる
                if (is_markdown) screen_name = screen_name.replace(/_(.*?)_/g, '\\_$1\\_');

                var text = tweet.text;
                text = text.replace(/[\[\]\n]/g, '').replace(/([\*`_])/g, "\\$1");

                return "[https://twitter.com/" + screen_name + "/status/" + tweet.id_str + ":embed#" + text + "]";
            } else if (format == "text") {
                return tweet.text;
            }
        },
        getFormat: function () {
            if (this.getListType() == "tweets") {
                return this.$container.find('[name="twitter-format"]:checked').val();
            }
            return "detail";
        },
        ajaxGetOrCache : function(url, force_disable_cache) {
            // ajax getまたはキャッシュから返す
            // タブ切り替えて戻すだけで通信しないようにするためのやつ
            // jqXHRではなくDeferredオブジェクトが返ることがあるので使う側で注意すること
            var self = this;

            // forceじゃなくてキャッシュあったら返す
            if (!force_disable_cache && self.ajaxGetOrCacheCache[url]) {
                var dfd = $.Deferred();
                dfd.resolve(self.ajaxGetOrCacheCache[url]);
                return dfd.promise();
            }

            // thenを追加してキャッシュに保存するというのをやっています
            return $.ajax({
                url: url
            }).done(function(res) {
                self.ajaxGetOrCacheCache[url] = res;
            });
        },
        ajaxGetOrCacheCache: {}
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].HatenaBookmark = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].HatenaBookmark.prototype = {
        // args: { container }
        init: function (args) {
            var self = this;

            self.$container = args.container;
            if (!self.$container.get(0)) return;
            self.$header = self.$container.find('.header');
            self.$itemsContainer  = self.$container.find('.items');
            self.$indicator  = self.$container.find('.indicator');
            self.template = _.template(self.$container.find('.template').html());
            self.$errorMessage  = self.$container.find('.error-message');
            self.$disabledMessage  = self.$container.find('.disabled-message');
            self.$footer = self.$container.find('.footer');
            self.$pasteButton  = self.$container.find('.paste-button');

            self.loadedPage = 0;

            self.bindEvents();
            self.resize();

            self.loadItems(1);
        },
        bindEvents: function () {
            var self = this;

            $(window).resize(_.throttle(function () {
                self.resize();
                self.loadItems(1);
            }, 100));

            self.$itemsContainer.on('click', '.item', function (event) {
                if ($(event.target).is('a')) return;
                if ($(event.target).parents('a').length > 0) return;
                $(this).toggleClass('selected');

                self.selectedItemsChanged();
                return false;
            });

            self.$container.on('dblclick', '.item', function (event) {
                if ($(event.target).is('a')) return;
                if ($(event.target).parents('a').length > 0) return;
                self.insertItems([$(this)]);
                $(this).removeClass('selected');
                self.selectedItemsChanged();
                Hatena.Diary.trackEvent(self.$pasteButton.attr('data-track-name'));
                return false;
            });

            self.$pasteButton.click(function (event) {
                var items = [];
                self.selectedItems().each(function () {
                    items.push($(this));
                    $(this).removeClass('selected');
                });
                self.insertItems(items.reverse());
                self.selectedItemsChanged();
            });

            // オートページャ
            // twitterからコピペ
            self.$itemsContainer.scroll(_.throttle(function() {
                var rate = ( self.$itemsContainer.scrollTop() + self.$itemsContainer.height() ) / self.$itemsContainer[0].scrollHeight;
                if (rate > 0.7) { // 下のほうに行ったらもっと読む
                    self.loadItems(self.loadedPage + 1);
                }
            }, 100));
        },

        resize: function() {
            var self = this;

            var mainHeight = $(window).height() - $('#editor-main').offset().top;
            self.$itemsContainer.height(
                mainHeight -
                    self.$header.outerHeight(true) -
                    self.$footer.outerHeight(true)
            );
        },

        selectedItemsChanged: function() {
            var self = this;

            if (self.selectedItems().length > 0) {
                self.$pasteButton.removeClass('disabled').addClass('enabled').prop('disabled', false);
            } else {
                self.$pasteButton.removeClass('enabled').addClass('disabled').prop('disabled', true);
            }
        },

        selectedItems: function() {
            var self = this;

            return self.$itemsContainer.find('.selected');
        },

        loadItems: function(page) {
            var self = this;

            if (self.isLoading) return;
            if (! self.$container.is(':visible')) return;

            if (page > 10) return;  // さかのぼりすぎない
            if (self.failed) return; // 一度失敗したらあきらめる

            if (self.loadedPage > page) return;

            self.isLoading = true;
            self.$indicator.show();
            self.$errorMessage.hide();

            $.ajax({
                url: '/api/hatena_bookmark/bookmarks?page=' + page,
                type: 'GET',
                dataType: 'json'
            }).done(function (items) {
                self.$errorMessage.hide();
                if (page === 1 && items.length === 0) {
                    self.showDisabledMessage();
                    return;
                }

                self.showItems(items);
            }).fail(function (res) {
                self.$errorMessage.show();
                self.failed = true;
            }).always(function () {
                self.$indicator.hide();
                self.isLoading = false;
            });

            self.loadedPage = page;
        },

        showDisabledMessage: function() {
            // ブクマを使いませんかみたいなやつ
            var self = this;
            self.$disabledMessage.show();
            self.$itemsContainer.hide();
            self.$footer.hide();
            self.failed = true;
        },

        showItems: function(items) {
            var self = this;

            var source = '';
            _.each(items, function (item) {
                source += self.template({
                    item: item
                });
            });
            self.$indicator.before(source);
            Hatena.Locale.updateTimestamps(self.$container[0]);
        },

        insertItems: function(items) {
            var self = this;
            var editor = Hatena.Diary.Editor.Support.currentEditor;
            var syntax = $('#syntax').val();
            var lines = [];
            _.each(items, function($item) {
                var url = $item.attr('data-comment-url');
                var permalink = $item.attr('data-permalink');
                var description = $item.attr('data-description');

                // ブックマークコメントはblockquoteとscriptの組なので，フィードリーダーでも読める．
                // ブックマークのAPIの仕様で，コメントがないときは，貼り付けコードをもらえない．
                // ブログカードにフォールバックするので，そのときはフィードリーダーでも読めるように:titleのリンクも出す．
                if (description && description.length > 0) {
                    lines.push('[' + url + ':embed]');
                } else {
                    lines.push('[' + permalink + ':embed]');
                    lines.push('[' + permalink + ':title]');
                }
            });

            var syntaxes = {
                html: lines,
                hatena: lines,
                markdown: lines
            };

            // みたまま編集のときは先に記法展開してから，そうでなかったらすぐに挿入
            if ($('#syntax').val() === 'html') {
                Hatena.Diary.extractSyntax(lines.join("\n")).done(function(data) {
                    // 編集できるように上下に空行足す
                    syntaxes.html = ['', data.html, ''];
                }).always(function() {
                    Hatena.Diary.EditorConnector.insertLines(syntaxes);
                });
            } else {
                Hatena.Diary.EditorConnector.insertLines(syntaxes);
            }
        }
    };

    // マイキュレーション親クラス
    // extendして使う
    Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype = {
        // args: { container }
        init: function (args) {
            var self = this;

            self.$container = args.container;
            if (!self.$container.get(0)) return;
            self.$header = self.$container.find('.header');
            self.$itemsContainer  = self.$container.find('.items');
            self.$tabsContainer = self.$container.find('.tab-container');
            self.$indicator  = self.$container.find('.indicator');
            self.$errorMessage  = self.$container.find('.error-message');
            self.$disabledMessage  = self.$container.find('.disabled-message');
            self.$footer = self.$container.find('.footer');
            self.$pasteButton  = self.$container.find('.paste-button');

            var $templateNode = self.$container.find('.template');
            if ($templateNode.get(0)) {
                self.template = _.template($templateNode.html());
            }

            var $editorTemplateNode = self.$container.find('.editor-template');
            if ($editorTemplateNode.get(0)) {
                self.editorTemplate = _.template($editorTemplateNode.html());
            }

            self.loadedPage = 0;

            self.bindEvents();
            self.resize();

            self.requestLoadItems();
        },
        // AutoPager使いたいときtrue
        // AutoPager有効にすると下までスクロールしたときloadItems(true)が呼ばれる
        enableAutoPager: false,
        // AutoPager最後まで受信したらtrueにしてください
        itemsReachedEnd: false,
        // 複数選択貼り付け時に逆順で貼り付けるかどうか
        pasteReverseOrder: false,
        bindEvents: function () {
            var self = this;

            $(window).resize(_.throttle(function () {
                self.resize();
                self.requestLoadItems();
            }, 100));

            self.$itemsContainer.on('click', '.item', function (event) {
                if ($(event.target).is('a')) return;
                if ($(event.target).parents('a').length > 0) return;
                $(this).toggleClass('selected');

                self.selectedItemsChanged();
                return false;
            });

            self.$container.on('dblclick', '.item', function (event) {
                if ($(event.target).is('a')) return;
                if ($(event.target).parents('a').length > 0) return;
                self.insertItems([$(this)]);
                $(this).removeClass('selected');
                self.selectedItemsChanged();
                Hatena.Diary.trackEvent(self.$pasteButton.attr('data-track-name'));
                return false;
            });

            self.$pasteButton.click(function (event) {
                var items = [];
                self.selectedItems().each(function () {
                    items.push($(this));
                    $(this).removeClass('selected');
                });
                self.insertItems(self.pasteReverseOrder ? items.reverse() : items);
                self.selectedItemsChanged();
            });

            self.tabs = new Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.Tab({
                container: self.$tabsContainer,
                backupKey: self.serviceName
            });
            $(self.tabs).on('change', function() {
                self.removeItems();
                self.requestLoadItems();
            });

            if (self.enableAutoPager) {
                self.$itemsContainer.scroll(_.throttle(function() {
                    var rate = ( self.$itemsContainer.scrollTop() + self.$itemsContainer.height() ) / self.$itemsContainer[0].scrollHeight;
                    // 下のほうに行ったらもっと読む
                    if (rate > 0.7 && !self.itemsReachedEnd) {
                        self.requestLoadItems(true);
                    }
                }, 100));
            }
        },
        resize: function() {
            var self = this;

            var mainHeight = $(window).height();

            var padding = 0;
            padding += parseInt(self.$itemsContainer.css('padding-top'), 10) || 0;
            padding += parseInt(self.$itemsContainer.css('padding-bottom'), 10) || 0;
            self.$itemsContainer.height(
                mainHeight -
                    self.$container.offset().top   -
                    self.$header.outerHeight(true) -
                    self.$footer.outerHeight(true) -
                    padding
            );
        },
        selectedItemsChanged: function() {
            var self = this;

            if (self.selectedItems().length > 0) {
                self.$pasteButton.removeClass('disabled').addClass('enabled').prop('disabled', false);
            } else {
                self.$pasteButton.removeClass('enabled').addClass('disabled').prop('disabled', true);
            }
        },
        selectedItems: function() {
            var self = this;

            return self.$itemsContainer.find('.selected');
        },
        requestLoadItems: function(is_more) {
            var self = this;

            if (self.isLoading) return;
            if (! self.$container.is(':visible')) return;

            // 最初からrequestされたけどページ内に要素がある場合は何もしない
            if (! is_more && self.getItemsOnPage().length > 0) return;

            self._requestLoadItems(is_more);
        },
        willRequestLoadItems: function (is_more) {
            var self = this;
            // 必要に応じてオーバーライドしてください
            // false を返すとリクエストするのをやめることができます
            return true;
        },
        _requestLoadItems: function (is_more) {
            var self = this;

            if (!self.willRequestLoadItems(is_more)) return;

            self.isLoading = true;
            self.$indicator.show();
            self.$errorMessage.hide();

            self.loadItems(is_more).done(function(feed) {
                self.showItems(feed.entries);
            }).fail(function(res) {
                self.$errorMessage.show();
            }).always(function() {
                self.$indicator.hide();
                self.isLoading = false;
            });
        },
        requestReload: function (is_more) {
            var self = this;

            if (self.isLoading) return;

            self.removeItems();
            self._requestLoadItems();
        },
        getItemsOnPage: function() {
            var self = this;
            return self.$itemsContainer.find('.item');
        },
        removeItems: function() {
            var self = this;
            self.getItemsOnPage().remove();
        },
        loadItems: function() {
            throw "not implemented";
            // 上書きして使ってください
        },
        showItems: function(items) {
            var self = this;

            var source = '';
            _.each(items, function (entry) {
                source += self.renderItem(entry);
            });
            self.$indicator.before(source);
            Hatena.Locale.updateTimestamps(self.$container[0]);
            $(self).triggerHandler('items-appended');
        },
        renderItem: function(item) {
            var self = this;
            return self.template({
                item: item
            });
        },
        insertItems: function(items) {
            // 必要なら上書きして使ってください
            var self = this;
            var lines = [];
            _.each(items, function($item) {
                var permalink = $item.attr('data-permalink');
                lines.push('[' + permalink + ':embed]');
            });
            Hatena.Diary.Editor.Support.currentEditor.insertLines(lines);
        }
    };


    // タブ切り替えイベントの管理
    // 変更イベントのディスパッチ
    // localStorageにバックアップ
    // 変更されたらchangeイベントを発行する
    // get()で値を取得
    // set(value)で値を設定
    // args:
    //   container: inputを含む要素
    //   backupKey: バックアップ用のキー localStorageのキーの一部になる
    Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.Tab = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.Tab.prototype = {
        // args: { container backupKey }
        init: function (args) {
            var self = this;

            self.$container = args.container;
            self.backupKey = args.backupKey;
            self.localStorageKey = 'MyCuration.Tab.' + self.backupKey;
            self.values = self.$container.find('input').map(function() { return $(this).val(); }).toArray();

            self.$container.delegate('input', 'change', function () {
                self.$container.find('label.selected').removeClass('selected');
                $(this).closest('label').addClass('selected');

                var value = $(this).val();
                self.value = value;
                try {
                    localStorage[self.localStorageKey] = value;
                } catch(ignore) {}

                $(self).triggerHandler('change');
            });

            try {
                if (localStorage[self.localStorageKey]) {
                    self.set(localStorage[self.localStorageKey]);
                }
            } catch(ignore) {}
        },
        get: function() {
            return this.value || this.values[0];
        },
        set: function(value) {
            var self = this;
            if (! _.include(self.values, value)) return;
            var $input = self.$container.find('input[value="' + value + '"]');
            $input.click();
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Archive = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Archive.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        init: function (args) {
            var self = this;

            self.$indicator = args.container.find('.indicator');

            self.parent.prototype.init.call(self, args);

            self._templatesByType = {
                'default': _.template(self.$container.find('.archive-item-template').html())
            };
        },
        bindEvents: function () {
            var self = this;

            self.parent.prototype.bindEvents.call(self);

            self.$submit = self.$container.find('.archive-keyword-submit');
            self.$keyword = self.$container.find('.archive-keyword');

            self.$submit.click(function (event) {
                self.initLoadCondition();
                self.requestReload();
                return false;
            });

            self.$keyword.keydown(function (event) {
                if (keyString(event) == 'RET') {
                    self.initLoadCondition();
                    self.requestReload();
                    return false;
                }
            });
        },
        initLoadCondition: function() {
            this.itemsReachedEnd = false;
            this.untilEpoch = null;
        },
        serviceName: 'Archive',
        enableAutoPager: true,
        pasteReverseOrder: true,
        willRequestLoadItems: function (more) {
            return true;
        },
        loadItems: function(more) {
            var self = this;

            var term = self.$keyword.val();

            var data = {
                permission: 'public',
                q: term
            };

            if (self.untilEpoch) {
                data.until = self.untilEpoch;
            }

            return $.ajax({
                url: 'entries.json',
                data: data,
                type: 'GET',
                dataType: 'json'
            }).then(function(json){
                if (json.entries.length > 0) {
                    self.untilEpoch = Date.parse(json.entries[json.entries.length - 1].created) / 1000;
                    self.itemsReachedEnd = !json.has_more;
                    return $.Deferred().resolve(json);
                } else {
                    // ヒット件数0なのでエラーとする
                    return $.Deferred().reject();
                }
            });
        },
        renderItem: function(item) {
            var self = this;

            item.datetimeEpoch = Date.parse(item.datetime);

            var template = self._templateByType('default');

            return template({
                entry: item,
                trim: function(text, chars) {
                        if (text.length <= chars) return text;
                        return text.substr(0, chars - 1) + ' ...';
                      }
            });
        },
        _templateByType: function(type) {
            var self = this;
            return self._templatesByType[type] || self._templatesByType['default'];
        },
        insertItems: function(items) {
            var self = this;

            var lines = {
                hatena:   [],
                markdown: []
            };
            _.each(items, function($item) {
                var item = {
                    permalink: $item.attr('data-permalink')
                };

                lines.hatena.push('[' + item.permalink + ':embed]', '[' + item.permalink + ':title]');
                lines.markdown.push('[' + item.permalink + ':embed]', '[' + item.permalink + ':title]');
            });

            Hatena.Diary.extractSyntax(lines.hatena).done(function(data) {
                lines.html = ['', data.html, ''];
            }).fail(function(error) {
                lines.html = lines.hatena;
                Hatena.Diary.BUG(error);
            }).always(function() {
                if (Hatena.Diary.EditorConnector.isiOS() || Hatena.Diary.EditorConnector.isAndroid()) {
                    // スマフォアプリのときうまく表示できないので記法そのままにしておく
                    lines.html = lines.hatena;
                }
                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        }
    };

    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Archive.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    Hatena.Diary.Pages.Admin['user-blog-edit'].Instagram = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Instagram.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        init: function (args) {
            var self = this;

            self.parent.prototype.init.call(self, args);

            $(self).on('items-appended', function() {
                self.setPaddingLeft();
            });
        },
        serviceName: 'Instagram',
        enableAutoPager: true,
        pasteReverseOrder: true,
        loadItems: function(more) {
            var self = this;

            var data = {};

            if (more) {
                var $lastItem =  self.$itemsContainer.find('.item:last');
                data.max_id = $lastItem.attr('data-next-max-id');
            }

            return $.ajax({
                url: '/api/instagram/recent',
                data: data,
                type: 'GET',
                dataType: 'json'
            }).fail(function() {
                self.pleaseReAuthorize();
            }).done(function(res) {
                if (res && res.data) {
                    res.entries = res.data;
                    // テンプレートにdata-max-id入れるので各エントリに入れる
                    _.each(res.entries, function(entry) {
                        entry.next_max_id = res.next_max_id;
                    });
                }

                // next_max_idなかったらこれで終わり(autopagerが無効になる)
                if (!res.next_max_id) {
                    self.itemsReachedEnd = true;
                }

                return res;
            });
        },
        pleaseReAuthorize: function() {
            var self = this;
            self.$container.find('.disabled-box').show();
        },
        insertItems: function(items) {
            var self = this;

            var lines = {
                hatena:   [],
                markdown: []
            };
            _.each(items, function($item) {
                var item = {
                    permalink: $item.attr('data-permalink'),
                    caption: $item.attr('data-caption'),
                    type: $item.attr('data-type')
                };

                var media_url = item.permalink + 'media/?size=l';

                // 動画はiframe(:embedで展開したらiframeになる)，写真はa>img
                if (item.type === 'video') {
                    lines.hatena.push('[' + item.permalink + ':embed]');
                    lines.markdown.push('[' + item.permalink + ':embed]');
                } else {
                    lines.hatena.push('[' + item.permalink + ':image=' + media_url + ']');
                    lines.markdown.push('[![](' + media_url + ')](' + item.permalink + ')');
                }

                // captionあったらcaptionでリンク，なかったら単なるリンク
                // captionないときmarkdownではタイトル取れないのではてな記法
                if (item.caption) {
                    var caption = item.caption.replace(/\r?\n/g, '');
                    lines.hatena.push('[' + item.permalink + ':title=' + caption + ']');
                    lines.markdown.push('[' + caption + '](' + item.permalink + ')');
                } else {
                    lines.hatena.push('[' + item.permalink + ':title]');
                    lines.markdown.push('[' + item.permalink + ':title]');
                }
            });


            Hatena.Diary.extractSyntax(lines.hatena).done(function(data) {
                lines.html = [data.html];
            }).fail(function(error) {
                lines.html = lines.hatena;
                Hatena.Diary.BUG(error);
            }).always(function() {
                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        },
        setPaddingLeft: function() {
            var self = this;

            // itemsが中央に揃うよう幅を調整
            // 一列に表示されているitemsの幅の合計から，paddingLeftを決める
            //
            // |----|               |----|  padding
            // |-------------------------|  .itemsContainer
            //      |---| |---| |---|       .item
            //      ^itemsLeft
            //                      ^itemsRight
            //
            // padding = itemsContainerの幅 - (itemsRight - itemsLeft) / 2

            var $itemsContainer = $('.items');
            var $items = $('.item');
            var $firstItem = $($items[0]);
            var firstItemTop = $firstItem.position().top;
            var itemsLeft = $firstItem.position().left;
            var itemsRight = itemsLeft + $firstItem.outerWidth();
            $items.each(function() {
                var $this = $(this);
                if ($this.position().top !== firstItemTop) return false;
                itemsRight = $this.position().left + $this.outerWidth();
            });

            var itemsWidthTotal = itemsRight - itemsLeft;
            var padding = ($itemsContainer.width() - itemsWidthTotal) / 2;

            $itemsContainer.css({
                'padding-left': padding + 'px'
            });
        }
    };

    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Instagram.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    Hatena.Diary.Pages.Admin['user-blog-edit'].Evernote = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Evernote.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        init: function (args) {
            var self = this;

            self.$keywordInput = args.container.find('.evernote-search-keyword');
            self.$keywordSubmit = args.container.find('.evernote-search-keyword-submit');

            // $.extend しているので this.constructor とかが正しく追加されていない
            self.parent.prototype.init.call(self, args);
        },
        bindEvents: function () {
            var self = this;

            // $.extend しているので this.constructor とかが正しく追加されていない
            self.parent.prototype.bindEvents.call(self);

            // AmazonSearch からだいたいコピペしてきた

            self.$keywordSubmit.click(function (event) {
                self.searchByInput();
                return false;
            });

            self.$keywordInput.keydown(function (event) {
                if (keyString(event) === 'RET') {
                    self.searchByInput();
                    return false;
                }
            });

            self.$keywordInput.focus(function() {
                // 下の貼り付けボタン表示されないことがある
                // 原因わからないけどリサイズしたらボタン出てくる
                // 検索ボックスにフォーカスしたときにダメ押しでもう1回リサイズ
                setTimeout(function() {
                    self.resize();
                }, 0);
            });

            self.$itemsContainer.on('show_items', function (event, args) {
                _.each(args.notes, function (note) {
                    var $item = self.$itemsContainer.find('.item[data-item-guid=' + note.guid + ']');

                    $.ajax({
                        url: '/api/evernote/note',
                        data: {
                            content: 1,
                            guid: $item.attr('data-item-guid')
                        },
                        type: 'GET',
                        dataType: 'json'
                    }).done(function (response) {
                        if (response && response.content) {
                            var content_type = $('#syntax').val() === 'html' ? 'html' : 'plain';

                            // APIの返り値では<などがエスケープされているので戻す
                            $item.find('.evernote-search-item-body').text(_.unescape(response.content.extended[content_type]));
                            $item.find('.evernote-search-item-body-preview').text(_.unescape(response.content.extended.excerpt));

                            $item.attr('data-loaded-body', true);

                            if (response.extended.has_resource) {
                                self.appendResources({ item: $item, resources: response.resources });
                                self.previewResources({ item : $item, resources : response.resources });
                            }
                        }
                    });
                });
            });

            self.$container.on('insert_items', function (event, args) {
                var notes = args.items;
                var resources = _.chain(notes).
                        map(function (note) { return $(note).find('.evernote-item-resource').get(); }).
                        flatten().
                        value();

                self.requestInsertResources(resources);

                var note_title = _.chain(notes).
                        map(function ($item) { return $item.find('.evernote-search-item-title').text(); }).
                        find(function (note_title) { return note_title; }).
                        value();
                var entry_title = Hatena.Diary.Editor.Support.currentEditor.title.val();

                if (note_title && !entry_title) {
                    Hatena.Diary.Editor.Support.currentEditor.title.val(note_title);
                }
            });
        },
        serviceName: 'Evernote',
        syntax: function () {
            return $('#syntax').val();
        },
        loadItems: function () {
            var self = this;
            var data = {
                filter_order: 'created'
            };

            return $.ajax({
                url: '/api/evernote/notes_metadata',
                data: data,
                type: 'GET',
                dataType: 'json'
            }).pipe(function(response) {
                if (!response) return response;

                if (!response.is_error) {
                    response.entries = response.notes;
                } else if (response.is_error && response.error_details.type === 'auth_expired') {
                    self.$container
                        .html(self.$container.find('.auth-expired-template').html())
                        .removeClass('enabled').addClass('disabled');
                    return response;
                }

                self.itemsReachedEnd = !response.extended.has_next;

                return response;
            }).fail(function(response) {
                if (!response) return response;

                // API利用制限に達した
                var responseText = null;
                try {
                    responseText = $.parseJSON(response.responseText);
                } catch(e) {
                }
                if (responseText && responseText.is_rate_limit_reached) {
                    self.$container
                        .html(self.$container.find('.rate-limit-reached-template').html())
                        .removeClass('enabled').addClass('disabled');
                    return response;
                }
            });
        },
        previewResources: function (args) {
            var self = this;
            var $note_item = args.item;
            var resources = args.resources;

            if (resources.length <= 0) return;

            var resource = resources[0];

            var $img = $('<img/>');
            $img.attr('src', '/api/evernote/thumbnail?guid=' + resource.guid);
            $img.addClass('resource-image');

            Hatena.Diary.Util.waitForResource(function () {
                return $note_item.attr('data-loaded-body');
            }, function () {
                $note_item.find('.evernote-image-preview').append($img);
            });
        },
        appendResources: function (args) {
            var self = this;

            var $item = args.item;
            var resources = args.resources;

            $item.attr('data-has-resource', true);
            $item.addClass('has-resource');
            var $resources = _.map(resources, function (resource) {
                var $resource_node = $('<li/>');
                var attrs = {
                    'data-guid': resource.guid
                };
                $resource_node.attr(attrs);
                $resource_node.addClass('evernote-item-resource');

                return $resource_node.get(0);
            });
            $item.find('.evernote-item-resources').append($resources);
        },
        requestInsertResources: function (resources) {
            var self = this;
            var resource = resources.shift();

            if (!resource) return;

            var $resource = $(resource);
            if ($resource.attr('data-uploaded')) {
                self.insertFotolifeImage({
                    annotation    : $resource.attr('data-fotolife-annotation'),
                    html          : $resource.attr('data-fotolife-html'),
                    hex_body_hash : $resource.attr('data-hex-body-hash')
                });
                self.requestInsertResources(resources);
            } else {
                var dfd = self.requestUploadResource($resource);
                dfd.done(function () {
                    self.requestInsertResources(resources);
                });
            }
        },
        requestUploadResource: function (resource) {
            var self = this;

            return $.ajax({
                url: '/api/upload/evernote/resource',
                data: {
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc'),
                    guid: resource.attr('data-guid')
                },
                dataType: 'json',
                type: 'POST'
            }).done(_.bind(self.onCompleteUploadingResource, self, resource));
        },
        onCompleteUploadingResource: function ($resource, response) {
            var self = this;

            $resource.attr({
                'data-uploaded' : 1,
                'data-fotolife-annotation' : response.annotation,
                'data-fotolife-html' : response.html,
                'data-hex-body-hash' : response.hex_body_hash
            });

            self.insertFotolifeImageByResource($resource);
        },
        insertFotolifeImageByResource: function ($resource) {
            var self = this;

            if (! $resource.attr('data-uploaded')) return;

            self.insertFotolifeImage({
                annotation    : $resource.attr('data-fotolife-annotation'),
                html          : $resource.attr('data-fotolife-html'),
                hex_body_hash : $resource.attr('data-hex-body-hash')
            });
        },
        insertFotolifeImage: function (args) {
            var self = this;

            var annotation = args.annotation;
            var hex_body_hash = args.hex_body_hash;
            var html = args.html;

            var uploadingMessage = Hatena.Locale.text('uploading');
            var editor = Hatena.Diary.Editor.Support.currentEditor;
            var current_body = editor.body.val();
            var placeholder = '[evernote:' + hex_body_hash + ' ' + uploadingMessage + ']';
            var image_source = self.syntax() === 'html' ? html : '[' + annotation + ']';
            var replaced = current_body.replace(placeholder, image_source);

            editor.setValue(replaced);
        },
        resourcesAreUploaded: function ($item) {
            return _.all($item.find('.evernote-resource').get(), function ($resource) {
                return $resource.attr('data-uploaded');
            });
        },
        readyToInserted: function ($items) {
            var self = this;
            return _.all($items, function ($item) {
                var loaded_body = $item.attr('data-loaded-body');
                var has_resource = $item.attr('data-has-resource');
                var upload_completed = has_resource ? self.resourcesAreUploaded($item) : true;
                return loaded_body && upload_completed;
            });
        },
        insertItems: function(items) {
            var self = this;

            Hatena.Diary.Util.waitForResource(function () {
                return self.readyToInserted(items);
            }, function () {
                var uploadingMessage = Hatena.Locale.text('uploading');
                var lines = _.map(items, function ($item) {
                    return $item.find('.evernote-search-item-body').text().replace(/\[evernote:([^\]]*)\]/gm, '[evernote:$1 ' + uploadingMessage + ']');
                });

                Hatena.Diary.Editor.Support.currentEditor.insertLines(lines);

                self.$container.trigger('insert_items', { items: items, lines: lines });
            });
        },
        showItems: function (items) {
            var self = this;
            self.parent.prototype.showItems.call(self, items);

            self.$itemsContainer.trigger('show_items', {notes: items});
        },
        searchByInput: function () {
            var self = this;

            self.search(self.$keywordInput.val());
        },
        search: function (keyword) {
            var self = this;

            if (typeof keyword != 'string') return false;

            keyword = keyword.replace(/^\s*/, '');
            keyword = keyword.replace(/\s*$/, '');

            // キーワードが空だったらリロード
            if (keyword.length === 0) {
                self.requestReload();
                return false;
            }

            // AmazonSearch からだいたいコピペ

            // if (self._searchingKeyword == keyword && self._searchingCategory == category) return false;

            if (self._searchDeferred) {
                self._searchDeferred.reject();
            }

            self.ajaxStarted();

            self._searchingKeyword = keyword;

            var currentAjax;
            var dfd = $.Deferred().done(function() {
            }).fail(function() {
                if (currentAjax) {
                    // セッション終了時に前のajaxをキャンセル
                    currentAjax.abort();
                }
            }).always(function() {
                self.ajaxFinished();
            });

            self.$itemsContainer.find('.evernote-search-item').remove();

            var searchWithOffset = function(offset) {
                self.ajaxStarted();

                currentAjax = $.ajax({
                    url: '/api/evernote/notes_metadata',
                    data: {
                        offset: offset,
                        filter_order: 'created',
                        filter_words: keyword
                    }
                }).done(function (response) {
                    self.showItems(response.notes);

                    if (response.extended.has_next && response.extended.next_offset) {
                        searchWithOffset(response.extended.next_offset);
                    } else {
                        dfd.resolve();
                        return;
                    }
                }).fail(function (response) {
                    dfd.reject(response);
                });
            };
            searchWithOffset(0);

            self._searchDeferred = dfd;
        },
        ajaxStarted: function () {
            var self = this;

            self.isAjaxing = true;

            self.$keywordSubmit.prop('disabled', true);
            self.$indicator.show();
            self.$errorMessage.hide();
        },
        ajaxFinished: function () {
            var self = this;

            self.isAjaxing = false;

            self.$keywordSubmit.prop('disabled', false);
            self.$errorMessage.hide();
            self.$indicator.hide();
        }
    };
    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Evernote.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        serviceName: 'Miil',
        enableAutoPager: true,
        pasteReverseOrder: true,
        init: function (args) {
            var self = this;

            self.parent.prototype.init.call(self, args);

            self.userManager = new Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserManager({
                container: self.$container
            });

            $(self.userManager).on('registered', function() {
                self.resetUser();
                self.requestLoadItems();
            });

            $(self.userManager).on('unregistered', function() {
                self.resetUser();
            });
        },
        loadItems: function(is_more) {
            var self = this;

            var dfd = $.Deferred();

            if (!(self.userManager && self.userManager.getUser())) {
                dfd.reject();
                return dfd;
            }

            var user = self.userManager.getUser();

            if (is_more) {
                user.forward();
            }
            user.load().done(function(data) {
                var photos = data.photos;
                _.each(photos, function(photo) {
                    photo.thumbnail_url = photo.url + '=s72';
                });

                dfd.resolve({
                    entries: photos
                });
            }).fail(function() {
                dfd.reject();
                self.itemsReachedEnd = true;
            });

            return dfd;
        },
        insertItems: function(items) {
            var self = this;

            var lines = [];

            _.each(items, function($item) {
                if ($('#syntax').val() === 'html') {
                    lines.push(self.editorTemplate({
                        item: {
                            permalink_url: $item.attr('data-permalink'),
                            image_url: $item.attr('data-image-url'),
                            title: $item.attr('data-title')
                        }
                    }));
                } else {
                    lines.push('[' + $item.attr('data-permalink') + ':image=' + $item.attr('data-image-url') + ']');
                    if ($item.attr('data-title')) {
                        lines.push($item.attr('data-title'));
                    }
                }
            });
            Hatena.Diary.Editor.Support.currentEditor.insertLines(lines);
        },
        resetUser: function() {
            var self = this;

            self.itemsReachedEnd = false;
            self.removeItems();

            if (self.userManager && self.userManager.getUser()) {
                self.userManager.getUser().rewind();
            }
        }
    };

    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    // ユーザー連携機能，UserLoaderからUserを受け取って保持する，連携UIの管理
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserManager = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserManager.prototype = {
        init: function (args) {
            var self = this;

            self.$container = args.container;

            self.$input = self.$container.find('.miil-user-name');
            self.$registerButton = self.$container.find('.register-button');
            self.$unregisterButton = self.$container.find('.unregister-button');

            self.$userImage = self.$container.find('.user-image');
            self.$name = self.$container.find('.user-name');
            self.$nameLink = self.$container.find('.user-name-link');
            self.$userNotFound = self.$container.find('.user-not-found-error');

            self.userLoader = new Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserLoader();

            self.bindEvents();

            self.tryRegisterFromInput();
        },
        bindEvents: function() {
            var self = this;

            self.$registerButton.on('click', function() {
                self.tryRegisterFromInput();
                return false;
            });

            self.$input.on('keydown', function(event) {
                if(keyString(event) === 'RET') {
                    self.tryRegisterFromInput();
                    return false;
                }
            });

            self.$unregisterButton.on('click', function() {
                self.unregister();
                return false;
            });
        },
        // inputに入力された値から認証を試みる
        tryRegisterFromInput: function() {
            var self = this;

            var user_name = self.$input.val();
            if (!user_name) return;
            self.tryRegister(user_name);
        },
        // validなユーザーと連携しているときUserのインスタンスを返す
        getUser: function() {
            var self = this;

            return self.currentUser;
        },
        // 指定された名前のユーザーとの連携を試みる
        tryRegister: function(user_name) {
            var self = this;

            self.userLoader.loadUser(user_name).done(function(user) {
                if (user.exists()) {
                    self.onUserFound(user);
                } else {
                    self.unregister();
                    self.$userNotFound.show();
                }
            });
        },
        // registerするときのいろいろ，状態書き換え，view更新
        onUserFound: function(user) {
            var self = this;

            self.currentUser = user;
            self.setUserImage(user.getImage() || self.DEFAULT_UESR_IMAGE);
            self.$name.text(user.getName());
            self.$nameLink.attr('href', 'http://miil.me/u/' + user.getName());
            self.$userNotFound.hide();
            self.$container.addClass('registered');
            Hatena.Diary.Pages.Admin['*'].saveBlogConfig('miil_user_name', user.getName());
            $(self).trigger('registered');
            $(window).resize();     // headerの高さ変わるため
        },
        // 連携解除する
        // view更新
        unregister: function() {
            var self = this;

            $(self).trigger('unregistered');

            self.currentUser = null;
            self.$input.focus();

            self.setUserImage(self.DEFAULT_UESR_IMAGE);
            self.$userNotFound.hide();
            Hatena.Diary.Pages.Admin['*'].saveBlogConfig('miil_user_name', '');
            self.$container.removeClass('registered');
            $(window).resize();     // headerの高さ変わるため
        },
        setUserImage: function(url) {
            var self = this;

            self.$userImage.attr('src', url);
        },
        DEFAULT_UESR_IMAGE: 'http://assets.miil.me/images/pc/user.jpg'
    };

    // Userクラスの生成，キャッシュ
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserLoader = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.UserLoader.prototype = {
        init: function (args) {
            var self = this;

            self.users = {};
        },
        loadUser: function(name) {
            var self = this;

            var dfd = $.Deferred();

            if (!self.users[name]) {
                self.users[name] = new Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.User(name);
            }

            self.users[name].load().always(function() {
                dfd.resolve(self.users[name]);
            });

            return dfd;
        }
    };

    // miilのユーザー一人に対応するオブジェクト
    // photosの読み込み，プロフィール情報を返す，ページング
    // オートページャ対応のためHatena.Diary.LazyListを使っています
    // load() → forward() → load() みたいに順番に読むとページングできる
    // rewind() → forward() するとページングが最初に戻る
    // 最初に戻すには，rewindPhotosCursor()してください
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.User = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Miil.User.prototype = {
        init: function (name) {
            var self = this;

            self.name = name;

            // photos_loaderの最初のページ
            self.photos_loader_root = new Hatena.Diary.LazyList(_.bind(self._photosLoaderBody, self));

            // ページング用のカーソルみたいなやつ
            self.photos_loader = self.photos_loader_root;
        },
        getName: function() {
            var self = this;

            return self.name;
        },
        // ユーザーのプロフィール画像のURL
        getImage: function() {
            var self = this;

            return self.basicData.photos[0].user.user_icon_url;

        },

        // データ読み込み関連
        load: function() {
            var self = this;

            return self.photos_loader.promise();
        },
        // loaderを進める 次にloadしたら通信が発生するかもしれない
        forward: function() {
            var self = this;
            self.photos_loader = self.photos_loader.next();
        },
        // loaderを最初に巻き戻す
        rewind: function() {
            var self = this;
            self.photos_loader = self.photos_loader_root;
        },
        // ユーザーがmiilに存在するか
        exists: function() {
            var self = this;

            return self.photos_loader_root.promise().state() === "resolved";
        },
        _photosURL: function(data) {
            var self = this;

            return 'http://api.miil.me/api/users/' + self.name + '/photos/public.json?' + $.param(data);
        },
        _getNextPageFromReceivedData: function(data) {
            if (!data) return;
            if (!data.next_url) return;

            var match = data.next_url.match(/page=(\d+)/);
            if (!match) return;
            return match[1];
        },
        // API読み込みの本体，前のレスポンスから次のURLを決める
        _photosLoaderBody: function(prev) {
            var self = this;

            // データ揃ったらresolve
            var photos_loaded = $.Deferred();

            // GETするページのURLが決まったらresolve
            var page_determined = $.Deferred();

            // 前の通信結果から次のページ決める
            if (prev) {
                prev.promise().done(function(data) {
                    var next_page = self._getNextPageFromReceivedData(data);
                    if (!next_page) {
                        page_determined.reject();
                    }
                    page_determined.resolve(next_page);
                }).fail(function() {
                    page_determined.reject();
                });
            } else {
                // 初回はnext_pageなしで通信
                page_determined.resolve();
            }

            page_determined.done(function(next_page) {
                var data = {};

                if (next_page) {
                    data.page = next_page;
                }

                $.ajax({
                    url: '/api/external/json',
                    data: {
                        url: self._photosURL(data)
                    },
                    type: 'GET',
                    dataType: 'json'
                }).done(function(data) {
                    if (data && data.photos && data.photos.length > 0) {
                        if(!self.basicData) {
                            // プロフィール画像などは同期的に返せるように入れておく
                            self.basicData = data;
                        }
                        photos_loaded.resolve(data);
                    } else {
                        // 通信に成功してもリストが空なら失敗と見なす
                        photos_loaded.reject();
                    }
                }).fail(function(res) {
                    photos_loaded.reject();
                });
            }).fail(function() {
                photos_loaded.reject();
            });

            return photos_loaded;
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Pixiv = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Pixiv.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        serviceName: 'Pixiv',
        enableAutoPager: true,
        page: 1,
        init: function (args) {
            var self = this;

            self.$container    = args.container;

            self.parent.prototype.init.call(self, args);
        },
        loadItems: function(is_more) {
            var self = this;

            return $.ajax({
                url: '/api/pixiv/my_works',
                data: {
                    page: self.page++
                }
            }).success(function(res) {
                self.itemsReachedEnd = !(res.entries && res.entries.length > 0);
            }).fail(function(res) {
                self.pleaseReAuthorize();
                self.itemsReachedEnd = true;
            });
        },
        pleaseReAuthorize: function() {
            var self = this;
            self.$container.find('.disabled-box').show();
        },
        insertItems: function(items) {
            var self = this;
            var hatena_syntaxes = [];
            _.each(items, function($item) {
                var permalink = $item.attr('data-permalink');
                hatena_syntaxes.push(self.editorTemplate({
                    item: {
                        id: $item.attr('data-id'),
                        image_url: $item.attr('data-image-url')
                    }
                }));
                hatena_syntaxes.push('[' + permalink + ':title]');
            });

            var lines = {
                hatena: hatena_syntaxes,
                markdown: hatena_syntaxes,
                html: hatena_syntaxes
            };

            Hatena.Diary.extractSyntax(hatena_syntaxes).done(function(data) {
                lines.html = [data.html];
            }).fail(function(error) {
                lines.html = lines.hatena;
                Hatena.Diary.BUG(error);
            }).always(function() {
                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        }
    };
    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Pixiv.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    // レストラン検索サイドバー
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        serviceName: 'Gourmet',
        enableAutoPager: true,
        init: function (args) {
            var self = this;

            self.$container    = args.container;

            var $searchInput  = args.container.find('.gourmet-keyword');
            var $searchSubmit = args.container.find('.gourmet-keyword-submit');

            self.gourmetSearcher = new Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet.Searcher({
                searchInput : $searchInput
            });

            $searchSubmit.on('click', function() {
                self.requestReload();
            });
            $searchInput.on('keydown', function (e) {
                if (keyString(e) === 'RET') {
                    self.requestReload();
                    return false;
                }
                return true;
            });

            $searchInput.focus(function() {
                self.$container.find('.gourmet-description').hide();
            });

            self.setupFormatSwitcher(); // 貼り付け形式切替

            self.parent.prototype.init.call(self, args);
        },
        loadItems: function(is_more) {
            var self = this;

            var dfd = $.Deferred();

            if (is_more) {
                self.gourmetSearcher.forward();
            }
            else {
                self.gourmetSearcher.reset();
                self.itemsReachedEnd = false;
            }

            self.gourmetSearcher.load().done(function(data) {
                dfd.resolve(data);
            }).fail(function() {
                dfd.reject();
            }).always(function() {
                self.itemsReachedEnd = ! self.gourmetSearcher.has_next;
            });

            return dfd;
        },
        insertItems: function(items) {
            var self = this;

            var lines = [];
            var suffix = self.$container.find('[name="gourmet-format"]:checked').val();
            _.each(items, function($item) {
                var syntax = $item.attr('data-syntax');
                syntax = syntax.replace(/\]$/, ":" + suffix + "]");
                lines.push(syntax);
            });

            Hatena.Diary.EditorConnector.insertLines({
                hatena: lines,
                markdown: lines,
                html: lines
            });
        },
        setupFormatSwitcher: function() {
            var self = this;
            var $formatsContainer = self.$container.find('.gourmet-formats');
            $formatsContainer.on('change', function(e) {
                var $input = $(e.target);
                $formatsContainer.find('label.selected').removeClass('selected');
                $input.closest('label').addClass('selected');
            });
        }
    };
    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    // Gourmetの検索を管理するオブジェクト
    // load() → forward() → load() みたいに順番に読むとページングできる
    // resetすると、ページングや検索wordが設定し直される
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet.Searcher = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gourmet.Searcher.prototype = {
        init: function (args) {
            var self = this;
            self.$searchInput = args.searchInput;
            self.reset();
        },

        load: function() {
            var self = this;
            var dfd = $.Deferred();

            var searchKeyword = self.searchKeyword;

            if (!searchKeyword) {
                dfd.reject();
                return dfd;
            }

            // レストラン検索APIから情報を取ってくる
            $.ajax({
                url : "/api/gourmet/search",
                type : "GET",
                data : {
                    word : searchKeyword,
                    page : self.page
                },
                dataType: "json"
            }).done(function(data) {
                if (data.entries.length === 0) {
                    // データが無くなったら次ページなし
                    self.has_next = false;
                }
                dfd.resolve(data);
            }).fail(function() {
                // データが取得できなかったら次ページなし
                self.has_next = false;
                dfd.reject();
            });

            return dfd;
        },
        forward: function() {
            var self = this;
            self.page++;
        },
        reset: function() {
            var self = this;
            self.page = 1;
            self.has_next = true; // 次がなくなったらfalseに
            self.resetSearchKeyword();
        },
        resetSearchKeyword: function() {
            var self = this;
            self.searchKeyword = self.$searchInput.val();
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Nicovideo = function () { this.init.apply(this, arguments); };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Nicovideo.prototype = {
        init: function (args) {
            var self = this;

            self.$container = args.container;
            self.$itemsContainer = self.$container.find('.items');
            self.$input = self.$container.find('.nicovideo-keyword');
            self.$inputReset = self.$container.find('.input-text-reset');
            self.$pasteButton = self.$container.find('.paste-button');
            self.$formatPlayer = self.$container.find('.nicovideo-formats label.player');
            self.$formatThumbnail = self.$container.find('.nicovideo-formats label.thumbnail');

            self.setupFormatSwitcher('.nicovideo-formats');

            self.bindEvents();
        },

        bindEvents: function () {
            var self = this;

            self.$input.keyup(_.debounce(function () {
                if(self.$input.val().length === 0) return;

                self.updateThumb();
            }, 500));

            self.$input.keydown(function (e) {
                if (keyString(e) === 'RET') {
                    if (self.findItem().length > 0) {
                        self.insertItem();
                        Hatena.Diary.trackEvent(self.$pasteButton.attr('data-track-name'));
                    }
                    return false;
                }
            });

            self.$pasteButton.click(function () {
                self.insertItem();
            });

            self.setupInputReset();
        },

        setupInputReset : function () {
            var self = this;

            self.$inputReset.click(function () {
                self.$input.val('');
                self.$input.focus();
                self.$inputReset.hide();

                return false;
            });

            self.$input.keyup(function (e) {
                if (self.$input.val().length > 0) {
                    self.$inputReset.show();
                } else {
                    self.$inputReset.hide();
                }
            });
        },

        findItem: function () {
            return this.$container.find('.items > .item');
        },

        itemChanged: function () {
            var self = this;

            var $item = self.findItem();

            if ($item.length === 0) {
                self.setPasteButtonStatus(false);
                return;
            }

            self.setPasteButtonStatus(true);

            var $format_player = self.$formatPlayer;
            var $format_thumbnail = self.$formatThumbnail;

            // videoのとき, 貼り付け形式は'動画' 'サムネイル' 'リンク'
            // それ以外のとき, 貼り付け形式は'サムネイル' 'リンク'
            if ($item.data('type') === 'video') {
                // 左端は'動画'なのでそれにスタイルを当てる
                $format_player.addClass('format-left');
                $format_thumbnail.removeClass('format-left');

                $format_player.show();
            } else {
                // 左端は'サムネイル'なのでそれにスタイルを当てる
                $format_player.removeClass('format-left');
                $format_thumbnail.addClass('format-left');

                if($format_player.is('.selected')) {
                    $format_player.removeClass('selected');
                    $format_player.find('input').prop('checked', false);

                    $format_thumbnail.addClass('selected');
                    $format_thumbnail.find('input').prop('checked', true);
                }

                $format_player.hide();
            }
        },

        setPasteButtonStatus : function (status) {
            var self = this;

            if (status) {
                self.$pasteButton.removeClass('disabled').addClass('enabled').prop('disabled', false);
            } else {
                self.$pasteButton.addClass('disabled').removeClass('enabled').prop('disabled', true);
            }
        },

        updateThumb: function () {
            var self = this;

            var input = self.$input.val();

            var canonical_input = self.removeParamsFromURL(input);

            var info = self.detectInfo(canonical_input);

            if (!info) {
                return;
            }

            var source = self.renderPreviewTemplate(info.type, {
                id: info.id
            });

            var $item = $($.trim(source));
            $item.data('type', info.type);
            $item.data('id', info.id);

            self.$itemsContainer.html($item);

            self.itemChanged();
        },

        removeParamsFromURL: function (url) {
            return url.replace(/\?.*$/, '');
        },

        // return: { id: 'sm2168098', type: 'video' }
        // 読み取れない場合はfalseを返す
        detectInfo: function (input) {
            var self = this;

            if (self.isNicovideoID(input)) {
                return self.detectInfoFromID(input);
            } else {
                return self.detectInfoFromURL(input);
            }
        },

        detectInfoFromID: function (id) {
            var self = this;

            return {
                id: id,
                type: self.detectIDType(id)
            };
        },

        detectInfoFromURL: function (input) {
            // コピペミス等を考慮してある程度URLっぽかったら良いことにする
            // 正しいURLはこんなの: http://www.nicovideo.jp/watch/sm2168098
            var regexps = {
                video: new RegExp("nicovideo.jp/watch/(\\w{0,2}\\d+)$"),
                community: new RegExp("com.nicovideo.jp/community/(co\\d+)$"),
                mylist: new RegExp("nicovideo.jp/mylist/(\\d+)$")
            };

            var info = false;
            _.find(regexps, function (regexp, type) {
                var result = regexp.exec(input);
                if (result) {
                    info = { id: result[1], type: type };
                    return true;
                } else {
                    return false;
                }
            });

            return info;
        },

        isNicovideoID: function (str) {
            // sm2168098, nm20097844など
            // 公式チャンネルの動画だと数字のみの場合もある(ex: http://www.nicovideo.jp/watch/1365403220)
            return (/^(\w{2})?\d+$/).test(str);
        },

        // マイリストはprefixがなくて判別不可能なので諦める
        detectIDType: function (id) {
            var prefix = id.slice(0, 2);
            if (prefix === 'co') {
                return 'community';
            } else {
                return 'video';
            }
        },

        renderPreviewTemplate: function (type, data) {
            return _.template(this.$container.find('.template-nicovideo-preview-' + type).html(), data);
        },

        renderTemplate: function (type, format, data) {
            var self = this;

            var $template = self.$container.find('.template-nicovideo-' + type + '-' + format);

            var source = _.template($.trim($template.html()), data);

            return source;
        },

        insertItem: function () {
            var self = this;

            var lines = [];

            var format = self.$container.find('[name="nicovideo-format"]:checked').val();

            var $item  = self.findItem();
            var source = self.renderTemplate($item.data('type'), format, { id: $item.data('id') });

            lines.push(source);

            var lines_data = {
                html: lines,
                hatena: lines,
                markdown: lines
            };

            var editor = Hatena.Diary.Editor.Support.currentEditor;
            // 見たまま編集モードでかつ貼り付け形式がリンクのとき, 記法展開する
            if (editor.mode === 'html' && format === 'link') {
                Hatena.Diary.extractSyntax(lines).done(function(data) {
                    lines_data.html = [data.html];
                    Hatena.Diary.EditorConnector.insertLines(lines_data);
                }).fail(function (error) {
                    Hatena.Diary.BUG(error);
                    Hatena.Diary.EditorConnector.insertLines(lines_data);
                });
            } else {
                Hatena.Diary.EditorConnector.insertLines(lines_data);
            }
        },

        setupFormatSwitcher: function (format_container_selector) {
            var self = this;
            var $format_container = self.$container.find(format_container_selector);

            $format_container.on('change', function (e) {
                var $input = $(e.target);

                $format_container.find('label.selected').removeClass('selected');
                $input.closest('label').addClass('selected');
            });
        }
    };

    // Gistサイドバー
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        serviceName: 'Gist',
        enableAutoPager: true,
        pasteReverseOrder: true,
        init: function (args) {
            var self = this;

            self.parent.prototype.init.call(self, args);

            self.userManager = new Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserManager({
                container: self.$container
            });

            $(self.userManager).on('registered', function() {
                self.resetUser();
                self.requestLoadItems();
            });

            $(self.userManager).on('unregistered', function() {
                self.resetUser();
            });
        },
        loadItems: function(more) {
            var self = this;

            var dfd = $.Deferred();

            if (!(self.userManager && self.userManager.getUser())) {
                dfd.reject();
                return dfd;
            }

            var user = self.userManager.getUser();

            if (more) {
                user.forward();
            }

            user.load().done(function(gists) {
                dfd.resolve({
                    entries: gists
                });
            }).fail(function(msg) {
                dfd.reject(msg);
                self.itemsReachedEnd = true;
            });

            return dfd;
        },
        showItems: function(items) {
            var self = this;
            var source = '';

            _.each(items, function (item) {

                var description_short;
                if (item.description) {
                    description_short = (item.description.length > 50) ?
                        item.description.substr(0, 50) + " ..." : item.description;
                }
                else {
                    description_short = '';
                }

                var language = _.values(item.files)[0].language;

                source += self.template({
                    item: item,
                    description: ((description_short) ? description_short : "gist" + item.id),
                    language: (language) ? language : "Unknown"
                });
            });
            self.$indicator.before(source);
            Hatena.Locale.updateTimestamps(self.$container[0]);
            $(self).triggerHandler('items-appended');
        },
        insertItems: function(items) {
            var self = this;
            var lines = [];
            var mode = Hatena.Diary.Editor.Support.currentEditor.mode;

            _.each(items, function($item) {
                var description = $item.data('description');
                // embed記法内にMarkdownの記号があると, embedとして展開されないのでエスケープする
                // [http://gist/:embed#foo `bar`] -> [http://gist/:embed#foo \`bar\`]
                if (mode === 'markdown') {
                    description = self.escape_markdown_chars(description);
                }

                var escaped_description = self.escape_text_for_description(description);
                var html_url = $item.data('html-url');

                lines.push('[' + html_url + ':embed#' + escaped_description + ']');

                if (mode === 'html') {
                    lines.push('<a href="' + html_url + '">' + escaped_description + '</a>');
                }
                else if (mode == 'hatena') {
                    lines.push('[' + html_url + ':title=' + escaped_description + ']');
                }
                else {
                    lines.push('[' + escaped_description + '](' + html_url + ')');
                }
            });

            Hatena.Diary.Editor.Support.currentEditor.insertLines(lines);
        },
        escape_text_for_description: function(text){
            text = text.replace(/[\n\[\]]/g, "");
            return _.escape(text);
        },
        escape_markdown_chars: function(text) {
            return text.replace(/[\\_\*`]/g, "\\$&");
        },
        resetUser: function() {
            var self = this;

            self.itemsReachedEnd = false;
            self.removeItems();

            if (self.userManager && self.userManager.getUser()) {
                self.userManager.getUser().rewind();
            }
        }
    };

    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    // ユーザー連携機能，UserLoaderからUserを受け取って保持する，連携UIの管理
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserManager = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserManager.prototype = {
        init: function (args) {
            var self = this;

            self.$container = args.container;

            self.$input = self.$container.find('.gist-user-name');
            self.$registerButton = self.$container.find('.register-button');
            self.$unregisterButton = self.$container.find('.unregister-button');

            self.$userImage = self.$container.find('.user-image');
            self.$name = self.$container.find('.user-name');
            self.$nameLink = self.$container.find('.user-name-link');
            self.$userNotFound = self.$container.find('.user-not-found-error');
            self.$apiLimit = self.$container.find('.api-limit-error');
            self.$ajaxError = self.$container.find('.ajax-error');

            self.userLoader = new Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserLoader();

            self.bindEvents();

            self.tryRegisterFromInput();
        },
        bindEvents: function() {
            var self = this;

            self.$registerButton.on('click', function() {
                self.tryRegisterFromInput();
                return false;
            });

            self.$input.on('keydown', function(event) {
                if(keyString(event) === 'RET') {
                    self.tryRegisterFromInput();
                    return false;
                }
            });

            self.$unregisterButton.on('click', function() {
                self.unregister();
                return false;
            });
        },
        // inputに入力された値から認証を試みる
        tryRegisterFromInput: function() {
            var self = this;

            var user_name = self.$input.val();
            if (!user_name) return;
            self.tryRegister(user_name);
        },
        // validなユーザーと連携しているときUserのインスタンスを返す
        getUser: function() {
            var self = this;

            return self.currentUser;
        },
        // 指定された名前のユーザーとの連携を試みる
        tryRegister: function(user_name) {
            var self = this;

            // loadUser後なのでuser.existsが使える
            self.userLoader.loadUser(user_name).done(function(user) {
                self.onUserFound(user);
            }).fail(function(msg) {
                self.unregister();
                if (msg === 'api') {
                    self.$apiLimit.show();
                }
                else if (msg === 'ajax') {
                    self.$ajaxError.show();
                }
                else {
                    self.$userNotFound.show();
                }
            });
        },
        // registerするときのいろいろ，状態書き換え，view更新
        onUserFound: function(user) {
            var self = this;

            self.currentUser = user;
            self.setUserImage(user.getImage());
            self.$name.text(user.getName());
            self.$nameLink.attr('href', 'http://gist.github.com/' + user.getName());
            self.$userNotFound.hide();
            self.$apiLimit.hide();
            self.$ajaxError.hide();
            self.$container.addClass('registered');
            Hatena.Diary.Pages.Admin['*'].saveBlogConfig('gist_user_name', user.getName());
            $(self).trigger('registered');
            $(window).resize();     // headerの高さ変わるため
        },
        // 連携解除する
        // view更新
        unregister: function() {
            var self = this;

            $(self).trigger('unregistered');

            self.currentUser = null;
            self.$input.focus();

            self.setUserImage(self.DEFAULT_UESR_IMAGE);
            self.$userNotFound.hide();
            self.$apiLimit.hide();
            self.$ajaxError.hide();
            Hatena.Diary.Pages.Admin['*'].saveBlogConfig('gist_user_name', '');
            self.$container.removeClass('registered');
            $(window).resize();     // headerの高さ変わるため
        },
        setUserImage: function(url) {
            var self = this;

            self.$userImage.attr('src', url);
        }
    };

    // Userクラスの生成，キャッシュ
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserLoader = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.UserLoader.prototype = {
        init: function (args) {
            var self = this;

            self.users = {};
        },
        loadUser: function(name) {
            var self = this;

            var dfd = $.Deferred();

            if (!self.users[name]) {
                self.users[name] = new Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.User(name);
            }

            self.users[name].load().done(function() {
                    dfd.resolve(self.users[name]);
            }).fail(function(msg) {
                dfd.reject(msg);
            });

            return dfd;
        }
    };

    // gistのユーザー一人に対応するオブジェクト
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.User = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Gist.User.prototype = {
        init: function (name) {
            this.name = name;
            this.page = 1;
            this._exists = false;
        },
        getName: function() {
            return this.name;
        },
        getImage: function() {
            return this.info.avatar_url;
        },
        load: function() {

            var self = this;
            var dfd = $.Deferred();

            var data = {
                page: self.page,
                per_page: 20
            };

            $.ajax({
                url: 'https://api.github.com/users/' + self.name + '/gists',
                data: data,
                type: 'GET',
                dataType: 'jsonp',
                jsonp: 'callback'
            }).done(function(res) {
                // API制限に達したとき
                if (res && res.data.message && res.data.message !== 'Not Found') {
                    dfd.reject('api');
                } else  if (res && res.data.length > 0) {
                    // ユーザ情報(アイコンなど)は同期的に返せるように入れておく
                    self.info = res.data[0].owner;
                    self._exists = true;
                    dfd.resolve(res.data);
                } else {
                    // 通信に成功してもリストが空なら失敗と見なす
                    // (Gist.loadItems()の分岐のため)
                    dfd.reject('not found');
                }
            }).fail(function(res) {
                dfd.reject('ajax');
            });

            return dfd;
        },
        forward: function() {
            this.page++;
        },
        rewind: function() {
            this.page = 1;
        },
        exists: function() {
            return this._exists;
        }
    };
    // Gist end.

    // flickr検索サイドバー
    Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        serviceName: 'Flickr',
        enableAutoPager: true,
        init: function (args) {
            var self = this;

            self.$container    = args.container;

            self.$searchInput  = args.container.find('.flickr-keyword');
            var $searchSubmit = args.container.find('.flickr-keyword-submit');

            self.flickrSearcher = new Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr.Searcher({
                searchInput : self.$searchInput
            });

            $searchSubmit.on('click', function() {
                if (self.$searchInput.val() !== '') {
                    self.requestReload();
                }
            });
            self.$searchInput.on('keydown', function (e) {
                if (keyString(e) === 'RET') {
                    if (self.$searchInput.val() !== '') {
                        self.requestReload();
                    }
                    return false;
                }
                return true;
            });

            self.$searchInput.focus(function() {
                self.$container.find('.flickr-description').hide();
            });

            self.parent.prototype.init.call(self, args);
        },
        loadItems: function(is_more) {
            var self = this;

            var dfd = $.Deferred();

            if (is_more) {
                self.flickrSearcher.forward();
            }
            else {
                self.flickrSearcher.reset();
                self.itemsReachedEnd = false;
            }

            self.flickrSearcher.load().done(function(data) {
                dfd.resolve(data);
            }).fail(function() {
                dfd.reject();
            }).always(function() {
                self.itemsReachedEnd = ! self.flickrSearcher.has_next;
            });

            return dfd;
        },
        getUserById: function(id) {
            var self = this;
            var dfd = $.Deferred();

            // ユーザ情報取得
            $.ajax({
                url : "/api/flickr/user",
                type : "GET",
                data : {
                    user_id : id,
                    page : self.page
                },
                dataType: "json"
            }).done(function(json) {
                var data = json.data;
                dfd.resolve(data);
            }).fail(function() {
                dfd.reject();
            });

            return dfd;
        },
        insertItems: function(items) {
            var self = this;

            var lines = {
                hatena:   [],
                markdown: []
            };

            var deferreds = [];

            // 各itemの撮影者をajaxで取得し、dfdをdeferredsに登録
            // 全部取得できたら本文に挿入
            _.each(items, function($item) {

                var item = {
                    permalink: $item.attr('data-permalink'),
                    title: $item.attr('data-title'),
                    src: $item.attr('data-src'),
                    user_id: $item.attr('data-user-id')
                };

                var dfd = $.Deferred();

                self.getUserById(item.user_id).done(function (user) {
                    item.username = user.username._content;

                    lines.hatena.push('[' + item.permalink + ':image=' + item.src + ']');
                    lines.markdown.push('[![](' + item.src + ')](' + item.permalink + ')');

                    lines.hatena.push('[' + item.permalink + ':title=photo by ' + item.username + ']');
                    lines.markdown.push('[photo by ' + item.username + '](' + item.permalink + ')');
                    dfd.resolve();
                });

                deferreds.push(dfd);
            });

            $.when.apply($, deferreds).done(function () {
                Hatena.Diary.extractSyntax(lines.hatena).done(function(data) {
                    lines.html = [data.html];
                }).fail(function(error) {
                    lines.html = lines.hatena;
                    Hatena.Diary.BUG(error);
                }).always(function() {
                    Hatena.Diary.EditorConnector.insertLines(lines);
                });
            });

        },
        _requestLoadItems: function (is_more) {
            var self = this;

            if (self.$searchInput.val() === '') return;

            self.isLoading = true;
            self.$indicator.show();
            self.$errorMessage.hide();

            self.loadItems(is_more).done(function(feed) {
                if (feed.length === 0 && self.$itemsContainer.find('.item').length === 0) {
                     self.$errorMessage.show();
                }
                else {
                    self.showItems(feed);
                }
            }).fail(function(res) {
                self.$errorMessage.show();
            }).always(function() {
                self.$indicator.hide();
                self.isLoading = false;
            });
        },
        showItems: function(items) {
            var self = this;

            var source = '';
            _.each(items, function (entry) {
                source += self.template({
                    item: entry
                });
            });
            self.$indicator.before(source);
            Hatena.Locale.updateTimestamps(self.$container[0]);
            $(self).triggerHandler('items-appended');
        },
        setupFormatSwitcher: function() {
            var self = this;
            var $formatsContainer = self.$container.find('.flickr-formats');
            $formatsContainer.on('change', function(e) {
                var $input = $(e.target);
                $formatsContainer.find('label.selected').removeClass('selected');
                $input.closest('label').addClass('selected');
            });
        }
    };
    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);


    // Flickrの検索を管理するオブジェクト
    // load() → forward() → load() みたいに順番に読むとページングできる
    // resetすると、ページングや検索wordが設定し直される
    Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr.Searcher = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Flickr.Searcher.prototype = {
        init: function (args) {
            var self = this;
            self.$searchInput = args.searchInput;
            self.reset();
        },

        load: function() {
            var self = this;
            var dfd = $.Deferred();

            var searchKeyword = encodeURIComponent(self.searchKeyword);

            if (!searchKeyword) {
                dfd.reject();
                return dfd;
            }

            // キーワードで画像検索
            $.ajax({
                url : "/api/flickr/search",
                type : "GET",
                data : {
                    word : searchKeyword,
                    page : self.page
                },
                dataType: "json"
            }).done(function(json) {
                var data = json.data;
                if (data.length === 0) {
                    // データが無くなったら次ページなし
                    self.has_next = false;
                }
                dfd.resolve(data);
            }).fail(function() {
                // データが取得できなかったら次ページなし
                self.has_next = false;
                dfd.reject();
            });

            return dfd;
        },
        forward: function() {
            var self = this;
            self.page++;
        },
        reset: function() {
            var self = this;
            self.page = 1;
            self.has_next = true; // 次がなくなったらfalseに
            self.resetSearchKeyword();
        },
        resetSearchKeyword: function() {
            var self = this;
            self.searchKeyword = self.$searchInput.val();
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].Itunes = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Itunes.prototype = {
        parent: Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration,
        init: function (args) {
            var self = this;

            self.parent.prototype.init.call(self, args);

            self._templatesByType = {
                'default':    _.template(self.$container.find('.template').html()),
                'artist':     _.template(self.$container.find('.template-artist').html()),
                'collection': _.template(self.$container.find('.template-collection').html()),
                'audiobook':  _.template(self.$container.find('.template-collection').html())
            };
        },
        bindEvents: function () {
            var self = this;

            self.parent.prototype.bindEvents.call(self);

            self.$submit = self.$container.find('.itunes-keyword-submit');
            self.$media = self.$container.find('.itunes-media');
            self.$keyword = self.$container.find('.itunes-keyword');
            self.$welcomeMessage = self.$container.find('.items-welcome');

            self.$submit.click(function (event) {
                self.requestReload();
                return false;
            });

            self.$media.change(function (event) {
                self.requestReload();
                return false;
            });

            self.$keyword.keydown(function (event) {
                if (keyString(event) == 'RET') {
                    self.requestReload();
                    return false;
                }
            });
        },
        serviceName: 'Itunes',
        enableAutoPager: false,
        pasteReverseOrder: false,
        willRequestLoadItems: function (more) {
            var self = this;
            return self.$keyword.val() !== '';
        },
        loadItems: function(more) {
            var self = this;

            self.$welcomeMessage.addClass('disable');

            var term = self.$keyword.val();
            var queries = self.$media.val().split(':');
            var media = queries[0];
            var entity = queries[1];

            var data = {
                term: term,
                media: media,
                entity: entity
            };

            return $.ajax({
                url: '/api/itunes/search',
                data: data,
                type: 'GET',
                dataType: 'json'
            });
        },
        renderItem: function(item) {
            var self = this;

            var type = item.wrapperType || 'default';
            var template = self._templateByType(type);

            // 価格の表示をいい感じにする
            item._formattedPrice = '';
            if (item.formattedPrice !== undefined) {
                item._formattedPrice = item.formattedPrice;
            }
            else if (item.trackPrice !== undefined || item.collectionPrice !== undefined) {
                var amount = item.trackPrice || item.collectionPrice;
                var currency = item.currency;
                if (amount < 0) {
                    // 販売されていないアイテムのとき価格が -1 になっているので無視
                }
                else if (currency === 'JPY') {
                    item._formattedPrice = '¥' + amount;
                }
                else {
                    item._formattedPrice = currency + ' ' + amount;
                }
            }

            // ジャンルをいろいろ考慮して出す
            item._genre = '';
            if (item.genres !== undefined && _.isArray(item.genres) && item.genres.length > 0) {
                item._genre = item.genres[0];
            }
            else if (item.primaryGenreName !== undefined) {
                item._genre = item.primaryGenreName;
            }

            return template({
                item: item
            });
        },
        _templateByType: function(type) {
            var self = this;
            return self._templatesByType[type] || self._templatesByType['default'];
        },
        insertItems: function(items) {
            var self = this;

            var lines = {
                hatena:   [],
                markdown: []
            };
            _.each(items, function($item) {
                var item = {
                    permalink: $item.attr('data-permalink')
                };

                lines.hatena.push('[' + item.permalink + ':embed]');
                lines.markdown.push('[' + item.permalink + ':embed]');
            });

            Hatena.Diary.extractSyntax(lines.hatena).done(function(data) {
                lines.html = ['', data.html, ''];
            }).fail(function(error) {
                lines.html = lines.hatena;
                Hatena.Diary.BUG(error);
            }).always(function() {
                if (Hatena.Diary.EditorConnector.isiOS() || Hatena.Diary.EditorConnector.isAndroid()) {
                    // スマフォアプリのときうまく表示できないので記法そのままにしておく
                    lines.html = lines.hatena;
                }
                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        }
    };

    Hatena.Diary.Util.extend(Hatena.Diary.Pages.Admin['user-blog-edit'].Itunes.prototype, Hatena.Diary.Pages.Admin['user-blog-edit'].MyCuration.prototype);

    // PR記事表示ボタン，記事のリストを管理
    Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion.prototype = {
        init: function (args) {
            var self = this;

            self.$element = args.$element;
            self.$buttons  = args.$buttons;
            self.$cancelButtons = args.$cancelButtons;

            self.entries = _.map(self.$element.find('.promotion-entry'), function(entry) {
                return new Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion.Entry({
                    manager: self,
                    $element: $(entry)
                });
            });

            // 表示するエントリを 2件 用意する まだ読まれていないエントリ優先
            var unreadEntries = self.getUnreadEntries();
            var readEntries = self.getReadEntries();
            self.activeEntries = _.first( unreadEntries.concat( _.shuffle( readEntries ) ), 2 );

            self.updateButtonStatus();
            self.bindEvents();
        },
        updateButtonStatus: function() {
            var self = this;

            _.each( self.activeEntries, function(entry, i) {
                var $button = $( self.$buttons.get(i) );
                $button.find('.promotion-entry-title').text(entry.getTitle());
                $button.css('display', 'inline-block');

                if (entry.isRead()) {
                    $button.removeClass('active');
                }
                else {
                    $button.addClass('active');
                }
            });
        },
        bindEvents: function() {
            var self = this;

            _.each(self.$buttons, function(button,i) {
                $(button).click( function(event) {
                    self.showEntry( self.activeEntries[i] );
                } );
            });

            _.each(self.$cancelButtons, function(cancelButton,i) {
                var $cancelButton = $(cancelButton);
                $cancelButton.click( function() {
                    var entry =  self.activeEntries[i];
                    // 1度消すと復活しない
                    entry.setAsClosed();

                    self.$buttons[i].remove();
                    $cancelButton.remove();
                    return false;
                } );
            } );

            // close
            self.$element.on('click', '.promotion-close', function() {
                self.hide();
            });

            // pager
            self.$element
                .on('click', '[data-target-promotion-index]', function () {
                    var index = $(this).attr('data-target-promotion-index');
                    self.showEntryAt(index);
                })
                .on('click', '[data-rel]', function () {
                    var rel = $(this).attr('data-rel');
                    var index = self.getCurrentEntry().$element.attr('data-' + rel);
                    self.showEntryAt(index);
                });
        },
        show: function () {
            var self = this;

            self.setPosition();
            self.setupBackground();
            self.$element.show();
        },
        hide: function () {
            var self = this;

            self.$element.hide();
            self.removeBackground();
        },
        showEntryAt: function (index) {
            var self = this;

            var entry = self.entries[index];
            if (entry) {
                self.showEntry(entry);
            }
        },
        showEntry: function (entry) {
            var self = this;

            self.index = entry.getIndex();

            self.show();

            _.each(self.entries, function(entry) {
                entry.hide();
            });

            entry.show();

            self.updatePagerMarker();
            self.updateButtonStatus();
        },
        getCurrentEntry: function () {
            var self = this;
            return self.entries[self.index];
        },
        setPosition: function() {
            var self = this;

            // 中央揃え，ちょっと上のほうに配置します．admin-headerはrelativeになってるのでその分は引く
            self.$element.css({
                left: ($(document).width() - self.$element.width()) * 0.5 - self.$element.parent().offset().left,
                top: ($(document).height() - self.$element.height()) * 0.25 - $('#admin-header').height()
            });
        },
        setupBackground: function() {
            var self = this;

            var $background = $('.promotion-entry-background');
            if (!$background.get(0)) {
                $background = $('<div>').addClass('promotion-entry-background').appendTo(document.body);
            }
            $background.stop().show().animate({
                opacity: 0.3
            });
            $background.one('click', function() {
                self.hide();
            });
        },
        removeBackground: function() {
            var self = this;

            $('.promotion-entry-background').stop(true).animate({
                opacity: 0.0
            }, null, null, function() {
                $(this).hide();
            });
        },
        updatePagerMarker: function () {
            var self = this;

            self.$element.find('.promotion-pager-markers .pager-marker').each(function (i) {
                $(this).removeClass('selected');
                if (i === self.index) {
                    $(this).addClass('selected');
                }
            });
        },
        getReadEntries: function() {
            var self = this;

            return _.filter(self.entries, function(entry) {
                return entry.isRead() && ! entry.isClosed();
            });
        },
        getUnreadEntries: function() {
            var self = this;

            return _.filter(self.entries, function(entry) {
                return ! entry.isRead() && ! entry.isClosed();
            });
        }
    };

    // 貼り付けボックスを表現するクラス
    Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.prototype = {
        init: function(args) {
            var self = this;
            self.$container = args.$container;
            self.$urlInput = self.$container.find('.js-embed-url');
            self.$previewButton = self.$container.find('.js-preview-button');
            self.$embedTypes = self.$container.find('.js-embed-types');
            self.$pasteButton = self.$container.find('.js-paste-button');
            self.$showEmbedCheckbox = self.$container.find('.js-show-embed-box-on-paste-url');
            self.candidates = [];

            // showしたら返す．貼り付け成功したらresolve, 失敗したらreject
            self.session = $.Deferred();
            self.session.reject();

            self.$container.on('click', '.js-close', function() {
                self.hide();
            });

            self.$previewButton.on('click', function() {
                self.requestPreview();
            });

            self.$urlInput.on('keydown', function(event) {
                if(keyString(event) === 'RET') {
                    self.requestPreview();
                    return false;
                }
            });

            self.$pasteButton.on('click', function() {
                self.requestPaste();
            });

            self.$container.on('keydown', ':input', function(event) {
                // ESC押したら閉じる
                // Compositionイベント見てないので日本語入力中も反応するけど，URL入力する欄しかないので考慮しない
                if(keyString(event) === 'ESC') {
                    self.hide();
                    return false;
                }
            });

            if (Hatena.Diary.Browser.isIE) {
                var editor = Hatena.Diary.Editor.Support.currentEditor;
                // IEでは，モーダルウィンドウ開くボタンクリックした瞬間に，エディタの選択範囲取れないので，タイマーで監視する………
                setInterval(function() {
                    try {
                        self.selectionRangeInTimer = editor.getSelectionRange();
                        self.selectionContentInTimer = editor.isCollapsed() ? null : editor.getSelectionText();
                    } catch(ignore) {
                        // いろんなエラーが出るけど些細な問題なので無視する
                    }
                }, 1000);

            }

            // URL貼り付けたときに貼り付けボックス出すかの制御
            // デフォルトオン，オプトアウト可能
            // ページロード時にlocalStorage→inputに書き出し，以降はinputを見る
            var key = 'EmbedBox.show-embed-box-on-paste-url';
            var pasteEnabled = true;
            try {
                pasteEnabled = localStorage.getItem(key) !== 'false';
            } catch(ignore) { }
            if (pasteEnabled) {
                self.$showEmbedCheckbox.prop('checked', true);
            }

            self.$showEmbedCheckbox.on('change', function() {
                var enabled = self.isEnabledOnPasteURL();
                localStorage.setItem(key, enabled);
                Hatena.Diary.trackEvent('EmbedBox.showFromPaste.setEnable.' + enabled);
            });

            $(document).on('show-embed-box', function() {
                self.show();
            });

            self.$embedTypes.on('change', ':input', function() {
                var $input = $(this);
                self.$embedTypes.find('.js-embed-type.selected').removeClass('selected');
                $input.parents('.js-embed-type').toggleClass('selected');
            });

            self.$embedTypes.on('dblclick', '.js-embed-type', function() {
                self.requestPaste();
            });
        },
        // 貼り付け時に貼り付けボックス開くの有効かを返す
        isEnabledOnPasteURL: function() {
            return this.$showEmbedCheckbox.prop('checked');
        },
        // モーダルウィンドウ開く
        show: function() {
            var self = this;
            if (self.isShown()) return;

            self.$container.css('left', ($(window).width()-self.$container.width())/2);

            self.$embedTypes.find('.js-embed-type.selected').removeClass('selected');

            Hatena.Diary.Window.show(self.$container, {
                showBackground: true,
                destroy : function () {
                    self.onHide();
                }
            });

            _.defer(function() {
                self.$urlInput.focus()[0].select();
            });

            self.checkSelection();

            Hatena.Diary.trackEvent('EmbedBox.show');

            self.session = $.Deferred();
            return self.session.promise();
        },
        setURL: function(url) {
            this.$urlInput.val(url);
        },
        isShown: function() {
            return this.$container.is(':visible');
        },
        // モーダルウィンドウ閉じる
        hide: function() {
            var self = this;
            Hatena.Diary.Window.hide(self.$container);
        },
        // モーダルウィンドウ閉じるときに呼ばれるcallback
        onHide: function() {
            var self = this;
            self.session.reject();
            self.reset();
        },
        // モーダルウィンドウ開いたときのエディタの選択範囲を保存しておく
        checkSelection: function() {
            var self = this;
            if (!Hatena.Diary.Browser.isIE) {
                var editor = Hatena.Diary.Editor.Support.currentEditor;
                self.selectionRange = editor.getSelectionRange();
                self.selectionContent = editor.isCollapsed() ? null : editor.getSelectionText();
            } else {
                // IEでは，直前の値を使う
                self.selectionRange = self.selectionRangeInTimer;
                self.selectionContent = self.selectionContentInTimer;
            }
        },
        // 入力されたURLをプレビューする
        requestPreview: function() {
            var self = this;

            var url = self.$urlInput.val();
            if (!url) return;

            // ロケーションバーからコピーするとプロトコル抜けるのへのおもてなし
            if (!url.match(/^https?:\/\//)) {
                url = 'http://' + url;
            }

            // :title とか貼ってしまうのの対策
            url = url.replace(/^(https?:\/\/.+):[^\d+]+$/, function(_, before_colon, after_colon) {
                return before_colon;
            });

            self.reset();

            // showしたときちょっと置いてfocusしてるので，こっちも
            _.defer(function() {
                self.$pasteButton.attr('disabled', false).removeClass('disabled').focus();
            });

            if (self.selectionRange && self.selectionContent) {
                self.candidates.push(self.createQuoteCandidate(url, self.selectionContent));
            }
            self.candidates.push(self.createImageCandidate(url));
            self.candidates.push(self.createEmbedCandidate(url));
            self.candidates.push(self.createTitleCandidate(url));
            self.candidates.push(self.createURLCandidate(url));
        },
        // 候補を全部隠して，貼り付けボタンをdisabledにする．新しいURLをプレビューするときと，モーダルウィンドウを閉じるときに呼ばれる．
        reset: function() {
            var self = this;
            _.each(self.candidates, function(candidate) {
                candidate.kill();
            });
            self.candidates = [];
            self.$pasteButton.attr('disabled', true).addClass('disabled');
        },
        // 貼り付け
        requestPaste: function() {
            var self = this;

            if (self.$pasteButton.is(':disabled')) return;

            // 貼り付けるのは，チェックされてるやつか，一番上のやつ
            var candidate = _.find(self.candidates, function(candidate) { return candidate.isChecked() }) || _.find(self.candidates, function(candidate) { return candidate.isEnabled() });

            Hatena.Diary.trackEvent('EmbedBox.paste');
            Hatena.Diary.trackEvent('EmbedBox.paste.' + candidate.type);

            self.session.resolve(candidate);

            candidate.paste();
            self.hide();
        },
        createEmbedCandidate: function(url) {
            var self = this;

            var $iframe = $('<iframe width="100%" scrolling="no">');
            var src = Hatena.Diary.URLGenerator.user_blog_url('/preview_url_embed') + '?' + $.param({ url: url});

            var embedSucceed = $.Deferred();

            // iframeがDOMに埋め込まれてないとMessenger使えない(postMessage.jsの仕様)ので，タイミングをずらす．
            _.defer(function() {
                var messenger = Messenger.createForFrame($iframe[0], src);
                messenger.addEventListener('resize', function (height) {
                    $iframe.css('height', height);
                    embedSucceed.resolve();
                });
                messenger.addEventListener('close', function () {
                    $iframe.remove();
                    embedSucceed.reject();
                });
            });

            // youtubeとか，大半は，iframeや，scriptを出すので，フィードリーダで消されてしまう．
            // そのため，:embed + :titleを挿入する．
            // twitterとiTunesはdivとscriptを出すので，:embed1つで事足りる．:title出さない
            var syntax;
            var anchor = document.createElement('a');
            anchor.href = url;
            if (_.contains(['twitter.com', 'itunes.apple.com'], anchor.host)) {
                syntax = "["+url+":embed]";

                // 文の末尾にiTunes入れると以降編集できなくなるので(tinyMCEが悪い)，うしろに改行つけたい．
                // 本来はtinymce側でなんとかしてほしい
                if ($('#syntax').val() === 'html') {
                    syntax += "\n\n ";
                }
            } else {
                syntax = "["+url+":embed]\n["+url+":title]";
            }

            return new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate({
                $root_container: self.$container,
                type: 'embed',
                syntax: syntax,
                loader: embedSucceed.promise(),
                $preview: $iframe
            });
        },

        createImageCandidate: function(url) {
            var self = this;

            var imageLoaded =  $.Deferred();
            var $img = $('<img>').on('load', function() {
                imageLoaded.resolve();
            }).on('error', function() {
                imageLoaded.reject();
            }).attr('src', url);

            return new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate({
                $root_container: self.$container,
                type: 'image',
                selectionRange: self.selectionRange,
                // :imageだけでは，リダイレクトする場合などに，うまく扱えない．画像であることを確認済なので，:image=でimgのsrcにも指定する．
                syntax: '[' + url + ':image=' + url + ']',
                loader: imageLoaded.promise(),
                $preview: $img
            });
        },
        createTitleCandidate: function(url) {
            var self = this;

            var $preview = $('<div>');

            var loadInfo = $.Deferred();

            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: '/api/extract_title',
                data: {
                    url: url,
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                }
            }).done(function(info) {
                if (info.title) {
                    $preview.text(info.title);
                    loadInfo.resolve();
                } else {
                    loadInfo.reject();
                }
            }).fail(function() {
                loadInfo.reject();
            });

            return new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate({
                $root_container: self.$container,
                type: 'title',
                selectionRange: self.selectionRange,
                syntax: '['+url+':title]',
                loader: loadInfo.promise(),
                $preview: $preview
            });
        },
        createURLCandidate: function(url) {
            var self = this;

            var $preview = $('<div>').text(url);

            return new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate({
                $root_container: self.$container,
                type: 'url',
                selectionRange: self.selectionRange,
                syntax: '['+url+']',
                loader: $.Deferred().resolve().promise(),
                $preview: $preview
            });
        },
        createQuoteCandidate: function(url, quote) {
            var self = this;
            var $preview = $('<pre>').text(quote);

            return new Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate({
                $root_container: self.$container,
                type: 'quote',
                selectionRange: self.selectionRange,
                syntax: '['+url+':title=' + quote + ']',
                loader: $.Deferred().resolve().promise(),
                $preview: $preview,
                paste: function() {
                    var editor = Hatena.Diary.Editor.Support.currentEditor;
                    editor.setSelectionRange(self.selectionRange);
                    editor.createLink(url);
                }
            });
        }
    };

    // あるURLの貼り付け形式を表現するクラス．viewの更新，syntaxの管理など
    Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate = function () { this.init.apply(this, arguments) };
    Hatena.Diary.Pages.Admin['user-blog-edit'].EmbedBox.Candidate.prototype = {
        // args: { $root_container, type, syntax|paste, load, $preview }
        init: function(args) {
            var self = this;
            self.type = args.type;
            self.selectionRange = args.selectionRange;

            // syntax指定されたらデフォルトの挙動(1行がリンクになる)
            if (args.syntax) {
                self.syntax = args.syntax;
            }

            // paste関数指定すればpasteの挙動を上書きできる
            if (args.paste) {
                self.paste = args.paste;
            }

            self.$container = args.$root_container.find('[data-embed-type="' + self.type + '"]');
            self.$container.hide();
            self.$radio = self.$container.find('.js-type-select');
            self.$radio.attr('checked', false);


            // previewContainreには引数で渡されたプレビューのための要素をappendする．有効なことが分かったらpreviewContainerは表示される．
            self.$previewContainer = self.$container.find('.js-preview-container');
            self.$previewContainer.hide();
            self.$previewContainer.append(args.$preview);

            // 有効なことが分かったらresolveされるやつ
            self.loader = args.loader;

            self.loader.done(function() {
                self.enable();
            }).fail(function() {
                self.disable();
            });

        },
        // 有効であるか(たとえば，:image形式で貼りたくて，かつ，画像であることが分かっているか)
        isEnabled: function() {
            var self = this;
            return self.loader.state() === "resolved";
        },
        // 有効なことがわかったとき
        enable: function() {
            var self = this;
            self.$container.show();
            self.$previewContainer.show();
        },
        // 無効なことがわかったとき
        disable: function() {
            var self = this;
            self.$container.hide();
            self.$previewContainer.empty();
        },
        // セッションを終了する
        kill: function() {
            var self = this;
            self.disable();
        },
        // radioボタンが選択されているか
        isChecked: function() {
            var self = this;

            return self.$radio.prop('checked');
        },
        // リンクを挿入
        paste: function() {
            var self = this;
            self.getSyntaxLines().done(function(lines) {
                if (self.selectionRange) {
                    Hatena.Diary.Editor.Support.currentEditor.setSelectionRange(self.selectionRange);
                }

                Hatena.Diary.EditorConnector.insertLines(lines);
            });
        },
        // 貼り付け用はてな記法をresolveするDeferredを返す
        getSyntaxLines: function() {
            var self = this;
            var gotSyntax = $.Deferred();

            var lines_data = self.syntax.split('\n');
            var lines = {
                html:     lines_data,
                hatena:   lines_data,
                markdown: lines_data
            };

            Hatena.Diary.extractSyntax(self.syntax).done(function(data) {
                lines.html = [data.html];
            }).always(function() {
                gotSyntax.resolve(lines);
            });

            return gotSyntax.promise();
        }
    };

    // PR記事1記事に対応するクラス
    Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion.Entry = function () { this.init.apply(this, arguments); };
    Hatena.Diary.Pages.Admin['user-blog-edit'].Promotion.Entry.prototype = {
        init: function (args) {
            var self = this;
            self.$element = args.$element;
            self.manager  = args.manager;
            self.bindEvents();
        },
        bindEvents: function() {
            var self = this;
            self.$element.on('click', '[data-keyword]', function(button) {
                self.manager.hide();
                Hatena.Diary.Editor.Support.currentEditor.insert($(this).attr('data-keyword'));
                Hatena.Diary.trackEvent('Promotion.Entry.Insert.' + self.entryID());
            });
        },
        isRead: function() {
            var self = this;
            try {
                return localStorage[self.localStorageKey()];
            } catch(ignore) {}
        },
        setAsRead: function() {
            var self = this;
            try {
                localStorage[self.localStorageKey()] = true;
            } catch(ignore) {}
        },
        localStorageKey: function() {
            var self = this;
            return 'Hatena.Diary.Promotion.Entry.read.' + self.entryID();
        },
        entryID: function() {
            var self = this;
            return self.$element.attr('data-promotion-entry-id');
        },
        isClosed: function() {
            var self = this;
            try {
                return localStorage['Hatena.Diary.Promotion.Entry.closed.' + self.entryID()];
            } catch(ignore) {}
        },
        setAsClosed: function() {
            var self = this;
            try {
                localStorage['Hatena.Diary.Promotion.Entry.closed.' + self.entryID()] = true;
            } catch(ignore) {}
        },
        show: function() {
            var self = this;
            self.$element.stop().fadeIn();

            Hatena.Diary.trackEvent('Promotion.Entry.Show.' + self.entryID());

            self.setAsRead();
        },
        hide: function() {
            var self = this;
            self.$element.fadeOut();
        },
        getTitle: function () {
            var self = this;
            return self.$element.attr('data-promotion-title');
        },
        getIndex: function () {
            var self = this;
            return +self.$element.attr('data-promotion-index');
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].updateOgDescriptionInput = function () {
        var $input = $('#og-description-input');

        $.ajax({
            url: './preview_og_description',
            method: 'POST',
            data: {
                body: $('#body').val(),
                syntax: $('#syntax').val(),
                rkm: Hatena.Diary.data('rkm'),
                rkc: Hatena.Diary.data('rkc')
            },
            dataType: 'json'
        }).done(function (data) {
            $('#og-description-input').attr('placeholder', _.escape(data.text));
        });
    };

    Hatena.Diary.Pages.Admin['user-blog-edit'].setupOgDescriptionInput = function (editor) {
        // 常に使うものではないので, リクエストを節約する
        // 見えてないときは更新しない
        editor.bind('change', _.debounce(function () {
            if ($('#og-description').is(':hidden')) return;

            Hatena.Diary.Pages.Admin['user-blog-edit'].updateOgDescriptionInput();
        }, 1000));

        // 編集オプションモジュールを表示するときに更新する
        $('.curation-bar-itemlist [data-support-type="editor-option"]').on('click', function () {
            Hatena.Diary.Pages.Admin['user-blog-edit'].updateOgDescriptionInput();
        });
    };
})(jQuery);

(function($){
    // コレクション(Entries, Categories)のインスタンスはページ内に高々1つしか存在せず，Collectionsから参照できる．
    // 個々のModelから参照したいときはここから呼べる．
    // コレクションと明らかに一対一で対応するものはコンストラクタで渡すべき(たとえばEntriesViewのコンストラクタにはentriesを渡す)
    var Collections = {
        entries: null,
        categories: null
    };
    // エントリ1つを表すオブジェクト
    var Entry = function(data){
        this.data = data;
    };
    Entry.prototype = {
        // 表示用のデータ
        getUUID: function() {
            return this.data.uuid;
        },
        getURL: function() {
            return this.data.url;
        },
        getEditURL: function() {
            return this.data.edit_url;
        },
        getTitle: function() {
            return this.data.title;
        },
        getSummary: function() {
            return this.data.summary;
        },
        getCreated: function() {
            return this.data.created;
        },
        getCreatedTime: function() {
            // epoch * 1000
            return this.getCreatedDate().getTime();
        },
        getCreatedDate: function() {
            return Hatena.Diary.Util.parseW3CDTF(this.data.created);
        },

        // datetimeはnullの場合があるので注意
        getDatetime: function() {
            return this.data.datetime;
        },
        getDatetimeTime: function() {
            // epoch * 1000
            var date = this.getDatetimeDate();

            if (date) {
                return date.getTime();
            } else {
                return null;
            }
        },
        getDatetimeDate: function() {
            return Hatena.Diary.Util.parseW3CDTF(this.data.datetime);
        },

        getAuthorName: function() {
            return this.data.author_name;
        },
        getCommentCount: function() {
            return this.data.comment_count;
        },
        getCategories: function() {
            return this.data.categories;
        },
        isPublic: function() {
            return this.data.is_public;
        },
        isScheduledEntry: function() {
            return this.data.is_scheduled_entry;
        },

        // 操作系
        select: function() {
            this.data.isSelected = true;
            $(this).triggerHandler('change');
        },
        unselect: function() {
            this.data.isSelected = false;
            $(this).triggerHandler('change');
        },
        isSelected: function() {
            return this.data.isSelected;
        },
        // このエントリを画面から消す
        // DBから消されるわけではない
        remove: function() {
            $(this).triggerHandler('remove');
        },
        // カテゴリを追加する
        addCategory: function(category_name) {
            if (_.contains(this.data.categories, category_name)) return;
            if (!this.data.categories) {
                this.data.categories = [];
            }
            this.data.categories.push(category_name);
            $(this).triggerHandler('change');
        },
        // 記事を編集できるかどうか
        canBeManageEntry: function() {
          return this.data.can_be_manage_entry;
        }
    };

    var EntryView = function(entry) {
        var self = this;
        self.entry = entry;

        self.rootTemplate = _.template($('.js-entry-root-template').html().replace(/^\s*/, '').replace(/\s*$/, ''));
        self.elementTemplate = _.template($('.js-entry-inner-template').html());

        self.render();
        $(self.entry).on('change', function() {
            self.render();
        }).on('remove', function() {
            self.remove();
        });
        self.$element.on('change', 'input', function() {
            var $input = $(this);
            if ($input.is(':checked')) {
                self.entry.select();
            } else {
                self.entry.unselect();
            }
            $(self.entry).triggerHandler('select');
        });
    };
    EntryView.prototype = {
        render: function() {
            // $elementは一度だけ作り，以後は最初に作った$elementの内容を更新する．
            if (!this.$element) {
                this.$element = $($.parseHTML(this.rootTemplate({entry: this.entry})));
            }

            this.$element.html(this.elementTemplate({entry: this.entry}));
            // 検索キーワード指定されていたらハイライトする
            if (Collections.entries && Collections.entries.getKeyword()) {
                var escapedKeyword = _.escape(Collections.entries.getKeyword());

                this.$element.find('.js-search-entry-title').html(function (i, html) {
                    return html.split(escapedKeyword).join('<span class="entry-search-keyword">' + escapedKeyword+ '</span>');
                });

                this.$element.find('.js-search-entry-body').html(function (i, html) {
                    return html.split(escapedKeyword).join('<span class="entry-search-keyword">' + escapedKeyword + '</span>');
                });
            }

            Hatena.Locale.updateTimestamps(this.$element[0]);
        },
        remove: function() {
            this.$element.remove();
        },
        getElement: function() {
            return this.$element;
        }
    };

    // エントリのコレクション，読み込み，クエリの管理
    var Entries = function() {
    };
    Entries.prototype = {
        // 指定したクエリで読み込む
        load: function() {
            var self = this;

            var data = {};
            if (self.keyword) {
                data.q = self.keyword;
            }
            if (self.category) {
                data.category = self.category;
            }

            if (self.getPermission() !== 'all') {
                data.permission = self.getPermission();
            }

            var lastEntry = _.last(self.entries);
            if (lastEntry) {
                data.until = lastEntry.getCreatedDate().getTime()/1000;
            }

            $.ajax({
                url: 'entries.json',
                data: data
            }).done(function(entries) {
                self.onLoaded(entries);
            });
        },
        onLoaded: function(data) {
            // data: { entries: [$entry], has_more: bool }
            var self = this;
            var $self = $(self);
            self.receivedEntries = [];
            self.receivedEntries = _.map(data.entries, function(entry_data) {
                return new Entry(entry_data);
            });
            $(self.receivedEntries).on('select', function() {
                $self.triggerHandler('select');
            }).on('remove', function() {
                $self.triggerHandler('remove');
            });
            if (!self.entries) self.entries = [];
            self.entries = self.entries.concat(self.receivedEntries);
            self.hasMore = data.has_more;
            $(self).triggerHandler('loaded');
        },
        // 最初から読み直す
        reset: function() {
            var self = this;
            _.each(self.entries, function(entry) {
                entry.remove();
            });
            self.entries = [];
            self.receivedEntries = [];
            self.hasMore = undefined;
            $(self).triggerHandler('reset');
            self.load();
        },
        // エントリを全て返す
        getEntries: function() {
            return this.entries;
        },
        // 最後に受信したEntryの配列を返す
        getReceivedEntries: function() {
            return this.receivedEntries;
        },
        // 続きあるかどうかを返す
        hasMoreEntries: function() {
            return this.hasMore;
        },
        // 検索キーワードを設定
        setKeyword: function(keyword) {
            this.keyword = keyword;
        },
        // 検索キーワードを返す
        getKeyword: function(keyword) {
            return this.keyword;
        },
        // 表示するカテゴリを設定
        setCategory: function(category) {
            this.category = category;
        },
        // permission: all|public|draft
        setPermission: function(permission) {
            this.permission = permission;
        },
        getPermission: function() {
            return this.permission;
        },
        getSelectedEntries: function() {
            return _.filter(this.entries, function(entry) { return entry.isSelected() });
        },
        // チェックをつけたエントリを削除
        // 操作が完了したらresolveするdeferredを返す
        deleteSelectedEntries: function() {
            var self = this;
            var entries_to_delete = self.getSelectedEntries();
            if (!entries_to_delete.length) return;

            var deleted = $.ajax({
                type: 'post',
                url: 'entries.delete.json',
                data: {
                    entry: _.map(entries_to_delete, function(entry) { return entry.getUUID() }),
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                },
                traditional: true
            });
            deleted.done(function() {
                self.entries = _.difference(self.entries, entries_to_delete);
                _.each(entries_to_delete, function(entry) {
                    entry.remove();
                });
            });
            return deleted;
        },
        // チェックをつけたエントリにカテゴリを追加
        // 操作が完了したらresolveするdeferredを返す
        addCategoryToSelectedEntries: function(category_name) {
            var self = this;
            var entries_to_add_category = self.getSelectedEntries();
            if (!entries_to_add_category.length) return;

            _.each(entries_to_add_category, function(entry) {
                entry.addCategory(category_name);
            });

            var categoryAdded = $.ajax({
                type: 'post',
                url: 'entries.add_category.json',
                data: {
                    entry: _.map(entries_to_add_category, function(entry) { return entry.getUUID() }),
                    category: category_name,
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                },
                traditional: true
            });
            return categoryAdded;
        }
    };

    var EntriesView = function(entries) {
        var self = this;
        self.entries = entries;
        var $entries = $(entries);

        self.$loadNextPage = $('.js-load-next-page');

        $entries.on('loaded', function() {
            self.render();
        });
        $entries.on('select remove', function() {
            self.renderButtons();
        });
        var $form = $('.js-entry-search-form');
        $('.js-categories-selector').on('change', function(event) {
            entries.setKeyword($form.find(':input[name="q"]').val());
            entries.setCategory($form.find(':input[name="category"]').val());
            entries.reset();
        });
        self.$loadNextPage.on('click', function(event) {
            self.entries.load();
        });
        $('.js-delete-entries-button').on('click', function() {
            if (!confirm(Hatena.Locale.text('epic.entry.delete.confirm'))) return;
            var deleted = self.entries.deleteSelectedEntries();
            deleted.always(function() {
                Collections.categories.reload();
            });
        });

        $('.js-entry-search-form').on('submit', function(event) {
            event.preventDefault();
            entries.setKeyword($form.find(':input[name="q"]').val());
            entries.setCategory($form.find(':input[name="category"]').val());
            entries.reset();
        });

        $('.js-entry-search-box-input').on('search', function() {
            var keyword = $form.find(':input[name="q"]').val();
            if (keyword !== '') return;
            entries.setKeyword('');
            entries.reset();
        });

        $('.js-select-all-entries').on('change', function() {
            if ($(this).is(':checked')) {
                _.each(entries.getEntries(), function(entry) {
                    entry.select();
                });
            } else {
                _.each(entries.getEntries(), function(entry) {
                    entry.unselect();
                });
            }
            self.renderButtons();
        });

    };
    EntriesView.prototype = {
        render: function() {
            var self = this;
            _.each(self.entries.getReceivedEntries(), function(entry) {
                var view = new EntryView(entry);
                $('.js-entries-container').append(view.getElement());
            });

            if (self.entries.hasMoreEntries()) {
                self.$loadNextPage.show();
            } else {
                self.$loadNextPage.hide();
            }
            self.renderButtons();
        },
        // カテゴリ追加とエントリ削除のenable / disabled, クラス追加
        // エントリをチェックしたときと，エントリが消えたときに呼ばれる
        renderButtons: function() {
            var self = this;
            var $deleteButton = $('.js-delete-entries-button');
            var $categoryButton = $('.js-category-dropdown-toggle');

            var selectedEntriesCount = self.entries.getSelectedEntries().length;
            if (selectedEntriesCount > 0) {
                $deleteButton.prop('disabled', false).removeClass('disabled').addClass('btn-danger');
                $categoryButton.prop('disabled', false).removeClass('disabled');
            } else {
                $deleteButton.prop('disabled', true).addClass('disabled').removeClass('btn-danger');
                $categoryButton.prop('disabled', true).addClass('disabled');
            }
        }
    };

    var Category = function(data) {
        this.data = data;
    };
    Category.prototype = {
        getName: function() {
            return this.data.name;
        },
        getEntriesCount: function() {
            return this.data.count;
        },
        setEntriesCount: function(count) {
            this.data.count = count;
            $(this).triggerHandler('change');
        }
    };

    // エントリにカテゴリ追加するときのview
    var CategoryAppenderView = function(category, entries) {
        var self = this;
        self.category = category;
        self.entries = entries;
        self.render();

        self.$element.on('click', function() {
            var categoryAdded = self.entries.addCategoryToSelectedEntries(self.category.getName());
            categoryAdded.always(function() {
                Collections.categories.reload();
            });
        });

        $(self.category).on('change', function() {
            self.render();
        });
    };
    CategoryAppenderView.prototype = {
        render: function() {
            if (!this.$element) {
                this.$element = $('<li>');
            }
            this.$element.text(this.category.getName() + ' (' + this.category.getEntriesCount() + ')');
        },
        getElement: function() {
            return this.$element;
        }
    };

    // しぼりこみのview
    var CategorySelectorView = function(category) {
        var self = this;
        self.category = category;
        self.render();

        $(self.category).on('change', function() {
            self.render();
        });
    };
    CategorySelectorView.prototype = {
        render: function() {
            if (!this.$element) {
                this.$element = $('<option>').val(this.category.getName());
            }
            this.$element.text(this.category.getName() + ' (' + this.category.getEntriesCount() + ')');
        },
        getElement: function() {
            return this.$element;
        }
    };

    var Categories = function() {
        var self = this;
        self.load();
    };
    Categories.prototype = {
        load: function() {
            var self = this;
            $.ajax({
                url: 'categories.json'
            }).done(function(data) {
                self.onLoaded(data);
            });
        },
        // ユーザーがカテゴリ追加した後などは読み込み直すことができる．実装としてはloadと同じ．
        reload: function() {
            this.load();
        },
        onLoaded: function(data) {
            // data = { categories: [ { name, count } ] }
            var self = this;

            if (!self.categories) {
                // はじめて受信した
                self.categories = _.map(data.categories, function(category_data) {
                    return new Category(category_data);
                });
                self.newCategories = self.categories;
            } else {
                self.newCategories = [];
                // 記事数増えたり新しいカテゴリできたりする
                _.each(data.categories, function(category_data) {
                    var category = self.getCategory(category_data.name);
                    if (category) {
                        category.setEntriesCount(category_data.count);
                    } else {
                        category = new Category(category_data);
                        self.categories.push(category);
                        self.newCategories.push(category);
                    }
                });
            }
            $(self).triggerHandler('loaded');
        },
        getNewCategories: function() {
            return this.newCategories;
        },
        getCategory: function(categoryName) {
            return _.find(this.categories, function(category) {
                return category.getName() === categoryName;
            });
        }
    };

    // カテゴリのリストに関するView
    // カテゴリのViewは2つあるのでジャグリングみたいな感じ
    var CategoriesView = function(categories, entries) {
        var self = this;
        self.categories = categories;
        self.entries = entries;
        var $categories = $(categories);

        $categories.on('loaded', function() {
            self.render();
        });

        $('.js-create-new-category').on('click', function() {
            var categoryName = window.prompt(Hatena.Locale.text('create_category'));
            if (!categoryName) return;

            var categoryAdded = self.entries.addCategoryToSelectedEntries(categoryName);
            categoryAdded.always(function() {
                self.categories.reload();
            });
        });
    };

    CategoriesView.prototype = {
        render: function() {
            var self = this;
            _.each(self.categories.getNewCategories(), function(category) {
                var selector_view = new CategorySelectorView(category);
                $('.js-categories-selector').append(selector_view.getElement());

                var appender_view = new CategoryAppenderView(category, self.entries);
                $('.js-create-new-category').before(appender_view.getElement());
            });
        }
    };

    // なんか汎用的なドロップダウンに見えなくもない
    var CategoriesDropdownView = function() {
        var self = this;
        self.$dropdown = $('.js-category-dropdown-list');
        self.$dropdownToggle = $('.js-category-dropdown-toggle');

        self.$dropdownToggle.on('click', function() {
            self.toggleDropdown();
            return false;
        });
        $(document).on('click', function(event) {
            self.hideDropdown();
        });
    };
    CategoriesDropdownView.prototype = {
        toggleDropdown: function() {
            this.$dropdown.toggle();
        },
        hideDropdown: function() {
            this.$dropdown.hide();
        }
    };

    var EntryTypeTabsView = function(entries) {
        var self = this;
        self.entries = entries;
        self.$tabs = $('.js-entry-type-select-tabs');
        self.$tabs.on('click', 'a', function (event) {
            self.clicked(event);
        });

        // デフォルトのpermissionをここで設定
        self.entries.setPermission(self.$tabs.find('.ui-tabs-active').find('a').attr('data-permission'));
    };
    EntryTypeTabsView.prototype = {
        clicked: function(event) {
            var self = this;
            event.preventDefault();
            self.$tabs.find('.ui-tabs-active').removeClass('ui-tabs-active');
            $(event.target).parents('li').addClass('ui-tabs-active');
            var permission = $(event.target).attr('data-permission');
            if (self.entries.getPermission() === permission) return;
            self.entries.setPermission(permission);
            self.entries.reset();
        }
    };

    var onEntriesPage = function(){
        var entries = new Entries();
        Collections.entries = entries;
        var entriesView = new EntriesView(entries);
        var categories = new Categories();
        Collections.categories = categories;
        var categoriesView = new CategoriesView(categories, entries);
        var categoriesDropdownView = new CategoriesDropdownView();
        var entryTypeTabs = new EntryTypeTabsView(entries);

        entries.reset();
    };

    Hatena.Diary.Pages.Admin['user-blog-entries'] = function () {
        onEntriesPage();
    };

    Hatena.Diary.Pages.Admin['user-blog-drafts'] = function (){
        onEntriesPage();
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-friend'] = function () {
        Hatena.Diary.Pages.createForParent();
    };

})(jQuery);
(function ($) {

    function showCategories (superCategory) {
        if (superCategory) {
            var $categories = $('.categories-container').filter(function () {
                return $(this).attr('data-super-category') === superCategory;
            }).show();

            if ($categories.length > 0) {
                $('#super-categories-container').hide();
                $('.submit-form-controls').show();
                location.hash = '#' + superCategory;
            }
            $('.back-button').show();
        } else {
            $('#super-categories-container').show();
            $('.categories-container').hide();
            $('.submit-form-controls').hide();
            $('.back-button').hide();
            location.hash = '#';
        }
    }

    Hatena.Diary.Pages.Admin['user-blog-group-official-dialog'] = function () {
        $(window).hashchange(function () {
            var m = /^#((?:\w|-)+)$/.exec(location.hash);
            if (m) {
                showCategories(m[1]);
            } else {
                showCategories(false);
            }
        }).hashchange();

        $('#super-categories-container .select-super-category').click(function () {
            var superCategory = $(this).closest('[data-super-category]').attr('data-super-category');
            showCategories(superCategory);
            return false;
        });

        $('.back-button').click(function () {
            showCategories(false);
            return false;
        });

        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Pages.send('resize', {
            height: 620,
            width: 620
        });

        $('.skip-button').click(function () {
            Hatena.Diary.Pages.send('close');
            return false;
        });

        $('form').submit(function () {
            var $form = $(this);

            $.ajax($form.attr('action'), {
                method: $form.attr('method'),
                data: $form.serialize()
            }).always(function () {
                Hatena.Diary.Pages.send('close');
            });

            Hatena.Diary.Pages.send('hide');

            return false;
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-import-diary-diary_name'] = function () {
        Hatena.Diary.Pages.Admin['user-blog-import'].setupDiaryProgress();

        // 上級設定リンク，クリックでトグルするやつ
        $('.toggle-hidden-section').click(function() {
            $(document.body).find($(this).attr('data-hidden-section-selector')).toggle();
        });
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['user-blog-import-movable_type'] = function () {
        Hatena.Diary.Pages.Admin['user-blog-import-movable_type'].setupMovableTypeProgress();

        $('.js-revert-movable-type-import').on('submit', function() {
            return confirm(Hatena.Locale.text('admin.import.undo.confirm'));
        });
    };
    Hatena.Diary.Pages.Admin['user-blog-import-movable_type'].setupMovableTypeProgress = function() {
        var $progress = $('.js-movable-type-import-progress');
        if (!$progress[0]) return;

        var $bar = $progress.find('.js-movable-type-import-bar');

        var api_url = $progress.attr('data-api-url');
        var on_complete_url = $progress.attr('data-on-complete-url');

        Hatena.Diary.Pages.Admin['user-blog-import'].setupProgress($bar, api_url, on_complete_url);
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Admin['user-blog-import'] = function () {
        Hatena.Diary.Pages.Admin['user-blog-import'].setupDiaryProgress();
    };

    Hatena.Diary.Pages.Admin['user-blog-import'].setupDiaryProgress = function () {
        var $progress = $('#import-progress');
        if (!$progress[0]) return;

        var $bar = $progress.find('.bar');
        if (!$bar[0]) return;

        var api_url = $progress.attr('data-progress-api');
        var on_success_url = $progress.attr('data-diary-page');

        Hatena.Diary.Pages.Admin['user-blog-import'].setupProgress($bar, api_url, on_success_url);
    };

    // 定期的にAPI取得してバーを伸ばして完了したらページ遷移
    // $bar: のびるelement width: 30% とかになる
    // api_url: 定期的にアクセスされるURL
    // on_success_url: 完了したときに飛ぶURL
    // APIから返る構造
    // {
    //  status: staarted|new|complete|failed
    //  progress: 0~100
    // }
    Hatena.Diary.Pages.Admin['user-blog-import'].setupProgress = function ($bar, api_url, on_success_url) {
        var progressCheck = function () {
            setTimeout(function () {
                $.ajax({
                    url : api_url,
                    type : 'GET',
                    cache: false,
                    dataType : 'json',
                    success : function (res) {
                        if (res.progress) {
                            $bar.css('width', res.progress + '%');
                        }

                        if (res.status == 'started' || res.status == 'new') {
                            progressCheck();
                        } else if (res.status == 'complete' || res.status == 'failed') {
                            setTimeout(function() {
                                location.href = on_success_url;
                            }, 1500);
                        }
                    },
                    error : function () {
                    }
                });
            }, 1000);
        };
        progressCheck();
    };

})(jQuery);
(function($){
    var Export = function(downloadURL, reserveURL) {
        this.downloadURL = downloadURL;
        this.reserveURL = reserveURL;
    };

    Export.prototype = {
        // 現在のエクスポート状態を同期的に返す
        // 状態は，not-created, running, completed の3つである
        getStatus: function() {
            return this.status;
        },
        // 日付の文字列を返す
        // HTTPヘッダの値からYYYY/MM/DD形式の文字列を作ろうとするが，失敗したら，HTTPヘッダの値そのものを返す
        getDate: function() {
            var date = this.date;

            if (!date) return null;

            var parsedDate;
            try {
                parsedDate = new Date(Date.parse(date));
                return [parsedDate.getFullYear(), parsedDate.getMonth()+1, parsedDate.getDate()].join("/");
            } catch(ignore) {
            }
            return date;
        },
        // 状態をサーバーから取得して更新する
        // /downloadは，以下のレスポンスコードを返すので，それを見て判断する
        // - 200: エクスポート完了しているとき
        // - 404: 一度もエクスポートしていないか，エクスポート失敗したとき
        // - 503: エクスポート中のとき
        fetchStatus: function() {
            var self = this;
            $.ajax({
                url: self.downloadURL,
                method: 'HEAD',
                cache: false
            }).done(function(_ignore, __ignore, res) {
                self.date = res.getResponseHeader('Date');
                self.status = 'completed';
                self._updated();
            }).fail(function(res) {
                self.date = null;
                if (res.status === 503) {
                    self.status = 'running';
                    setTimeout(function() {
                        self.fetchStatus();
                    }, 1000);
                } else {
                    self.status = 'not-created';
                }
                self._updated();
            });
        },
        // エクスポートを予約する
        reserveExport: function() {
            var self = this;
            $.ajax({
                url: self.reserveURL,
                method: 'POST',
                data: {
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc')
                }
            }).always(function() {
                self.fetchStatus();
            });
            self.status = 'running';
            self._updated();
        },
        _updated: function(data) {
            $(this).triggerHandler('updated');
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-export-movable_type'] = function () {
        var $container = $('.js-export-wrapper');
        var $panels = $container.find('.js-export-control-panel');
        var $reserveCompletedAt = $container.find('.js-reserve-completed-at');
        var $reserveButton = $container.find('.js-reserve-export-button');
        var $successMessage = $('.js-export-success-message');

        var statusToSelector = {
            'not-created': '.js-reserve-export-wrapper',
            'running': '.js-exporting-wrapper',
            'completed': '.js-export-completed-wrapper'
        };

        var exportModel = new Export(
            $container.attr('data-download-url'),
            $container.attr('data-reserve-url')
        );

        $reserveButton.on('click', function() {
            exportModel.reserveExport();
        });

        $(exportModel).on('updated', function() {
            var status = exportModel.getStatus();
            $panels.hide();
            $container.find(statusToSelector[status]).show();
            $reserveCompletedAt.text(exportModel.getDate());
            if (status === 'completed') {
                $successMessage.show();
            } else {
                $successMessage.hide();
            }
        });

        exportModel.fetchStatus();
    };
})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-subscribe-done'] = function () {
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Util.sendResizeRequest();
        Hatena.Diary.Pages.send('done');
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Admin['user-blog-subscribe'] = function () {
        $('#subscribe-form').submit(function () {
            Hatena.Diary.Util.preventDuplicateSubmit($(this));
        });
        Hatena.Diary.Pages.createForParent();
        Hatena.Diary.Util.sendResizeRequest();

        $('section input[type=checkbox]').focus();
    };

})(jQuery);

(function($){

    var User = function (data) {
        this.initialize(data);
    };
    User.prototype = {
        initialize: function (data) {
            this.is_subscribing = data.is_subscribing;
            this.is_guest = Hatena.Diary.data('rkm') && Hatena.Diary.data('rkc') ? false : true;
        }
    };

    var Subscribe = function (data) {
        this.initialize(data);
    };
    Subscribe.prototype = {
        initialize: function (data) {
            this.subscribers_count = data.subscribers_count;
            this.url = Hatena.Diary.data('admin-domain') + '/' +
                        Hatena.Diary.data('author')       + '/' +
                        Hatena.Diary.data('blog-host')    + '/subscribe';
        },

        updateSubscribedStatus: function (subscribing) {
            var ajax = $.ajax({
                type: "POST",
                url: this.url,
                data: {
                    rkm: Hatena.Diary.data('rkm'),
                    rkc: Hatena.Diary.data('rkc'),
                    "delete": subscribing ? 1 : 0
                }
            });
            return ajax;
        }
     };

    var SubscribeView = function ($el) {
        this.initialize($el);
    };
    SubscribeView.prototype = {
        initialize: function ($el) {
            var self = this;

            self.$el = $el;

            self.subscribe = new Subscribe({
                subscribers_count: parseInt(self.$el.data('subscribers-count'), 10)
            });

            self.user = new User({
                is_subscribing: self.$el.data('is-subscribing')
            });

            // 子ウィンドウだったら親ウィンドウにメッセージを送って自身と閉じる
            if (window.opener) {
                self.subscribe.updateSubscribedStatus(self.user.is_subscribing).success(function () {
                    var messenger = Messenger.createForParent();
                    messenger.send('sendLoginInfo', { subscribed: true });
                    window.close();
                });
            }

            self.$subscribe_btn = self.$el.find('.js-hatena-follow-button');
            self.$subscription_count = self.$el.find('.js-subscription-count');
            self.$subscription_count_box = self.$el.find('.js-subscription-count-box');

            // 購読中か未購読かによってボタンのクラスを最初に変える
            self.changeSubscribeBtnClass();

            // countがあったら購読者数のバルーンを表示
            self.showCountBox();
            // バルーンに購読者数をセット
            self.setCount();

            self.$subscribe_btn.on('click', function () {
                // ゲストだったらポップアップでログイン画面を出す
                if (self.user.is_guest) {
                    self.popupLoginWindow();
                    return false;
                }
                self.subscribe.updateSubscribedStatus(self.user.is_subscribing).success(function () {
                    // 購読が成功したらリロード
                    location.reload();
                });

                return false;
            });
        },

        changeSubscribeBtnClass: function () {
            var is_subscribing = this.user.is_subscribing;
            this.$subscribe_btn.removeClass(is_subscribing ? 'unsubscribing' : 'subscribing');
            this.$subscribe_btn.addClass(is_subscribing ? 'subscribing' : 'unsubscribing');
        },

        setCount: function () {
            this.$subscription_count.text(this.subscribe.subscribers_count);
        },

        showCountBox: function () {
            if (this.subscribe.subscribers_count >= 1) {
                this.$subscription_count_box.show();
            }
        },

        popupLoginWindow: function () {
            var options = { width: 900, height: 600, scrollbars: 'yes' };
            options.left = Math.floor((screen.width - options.width) / 2);
            options.top  = Math.floor((screen.height - options.height) / 2);
            var login_window = window.open(
                '',
                'login',
                Hatena.Diary.Util.positionToPositionString(options)
            );

            var messenger = Messenger.createForWindow(login_window, 'http://www.hatena.ne.jp/login?location=' + window.location.href);

            var self = this;
            messenger.addEventListener('sendLoginInfo', function(data) {
                // 購読成功していたらリロード
                if (data.subscribed) {
                    location.reload();
                }
            });
        }
    };

    Hatena.Diary.Pages.Admin['user-blog-subscribe-iframe'] = function () {
        var view = new SubscribeView($('.js-hatena-follow-button-box'));
    };

})(jQuery);

(function($){
    Hatena.Diary.Pages.Admin['user-blog-members'] = function () {
        $('.js-manage-members-table').on('click', '.js-edit-role', function() {
            var $row = $(this).parents('.js-member-row');
            $row.find('.js-form-member-update').show();
            $row.find('.js-member-role').hide();
        }).on('click', '.js-edit-cancel', function() {
            var $row = $(this).parents('.js-member-row');
            $row.find('.js-member-role').show();
            $row.find('.js-form-member-update').hide();
        });
    };
})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['*'] = function () {
        // iframeからはアクセスログのapiを叩かない
        if (window.parent === window) {
            Hatena.Diary.AccessLog.ping();
        }

        Hatena.Diary.Pages.infoLoaded.done(function(info) {
            Hatena.Diary.Pages.Blogs['*'].init(info);
        });

        Hatena.Diary.Util.updateDynamicPieces([document]);

        $(document).on('click', 'img.hatena-fotolife, img.magnifiable, img.http-image', function () {
            var img = this;
            var $img = $(img);

            if ($img.data('colorbox')) {
                // colorbox is already set up
                return;
            }

            // a要素に含まれ，リンク先が画像のsrcと異なるときは拡大しない
            var closest_a = $img.closest('a').get(0);
            if (closest_a && closest_a.href !== img.src) {
                return;
            }

            $img.colorbox({
                maxWidth    : '95%',
                maxHeight   : '95%',
                transition : 'none',
                photo: true,
                href : $img.attr('src'),
                title : ' ',
                open : true
            });

            $('#cboxContent').click(function () {
                $.colorbox.close();
            });

            return false;
        });

        Hatena.Diary.Pages.Blogs['*'].setupRecentCommentsModule();

        Hatena.Diary.Pages.Blogs['*'].setupArchiveModule();

        Hatena.Diary.Pages.Blogs['*'].setupEntriesAccessRankingModule();

        Hatena.Diary.Pages.Blogs['*'].setupCirclesModule();

        Hatena.Diary.Pages.Blogs['*'].prepareForGlobalHeader();

        Hatena.Diary.Pages.Blogs['*'].setupOndemandCommentDeleteButton();

        Hatena.Diary.Pages.Blogs['*'].highlightKeyword();


        // archiveとはてなブックマークコメントではスターは小さいやつを使う
        if (! _.contains(['archive', 'hatena-bookmark-comment'], Hatena.Diary.data('page'))) {
            Hatena.Diary.Star.initBigStar();
            Hatena.Diary.Star.initSelectStar();
            Hatena.Diary.Star.initStarNavigation();
            Hatena.Diary.Star.initDeleteStar();
        }

        Hatena.Epic.Component.setupTouchViewSuggest();

        Hatena.Diary.Pages.Blogs['*'].setupTumblrShareButtons();
    };

    Hatena.Diary.Pages.Blogs['*'].setupRecentCommentsModule = function () {
        var $recentComments = $('.hatena-module-recent-comments');
        if ( $recentComments.length === 0 ) return;
        var template = _.template($('.recent-comments-template').html());

        var max_count = 0;
        // コメントモジュールが複数ある場合があるので、最大の数のコメントを取得する
        $recentComments.each ( function () {
            var $moduleBody = $(this).find('.hatena-module-body');
            var count = $moduleBody.attr('data-count');
            max_count = _.max([max_count, count]);
        });
        if ( max_count === 0 ) return;

        $.ajax({
            url: Hatena.Diary.URLGenerator.user_blog_url('/api/recent_comments'),
            dataType: 'json',
            data : {
                count: max_count
            }
        }).done( function (comments) {
            $recentComments.each( function () {
                var $container = $(this);
                var $moduleBody = $container.find('.hatena-module-body');
                var count = $moduleBody.attr('data-count');
                var comment_source = '';
                for ( var i = 0; i < count; i++ ) {
                    if ( ! comments[i] ) break;
                    comment_source += template({
                        comment: comments[i]
                    });
                }
                $container.find('.recent-comments').html(comment_source);
                Hatena.Diary.Util.updateDynamicPieces($container);
            });

            Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].setupRecentCommentsModule");
        });
    };

    Hatena.Diary.Pages.Blogs['*'].setupArchiveModule = function () {
        var $archives = $('.hatena-module-archive');
        if ( $archives.length === 0 ) return;

        var detectDate = function () {
            // archiveのとき, 一番上の日付から年を読む
            if (Hatena.Diary.data('page') === 'archive') {
                var $entry = $('section.archive-entry:first');
                if ($entry.length > 0) {
                    var year_month_day = $entry.find('div.date > a > time').attr('datetime');
                    var year_str = year_month_day.split('-')[0];
                    var month_str = year_month_day.split('-')[1];

                    return { year: year_str, month: month_str };
                }

                return null;
            }

            // ページにエントリがあるとき, 一番上のエントリの日付から年を読む
            var $article = $('article.entry:first');
            if ($article.length > 0) {
                var date_year_str = $article.find('header time > span.date-year').text();
                var date_month_str = $article.find('header time > span.date-month').text();
                return { year: date_year_str, month: date_month_str };
            }

            return null;
        };

        // default
        var setupDefault = function ($archive) {
            var $open_year;
            var date = detectDate();
            if (date) {
                var year = date['year'];
                if (year) {
                    var $year = $archive.find('li.archive-module-year[data-year="' + year + '"]');

                    $open_year = $year.length > 0 ? $year : null;
                }
            }

            $open_year = $open_year || $('li.archive-module-year:first');
            $open_year.removeClass('archive-module-year-hidden');

            $archive.find('.archive-module-button').click(function (e) {
                e.preventDefault();

                var $year = $(this).parent('.archive-module-year');
                $year.toggleClass('archive-module-year-hidden');
            });
        };

        // calendarモジュールのセットアップ
        var setupCalendar = function ($archive) {
            var $selector = $archive.find('.js-archive-module-calendar-selector');

            var updateCalendar = function () {
                var $date = $selector.find('option:selected');
                var year = $date.data('year');
                var month = $date.data('month');
                $.ajax({
                    type: 'get',
                    url: Hatena.Diary.URLGenerator.user_blog_url('/archive_module_calendar'),
                    data: { month : month, year: year }
                }).done(function(res) { // days object
                    $archive.find('.js-archive-module-calendar-container').html(res);
                });
            };

            $selector.change(function () {
                updateCalendar();
            });

            // 表示ページに合わせてカレンダーを初期化
            var date = detectDate();
            if (date) {
                $selector.val(date['year'] + ' ' + date['month']);
            }
            updateCalendar();
        };

        // Archiveのtype( default, calendar )によって出し分け
        _.each($archives, function (archive) {
            var $archive = $(archive);
            var archiveType = $archive.data('archiveType');
            $.ajax({
                type: 'get',
                url: Hatena.Diary.URLGenerator.user_blog_url('/archive_module'),
                data: { archive_type: archiveType },
                dataType: 'html'
            }).done(function(res) {
                $archive.find('.hatena-module-body').append(res);

                Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].setupArchiveModule");

                if (archiveType == 'calendar') {
                    setupCalendar($archive);
                } else {
                    setupDefault($archive);
                }
            });
        });

    };

    // 記事検索で検索結果のタイトル・本文のキーワードをハイライトする
    Hatena.Diary.Pages.Blogs['*'].highlightKeyword = function () {

        if (!!Hatena.Diary.Location.params() && Hatena.Diary.Location.params()['q']){
            var keywords= $('.search-result').data("searchQueries");
            if (!keywords) return;

            $(".entry-title").highlight(keywords, { caseSensitive:false });
            $(".entry-description").highlight(keywords, { caseSensitive:false });
        }

    };

    Hatena.Diary.Pages.Blogs['*'].setupEntriesAccessRankingModule = function () {
        var $entriesAccessRanking = $('.hatena-module-entries-access-ranking');
        if ($entriesAccessRanking.length === 0) return;

        $entriesAccessRanking.each(function () {
            var $self = $(this);
            var queryParams = {};
            // `data-`のprefixがついた属性をすべて取得し，クエリパラメータにする
            _.each( ($self)[0].attributes, function (attr) {
                if ( ! attr.name.match(/^data-/) ) return;
                // `data-`のprefixはクエリパラメータのkeyには不要なので取り除く
                queryParams[ attr.name.replace(/^data\-/, '') ] = attr.value;
            } );

            $.ajax({
                type: 'GET',
                url: Hatena.Diary.URLGenerator.user_blog_url('/entries_access_ranking_module'),
                data: queryParams,
                dataType: 'html'
            }).done(function(res) {
                $self.find('.hatena-module-body').append(res);
            });
        });
    };

    Hatena.Diary.Pages.Blogs['*'].setupCirclesModule = function () {
        var $circles = $('.hatena-module-circles');
        if ($circles.length === 0) return;

        // 更新があったグループはJSで表示を変更する
        var mtime = 0, circleIds = [], elems = {};
        $circles.find('[data-circle-id][data-circle-mtime]').each(function () {
            var $elem = $(this);
            var circleId = $elem.attr('data-circle-id');
            circleIds.push(circleId);
            elems[circleId] = $elem;
            var m = Number($elem.attr('data-circle-mtime'));
            if (m > mtime) mtime = m;
        });

        $.ajax({
            type: 'GET',
            url: Hatena.Diary.URLGenerator.user_blog_url('/api/module/circles'),
            data: { mtime: mtime, circle_id: circleIds },
            traditional: true,
            dataType: 'json'
        }).done(function (data) {
            for (var circleId in data.circles) {
                elems[circleId].replaceWith($.parseHTML(data.circles[circleId].html || ' '));
            }



            Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].setupCirclesModule");
        });
    };

    function navigateToEditNewEntry () {
        Hatena.Diary.Pages.infoLoaded.done(function (info) {
            if (info.can_open_editor) {
                Hatena.Diary.Pages.Blogs['*'].newEntry();
            } else {
                location.href = Hatena.Diary.data('admin-domain') + '/my/?fragment=edit';
            }
        });
    }

    Hatena.Diary.Pages.Blogs['*'].toggleMyMenuDropdown = function(data) {
        Hatena.Diary.Dropdown.toggle(
            '/-/menu/mymenu?location=' + encodeURIComponent(location.href),
            data, 'mymenu', {
                callback: function (dropdown, messenger) {
                    var blog_to_$dropdown_container = {};

                    messenger.addEventListener('feedback', function (data) {
                        Hatena.Diary.Feedback.toggle(data.uri);
                    });

                    messenger.addEventListener('myblogmenu.init', function (data) {
                        var init = {
                            top: $(dropdown).offset().top + data.top,
                            right: $(dropdown).offset().left - 2,
                            height: 266
                        };
                        Hatena.Diary.Dropdown.toggle(
                            '/-/menu/myblogmenu?blog=' + encodeURIComponent(data.blogUri),
                            init,
                            null, {
                                callback: function (dropdown, messenger) {
                                    blog_to_$dropdown_container[data.blogUri] = $(dropdown).parent();

                                    // XXX: callbackが呼ばれるタイミングはshowされる前なのでそれを待ってから隠す
                                    _.delay(function () {
                                        $(dropdown).parent().hide();
                                    });
                                },
                                key: data.blogUri,
                                parent: 'mymenu',
                                className: 'hatena-diary-dropdown-myblogs'
                            }
                        );
                    });

                    messenger.addEventListener('myblogmenu.open', function (data) {
                        var $dropdown_container = blog_to_$dropdown_container[data.blogUri];
                        $dropdown_container.show();

                        var self = Hatena.Diary.Pages.Blogs['*'].toggleMyMenuDropdown;
                        self.$active_dropdown_container = $dropdown_container;
                    });

                    messenger.addEventListener('myblogmenu.close', function (data) {
                        var $dropdown_container = blog_to_$dropdown_container[data.blogUri];
                        $dropdown_container.hide();

                        var self = Hatena.Diary.Pages.Blogs['*'].toggleMyMenuDropdown;
                        self.$active_dropdown_container = null;
                    });

                    messenger.addEventListener('new-entry', function (data) {
                        navigateToEditNewEntry();
                    });
                }
            }
        );

        var $active_dropdown_container = Hatena.Diary.Pages.Blogs['*'].toggleMyMenuDropdown.$active_dropdown_container;

        // メニューを再度開くとき, サブメニューを開いている状態を復元する
        if ($active_dropdown_container && $active_dropdown_container.is(':hidden')) {
            $active_dropdown_container.fadeIn('fast');
        }
    };

    Hatena.Diary.Pages.Blogs['*'].prepareForGlobalHeader = function() {
        if (window != window.parent) return null;
        if (!Hatena.Diary.Pages.messenger) return null;

        Hatena.Diary.Pages.message('new-entry', function (data) {
            navigateToEditNewEntry();
        });

        Hatena.Diary.Pages.message('units', function (data) {
            Hatena.Diary.Dropdown.toggle(data.uri, data);
        });

        Hatena.Diary.Pages.message('feedback', function (data) {
            Hatena.Diary.Feedback.toggle(data.uri);
        });

        Hatena.Diary.Pages.message('mymenu', function (data) {
           Hatena.Diary.Pages.Blogs['*'].toggleMyMenuDropdown(data);
        });

        Hatena.Diary.Pages.message('servicesmenu', function (data) {
            Hatena.Diary.Dropdown.toggle('/-/menu/services', data);
        });

        Hatena.Diary.Pages.message('subscribe', function (data) {
            var offset = { left: data.left + 5 };
            Hatena.Diary.Subscribe.openSubscribeWindow(offset);
        });

        var notifyWindow;
        Hatena.Diary.Pages.message('notify', function (data) {
            var BASE = data.BASE;

            if (notifyWindow) {
                if (notifyWindow.is(':visible')) {
                    Hatena.Diary.Window.hide(notifyWindow, function () {
                        notifyWindow.remove();
                        notifyWindow = null;
                    });
                    return;
                } else {
                    notifyWindow.remove();
                    notifyWindow = null;
                }
            }

            notifyWindow = $('<div id="notify-window" class="hatena-globalheader-window"></div>').
                css({
                    left : data.left - 250 + 32
                });

            notifyWindow.html("<img src='https://b.st-hatena.com/images/loading32.gif' class='loading' style='position:absolute;'/>");

            var iframe = $('<iframe style="border:none" frameBorder="0" class="notify" width="250" height="300"></iframe>').appendTo(notifyWindow);

            iframe.attr('src', 'https://www' + BASE + '/notify/notices.iframe?' + new Date().getTime());

            iframe.ready(function () {
                notifyWindow.find('img').remove();
            });

            notifyWindow.
                //            css({
                //                top: $(document.body).scrollTop() + 37
                //            }).
                hide().
                fadeIn('fast').
                appendTo(document.body);

            Hatena.Diary.Window.show(notifyWindow, {
                fixScroll: true
            });
        });

        Hatena.Diary.Pages.message('blogmenu', function (data) {
            var params = {};
            if (Hatena.Diary.data('blog')) {
                params['blog'] = location.href;
                if (
                    Hatena.Diary.data('page') === 'entry' &&
                    // 削除されてエントリがない or Not Found 状態 であれば対象のエントリがなくなるので
                    // パーマリンクフラグをたてない
                    $('article.entry:not([class~="no-entry"])').length > 0
                ) {
                    params['blog_permalink'] = 1;
                }
            }
            var uri = '/-/menu/blogmenu?' + $.param(params);
            Hatena.Diary.Dropdown.toggle(uri, data, 'blogmenu', {
                callback: function (dropdown, messenger) {
                    messenger.addEventListener('edit-this-entry', function (data) {
                        var $entry = $('article.entry').first();
                        Hatena.Diary.Pages.Blogs['*'].editEntry( $entry );
                    });
                    messenger.addEventListener('new-entry', function (data) {
                        navigateToEditNewEntry();
                    });
                    messenger.addEventListener('subscribe', function (data) {
                        var uri = '' +
                            Hatena.Diary.data('admin-domain') + '/' +
                            Hatena.Diary.data('author')       + '/' +
                            Hatena.Diary.data('blog')         + '/subscribe?iframe=1';

                        Hatena.Diary.Browser.thirdPartyCookiesBlocked.done(function(blocked) {
                            if (blocked) {
                                Hatena.Diary.Subscribe.subscribeButtonHandlerWindow(uri);
                            } else {
                                var offset = { left: data.left + 5 };
                                Hatena.Diary.Subscribe.subscribeButtonHandlerIframe(uri, offset, { className: 'hatena-globalheader-window' });
                            }
                        });
                    });
                }
            });
        });

        Hatena.Diary.Pages.message('locale', function (data) {
            var uri = Hatena.Diary.data('admin-domain') + '/-/locale';

            Hatena.Diary.Dropdown.toggle(uri, data, 'locale');
        });
    };

    Hatena.Diary.Pages.Blogs['*'].init = function (info) {
        if (arguments.callee.called) return; arguments.callee.called = true;

        // globalhaederがキャッシュされているのでこちらからviaを送ってやる
        var via = Hatena.Diary.Location.param('via');
        if (via) {
            Hatena.Diary.Pages.send('inheritVia', via);
        }

        if (info.message) {
            Hatena.Diary.Util.showFlashMessage(info.message);
        }

        if (info.show_modal) {
            var $modalContainer = $('<div class="hatena-iframe-container"></div>').appendTo(document.body);
            var $iframe = $('<iframe frameborder="0"></iframe>').appendTo($modalContainer);

            var messenger = Messenger.createForFrame($iframe[0], info.show_modal.url);

            messenger.addEventListener('resize', function (data) {
                if (data) {
                    $modalContainer.css(data);
                    $(window).trigger('resize'); // reset position
                }
            });

            var destroyed = $.Deferred();

            // hide 時はただ隠すだけ、close が呼ばれてはじめて
            // iframe を消す
            messenger.addEventListener('hide', function () {
                Hatena.Diary.Window.hide($modalContainer);
            });

            messenger.addEventListener('close', function () {
                destroyed.done(function () {
                    $iframe.remove();
                    messenger.destroy();
                });
                Hatena.Diary.Window.hide($modalContainer);
            });

            Hatena.Diary.Window.show($modalContainer, {
                destroy: function () {
                    destroyed.resolve();
                },
                fixScroll: true,
                center: true,
                showBackground: true
            });
        }

        var self = this;

        Hatena.Diary.Browser.thirdPartyCookiesBlocked.resolve(!info.cookie_received);

        $('article.entry').each(function () {
            var $this = $(this);
            self.initEntry($this);
        });

        if (info.editable) {
            var $entry,
                timer,
                $menu = $('<div>').addClass('entry-header-menu'),
                create_edit_button = function ($entry) {
                    // エントリにカーソル合わせると出てくる「編集」ボタンを作る
                    return $('<a>')
                             .attr( 'href', 'javascript:void' )
                             .text( Hatena.Locale.text('edit') )
                             .on('click', function (e) {
                                 e.preventDefault();
                                 Hatena.Diary.Pages.Blogs['*'].editEntry( $entry );
                             });
                };

            $(document).on('mouseenter', 'article.entry', function () {
                var $hovered = $(this);
                if ( $hovered.is($entry) ) {
                    clearTimeout(timer);
                    return;
                }

                $entry = $hovered;
                if ( !$entry.attr('data-uuid') ) return;

                $menu
                  .empty()
                  .append( create_edit_button($entry) )
                  .appendTo( $entry.find('.entry-header') )
                  .show();
            });

            $(document).on('mouseleave', 'article.entry', function () {
                clearTimeout(timer);
                timer = setTimeout(function () {
                    $entry = null;
                    $menu.fadeOut('fast');
                }, 2000);
            });

            // 新規開設時
            if ( info.has_just_registered ) {
                _gaq.push(['_trackPageview', '/register.done']);
            }

            // インデックスページで，プレビューではなくて，グローバルヘッダ表示中のとき
            if (Hatena.Diary.data('page') === 'index' && ! Hatena.Diary.Location.param('preview') && $('#globalheader').is(':visible')) {
                Hatena.Diary.Pages.Blogs['*'].setupFirstEntry();
            }

            Hatena.Diary.setupProModal();

        }

        Hatena.Diary.Pages.Blogs['*'].renderGooglePlusOneButtons();
        // ブックマークコメントウィジェット
        Hatena.Diary.Pages.Blogs['*'].setupHatenaBookmarkComment($('#container'));

        // エントリー一覧のカルーセル
        Hatena.Diary.Pages.Blogs['*'].setupEntryModuleCarousel();

        // 購読ボタンと購読者数
        this.initSubscribe(info);

        Hatena.Diary.Browser.thirdPartyCookiesBlocked.done(function(blocked) {
            if (blocked) {
                Hatena.Diary.Star.initStarForThirdPartyCookiesDisabled(info);
            }
        });

        Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].init");
    };

    Hatena.Diary.Pages.Blogs['*'].setupFirstEntry = function() {
        $('.entry-content').show();

        // 1記事もないとき，記事を書こうみたいなツールチップなどを表示する

        var $tooltip = $('.welcome-tooltip-newentry');
        $tooltip.click(function() {
            Hatena.Diary.Pages.Blogs['*'].newEntry();
        });
        Hatena.Diary.Pages.send('newEntryGeometry');
        Hatena.Diary.Pages.message('newEntryGeometry', function(geometry) {
            $tooltip.offset({
                left : (geometry.left + (geometry.width / 2)) - ($tooltip.outerWidth() / 2)
            });
            $tooltip.show();
        });
    };

    Hatena.Diary.Pages.Blogs['*'].newEntry = function (opts) {
        if (!opts) opts = {};

        Hatena.Diary.Editor.showEditInPlace(null, {
            update : function (data) {
                // data.entryは前後に空白を含むので消す
                var $newEntry = $(data.entry.replace(/^\s+/, '').replace(/\s+$/, ''));

                // 下書き投稿のときは何もしない
                if (!$newEntry.length) return;

                $newEntry.insertBefore('#main article.entry:first');
                Hatena.Diary.Pages.Blogs['*'].initEntry($newEntry);
                Hatena.Diary.Util.updateDynamicPieces($newEntry.parent());
                $('[data-remove-on-new-entry=1]').remove();
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].editEntry = function ($entry) {
        if (!$entry) return;

        Hatena.Diary.Editor.showEditInPlace($entry, {
            update : function (data) {
                // data.entryは前後に空白を含むので消す
                var $newEntry = $(data.entry.replace(/^\s+/, '').replace(/\s+$/, ''));

                // 記事を削除した場合は, 削除エントリーを消す
                if (!$newEntry.length) {
                    $entry.remove();
                    return;
                }
                $entry.replaceWith($newEntry);
                Hatena.Diary.Pages.Blogs['*'].initEntry($newEntry);
                Hatena.Diary.Util.updateDynamicPieces($newEntry.parent());
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].initEntry = function (entry) {
        var self = this;
        var uuid = entry.attr('data-uuid');

        Hatena.Diary.Util.replaceYoutubeURL(entry);

        var container = entry.find('.comment-box .comment');
        $(container).delegate('.comment-delete-button', 'click', function (e) {
            var $button = $(this);

            Hatena.Diary.Pages.Blogs['*'].deleteCommentHandler(entry, $button);

            return false;
        });

        var showEntryInfo = function (entry, container, maxCommentsCount) {
            return self.loadEntryInfo(entry).done(function (info) {

                if (info.comments) {

                    var $readMoreLine = entry.find('.read-more-comments');
                    var $readMoreButton = $readMoreLine.find('a');
                    // readMoreButtonが無いか、maxCommentsCountが0またはコメントの総数がmaxCommentsCountより少ないとき、全件表示
                    var commentsCount = info.comments.entries.length;
                    var expandedInThisSession = false;
                    try {
                        var entriesExpandedComments = JSON.parse(sessionStorage.getItem('entriesExpandedComments')) || {};
                        expandedInThisSession = entriesExpandedComments[entry.attr('data-uuid')];
                    } catch (_ignored) {
                    }
                    if ($readMoreLine.length === 0 || maxCommentsCount === 0 || commentsCount <= maxCommentsCount || expandedInThisSession) {
                        maxCommentsCount = commentsCount;

                        // すべてのコメントが表示される
                        // すでに表示されているコメントがあったら消す
                        // このとき「もっと読む」も消える
                        container.children().remove();
                        entry.attr('data-comments-expanded', true);
                    } else {
                        // まだ表示されていないコメントがあるから「もっと読む」を表示する
                        $readMoreLine.show();
                    }

                    // コメントのHTMLを連結して一括でDOMにする
                    var commentHTML = '';
                    for (var i = 0, len = maxCommentsCount; i < len; i++) {
                        commentHTML += info.comments.entries[i];
                    }
                    var $comments = $(commentHTML);

                    container.prepend($comments);

                    // 未表示のコメントの数を表示する
                    $readMoreButton.text(
                        Hatena.Locale.text('read_more_comments') + ' (' + (info.comments.entries.length - maxCommentsCount) + ')'
                    );

                    if (Hatena.Star) {
                        Hatena.Diary.Util.waitForResource(function() {
                            return Hatena.Star && Hatena.Star.WindowObserver.loaded;
                        }, function() {
                            Hatena.Star.EntryLoader.intoCommentScope(function () {
                                Hatena.Diary.Util.updateDynamicPieces(container);
                            });
                        });
                    } else {
                        Hatena.Diary.Util.updateDynamicPieces(container);
                    }
                }

                Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].init.showEntryInfo");
            }).
                fail( Hatena.Diary.REPORT_BUG('loadEntryInfo') );
        };

        var $readMoreLine = entry.find('.read-more-comments');
        var $readMoreButton = $readMoreLine.find('a');

        // コメント最初は3件まで表示
        showEntryInfo(entry, container, 3);

        $readMoreButton.click(function (e) {
            // 「もっと読む」がクリックされたらコメント全件表示
            showEntryInfo(entry, container, 0).done(function () {
                try {
                    // もっと読むがクリックされた場合 sessionStorage に状態を保存しておく
                    var map = {};
                    $('article[data-comments-expanded][data-uuid]').each(function () {
                        map[$(this).attr('data-uuid')] = true;
                    });
                    sessionStorage.setItem('entriesExpandedComments', JSON.stringify(map));
                } catch (_ignored) {
                }
            });
            return false;
        });

        Hatena.Diary.Pages.infoLoaded.done(function (info) {
            entry.find('.leave-comment-title').toggle(
                info.cookie_received ? info.commentable : true
            ).on('click touchend', function () {
                var $button = $(this);
                Hatena.Diary.Pages.Blogs['*'].leaveCommentHandler(entry, $button);

                return false;
            });
        });

    };

    Hatena.Diary.Pages.Blogs['*'].deleteCommentHandler = function ($entry, $button) {
        var commentId = $button.closest('li.entry-comment').attr('id');

        var uri = Hatena.Diary.data('admin-domain') +
            '/' + Hatena.Diary.data('author') + '/' + Hatena.Diary.data('blog') +
            '/comment/delete?comment=' + encodeURIComponent(commentId.slice(8));

        Hatena.Diary.Browser.thirdPartyCookiesBlocked.done(function(blocked) {
            if (blocked) {
                Hatena.Diary.Pages.Blogs['*'].deleteCommentHandlerWindow($entry, $button, commentId, uri);
            } else {
                Hatena.Diary.Pages.Blogs['*'].deleteCommentHandlerIframe($entry, $button, commentId, uri);
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].deleteCommentHandlerIframe = function ($entry, $button, commentId, uri) {
        var iframeContainer = $(
            '<div class="hatena-iframe-container"><div class="loading">' +
                '<img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt="loading"/>' +
                Hatena.Locale.text('loading') +
                '</div></div>').appendTo($entry);
        var iframe = $('<iframe frameborder="0"></iframe>').appendTo(iframeContainer);
        iframeContainer.
            css({
                width: 440,
                height: 120,
                position: 'absolute'
            }).
            offset( $button.offset() );

        var loading = iframeContainer.find('.loading').hide();
        setTimeout( function () { loading.show() }, 250);
        iframe.load(function () { loading.remove() });

        var messenger = Messenger.createForFrame(iframe[0], uri);
        messenger.addEventListener('delete', function (data) {
            $("#" + commentId).fadeOut();
        });
        messenger.addEventListener('close', function () {
            Hatena.Diary.Window.hide(iframeContainer);
        });

        Hatena.Diary.Window.show(iframeContainer, {
            destroy : function () {
                iframe.remove();
                messenger.destroy();
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].deleteCommentHandlerWindow = function ($entry, $button, commentId, uri) {
        var position = {
            width:  300,
            height: 150
        };
        position.left = Math.floor((screen.width - position.width) / 2);
        position.top = Math.floor((screen.height - position.height) / 2);

        var position_string = Hatena.Diary.Util.positionToPositionString(position);

        var delete_comment_window = window.open('', 'delete_comment', position_string);

        var messenger = Messenger.createForWindow(delete_comment_window, uri);

        var close = function() {
            messenger.destroy();
            delete_comment_window.close();
        };

        messenger.addEventListener('delete', function (data) {
            $("#" + commentId).fadeOut();
        });

        messenger.addEventListener('close', close);

        $(document.body).one('focus', close);

    };


    Hatena.Diary.Pages.Blogs['*'].leaveCommentHandler = function ($entry, $button) {
        // viewable状態でコメント出来るかどうか決めるため
        // bkをtokenとして渡す
        var uri = Hatena.Diary.data('admin-domain') +
            '/' + Hatena.Diary.data('author') + '/' + Hatena.Diary.data('blog') + '/comment?' +
            $.param({
                entry : $entry.attr('data-uuid'),
                token : $.cookie('bk')
            });

        Hatena.Diary.Browser.thirdPartyCookiesBlocked.done(function(blocked) {
            if (blocked) {
                Hatena.Diary.Pages.Blogs['*'].leaveCommentHandlerWindow($entry, $button, uri);
            } else {
                Hatena.Diary.Pages.Blogs['*'].leaveCommentHandlerIframe($entry, $button, uri);
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].leaveCommentHandlerWindow = function($entry, $button, uri) {
        var position = {
            width:  400,
            height: 240
        };
        position.left = Math.floor((screen.width - position.width) / 2);
        position.top = Math.floor((screen.height - position.height) / 2);

        var position_string = Hatena.Diary.Util.positionToPositionString(position);

        var comment_window = window.open('', 'comment', position_string);

        var messenger = Messenger.createForWindow(comment_window, uri);

        messenger.addEventListener('close', function() {
            messenger.destroy();
            comment_window.close();
        });

        messenger.addEventListener('update', function (data) {
            Hatena.Diary.Pages.Blogs['*'].appendPostedComment($entry, data.comment);
        });
    };

    Hatena.Diary.Pages.Blogs['*'].leaveCommentHandlerIframe = function($entry, $button, uri) {
        var container = $(
            '<div class="hatena-iframe-container">' +
                '<div class="loading">' +
                '<img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt="loading"/>' +
                Hatena.Locale.text('loading') +
                '</div>' +
                '</div>').
            hide().
            appendTo(document.body);

        var iframe = $('<iframe frameborder="0"></iframe>').appendTo(container);

        var loading = container.find('.loading').hide();

        setTimeout(function () {
            loading.show();
        }, 250);

        iframe.load(function () {
            loading.remove();
        });

        var offset   = $button.offset();
        var maxWidth = $(window).width();
        var winWidth = 440;
        var padding  = 10;

        // コメントframe幅がmaxWindowより大きい場合は, 縮めて中央に表示
        if ( (winWidth + 2*padding) > maxWidth ) {
            winWidth = maxWidth - 2*padding;
            offset.left = padding;
        }

        var height = 235;

        // 上が新しいときコメント書くボタンの上にウィンドウ出す
        var top_is_new = Hatena.Diary.data('blog-comments-top-is-new');
        if (top_is_new) {
            offset.top -= height;
            offset.top += $button.height();
        }

        container.
            css({
                width: winWidth,
                height: height,
                position: 'absolute'
            }).
            offset(offset);

        editinplace = iframe[0];

        var messenger = Messenger.createForFrame(editinplace, uri);

        messenger.addEventListener('update', function (data) {
            Hatena.Diary.Pages.Blogs['*'].appendPostedComment($entry, data.comment);
        });

        messenger.addEventListener('close', function () {
            Hatena.Diary.Window.hide(container);
        });

        messenger.addEventListener('resize', function (data) {
            if (data) {
                if (top_is_new && data.height  != height) {
                    data.top = container.css('top') + height - data.height;
                }
                container.css(data);
            }
        });

        Hatena.Diary.Window.show(container, {
            closeExplicitly : true,
            destroy : function () {
                iframe.remove();
                messenger.destroy();
            }
        });
    };

    Hatena.Diary.Pages.Blogs['*'].appendPostedComment = function($entry, comment_html) {
        var $container = $entry.find('.comment-box .comment');
        var top_is_new = Hatena.Diary.data('blog-comments-top-is-new');
        if (top_is_new) {
            $container.prepend(comment_html);
        } else {
            $container.append(comment_html);
        }

        if (Hatena.Star) {
            Hatena.Star.EntryLoader.intoCommentScope(function() {
                Hatena.Diary.Util.updateDynamicPieces($container);
            });
        } else {
            Hatena.Diary.Util.updateDynamicPieces($container);
        }
    };

    Hatena.Diary.Pages.Blogs['*'].loadEntryInfo = function me (entry) {
        if (!me.data) me.data = {
            timer : setTimeout(function () {
                var data = me.data;
                me.data = null;
                $.ajax({
                    url : Hatena.Diary.URLGenerator.user_blog_url('/api/entry/info'),
                    type : "get",
                    dataType : 'json',
                    cache : false,
                    data : {
                        e : data.entries
                    },
                    success : function (res) {
                        var entries = res.entries;
                        for (var key in entries) if (entries.hasOwnProperty(key)) {
                            var val = entries[key];
                            data.deferred[key].resolve(val);
                        }

                        Hatena.Diary.SpeedTrack.record("Pages.Blogs['*'].loadEntryInfo.ajax.success");
                    }
                });
            }, 0),
            entries : [],
            deferred : {}
        };

        var ret  = $.Deferred();
        var uuid = entry.attr('data-uuid');

        me.data.entries.push(uuid);
        me.data.deferred[uuid] = ret;

        return ret;
    };

    // スクロールで要素が表示されたときに何かする
    Hatena.Diary.Pages.Blogs['*'].elementDidAppear = function (element) {
        var deferred = $.Deferred();
        var _window = $(window);

        if (_window.scrollTop() > ($(element).offset().top - _window.height())) {
            deferred.resolve();
        } else {
            _window.scroll(_.throttle(function () {
                if (_window.scrollTop() > ($(element).offset().top - _window.height())) {
                    deferred.resolve();
                }
            }, 200));
        }
        return deferred.promise();
    };

    // Google+ボタンを描画 plusone.jsのロードに失敗してるようなら何もしない(なぜか読めてないことがある)
    // YouTubeのsubscribeボタンもplusone.jsに入ってるので描画
    // https://developers.google.com/+/web/+1button/?hl=ja
    Hatena.Diary.Pages.Blogs['*'].renderGooglePlusOneButtons = function() {
        if (!window.gapi) return;

        try {
            window.gapi.plusone.go('container');
            window.gapi.ytsubscribe.go('container');
        } catch(ignore) {
            // Google+ボタンはIE8以上のみ対応で，IE7では例外出るけど，無視する．
        }
    };

    // 購読する/しない ボタン
    // - 自分のブログ : 非表示
    // - 購読済ブログ : "読者をやめる"
    // - 未購読ブログ : "読者になる"
    // args: info.subscribes [JSON] admin /api/init
    Hatena.Diary.Pages.Blogs['*'].initSubscribe = function (info) {

        // 購読者数を表示
        var $countbox = $('div.hatena-module-profile .subscription-count-box');
        Hatena.Diary.Subscribe.showSubscribe($countbox, info.subscribes);

        // アンテナページの公式ブログ購読ボタンにイベント付けない
        var $subscribeButtons = Hatena.Diary.Subscribe.getSubscribeButtons().not('.js-admin-antenna-follow');

        $subscribeButtons.addClass(info.subscribe ? 'subscribing' : 'unsubscribing');

        $subscribeButtons.click(function () {
            var $button = $(this);
            var offset = $button.offset();
            offset.top += $button.height();

            Hatena.Diary.Subscribe.openSubscribeWindow(offset);

            return false;
        });

    };

    Hatena.Diary.Pages.Blogs['*'].setupHatenaBookmarkComment = function ($superNode) {
        // 上位のノードを指定すること
        // ブックマークコメントウィジェットのサイズ調整
        var $bookmark_comment = $superNode.find('.hatena-bookmark-comment-iframe');

        if ($bookmark_comment.size() === 0) return;

        _.each($bookmark_comment, function (item) {
            var $item = $(item);
            var messenger = Messenger.createForFrame($item[0], $item.attr('data-src'));
            messenger.addEventListener('resize', function (height) {
                $item.css('height', height);
            });
        });
    };

    Hatena.Diary.Pages.Blogs['*'].setupOndemandCommentDeleteButton = function() {
        $(document).on('mouseenter', '.entry-comment', function(e) {
            var $comment = $(this);
            if ($comment.find('.comment-delete-button img').size() > 0)
                return;
            var comment_uuid = $comment.attr('data-comment-uuid');
            var blog_uuid = $comment.attr('data-blog-uuid');
            var url = Hatena.Diary.data('admin-domain') + '/api/comment.delete.image?comment=' + comment_uuid + '&blog=' + blog_uuid;
            var $img = $('<img>');
            $img.attr('src', url);
            var handler = function() {
                $img.attr('alt', 'delete');
            };
            $img.load(handler);
            $img.error(handler);
            $comment.find('.comment-delete-button').append($img);
        });
    };

    // Tumblr 提供のブックマークレット http://www.tumblr.com/apps#bookmarklet_window を
    // URL およびタイトルを明に指定できるように改造したもの
    Hatena.Diary.Pages.Blogs['*'].setupTumblrShareButtons = function (elem) {
        $(elem || document.body).find('a[data-hatenablog-tumblr-share-button]').on('click', function () {
            var selection = window.getSelection   ? window.getSelection()
                : document.getSelection ? document.getSelection()
                : document.selection    ? document.selection.createRange().text : 0;
            var url = 'http://www.tumblr.com/share?' + $.param({
                v: 3,
                u: $(this).attr('data-share-url') || location.href,
                t: $(this).attr('data-share-title') || document.title,
                s: selection + ''
            });
            var go = function () {
                if (!window.open(url, 't', 'toolbar=0,resizable=0,status=1,width=450,height=430')) {
                    location.href = url;
                }
            };
            if (/Firefox/.test(navigator.userAvent)) {
                setTimeout(go, 0);
            } else {
                go();
            }
            return false;
        });
    };

    Hatena.Diary.Pages.Blogs['*'].setupEntryModuleCarousel = function() {
        var $carouselScripts = $(document).find('script[type="text/x-hatenablog-carousel"]');

        _.each($carouselScripts, function (item) {
            var $item = $(item);
            new Hatena.Diary.EntryModuleCarousel($(document).find($item.html()));
        });

    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['blog-count-limit-exceeded'] = function () {
        Hatena.Diary.Pages.infoLoaded.done(function (info) {
            var selector = info.editable ? '.js-message-author' : '.js-message-guest';
            $('#container').append($(selector).html());
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['circle'] = function () {
        Hatena.Diary.Pages.Blogs['circle'].setupControls();
        Hatena.Diary.Pages.Blogs['circle'].setupSidebar();
        Hatena.Diary.Pages.Blogs['circle'].setupSpace();

        Hatena.Diary.Pages.infoLoaded.done(function (info) {
            if (info.flash && info.flash.has_just_created_circle) {
                var closeFlash = function () { $('#flash-created-circle').fadeOut('fast') };
                $('#flash-created-circle')
                    .find('.close').click(function () { closeFlash() }).end()
                    .show();
                $(document.body).on('click', function (e) {
                    if ($(e.target).closest('#flash-created-circle').length === 0) {
                        closeFlash();
                        $(document.body).off('click', arguments.callee);
                        return false;
                    }
                });
            }
        });

        Hatena.Diary.Util.initScrollFollowedElement($('.js-followed-ad-container'), false);
    };

    Hatena.Diary.Pages.Blogs['circle'].setupControls = function () {
        Hatena.Diary.Pages.infoLoaded.done(function (info) {
            if (info.is_admin) {
                $('.admin-control').addClass('admin-control-available');
            } else {
                $('.admin-control').addClass('admin-control-unavailable');
            }

            if (info.is_member) {
                $('.circle-member-control').addClass('circle-member-control-available');
            } else {
                $('.circle-member-control').addClass('circle-member-control-unavailable');
            }

            if (info.has_blogs) {
                $('.blog-user-control').addClass('blog-user-control-available');
            } else {
                $('.blog-user-control').addClass('blog-user-control-unavailable');
            }

            if (info.cookie_received === false) {
                // サードパーティークッキー無効のときに出す指定があるものは出るようにクラスをふり直す
                $('[data-user-unknown-overrides]')
                    .removeClass('admin-control-unavailable circle-member-control-unavailable blog-user-control-unavailable')
                    .addClass('admin-control-available circle-member-control-available blog-user-control-available');
            }
        });
    };

    // 可能なら汎用化したい
    function createMessenger (url, name, $container) {
        return Hatena.Diary.Browser.thirdPartyCookiesBlocked.pipe(function (blocked) {
            var messenger;

            if (blocked) {
                var size = { width: 300, height: 400 };
                size.left = Math.floor((screen.width - size.width) / 2);
                size.top  = Math.floor((screen.height - size.height) / 2);

                var subwindow = window.open('', name, Hatena.Diary.Util.positionToPositionString(size));
                messenger = Messenger.createForWindow(subwindow, url);

                messenger.addEventListener('close', function () {
                    messenger.destroy();
                    subwindow.close();
                });
            } else {
                var $iframe = $('<iframe frameborder=0>').appendTo($container);
                messenger = Messenger.createForFrame(
                    $iframe[0], url
                );

                messenger.addEventListener('close', function () {
                    Hatena.Diary.Window.hide($container);
                });

                messenger.addEventListener('resize', function (css) {
                    if (css) $iframe.css(css);
                });

                Hatena.Diary.Window.show($container, {
                    destroy: function () {
                        $iframe.remove();
                        messenger.destroy();
                    }
                });
            }

            return messenger;
        });
    }

    Hatena.Diary.Pages.Blogs['circle'].setupSidebar = function () {
        $('.manage-membership-button').click(function () {
            createMessenger(
                $('html').attr('data-admin-domain') + '/-/group/' + $('html').attr('data-circle-id') + '/membership',
                'manage-membership',
                $(this).siblings('.manage-membership-popup')
            );

            return false;
        });
    };

    Hatena.Diary.Pages.Blogs['circle'].setupSpace = function () {
        if (!$('.hatena-module.circle-space')[0]) return;
        $.getScript('http://space.hatena.ne.jp/js/interest.widget.js');
    };

    Hatena.Diary.Pages.Blogs['circle-blogs'] = function () {
        Hatena.Diary.Pages.Blogs['circle'].setupSidebar();
    };

    Hatena.Diary.Pages.Blogs['group-category'] = function () {
        Hatena.Diary.Util.initScrollFollowedElement($('.js-followed-ad-container'), true);
    };

    Hatena.Diary.Pages.Blogs['recent-groups'] = function () {
        Hatena.Diary.Util.initScrollFollowedElement($('.js-followed-ad-container'), true);
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['famous-blogs-top'] = function () {
        $(document).on('click', '.js-read-old-entries', function() {
            var $button = $(this);
            $button.closest('.js-category-container').find('.js-old-entry').show();
            $button.remove();
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['global-top'] = function() {
        $('img[data-alternate-src]').one('error', function() {
            var $img = $(this);
            $img.attr('src', $img.attr('data-alternate-src'));
        });

        $('.js-category-wrapper').tabs({
            selected : 0
        });

        // 標準のタブのUIではなく，nav-barのスタイルを当てたいので，クラス消す
        $('.js-category-wrapper .ui-tabs-nav').removeClass('ui-tabs-nav');

        // globalトップはキャッシュされてるので、jsでviaの引き継ぎをする
        var via = Hatena.Diary.Location.param('via');
        if (via) {
            Hatena.Diary.inheritVia(via);
        }
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Blogs['guide-pro-modal-ad'] = function () {
        Hatena.Diary.Pages.createForParent();

        $('.close-window').on('click', function (e) {
            Hatena.Diary.Pages.send('close', { name : window.name });
            return false;
        });
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['hatena-bookmark-comment'] = function () {
        var messenger = Messenger.createForParent(),
        OFFSET = 30,        // iframeのbodyとの余白分, 十分大きい適当な値
        current_height = 0;

        var sendResize = function () {
            var next_height = $('body').height() + OFFSET;
            if (next_height !== current_height) {
                messenger.send('resize', next_height);
                current_height = next_height;
            }
        };

        // ボタンがクリックされたときサイズが変わる
        $(document).on('click', '.hatena-bookmark-span-button', function () {
            sendResize();
        });

        setInterval(function(){
            sendResize();
        }, 1000);
    };

})(jQuery);
(function($){

    Hatena.Diary.Pages.Blogs['index'] = function () {
        Hatena.Diary.Location.setup();

        $(window).hashchange(function () {
            if (location.hash == '#edit') {

                Hatena.Diary.Pages.infoLoaded.done(function (info) {
                    if (info.editable) {
                        Hatena.Diary.Pages.Blogs['*'].newEntry();
                    }
                }).
                    fail(function (e) {
                        Hatena.Diary.BUG(e);
                    });
            }
        }).hashchange();
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['preview'] = function() {
        try {
            if (!window.sessionStorage)
                return;
            var editor_id = $('#content').attr('data-editor-id');
            if (!editor_id)
                return;
            var $document = $(document);

            var pos = sessionStorage.previewed_scroll_position ? JSON.parse(sessionStorage.previewed_scroll_position) : null;
            if (pos && pos.editor_id == editor_id) {
                $document.scrollTop(pos.top);
                $document.scrollLeft(pos.left);
            }

            $document.scroll(_.throttle(function() {
                sessionStorage.previewed_scroll_position = JSON.stringify({
                    editor_id : editor_id,
                    top: $document.scrollTop(),
                    left: $document.scrollLeft()
                });
            }, 100));
        } catch (_ignored) {
        }
    };

})(jQuery);

(function($){
    Hatena.Diary.Pages.Blogs['preview_url_embed'] = function () {
        var messenger = Messenger.createForParent();

        // 最初の1回は必ずsendするために，nullにしておく．
        // IEでは，非表示な要素の高さ取れないため，最初高さ取ると0になる．
        // 0で送ると，親でiframeが表示されて，その後高さを取得すると，正しい高さになり，表示される．
        var current_height = null;

        var sendResize = function () {
            var next_height = $('body').height();
            if (next_height !== current_height) {
                messenger.send('resize', next_height);
                current_height = next_height;
            }
        };

        // 展開成功していたらこの要素がある．高さを親に伝える．失敗してたらiframe消してもらう．
        var embed_success = !! $('.js-embed-preview')[0];

        if (embed_success) {
            sendResize();
            setInterval(function(){
                sendResize();
            }, 1000);
        } else {
            // 展開失敗
            messenger.send('close');
        }
    };

})(jQuery);

(function($){

    Hatena.Diary.Pages.Blogs['realtime_preview'] = function() {
        try{
            if (!window.sessionStorage)
                return;

            var editor_id = $('#realtime-preview-content').attr('data-editor-id');

            if (!editor_id)
                return;
            var $wrapper = $('#realtime-preview-wrapper');

            var pos = sessionStorage.realtime_previewed_scroll_position ? JSON.parse(sessionStorage.realtime_previewed_scroll_position) : null;
            if (pos && pos.editor_id == editor_id) {
                $wrapper.scrollTop(pos.top);
                $wrapper.scrollLeft(pos.left);
            }

            $wrapper.scroll(_.throttle(function() {
                sessionStorage.realtime_previewed_scroll_position = JSON.stringify({
                    editor_id : editor_id,
                    top: $wrapper.scrollTop(),
                    left: $wrapper.scrollLeft()
                });
            }, 100));
        } catch (_ignored) {
        }
    };

})(jQuery);

(function($){

Hatena.Diary.Pages.AdminTouch['globalheader'] = function () {
    Hatena.Diary.Pages.createForParent();

    Hatena.Diary.Pages.loadInfo().done(function (info, privateInfo) {
        Hatena.Diary.Pages.AdminTouch['globalheader'].initSubscribe(info);
    });
};

// スマフォグローバルヘッダの購読ボタン
Hatena.Diary.Pages.AdminTouch['globalheader'].initSubscribe = function (info) {
    // ブログがないときは何もしない
    // 自分のブログには読者になる出さない
    // 購読中も出さない
    if (!info.blog) return;
    if (info.can_open_editor) return;
    if (info.subscribe) return;

    var $container = $('.js-subscribe-container');
    var $link = $container.find('.js-subscribe-link');

    // リンク先設定
    $link.attr('href', info.subscribe_url);

    // 購読ボタン表示
    $container.show();
};

Hatena.Diary.Pages.AdminTouch['*'] = function () {
    Hatena.Locale.setupTimestampUpdater();
    $('label').click(function () {}); // Mobile safari は onclick つけないと label が効かないらしい

    Hatena.Diary.Pages.AdminTouch['*'].androidAppBanner.init();
};

Hatena.Diary.Pages.AdminTouch['*'].androidAppBanner = {
    init : function () {
        // Androidアプリ用のバナー

        var self = this;

        var $banner = $('#android-app-banner');

        if ($banner.length === 0) {
            return;
        }
        var $closeButton = $('#android-app-banner-close');

        $closeButton.click(function (e) {
            $banner.slideToggle(400);
            self.setDismiss(true);
        });

        if (!self.isDismissed()) {
            setTimeout(function () {
                $banner.slideToggle(400);
            }, 0);
        }
    },

    _localStorageKey : 'Hatena.Diary.Pages.AdminTouch.dismissAndroidAppBanner',

    _localStorageEnabled : function () {
        try {
            if (window.localStorage) {
                return true;
            }
        } catch (ignore) {}
        return false;
    },

    isDismissed : function () {
        // 非表示に設定されているかどうか
        var self = this;
        if (self._localStorageEnabled()) {
            return localStorage.getItem(self._localStorageKey) === 'true';
        }
        return false;
    },

    setDismiss : function (dismissed) {
        // 非表示に設定する
        var self = this;
        if (self._localStorageEnabled()) {
            localStorage.setItem(self._localStorageKey, dismissed ? 'true' : 'false');
        }
    }
};

Hatena.Diary.Pages.AdminTouch['index'] = function () {
    var tabs   = $('#admin-top-tab');
    var navs   = $('#admin-top-tab .nav-cell');
    var panels = $('#config-container > .section');

    var loaded = false;
    $(window).load(function () { loaded = true });

    navs.click(function () {
        var $this = $(this);
        navs.removeClass('selected');
        navs.find('a img').each(function () {
            if (/-selected/.test(this.src)) {
                this.src = this.src.replace(/-selected/, '');
            }
        });
        panels.hide();

        var a = $this.find('a');
        $this.addClass('selected');
        a.find('img').each(function () {
            this.src = this.src.replace(/\.([^.\/]+)$/, '-selected.$1');
        });

        var panel = panels.filter(a.attr('href'));
        panel.show();

        tabs.trigger('tabsactivate', { panel : { id : panel.attr('id') } });

        if ('replaceState' in history && loaded) {
            var hash = (a.attr('href').match(/(#.+)/))[0];
            if (hash) {
                history.replaceState(null, document.title, hash);
            }
        }

        // antenna
        var $closedBlogs = $('.closed-blog');
        $closedBlogs.each(function(){
            var $closedBlog = $(this);
            var antennaUrl = $closedBlog.data("antennaUrl");
            $.ajax({
                type: 'GET',
                url: antennaUrl,
                data: { device: 'touch' },
                dataType: 'html',
                crossDomain: true,
                xhrFields: {
                        withCredentials: true
                }
            }).done(function(res){
                $closedBlog.empty();
                $closedBlog.append(res);
                var $blogContents = $closedBlog.find('.js-blog-content');
                Hatena.Locale.updateTimestamps($blogContents[0]);
            });
        });
        return false;
    });

    var BASE     = location.hostname.match(/\.hatena\.[^:]+/)[0];
    var notifyCount = $('#admin-top-tab .notify-count').hide();
    $.getJSON("https://www" + BASE + "/notify/notices.count.json?callback=?", function (res) {
        if (res.count) {
            notifyCount.text(res.count).show();
        }
        Hatena.Diary.Util.needComrule2013(res);
    });

    tabs.on('tabsactivate', function (e, ui) {
        if (ui.panel.id == 'notify') {
            notifyCount.hide();
            var notifyContainer = $('#notify').empty();
            var uri = 'https://www' + BASE + '/notify/notices.iframe?' + new Date().getTime();
            $('<iframe style="width: 100%; height: 340px; margin: 5px 0; padding: 0" frameborder="0"/>').attr('src', uri).appendTo(notifyContainer);
        }
    });

    var selected = navs.filter(function () {
        return $(this).find('a').filter(function () { return $(this).attr('href') == location.hash }).length !== 0;
    });
    (selected.length ? selected : navs.eq(0)).click();

    Hatena.Diary.Pages.AdminTouch['user-blog-entries'].setupEntryListLinks();

    Hatena.Diary.Pages.AdminTouch['index'].getDashboardData();
};

Hatena.Diary.Pages.AdminTouch['user-blog-comment-done'] = function () {
    Hatena.Diary.Pages.createForParent();

    var comment = document.getElementById('posted').value;

    Hatena.Diary.Pages.send('update', { comment : comment });

    Hatena.Diary.Pages.send('close');
};

Hatena.Diary.Pages.AdminTouch['index'].getDashboardData = function () {
    $.ajax({
        type: 'GET',
        url: '/-/dashboard_data',
        data: { device: 'touch' }
    }).done(function(data) {
        $('section#subscribe').append(data.subscribing_blogs);
        $('section.js-hotentry-container').append(data.hot_entries);
    });
};

Hatena.Diary.Pages.AdminTouch['locale'] = function () {
    $('a.js-set-language').on('click', function () {
        var $this = $(this);
        var lang = $this.attr('data-lang');
        Hatena.Locale.setAcceptLang(lang);
        location.href = Hatena.Diary.Location.param('location') || '/';
        return false;
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'] = function () {
    Hatena.Diary.Backup.UI = 'touch';
    Hatena.Diary.Backup.setup();

    var editEntry = $('#edit-entry');

    if (Hatena.Diary.Pages.AdminTouch['user-blog-edit'].contentEditableEnabledAndEditorModeIsHTML()) {

        var textarea = editEntry.find('textarea#entry-body');
        var iframe = $('<iframe src="about:blank" frameborder="0">')
                     .attr('id', 'entry-html-body')
                     .prependTo('div.edit-body');

        var wysiwygDocument = iframe.prop('contentDocument');
        var body = textarea.val();
        // 初投稿の場合は <p> を入れておく
        if (!body && !$('form#edit-form input[name="entry"]').val()) {
            body = '<p><br/></p>';
        }
        var link = wysiwygDocument.createElement('link');
        link.setAttribute('type', 'text/css');
        link.setAttribute('rel',  'stylesheet');
        link.setAttribute('href', Hatena.Diary.data('admin-domain') + '/css/touch/blog-edit.css');

        wysiwygDocument.getElementsByTagName('head')[0].appendChild(link);
        wysiwygDocument.body.innerHTML = body;
        wysiwygDocument.body.contentEditable = true;
        wysiwygDocument.body.addEventListener('keyup', function () {
            textarea.val(wysiwygDocument.body.innerHTML);
        }, true);

        $('form#edit-form').append($('<input type="hidden" name="wysiwyg" value="1">')).submit(function () {
            $('textarea#entry-body').val(wysiwygDocument.body.innerHTML);
        }).bind('backup-restore', function () {
            wysiwygDocument.body.innerHTML = textarea.val();
        });

        // これしないと Safari で入力できなくなる
        $('input#entry-title').blur(function () {
            iframe.focus();
        });

        // 編集中にリンクをクリックすると別の画面に遷移しているためclickイベントを無効化してる
        $(wysiwygDocument).on('click', "a", function() {
            return false;
        });

        textarea.hide();
    }

    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupUpload();

    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupMyCuration();

    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupScheduledEntry();

    if (Hatena.Diary.Pages.AdminTouch['user-blog-edit'].dateTimeEditorEnabled()) {
        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupDateTimeEditor();
    }

    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupOptionsToggle();
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupOptionsToggle = function () {
    var $options = $('.post-options');
    $('.js-toggle-options').on('click', function() {
        $options.toggle();
        $(document).scrollTop($options.position().top);
        return false;
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].execCommand = function (command, value) {
    var editor = tinymce.get('entry-body');
    editor.execCommand(command, false, value);
    editor.save();
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].contentEditableEnabledAndEditorModeIsHTML = function() {
    // Android のデフォルトブラウザは避ける
    // (Opera Mobile はそもそも contentEditable 非対応)
    var editEntry = $('#edit-entry');
    var ua = navigator.userAgent;
    var isMobileSafari = /\b(?:iPhone|iPad)\b/.exec(ua) && /\bVersion\/(\d+\.\d+)/.exec(ua) && Number(RegExp.$1) >= 5.1;
    var isAndroidChrome = /\bAndroid\b/.exec(ua) && /\bChrome\b/.exec(ua);
    return editEntry.attr('data-entry-syntax') == 'html' && 'contentEditable' in document.body &&
        (isMobileSafari || isAndroidChrome);
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].pickColor = function (callback) {
    var button = $('#edit-entry .toolbar button[data-action="color"]');
    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].ColorPicker.show(button.offset(), function (e, color) {
        callback(color);
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].fontSize = function (delta) {
    var selection = tinymce.get('entry-body').selection;

    var span = selection.getNode();
    if (span.nodeName.toLowerCase() != 'span')  {
        span = document.createElement('span');
        span.setAttribute('style', 'font-size: ' + (100 + delta) + '%');

        var range = selection.getRng();
        range.surroundContents(span);
        selection.setRng(range);
    } else {
        var remove = false;
        span.setAttribute('style', span.getAttribute('style').replace(/font-size:\s*(\d+)%|$/, function (_, size) {
            if (typeof(size) == 'undefined') size = 100;
            size = +size + delta;
            if (size == 100) remove = true;
            return 'font-size:' + size + '%';
        }));

        if (remove) {
            var frag = document.createDocumentFragment();
            while (span.firstChild) frag.appendChild(span.firstChild);
            span.parentNode.insertBefore(frag, span);
            span.parentNode.removeChild(span);
        }
    }
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText = function(text) {
    if ($('iframe#entry-html-body').length > 0) {
        this.insertText.contentEditable(text);
    } else if (navigator.userAgent.match(/3DS/)) {
        this.insertText.textarea3DS(text);
    } else {
        this.insertText.textarea(text);
    }
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText.textarea = function(text) {
    var $textarea = $('textarea#entry-body');
    var textarea = $textarea[0];
    var val = $textarea.val();

    var range = {
        start: textarea.selectionStart,
        end: textarea.selectionEnd
    };

    $textarea.val(val.substring(0, range.start) + text + val.substring(range.end));
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText.textarea3DS = function(text) {
    // 3DSではselectionStartとか取れないので，必ずテキストエリアの最後に挿入する

    var $textarea = $('textarea#entry-body');
    var val = $textarea.val();

    var lastChar = val[val.length - 1];
    var middle = '';
    if (lastChar === "\n" || lastChar === undefined) {
        // do nothing
    } else {
        middle = "\n";
    }

    $textarea.val(val + middle + text + "\n");
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText.contentEditable = function(text) {
    // 雑談: focusしてからじゃないとexecCommandできない
    var contentDocument = $('#entry-html-body').prop('contentDocument');
    contentDocument.body.focus();
    contentDocument.execCommand('insertHTML', false, text);
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].EDITOR_ACTIONS = {
    bold : function () {
        // http://www.tinymce.com/wiki.php/Command_identifiers
        this.execCommand('Bold');
    },

    italic : function () {
        this.execCommand('Italic');
    },

    strike : function () {
        this.execCommand('StrikeThrough');
    },

    underline : function () {
        this.execCommand('Underline');
    },

    removeFormat : function () {
        this.execCommand("removeFormat");
        this.execCommand("unlink");
    },

    fontSizeIncl : function () {
        this.fontSize(+10);
    },

    fontSizeDecl : function () {
        this.fontSize(-10);
    },

    unorderedList : function () {
        this.execCommand("InsertUnorderedList");
    },

    orderedList : function () {
        this.execCommand("InsertOrderedList");
    },

    color : function () {
        var self = this;
        self.pickColor(function (color) {
            if (color) {
                self.execCommand("ForeColor", color);
            } else {
                self.execCommand("RemoveFormat");
            }
        });
    },

    link : function () {
        var url = prompt('URL');
        if (url) {
            url = url.toLowerCase();
        }
        this.execCommand("CreateLink", url);
    }
};

// from editor/editor.js
Hatena.Diary.Pages.AdminTouch['user-blog-edit'].ColorPicker = {
    show : function (position, callback) {
        var container = Hatena.Diary.Pages.AdminTouch['user-blog-edit'].ColorPicker.container;
        if (!container) {
            container = $('<div class="hatena-diary-color-picker" tabindex="0"><a href="#" class="color-chip default" data-color="">' + Hatena.Locale.text('default') + '</a></div>').appendTo(document.body).hide();
            container.delegate('.color-chip', 'click', function () {
                var color = $(this).attr('data-color');
                container.trigger('colorpick', color);
                container.hide();
                return false;
            });

            var padding = 8;
            var size    = 30;

            var colors = [
                ['#ffffff', '#cccccc', '#999999', '#666666', '#333333', '#000000'],
                ['#cc0000', '#cc00cc', '#0000cc', '#00cccc', '#00cc00', '#cccc00'],
                ['#990000', '#990099', '#000099', '#009999', '#008800', '#aaaa00'],
                ['#660000', '#660066', '#000066', '#006666', '#006600', '#666600'],
                ['#330000', '#330033', '#000033', '#003333', '#003300', '#333300']
            ];

            container.css({
                width: colors[0].length * (size + padding) + padding,
                height: (colors.length + 1) * (size + padding) + padding
            });

            var defcol = container.find("a").css({
                top: padding,
                left: padding,
                height: size,
                width: container.width() - padding * 2
            });

            var chip = $('<a href="#" class="color-chip"></a>');
            for (var i = 0, it; (it = colors[i]); i++) {
                for (var j = 0, col; (col = it[j]); j++) {
                    chip.clone().attr('data-color', col).css({
                        top: (i + 1) * (size + padding) + padding,
                        left: j * (size + padding) + padding,
                        background: col,
                        width : size,
                        height : size
                    }).appendTo(container);
                }
            }

            Hatena.Diary.Pages.AdminTouch['user-blog-edit'].ColorPicker.container = container;
        }

        container.unbind('colorpick');
        container.bind('colorpick', callback);

        container.css(position);
        container.fadeIn('fast');

        container.focus();
        $(container).one('blur', function () { container.hide() });
    }
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupUpload = function() {
    var can_upload_file = function() {
        // http://stackoverflow.com/questions/8077955/detect-if-input-type-file-is-supported
        var elem = document.createElement('input');
        elem.type = 'file';
        return !elem.disabled;
    };
    if (!can_upload_file()) return;

    var $container = $('.toolbar-container');
    $container.show();

    var can_use_form_data = (typeof FormData != 'undefined');

    if (can_use_form_data) {
        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupAjaxUpload();
    } else {
        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupIframeUpload();
    }
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupAjaxUpload = function() {
    var $container = $('.toolbar-container');
    var $file_input = $container.find('input[type=file]');

    $file_input.change(function () {
        if ( ! this.files.length > 0 ) return;
        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].uploadImage({
            $input   : $file_input,
            $progress: $container.find('.progress')
        }).done(Hatena.Diary.Pages.AdminTouch['user-blog-edit'].uploadDone)
        .fail(function(res) {
            alert(Hatena.Locale.text('admin.blog.config.image_upload_failure'));
        });
        Hatena.Diary.trackEvent('upload-photo-smartphone');
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupIframeUpload = function() {
    var $container = $('.toolbar-container');
    var $file_input = $container.find('input[type=file]');

    $container.addClass('iframe-uploader');

    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setIframeUploader({
        fileinput : $container.find('.file-container'),
        fotosize  : 800,
        callback  : Hatena.Diary.Pages.AdminTouch['user-blog-edit'].uploadDone
    });
};

// admin.jsからコピペ→書き換え
Hatena.Diary.Pages.AdminTouch['user-blog-edit'].uploadImage = function (args) {
    var folder = args.folder || "Hatena Blog";
    var fotosize = args.fotosize || 1000;
    var $input = args.$input;
    var image = $input.prop('files')[0];
    var $progress = args.$progress;
    var dfd = $.Deferred();

    $input.prop('disabled', true);

    var data = new FormData();
    data.append('rkm', Hatena.Diary.data('rkm'));
    data.append('append', 1);
    data.append('fototitle', "");
    data.append('folder', folder);
    data.append('fotosize', fotosize);
    data.append('image', image);

    $progress.show();
    var $bar = $progress.find('.bar');
    $bar.width('0%');
    var $percent = $progress.find('.percent');
    var updateProgress = function (percent) {
        if (percent > 100) percent = 100;
        $bar.width(percent + '%');
        $percent.text(Hatena.Locale.text('uploading'));
    };

    var xhr = new XMLHttpRequest();

    xhr.upload.addEventListener("progress", function (e) {
        var percent = e.lengthComputable ? (e.loaded / e.total * 100) : NaN;
        updateProgress( percent );
    }, false);

    xhr.addEventListener("load", function (e) {
        updateProgress( 100 );
        $progress.hide();
        $input.prop('disabled', false);

        if (xhr.status !== 200) {
            dfd.reject(xhr.responseText);
            return;
        }

        var fotolife_syntax = xhr.responseText;
        dfd.resolve(fotolife_syntax);

    }, false);

    xhr.addEventListener("error", function (e) {
        $progress.hide();
        $input.prop('disabled', false);
        dfd.reject(e);
    }, false);

    xhr.open("POST", "/f/" + Hatena.Diary.data('name') + "/upbysmart?dummy=" + (new Date()).getTime());
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.send(data);

    return dfd;
};

// admin.jsからコピペ→ちょっと書き換え(callback呼ぶかどうかのところ)
Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setIframeUploader = function (args) {
    var fileinput = args.fileinput;
    var fotosize = args.fotosize;
    var callback = args.callback;

    var iframe = $('<iframe/>');
    fileinput.replaceWith(iframe);
    var src = "/api/upload/fotolife_smart";
    iframe.attr('src', src);
    iframe.addClass('uploader');
    iframe.load(function () {
        var document;
        if (iframe[0].contentDocument) {
            document = iframe[0].contentDocument;
        } else if (iframe[0].contentWindow) {
            document = iframe[0].contentWindow.document;
        } else {
            return;
        }
        if (document.body.innerHTML.match(/^\s*(f:id:\S+)/)) {
            iframe[0].contentWindow.location.replace(src);
        }
        if (document.body.innerHTML.match(/f:id:([^:]+):(\d+)([jpg]):image/)) {
            callback(document.body.innerHTML);
        }

        $(document).find('input[name="fotosize"]').val(fotosize);
        var images = $(document).find('input[type="file"]');
        $(images[0]).change ( function () {
            $(document).find('#fotolife-upload-form').submit();
            $(images[0]).replaceWith($('<h5>').text(Hatena.Locale.text('uploading')));
        });
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].uploadDone = function(fotolife_syntax) {
    Hatena.Diary.Pages.AdminTouch['user-blog-edit'].trackPhotoUpload();

    if (Hatena.Diary.Pages.AdminTouch['user-blog-edit'].contentEditableEnabledAndEditorModeIsHTML()) {
        // contentEditable有効なとき記法をHTMLに展開
        Hatena.Diary.extractFotolifeSyntax(fotolife_syntax).done(function(res) {
            Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText(res.html);
        });
    } else {
        Hatena.Diary.Pages.AdminTouch['user-blog-edit'].insertText('[' + fotolife_syntax.replace(/:image/, ':plain') + ']');
    }
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].trackPhotoUpload = function() {
    // アップロードされたときにfluentdに記録
    // XHRでアップロードかformでアップロードかでキーを変えています
    var track_name = (typeof FormData != 'undefined') ? 'photo-xhr-upload-touch' : 'photo-form-upload-touch';
    Hatena.Diary.trackEvent(track_name);
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupMyCuration = function() {
    $('[data-curation-action]').click(function() {
        var action = $(this).attr('data-curation-action');
        Hatena.Diary.EditorConnector.loadServiceOnChildWindow("/-/curation/" + action);
        Hatena.Diary.trackEvent('open-curation-' + action);
    });
};

// <input> type="date/time" が有効か
Hatena.Diary.Pages.AdminTouch['user-blog-edit'].dateTimeEditorEnabled = function() {
    var enable_list = _.map(['date', 'time'], function (type) {
        // 参照: http://stackoverflow.com/questions/10193294/how-can-i-tell-if-a-browser-supports-input-type-date
        var input = document.createElement('input');
        input.setAttribute('type', type);
        input.setAttribute('value', 'not-a-date');
        return input.type !== 'text' && input.value !== 'not-a-date';
    });

    return _.all(enable_list);
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupScheduledEntry = function() {
    // 日付あるとき，チェックボックス出す
    // チェックついてるとき，公開ボタン，下書きボタン，シェアUIを消して，予約投稿ボタン出す

    var $datetime = $('input[name=datetime]');
    var $checkbox = $('.js-scheduled-entry-checkbox');
    var $normalParts = $('.js-show-on-normal-post');
    var $scheduledParts = $('.js-show-on-scheduled-post');

    // datetimeかcheckboxが更新されたら呼ばれる
    var updateParts = function() {
        if ($datetime.val()) {
            $checkbox.prop('disabled', false);
        } else {
            $checkbox.prop('disabled', true);
        }

        if ($datetime.val() && $checkbox.prop('checked')) {
            $normalParts.hide();
            $scheduledParts.show();
        } else {
            $normalParts.show();
            $scheduledParts.hide();
        }
    };

    $datetime.on('change', updateParts);
    $checkbox.on('change', updateParts);

    updateParts();
};

Hatena.Diary.Pages.AdminTouch['user-blog-edit'].setupDateTimeEditor = function() {
    $('.post-options .js-datetime').show();

    var $date = $('.js-datetime-input-date');
    var $time = $('.js-datetime-input-time');
    var $datetime = $('input[name=datetime]');

    // 値を設定するだけでなく,changeイベントも発行する．予約投稿JSがdatetimeのchangeイベント見てるため
    var setDatetime = function(value) {
        $datetime.val(value).trigger('change');
    };

    // admin-user-blog-edit.jsからのコピペ
    var todayString = function () {
        var now = new Date();
        var date = [];
        date.push((1900 + now.getYear()).toString());
        date.push(('0' + (1 + now.getMonth()).toString()).slice(-2));
        date.push(('0' + now.getDate().toString()).slice(-2));
        return date.join('-');
    };

    // 投稿日時があるとき(既に投稿されたエントリを編集するとき), フィルインする
    var entry_datetime = $datetime.val();
    if (entry_datetime) {
        var match_data = entry_datetime.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})\+(\d{2}:\d{2})$/);
        var date = match_data[1];
        var time = match_data[2];

        $date.val(date);
        $time.val(time);
    }

    $date.change(function() {
        var date = $date.val();
        var time = $time.val();

        // 消去されたとき, 初期値に戻す
        if (!date) {
            setDatetime(entry_datetime);
            return;
        }

        if (!time) {
            $time.val('00:00');
            time = '00:00';
        }

        setDatetime(date + 'T' + time);
    });

    $time.change(function() {
        var date = $date.val();
        var time = $time.val();

        // 消去されたとき, 初期値に戻す
        if (!time) {
            setDatetime(entry_datetime);
            return;
        }

        if (!date) {
            var today = todayString();
            $date.val(today);
            date = today;
        }

        setDatetime(date + 'T' + time);
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-action'] = function () {
    Hatena.Diary.Pages.createForParent();
    Hatena.Diary.Pages.send('resize', {
        height: $(document.body).height()
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-comment'] = function () {
    Hatena.Diary.Pages.createForParent();

    var resize = function(){
        Hatena.Diary.Pages.send('resize', {
            height: $('html').height()
        });
    };

    // CAPTCHAなど画像あるとき読み込むと高さ変わる
    var $img = $('img');
    if ($img.length > 0) {
        $('img').on('load', resize);
    }

    resize();
};

Hatena.Diary.Pages.AdminTouch['user-blog-entries'] = function () {
    Hatena.Diary.Pages.AdminTouch['user-blog-entries'].setupEntryListLinks();
};

Hatena.Diary.Pages.AdminTouch['user-blog-entries'].setupEntryListLinks = function () {
    $('ul#entries li').click(function (e) {
        if ($(e.target).parents('a').length === 0) {
            location.href = $(this).find('a:first').attr('href');
        }
    });
};

Hatena.Diary.Pages.AdminTouch['user-blog-accesslog'] = function () {
    var table = $('#access-counts').remove();
    var counts = {};
    table.find('tr').each(function () {
        var $this = $(this);
        var time  = +$this.find('td[data-time]').attr('data-time');
        var count = +$this.find('td[data-count]').attr('data-count');
        counts[time] = count;
    });

    AccessLog.showGraph(counts, {
        parent : $('#access-counts-daily'),
        timeformat : '%m/%d',
        minTickSize : [1, 'day'],
        unit   : 24 * 60 * 60 * 1000,
        number : 14,
        graphAreaMarginRight : 20,
        barWidth : 15
    });

    AccessLog.showGraph(counts, {
        parent : $('#access-counts-hourly'),
        timeformat : '%d %H:%M',
        minTickSize : [1, 'hour'],
        unit   : 60 * 60 * 1000,
        number : 24,
        graphAreaMarginRight : 20,
        barWidth : 10
    });

    $('#access-counts-tabs').tabs({ active : 0 });

    $('#summary-detail-tabs').tabs({ active : 0 });

    $('.summary-box .hosts').delegate('.host', 'click', function() {
        $('.summary-box .hosts .selected').removeClass('selected');
        $(this).addClass('selected');

        var host = $(this).attr('data-site-host');
        $('.summary-box .site.selected').removeClass('selected');
        $('.summary-box .sites').find('*[data-site-host="' + host + '"]').addClass('selected');
        return false;
    });
};

Hatena.Diary.Pages.AdminTouch['antenna'] = function () {

    var $closedBlogs = $('.closed-blog');
    $closedBlogs.each(function(){
        var $closedBlog = $(this);
        var antennaUrl = $closedBlog.data("antennaUrl");
        $.ajax({
            type: 'GET',
            url: antennaUrl,
            data: { device: 'touch' },
            dataType: 'html',
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            }
        }).done(function(res){
            $closedBlog.empty();
            $closedBlog.append(res);
            var $blogContents = $closedBlog.find('.js-blog-content');
            Hatena.Locale.updateTimestamps($blogContents[0]);
        });
    });

};

Hatena.Diary.Pages.AdminTouch['topic-show'] = function () {
    var $description = $('.description');
    var $topic_entries_tabs = $('#topic-entries-tabs');

    // 「続きを読む」をクリックすると説明文をすべて表示する
    $description.find('.read-more').on('click', function (e) {
        e.preventDefault();
        var $read_more_text = $description.find('.read-more-text');
        $description.html( $read_more_text.html() );
    });

    // 「注目」と「新着」タブの切替
    $topic_entries_tabs.tabs({ active : 0 });
};

})(jQuery);

(function($){

Hatena.Diary.Pages.BlogsTouch['*'] = function () {
    // iframeからはアクセスログのapiを叩かない
    if (window.parent === window ) {
        Hatena.Diary.AccessLog.ping();
    }

    Hatena.Diary.Pages.infoLoaded.done(function(info) {
        Hatena.Diary.Pages.BlogsTouch['*'].init(info);
    });

    Hatena.Diary.Util.updateDynamicPieces([document]);

    Hatena.Diary.Pages.BlogsTouch['*'].initEntries();
    Hatena.Diary.Pages.BlogsTouch['*'].initFooterAction();
    Hatena.Diary.Pages.BlogsTouch['*'].setupOndemandCommentDeleteButton();
    Hatena.Diary.Star.initBigStar();
    Hatena.Diary.Pages.BlogsTouch['*'].setupEntriesAccessRankingModule();
};

Hatena.Diary.Pages.BlogsTouch['*'].init = function (info) {
    // グローバルヘッダから情報もらえるので，使いたかったらここで使う

    // globalhaederがキャッシュされているのでこちらからviaを送ってやる
    var via = Hatena.Diary.Location.param('via');
    if (via) {
        Hatena.Diary.Pages.send('inheritVia', via);
    }
};

Hatena.Diary.Pages.BlogsTouch['*'].initEntries = function () {
    var self = this;
    $('.js-entry-article').each(function () {
        var $this = $(this);
        self.initEntry($this);
    });
};

Hatena.Diary.Pages.BlogsTouch['*'].initEntry = function (entry) {
    var self = this;
    var uuid = entry.attr('data-uuid');
    Hatena.Diary.Util.replaceYoutubeURL(entry);

    Hatena.Diary.Pages.BlogsTouch['*'].initEntryComment(entry);
    Hatena.Diary.Pages.BlogsTouch['*'].initEditButton(entry);
};

Hatena.Diary.Pages.BlogsTouch['*'].initEntryComment = function (entry) {
    var self = this;
    var container = entry.find('.js-comment-box .js-comment');
    $(container).delegate('.js-comment-delete-button', 'click', function (e) {
        var $this = $(this);
        var commentId = $this.closest('.js-entry-comment').attr('id');

        var iframeContainer = $(
            '<div class="hatena-iframe-container"><div class="loading js-loading">' +
            '<img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt="loading"/>' +
            Hatena.Locale.text('loading') +
            '</div></div>').appendTo(this);
        var iframe = $('<iframe frameborder="0"></iframe>').appendTo(iframeContainer);
        iframeContainer.
        css({
            width: 440,
            height: 120,
            position: 'absolute',
            zIndex: 999
        }).
        offset( $this.offset() );

        var loading = iframeContainer.find('.js-loading').hide();
        setTimeout( function () { loading.show() }, 250);
        iframe.load(function () { loading.remove() });

        var uri = Hatena.Diary.data('admin-domain') +
            '/' + Hatena.Diary.data('author') + '/' + Hatena.Diary.data('blog') +
            '/comment/delete?comment=' + encodeURIComponent(commentId.slice(8));

        var messenger = Messenger.createForFrame(iframe[0], uri);
        messenger.addEventListener('delete', function (data) {
            $("#" + commentId).fadeOut();
        });
        messenger.addEventListener('close', function () {
            Hatena.Diary.Window.hide(iframeContainer);
        });

        Hatena.Diary.Window.show(iframeContainer, {
            destroy : function () {
                iframe.remove();
                messenger.destroy();
            }
        });
        return false;
    });

    self.loadEntryInfo(entry).done(function (info) {
        if (Hatena.Diary.data('page') == 'entry') {
            if (info.comments) {
                var container = entry.find('.js-comment-box .js-comment');
                for (var i = 0, len = info.comments.entries.length; i < len; i++) {
                    container.append(info.comments.entries[i]);
                }
                Hatena.Diary.Util.updateDynamicPieces(container);
            }
        } else {
            entry.find('.js-leave-comment-title').text('(' + (info.comments ? info.comments.entries.length : 0) + ')');
        }
    }).
    fail( Hatena.Diary.REPORT_BUG('loadEntryInfo') );

    if (Hatena.Diary.data('page') == 'entry') entry.find('.js-leave-comment-title').on('click touchend', function (e) {
        var $this = $(this);

        var container = $(
            '<div class="hatena-iframe-container">' +
                '<div class="loading js-loading"><img src="' + Hatena.Diary.URLGenerator.static_url('/images/loading.gif') + '" alt="loading"/>' +
                    Hatena.Locale.text('loading') +
                '</div>' +
            '</div>'
        ).insertAfter($this);

        if ($this.data('comment-container')) {
            $this.data('comment-container').remove();
        }
        $this.data('comment-container', container);

        var iframe = $('<iframe frameborder="0"></iframe>').appendTo(container);

        var loading = container.find('.js-loading').hide();

        setTimeout(function () {
            loading.show();
        }, 250);

        iframe.load(function () {
            loading.remove();
        });

        container.
            css({
                width: '100%'/*,
                height: 235
                */
            });

        editinplace = iframe[0];

        var uri = Hatena.Diary.data('admin-domain') +
            '/touch/' + Hatena.Diary.data('author') + '/' + Hatena.Diary.data('blog') + '/comment?' +
            $.param({
                entry : entry.attr('data-uuid'),
                token : $.cookie('bk')
            });

        var messenger = Messenger.createForFrame(editinplace, uri);
        messenger.addEventListener('update', function (data) {
            var container = entry.find('.js-comment-box .js-comment');
            var top_is_new = Hatena.Diary.data('blog-comments-top-is-new');
            if (top_is_new) {
                container.prepend(data.comment);
            } else {
                container.append(data.comment);
            }
            Hatena.Diary.Util.updateDynamicPieces(container);
        });

        messenger.addEventListener('close', function () {
            container.remove();
            messenger.destroy();
        });

        messenger.addEventListener('resize', function (css) {
            if (css) container.css(css);
        });

        return false;
    });
};

Hatena.Diary.Pages.BlogsTouch['*'].initEditButton = function ($entry) {
    var $button_container = $entry.find('.js-entry-edit-button-container');
    var $button = $button_container.find('.js-entry-edit-button');


    Hatena.Diary.Pages.infoLoaded.done(function (info) {
        if (!info.editable) return;

        $button_container.show();
        var editor_url = Hatena.Diary.data('admin-domain') + '/' +
            Hatena.Diary.data('author')       + '/' +
            Hatena.Diary.data('blog')         + '/edit?entry=' + $entry.attr('data-uuid');
        $button.attr('href', editor_url);
    });
};

Hatena.Diary.Pages.BlogsTouch['*'].loadEntryInfo = function me (entry) {
    if (!me.data) me.data = {
        timer : setTimeout(function () {
            var data = me.data;
            me.data = null;
            $.ajax({
                url : Hatena.Diary.URLGenerator.user_blog_url('/api/entry/info'),
                type : "get",
                dataType : 'json',
                cache : false,
                data : {
                    e : data.entries
                },
                success : function (res) {
                    var entries = res.entries;
                    for (var key in entries) if (entries.hasOwnProperty(key)) {
                        var val = entries[key];
                        data.deferred[key].resolve(val);
                    }
                }
            });
        }, 0),
        entries : [],
        deferred : {}
    };

    var ret  = $.Deferred();
    var uuid = entry.attr('data-uuid');

    me.data.entries.push(uuid);
    me.data.deferred[uuid] = ret;

    return ret;
};

Hatena.Diary.Pages.BlogsTouch['*'].setupOndemandCommentDeleteButton = function() {
    $(document).on('mouseenter', '.js-entry-comment', function() {
        var $comment = $(this);
        if ($comment.find('.js-comment-delete-button .js-comment-delete-image').size() > 0)
            return;
        var comment_uuid = $comment.attr('data-comment-uuid');
        var blog_uuid = $comment.attr('data-blog-uuid');
        var url = Hatena.Diary.data('admin-domain') + '/api/comment.delete.image?comment=' + comment_uuid + '&blog=' + blog_uuid;
        var $img = $('<img>');
        $img.addClass('js-comment-delete-image');
        $img.attr('src', url);
        var handler = function() {
            $img.attr('alt', 'delete');
        };
        $img.load(handler);
        $img.error(handler);
        $comment.find('.js-comment-delete-button').append($img);
    });
};

Hatena.Diary.Pages.BlogsTouch['*'].initFooterAction = function () {
    var footerAction = $('iframe.js-footer-action');
    if (footerAction.length) {
        try {
            var messenger = Messenger.createForFrame(footerAction.get(0), footerAction.attr('data-src'));
            messenger.addEventListener('resize', function (css) {
                if (css) footerAction.css(css);
            });
        } catch(ignore) {
            // AndroidではMessenger作るのに失敗してSecurityErrorが発生する場合がある
            // 通信できなかったら仕方ないのであきらめる
        }
    }
};

Hatena.Diary.Pages.BlogsTouch['*'].setupEntriesAccessRankingModule = function () {
    var $entriesAccessRanking = $('.hatena-module-entries-access-ranking');
    if ($entriesAccessRanking.length === 0) return;

    $entriesAccessRanking.each(function () {
        var $self = $(this);
        var queryParams = {};
        // `data-`のprefixがついた属性をすべて取得し，クエリパラメータにする
        _.each( ($self)[0].attributes, function (attr) {
            if ( ! attr.name.match(/^data-/) ) return;
            // `data-`のprefixはクエリパラメータのkeyには不要なので取り除く
            queryParams[ attr.name.replace(/^data\-/, '') ] = attr.value;
        } );

        $.ajax({
            type: 'GET',
            url: Hatena.Diary.URLGenerator.user_blog_url('/entries_access_ranking_module'),
            data: queryParams,
            dataType: 'html'
        }).done(function(res) {
            $self.find('.hatena-module-body').append(res);
        });
    });
};

Hatena.Diary.Pages.BlogsTouch['global-top'] = function () {
    // viaを引き継いでiframeを読み込む
    var via = Hatena.Diary.Location.param('via');
    var $dashboardLinks = $('iframe.js-dashboard-link');
    $dashboardLinks.each(function(index, element) {
        var $iframe = $(element);
        var src = $iframe.data('src').split(/\?/);
        var query = src[1] || '';

        var params = Hatena.Diary.Util.decodeParam(query);
        params['via'] = via;

        element.contentWindow.location.replace(src[0] + '?' + $.param(params, true));
    });

    $('img[data-alternate-src]').one('error', function() {
        var $img = $(this);
        $img.attr('src', $img.attr('data-alternate-src'));
    });

    $('.js-category-wrapper').tabs({
        selected : 0
    });

    // 標準のタブのUIではなく，nav-barのスタイルを当てたいので，クラス消す
    $('.js-category-wrapper .ui-tabs-nav').removeClass('ui-tabs-nav');
};

})(jQuery);

if (!Hatena.Locale) {
  document.createElement('time'); // IE

Hatena.Locale = {
    /* --- Languages --- */

    getAvailLangs: function () {
        if (this._availLangs) return this._availLangs;
        var de = document.documentElement;
        var langs = de ? de.getAttribute('data-avail-langs') : '';
        if (langs) {
            langs = langs.split(/\s+/);
        } else {
            langs = [];
        }
        this._availLangs = langs;
        return langs;
    },

    setAcceptLang: function (newLang) {
        var cookie = new this.Cookie();
        cookie.set('Accept-Language', newLang, {domain: this.cookieDomain, expires: '+1y', path: '/'});
        cookie.set('_hatena_set_lang', 1, {domain: this.cookieDomain, expires: '+1d', path: '/'});
    },

    getTextLang: function () {
        var docEl = document.documentElement;
        if (!docEl) return 'ja';
        var lang = docEl.getAttribute('lang');
        return lang || 'ja';
    },

    loadTextData: function () {
        var key = 'textDataLoaded' + this.textDataDirName + this.textDataFileNameStemSuffix;
        if (this[key]) return;
        this[key] = true;

        var self = this;
        var host = this.dataHost;
        var lang = this.getTextLang();
        var date = new Date();
        var url = 'http://' + host + '/js/' + this.textDataDirName + 'texts-' + lang + this.textDataFileNameStemSuffix + '.js?' + date.getFullYear() + date.getMonth() + date.getDate();

        if (typeof Ten != "undefined" && Ten.AsyncLoader) {
            Ten.AsyncLoader.loadScripts([url], function () {
                var key = 'Hatena.Locale,' + self.project + ',Text';
                Ten.AsyncLoader.registerObject(key, self);
            });
        } else {
            var script = document.createElement('script');
            script.src = url;
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    },

    text: function (msgid) {
        var allArgs = arguments;
        var lang = this.getTextLang();
        var entry;
        try {
            entry = Hatena[this.project].Locale.Data.Text[lang][msgid];
        } catch (e) {}
        if (entry) {
            var v = entry.value;
            var args = entry.args;
            if (args) {
                var i = 0;
                return v.replace(/%s/, function () {
                    return allArgs[parseInt(args[i++], 10)];
                });
            } else {
                return v;
            }
        } else {
            return msgid;
        }
    },

    textN: function (msgid, n) {
        var allArgs = arguments;
        var lang = this.getTextLang();
        n = n || 0;
        var entry;
        try {
            entry = Hatena[this.project].Locale.Data.Text[lang][msgid];
        } catch (e) { }
        if (entry) {
            var qt = entry.quanttype || 'o';
            var v = entry.value;
            var args = entry.args;
            if (qt == '1_o') {
                if (n == 1) {
                    v = entry.value_1;
                    args = entry.args_1;
                }
            } else if (qt == '01_o') {
                if (n === 0 || n === 1) {
                    v = entry.value_1;
                    args = entry.args_1;
                }
            }

            if (args) {
                var i = 0;
                return v.replace(/%s/, function () {
                    return allArgs[1 + parseInt(args[i++], 10)];
                });
            } else {
                return v;
            }
        } else {
            return msgid;
        }
    },

    textFwN: function (msgid, n) {
        var lang = this.getTextLang();
        if (/^ja(?:-|$)$/.test(lang)) {
            //
        } else {
            n *= 2;
        }

        var args = [msgid, n, this.number(n)];
        for (var i = 2; i < arguments.length; i++) {
            args.push(arguments[i]);
        }

        return this.textN.apply(this, args);
    },

    // IE
    _period00: new RegExp('\\' + Number(0).toLocaleString().replace(/0/g, '') + '0+$'),

    number: function (n) {
        return (n + 0).toLocaleString().replace(this._period00, '');
    },

    /* --- Regions --- */

    getAvailRegions: function () {
        if (this._availRegions) return this._availRegions;
        var de = document.documentElement;
        var regions = de ? de.getAttribute('data-avail-regions') : '';
        if (regions) {
            regions = regions.split(/\s+/);
        } else {
            regions = [];
        }
        this._availRegions = regions;
        return regions;
    },

    getRegionCode: function () {
        var docEl = document.documentElement;
        if (!docEl) return 0;
        var region = docEl.getAttribute('data-region');
        return parseInt(region || 0, 10);
    },

    setRegionCode: function (newRegionCode) {
        var cookie = new this.Cookie();
        cookie.set('_hatena_region', newRegionCode, {domain: this.cookieDomain, expires: '+1y', path: '/'});
    },

    /* --- Date and Time --- */

    datetimeHTML: function (dt) {
        var y = '000' + dt.getUTCFullYear(); y = y.substring(y.length - 4);
        var M = '0' + (dt.getUTCMonth() + 1); M = M.substring(M.length - 2);
        var d = '0' + dt.getUTCDate(); d = d.substring(d.length - 2);
        var h = '0' + dt.getUTCHours(); h = h.substring(h.length - 2);
        var m = '0' + dt.getUTCMinutes(); m = m.substring(m.length - 2);
        var s = '0' + dt.getUTCSeconds(); s = s.substring(s.length - 2);
        var ms = '00' + dt.getUTCMilliseconds(); ms = ms.substring(ms.length - 3);
        return '<time datetime="'+y+'-'+M+'-'+d+'T'+h+':'+m+':'+s+'.'+ms+'Z">' + dt.toLocaleString() + '</time>';
    },

    /* You have to add service name tags to msgids such as "minutes_n"
       in Hatena::Translator such that messages are included in
       data-??.js. */
    deltaDatetime: function (dt) {
        function datetime_to_delta (date) {
            var diff   = (new Date().getTime() - date.getTime()) / 1000;
            var future = diff < 0;
            if (future) diff = -diff;
            diff = Math.floor(diff / 60);
            if (diff < 60) {
                return { num : diff, unit : 'minutes_n', future : future };
            }
            diff = Math.floor(diff / 60);
            if (diff < 24) {
                return { num : diff, unit : 'hours_n', future : future };
            }
            diff = Math.floor(diff / 24);
            if (diff < 365) {
                return { num : diff, unit : 'days_n', future : future };
            }
            diff = Math.floor(diff / 365);
            return { num : diff, unit : 'years_n', future : future };
        }

        var delta = datetime_to_delta(dt);

        if (typeof delta.num != "undefined") {
            var text = Hatena.Locale.textN(delta.unit, delta.num, delta.num);
            if (delta.future) {
                return Hatena.Locale.text('datetime.later', text);
            } else {
                return Hatena.Locale.text('datetime.ago', text);
            }
        } else {
            return dt.toLocaleString();
        }
    },

    updateTimestamps: function (root) {
        var datetimePattern = /(\d+-\d+-\d+)T(\d+:\d+:\d+)(?:\.(\d+))?Z/;

        root = root || document;
        var targets = root.getElementsByTagName('time'); // XXX class=""
        for (var i = 0, len = targets.length; i < len; i++) {
            var time = targets[i];
            if (time._date) { continue; }

            // Check date type
            var isRelative = (time.getAttribute('data-relative') !== null);
            var isLocal    = (time.getAttribute('data-local') !== null);
            if (!isRelative && !isLocal) { continue; }

            // Time attr -> Date object
            var datetime = time.getAttribute('datetime');
            var epoch    = time.getAttribute('data-epoch');
            if (!datetime && !epoch) { continue; }

            var date;
            if (datetime && datetime.match(datetimePattern)) {
                date = new Date(datetime);
            }
            else if (epoch && epoch.match(/^\d+$/)) {
                date = new Date(+epoch);
            }
            if (! date) { continue; }

            // Set innerHTML
            if (isRelative) {
                try {
                    time.innerHTML = Hatena.Locale.deltaDatetime(date);
                } catch (e) {}
            }
            if (isLocal) {
                time.innerHTML = date.toLocaleString();
            }
        }
    },

    setupTimestampUpdater : function () {
        if (Hatena.Locale._timestampUpdaterEnabled) return;
        Hatena.Locale._timestampUpdaterEnabled = true;

        Hatena.Locale.updateTimestamps();
        setInterval(function () {
            Hatena.Locale.updateTimestamps();
        }, 60 * 1000);
    },

    /* --- URLs and Navigation --- */

    reload: function (args) {
        var query = location.search;
        if (query) {
            args = args || {};
            var preserve = args.preserve || {};

            query = query.replace(/^\?/, '').split(/[&;]/);
            var changed = false;
            var newQuery = [];
            for (var i = 0; i < query.length; i++) {
                var qp = query[i];
                var m;
                if ((m = qp.match(/^(locale.[^=]+)/))) {
                    if (preserve[m[1]]) {
                        newQuery.push(qp);
                    } else {
                        changed = true;
                    }
                } else {
                    newQuery.push(qp);
                }
            }

            if (changed) {
                location.search = '?' + newQuery.join('&');
                return;
            }
        }

        location.reload(true);
    },

    reloadIfWrongLocale: function () {
        var cookie = new this.Cookie();

        if (/\blocale\.(?:lang|region|country)\b/.test(location.search)) {
            return;
        }

        if (cookie.get('_hatena_locale_reload')) {
            cookie.set('_hatena_locale_reload', '', {domain: this.cookieDomain, expires: '-1y', path: '/'});
            return;
        } else {
            var cookieLang = (cookie.get('Accept-Language') || '').split(/,/)[0].split(/;/)[0].replace(/[^A-Za-z0-9\-]/g, '').toLowerCase();
            var cookieRegion = cookie.get('_hatena_region');
            if (!cookieLang || cookieRegion === null || cookieRegion === '') return;
            cookieRegion = parseInt(cookieRegion, 10);

            var currentLang = Hatena.Locale.getTextLang();
            var currentRegion = Hatena.Locale.getRegionCode();
            if (currentLang == cookieLang && currentRegion == cookieRegion) return;

            var availLangs = Hatena.Locale.getAvailLangs();
            var availRegions = Hatena.Locale.getAvailRegions();
            if (availLangs.join(",").indexOf(cookieLang) == -1) return;
            if (availRegions.join(",").indexOf(cookieRegion) == -1) return;

            cookie.set('_hatena_locale_reload', 1, {domain: this.cookieDomain, path: '/'});
            location.reload(true);
            return;
        }
    },

    urlWithLangAndRegion: function (url) {
        var q = [];
        if (/\?/.test(url)) {
            var u = url.split(/\?/, 2);
            var qp = u[1].split(/[&;]/);
            for (var i = 0; i < qp.length; i++) {
                if (!/^locale\.(lang|region)=/.test(qp[i])) {
                    q.push(qp[i]);
                }
            }
            url = u[0];
        }
        q.push('locale.lang=' + encodeURIComponent(this.getTextLang()));
        q.push('locale.region=' + encodeURIComponent(this.getRegionCode()));
        return url + '?' + q.join('&');
    },

    /* --- Cookie and remote data configuration --- */

    project: 'Default',
    textDataFileNameStemSuffix: '',
    textDataDirName: '',
    dataHost: location.host,
    cookieDomain: '.hatena.ne.jp'
};
Hatena.Locale.Cookie = function () { this.init.apply(this, arguments) };
Hatena.Locale.Cookie.prototype = {
    init : function (string) {
        this.cookies = this.parse(string);
    },

    parse: function(string) {
        var cookies = { };

        var segments = (string || document.cookie).split(/;\s*/);
        while (segments.length) {
            try {
                var segment = segments.shift().replace(/^\s*|\s*$/g, '');
                if (!segment.match(/^([^=]*)=(.*)$/))
                    continue;
                var key = RegExp.$1, value = RegExp.$2;
                if (value.indexOf('&') != -1) {
                    value = value.split(/&/);
                    for (var i = 0; i < value.length; i++)
                        value[i] = decodeURIComponent(value[i]);
                } else {
                    value = decodeURIComponent(value);
                }
                key = decodeURIComponent(key);

                cookies[key] = value;
            } catch (e) {
            }
        }

        return cookies;
    },

    set: function(key, value, option) {
        this.cookies[key] = value;

        if (value instanceof Array) {
            for (var i = 0; i < value.length; i++)
                value[i] = encodeURIComponent(value[i]);
            value = value.join('&');
        } else {
            value = encodeURIComponent(value);
        }
        var cookie = encodeURIComponent(key) + '=' + value;

        option = option || { };
        if (typeof option == 'string' || option instanceof Date) {
            // deprecated
            option = {
                expires: option
            };
        }

        if (!option.expires) {
            option.expires = this.defaultExpires;
        }
        if (/^\+?(\d+)([ymdh])$/.exec(option.expires)) {
            var count = parseInt(RegExp.$1, 10);
            var field = ({ y: 'FullYear', m: 'Month', d: 'Date', h: 'Hours' })[RegExp.$2];

            var date = new Date();
            date['set' + field](date['get' + field]() + count);
            option.expires = date;
        }

        if (option.expires) {
            if (option.expires.toUTCString)
                option.expires = option.expires.toUTCString();
            cookie += '; expires=' + option.expires;
        }
        if (option.domain) {
            cookie += '; domain=' + option.domain;
        }
        if (option.path) {
            cookie += '; path=' + option.path;
        } else {
            cookie += '; path=/';
        }

        return (document.cookie = cookie);
    },
    get: function(key) {
        return this.cookies[key];
    },
    has: function(key) {
        return (key in this.cookies) && !(key in Object.prototype);
    },
    clear: function(key) {
        this.set(key, '', new Date(0));
        delete this.cookies[key];
    }
};

if (/\.hatena\.com$/i.test(location.hostname)) {
    Hatena.Locale.cookieDomain = '.hatena.com';
}

} // if (!Hatena.Locale)
