text: /*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
  !function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=Array.isArray(d)))?(e?(e=!1,f=c&&Array.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,N,e),g(f,c,O,e)):(f++,j.call(a,g(f,c,N,e),g(f,c,O,e),g(f,c,N,c.notifyWith))):(d!==N&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),
      a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},U=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function V(){this.expando=r.expando+V.uid++}V.uid=1,V.prototype={cache:function(a){var b=a[this.expando];return b||(b={},U(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){Array.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(L)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var W=new V,X=new V,Y=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function $(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:Y.test(a)?JSON.parse(a):a)}function _(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Z,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=$(c)}catch(e){}X.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return X.hasData(a)||W.hasData(a)},data:function(a,b,c){return X.access(a,b,c)},removeData:function(a,b){X.remove(a,b)},_data:function(a,b,c){return W.access(a,b,c)},_removeData:function(a,b){W.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=X.get(f),1===f.nodeType&&!W.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),_(f,d,e[d])));W.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){X.set(this,a)}):T(this,function(b){var c;if(f&&void 0===b){if(c=X.get(f,a),void 0!==c)return c;if(c=_(f,a),void 0!==c)return c}else this.each(function(){X.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=W.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var aa=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ba=new RegExp("^(?:([+-])=|)("+aa+")([a-z%]*)$","i"),ca=["Top","Right","Bottom","Left"],da=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ea=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function fa(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&ba.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ga={};function ha(a){var b,c=a.ownerDocument,d=a.nodeName,e=ga[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ga[d]=e,e)}function ia(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=W.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&da(d)&&(e[f]=ha(d))):"none"!==c&&(e[f]="none",W.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ia(this,!0)},hide:function(){return ia(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){da(this)?r(this).show():r(this).hide()})}});var ja=/^(?:checkbox|radio)$/i,ka=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c<d;c++)W.set(a[c],"globalEval",!b||W.get(b[c],"globalEval"))}var pa=/<|&#?\w+;/;function qa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(pa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ka.exec(f)||["",""])[1].toLowerCase(),i=ma[h]||ma._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==xa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===xa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&B(this,"input"))return this.click(),!1},_default:function(a){return B(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?va:wa,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:wa,isPropagationStopped:wa,isImmediatePropagationStopped:wa,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=va,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=va,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=va,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&sa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ta.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return ya(this,a,b,c,d)},one:function(a,b,c,d){return ya(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=wa),this.each(function(){r.event.remove(this,a,c,b)})}});var za=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/<script|<style|<link/i,Ba=/checked\s*(?:[^=]|=\s*.checked.)/i,Ca=/^true\/(.*)/,Da=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}X.hasData(a)&&(h=X.access(a),i=r.extend({},h),X.set(b,i))}}function Ia(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ja.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ja(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,na(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ga),l=0;l<i;l++)j=h[l],la.test(j.type||"")&&!W.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Da,""),k))}return a}function Ka(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(na(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&oa(na(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(za,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d<e;d++)Ia(f[d],g[d]);if(b)if(c)for(f=f||na(a),g=g||na(h),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);else Ha(a,h);return g=na(h,"script"),g.length>0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(na(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ja(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(na(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var La=/^margin/,Ma=new RegExp("^("+aa+")(?!px)[a-z%]+$","i"),Na=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",ra.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,ra.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Oa(a,b,c){var d,e,f,g,h=a.style;return c=c||Na(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ma.test(g)&&La.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Pa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Qa=/^(none|table(?!-c[ea]).+)/,Ra=/^--/,Sa={position:"absolute",visibility:"hidden",display:"block"},Ta={letterSpacing:"0",fontWeight:"400"},Ua=["Webkit","Moz","ms"],Va=d.createElement("div").style;function Wa(a){if(a in Va)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ua.length;while(c--)if(a=Ua[c]+b,a in Va)return a}function Xa(a){var b=r.cssProps[a];return b||(b=r.cssProps[a]=Wa(a)||a),b}function Ya(a,b,c){var d=ba.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Za(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ca[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ca[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ca[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ca[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+ca[f]+"Width",!0,e)));return g}function $a(a,b,c){var d,e=Na(a),f=Oa(a,b,e),g="border-box"===r.css(a,"boxSizing",!1,e);return Ma.test(f)?f:(d=g&&(o.boxSizingReliable()||f===a.style[b]),"auto"===f&&(f=a["offset"+b[0].toUpperCase()+b.slice(1)]),f=parseFloat(f)||0,f+Za(a,b,c||(g?"border":"content"),d,e)+"px")}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Oa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=Ra.test(b),j=a.style;return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:j[b]:(f=typeof c,"string"===f&&(e=ba.exec(c))&&e[1]&&(c=fa(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(j[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i?j.setProperty(b,c):j[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b),i=Ra.test(b);return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Oa(a,b,d)),"normal"===e&&b in Ta&&(e=Ta[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Qa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?$a(a,b,d):ea(a,Sa,function(){return $a(a,b,d)})},set:function(a,c,d){var e,f=d&&Na(a),g=d&&Za(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=ba.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ya(a,c,g)}}}),r.cssHooks.marginLeft=Pa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Oa(a,"marginLeft"))||a.getBoundingClientRect().left-ea(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ca[d]+b]=f[d]||f[d-2]||f[0];return e}},La.test(a)||(r.cssHooks[a+b].set=Ya)}),r.fn.extend({css:function(a,b){return T(this,function(a,b,c){var d,e,f={},g=0;if(Array.isArray(b)){for(d=Na(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&da(a),q=W.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],cb.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=W.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ia([a],!0),j=a.style.display||j,k=r.css(a,"display"),ia([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=W.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ia([a],!0),m.done(function(){p||ia([a]),W.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=hb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],Array.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=kb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=ab||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(i||h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:ab||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);f<g;f++)if(d=kb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,hb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j}r.Animation=r.extend(kb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return fa(c.elem,a,ba.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(L);for(var c,d=0,e=a.length;d<e;d++)c=a[d],kb.tweeners[c]=kb.tweeners[c]||[],kb.tweeners[c].unshift(b)},prefilters:[ib],prefilter:function(a,b){b?kb.prefilters.unshift(a):kb.prefilters.push(a)}}),r.speed=function(a,b,c){var d=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off?d.duration=0:"number"!=typeof d.duration&&(d.duration in r.fx.speeds?d.duration=r.fx.speeds[d.duration]:d.duration=r.fx.speeds._default),null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){r.isFunction(d.old)&&d.old.call(this),d.queue&&r.dequeue(this,d.queue)},d},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(da).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=kb(this,r.extend({},a),f);(e||W.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=W.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&db.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=W.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),r.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(ab=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),ab=void 0},r.fx.timer=function(a){r.timers.push(a),r.fx.start()},r.fx.interval=13,r.fx.start=function(){bb||(bb=!0,eb())},r.fx.stop=function(){bb=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var lb,mb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),
      null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!B(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Tb=[],Ub=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Tb.pop()||r.expando+"_"+ub++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Ub.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ub.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Ub,"$1"+e):b.jsonp!==!1&&(b.url+=(vb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Tb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=pb(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Vb=a.jQuery,Wb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Wb),b&&a.jQuery===r&&(a.jQuery=Vb),r},b||(a.jQuery=a.$=r),r});
  /*! jQuery UI - v1.12.1 - 2017-06-21
  * http://jqueryui.com
  * Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/sortable.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/dialog.js, widgets/mouse.js
  * Copyright jQuery Foundation and other contributors; Licensed MIT */
  
  (function( factory ) {
  	if ( typeof define === "function" && define.amd ) {
  
  		// AMD. Register as an anonymous module.
  		define([ "jquery" ], factory );
  	} else {
  
  		// Browser globals
  		factory( jQuery );
  	}
  }(function( $ ) {
  
  $.ui = $.ui || {};
  
  var version = $.ui.version = "1.12.1";
  
  
  /*!
   * jQuery UI Widget 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Widget
  //>>group: Core
  //>>description: Provides a factory for creating stateful widgets with a common API.
  //>>docs: http://api.jqueryui.com/jQuery.widget/
  //>>demos: http://jqueryui.com/widget/
  
  
  
  var widgetUuid = 0;
  var widgetSlice = Array.prototype.slice;
  
  $.cleanData = ( function( orig ) {
  	return function( elems ) {
  		var events, elem, i;
  		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
  			try {
  
  				// Only trigger remove when necessary to save time
  				events = $._data( elem, "events" );
  				if ( events && events.remove ) {
  					$( elem ).triggerHandler( "remove" );
  				}
  
  			// Http://bugs.jquery.com/ticket/8235
  			} catch ( e ) {}
  		}
  		orig( elems );
  	};
  } )( $.cleanData );
  
  $.widget = function( name, base, prototype ) {
  	var existingConstructor, constructor, basePrototype;
  
  	// ProxiedPrototype allows the provided prototype to remain unmodified
  	// so that it can be used as a mixin for multiple widgets (#8876)
  	var proxiedPrototype = {};
  
  	var namespace = name.split( "." )[ 0 ];
  	name = name.split( "." )[ 1 ];
  	var fullName = namespace + "-" + name;
  
  	if ( !prototype ) {
  		prototype = base;
  		base = $.Widget;
  	}
  
  	if ( $.isArray( prototype ) ) {
  		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
  	}
  
  	// Create selector for plugin
  	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
  		return !!$.data( elem, fullName );
  	};
  
  	$[ namespace ] = $[ namespace ] || {};
  	existingConstructor = $[ namespace ][ name ];
  	constructor = $[ namespace ][ name ] = function( options, element ) {
  
  		// Allow instantiation without "new" keyword
  		if ( !this._createWidget ) {
  			return new constructor( options, element );
  		}
  
  		// Allow instantiation without initializing for simple inheritance
  		// must use "new" keyword (the code above always passes args)
  		if ( arguments.length ) {
  			this._createWidget( options, element );
  		}
  	};
  
  	// Extend with the existing constructor to carry over any static properties
  	$.extend( constructor, existingConstructor, {
  		version: prototype.version,
  
  		// Copy the object used to create the prototype in case we need to
  		// redefine the widget later
  		_proto: $.extend( {}, prototype ),
  
  		// Track widgets that inherit from this widget in case this widget is
  		// redefined after a widget inherits from it
  		_childConstructors: []
  	} );
  
  	basePrototype = new base();
  
  	// We need to make the options hash a property directly on the new instance
  	// otherwise we'll modify the options hash on the prototype that we're
  	// inheriting from
  	basePrototype.options = $.widget.extend( {}, basePrototype.options );
  	$.each( prototype, function( prop, value ) {
  		if ( !$.isFunction( value ) ) {
  			proxiedPrototype[ prop ] = value;
  			return;
  		}
  		proxiedPrototype[ prop ] = ( function() {
  			function _super() {
  				return base.prototype[ prop ].apply( this, arguments );
  			}
  
  			function _superApply( args ) {
  				return base.prototype[ prop ].apply( this, args );
  			}
  
  			return function() {
  				var __super = this._super;
  				var __superApply = this._superApply;
  				var returnValue;
  
  				this._super = _super;
  				this._superApply = _superApply;
  
  				returnValue = value.apply( this, arguments );
  
  				this._super = __super;
  				this._superApply = __superApply;
  
  				return returnValue;
  			};
  		} )();
  	} );
  	constructor.prototype = $.widget.extend( basePrototype, {
  
  		// TODO: remove support for widgetEventPrefix
  		// always use the name + a colon as the prefix, e.g., draggable:start
  		// don't prefix for widgets that aren't DOM-based
  		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
  	}, proxiedPrototype, {
  		constructor: constructor,
  		namespace: namespace,
  		widgetName: name,
  		widgetFullName: fullName
  	} );
  
  	// If this widget is being redefined then we need to find all widgets that
  	// are inheriting from it and redefine all of them so that they inherit from
  	// the new version of this widget. We're essentially trying to replace one
  	// level in the prototype chain.
  	if ( existingConstructor ) {
  		$.each( existingConstructor._childConstructors, function( i, child ) {
  			var childPrototype = child.prototype;
  
  			// Redefine the child widget using the same prototype that was
  			// originally used, but inherit from the new version of the base
  			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
  				child._proto );
  		} );
  
  		// Remove the list of existing child constructors from the old constructor
  		// so the old child constructors can be garbage collected
  		delete existingConstructor._childConstructors;
  	} else {
  		base._childConstructors.push( constructor );
  	}
  
  	$.widget.bridge( name, constructor );
  
  	return constructor;
  };
  
  $.widget.extend = function( target ) {
  	var input = widgetSlice.call( arguments, 1 );
  	var inputIndex = 0;
  	var inputLength = input.length;
  	var key;
  	var value;
  
  	for ( ; inputIndex < inputLength; inputIndex++ ) {
  		for ( key in input[ inputIndex ] ) {
  			value = input[ inputIndex ][ key ];
  			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
  
  				// Clone objects
  				if ( $.isPlainObject( value ) ) {
  					target[ key ] = $.isPlainObject( target[ key ] ) ?
  						$.widget.extend( {}, target[ key ], value ) :
  
  						// Don't extend strings, arrays, etc. with objects
  						$.widget.extend( {}, value );
  
  				// Copy everything else by reference
  				} else {
  					target[ key ] = value;
  				}
  			}
  		}
  	}
  	return target;
  };
  
  $.widget.bridge = function( name, object ) {
  	var fullName = object.prototype.widgetFullName || name;
  	$.fn[ name ] = function( options ) {
  		var isMethodCall = typeof options === "string";
  		var args = widgetSlice.call( arguments, 1 );
  		var returnValue = this;
  
  		if ( isMethodCall ) {
  
  			// If this is an empty collection, we need to have the instance method
  			// return undefined instead of the jQuery instance
  			if ( !this.length && options === "instance" ) {
  				returnValue = undefined;
  			} else {
  				this.each( function() {
  					var methodValue;
  					var instance = $.data( this, fullName );
  
  					if ( options === "instance" ) {
  						returnValue = instance;
  						return false;
  					}
  
  					if ( !instance ) {
  						return $.error( "cannot call methods on " + name +
  							" prior to initialization; " +
  							"attempted to call method '" + options + "'" );
  					}
  
  					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
  						return $.error( "no such method '" + options + "' for " + name +
  							" widget instance" );
  					}
  
  					methodValue = instance[ options ].apply( instance, args );
  
  					if ( methodValue !== instance && methodValue !== undefined ) {
  						returnValue = methodValue && methodValue.jquery ?
  							returnValue.pushStack( methodValue.get() ) :
  							methodValue;
  						return false;
  					}
  				} );
  			}
  		} else {
  
  			// Allow multiple hashes to be passed on init
  			if ( args.length ) {
  				options = $.widget.extend.apply( null, [ options ].concat( args ) );
  			}
  
  			this.each( function() {
  				var instance = $.data( this, fullName );
  				if ( instance ) {
  					instance.option( options || {} );
  					if ( instance._init ) {
  						instance._init();
  					}
  				} else {
  					$.data( this, fullName, new object( options, this ) );
  				}
  			} );
  		}
  
  		return returnValue;
  	};
  };
  
  $.Widget = function( /* options, element */ ) {};
  $.Widget._childConstructors = [];
  
  $.Widget.prototype = {
  	widgetName: "widget",
  	widgetEventPrefix: "",
  	defaultElement: "<div>",
  
  	options: {
  		classes: {},
  		disabled: false,
  
  		// Callbacks
  		create: null
  	},
  
  	_createWidget: function( options, element ) {
  		element = $( element || this.defaultElement || this )[ 0 ];
  		this.element = $( element );
  		this.uuid = widgetUuid++;
  		this.eventNamespace = "." + this.widgetName + this.uuid;
  
  		this.bindings = $();
  		this.hoverable = $();
  		this.focusable = $();
  		this.classesElementLookup = {};
  
  		if ( element !== this ) {
  			$.data( element, this.widgetFullName, this );
  			this._on( true, this.element, {
  				remove: function( event ) {
  					if ( event.target === element ) {
  						this.destroy();
  					}
  				}
  			} );
  			this.document = $( element.style ?
  
  				// Element within the document
  				element.ownerDocument :
  
  				// Element is window or document
  				element.document || element );
  			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
  		}
  
  		this.options = $.widget.extend( {},
  			this.options,
  			this._getCreateOptions(),
  			options );
  
  		this._create();
  
  		if ( this.options.disabled ) {
  			this._setOptionDisabled( this.options.disabled );
  		}
  
  		this._trigger( "create", null, this._getCreateEventData() );
  		this._init();
  	},
  
  	_getCreateOptions: function() {
  		return {};
  	},
  
  	_getCreateEventData: $.noop,
  
  	_create: $.noop,
  
  	_init: $.noop,
  
  	destroy: function() {
  		var that = this;
  
  		this._destroy();
  		$.each( this.classesElementLookup, function( key, value ) {
  			that._removeClass( value, key );
  		} );
  
  		// We can probably remove the unbind calls in 2.0
  		// all event bindings should go through this._on()
  		this.element
  			.off( this.eventNamespace )
  			.removeData( this.widgetFullName );
  		this.widget()
  			.off( this.eventNamespace )
  			.removeAttr( "aria-disabled" );
  
  		// Clean up events and states
  		this.bindings.off( this.eventNamespace );
  	},
  
  	_destroy: $.noop,
  
  	widget: function() {
  		return this.element;
  	},
  
  	option: function( key, value ) {
  		var options = key;
  		var parts;
  		var curOption;
  		var i;
  
  		if ( arguments.length === 0 ) {
  
  			// Don't return a reference to the internal hash
  			return $.widget.extend( {}, this.options );
  		}
  
  		if ( typeof key === "string" ) {
  
  			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
  			options = {};
  			parts = key.split( "." );
  			key = parts.shift();
  			if ( parts.length ) {
  				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
  				for ( i = 0; i < parts.length - 1; i++ ) {
  					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
  					curOption = curOption[ parts[ i ] ];
  				}
  				key = parts.pop();
  				if ( arguments.length === 1 ) {
  					return curOption[ key ] === undefined ? null : curOption[ key ];
  				}
  				curOption[ key ] = value;
  			} else {
  				if ( arguments.length === 1 ) {
  					return this.options[ key ] === undefined ? null : this.options[ key ];
  				}
  				options[ key ] = value;
  			}
  		}
  
  		this._setOptions( options );
  
  		return this;
  	},
  
  	_setOptions: function( options ) {
  		var key;
  
  		for ( key in options ) {
  			this._setOption( key, options[ key ] );
  		}
  
  		return this;
  	},
  
  	_setOption: function( key, value ) {
  		if ( key === "classes" ) {
  			this._setOptionClasses( value );
  		}
  
  		this.options[ key ] = value;
  
  		if ( key === "disabled" ) {
  			this._setOptionDisabled( value );
  		}
  
  		return this;
  	},
  
  	_setOptionClasses: function( value ) {
  		var classKey, elements, currentElements;
  
  		for ( classKey in value ) {
  			currentElements = this.classesElementLookup[ classKey ];
  			if ( value[ classKey ] === this.options.classes[ classKey ] ||
  					!currentElements ||
  					!currentElements.length ) {
  				continue;
  			}
  
  			// We are doing this to create a new jQuery object because the _removeClass() call
  			// on the next line is going to destroy the reference to the current elements being
  			// tracked. We need to save a copy of this collection so that we can add the new classes
  			// below.
  			elements = $( currentElements.get() );
  			this._removeClass( currentElements, classKey );
  
  			// We don't use _addClass() here, because that uses this.options.classes
  			// for generating the string of classes. We want to use the value passed in from
  			// _setOption(), this is the new value of the classes option which was passed to
  			// _setOption(). We pass this value directly to _classes().
  			elements.addClass( this._classes( {
  				element: elements,
  				keys: classKey,
  				classes: value,
  				add: true
  			} ) );
  		}
  	},
  
  	_setOptionDisabled: function( value ) {
  		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
  
  		// If the widget is becoming disabled, then nothing is interactive
  		if ( value ) {
  			this._removeClass( this.hoverable, null, "ui-state-hover" );
  			this._removeClass( this.focusable, null, "ui-state-focus" );
  		}
  	},
  
  	enable: function() {
  		return this._setOptions( { disabled: false } );
  	},
  
  	disable: function() {
  		return this._setOptions( { disabled: true } );
  	},
  
  	_classes: function( options ) {
  		var full = [];
  		var that = this;
  
  		options = $.extend( {
  			element: this.element,
  			classes: this.options.classes || {}
  		}, options );
  
  		function processClassString( classes, checkOption ) {
  			var current, i;
  			for ( i = 0; i < classes.length; i++ ) {
  				current = that.classesElementLookup[ classes[ i ] ] || $();
  				if ( options.add ) {
  					current = $( $.unique( current.get().concat( options.element.get() ) ) );
  				} else {
  					current = $( current.not( options.element ).get() );
  				}
  				that.classesElementLookup[ classes[ i ] ] = current;
  				full.push( classes[ i ] );
  				if ( checkOption && options.classes[ classes[ i ] ] ) {
  					full.push( options.classes[ classes[ i ] ] );
  				}
  			}
  		}
  
  		this._on( options.element, {
  			"remove": "_untrackClassesElement"
  		} );
  
  		if ( options.keys ) {
  			processClassString( options.keys.match( /\S+/g ) || [], true );
  		}
  		if ( options.extra ) {
  			processClassString( options.extra.match( /\S+/g ) || [] );
  		}
  
  		return full.join( " " );
  	},
  
  	_untrackClassesElement: function( event ) {
  		var that = this;
  		$.each( that.classesElementLookup, function( key, value ) {
  			if ( $.inArray( event.target, value ) !== -1 ) {
  				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
  			}
  		} );
  	},
  
  	_removeClass: function( element, keys, extra ) {
  		return this._toggleClass( element, keys, extra, false );
  	},
  
  	_addClass: function( element, keys, extra ) {
  		return this._toggleClass( element, keys, extra, true );
  	},
  
  	_toggleClass: function( element, keys, extra, add ) {
  		add = ( typeof add === "boolean" ) ? add : extra;
  		var shift = ( typeof element === "string" || element === null ),
  			options = {
  				extra: shift ? keys : extra,
  				keys: shift ? element : keys,
  				element: shift ? this.element : element,
  				add: add
  			};
  		options.element.toggleClass( this._classes( options ), add );
  		return this;
  	},
  
  	_on: function( suppressDisabledCheck, element, handlers ) {
  		var delegateElement;
  		var instance = this;
  
  		// No suppressDisabledCheck flag, shuffle arguments
  		if ( typeof suppressDisabledCheck !== "boolean" ) {
  			handlers = element;
  			element = suppressDisabledCheck;
  			suppressDisabledCheck = false;
  		}
  
  		// No element argument, shuffle and use this.element
  		if ( !handlers ) {
  			handlers = element;
  			element = this.element;
  			delegateElement = this.widget();
  		} else {
  			element = delegateElement = $( element );
  			this.bindings = this.bindings.add( element );
  		}
  
  		$.each( handlers, function( event, handler ) {
  			function handlerProxy() {
  
  				// Allow widgets to customize the disabled handling
  				// - disabled as an array instead of boolean
  				// - disabled class as method for disabling individual parts
  				if ( !suppressDisabledCheck &&
  						( instance.options.disabled === true ||
  						$( this ).hasClass( "ui-state-disabled" ) ) ) {
  					return;
  				}
  				return ( typeof handler === "string" ? instance[ handler ] : handler )
  					.apply( instance, arguments );
  			}
  
  			// Copy the guid so direct unbinding works
  			if ( typeof handler !== "string" ) {
  				handlerProxy.guid = handler.guid =
  					handler.guid || handlerProxy.guid || $.guid++;
  			}
  
  			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
  			var eventName = match[ 1 ] + instance.eventNamespace;
  			var selector = match[ 2 ];
  
  			if ( selector ) {
  				delegateElement.on( eventName, selector, handlerProxy );
  			} else {
  				element.on( eventName, handlerProxy );
  			}
  		} );
  	},
  
  	_off: function( element, eventName ) {
  		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
  			this.eventNamespace;
  		element.off( eventName ).off( eventName );
  
  		// Clear the stack to avoid memory leaks (#10056)
  		this.bindings = $( this.bindings.not( element ).get() );
  		this.focusable = $( this.focusable.not( element ).get() );
  		this.hoverable = $( this.hoverable.not( element ).get() );
  	},
  
  	_delay: function( handler, delay ) {
  		function handlerProxy() {
  			return ( typeof handler === "string" ? instance[ handler ] : handler )
  				.apply( instance, arguments );
  		}
  		var instance = this;
  		return setTimeout( handlerProxy, delay || 0 );
  	},
  
  	_hoverable: function( element ) {
  		this.hoverable = this.hoverable.add( element );
  		this._on( element, {
  			mouseenter: function( event ) {
  				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
  			},
  			mouseleave: function( event ) {
  				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
  			}
  		} );
  	},
  
  	_focusable: function( element ) {
  		this.focusable = this.focusable.add( element );
  		this._on( element, {
  			focusin: function( event ) {
  				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
  			},
  			focusout: function( event ) {
  				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
  			}
  		} );
  	},
  
  	_trigger: function( type, event, data ) {
  		var prop, orig;
  		var callback = this.options[ type ];
  
  		data = data || {};
  		event = $.Event( event );
  		event.type = ( type === this.widgetEventPrefix ?
  			type :
  			this.widgetEventPrefix + type ).toLowerCase();
  
  		// The original event may come from any element
  		// so we need to reset the target on the new event
  		event.target = this.element[ 0 ];
  
  		// Copy original event properties over to the new event
  		orig = event.originalEvent;
  		if ( orig ) {
  			for ( prop in orig ) {
  				if ( !( prop in event ) ) {
  					event[ prop ] = orig[ prop ];
  				}
  			}
  		}
  
  		this.element.trigger( event, data );
  		return !( $.isFunction( callback ) &&
  			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
  			event.isDefaultPrevented() );
  	}
  };
  
  $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
  	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
  		if ( typeof options === "string" ) {
  			options = { effect: options };
  		}
  
  		var hasOptions;
  		var effectName = !options ?
  			method :
  			options === true || typeof options === "number" ?
  				defaultEffect :
  				options.effect || defaultEffect;
  
  		options = options || {};
  		if ( typeof options === "number" ) {
  			options = { duration: options };
  		}
  
  		hasOptions = !$.isEmptyObject( options );
  		options.complete = callback;
  
  		if ( options.delay ) {
  			element.delay( options.delay );
  		}
  
  		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
  			element[ method ]( options );
  		} else if ( effectName !== method && element[ effectName ] ) {
  			element[ effectName ]( options.duration, options.easing, callback );
  		} else {
  			element.queue( function( next ) {
  				$( this )[ method ]();
  				if ( callback ) {
  					callback.call( element[ 0 ] );
  				}
  				next();
  			} );
  		}
  	};
  } );
  
  var widget = $.widget;
  
  
  /*!
   * jQuery UI Position 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   *
   * http://api.jqueryui.com/position/
   */
  
  //>>label: Position
  //>>group: Core
  //>>description: Positions elements relative to other elements.
  //>>docs: http://api.jqueryui.com/position/
  //>>demos: http://jqueryui.com/position/
  
  
  ( function() {
  var cachedScrollbarWidth,
  	max = Math.max,
  	abs = Math.abs,
  	rhorizontal = /left|center|right/,
  	rvertical = /top|center|bottom/,
  	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
  	rposition = /^\w+/,
  	rpercent = /%$/,
  	_position = $.fn.position;
  
  function getOffsets( offsets, width, height ) {
  	return [
  		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
  		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
  	];
  }
  
  function parseCss( element, property ) {
  	return parseInt( $.css( element, property ), 10 ) || 0;
  }
  
  function getDimensions( elem ) {
  	var raw = elem[ 0 ];
  	if ( raw.nodeType === 9 ) {
  		return {
  			width: elem.width(),
  			height: elem.height(),
  			offset: { top: 0, left: 0 }
  		};
  	}
  	if ( $.isWindow( raw ) ) {
  		return {
  			width: elem.width(),
  			height: elem.height(),
  			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
  		};
  	}
  	if ( raw.preventDefault ) {
  		return {
  			width: 0,
  			height: 0,
  			offset: { top: raw.pageY, left: raw.pageX }
  		};
  	}
  	return {
  		width: elem.outerWidth(),
  		height: elem.outerHeight(),
  		offset: elem.offset()
  	};
  }
  
  $.position = {
  	scrollbarWidth: function() {
  		if ( cachedScrollbarWidth !== undefined ) {
  			return cachedScrollbarWidth;
  		}
  		var w1, w2,
  			div = $( "<div " +
  				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
  				"<div style='height:100px;width:auto;'></div></div>" ),
  			innerDiv = div.children()[ 0 ];
  
  		$( "body" ).append( div );
  		w1 = innerDiv.offsetWidth;
  		div.css( "overflow", "scroll" );
  
  		w2 = innerDiv.offsetWidth;
  
  		if ( w1 === w2 ) {
  			w2 = div[ 0 ].clientWidth;
  		}
  
  		div.remove();
  
  		return ( cachedScrollbarWidth = w1 - w2 );
  	},
  	getScrollInfo: function( within ) {
  		var overflowX = within.isWindow || within.isDocument ? "" :
  				within.element.css( "overflow-x" ),
  			overflowY = within.isWindow || within.isDocument ? "" :
  				within.element.css( "overflow-y" ),
  			hasOverflowX = overflowX === "scroll" ||
  				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
  			hasOverflowY = overflowY === "scroll" ||
  				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
  		return {
  			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
  			height: hasOverflowX ? $.position.scrollbarWidth() : 0
  		};
  	},
  	getWithinInfo: function( element ) {
  		var withinElement = $( element || window ),
  			isWindow = $.isWindow( withinElement[ 0 ] ),
  			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
  			hasOffset = !isWindow && !isDocument;
  		return {
  			element: withinElement,
  			isWindow: isWindow,
  			isDocument: isDocument,
  			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
  			scrollLeft: withinElement.scrollLeft(),
  			scrollTop: withinElement.scrollTop(),
  			width: withinElement.outerWidth(),
  			height: withinElement.outerHeight()
  		};
  	}
  };
  
  $.fn.position = function( options ) {
  	if ( !options || !options.of ) {
  		return _position.apply( this, arguments );
  	}
  
  	// Make a copy, we don't want to modify arguments
  	options = $.extend( {}, options );
  
  	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
  		target = $( options.of ),
  		within = $.position.getWithinInfo( options.within ),
  		scrollInfo = $.position.getScrollInfo( within ),
  		collision = ( options.collision || "flip" ).split( " " ),
  		offsets = {};
  
  	dimensions = getDimensions( target );
  	if ( target[ 0 ].preventDefault ) {
  
  		// Force left top to allow flipping
  		options.at = "left top";
  	}
  	targetWidth = dimensions.width;
  	targetHeight = dimensions.height;
  	targetOffset = dimensions.offset;
  
  	// Clone to reuse original targetOffset later
  	basePosition = $.extend( {}, targetOffset );
  
  	// Force my and at to have valid horizontal and vertical positions
  	// if a value is missing or invalid, it will be converted to center
  	$.each( [ "my", "at" ], function() {
  		var pos = ( options[ this ] || "" ).split( " " ),
  			horizontalOffset,
  			verticalOffset;
  
  		if ( pos.length === 1 ) {
  			pos = rhorizontal.test( pos[ 0 ] ) ?
  				pos.concat( [ "center" ] ) :
  				rvertical.test( pos[ 0 ] ) ?
  					[ "center" ].concat( pos ) :
  					[ "center", "center" ];
  		}
  		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
  		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
  
  		// Calculate offsets
  		horizontalOffset = roffset.exec( pos[ 0 ] );
  		verticalOffset = roffset.exec( pos[ 1 ] );
  		offsets[ this ] = [
  			horizontalOffset ? horizontalOffset[ 0 ] : 0,
  			verticalOffset ? verticalOffset[ 0 ] : 0
  		];
  
  		// Reduce to just the positions without the offsets
  		options[ this ] = [
  			rposition.exec( pos[ 0 ] )[ 0 ],
  			rposition.exec( pos[ 1 ] )[ 0 ]
  		];
  	} );
  
  	// Normalize collision option
  	if ( collision.length === 1 ) {
  		collision[ 1 ] = collision[ 0 ];
  	}
  
  	if ( options.at[ 0 ] === "right" ) {
  		basePosition.left += targetWidth;
  	} else if ( options.at[ 0 ] === "center" ) {
  		basePosition.left += targetWidth / 2;
  	}
  
  	if ( options.at[ 1 ] === "bottom" ) {
  		basePosition.top += targetHeight;
  	} else if ( options.at[ 1 ] === "center" ) {
  		basePosition.top += targetHeight / 2;
  	}
  
  	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
  	basePosition.left += atOffset[ 0 ];
  	basePosition.top += atOffset[ 1 ];
  
  	return this.each( function() {
  		var collisionPosition, using,
  			elem = $( this ),
  			elemWidth = elem.outerWidth(),
  			elemHeight = elem.outerHeight(),
  			marginLeft = parseCss( this, "marginLeft" ),
  			marginTop = parseCss( this, "marginTop" ),
  			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
  				scrollInfo.width,
  			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
  				scrollInfo.height,
  			position = $.extend( {}, basePosition ),
  			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
  
  		if ( options.my[ 0 ] === "right" ) {
  			position.left -= elemWidth;
  		} else if ( options.my[ 0 ] === "center" ) {
  			position.left -= elemWidth / 2;
  		}
  
  		if ( options.my[ 1 ] === "bottom" ) {
  			position.top -= elemHeight;
  		} else if ( options.my[ 1 ] === "center" ) {
  			position.top -= elemHeight / 2;
  		}
  
  		position.left += myOffset[ 0 ];
  		position.top += myOffset[ 1 ];
  
  		collisionPosition = {
  			marginLeft: marginLeft,
  			marginTop: marginTop
  		};
  
  		$.each( [ "left", "top" ], function( i, dir ) {
  			if ( $.ui.position[ collision[ i ] ] ) {
  				$.ui.position[ collision[ i ] ][ dir ]( position, {
  					targetWidth: targetWidth,
  					targetHeight: targetHeight,
  					elemWidth: elemWidth,
  					elemHeight: elemHeight,
  					collisionPosition: collisionPosition,
  					collisionWidth: collisionWidth,
  					collisionHeight: collisionHeight,
  					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
  					my: options.my,
  					at: options.at,
  					within: within,
  					elem: elem
  				} );
  			}
  		} );
  
  		if ( options.using ) {
  
  			// Adds feedback as second argument to using callback, if present
  			using = function( props ) {
  				var left = targetOffset.left - position.left,
  					right = left + targetWidth - elemWidth,
  					top = targetOffset.top - position.top,
  					bottom = top + targetHeight - elemHeight,
  					feedback = {
  						target: {
  							element: target,
  							left: targetOffset.left,
  							top: targetOffset.top,
  							width: targetWidth,
  							height: targetHeight
  						},
  						element: {
  							element: elem,
  							left: position.left,
  							top: position.top,
  							width: elemWidth,
  							height: elemHeight
  						},
  						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
  						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
  					};
  				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
  					feedback.horizontal = "center";
  				}
  				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
  					feedback.vertical = "middle";
  				}
  				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
  					feedback.important = "horizontal";
  				} else {
  					feedback.important = "vertical";
  				}
  				options.using.call( this, props, feedback );
  			};
  		}
  
  		elem.offset( $.extend( position, { using: using } ) );
  	} );
  };
  
  $.ui.position = {
  	fit: {
  		left: function( position, data ) {
  			var within = data.within,
  				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
  				outerWidth = within.width,
  				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  				overLeft = withinOffset - collisionPosLeft,
  				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
  				newOverRight;
  
  			// Element is wider than within
  			if ( data.collisionWidth > outerWidth ) {
  
  				// Element is initially over the left side of within
  				if ( overLeft > 0 && overRight <= 0 ) {
  					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
  						withinOffset;
  					position.left += overLeft - newOverRight;
  
  				// Element is initially over right side of within
  				} else if ( overRight > 0 && overLeft <= 0 ) {
  					position.left = withinOffset;
  
  				// Element is initially over both left and right sides of within
  				} else {
  					if ( overLeft > overRight ) {
  						position.left = withinOffset + outerWidth - data.collisionWidth;
  					} else {
  						position.left = withinOffset;
  					}
  				}
  
  			// Too far left -> align with left edge
  			} else if ( overLeft > 0 ) {
  				position.left += overLeft;
  
  			// Too far right -> align with right edge
  			} else if ( overRight > 0 ) {
  				position.left -= overRight;
  
  			// Adjust based on position and margin
  			} else {
  				position.left = max( position.left - collisionPosLeft, position.left );
  			}
  		},
  		top: function( position, data ) {
  			var within = data.within,
  				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
  				outerHeight = data.within.height,
  				collisionPosTop = position.top - data.collisionPosition.marginTop,
  				overTop = withinOffset - collisionPosTop,
  				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
  				newOverBottom;
  
  			// Element is taller than within
  			if ( data.collisionHeight > outerHeight ) {
  
  				// Element is initially over the top of within
  				if ( overTop > 0 && overBottom <= 0 ) {
  					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
  						withinOffset;
  					position.top += overTop - newOverBottom;
  
  				// Element is initially over bottom of within
  				} else if ( overBottom > 0 && overTop <= 0 ) {
  					position.top = withinOffset;
  
  				// Element is initially over both top and bottom of within
  				} else {
  					if ( overTop > overBottom ) {
  						position.top = withinOffset + outerHeight - data.collisionHeight;
  					} else {
  						position.top = withinOffset;
  					}
  				}
  
  			// Too far up -> align with top
  			} else if ( overTop > 0 ) {
  				position.top += overTop;
  
  			// Too far down -> align with bottom edge
  			} else if ( overBottom > 0 ) {
  				position.top -= overBottom;
  
  			// Adjust based on position and margin
  			} else {
  				position.top = max( position.top - collisionPosTop, position.top );
  			}
  		}
  	},
  	flip: {
  		left: function( position, data ) {
  			var within = data.within,
  				withinOffset = within.offset.left + within.scrollLeft,
  				outerWidth = within.width,
  				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
  				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  				overLeft = collisionPosLeft - offsetLeft,
  				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
  				myOffset = data.my[ 0 ] === "left" ?
  					-data.elemWidth :
  					data.my[ 0 ] === "right" ?
  						data.elemWidth :
  						0,
  				atOffset = data.at[ 0 ] === "left" ?
  					data.targetWidth :
  					data.at[ 0 ] === "right" ?
  						-data.targetWidth :
  						0,
  				offset = -2 * data.offset[ 0 ],
  				newOverRight,
  				newOverLeft;
  
  			if ( overLeft < 0 ) {
  				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
  					outerWidth - withinOffset;
  				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
  					position.left += myOffset + atOffset + offset;
  				}
  			} else if ( overRight > 0 ) {
  				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
  					atOffset + offset - offsetLeft;
  				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
  					position.left += myOffset + atOffset + offset;
  				}
  			}
  		},
  		top: function( position, data ) {
  			var within = data.within,
  				withinOffset = within.offset.top + within.scrollTop,
  				outerHeight = within.height,
  				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
  				collisionPosTop = position.top - data.collisionPosition.marginTop,
  				overTop = collisionPosTop - offsetTop,
  				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
  				top = data.my[ 1 ] === "top",
  				myOffset = top ?
  					-data.elemHeight :
  					data.my[ 1 ] === "bottom" ?
  						data.elemHeight :
  						0,
  				atOffset = data.at[ 1 ] === "top" ?
  					data.targetHeight :
  					data.at[ 1 ] === "bottom" ?
  						-data.targetHeight :
  						0,
  				offset = -2 * data.offset[ 1 ],
  				newOverTop,
  				newOverBottom;
  			if ( overTop < 0 ) {
  				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
  					outerHeight - withinOffset;
  				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
  					position.top += myOffset + atOffset + offset;
  				}
  			} else if ( overBottom > 0 ) {
  				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
  					offset - offsetTop;
  				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
  					position.top += myOffset + atOffset + offset;
  				}
  			}
  		}
  	},
  	flipfit: {
  		left: function() {
  			$.ui.position.flip.left.apply( this, arguments );
  			$.ui.position.fit.left.apply( this, arguments );
  		},
  		top: function() {
  			$.ui.position.flip.top.apply( this, arguments );
  			$.ui.position.fit.top.apply( this, arguments );
  		}
  	}
  };
  
  } )();
  
  var position = $.ui.position;
  
  
  /*!
   * jQuery UI :data 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: :data Selector
  //>>group: Core
  //>>description: Selects elements which have data stored under the specified key.
  //>>docs: http://api.jqueryui.com/data-selector/
  
  
  var data = $.extend( $.expr[ ":" ], {
  	data: $.expr.createPseudo ?
  		$.expr.createPseudo( function( dataName ) {
  			return function( elem ) {
  				return !!$.data( elem, dataName );
  			};
  		} ) :
  
  		// Support: jQuery <1.8
  		function( elem, i, match ) {
  			return !!$.data( elem, match[ 3 ] );
  		}
  } );
  
  /*!
   * jQuery UI Disable Selection 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: disableSelection
  //>>group: Core
  //>>description: Disable selection of text content within the set of matched elements.
  //>>docs: http://api.jqueryui.com/disableSelection/
  
  // This file is deprecated
  
  
  var disableSelection = $.fn.extend( {
  	disableSelection: ( function() {
  		var eventType = "onselectstart" in document.createElement( "div" ) ?
  			"selectstart" :
  			"mousedown";
  
  		return function() {
  			return this.on( eventType + ".ui-disableSelection", function( event ) {
  				event.preventDefault();
  			} );
  		};
  	} )(),
  
  	enableSelection: function() {
  		return this.off( ".ui-disableSelection" );
  	}
  } );
  
  
  /*!
   * jQuery UI Focusable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: :focusable Selector
  //>>group: Core
  //>>description: Selects elements which can be focused.
  //>>docs: http://api.jqueryui.com/focusable-selector/
  
  
  
  // Selectors
  $.ui.focusable = function( element, hasTabindex ) {
  	var map, mapName, img, focusableIfVisible, fieldset,
  		nodeName = element.nodeName.toLowerCase();
  
  	if ( "area" === nodeName ) {
  		map = element.parentNode;
  		mapName = map.name;
  		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
  			return false;
  		}
  		img = $( "img[usemap='#" + mapName + "']" );
  		return img.length > 0 && img.is( ":visible" );
  	}
  
  	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
  		focusableIfVisible = !element.disabled;
  
  		if ( focusableIfVisible ) {
  
  			// Form controls within a disabled fieldset are disabled.
  			// However, controls within the fieldset's legend do not get disabled.
  			// Since controls generally aren't placed inside legends, we skip
  			// this portion of the check.
  			fieldset = $( element ).closest( "fieldset" )[ 0 ];
  			if ( fieldset ) {
  				focusableIfVisible = !fieldset.disabled;
  			}
  		}
  	} else if ( "a" === nodeName ) {
  		focusableIfVisible = element.href || hasTabindex;
  	} else {
  		focusableIfVisible = hasTabindex;
  	}
  
  	return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
  };
  
  // Support: IE 8 only
  // IE 8 doesn't resolve inherit to visible/hidden for computed values
  function visible( element ) {
  	var visibility = element.css( "visibility" );
  	while ( visibility === "inherit" ) {
  		element = element.parent();
  		visibility = element.css( "visibility" );
  	}
  	return visibility !== "hidden";
  }
  
  $.extend( $.expr[ ":" ], {
  	focusable: function( element ) {
  		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
  	}
  } );
  
  var focusable = $.ui.focusable;
  
  
  
  
  // Support: IE8 Only
  // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
  // with a string, so we need to find the proper form.
  var form = $.fn.form = function() {
  	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
  };
  
  
  /*!
   * jQuery UI Form Reset Mixin 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Form Reset Mixin
  //>>group: Core
  //>>description: Refresh input widgets when their form is reset
  //>>docs: http://api.jqueryui.com/form-reset-mixin/
  
  
  
  var formResetMixin = $.ui.formResetMixin = {
  	_formResetHandler: function() {
  		var form = $( this );
  
  		// Wait for the form reset to actually happen before refreshing
  		setTimeout( function() {
  			var instances = form.data( "ui-form-reset-instances" );
  			$.each( instances, function() {
  				this.refresh();
  			} );
  		} );
  	},
  
  	_bindFormResetHandler: function() {
  		this.form = this.element.form();
  		if ( !this.form.length ) {
  			return;
  		}
  
  		var instances = this.form.data( "ui-form-reset-instances" ) || [];
  		if ( !instances.length ) {
  
  			// We don't use _on() here because we use a single event handler per form
  			this.form.on( "reset.ui-form-reset", this._formResetHandler );
  		}
  		instances.push( this );
  		this.form.data( "ui-form-reset-instances", instances );
  	},
  
  	_unbindFormResetHandler: function() {
  		if ( !this.form.length ) {
  			return;
  		}
  
  		var instances = this.form.data( "ui-form-reset-instances" );
  		instances.splice( $.inArray( this, instances ), 1 );
  		if ( instances.length ) {
  			this.form.data( "ui-form-reset-instances", instances );
  		} else {
  			this.form
  				.removeData( "ui-form-reset-instances" )
  				.off( "reset.ui-form-reset" );
  		}
  	}
  };
  
  
  /*!
   * jQuery UI Keycode 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Keycode
  //>>group: Core
  //>>description: Provide keycodes as keynames
  //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
  
  
  var keycode = $.ui.keyCode = {
  	BACKSPACE: 8,
  	COMMA: 188,
  	DELETE: 46,
  	DOWN: 40,
  	END: 35,
  	ENTER: 13,
  	ESCAPE: 27,
  	HOME: 36,
  	LEFT: 37,
  	PAGE_DOWN: 34,
  	PAGE_UP: 33,
  	PERIOD: 190,
  	RIGHT: 39,
  	SPACE: 32,
  	TAB: 9,
  	UP: 38
  };
  
  
  
  
  // Internal use only
  var escapeSelector = $.ui.escapeSelector = ( function() {
  	var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
  	return function( selector ) {
  		return selector.replace( selectorEscape, "\\$1" );
  	};
  } )();
  
  
  /*!
   * jQuery UI Labels 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: labels
  //>>group: Core
  //>>description: Find all the labels associated with a given input
  //>>docs: http://api.jqueryui.com/labels/
  
  
  
  var labels = $.fn.labels = function() {
  	var ancestor, selector, id, labels, ancestors;
  
  	// Check control.labels first
  	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
  		return this.pushStack( this[ 0 ].labels );
  	}
  
  	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
  	// Above browsers do not support control.labels. Everything below is to support them
  	// as well as document fragments. control.labels does not work on document fragments
  	labels = this.eq( 0 ).parents( "label" );
  
  	// Look for the label based on the id
  	id = this.attr( "id" );
  	if ( id ) {
  
  		// We don't search against the document in case the element
  		// is disconnected from the DOM
  		ancestor = this.eq( 0 ).parents().last();
  
  		// Get a full set of top level ancestors
  		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
  
  		// Create a selector for the label based on the id
  		selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
  
  		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
  
  	}
  
  	// Return whatever we have found for labels
  	return this.pushStack( labels );
  };
  
  
  /*!
   * jQuery UI Scroll Parent 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: scrollParent
  //>>group: Core
  //>>description: Get the closest ancestor element that is scrollable.
  //>>docs: http://api.jqueryui.com/scrollParent/
  
  
  
  var scrollParent = $.fn.scrollParent = function( includeHidden ) {
  	var position = this.css( "position" ),
  		excludeStaticParent = position === "absolute",
  		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
  		scrollParent = this.parents().filter( function() {
  			var parent = $( this );
  			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
  				return false;
  			}
  			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
  				parent.css( "overflow-x" ) );
  		} ).eq( 0 );
  
  	return position === "fixed" || !scrollParent.length ?
  		$( this[ 0 ].ownerDocument || document ) :
  		scrollParent;
  };
  
  
  /*!
   * jQuery UI Tabbable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: :tabbable Selector
  //>>group: Core
  //>>description: Selects elements which can be tabbed to.
  //>>docs: http://api.jqueryui.com/tabbable-selector/
  
  
  
  var tabbable = $.extend( $.expr[ ":" ], {
  	tabbable: function( element ) {
  		var tabIndex = $.attr( element, "tabindex" ),
  			hasTabindex = tabIndex != null;
  		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
  	}
  } );
  
  
  /*!
   * jQuery UI Unique ID 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: uniqueId
  //>>group: Core
  //>>description: Functions to generate and remove uniqueId's
  //>>docs: http://api.jqueryui.com/uniqueId/
  
  
  
  var uniqueId = $.fn.extend( {
  	uniqueId: ( function() {
  		var uuid = 0;
  
  		return function() {
  			return this.each( function() {
  				if ( !this.id ) {
  					this.id = "ui-id-" + ( ++uuid );
  				}
  			} );
  		};
  	} )(),
  
  	removeUniqueId: function() {
  		return this.each( function() {
  			if ( /^ui-id-\d+$/.test( this.id ) ) {
  				$( this ).removeAttr( "id" );
  			}
  		} );
  	}
  } );
  
  
  
  
  // This file is deprecated
  var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
  
  /*!
   * jQuery UI Mouse 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Mouse
  //>>group: Widgets
  //>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
  //>>docs: http://api.jqueryui.com/mouse/
  
  
  
  var mouseHandled = false;
  $( document ).on( "mouseup", function() {
  	mouseHandled = false;
  } );
  
  var widgetsMouse = $.widget( "ui.mouse", {
  	version: "1.12.1",
  	options: {
  		cancel: "input, textarea, button, select, option",
  		distance: 1,
  		delay: 0
  	},
  	_mouseInit: function() {
  		var that = this;
  
  		this.element
  			.on( "mousedown." + this.widgetName, function( event ) {
  				return that._mouseDown( event );
  			} )
  			.on( "click." + this.widgetName, function( event ) {
  				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
  					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
  					event.stopImmediatePropagation();
  					return false;
  				}
  			} );
  
  		this.started = false;
  	},
  
  	// TODO: make sure destroying one instance of mouse doesn't mess with
  	// other instances of mouse
  	_mouseDestroy: function() {
  		this.element.off( "." + this.widgetName );
  		if ( this._mouseMoveDelegate ) {
  			this.document
  				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
  				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
  		}
  	},
  
  	_mouseDown: function( event ) {
  
  		// don't let more than one widget handle mouseStart
  		if ( mouseHandled ) {
  			return;
  		}
  
  		this._mouseMoved = false;
  
  		// We may have missed mouseup (out of window)
  		( this._mouseStarted && this._mouseUp( event ) );
  
  		this._mouseDownEvent = event;
  
  		var that = this,
  			btnIsLeft = ( event.which === 1 ),
  
  			// event.target.nodeName works around a bug in IE 8 with
  			// disabled inputs (#7620)
  			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
  				$( event.target ).closest( this.options.cancel ).length : false );
  		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
  			return true;
  		}
  
  		this.mouseDelayMet = !this.options.delay;
  		if ( !this.mouseDelayMet ) {
  			this._mouseDelayTimer = setTimeout( function() {
  				that.mouseDelayMet = true;
  			}, this.options.delay );
  		}
  
  		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
  			this._mouseStarted = ( this._mouseStart( event ) !== false );
  			if ( !this._mouseStarted ) {
  				event.preventDefault();
  				return true;
  			}
  		}
  
  		// Click event may never have fired (Gecko & Opera)
  		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
  			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
  		}
  
  		// These delegates are required to keep context
  		this._mouseMoveDelegate = function( event ) {
  			return that._mouseMove( event );
  		};
  		this._mouseUpDelegate = function( event ) {
  			return that._mouseUp( event );
  		};
  
  		this.document
  			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
  			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
  
  		event.preventDefault();
  
  		mouseHandled = true;
  		return true;
  	},
  
  	_mouseMove: function( event ) {
  
  		// Only check for mouseups outside the document if you've moved inside the document
  		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
  		// fire a mousemove event if content is placed under the cursor. See #7778
  		// Support: IE <9
  		if ( this._mouseMoved ) {
  
  			// IE mouseup check - mouseup happened when mouse was out of window
  			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
  					!event.button ) {
  				return this._mouseUp( event );
  
  			// Iframe mouseup check - mouseup occurred in another document
  			} else if ( !event.which ) {
  
  				// Support: Safari <=8 - 9
  				// Safari sets which to 0 if you press any of the following keys
  				// during a drag (#14461)
  				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
  						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
  					this.ignoreMissingWhich = true;
  				} else if ( !this.ignoreMissingWhich ) {
  					return this._mouseUp( event );
  				}
  			}
  		}
  
  		if ( event.which || event.button ) {
  			this._mouseMoved = true;
  		}
  
  		if ( this._mouseStarted ) {
  			this._mouseDrag( event );
  			return event.preventDefault();
  		}
  
  		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
  			this._mouseStarted =
  				( this._mouseStart( this._mouseDownEvent, event ) !== false );
  			( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
  		}
  
  		return !this._mouseStarted;
  	},
  
  	_mouseUp: function( event ) {
  		this.document
  			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
  			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
  
  		if ( this._mouseStarted ) {
  			this._mouseStarted = false;
  
  			if ( event.target === this._mouseDownEvent.target ) {
  				$.data( event.target, this.widgetName + ".preventClickEvent", true );
  			}
  
  			this._mouseStop( event );
  		}
  
  		if ( this._mouseDelayTimer ) {
  			clearTimeout( this._mouseDelayTimer );
  			delete this._mouseDelayTimer;
  		}
  
  		this.ignoreMissingWhich = false;
  		mouseHandled = false;
  		event.preventDefault();
  	},
  
  	_mouseDistanceMet: function( event ) {
  		return ( Math.max(
  				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
  				Math.abs( this._mouseDownEvent.pageY - event.pageY )
  			) >= this.options.distance
  		);
  	},
  
  	_mouseDelayMet: function( /* event */ ) {
  		return this.mouseDelayMet;
  	},
  
  	// These are placeholder methods, to be overriden by extending plugin
  	_mouseStart: function( /* event */ ) {},
  	_mouseDrag: function( /* event */ ) {},
  	_mouseStop: function( /* event */ ) {},
  	_mouseCapture: function( /* event */ ) { return true; }
  } );
  
  
  
  
  // $.ui.plugin is deprecated. Use $.widget() extensions instead.
  var plugin = $.ui.plugin = {
  	add: function( module, option, set ) {
  		var i,
  			proto = $.ui[ module ].prototype;
  		for ( i in set ) {
  			proto.plugins[ i ] = proto.plugins[ i ] || [];
  			proto.plugins[ i ].push( [ option, set[ i ] ] );
  		}
  	},
  	call: function( instance, name, args, allowDisconnected ) {
  		var i,
  			set = instance.plugins[ name ];
  
  		if ( !set ) {
  			return;
  		}
  
  		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
  				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
  			return;
  		}
  
  		for ( i = 0; i < set.length; i++ ) {
  			if ( instance.options[ set[ i ][ 0 ] ] ) {
  				set[ i ][ 1 ].apply( instance.element, args );
  			}
  		}
  	}
  };
  
  
  
  var safeActiveElement = $.ui.safeActiveElement = function( document ) {
  	var activeElement;
  
  	// Support: IE 9 only
  	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
  	try {
  		activeElement = document.activeElement;
  	} catch ( error ) {
  		activeElement = document.body;
  	}
  
  	// Support: IE 9 - 11 only
  	// IE may return null instead of an element
  	// Interestingly, this only seems to occur when NOT in an iframe
  	if ( !activeElement ) {
  		activeElement = document.body;
  	}
  
  	// Support: IE 11 only
  	// IE11 returns a seemingly empty object in some cases when accessing
  	// document.activeElement from an <iframe>
  	if ( !activeElement.nodeName ) {
  		activeElement = document.body;
  	}
  
  	return activeElement;
  };
  
  
  
  var safeBlur = $.ui.safeBlur = function( element ) {
  
  	// Support: IE9 - 10 only
  	// If the <body> is blurred, IE will switch windows, see #9420
  	if ( element && element.nodeName.toLowerCase() !== "body" ) {
  		$( element ).trigger( "blur" );
  	}
  };
  
  
  /*!
   * jQuery UI Draggable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Draggable
  //>>group: Interactions
  //>>description: Enables dragging functionality for any element.
  //>>docs: http://api.jqueryui.com/draggable/
  //>>demos: http://jqueryui.com/draggable/
  //>>css.structure: ../../themes/base/draggable.css
  
  
  
  $.widget( "ui.draggable", $.ui.mouse, {
  	version: "1.12.1",
  	widgetEventPrefix: "drag",
  	options: {
  		addClasses: true,
  		appendTo: "parent",
  		axis: false,
  		connectToSortable: false,
  		containment: false,
  		cursor: "auto",
  		cursorAt: false,
  		grid: false,
  		handle: false,
  		helper: "original",
  		iframeFix: false,
  		opacity: false,
  		refreshPositions: false,
  		revert: false,
  		revertDuration: 500,
  		scope: "default",
  		scroll: true,
  		scrollSensitivity: 20,
  		scrollSpeed: 20,
  		snap: false,
  		snapMode: "both",
  		snapTolerance: 20,
  		stack: false,
  		zIndex: false,
  
  		// Callbacks
  		drag: null,
  		start: null,
  		stop: null
  	},
  	_create: function() {
  
  		if ( this.options.helper === "original" ) {
  			this._setPositionRelative();
  		}
  		if ( this.options.addClasses ) {
  			this._addClass( "ui-draggable" );
  		}
  		this._setHandleClassName();
  
  		this._mouseInit();
  	},
  
  	_setOption: function( key, value ) {
  		this._super( key, value );
  		if ( key === "handle" ) {
  			this._removeHandleClassName();
  			this._setHandleClassName();
  		}
  	},
  
  	_destroy: function() {
  		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
  			this.destroyOnClear = true;
  			return;
  		}
  		this._removeHandleClassName();
  		this._mouseDestroy();
  	},
  
  	_mouseCapture: function( event ) {
  		var o = this.options;
  
  		// Among others, prevent a drag on a resizable-handle
  		if ( this.helper || o.disabled ||
  				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
  			return false;
  		}
  
  		//Quit if we're not on a valid handle
  		this.handle = this._getHandle( event );
  		if ( !this.handle ) {
  			return false;
  		}
  
  		this._blurActiveElement( event );
  
  		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
  
  		return true;
  
  	},
  
  	_blockFrames: function( selector ) {
  		this.iframeBlocks = this.document.find( selector ).map( function() {
  			var iframe = $( this );
  
  			return $( "<div>" )
  				.css( "position", "absolute" )
  				.appendTo( iframe.parent() )
  				.outerWidth( iframe.outerWidth() )
  				.outerHeight( iframe.outerHeight() )
  				.offset( iframe.offset() )[ 0 ];
  		} );
  	},
  
  	_unblockFrames: function() {
  		if ( this.iframeBlocks ) {
  			this.iframeBlocks.remove();
  			delete this.iframeBlocks;
  		}
  	},
  
  	_blurActiveElement: function( event ) {
  		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
  			target = $( event.target );
  
  		// Don't blur if the event occurred on an element that is within
  		// the currently focused element
  		// See #10527, #12472
  		if ( target.closest( activeElement ).length ) {
  			return;
  		}
  
  		// Blur any element that currently has focus, see #4261
  		$.ui.safeBlur( activeElement );
  	},
  
  	_mouseStart: function( event ) {
  
  		var o = this.options;
  
  		//Create and append the visible helper
  		this.helper = this._createHelper( event );
  
  		this._addClass( this.helper, "ui-draggable-dragging" );
  
  		//Cache the helper size
  		this._cacheHelperProportions();
  
  		//If ddmanager is used for droppables, set the global draggable
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.current = this;
  		}
  
  		/*
  		 * - Position generation -
  		 * This block generates everything position related - it's the core of draggables.
  		 */
  
  		//Cache the margins of the original element
  		this._cacheMargins();
  
  		//Store the helper's css position
  		this.cssPosition = this.helper.css( "position" );
  		this.scrollParent = this.helper.scrollParent( true );
  		this.offsetParent = this.helper.offsetParent();
  		this.hasFixedAncestor = this.helper.parents().filter( function() {
  				return $( this ).css( "position" ) === "fixed";
  			} ).length > 0;
  
  		//The element's absolute position on the page minus margins
  		this.positionAbs = this.element.offset();
  		this._refreshOffsets( event );
  
  		//Generate the original position
  		this.originalPosition = this.position = this._generatePosition( event, false );
  		this.originalPageX = event.pageX;
  		this.originalPageY = event.pageY;
  
  		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
  		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
  
  		//Set a containment if given in the options
  		this._setContainment();
  
  		//Trigger event + callbacks
  		if ( this._trigger( "start", event ) === false ) {
  			this._clear();
  			return false;
  		}
  
  		//Recache the helper size
  		this._cacheHelperProportions();
  
  		//Prepare the droppable offsets
  		if ( $.ui.ddmanager && !o.dropBehaviour ) {
  			$.ui.ddmanager.prepareOffsets( this, event );
  		}
  
  		// Execute the drag once - this causes the helper not to be visible before getting its
  		// correct position
  		this._mouseDrag( event, true );
  
  		// If the ddmanager is used for droppables, inform the manager that dragging has started
  		// (see #5003)
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.dragStart( this, event );
  		}
  
  		return true;
  	},
  
  	_refreshOffsets: function( event ) {
  		this.offset = {
  			top: this.positionAbs.top - this.margins.top,
  			left: this.positionAbs.left - this.margins.left,
  			scroll: false,
  			parent: this._getParentOffset(),
  			relative: this._getRelativeOffset()
  		};
  
  		this.offset.click = {
  			left: event.pageX - this.offset.left,
  			top: event.pageY - this.offset.top
  		};
  	},
  
  	_mouseDrag: function( event, noPropagation ) {
  
  		// reset any necessary cached properties (see #5009)
  		if ( this.hasFixedAncestor ) {
  			this.offset.parent = this._getParentOffset();
  		}
  
  		//Compute the helpers position
  		this.position = this._generatePosition( event, true );
  		this.positionAbs = this._convertPositionTo( "absolute" );
  
  		//Call plugins and callbacks and use the resulting position if something is returned
  		if ( !noPropagation ) {
  			var ui = this._uiHash();
  			if ( this._trigger( "drag", event, ui ) === false ) {
  				this._mouseUp( new $.Event( "mouseup", event ) );
  				return false;
  			}
  			this.position = ui.position;
  		}
  
  		this.helper[ 0 ].style.left = this.position.left + "px";
  		this.helper[ 0 ].style.top = this.position.top + "px";
  
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.drag( this, event );
  		}
  
  		return false;
  	},
  
  	_mouseStop: function( event ) {
  
  		//If we are using droppables, inform the manager about the drop
  		var that = this,
  			dropped = false;
  		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
  			dropped = $.ui.ddmanager.drop( this, event );
  		}
  
  		//if a drop comes from outside (a sortable)
  		if ( this.dropped ) {
  			dropped = this.dropped;
  			this.dropped = false;
  		}
  
  		if ( ( this.options.revert === "invalid" && !dropped ) ||
  				( this.options.revert === "valid" && dropped ) ||
  				this.options.revert === true || ( $.isFunction( this.options.revert ) &&
  				this.options.revert.call( this.element, dropped ) )
  		) {
  			$( this.helper ).animate(
  				this.originalPosition,
  				parseInt( this.options.revertDuration, 10 ),
  				function() {
  					if ( that._trigger( "stop", event ) !== false ) {
  						that._clear();
  					}
  				}
  			);
  		} else {
  			if ( this._trigger( "stop", event ) !== false ) {
  				this._clear();
  			}
  		}
  
  		return false;
  	},
  
  	_mouseUp: function( event ) {
  		this._unblockFrames();
  
  		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
  		// (see #5003)
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.dragStop( this, event );
  		}
  
  		// Only need to focus if the event occurred on the draggable itself, see #10527
  		if ( this.handleElement.is( event.target ) ) {
  
  			// The interaction is over; whether or not the click resulted in a drag,
  			// focus the element
  			this.element.trigger( "focus" );
  		}
  
  		return $.ui.mouse.prototype._mouseUp.call( this, event );
  	},
  
  	cancel: function() {
  
  		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
  			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
  		} else {
  			this._clear();
  		}
  
  		return this;
  
  	},
  
  	_getHandle: function( event ) {
  		return this.options.handle ?
  			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
  			true;
  	},
  
  	_setHandleClassName: function() {
  		this.handleElement = this.options.handle ?
  			this.element.find( this.options.handle ) : this.element;
  		this._addClass( this.handleElement, "ui-draggable-handle" );
  	},
  
  	_removeHandleClassName: function() {
  		this._removeClass( this.handleElement, "ui-draggable-handle" );
  	},
  
  	_createHelper: function( event ) {
  
  		var o = this.options,
  			helperIsFunction = $.isFunction( o.helper ),
  			helper = helperIsFunction ?
  				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
  				( o.helper === "clone" ?
  					this.element.clone().removeAttr( "id" ) :
  					this.element );
  
  		if ( !helper.parents( "body" ).length ) {
  			helper.appendTo( ( o.appendTo === "parent" ?
  				this.element[ 0 ].parentNode :
  				o.appendTo ) );
  		}
  
  		// Http://bugs.jqueryui.com/ticket/9446
  		// a helper function can return the original element
  		// which wouldn't have been set to relative in _create
  		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
  			this._setPositionRelative();
  		}
  
  		if ( helper[ 0 ] !== this.element[ 0 ] &&
  				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
  			helper.css( "position", "absolute" );
  		}
  
  		return helper;
  
  	},
  
  	_setPositionRelative: function() {
  		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
  			this.element[ 0 ].style.position = "relative";
  		}
  	},
  
  	_adjustOffsetFromHelper: function( obj ) {
  		if ( typeof obj === "string" ) {
  			obj = obj.split( " " );
  		}
  		if ( $.isArray( obj ) ) {
  			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
  		}
  		if ( "left" in obj ) {
  			this.offset.click.left = obj.left + this.margins.left;
  		}
  		if ( "right" in obj ) {
  			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
  		}
  		if ( "top" in obj ) {
  			this.offset.click.top = obj.top + this.margins.top;
  		}
  		if ( "bottom" in obj ) {
  			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
  		}
  	},
  
  	_isRootNode: function( element ) {
  		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
  	},
  
  	_getParentOffset: function() {
  
  		//Get the offsetParent and cache its position
  		var po = this.offsetParent.offset(),
  			document = this.document[ 0 ];
  
  		// This is a special case where we need to modify a offset calculated on start, since the
  		// following happened:
  		// 1. The position of the helper is absolute, so it's position is calculated based on the
  		// next positioned parent
  		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
  		// the document, which means that the scroll is included in the initial calculation of the
  		// offset of the parent, and never recalculated upon drag
  		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
  				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
  			po.left += this.scrollParent.scrollLeft();
  			po.top += this.scrollParent.scrollTop();
  		}
  
  		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
  			po = { top: 0, left: 0 };
  		}
  
  		return {
  			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
  			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
  		};
  
  	},
  
  	_getRelativeOffset: function() {
  		if ( this.cssPosition !== "relative" ) {
  			return { top: 0, left: 0 };
  		}
  
  		var p = this.element.position(),
  			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
  
  		return {
  			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
  				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
  			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
  				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 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 isUserScrollable, c, ce,
  			o = this.options,
  			document = this.document[ 0 ];
  
  		this.relativeContainer = null;
  
  		if ( !o.containment ) {
  			this.containment = null;
  			return;
  		}
  
  		if ( o.containment === "window" ) {
  			this.containment = [
  				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
  				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
  				$( window ).scrollLeft() + $( window ).width() -
  					this.helperProportions.width - this.margins.left,
  				$( window ).scrollTop() +
  					( $( window ).height() || document.body.parentNode.scrollHeight ) -
  					this.helperProportions.height - this.margins.top
  			];
  			return;
  		}
  
  		if ( o.containment === "document" ) {
  			this.containment = [
  				0,
  				0,
  				$( document ).width() - this.helperProportions.width - this.margins.left,
  				( $( document ).height() || document.body.parentNode.scrollHeight ) -
  					this.helperProportions.height - this.margins.top
  			];
  			return;
  		}
  
  		if ( o.containment.constructor === Array ) {
  			this.containment = o.containment;
  			return;
  		}
  
  		if ( o.containment === "parent" ) {
  			o.containment = this.helper[ 0 ].parentNode;
  		}
  
  		c = $( o.containment );
  		ce = c[ 0 ];
  
  		if ( !ce ) {
  			return;
  		}
  
  		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
  
  		this.containment = [
  			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
  				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
  			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
  				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
  			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
  				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
  				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
  				this.helperProportions.width -
  				this.margins.left -
  				this.margins.right,
  			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
  				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
  				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
  				this.helperProportions.height -
  				this.margins.top -
  				this.margins.bottom
  		];
  		this.relativeContainer = c;
  	},
  
  	_convertPositionTo: function( d, pos ) {
  
  		if ( !pos ) {
  			pos = this.position;
  		}
  
  		var mod = d === "absolute" ? 1 : -1,
  			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
  
  		return {
  			top: (
  
  				// The absolute mouse position
  				pos.top	+
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.top * mod +
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.top * mod -
  				( ( this.cssPosition === "fixed" ?
  					-this.offset.scroll.top :
  					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
  			),
  			left: (
  
  				// The absolute mouse position
  				pos.left +
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.left * mod +
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.left * mod	-
  				( ( this.cssPosition === "fixed" ?
  					-this.offset.scroll.left :
  					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
  			)
  		};
  
  	},
  
  	_generatePosition: function( event, constrainPosition ) {
  
  		var containment, co, top, left,
  			o = this.options,
  			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
  			pageX = event.pageX,
  			pageY = event.pageY;
  
  		// Cache the scroll
  		if ( !scrollIsRootNode || !this.offset.scroll ) {
  			this.offset.scroll = {
  				top: this.scrollParent.scrollTop(),
  				left: this.scrollParent.scrollLeft()
  			};
  		}
  
  		/*
  		 * - Position constraining -
  		 * Constrain the position to a mix of grid, containment.
  		 */
  
  		// If we are not dragging yet, we won't check for options
  		if ( constrainPosition ) {
  			if ( this.containment ) {
  				if ( this.relativeContainer ) {
  					co = this.relativeContainer.offset();
  					containment = [
  						this.containment[ 0 ] + co.left,
  						this.containment[ 1 ] + co.top,
  						this.containment[ 2 ] + co.left,
  						this.containment[ 3 ] + co.top
  					];
  				} else {
  					containment = this.containment;
  				}
  
  				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
  					pageX = containment[ 0 ] + this.offset.click.left;
  				}
  				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
  					pageY = containment[ 1 ] + this.offset.click.top;
  				}
  				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
  					pageX = containment[ 2 ] + this.offset.click.left;
  				}
  				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
  					pageY = containment[ 3 ] + this.offset.click.top;
  				}
  			}
  
  			if ( o.grid ) {
  
  				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
  				// argument errors in IE (see ticket #6950)
  				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
  					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
  				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
  					top - this.offset.click.top > containment[ 3 ] ) ?
  						top :
  						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
  							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
  
  				left = o.grid[ 0 ] ? this.originalPageX +
  					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
  					this.originalPageX;
  				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
  					left - this.offset.click.left > containment[ 2 ] ) ?
  						left :
  						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
  							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
  			}
  
  			if ( o.axis === "y" ) {
  				pageX = this.originalPageX;
  			}
  
  			if ( o.axis === "x" ) {
  				pageY = this.originalPageY;
  			}
  		}
  
  		return {
  			top: (
  
  				// The absolute mouse position
  				pageY -
  
  				// Click offset (relative to the element)
  				this.offset.click.top -
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.top -
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.top +
  				( this.cssPosition === "fixed" ?
  					-this.offset.scroll.top :
  					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
  			),
  			left: (
  
  				// The absolute mouse position
  				pageX -
  
  				// Click offset (relative to the element)
  				this.offset.click.left -
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.left -
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.left +
  				( this.cssPosition === "fixed" ?
  					-this.offset.scroll.left :
  					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
  			)
  		};
  
  	},
  
  	_clear: function() {
  		this._removeClass( this.helper, "ui-draggable-dragging" );
  		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
  			this.helper.remove();
  		}
  		this.helper = null;
  		this.cancelHelperRemoval = false;
  		if ( this.destroyOnClear ) {
  			this.destroy();
  		}
  	},
  
  	// From now on bulk stuff - mainly helpers
  
  	_trigger: function( type, event, ui ) {
  		ui = ui || this._uiHash();
  		$.ui.plugin.call( this, type, [ event, ui, this ], true );
  
  		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
  		if ( /^(drag|start|stop)/.test( type ) ) {
  			this.positionAbs = this._convertPositionTo( "absolute" );
  			ui.offset = this.positionAbs;
  		}
  		return $.Widget.prototype._trigger.call( this, type, event, ui );
  	},
  
  	plugins: {},
  
  	_uiHash: function() {
  		return {
  			helper: this.helper,
  			position: this.position,
  			originalPosition: this.originalPosition,
  			offset: this.positionAbs
  		};
  	}
  
  } );
  
  $.ui.plugin.add( "draggable", "connectToSortable", {
  	start: function( event, ui, draggable ) {
  		var uiSortable = $.extend( {}, ui, {
  			item: draggable.element
  		} );
  
  		draggable.sortables = [];
  		$( draggable.options.connectToSortable ).each( function() {
  			var sortable = $( this ).sortable( "instance" );
  
  			if ( sortable && !sortable.options.disabled ) {
  				draggable.sortables.push( sortable );
  
  				// RefreshPositions is called at drag start to refresh the containerCache
  				// which is used in drag. This ensures it's initialized and synchronized
  				// with any changes that might have happened on the page since initialization.
  				sortable.refreshPositions();
  				sortable._trigger( "activate", event, uiSortable );
  			}
  		} );
  	},
  	stop: function( event, ui, draggable ) {
  		var uiSortable = $.extend( {}, ui, {
  			item: draggable.element
  		} );
  
  		draggable.cancelHelperRemoval = false;
  
  		$.each( draggable.sortables, function() {
  			var sortable = this;
  
  			if ( sortable.isOver ) {
  				sortable.isOver = 0;
  
  				// Allow this sortable to handle removing the helper
  				draggable.cancelHelperRemoval = true;
  				sortable.cancelHelperRemoval = false;
  
  				// Use _storedCSS To restore properties in the sortable,
  				// as this also handles revert (#9675) since the draggable
  				// may have modified them in unexpected ways (#8809)
  				sortable._storedCSS = {
  					position: sortable.placeholder.css( "position" ),
  					top: sortable.placeholder.css( "top" ),
  					left: sortable.placeholder.css( "left" )
  				};
  
  				sortable._mouseStop( event );
  
  				// Once drag has ended, the sortable should return to using
  				// its original helper, not the shared helper from draggable
  				sortable.options.helper = sortable.options._helper;
  			} else {
  
  				// Prevent this Sortable from removing the helper.
  				// However, don't set the draggable to remove the helper
  				// either as another connected Sortable may yet handle the removal.
  				sortable.cancelHelperRemoval = true;
  
  				sortable._trigger( "deactivate", event, uiSortable );
  			}
  		} );
  	},
  	drag: function( event, ui, draggable ) {
  		$.each( draggable.sortables, function() {
  			var innermostIntersecting = false,
  				sortable = this;
  
  			// Copy over variables that sortable's _intersectsWith uses
  			sortable.positionAbs = draggable.positionAbs;
  			sortable.helperProportions = draggable.helperProportions;
  			sortable.offset.click = draggable.offset.click;
  
  			if ( sortable._intersectsWith( sortable.containerCache ) ) {
  				innermostIntersecting = true;
  
  				$.each( draggable.sortables, function() {
  
  					// Copy over variables that sortable's _intersectsWith uses
  					this.positionAbs = draggable.positionAbs;
  					this.helperProportions = draggable.helperProportions;
  					this.offset.click = draggable.offset.click;
  
  					if ( this !== sortable &&
  							this._intersectsWith( this.containerCache ) &&
  							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
  						innermostIntersecting = false;
  					}
  
  					return innermostIntersecting;
  				} );
  			}
  
  			if ( innermostIntersecting ) {
  
  				// If it intersects, we use a little isOver variable and set it once,
  				// so that the move-in stuff gets fired only once.
  				if ( !sortable.isOver ) {
  					sortable.isOver = 1;
  
  					// Store draggable's parent in case we need to reappend to it later.
  					draggable._parent = ui.helper.parent();
  
  					sortable.currentItem = ui.helper
  						.appendTo( sortable.element )
  						.data( "ui-sortable-item", true );
  
  					// Store helper option to later restore it
  					sortable.options._helper = sortable.options.helper;
  
  					sortable.options.helper = function() {
  						return ui.helper[ 0 ];
  					};
  
  					// Fire the start events of the sortable with our passed browser event,
  					// and our own helper (so it doesn't create a new one)
  					event.target = sortable.currentItem[ 0 ];
  					sortable._mouseCapture( event, true );
  					sortable._mouseStart( event, true, true );
  
  					// Because the browser event is way off the new appended portlet,
  					// modify necessary variables to reflect the changes
  					sortable.offset.click.top = draggable.offset.click.top;
  					sortable.offset.click.left = draggable.offset.click.left;
  					sortable.offset.parent.left -= draggable.offset.parent.left -
  						sortable.offset.parent.left;
  					sortable.offset.parent.top -= draggable.offset.parent.top -
  						sortable.offset.parent.top;
  
  					draggable._trigger( "toSortable", event );
  
  					// Inform draggable that the helper is in a valid drop zone,
  					// used solely in the revert option to handle "valid/invalid".
  					draggable.dropped = sortable.element;
  
  					// Need to refreshPositions of all sortables in the case that
  					// adding to one sortable changes the location of the other sortables (#9675)
  					$.each( draggable.sortables, function() {
  						this.refreshPositions();
  					} );
  
  					// Hack so receive/update callbacks work (mostly)
  					draggable.currentItem = draggable.element;
  					sortable.fromOutside = draggable;
  				}
  
  				if ( sortable.currentItem ) {
  					sortable._mouseDrag( event );
  
  					// Copy the sortable's position because the draggable's can potentially reflect
  					// a relative position, while sortable is always absolute, which the dragged
  					// element has now become. (#8809)
  					ui.position = sortable.position;
  				}
  			} else {
  
  				// If it doesn't intersect with the sortable, and it intersected before,
  				// we fake the drag stop of the sortable, but make sure it doesn't remove
  				// the helper by using cancelHelperRemoval.
  				if ( sortable.isOver ) {
  
  					sortable.isOver = 0;
  					sortable.cancelHelperRemoval = true;
  
  					// Calling sortable's mouseStop would trigger a revert,
  					// so revert must be temporarily false until after mouseStop is called.
  					sortable.options._revert = sortable.options.revert;
  					sortable.options.revert = false;
  
  					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
  					sortable._mouseStop( event, true );
  
  					// Restore sortable behaviors that were modfied
  					// when the draggable entered the sortable area (#9481)
  					sortable.options.revert = sortable.options._revert;
  					sortable.options.helper = sortable.options._helper;
  
  					if ( sortable.placeholder ) {
  						sortable.placeholder.remove();
  					}
  
  					// Restore and recalculate the draggable's offset considering the sortable
  					// may have modified them in unexpected ways. (#8809, #10669)
  					ui.helper.appendTo( draggable._parent );
  					draggable._refreshOffsets( event );
  					ui.position = draggable._generatePosition( event, true );
  
  					draggable._trigger( "fromSortable", event );
  
  					// Inform draggable that the helper is no longer in a valid drop zone
  					draggable.dropped = false;
  
  					// Need to refreshPositions of all sortables just in case removing
  					// from one sortable changes the location of other sortables (#9675)
  					$.each( draggable.sortables, function() {
  						this.refreshPositions();
  					} );
  				}
  			}
  		} );
  	}
  } );
  
  $.ui.plugin.add( "draggable", "cursor", {
  	start: function( event, ui, instance ) {
  		var t = $( "body" ),
  			o = instance.options;
  
  		if ( t.css( "cursor" ) ) {
  			o._cursor = t.css( "cursor" );
  		}
  		t.css( "cursor", o.cursor );
  	},
  	stop: function( event, ui, instance ) {
  		var o = instance.options;
  		if ( o._cursor ) {
  			$( "body" ).css( "cursor", o._cursor );
  		}
  	}
  } );
  
  $.ui.plugin.add( "draggable", "opacity", {
  	start: function( event, ui, instance ) {
  		var t = $( ui.helper ),
  			o = instance.options;
  		if ( t.css( "opacity" ) ) {
  			o._opacity = t.css( "opacity" );
  		}
  		t.css( "opacity", o.opacity );
  	},
  	stop: function( event, ui, instance ) {
  		var o = instance.options;
  		if ( o._opacity ) {
  			$( ui.helper ).css( "opacity", o._opacity );
  		}
  	}
  } );
  
  $.ui.plugin.add( "draggable", "scroll", {
  	start: function( event, ui, i ) {
  		if ( !i.scrollParentNotHidden ) {
  			i.scrollParentNotHidden = i.helper.scrollParent( false );
  		}
  
  		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
  				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
  			i.overflowOffset = i.scrollParentNotHidden.offset();
  		}
  	},
  	drag: function( event, ui, i  ) {
  
  		var o = i.options,
  			scrolled = false,
  			scrollParent = i.scrollParentNotHidden[ 0 ],
  			document = i.document[ 0 ];
  
  		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
  			if ( !o.axis || o.axis !== "x" ) {
  				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
  						o.scrollSensitivity ) {
  					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
  				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
  					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
  				}
  			}
  
  			if ( !o.axis || o.axis !== "y" ) {
  				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
  						o.scrollSensitivity ) {
  					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
  				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
  					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
  				}
  			}
  
  		} else {
  
  			if ( !o.axis || o.axis !== "x" ) {
  				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
  					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
  				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
  						o.scrollSensitivity ) {
  					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
  				}
  			}
  
  			if ( !o.axis || o.axis !== "y" ) {
  				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
  					scrolled = $( document ).scrollLeft(
  						$( document ).scrollLeft() - o.scrollSpeed
  					);
  				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
  						o.scrollSensitivity ) {
  					scrolled = $( document ).scrollLeft(
  						$( document ).scrollLeft() + o.scrollSpeed
  					);
  				}
  			}
  
  		}
  
  		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
  			$.ui.ddmanager.prepareOffsets( i, event );
  		}
  
  	}
  } );
  
  $.ui.plugin.add( "draggable", "snap", {
  	start: function( event, ui, i ) {
  
  		var o = i.options;
  
  		i.snapElements = [];
  
  		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
  			.each( function() {
  				var $t = $( this ),
  					$o = $t.offset();
  				if ( this !== i.element[ 0 ] ) {
  					i.snapElements.push( {
  						item: this,
  						width: $t.outerWidth(), height: $t.outerHeight(),
  						top: $o.top, left: $o.left
  					} );
  				}
  			} );
  
  	},
  	drag: function( event, ui, inst ) {
  
  		var ts, bs, ls, rs, l, r, t, b, i, first,
  			o = inst.options,
  			d = o.snapTolerance,
  			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
  			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
  
  		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
  
  			l = inst.snapElements[ i ].left - inst.margins.left;
  			r = l + inst.snapElements[ i ].width;
  			t = inst.snapElements[ i ].top - inst.margins.top;
  			b = t + inst.snapElements[ i ].height;
  
  			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
  					!$.contains( inst.snapElements[ i ].item.ownerDocument,
  					inst.snapElements[ i ].item ) ) {
  				if ( inst.snapElements[ i ].snapping ) {
  					( inst.options.snap.release &&
  						inst.options.snap.release.call(
  							inst.element,
  							event,
  							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
  						) );
  				}
  				inst.snapElements[ i ].snapping = false;
  				continue;
  			}
  
  			if ( o.snapMode !== "inner" ) {
  				ts = Math.abs( t - y2 ) <= d;
  				bs = Math.abs( b - y1 ) <= d;
  				ls = Math.abs( l - x2 ) <= d;
  				rs = Math.abs( r - x1 ) <= d;
  				if ( ts ) {
  					ui.position.top = inst._convertPositionTo( "relative", {
  						top: t - inst.helperProportions.height,
  						left: 0
  					} ).top;
  				}
  				if ( bs ) {
  					ui.position.top = inst._convertPositionTo( "relative", {
  						top: b,
  						left: 0
  					} ).top;
  				}
  				if ( ls ) {
  					ui.position.left = inst._convertPositionTo( "relative", {
  						top: 0,
  						left: l - inst.helperProportions.width
  					} ).left;
  				}
  				if ( rs ) {
  					ui.position.left = inst._convertPositionTo( "relative", {
  						top: 0,
  						left: r
  					} ).left;
  				}
  			}
  
  			first = ( ts || bs || ls || rs );
  
  			if ( o.snapMode !== "outer" ) {
  				ts = Math.abs( t - y1 ) <= d;
  				bs = Math.abs( b - y2 ) <= d;
  				ls = Math.abs( l - x1 ) <= d;
  				rs = Math.abs( r - x2 ) <= d;
  				if ( ts ) {
  					ui.position.top = inst._convertPositionTo( "relative", {
  						top: t,
  						left: 0
  					} ).top;
  				}
  				if ( bs ) {
  					ui.position.top = inst._convertPositionTo( "relative", {
  						top: b - inst.helperProportions.height,
  						left: 0
  					} ).top;
  				}
  				if ( ls ) {
  					ui.position.left = inst._convertPositionTo( "relative", {
  						top: 0,
  						left: l
  					} ).left;
  				}
  				if ( rs ) {
  					ui.position.left = inst._convertPositionTo( "relative", {
  						top: 0,
  						left: r - inst.helperProportions.width
  					} ).left;
  				}
  			}
  
  			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
  				( inst.options.snap.snap &&
  					inst.options.snap.snap.call(
  						inst.element,
  						event,
  						$.extend( inst._uiHash(), {
  							snapItem: inst.snapElements[ i ].item
  						} ) ) );
  			}
  			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
  
  		}
  
  	}
  } );
  
  $.ui.plugin.add( "draggable", "stack", {
  	start: function( event, ui, instance ) {
  		var min,
  			o = instance.options,
  			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
  				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
  					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
  			} );
  
  		if ( !group.length ) { return; }
  
  		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
  		$( group ).each( function( i ) {
  			$( this ).css( "zIndex", min + i );
  		} );
  		this.css( "zIndex", ( min + group.length ) );
  	}
  } );
  
  $.ui.plugin.add( "draggable", "zIndex", {
  	start: function( event, ui, instance ) {
  		var t = $( ui.helper ),
  			o = instance.options;
  
  		if ( t.css( "zIndex" ) ) {
  			o._zIndex = t.css( "zIndex" );
  		}
  		t.css( "zIndex", o.zIndex );
  	},
  	stop: function( event, ui, instance ) {
  		var o = instance.options;
  
  		if ( o._zIndex ) {
  			$( ui.helper ).css( "zIndex", o._zIndex );
  		}
  	}
  } );
  
  var widgetsDraggable = $.ui.draggable;
  
  
  /*!
   * jQuery UI Droppable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Droppable
  //>>group: Interactions
  //>>description: Enables drop targets for draggable elements.
  //>>docs: http://api.jqueryui.com/droppable/
  //>>demos: http://jqueryui.com/droppable/
  
  
  
  $.widget( "ui.droppable", {
  	version: "1.12.1",
  	widgetEventPrefix: "drop",
  	options: {
  		accept: "*",
  		addClasses: true,
  		greedy: false,
  		scope: "default",
  		tolerance: "intersect",
  
  		// Callbacks
  		activate: null,
  		deactivate: null,
  		drop: null,
  		out: null,
  		over: null
  	},
  	_create: function() {
  
  		var proportions,
  			o = this.options,
  			accept = o.accept;
  
  		this.isover = false;
  		this.isout = true;
  
  		this.accept = $.isFunction( accept ) ? accept : function( d ) {
  			return d.is( accept );
  		};
  
  		this.proportions = function( /* valueToWrite */ ) {
  			if ( arguments.length ) {
  
  				// Store the droppable's proportions
  				proportions = arguments[ 0 ];
  			} else {
  
  				// Retrieve or derive the droppable's proportions
  				return proportions ?
  					proportions :
  					proportions = {
  						width: this.element[ 0 ].offsetWidth,
  						height: this.element[ 0 ].offsetHeight
  					};
  			}
  		};
  
  		this._addToManager( o.scope );
  
  		o.addClasses && this._addClass( "ui-droppable" );
  
  	},
  
  	_addToManager: function( scope ) {
  
  		// Add the reference and positions to the manager
  		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
  		$.ui.ddmanager.droppables[ scope ].push( this );
  	},
  
  	_splice: function( drop ) {
  		var i = 0;
  		for ( ; i < drop.length; i++ ) {
  			if ( drop[ i ] === this ) {
  				drop.splice( i, 1 );
  			}
  		}
  	},
  
  	_destroy: function() {
  		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
  
  		this._splice( drop );
  	},
  
  	_setOption: function( key, value ) {
  
  		if ( key === "accept" ) {
  			this.accept = $.isFunction( value ) ? value : function( d ) {
  				return d.is( value );
  			};
  		} else if ( key === "scope" ) {
  			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
  
  			this._splice( drop );
  			this._addToManager( value );
  		}
  
  		this._super( key, value );
  	},
  
  	_activate: function( event ) {
  		var draggable = $.ui.ddmanager.current;
  
  		this._addActiveClass();
  		if ( draggable ) {
  			this._trigger( "activate", event, this.ui( draggable ) );
  		}
  	},
  
  	_deactivate: function( event ) {
  		var draggable = $.ui.ddmanager.current;
  
  		this._removeActiveClass();
  		if ( draggable ) {
  			this._trigger( "deactivate", event, this.ui( draggable ) );
  		}
  	},
  
  	_over: function( event ) {
  
  		var draggable = $.ui.ddmanager.current;
  
  		// Bail if draggable and droppable are same element
  		if ( !draggable || ( draggable.currentItem ||
  				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  			return;
  		}
  
  		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
  				draggable.element ) ) ) {
  			this._addHoverClass();
  			this._trigger( "over", event, this.ui( draggable ) );
  		}
  
  	},
  
  	_out: function( event ) {
  
  		var draggable = $.ui.ddmanager.current;
  
  		// Bail if draggable and droppable are same element
  		if ( !draggable || ( draggable.currentItem ||
  				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  			return;
  		}
  
  		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
  				draggable.element ) ) ) {
  			this._removeHoverClass();
  			this._trigger( "out", event, this.ui( draggable ) );
  		}
  
  	},
  
  	_drop: function( event, custom ) {
  
  		var draggable = custom || $.ui.ddmanager.current,
  			childrenIntersection = false;
  
  		// Bail if draggable and droppable are same element
  		if ( !draggable || ( draggable.currentItem ||
  				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  			return false;
  		}
  
  		this.element
  			.find( ":data(ui-droppable)" )
  			.not( ".ui-draggable-dragging" )
  			.each( function() {
  				var inst = $( this ).droppable( "instance" );
  				if (
  					inst.options.greedy &&
  					!inst.options.disabled &&
  					inst.options.scope === draggable.options.scope &&
  					inst.accept.call(
  						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
  					) &&
  					intersect(
  						draggable,
  						$.extend( inst, { offset: inst.element.offset() } ),
  						inst.options.tolerance, event
  					)
  				) {
  					childrenIntersection = true;
  					return false; }
  			} );
  		if ( childrenIntersection ) {
  			return false;
  		}
  
  		if ( this.accept.call( this.element[ 0 ],
  				( draggable.currentItem || draggable.element ) ) ) {
  			this._removeActiveClass();
  			this._removeHoverClass();
  
  			this._trigger( "drop", event, this.ui( draggable ) );
  			return this.element;
  		}
  
  		return false;
  
  	},
  
  	ui: function( c ) {
  		return {
  			draggable: ( c.currentItem || c.element ),
  			helper: c.helper,
  			position: c.position,
  			offset: c.positionAbs
  		};
  	},
  
  	// Extension points just to make backcompat sane and avoid duplicating logic
  	// TODO: Remove in 1.13 along with call to it below
  	_addHoverClass: function() {
  		this._addClass( "ui-droppable-hover" );
  	},
  
  	_removeHoverClass: function() {
  		this._removeClass( "ui-droppable-hover" );
  	},
  
  	_addActiveClass: function() {
  		this._addClass( "ui-droppable-active" );
  	},
  
  	_removeActiveClass: function() {
  		this._removeClass( "ui-droppable-active" );
  	}
  } );
  
  var intersect = $.ui.intersect = ( function() {
  	function isOverAxis( x, reference, size ) {
  		return ( x >= reference ) && ( x < ( reference + size ) );
  	}
  
  	return function( draggable, droppable, toleranceMode, event ) {
  
  		if ( !droppable.offset ) {
  			return false;
  		}
  
  		var x1 = ( draggable.positionAbs ||
  				draggable.position.absolute ).left + draggable.margins.left,
  			y1 = ( draggable.positionAbs ||
  				draggable.position.absolute ).top + draggable.margins.top,
  			x2 = x1 + draggable.helperProportions.width,
  			y2 = y1 + draggable.helperProportions.height,
  			l = droppable.offset.left,
  			t = droppable.offset.top,
  			r = l + droppable.proportions().width,
  			b = t + droppable.proportions().height;
  
  		switch ( toleranceMode ) {
  		case "fit":
  			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
  		case "intersect":
  			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
  				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
  				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
  				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
  		case "pointer":
  			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
  				isOverAxis( event.pageX, l, droppable.proportions().width );
  		case "touch":
  			return (
  				( y1 >= t && y1 <= b ) || // Top edge touching
  				( y2 >= t && y2 <= b ) || // Bottom edge touching
  				( y1 < t && y2 > b ) // Surrounded vertically
  			) && (
  				( x1 >= l && x1 <= r ) || // Left edge touching
  				( x2 >= l && x2 <= r ) || // Right edge touching
  				( x1 < l && x2 > r ) // Surrounded horizontally
  			);
  		default:
  			return false;
  		}
  	};
  } )();
  
  /*
  	This manager tracks offsets of draggables and droppables
  */
  $.ui.ddmanager = {
  	current: null,
  	droppables: { "default": [] },
  	prepareOffsets: function( t, event ) {
  
  		var i, j,
  			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
  			type = event ? event.type : null, // workaround for #2317
  			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
  
  		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
  
  			// No disabled and non-accepted
  			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
  					( t.currentItem || t.element ) ) ) ) {
  				continue;
  			}
  
  			// Filter out elements in the current dragged item
  			for ( j = 0; j < list.length; j++ ) {
  				if ( list[ j ] === m[ i ].element[ 0 ] ) {
  					m[ i ].proportions().height = 0;
  					continue droppablesLoop;
  				}
  			}
  
  			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
  			if ( !m[ i ].visible ) {
  				continue;
  			}
  
  			// Activate the droppable if used directly from draggables
  			if ( type === "mousedown" ) {
  				m[ i ]._activate.call( m[ i ], event );
  			}
  
  			m[ i ].offset = m[ i ].element.offset();
  			m[ i ].proportions( {
  				width: m[ i ].element[ 0 ].offsetWidth,
  				height: m[ i ].element[ 0 ].offsetHeight
  			} );
  
  		}
  
  	},
  	drop: function( draggable, event ) {
  
  		var dropped = false;
  
  		// Create a copy of the droppables in case the list changes during the drop (#9116)
  		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
  
  			if ( !this.options ) {
  				return;
  			}
  			if ( !this.options.disabled && this.visible &&
  					intersect( draggable, this, this.options.tolerance, event ) ) {
  				dropped = this._drop.call( this, event ) || dropped;
  			}
  
  			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
  					( draggable.currentItem || draggable.element ) ) ) {
  				this.isout = true;
  				this.isover = false;
  				this._deactivate.call( this, event );
  			}
  
  		} );
  		return dropped;
  
  	},
  	dragStart: function( draggable, event ) {
  
  		// Listen for scrolling so that if the dragging causes scrolling the position of the
  		// droppables can be recalculated (see #5003)
  		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
  			if ( !draggable.options.refreshPositions ) {
  				$.ui.ddmanager.prepareOffsets( draggable, event );
  			}
  		} );
  	},
  	drag: function( draggable, event ) {
  
  		// If you have a highly dynamic page, you might try this option. It renders positions
  		// every time you move the mouse.
  		if ( draggable.options.refreshPositions ) {
  			$.ui.ddmanager.prepareOffsets( draggable, event );
  		}
  
  		// Run through all droppables and check their positions based on specific tolerance options
  		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
  
  			if ( this.options.disabled || this.greedyChild || !this.visible ) {
  				return;
  			}
  
  			var parentInstance, scope, parent,
  				intersects = intersect( draggable, this, this.options.tolerance, event ),
  				c = !intersects && this.isover ?
  					"isout" :
  					( intersects && !this.isover ? "isover" : null );
  			if ( !c ) {
  				return;
  			}
  
  			if ( this.options.greedy ) {
  
  				// find droppable parents with same scope
  				scope = this.options.scope;
  				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
  					return $( this ).droppable( "instance" ).options.scope === scope;
  				} );
  
  				if ( parent.length ) {
  					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
  					parentInstance.greedyChild = ( c === "isover" );
  				}
  			}
  
  			// We just moved into a greedy child
  			if ( parentInstance && c === "isover" ) {
  				parentInstance.isover = false;
  				parentInstance.isout = true;
  				parentInstance._out.call( parentInstance, event );
  			}
  
  			this[ c ] = true;
  			this[ c === "isout" ? "isover" : "isout" ] = false;
  			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
  
  			// We just moved out of a greedy child
  			if ( parentInstance && c === "isout" ) {
  				parentInstance.isout = false;
  				parentInstance.isover = true;
  				parentInstance._over.call( parentInstance, event );
  			}
  		} );
  
  	},
  	dragStop: function( draggable, event ) {
  		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
  
  		// Call prepareOffsets one final time since IE does not fire return scroll events when
  		// overflow was caused by drag (see #5003)
  		if ( !draggable.options.refreshPositions ) {
  			$.ui.ddmanager.prepareOffsets( draggable, event );
  		}
  	}
  };
  
  // DEPRECATED
  // TODO: switch return back to widget declaration at top of file when this is removed
  if ( $.uiBackCompat !== false ) {
  
  	// Backcompat for activeClass and hoverClass options
  	$.widget( "ui.droppable", $.ui.droppable, {
  		options: {
  			hoverClass: false,
  			activeClass: false
  		},
  		_addActiveClass: function() {
  			this._super();
  			if ( this.options.activeClass ) {
  				this.element.addClass( this.options.activeClass );
  			}
  		},
  		_removeActiveClass: function() {
  			this._super();
  			if ( this.options.activeClass ) {
  				this.element.removeClass( this.options.activeClass );
  			}
  		},
  		_addHoverClass: function() {
  			this._super();
  			if ( this.options.hoverClass ) {
  				this.element.addClass( this.options.hoverClass );
  			}
  		},
  		_removeHoverClass: function() {
  			this._super();
  			if ( this.options.hoverClass ) {
  				this.element.removeClass( this.options.hoverClass );
  			}
  		}
  	} );
  }
  
  var widgetsDroppable = $.ui.droppable;
  
  
  /*!
   * jQuery UI Resizable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Resizable
  //>>group: Interactions
  //>>description: Enables resize functionality for any element.
  //>>docs: http://api.jqueryui.com/resizable/
  //>>demos: http://jqueryui.com/resizable/
  //>>css.structure: ../../themes/base/core.css
  //>>css.structure: ../../themes/base/resizable.css
  //>>css.theme: ../../themes/base/theme.css
  
  
  
  $.widget( "ui.resizable", $.ui.mouse, {
  	version: "1.12.1",
  	widgetEventPrefix: "resize",
  	options: {
  		alsoResize: false,
  		animate: false,
  		animateDuration: "slow",
  		animateEasing: "swing",
  		aspectRatio: false,
  		autoHide: false,
  		classes: {
  			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
  		},
  		containment: false,
  		ghost: false,
  		grid: false,
  		handles: "e,s,se",
  		helper: false,
  		maxHeight: null,
  		maxWidth: null,
  		minHeight: 10,
  		minWidth: 10,
  
  		// See #7960
  		zIndex: 90,
  
  		// Callbacks
  		resize: null,
  		start: null,
  		stop: null
  	},
  
  	_num: function( value ) {
  		return parseFloat( value ) || 0;
  	},
  
  	_isNumber: function( value ) {
  		return !isNaN( parseFloat( value ) );
  	},
  
  	_hasScroll: function( el, a ) {
  
  		if ( $( el ).css( "overflow" ) === "hidden" ) {
  			return false;
  		}
  
  		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
  			has = false;
  
  		if ( el[ scroll ] > 0 ) {
  			return true;
  		}
  
  		// TODO: determine which cases actually cause this to happen
  		// if the element doesn't have the scroll set, see if it's possible to
  		// set the scroll
  		el[ scroll ] = 1;
  		has = ( el[ scroll ] > 0 );
  		el[ scroll ] = 0;
  		return has;
  	},
  
  	_create: function() {
  
  		var margins,
  			o = this.options,
  			that = this;
  		this._addClass( "ui-resizable" );
  
  		$.extend( this, {
  			_aspectRatio: !!( o.aspectRatio ),
  			aspectRatio: o.aspectRatio,
  			originalElement: this.element,
  			_proportionallyResizeElements: [],
  			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
  		} );
  
  		// Wrap the element if it cannot hold child nodes
  		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
  
  			this.element.wrap(
  				$( "<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.resizable( "instance" )
  			);
  
  			this.elementIsWrapper = true;
  
  			margins = {
  				marginTop: this.originalElement.css( "marginTop" ),
  				marginRight: this.originalElement.css( "marginRight" ),
  				marginBottom: this.originalElement.css( "marginBottom" ),
  				marginLeft: this.originalElement.css( "marginLeft" )
  			};
  
  			this.element.css( margins );
  			this.originalElement.css( "margin", 0 );
  
  			// support: Safari
  			// Prevent Safari textarea resize
  			this.originalResizeStyle = this.originalElement.css( "resize" );
  			this.originalElement.css( "resize", "none" );
  
  			this._proportionallyResizeElements.push( this.originalElement.css( {
  				position: "static",
  				zoom: 1,
  				display: "block"
  			} ) );
  
  			// Support: IE9
  			// avoid IE jump (hard set the margin)
  			this.originalElement.css( margins );
  
  			this._proportionallyResize();
  		}
  
  		this._setupHandles();
  
  		if ( o.autoHide ) {
  			$( this.element )
  				.on( "mouseenter", function() {
  					if ( o.disabled ) {
  						return;
  					}
  					that._removeClass( "ui-resizable-autohide" );
  					that._handles.show();
  				} )
  				.on( "mouseleave", function() {
  					if ( o.disabled ) {
  						return;
  					}
  					if ( !that.resizing ) {
  						that._addClass( "ui-resizable-autohide" );
  						that._handles.hide();
  					}
  				} );
  		}
  
  		this._mouseInit();
  	},
  
  	_destroy: function() {
  
  		this._mouseDestroy();
  
  		var wrapper,
  			_destroy = function( exp ) {
  				$( exp )
  					.removeData( "resizable" )
  					.removeData( "ui-resizable" )
  					.off( ".resizable" )
  					.find( ".ui-resizable-handle" )
  						.remove();
  			};
  
  		// TODO: Unwrap at same DOM position
  		if ( this.elementIsWrapper ) {
  			_destroy( this.element );
  			wrapper = this.element;
  			this.originalElement.css( {
  				position: wrapper.css( "position" ),
  				width: wrapper.outerWidth(),
  				height: wrapper.outerHeight(),
  				top: wrapper.css( "top" ),
  				left: wrapper.css( "left" )
  			} ).insertAfter( wrapper );
  			wrapper.remove();
  		}
  
  		this.originalElement.css( "resize", this.originalResizeStyle );
  		_destroy( this.originalElement );
  
  		return this;
  	},
  
  	_setOption: function( key, value ) {
  		this._super( key, value );
  
  		switch ( key ) {
  		case "handles":
  			this._removeHandles();
  			this._setupHandles();
  			break;
  		default:
  			break;
  		}
  	},
  
  	_setupHandles: function() {
  		var o = this.options, handle, i, n, hname, axis, that = this;
  		this.handles = o.handles ||
  			( !$( ".ui-resizable-handle", this.element ).length ?
  				"e,s,se" : {
  					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"
  				} );
  
  		this._handles = $();
  		if ( this.handles.constructor === String ) {
  
  			if ( this.handles === "all" ) {
  				this.handles = "n,e,s,w,se,sw,ne,nw";
  			}
  
  			n = this.handles.split( "," );
  			this.handles = {};
  
  			for ( i = 0; i < n.length; i++ ) {
  
  				handle = $.trim( n[ i ] );
  				hname = "ui-resizable-" + handle;
  				axis = $( "<div>" );
  				this._addClass( axis, "ui-resizable-handle " + hname );
  
  				axis.css( { zIndex: o.zIndex } );
  
  				this.handles[ handle ] = ".ui-resizable-" + handle;
  				this.element.append( axis );
  			}
  
  		}
  
  		this._renderAxis = function( target ) {
  
  			var i, axis, padPos, padWrapper;
  
  			target = target || this.element;
  
  			for ( i in this.handles ) {
  
  				if ( this.handles[ i ].constructor === String ) {
  					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
  				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
  					this.handles[ i ] = $( this.handles[ i ] );
  					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
  				}
  
  				if ( this.elementIsWrapper &&
  						this.originalElement[ 0 ]
  							.nodeName
  							.match( /^(textarea|input|select|button)$/i ) ) {
  					axis = $( this.handles[ i ], this.element );
  
  					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
  						axis.outerHeight() :
  						axis.outerWidth();
  
  					padPos = [ "padding",
  						/ne|nw|n/.test( i ) ? "Top" :
  						/se|sw|s/.test( i ) ? "Bottom" :
  						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
  
  					target.css( padPos, padWrapper );
  
  					this._proportionallyResize();
  				}
  
  				this._handles = this._handles.add( this.handles[ i ] );
  			}
  		};
  
  		// TODO: make renderAxis a prototype function
  		this._renderAxis( this.element );
  
  		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
  		this._handles.disableSelection();
  
  		this._handles.on( "mouseover", function() {
  			if ( !that.resizing ) {
  				if ( this.className ) {
  					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
  				}
  				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
  			}
  		} );
  
  		if ( o.autoHide ) {
  			this._handles.hide();
  			this._addClass( "ui-resizable-autohide" );
  		}
  	},
  
  	_removeHandles: function() {
  		this._handles.remove();
  	},
  
  	_mouseCapture: function( event ) {
  		var i, handle,
  			capture = false;
  
  		for ( i in this.handles ) {
  			handle = $( this.handles[ i ] )[ 0 ];
  			if ( handle === event.target || $.contains( handle, event.target ) ) {
  				capture = true;
  			}
  		}
  
  		return !this.options.disabled && capture;
  	},
  
  	_mouseStart: function( event ) {
  
  		var curleft, curtop, cursor,
  			o = this.options,
  			el = this.element;
  
  		this.resizing = true;
  
  		this._renderProxy();
  
  		curleft = this._num( this.helper.css( "left" ) );
  		curtop = this._num( this.helper.css( "top" ) );
  
  		if ( o.containment ) {
  			curleft += $( o.containment ).scrollLeft() || 0;
  			curtop += $( o.containment ).scrollTop() || 0;
  		}
  
  		this.offset = this.helper.offset();
  		this.position = { left: curleft, top: curtop };
  
  		this.size = this._helper ? {
  				width: this.helper.width(),
  				height: this.helper.height()
  			} : {
  				width: el.width(),
  				height: el.height()
  			};
  
  		this.originalSize = this._helper ? {
  				width: el.outerWidth(),
  				height: el.outerHeight()
  			} : {
  				width: el.width(),
  				height: el.height()
  			};
  
  		this.sizeDiff = {
  			width: el.outerWidth() - el.width(),
  			height: el.outerHeight() - el.height()
  		};
  
  		this.originalPosition = { left: curleft, top: curtop };
  		this.originalMousePosition = { left: event.pageX, top: event.pageY };
  
  		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
  			o.aspectRatio :
  			( ( this.originalSize.width / this.originalSize.height ) || 1 );
  
  		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
  		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
  
  		this._addClass( "ui-resizable-resizing" );
  		this._propagate( "start", event );
  		return true;
  	},
  
  	_mouseDrag: function( event ) {
  
  		var data, props,
  			smp = this.originalMousePosition,
  			a = this.axis,
  			dx = ( event.pageX - smp.left ) || 0,
  			dy = ( event.pageY - smp.top ) || 0,
  			trigger = this._change[ a ];
  
  		this._updatePrevProperties();
  
  		if ( !trigger ) {
  			return false;
  		}
  
  		data = trigger.apply( this, [ event, dx, dy ] );
  
  		this._updateVirtualBoundaries( event.shiftKey );
  		if ( this._aspectRatio || event.shiftKey ) {
  			data = this._updateRatio( data, event );
  		}
  
  		data = this._respectSize( data, event );
  
  		this._updateCache( data );
  
  		this._propagate( "resize", event );
  
  		props = this._applyChanges();
  
  		if ( !this._helper && this._proportionallyResizeElements.length ) {
  			this._proportionallyResize();
  		}
  
  		if ( !$.isEmptyObject( props ) ) {
  			this._updatePrevProperties();
  			this._trigger( "resize", event, this.ui() );
  			this._applyChanges();
  		}
  
  		return false;
  	},
  
  	_mouseStop: function( event ) {
  
  		this.resizing = false;
  		var pr, ista, soffseth, soffsetw, s, left, top,
  			o = this.options, that = this;
  
  		if ( this._helper ) {
  
  			pr = this._proportionallyResizeElements;
  			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
  			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
  			soffsetw = ista ? 0 : that.sizeDiff.width;
  
  			s = {
  				width: ( that.helper.width()  - soffsetw ),
  				height: ( that.helper.height() - soffseth )
  			};
  			left = ( parseFloat( that.element.css( "left" ) ) +
  				( that.position.left - that.originalPosition.left ) ) || null;
  			top = ( parseFloat( that.element.css( "top" ) ) +
  				( that.position.top - that.originalPosition.top ) ) || null;
  
  			if ( !o.animate ) {
  				this.element.css( $.extend( s, { top: top, left: left } ) );
  			}
  
  			that.helper.height( that.size.height );
  			that.helper.width( that.size.width );
  
  			if ( this._helper && !o.animate ) {
  				this._proportionallyResize();
  			}
  		}
  
  		$( "body" ).css( "cursor", "auto" );
  
  		this._removeClass( "ui-resizable-resizing" );
  
  		this._propagate( "stop", event );
  
  		if ( this._helper ) {
  			this.helper.remove();
  		}
  
  		return false;
  
  	},
  
  	_updatePrevProperties: function() {
  		this.prevPosition = {
  			top: this.position.top,
  			left: this.position.left
  		};
  		this.prevSize = {
  			width: this.size.width,
  			height: this.size.height
  		};
  	},
  
  	_applyChanges: function() {
  		var props = {};
  
  		if ( this.position.top !== this.prevPosition.top ) {
  			props.top = this.position.top + "px";
  		}
  		if ( this.position.left !== this.prevPosition.left ) {
  			props.left = this.position.left + "px";
  		}
  		if ( this.size.width !== this.prevSize.width ) {
  			props.width = this.size.width + "px";
  		}
  		if ( this.size.height !== this.prevSize.height ) {
  			props.height = this.size.height + "px";
  		}
  
  		this.helper.css( props );
  
  		return props;
  	},
  
  	_updateVirtualBoundaries: function( forceAspectRatio ) {
  		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
  			o = this.options;
  
  		b = {
  			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
  			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
  			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
  			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
  		};
  
  		if ( this._aspectRatio || forceAspectRatio ) {
  			pMinWidth = b.minHeight * this.aspectRatio;
  			pMinHeight = b.minWidth / this.aspectRatio;
  			pMaxWidth = b.maxHeight * this.aspectRatio;
  			pMaxHeight = b.maxWidth / this.aspectRatio;
  
  			if ( pMinWidth > b.minWidth ) {
  				b.minWidth = pMinWidth;
  			}
  			if ( pMinHeight > b.minHeight ) {
  				b.minHeight = pMinHeight;
  			}
  			if ( pMaxWidth < b.maxWidth ) {
  				b.maxWidth = pMaxWidth;
  			}
  			if ( pMaxHeight < b.maxHeight ) {
  				b.maxHeight = pMaxHeight;
  			}
  		}
  		this._vBoundaries = b;
  	},
  
  	_updateCache: function( data ) {
  		this.offset = this.helper.offset();
  		if ( this._isNumber( data.left ) ) {
  			this.position.left = data.left;
  		}
  		if ( this._isNumber( data.top ) ) {
  			this.position.top = data.top;
  		}
  		if ( this._isNumber( data.height ) ) {
  			this.size.height = data.height;
  		}
  		if ( this._isNumber( data.width ) ) {
  			this.size.width = data.width;
  		}
  	},
  
  	_updateRatio: function( data ) {
  
  		var cpos = this.position,
  			csize = this.size,
  			a = this.axis;
  
  		if ( this._isNumber( data.height ) ) {
  			data.width = ( data.height * this.aspectRatio );
  		} else if ( this._isNumber( data.width ) ) {
  			data.height = ( data.width / this.aspectRatio );
  		}
  
  		if ( a === "sw" ) {
  			data.left = cpos.left + ( csize.width - data.width );
  			data.top = null;
  		}
  		if ( a === "nw" ) {
  			data.top = cpos.top + ( csize.height - data.height );
  			data.left = cpos.left + ( csize.width - data.width );
  		}
  
  		return data;
  	},
  
  	_respectSize: function( data ) {
  
  		var o = this._vBoundaries,
  			a = this.axis,
  			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
  			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
  			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
  			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
  			dw = this.originalPosition.left + this.originalSize.width,
  			dh = this.originalPosition.top + this.originalSize.height,
  			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
  		if ( isminw ) {
  			data.width = o.minWidth;
  		}
  		if ( isminh ) {
  			data.height = o.minHeight;
  		}
  		if ( ismaxw ) {
  			data.width = o.maxWidth;
  		}
  		if ( ismaxh ) {
  			data.height = o.maxHeight;
  		}
  
  		if ( isminw && cw ) {
  			data.left = dw - o.minWidth;
  		}
  		if ( ismaxw && cw ) {
  			data.left = dw - o.maxWidth;
  		}
  		if ( isminh && ch ) {
  			data.top = dh - o.minHeight;
  		}
  		if ( ismaxh && ch ) {
  			data.top = dh - o.maxHeight;
  		}
  
  		// Fixing jump error on top/left - bug #2330
  		if ( !data.width && !data.height && !data.left && data.top ) {
  			data.top = null;
  		} else if ( !data.width && !data.height && !data.top && data.left ) {
  			data.left = null;
  		}
  
  		return data;
  	},
  
  	_getPaddingPlusBorderDimensions: function( element ) {
  		var i = 0,
  			widths = [],
  			borders = [
  				element.css( "borderTopWidth" ),
  				element.css( "borderRightWidth" ),
  				element.css( "borderBottomWidth" ),
  				element.css( "borderLeftWidth" )
  			],
  			paddings = [
  				element.css( "paddingTop" ),
  				element.css( "paddingRight" ),
  				element.css( "paddingBottom" ),
  				element.css( "paddingLeft" )
  			];
  
  		for ( ; i < 4; i++ ) {
  			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
  			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
  		}
  
  		return {
  			height: widths[ 0 ] + widths[ 2 ],
  			width: widths[ 1 ] + widths[ 3 ]
  		};
  	},
  
  	_proportionallyResize: function() {
  
  		if ( !this._proportionallyResizeElements.length ) {
  			return;
  		}
  
  		var prel,
  			i = 0,
  			element = this.helper || this.element;
  
  		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
  
  			prel = this._proportionallyResizeElements[ i ];
  
  			// TODO: Seems like a bug to cache this.outerDimensions
  			// considering that we are in a loop.
  			if ( !this.outerDimensions ) {
  				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
  			}
  
  			prel.css( {
  				height: ( element.height() - this.outerDimensions.height ) || 0,
  				width: ( element.width() - this.outerDimensions.width ) || 0
  			} );
  
  		}
  
  	},
  
  	_renderProxy: function() {
  
  		var el = this.element, o = this.options;
  		this.elementOffset = el.offset();
  
  		if ( this._helper ) {
  
  			this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
  
  			this._addClass( this.helper, this._helper );
  			this.helper.css( {
  				width: this.element.outerWidth(),
  				height: this.element.outerHeight(),
  				position: "absolute",
  				left: this.elementOffset.left + "px",
  				top: this.elementOffset.top + "px",
  				zIndex: ++o.zIndex //TODO: Don't modify option
  			} );
  
  			this.helper
  				.appendTo( "body" )
  				.disableSelection();
  
  		} else {
  			this.helper = this.element;
  		}
  
  	},
  
  	_change: {
  		e: function( event, dx ) {
  			return { width: this.originalSize.width + dx };
  		},
  		w: function( event, dx ) {
  			var cs = this.originalSize, sp = this.originalPosition;
  			return { left: sp.left + dx, width: cs.width - dx };
  		},
  		n: function( event, dx, dy ) {
  			var cs = this.originalSize, sp = this.originalPosition;
  			return { top: sp.top + dy, height: cs.height - dy };
  		},
  		s: function( event, dx, dy ) {
  			return { height: this.originalSize.height + dy };
  		},
  		se: function( event, dx, dy ) {
  			return $.extend( this._change.s.apply( this, arguments ),
  				this._change.e.apply( this, [ event, dx, dy ] ) );
  		},
  		sw: function( event, dx, dy ) {
  			return $.extend( this._change.s.apply( this, arguments ),
  				this._change.w.apply( this, [ event, dx, dy ] ) );
  		},
  		ne: function( event, dx, dy ) {
  			return $.extend( this._change.n.apply( this, arguments ),
  				this._change.e.apply( this, [ event, dx, dy ] ) );
  		},
  		nw: function( event, dx, dy ) {
  			return $.extend( this._change.n.apply( this, arguments ),
  				this._change.w.apply( this, [ event, dx, dy ] ) );
  		}
  	},
  
  	_propagate: function( n, event ) {
  		$.ui.plugin.call( this, n, [ event, this.ui() ] );
  		( n !== "resize" && this._trigger( n, event, 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
  		};
  	}
  
  } );
  
  /*
   * Resizable Extensions
   */
  
  $.ui.plugin.add( "resizable", "animate", {
  
  	stop: function( event ) {
  		var that = $( this ).resizable( "instance" ),
  			o = that.options,
  			pr = that._proportionallyResizeElements,
  			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
  			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
  			soffsetw = ista ? 0 : that.sizeDiff.width,
  			style = {
  				width: ( that.size.width - soffsetw ),
  				height: ( that.size.height - soffseth )
  			},
  			left = ( parseFloat( that.element.css( "left" ) ) +
  				( that.position.left - that.originalPosition.left ) ) || null,
  			top = ( parseFloat( that.element.css( "top" ) ) +
  				( that.position.top - that.originalPosition.top ) ) || null;
  
  		that.element.animate(
  			$.extend( style, top && left ? { top: top, left: left } : {} ), {
  				duration: o.animateDuration,
  				easing: o.animateEasing,
  				step: function() {
  
  					var data = {
  						width: parseFloat( that.element.css( "width" ) ),
  						height: parseFloat( that.element.css( "height" ) ),
  						top: parseFloat( that.element.css( "top" ) ),
  						left: parseFloat( that.element.css( "left" ) )
  					};
  
  					if ( pr && pr.length ) {
  						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
  					}
  
  					// Propagating resize, and updating values for each animation step
  					that._updateCache( data );
  					that._propagate( "resize", event );
  
  				}
  			}
  		);
  	}
  
  } );
  
  $.ui.plugin.add( "resizable", "containment", {
  
  	start: function() {
  		var element, p, co, ch, cw, width, height,
  			that = $( this ).resizable( "instance" ),
  			o = that.options,
  			el = that.element,
  			oc = o.containment,
  			ce = ( oc instanceof $ ) ?
  				oc.get( 0 ) :
  				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
  
  		if ( !ce ) {
  			return;
  		}
  
  		that.containerElement = $( ce );
  
  		if ( /document/.test( oc ) || oc === document ) {
  			that.containerOffset = {
  				left: 0,
  				top: 0
  			};
  			that.containerPosition = {
  				left: 0,
  				top: 0
  			};
  
  			that.parentData = {
  				element: $( document ),
  				left: 0,
  				top: 0,
  				width: $( document ).width(),
  				height: $( document ).height() || document.body.parentNode.scrollHeight
  			};
  		} else {
  			element = $( ce );
  			p = [];
  			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
  				p[ i ] = that._num( element.css( "padding" + name ) );
  			} );
  
  			that.containerOffset = element.offset();
  			that.containerPosition = element.position();
  			that.containerSize = {
  				height: ( element.innerHeight() - p[ 3 ] ),
  				width: ( element.innerWidth() - p[ 1 ] )
  			};
  
  			co = that.containerOffset;
  			ch = that.containerSize.height;
  			cw = that.containerSize.width;
  			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
  			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
  
  			that.parentData = {
  				element: ce,
  				left: co.left,
  				top: co.top,
  				width: width,
  				height: height
  			};
  		}
  	},
  
  	resize: function( event ) {
  		var woset, hoset, isParent, isOffsetRelative,
  			that = $( this ).resizable( "instance" ),
  			o = that.options,
  			co = that.containerOffset,
  			cp = that.position,
  			pRatio = that._aspectRatio || event.shiftKey,
  			cop = {
  				top: 0,
  				left: 0
  			},
  			ce = that.containerElement,
  			continueResize = true;
  
  		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
  			cop = co;
  		}
  
  		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
  			that.size.width = that.size.width +
  				( that._helper ?
  					( that.position.left - co.left ) :
  					( that.position.left - cop.left ) );
  
  			if ( pRatio ) {
  				that.size.height = that.size.width / that.aspectRatio;
  				continueResize = false;
  			}
  			that.position.left = o.helper ? co.left : 0;
  		}
  
  		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
  			that.size.height = that.size.height +
  				( that._helper ?
  					( that.position.top - co.top ) :
  					that.position.top );
  
  			if ( pRatio ) {
  				that.size.width = that.size.height * that.aspectRatio;
  				continueResize = false;
  			}
  			that.position.top = that._helper ? co.top : 0;
  		}
  
  		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
  		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
  
  		if ( isParent && isOffsetRelative ) {
  			that.offset.left = that.parentData.left + that.position.left;
  			that.offset.top = that.parentData.top + that.position.top;
  		} else {
  			that.offset.left = that.element.offset().left;
  			that.offset.top = that.element.offset().top;
  		}
  
  		woset = Math.abs( that.sizeDiff.width +
  			( that._helper ?
  				that.offset.left - cop.left :
  				( that.offset.left - co.left ) ) );
  
  		hoset = Math.abs( that.sizeDiff.height +
  			( that._helper ?
  				that.offset.top - cop.top :
  				( that.offset.top - co.top ) ) );
  
  		if ( woset + that.size.width >= that.parentData.width ) {
  			that.size.width = that.parentData.width - woset;
  			if ( pRatio ) {
  				that.size.height = that.size.width / that.aspectRatio;
  				continueResize = false;
  			}
  		}
  
  		if ( hoset + that.size.height >= that.parentData.height ) {
  			that.size.height = that.parentData.height - hoset;
  			if ( pRatio ) {
  				that.size.width = that.size.height * that.aspectRatio;
  				continueResize = false;
  			}
  		}
  
  		if ( !continueResize ) {
  			that.position.left = that.prevPosition.left;
  			that.position.top = that.prevPosition.top;
  			that.size.width = that.prevSize.width;
  			that.size.height = that.prevSize.height;
  		}
  	},
  
  	stop: function() {
  		var that = $( this ).resizable( "instance" ),
  			o = that.options,
  			co = that.containerOffset,
  			cop = that.containerPosition,
  			ce = that.containerElement,
  			helper = $( that.helper ),
  			ho = helper.offset(),
  			w = helper.outerWidth() - that.sizeDiff.width,
  			h = helper.outerHeight() - that.sizeDiff.height;
  
  		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
  			$( this ).css( {
  				left: ho.left - cop.left - co.left,
  				width: w,
  				height: h
  			} );
  		}
  
  		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
  			$( this ).css( {
  				left: ho.left - cop.left - co.left,
  				width: w,
  				height: h
  			} );
  		}
  	}
  } );
  
  $.ui.plugin.add( "resizable", "alsoResize", {
  
  	start: function() {
  		var that = $( this ).resizable( "instance" ),
  			o = that.options;
  
  		$( o.alsoResize ).each( function() {
  			var el = $( this );
  			el.data( "ui-resizable-alsoresize", {
  				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
  				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
  			} );
  		} );
  	},
  
  	resize: function( event, ui ) {
  		var that = $( this ).resizable( "instance" ),
  			o = that.options,
  			os = that.originalSize,
  			op = that.originalPosition,
  			delta = {
  				height: ( that.size.height - os.height ) || 0,
  				width: ( that.size.width - os.width ) || 0,
  				top: ( that.position.top - op.top ) || 0,
  				left: ( that.position.left - op.left ) || 0
  			};
  
  			$( o.alsoResize ).each( function() {
  				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
  					css = el.parents( ui.originalElement[ 0 ] ).length ?
  							[ "width", "height" ] :
  							[ "width", "height", "top", "left" ];
  
  				$.each( css, function( i, prop ) {
  					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
  					if ( sum && sum >= 0 ) {
  						style[ prop ] = sum || null;
  					}
  				} );
  
  				el.css( style );
  			} );
  	},
  
  	stop: function() {
  		$( this ).removeData( "ui-resizable-alsoresize" );
  	}
  } );
  
  $.ui.plugin.add( "resizable", "ghost", {
  
  	start: function() {
  
  		var that = $( this ).resizable( "instance" ), cs = that.size;
  
  		that.ghost = that.originalElement.clone();
  		that.ghost.css( {
  			opacity: 0.25,
  			display: "block",
  			position: "relative",
  			height: cs.height,
  			width: cs.width,
  			margin: 0,
  			left: 0,
  			top: 0
  		} );
  
  		that._addClass( that.ghost, "ui-resizable-ghost" );
  
  		// DEPRECATED
  		// TODO: remove after 1.12
  		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
  
  			// Ghost option
  			that.ghost.addClass( this.options.ghost );
  		}
  
  		that.ghost.appendTo( that.helper );
  
  	},
  
  	resize: function() {
  		var that = $( this ).resizable( "instance" );
  		if ( that.ghost ) {
  			that.ghost.css( {
  				position: "relative",
  				height: that.size.height,
  				width: that.size.width
  			} );
  		}
  	},
  
  	stop: function() {
  		var that = $( this ).resizable( "instance" );
  		if ( that.ghost && that.helper ) {
  			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
  		}
  	}
  
  } );
  
  $.ui.plugin.add( "resizable", "grid", {
  
  	resize: function() {
  		var outerDimensions,
  			that = $( this ).resizable( "instance" ),
  			o = that.options,
  			cs = that.size,
  			os = that.originalSize,
  			op = that.originalPosition,
  			a = that.axis,
  			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
  			gridX = ( grid[ 0 ] || 1 ),
  			gridY = ( grid[ 1 ] || 1 ),
  			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
  			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
  			newWidth = os.width + ox,
  			newHeight = os.height + oy,
  			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
  			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
  			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
  			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
  
  		o.grid = grid;
  
  		if ( isMinWidth ) {
  			newWidth += gridX;
  		}
  		if ( isMinHeight ) {
  			newHeight += gridY;
  		}
  		if ( isMaxWidth ) {
  			newWidth -= gridX;
  		}
  		if ( isMaxHeight ) {
  			newHeight -= gridY;
  		}
  
  		if ( /^(se|s|e)$/.test( a ) ) {
  			that.size.width = newWidth;
  			that.size.height = newHeight;
  		} else if ( /^(ne)$/.test( a ) ) {
  			that.size.width = newWidth;
  			that.size.height = newHeight;
  			that.position.top = op.top - oy;
  		} else if ( /^(sw)$/.test( a ) ) {
  			that.size.width = newWidth;
  			that.size.height = newHeight;
  			that.position.left = op.left - ox;
  		} else {
  			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
  				outerDimensions = that._getPaddingPlusBorderDimensions( this );
  			}
  
  			if ( newHeight - gridY > 0 ) {
  				that.size.height = newHeight;
  				that.position.top = op.top - oy;
  			} else {
  				newHeight = gridY - outerDimensions.height;
  				that.size.height = newHeight;
  				that.position.top = op.top + os.height - newHeight;
  			}
  			if ( newWidth - gridX > 0 ) {
  				that.size.width = newWidth;
  				that.position.left = op.left - ox;
  			} else {
  				newWidth = gridX - outerDimensions.width;
  				that.size.width = newWidth;
  				that.position.left = op.left + os.width - newWidth;
  			}
  		}
  	}
  
  } );
  
  var widgetsResizable = $.ui.resizable;
  
  
  /*!
   * jQuery UI Sortable 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Sortable
  //>>group: Interactions
  //>>description: Enables items in a list to be sorted using the mouse.
  //>>docs: http://api.jqueryui.com/sortable/
  //>>demos: http://jqueryui.com/sortable/
  //>>css.structure: ../../themes/base/sortable.css
  
  
  
  var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
  	version: "1.12.1",
  	widgetEventPrefix: "sort",
  	ready: false,
  	options: {
  		appendTo: "parent",
  		axis: false,
  		connectWith: false,
  		containment: false,
  		cursor: "auto",
  		cursorAt: false,
  		dropOnEmpty: true,
  		forcePlaceholderSize: false,
  		forceHelperSize: false,
  		grid: false,
  		handle: false,
  		helper: "original",
  		items: "> *",
  		opacity: false,
  		placeholder: false,
  		revert: false,
  		scroll: true,
  		scrollSensitivity: 20,
  		scrollSpeed: 20,
  		scope: "default",
  		tolerance: "intersect",
  		zIndex: 1000,
  
  		// Callbacks
  		activate: null,
  		beforeStop: null,
  		change: null,
  		deactivate: null,
  		out: null,
  		over: null,
  		receive: null,
  		remove: null,
  		sort: null,
  		start: null,
  		stop: null,
  		update: null
  	},
  
  	_isOverAxis: function( x, reference, size ) {
  		return ( x >= reference ) && ( x < ( reference + size ) );
  	},
  
  	_isFloating: function( item ) {
  		return ( /left|right/ ).test( item.css( "float" ) ) ||
  			( /inline|table-cell/ ).test( item.css( "display" ) );
  	},
  
  	_create: function() {
  		this.containerCache = {};
  		this._addClass( "ui-sortable" );
  
  		//Get the items
  		this.refresh();
  
  		//Let's determine the parent's offset
  		this.offset = this.element.offset();
  
  		//Initialize mouse events for interaction
  		this._mouseInit();
  
  		this._setHandleClassName();
  
  		//We're ready to go
  		this.ready = true;
  
  	},
  
  	_setOption: function( key, value ) {
  		this._super( key, value );
  
  		if ( key === "handle" ) {
  			this._setHandleClassName();
  		}
  	},
  
  	_setHandleClassName: function() {
  		var that = this;
  		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
  		$.each( this.items, function() {
  			that._addClass(
  				this.instance.options.handle ?
  					this.item.find( this.instance.options.handle ) :
  					this.item,
  				"ui-sortable-handle"
  			);
  		} );
  	},
  
  	_destroy: function() {
  		this._mouseDestroy();
  
  		for ( var i = this.items.length - 1; i >= 0; i-- ) {
  			this.items[ i ].item.removeData( this.widgetName + "-item" );
  		}
  
  		return this;
  	},
  
  	_mouseCapture: function( event, overrideHandle ) {
  		var currentItem = null,
  			validHandle = false,
  			that = this;
  
  		if ( this.reverting ) {
  			return false;
  		}
  
  		if ( this.options.disabled || this.options.type === "static" ) {
  			return false;
  		}
  
  		//We have to refresh the items data once first
  		this._refreshItems( event );
  
  		//Find out if the clicked node (or one of its parents) is a actual item in this.items
  		$( event.target ).parents().each( function() {
  			if ( $.data( this, that.widgetName + "-item" ) === that ) {
  				currentItem = $( this );
  				return false;
  			}
  		} );
  		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
  			currentItem = $( event.target );
  		}
  
  		if ( !currentItem ) {
  			return false;
  		}
  		if ( this.options.handle && !overrideHandle ) {
  			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
  				if ( this === event.target ) {
  					validHandle = true;
  				}
  			} );
  			if ( !validHandle ) {
  				return false;
  			}
  		}
  
  		this.currentItem = currentItem;
  		this._removeCurrentsFromItems();
  		return true;
  
  	},
  
  	_mouseStart: function( event, overrideHandle, noActivation ) {
  
  		var i, body,
  			o = this.options;
  
  		this.currentContainer = this;
  
  		//We only need to call refreshPositions, because the refreshItems call has been moved to
  		// mouseCapture
  		this.refreshPositions();
  
  		//Create and append the visible helper
  		this.helper = this._createHelper( event );
  
  		//Cache the helper size
  		this._cacheHelperProportions();
  
  		/*
  		 * - Position generation -
  		 * This block generates everything position related - it's the core of draggables.
  		 */
  
  		//Cache the margins of the original element
  		this._cacheMargins();
  
  		//Get the next scrolling parent
  		this.scrollParent = this.helper.scrollParent();
  
  		//The element's absolute position on the page minus margins
  		this.offset = this.currentItem.offset();
  		this.offset = {
  			top: this.offset.top - this.margins.top,
  			left: this.offset.left - this.margins.left
  		};
  
  		$.extend( this.offset, {
  			click: { //Where the click happened, relative to the element
  				left: event.pageX - this.offset.left,
  				top: event.pageY - this.offset.top
  			},
  			parent: this._getParentOffset(),
  
  			// This is a relative to absolute position minus the actual position calculation -
  			// only used for relative positioned helper
  			relative: this._getRelativeOffset()
  		} );
  
  		// Only after we got the offset, we can change the helper's position to absolute
  		// TODO: Still need to figure out a way to make relative sorting possible
  		this.helper.css( "position", "absolute" );
  		this.cssPosition = this.helper.css( "position" );
  
  		//Generate the original position
  		this.originalPosition = this._generatePosition( event );
  		this.originalPageX = event.pageX;
  		this.originalPageY = event.pageY;
  
  		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
  		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
  
  		//Cache the former DOM position
  		this.domPosition = {
  			prev: this.currentItem.prev()[ 0 ],
  			parent: this.currentItem.parent()[ 0 ]
  		};
  
  		// If the helper is not the original, hide the original so it's not playing any role during
  		// the drag, won't cause anything bad this way
  		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
  			this.currentItem.hide();
  		}
  
  		//Create the placeholder
  		this._createPlaceholder();
  
  		//Set a containment if given in the options
  		if ( o.containment ) {
  			this._setContainment();
  		}
  
  		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
  			body = this.document.find( "body" );
  
  			// Support: IE
  			this.storedCursor = body.css( "cursor" );
  			body.css( "cursor", o.cursor );
  
  			this.storedStylesheet =
  				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
  		}
  
  		if ( o.opacity ) { // opacity option
  			if ( this.helper.css( "opacity" ) ) {
  				this._storedOpacity = this.helper.css( "opacity" );
  			}
  			this.helper.css( "opacity", o.opacity );
  		}
  
  		if ( o.zIndex ) { // zIndex option
  			if ( this.helper.css( "zIndex" ) ) {
  				this._storedZIndex = this.helper.css( "zIndex" );
  			}
  			this.helper.css( "zIndex", o.zIndex );
  		}
  
  		//Prepare scrolling
  		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  				this.scrollParent[ 0 ].tagName !== "HTML" ) {
  			this.overflowOffset = this.scrollParent.offset();
  		}
  
  		//Call callbacks
  		this._trigger( "start", event, this._uiHash() );
  
  		//Recache the helper size
  		if ( !this._preserveHelperProportions ) {
  			this._cacheHelperProportions();
  		}
  
  		//Post "activate" events to possible containers
  		if ( !noActivation ) {
  			for ( i = this.containers.length - 1; i >= 0; i-- ) {
  				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
  			}
  		}
  
  		//Prepare possible droppables
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.current = this;
  		}
  
  		if ( $.ui.ddmanager && !o.dropBehaviour ) {
  			$.ui.ddmanager.prepareOffsets( this, event );
  		}
  
  		this.dragging = true;
  
  		this._addClass( this.helper, "ui-sortable-helper" );
  
  		// Execute the drag once - this causes the helper not to be visiblebefore getting its
  		// correct position
  		this._mouseDrag( event );
  		return true;
  
  	},
  
  	_mouseDrag: function( event ) {
  		var i, item, itemElement, intersection,
  			o = this.options,
  			scrolled = false;
  
  		//Compute the helpers position
  		this.position = this._generatePosition( event );
  		this.positionAbs = this._convertPositionTo( "absolute" );
  
  		if ( !this.lastPositionAbs ) {
  			this.lastPositionAbs = this.positionAbs;
  		}
  
  		//Do scrolling
  		if ( this.options.scroll ) {
  			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  					this.scrollParent[ 0 ].tagName !== "HTML" ) {
  
  				if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
  						event.pageY < o.scrollSensitivity ) {
  					this.scrollParent[ 0 ].scrollTop =
  						scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
  				} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
  					this.scrollParent[ 0 ].scrollTop =
  						scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
  				}
  
  				if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
  						event.pageX < o.scrollSensitivity ) {
  					this.scrollParent[ 0 ].scrollLeft = scrolled =
  						this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
  				} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
  					this.scrollParent[ 0 ].scrollLeft = scrolled =
  						this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
  				}
  
  			} else {
  
  				if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
  					scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
  				} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
  						o.scrollSensitivity ) {
  					scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
  				}
  
  				if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
  					scrolled = this.document.scrollLeft(
  						this.document.scrollLeft() - o.scrollSpeed
  					);
  				} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
  						o.scrollSensitivity ) {
  					scrolled = this.document.scrollLeft(
  						this.document.scrollLeft() + o.scrollSpeed
  					);
  				}
  
  			}
  
  			if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
  				$.ui.ddmanager.prepareOffsets( this, event );
  			}
  		}
  
  		//Regenerate the absolute position used for position checks
  		this.positionAbs = this._convertPositionTo( "absolute" );
  
  		//Set the helper 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";
  		}
  
  		//Rearrange
  		for ( i = this.items.length - 1; i >= 0; i-- ) {
  
  			//Cache variables and intersection, continue if no intersection
  			item = this.items[ i ];
  			itemElement = item.item[ 0 ];
  			intersection = this._intersectsWithPointer( item );
  			if ( !intersection ) {
  				continue;
  			}
  
  			// Only put the placeholder inside the current Container, skip all
  			// items from other containers. This works because when moving
  			// an item from one container to another the
  			// currentContainer is switched before the placeholder is moved.
  			//
  			// Without this, moving items in "sub-sortables" can cause
  			// the placeholder to jitter between the outer and inner container.
  			if ( item.instance !== this.currentContainer ) {
  				continue;
  			}
  
  			// Cannot intersect with itself
  			// no useless actions that have been done before
  			// no action if the item moved is the parent of the item checked
  			if ( itemElement !== this.currentItem[ 0 ] &&
  				this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement &&
  				!$.contains( this.placeholder[ 0 ], itemElement ) &&
  				( this.options.type === "semi-dynamic" ?
  					!$.contains( this.element[ 0 ], itemElement ) :
  					true
  				)
  			) {
  
  				this.direction = intersection === 1 ? "down" : "up";
  
  				if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) {
  					this._rearrange( event, item );
  				} else {
  					break;
  				}
  
  				this._trigger( "change", event, this._uiHash() );
  				break;
  			}
  		}
  
  		//Post events to containers
  		this._contactContainers( event );
  
  		//Interconnect with droppables
  		if ( $.ui.ddmanager ) {
  			$.ui.ddmanager.drag( this, event );
  		}
  
  		//Call callbacks
  		this._trigger( "sort", event, this._uiHash() );
  
  		this.lastPositionAbs = this.positionAbs;
  		return false;
  
  	},
  
  	_mouseStop: function( event, noPropagation ) {
  
  		if ( !event ) {
  			return;
  		}
  
  		//If we are using droppables, inform the manager about the drop
  		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
  			$.ui.ddmanager.drop( this, event );
  		}
  
  		if ( this.options.revert ) {
  			var that = this,
  				cur = this.placeholder.offset(),
  				axis = this.options.axis,
  				animation = {};
  
  			if ( !axis || axis === "x" ) {
  				animation.left = cur.left - this.offset.parent.left - this.margins.left +
  					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
  						0 :
  						this.offsetParent[ 0 ].scrollLeft
  					);
  			}
  			if ( !axis || axis === "y" ) {
  				animation.top = cur.top - this.offset.parent.top - this.margins.top +
  					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
  						0 :
  						this.offsetParent[ 0 ].scrollTop
  					);
  			}
  			this.reverting = true;
  			$( this.helper ).animate(
  				animation,
  				parseInt( this.options.revert, 10 ) || 500,
  				function() {
  					that._clear( event );
  				}
  			);
  		} else {
  			this._clear( event, noPropagation );
  		}
  
  		return false;
  
  	},
  
  	cancel: function() {
  
  		if ( this.dragging ) {
  
  			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
  
  			if ( this.options.helper === "original" ) {
  				this.currentItem.css( this._storedCSS );
  				this._removeClass( this.currentItem, "ui-sortable-helper" );
  			} else {
  				this.currentItem.show();
  			}
  
  			//Post deactivating events to containers
  			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
  				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
  				if ( this.containers[ i ].containerCache.over ) {
  					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
  					this.containers[ i ].containerCache.over = 0;
  				}
  			}
  
  		}
  
  		if ( this.placeholder ) {
  
  			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
  			// it unbinds ALL events from the original node!
  			if ( this.placeholder[ 0 ].parentNode ) {
  				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
  			}
  			if ( this.options.helper !== "original" && this.helper &&
  					this.helper[ 0 ].parentNode ) {
  				this.helper.remove();
  			}
  
  			$.extend( this, {
  				helper: null,
  				dragging: false,
  				reverting: false,
  				_noFinalSort: null
  			} );
  
  			if ( this.domPosition.prev ) {
  				$( this.domPosition.prev ).after( this.currentItem );
  			} else {
  				$( this.domPosition.parent ).prepend( this.currentItem );
  			}
  		}
  
  		return this;
  
  	},
  
  	serialize: function( o ) {
  
  		var items = this._getItemsAsjQuery( o && o.connected ),
  			str = [];
  		o = o || {};
  
  		$( items ).each( function() {
  			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
  				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
  			if ( res ) {
  				str.push(
  					( o.key || res[ 1 ] + "[]" ) +
  					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
  			}
  		} );
  
  		if ( !str.length && o.key ) {
  			str.push( o.key + "=" );
  		}
  
  		return str.join( "&" );
  
  	},
  
  	toArray: function( o ) {
  
  		var items = this._getItemsAsjQuery( o && o.connected ),
  			ret = [];
  
  		o = o || {};
  
  		items.each( function() {
  			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
  		} );
  		return ret;
  
  	},
  
  	/* Be careful with the following core functions */
  	_intersectsWith: function( item ) {
  
  		var x1 = this.positionAbs.left,
  			x2 = x1 + this.helperProportions.width,
  			y1 = this.positionAbs.top,
  			y2 = y1 + this.helperProportions.height,
  			l = item.left,
  			r = l + item.width,
  			t = item.top,
  			b = t + item.height,
  			dyClick = this.offset.click.top,
  			dxClick = this.offset.click.left,
  			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
  				( y1 + dyClick ) < b ),
  			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
  				( x1 + dxClick ) < r ),
  			isOverElement = isOverElementHeight && isOverElementWidth;
  
  		if ( this.options.tolerance === "pointer" ||
  			this.options.forcePointerForContainers ||
  			( this.options.tolerance !== "pointer" &&
  				this.helperProportions[ this.floating ? "width" : "height" ] >
  				item[ this.floating ? "width" : "height" ] )
  		) {
  			return isOverElement;
  		} else {
  
  			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
  				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
  				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
  				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
  
  		}
  	},
  
  	_intersectsWithPointer: function( item ) {
  		var verticalDirection, horizontalDirection,
  			isOverElementHeight = ( this.options.axis === "x" ) ||
  				this._isOverAxis(
  					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
  			isOverElementWidth = ( this.options.axis === "y" ) ||
  				this._isOverAxis(
  					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
  			isOverElement = isOverElementHeight && isOverElementWidth;
  
  		if ( !isOverElement ) {
  			return false;
  		}
  
  		verticalDirection = this._getDragVerticalDirection();
  		horizontalDirection = this._getDragHorizontalDirection();
  
  		return this.floating ?
  			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
  			: ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
  
  	},
  
  	_intersectsWithSides: function( item ) {
  
  		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
  				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
  			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
  				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
  			verticalDirection = this._getDragVerticalDirection(),
  			horizontalDirection = this._getDragHorizontalDirection();
  
  		if ( this.floating && horizontalDirection ) {
  			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
  				( horizontalDirection === "left" && !isOverRightHalf ) );
  		} else {
  			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
  				( verticalDirection === "up" && !isOverBottomHalf ) );
  		}
  
  	},
  
  	_getDragVerticalDirection: function() {
  		var delta = this.positionAbs.top - this.lastPositionAbs.top;
  		return delta !== 0 && ( delta > 0 ? "down" : "up" );
  	},
  
  	_getDragHorizontalDirection: function() {
  		var delta = this.positionAbs.left - this.lastPositionAbs.left;
  		return delta !== 0 && ( delta > 0 ? "right" : "left" );
  	},
  
  	refresh: function( event ) {
  		this._refreshItems( event );
  		this._setHandleClassName();
  		this.refreshPositions();
  		return this;
  	},
  
  	_connectWith: function() {
  		var options = this.options;
  		return options.connectWith.constructor === String ?
  			[ options.connectWith ] :
  			options.connectWith;
  	},
  
  	_getItemsAsjQuery: function( connected ) {
  
  		var i, j, cur, inst,
  			items = [],
  			queries = [],
  			connectWith = this._connectWith();
  
  		if ( connectWith && connected ) {
  			for ( i = connectWith.length - 1; i >= 0; i-- ) {
  				cur = $( connectWith[ i ], this.document[ 0 ] );
  				for ( j = cur.length - 1; j >= 0; j-- ) {
  					inst = $.data( cur[ j ], this.widgetFullName );
  					if ( inst && inst !== this && !inst.options.disabled ) {
  						queries.push( [ $.isFunction( inst.options.items ) ?
  							inst.options.items.call( inst.element ) :
  							$( inst.options.items, inst.element )
  								.not( ".ui-sortable-helper" )
  								.not( ".ui-sortable-placeholder" ), inst ] );
  					}
  				}
  			}
  		}
  
  		queries.push( [ $.isFunction( this.options.items ) ?
  			this.options.items
  				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
  			$( this.options.items, this.element )
  				.not( ".ui-sortable-helper" )
  				.not( ".ui-sortable-placeholder" ), this ] );
  
  		function addItems() {
  			items.push( this );
  		}
  		for ( i = queries.length - 1; i >= 0; i-- ) {
  			queries[ i ][ 0 ].each( addItems );
  		}
  
  		return $( items );
  
  	},
  
  	_removeCurrentsFromItems: function() {
  
  		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
  
  		this.items = $.grep( this.items, function( item ) {
  			for ( var j = 0; j < list.length; j++ ) {
  				if ( list[ j ] === item.item[ 0 ] ) {
  					return false;
  				}
  			}
  			return true;
  		} );
  
  	},
  
  	_refreshItems: function( event ) {
  
  		this.items = [];
  		this.containers = [ this ];
  
  		var i, j, cur, inst, targetData, _queries, item, queriesLength,
  			items = this.items,
  			queries = [ [ $.isFunction( this.options.items ) ?
  				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
  				$( this.options.items, this.element ), this ] ],
  			connectWith = this._connectWith();
  
  		//Shouldn't be run the first time through due to massive slow-down
  		if ( connectWith && this.ready ) {
  			for ( i = connectWith.length - 1; i >= 0; i-- ) {
  				cur = $( connectWith[ i ], this.document[ 0 ] );
  				for ( j = cur.length - 1; j >= 0; j-- ) {
  					inst = $.data( cur[ j ], this.widgetFullName );
  					if ( inst && inst !== this && !inst.options.disabled ) {
  						queries.push( [ $.isFunction( inst.options.items ) ?
  							inst.options.items
  								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
  							$( inst.options.items, inst.element ), inst ] );
  						this.containers.push( inst );
  					}
  				}
  			}
  		}
  
  		for ( i = queries.length - 1; i >= 0; i-- ) {
  			targetData = queries[ i ][ 1 ];
  			_queries = queries[ i ][ 0 ];
  
  			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
  				item = $( _queries[ j ] );
  
  				// Data for target checking (mouse manager)
  				item.data( this.widgetName + "-item", targetData );
  
  				items.push( {
  					item: item,
  					instance: targetData,
  					width: 0, height: 0,
  					left: 0, top: 0
  				} );
  			}
  		}
  
  	},
  
  	refreshPositions: function( fast ) {
  
  		// Determine whether items are being displayed horizontally
  		this.floating = this.items.length ?
  			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
  			false;
  
  		//This has to be redone because due to the item being moved out/into the offsetParent,
  		// the offsetParent's position will change
  		if ( this.offsetParent && this.helper ) {
  			this.offset.parent = this._getParentOffset();
  		}
  
  		var i, item, t, p;
  
  		for ( i = this.items.length - 1; i >= 0; i-- ) {
  			item = this.items[ i ];
  
  			//We ignore calculating positions of all connected containers when we're not over them
  			if ( item.instance !== this.currentContainer && this.currentContainer &&
  					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
  				continue;
  			}
  
  			t = this.options.toleranceElement ?
  				$( this.options.toleranceElement, item.item ) :
  				item.item;
  
  			if ( !fast ) {
  				item.width = t.outerWidth();
  				item.height = t.outerHeight();
  			}
  
  			p = t.offset();
  			item.left = p.left;
  			item.top = p.top;
  		}
  
  		if ( this.options.custom && this.options.custom.refreshContainers ) {
  			this.options.custom.refreshContainers.call( this );
  		} else {
  			for ( i = this.containers.length - 1; i >= 0; i-- ) {
  				p = this.containers[ i ].element.offset();
  				this.containers[ i ].containerCache.left = p.left;
  				this.containers[ i ].containerCache.top = p.top;
  				this.containers[ i ].containerCache.width =
  					this.containers[ i ].element.outerWidth();
  				this.containers[ i ].containerCache.height =
  					this.containers[ i ].element.outerHeight();
  			}
  		}
  
  		return this;
  	},
  
  	_createPlaceholder: function( that ) {
  		that = that || this;
  		var className,
  			o = that.options;
  
  		if ( !o.placeholder || o.placeholder.constructor === String ) {
  			className = o.placeholder;
  			o.placeholder = {
  				element: function() {
  
  					var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),
  						element = $( "<" + nodeName + ">", that.document[ 0 ] );
  
  						that._addClass( element, "ui-sortable-placeholder",
  								className || that.currentItem[ 0 ].className )
  							._removeClass( element, "ui-sortable-helper" );
  
  					if ( nodeName === "tbody" ) {
  						that._createTrPlaceholder(
  							that.currentItem.find( "tr" ).eq( 0 ),
  							$( "<tr>", that.document[ 0 ] ).appendTo( element )
  						);
  					} else if ( nodeName === "tr" ) {
  						that._createTrPlaceholder( that.currentItem, element );
  					} else if ( nodeName === "img" ) {
  						element.attr( "src", that.currentItem.attr( "src" ) );
  					}
  
  					if ( !className ) {
  						element.css( "visibility", "hidden" );
  					}
  
  					return element;
  				},
  				update: function( container, p ) {
  
  					// 1. If a className is set as 'placeholder option, we don't force sizes -
  					// the class is responsible for that
  					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
  					// class name is specified
  					if ( className && !o.forcePlaceholderSize ) {
  						return;
  					}
  
  					//If the element doesn't have a actual height by itself (without styles coming
  					// from a stylesheet), it receives the inline height from the dragged item
  					if ( !p.height() ) {
  						p.height(
  							that.currentItem.innerHeight() -
  							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
  							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
  					}
  					if ( !p.width() ) {
  						p.width(
  							that.currentItem.innerWidth() -
  							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
  							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
  					}
  				}
  			};
  		}
  
  		//Create the placeholder
  		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
  
  		//Append it after the actual current item
  		that.currentItem.after( that.placeholder );
  
  		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
  		o.placeholder.update( that, that.placeholder );
  
  	},
  
  	_createTrPlaceholder: function( sourceTr, targetTr ) {
  		var that = this;
  
  		sourceTr.children().each( function() {
  			$( "<td>&#160;</td>", that.document[ 0 ] )
  				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
  				.appendTo( targetTr );
  		} );
  	},
  
  	_contactContainers: function( event ) {
  		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
  			floating, axis,
  			innermostContainer = null,
  			innermostIndex = null;
  
  		// Get innermost container that intersects with item
  		for ( i = this.containers.length - 1; i >= 0; i-- ) {
  
  			// Never consider a container that's located within the item itself
  			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
  				continue;
  			}
  
  			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
  
  				// If we've already found a container and it's more "inner" than this, then continue
  				if ( innermostContainer &&
  						$.contains(
  							this.containers[ i ].element[ 0 ],
  							innermostContainer.element[ 0 ] ) ) {
  					continue;
  				}
  
  				innermostContainer = this.containers[ i ];
  				innermostIndex = i;
  
  			} else {
  
  				// container doesn't intersect. trigger "out" event if necessary
  				if ( this.containers[ i ].containerCache.over ) {
  					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
  					this.containers[ i ].containerCache.over = 0;
  				}
  			}
  
  		}
  
  		// If no intersecting containers found, return
  		if ( !innermostContainer ) {
  			return;
  		}
  
  		// Move the item into the container if it's not there already
  		if ( this.containers.length === 1 ) {
  			if ( !this.containers[ innermostIndex ].containerCache.over ) {
  				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
  				this.containers[ innermostIndex ].containerCache.over = 1;
  			}
  		} else {
  
  			// When entering a new container, we will find the item with the least distance and
  			// append our item near it
  			dist = 10000;
  			itemWithLeastDistance = null;
  			floating = innermostContainer.floating || this._isFloating( this.currentItem );
  			posProperty = floating ? "left" : "top";
  			sizeProperty = floating ? "width" : "height";
  			axis = floating ? "pageX" : "pageY";
  
  			for ( j = this.items.length - 1; j >= 0; j-- ) {
  				if ( !$.contains(
  						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
  				) {
  					continue;
  				}
  				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
  					continue;
  				}
  
  				cur = this.items[ j ].item.offset()[ posProperty ];
  				nearBottom = false;
  				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
  					nearBottom = true;
  				}
  
  				if ( Math.abs( event[ axis ] - cur ) < dist ) {
  					dist = Math.abs( event[ axis ] - cur );
  					itemWithLeastDistance = this.items[ j ];
  					this.direction = nearBottom ? "up" : "down";
  				}
  			}
  
  			//Check if dropOnEmpty is enabled
  			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
  				return;
  			}
  
  			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
  				if ( !this.currentContainer.containerCache.over ) {
  					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
  					this.currentContainer.containerCache.over = 1;
  				}
  				return;
  			}
  
  			itemWithLeastDistance ?
  				this._rearrange( event, itemWithLeastDistance, null, true ) :
  				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
  			this._trigger( "change", event, this._uiHash() );
  			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
  			this.currentContainer = this.containers[ innermostIndex ];
  
  			//Update the placeholder
  			this.options.placeholder.update( this.currentContainer, this.placeholder );
  
  			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
  			this.containers[ innermostIndex ].containerCache.over = 1;
  		}
  
  	},
  
  	_createHelper: function( event ) {
  
  		var o = this.options,
  			helper = $.isFunction( o.helper ) ?
  				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
  				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
  
  		//Add the helper to the DOM if that didn't happen already
  		if ( !helper.parents( "body" ).length ) {
  			$( o.appendTo !== "parent" ?
  				o.appendTo :
  				this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );
  		}
  
  		if ( helper[ 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" )
  			};
  		}
  
  		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
  			helper.width( this.currentItem.width() );
  		}
  		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
  			helper.height( this.currentItem.height() );
  		}
  
  		return helper;
  
  	},
  
  	_adjustOffsetFromHelper: function( obj ) {
  		if ( typeof obj === "string" ) {
  			obj = obj.split( " " );
  		}
  		if ( $.isArray( obj ) ) {
  			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
  		}
  		if ( "left" in obj ) {
  			this.offset.click.left = obj.left + this.margins.left;
  		}
  		if ( "right" in obj ) {
  			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
  		}
  		if ( "top" in obj ) {
  			this.offset.click.top = obj.top + this.margins.top;
  		}
  		if ( "bottom" in obj ) {
  			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
  		}
  	},
  
  	_getParentOffset: function() {
  
  		//Get the offsetParent and cache its position
  		this.offsetParent = this.helper.offsetParent();
  		var po = this.offsetParent.offset();
  
  		// This is a special case where we need to modify a offset calculated on start, since the
  		// following happened:
  		// 1. The position of the helper is absolute, so it's position is calculated based on the
  		// next positioned parent
  		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
  		// the document, which means that the scroll is included in the initial calculation of the
  		// offset of the parent, and never recalculated upon drag
  		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
  			po.left += this.scrollParent.scrollLeft();
  			po.top += this.scrollParent.scrollTop();
  		}
  
  		// This needs to be actually done for all browsers, since pageX/pageY includes this
  		// information with an ugly IE fix
  		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
  				( this.offsetParent[ 0 ].tagName &&
  				this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
  			po = { top: 0, left: 0 };
  		}
  
  		return {
  			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
  			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
  		};
  
  	},
  
  	_getRelativeOffset: function() {
  
  		if ( this.cssPosition === "relative" ) {
  			var p = this.currentItem.position();
  			return {
  				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
  					this.scrollParent.scrollTop(),
  				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
  					this.scrollParent.scrollLeft()
  			};
  		} else {
  			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 ce, co, over,
  			o = this.options;
  		if ( o.containment === "parent" ) {
  			o.containment = this.helper[ 0 ].parentNode;
  		}
  		if ( o.containment === "document" || o.containment === "window" ) {
  			this.containment = [
  				0 - this.offset.relative.left - this.offset.parent.left,
  				0 - this.offset.relative.top - this.offset.parent.top,
  				o.containment === "document" ?
  					this.document.width() :
  					this.window.width() - this.helperProportions.width - this.margins.left,
  				( o.containment === "document" ?
  					( this.document.height() || document.body.parentNode.scrollHeight ) :
  					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
  				) - this.helperProportions.height - this.margins.top
  			];
  		}
  
  		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
  			ce = $( o.containment )[ 0 ];
  			co = $( o.containment ).offset();
  			over = ( $( ce ).css( "overflow" ) !== "hidden" );
  
  			this.containment = [
  				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
  					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
  				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
  					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
  				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
  					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
  					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
  					this.helperProportions.width - this.margins.left,
  				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
  					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
  					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
  					this.helperProportions.height - this.margins.top
  			];
  		}
  
  	},
  
  	_convertPositionTo: function( d, pos ) {
  
  		if ( !pos ) {
  			pos = this.position;
  		}
  		var mod = d === "absolute" ? 1 : -1,
  			scroll = this.cssPosition === "absolute" &&
  				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
  					this.offsetParent :
  					this.scrollParent,
  			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
  
  		return {
  			top: (
  
  				// The absolute mouse position
  				pos.top	+
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.top * mod +
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.top * mod -
  				( ( this.cssPosition === "fixed" ?
  					-this.scrollParent.scrollTop() :
  					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
  			),
  			left: (
  
  				// The absolute mouse position
  				pos.left +
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.left * mod +
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.left * mod	-
  				( ( this.cssPosition === "fixed" ?
  					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
  					scroll.scrollLeft() ) * mod )
  			)
  		};
  
  	},
  
  	_generatePosition: function( event ) {
  
  		var top, left,
  			o = this.options,
  			pageX = event.pageX,
  			pageY = event.pageY,
  			scroll = this.cssPosition === "absolute" &&
  				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
  					this.offsetParent :
  					this.scrollParent,
  				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
  
  		// This is another very weird special case that only happens for relative elements:
  		// 1. If the css position is relative
  		// 2. and the scroll parent is the document or similar to the offset parent
  		// we have to refresh the relative offset during the scroll so there are no jumps
  		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
  			this.offset.relative = this._getRelativeOffset();
  		}
  
  		/*
  		 * - Position constraining -
  		 * Constrain the position to a mix of grid, containment.
  		 */
  
  		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
  
  			if ( this.containment ) {
  				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
  					pageX = this.containment[ 0 ] + this.offset.click.left;
  				}
  				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
  					pageY = this.containment[ 1 ] + this.offset.click.top;
  				}
  				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
  					pageX = this.containment[ 2 ] + this.offset.click.left;
  				}
  				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
  					pageY = this.containment[ 3 ] + this.offset.click.top;
  				}
  			}
  
  			if ( o.grid ) {
  				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
  					o.grid[ 1 ] ) * o.grid[ 1 ];
  				pageY = this.containment ?
  					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
  						top - this.offset.click.top <= this.containment[ 3 ] ) ?
  							top :
  							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
  								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
  								top;
  
  				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
  					o.grid[ 0 ] ) * o.grid[ 0 ];
  				pageX = this.containment ?
  					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
  						left - this.offset.click.left <= this.containment[ 2 ] ) ?
  							left :
  							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
  								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
  								left;
  			}
  
  		}
  
  		return {
  			top: (
  
  				// The absolute mouse position
  				pageY -
  
  				// Click offset (relative to the element)
  				this.offset.click.top -
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.top -
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.top +
  				( ( this.cssPosition === "fixed" ?
  					-this.scrollParent.scrollTop() :
  					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
  			),
  			left: (
  
  				// The absolute mouse position
  				pageX -
  
  				// Click offset (relative to the element)
  				this.offset.click.left -
  
  				// Only for relative positioned nodes: Relative offset from element to offset parent
  				this.offset.relative.left -
  
  				// The offsetParent's offset without borders (offset + border)
  				this.offset.parent.left +
  				( ( this.cssPosition === "fixed" ?
  					-this.scrollParent.scrollLeft() :
  					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
  			)
  		};
  
  	},
  
  	_rearrange: function( event, i, a, hardRefresh ) {
  
  		a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :
  			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
  				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
  
  		//Various things done here to improve the performance:
  		// 1. we create a setTimeout, that calls refreshPositions
  		// 2. on the instance, we have a counter variable, that get's higher after every append
  		// 3. on the local scope, we copy the counter variable, and check in the timeout,
  		// if it's still the same
  		// 4. this lets only the last addition to the timeout stack through
  		this.counter = this.counter ? ++this.counter : 1;
  		var counter = this.counter;
  
  		this._delay( function() {
  			if ( counter === this.counter ) {
  
  				//Precompute after each DOM insertion, NOT on mousemove
  				this.refreshPositions( !hardRefresh );
  			}
  		} );
  
  	},
  
  	_clear: function( event, noPropagation ) {
  
  		this.reverting = false;
  
  		// We delay all events that have to be triggered to after the point where the placeholder
  		// has been removed and everything else normalized again
  		var i,
  			delayedTriggers = [];
  
  		// We first have to update the dom position of the actual currentItem
  		// Note: don't do it if the current item is already removed (by a user), or it gets
  		// reappended (see #4088)
  		if ( !this._noFinalSort && this.currentItem.parent().length ) {
  			this.placeholder.before( this.currentItem );
  		}
  		this._noFinalSort = null;
  
  		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
  			for ( i in this._storedCSS ) {
  				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
  					this._storedCSS[ i ] = "";
  				}
  			}
  			this.currentItem.css( this._storedCSS );
  			this._removeClass( this.currentItem, "ui-sortable-helper" );
  		} else {
  			this.currentItem.show();
  		}
  
  		if ( this.fromOutside && !noPropagation ) {
  			delayedTriggers.push( function( event ) {
  				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
  			} );
  		}
  		if ( ( this.fromOutside ||
  				this.domPosition.prev !==
  				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
  				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
  
  			// Trigger update callback if the DOM position has changed
  			delayedTriggers.push( function( event ) {
  				this._trigger( "update", event, this._uiHash() );
  			} );
  		}
  
  		// Check if the items Container has Changed and trigger appropriate
  		// events.
  		if ( this !== this.currentContainer ) {
  			if ( !noPropagation ) {
  				delayedTriggers.push( function( event ) {
  					this._trigger( "remove", event, this._uiHash() );
  				} );
  				delayedTriggers.push( ( function( c ) {
  					return function( event ) {
  						c._trigger( "receive", event, this._uiHash( this ) );
  					};
  				} ).call( this, this.currentContainer ) );
  				delayedTriggers.push( ( function( c ) {
  					return function( event ) {
  						c._trigger( "update", event, this._uiHash( this ) );
  					};
  				} ).call( this, this.currentContainer ) );
  			}
  		}
  
  		//Post events to containers
  		function delayEvent( type, instance, container ) {
  			return function( event ) {
  				container._trigger( type, event, instance._uiHash( instance ) );
  			};
  		}
  		for ( i = this.containers.length - 1; i >= 0; i-- ) {
  			if ( !noPropagation ) {
  				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
  			}
  			if ( this.containers[ i ].containerCache.over ) {
  				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
  				this.containers[ i ].containerCache.over = 0;
  			}
  		}
  
  		//Do what was originally in plugins
  		if ( this.storedCursor ) {
  			this.document.find( "body" ).css( "cursor", this.storedCursor );
  			this.storedStylesheet.remove();
  		}
  		if ( this._storedOpacity ) {
  			this.helper.css( "opacity", this._storedOpacity );
  		}
  		if ( this._storedZIndex ) {
  			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
  		}
  
  		this.dragging = false;
  
  		if ( !noPropagation ) {
  			this._trigger( "beforeStop", event, this._uiHash() );
  		}
  
  		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
  		// it unbinds ALL events from the original node!
  		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
  
  		if ( !this.cancelHelperRemoval ) {
  			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
  				this.helper.remove();
  			}
  			this.helper = null;
  		}
  
  		if ( !noPropagation ) {
  			for ( i = 0; i < delayedTriggers.length; i++ ) {
  
  				// Trigger all delayed events
  				delayedTriggers[ i ].call( this, event );
  			}
  			this._trigger( "stop", event, this._uiHash() );
  		}
  
  		this.fromOutside = false;
  		return !this.cancelHelperRemoval;
  
  	},
  
  	_trigger: function() {
  		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
  			this.cancel();
  		}
  	},
  
  	_uiHash: function( _inst ) {
  		var inst = _inst || this;
  		return {
  			helper: inst.helper,
  			placeholder: inst.placeholder || $( [] ),
  			position: inst.position,
  			originalPosition: inst.originalPosition,
  			offset: inst.positionAbs,
  			item: inst.currentItem,
  			sender: _inst ? _inst.element : null
  		};
  	}
  
  } );
  
  
  /*!
   * jQuery UI Controlgroup 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Controlgroup
  //>>group: Widgets
  //>>description: Visually groups form control widgets
  //>>docs: http://api.jqueryui.com/controlgroup/
  //>>demos: http://jqueryui.com/controlgroup/
  //>>css.structure: ../../themes/base/core.css
  //>>css.structure: ../../themes/base/controlgroup.css
  //>>css.theme: ../../themes/base/theme.css
  
  
  var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
  
  var widgetsControlgroup = $.widget( "ui.controlgroup", {
  	version: "1.12.1",
  	defaultElement: "<div>",
  	options: {
  		direction: "horizontal",
  		disabled: null,
  		onlyVisible: true,
  		items: {
  			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
  			"controlgroupLabel": ".ui-controlgroup-label",
  			"checkboxradio": "input[type='checkbox'], input[type='radio']",
  			"selectmenu": "select",
  			"spinner": ".ui-spinner-input"
  		}
  	},
  
  	_create: function() {
  		this._enhance();
  	},
  
  	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
  	_enhance: function() {
  		this.element.attr( "role", "toolbar" );
  		this.refresh();
  	},
  
  	_destroy: function() {
  		this._callChildMethod( "destroy" );
  		this.childWidgets.removeData( "ui-controlgroup-data" );
  		this.element.removeAttr( "role" );
  		if ( this.options.items.controlgroupLabel ) {
  			this.element
  				.find( this.options.items.controlgroupLabel )
  				.find( ".ui-controlgroup-label-contents" )
  				.contents().unwrap();
  		}
  	},
  
  	_initWidgets: function() {
  		var that = this,
  			childWidgets = [];
  
  		// First we iterate over each of the items options
  		$.each( this.options.items, function( widget, selector ) {
  			var labels;
  			var options = {};
  
  			// Make sure the widget has a selector set
  			if ( !selector ) {
  				return;
  			}
  
  			if ( widget === "controlgroupLabel" ) {
  				labels = that.element.find( selector );
  				labels.each( function() {
  					var element = $( this );
  
  					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
  						return;
  					}
  					element.contents()
  						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
  				} );
  				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
  				childWidgets = childWidgets.concat( labels.get() );
  				return;
  			}
  
  			// Make sure the widget actually exists
  			if ( !$.fn[ widget ] ) {
  				return;
  			}
  
  			// We assume everything is in the middle to start because we can't determine
  			// first / last elements until all enhancments are done.
  			if ( that[ "_" + widget + "Options" ] ) {
  				options = that[ "_" + widget + "Options" ]( "middle" );
  			} else {
  				options = { classes: {} };
  			}
  
  			// Find instances of this widget inside controlgroup and init them
  			that.element
  				.find( selector )
  				.each( function() {
  					var element = $( this );
  					var instance = element[ widget ]( "instance" );
  
  					// We need to clone the default options for this type of widget to avoid
  					// polluting the variable options which has a wider scope than a single widget.
  					var instanceOptions = $.widget.extend( {}, options );
  
  					// If the button is the child of a spinner ignore it
  					// TODO: Find a more generic solution
  					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
  						return;
  					}
  
  					// Create the widget if it doesn't exist
  					if ( !instance ) {
  						instance = element[ widget ]()[ widget ]( "instance" );
  					}
  					if ( instance ) {
  						instanceOptions.classes =
  							that._resolveClassesValues( instanceOptions.classes, instance );
  					}
  					element[ widget ]( instanceOptions );
  
  					// Store an instance of the controlgroup to be able to reference
  					// from the outermost element for changing options and refresh
  					var widgetElement = element[ widget ]( "widget" );
  					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
  						instance ? instance : element[ widget ]( "instance" ) );
  
  					childWidgets.push( widgetElement[ 0 ] );
  				} );
  		} );
  
  		this.childWidgets = $( $.unique( childWidgets ) );
  		this._addClass( this.childWidgets, "ui-controlgroup-item" );
  	},
  
  	_callChildMethod: function( method ) {
  		this.childWidgets.each( function() {
  			var element = $( this ),
  				data = element.data( "ui-controlgroup-data" );
  			if ( data && data[ method ] ) {
  				data[ method ]();
  			}
  		} );
  	},
  
  	_updateCornerClass: function( element, position ) {
  		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
  		var add = this._buildSimpleOptions( position, "label" ).classes.label;
  
  		this._removeClass( element, null, remove );
  		this._addClass( element, null, add );
  	},
  
  	_buildSimpleOptions: function( position, key ) {
  		var direction = this.options.direction === "vertical";
  		var result = {
  			classes: {}
  		};
  		result.classes[ key ] = {
  			"middle": "",
  			"first": "ui-corner-" + ( direction ? "top" : "left" ),
  			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
  			"only": "ui-corner-all"
  		}[ position ];
  
  		return result;
  	},
  
  	_spinnerOptions: function( position ) {
  		var options = this._buildSimpleOptions( position, "ui-spinner" );
  
  		options.classes[ "ui-spinner-up" ] = "";
  		options.classes[ "ui-spinner-down" ] = "";
  
  		return options;
  	},
  
  	_buttonOptions: function( position ) {
  		return this._buildSimpleOptions( position, "ui-button" );
  	},
  
  	_checkboxradioOptions: function( position ) {
  		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
  	},
  
  	_selectmenuOptions: function( position ) {
  		var direction = this.options.direction === "vertical";
  		return {
  			width: direction ? "auto" : false,
  			classes: {
  				middle: {
  					"ui-selectmenu-button-open": "",
  					"ui-selectmenu-button-closed": ""
  				},
  				first: {
  					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
  					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
  				},
  				last: {
  					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
  					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
  				},
  				only: {
  					"ui-selectmenu-button-open": "ui-corner-top",
  					"ui-selectmenu-button-closed": "ui-corner-all"
  				}
  
  			}[ position ]
  		};
  	},
  
  	_resolveClassesValues: function( classes, instance ) {
  		var result = {};
  		$.each( classes, function( key ) {
  			var current = instance.options.classes[ key ] || "";
  			current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
  			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
  		} );
  		return result;
  	},
  
  	_setOption: function( key, value ) {
  		if ( key === "direction" ) {
  			this._removeClass( "ui-controlgroup-" + this.options.direction );
  		}
  
  		this._super( key, value );
  		if ( key === "disabled" ) {
  			this._callChildMethod( value ? "disable" : "enable" );
  			return;
  		}
  
  		this.refresh();
  	},
  
  	refresh: function() {
  		var children,
  			that = this;
  
  		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
  
  		if ( this.options.direction === "horizontal" ) {
  			this._addClass( null, "ui-helper-clearfix" );
  		}
  		this._initWidgets();
  
  		children = this.childWidgets;
  
  		// We filter here because we need to track all childWidgets not just the visible ones
  		if ( this.options.onlyVisible ) {
  			children = children.filter( ":visible" );
  		}
  
  		if ( children.length ) {
  
  			// We do this last because we need to make sure all enhancment is done
  			// before determining first and last
  			$.each( [ "first", "last" ], function( index, value ) {
  				var instance = children[ value ]().data( "ui-controlgroup-data" );
  
  				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
  					var options = that[ "_" + instance.widgetName + "Options" ](
  						children.length === 1 ? "only" : value
  					);
  					options.classes = that._resolveClassesValues( options.classes, instance );
  					instance.element[ instance.widgetName ]( options );
  				} else {
  					that._updateCornerClass( children[ value ](), value );
  				}
  			} );
  
  			// Finally call the refresh method on each of the child widgets.
  			this._callChildMethod( "refresh" );
  		}
  	}
  } );
  
  /*!
   * jQuery UI Checkboxradio 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Checkboxradio
  //>>group: Widgets
  //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
  //>>docs: http://api.jqueryui.com/checkboxradio/
  //>>demos: http://jqueryui.com/checkboxradio/
  //>>css.structure: ../../themes/base/core.css
  //>>css.structure: ../../themes/base/button.css
  //>>css.structure: ../../themes/base/checkboxradio.css
  //>>css.theme: ../../themes/base/theme.css
  
  
  
  $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
  	version: "1.12.1",
  	options: {
  		disabled: null,
  		label: null,
  		icon: true,
  		classes: {
  			"ui-checkboxradio-label": "ui-corner-all",
  			"ui-checkboxradio-icon": "ui-corner-all"
  		}
  	},
  
  	_getCreateOptions: function() {
  		var disabled, labels;
  		var that = this;
  		var options = this._super() || {};
  
  		// We read the type here, because it makes more sense to throw a element type error first,
  		// rather then the error for lack of a label. Often if its the wrong type, it
  		// won't have a label (e.g. calling on a div, btn, etc)
  		this._readType();
  
  		labels = this.element.labels();
  
  		// If there are multiple labels, use the last one
  		this.label = $( labels[ labels.length - 1 ] );
  		if ( !this.label.length ) {
  			$.error( "No label found for checkboxradio widget" );
  		}
  
  		this.originalLabel = "";
  
  		// We need to get the label text but this may also need to make sure it does not contain the
  		// input itself.
  		this.label.contents().not( this.element[ 0 ] ).each( function() {
  
  			// The label contents could be text, html, or a mix. We concat each element to get a
  			// string representation of the label, without the input as part of it.
  			that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
  		} );
  
  		// Set the label option if we found label text
  		if ( this.originalLabel ) {
  			options.label = this.originalLabel;
  		}
  
  		disabled = this.element[ 0 ].disabled;
  		if ( disabled != null ) {
  			options.disabled = disabled;
  		}
  		return options;
  	},
  
  	_create: function() {
  		var checked = this.element[ 0 ].checked;
  
  		this._bindFormResetHandler();
  
  		if ( this.options.disabled == null ) {
  			this.options.disabled = this.element[ 0 ].disabled;
  		}
  
  		this._setOption( "disabled", this.options.disabled );
  		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
  		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
  
  		if ( this.type === "radio" ) {
  			this._addClass( this.label, "ui-checkboxradio-radio-label" );
  		}
  
  		if ( this.options.label && this.options.label !== this.originalLabel ) {
  			this._updateLabel();
  		} else if ( this.originalLabel ) {
  			this.options.label = this.originalLabel;
  		}
  
  		this._enhance();
  
  		if ( checked ) {
  			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
  			if ( this.icon ) {
  				this._addClass( this.icon, null, "ui-state-hover" );
  			}
  		}
  
  		this._on( {
  			change: "_toggleClasses",
  			focus: function() {
  				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
  			},
  			blur: function() {
  				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
  			}
  		} );
  	},
  
  	_readType: function() {
  		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
  		this.type = this.element[ 0 ].type;
  		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
  			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
  				" and element.type=" + this.type );
  		}
  	},
  
  	// Support jQuery Mobile enhanced option
  	_enhance: function() {
  		this._updateIcon( this.element[ 0 ].checked );
  	},
  
  	widget: function() {
  		return this.label;
  	},
  
  	_getRadioGroup: function() {
  		var group;
  		var name = this.element[ 0 ].name;
  		var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
  
  		if ( !name ) {
  			return $( [] );
  		}
  
  		if ( this.form.length ) {
  			group = $( this.form[ 0 ].elements ).filter( nameSelector );
  		} else {
  
  			// Not inside a form, check all inputs that also are not inside a form
  			group = $( nameSelector ).filter( function() {
  				return $( this ).form().length === 0;
  			} );
  		}
  
  		return group.not( this.element );
  	},
  
  	_toggleClasses: function() {
  		var checked = this.element[ 0 ].checked;
  		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
  
  		if ( this.options.icon && this.type === "checkbox" ) {
  			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
  				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
  		}
  
  		if ( this.type === "radio" ) {
  			this._getRadioGroup()
  				.each( function() {
  					var instance = $( this ).checkboxradio( "instance" );
  
  					if ( instance ) {
  						instance._removeClass( instance.label,
  							"ui-checkboxradio-checked", "ui-state-active" );
  					}
  				} );
  		}
  	},
  
  	_destroy: function() {
  		this._unbindFormResetHandler();
  
  		if ( this.icon ) {
  			this.icon.remove();
  			this.iconSpace.remove();
  		}
  	},
  
  	_setOption: function( key, value ) {
  
  		// We don't allow the value to be set to nothing
  		if ( key === "label" && !value ) {
  			return;
  		}
  
  		this._super( key, value );
  
  		if ( key === "disabled" ) {
  			this._toggleClass( this.label, null, "ui-state-disabled", value );
  			this.element[ 0 ].disabled = value;
  
  			// Don't refresh when setting disabled
  			return;
  		}
  		this.refresh();
  	},
  
  	_updateIcon: function( checked ) {
  		var toAdd = "ui-icon ui-icon-background ";
  
  		if ( this.options.icon ) {
  			if ( !this.icon ) {
  				this.icon = $( "<span>" );
  				this.iconSpace = $( "<span> </span>" );
  				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
  			}
  
  			if ( this.type === "checkbox" ) {
  				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
  				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
  			} else {
  				toAdd += "ui-icon-blank";
  			}
  			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
  			if ( !checked ) {
  				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
  			}
  			this.icon.prependTo( this.label ).after( this.iconSpace );
  		} else if ( this.icon !== undefined ) {
  			this.icon.remove();
  			this.iconSpace.remove();
  			delete this.icon;
  		}
  	},
  
  	_updateLabel: function() {
  
  		// Remove the contents of the label ( minus the icon, icon space, and input )
  		var contents = this.label.contents().not( this.element[ 0 ] );
  		if ( this.icon ) {
  			contents = contents.not( this.icon[ 0 ] );
  		}
  		if ( this.iconSpace ) {
  			contents = contents.not( this.iconSpace[ 0 ] );
  		}
  		contents.remove();
  
  		this.label.append( this.options.label );
  	},
  
  	refresh: function() {
  		var checked = this.element[ 0 ].checked,
  			isDisabled = this.element[ 0 ].disabled;
  
  		this._updateIcon( checked );
  		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
  		if ( this.options.label !== null ) {
  			this._updateLabel();
  		}
  
  		if ( isDisabled !== this.options.disabled ) {
  			this._setOptions( { "disabled": isDisabled } );
  		}
  	}
  
  } ] );
  
  var widgetsCheckboxradio = $.ui.checkboxradio;
  
  
  /*!
   * jQuery UI Button 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Button
  //>>group: Widgets
  //>>description: Enhances a form with themeable buttons.
  //>>docs: http://api.jqueryui.com/button/
  //>>demos: http://jqueryui.com/button/
  //>>css.structure: ../../themes/base/core.css
  //>>css.structure: ../../themes/base/button.css
  //>>css.theme: ../../themes/base/theme.css
  
  
  
  $.widget( "ui.button", {
  	version: "1.12.1",
  	defaultElement: "<button>",
  	options: {
  		classes: {
  			"ui-button": "ui-corner-all"
  		},
  		disabled: null,
  		icon: null,
  		iconPosition: "beginning",
  		label: null,
  		showLabel: true
  	},
  
  	_getCreateOptions: function() {
  		var disabled,
  
  			// This is to support cases like in jQuery Mobile where the base widget does have
  			// an implementation of _getCreateOptions
  			options = this._super() || {};
  
  		this.isInput = this.element.is( "input" );
  
  		disabled = this.element[ 0 ].disabled;
  		if ( disabled != null ) {
  			options.disabled = disabled;
  		}
  
  		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
  		if ( this.originalLabel ) {
  			options.label = this.originalLabel;
  		}
  
  		return options;
  	},
  
  	_create: function() {
  		if ( !this.option.showLabel & !this.options.icon ) {
  			this.options.showLabel = true;
  		}
  
  		// We have to check the option again here even though we did in _getCreateOptions,
  		// because null may have been passed on init which would override what was set in
  		// _getCreateOptions
  		if ( this.options.disabled == null ) {
  			this.options.disabled = this.element[ 0 ].disabled || false;
  		}
  
  		this.hasTitle = !!this.element.attr( "title" );
  
  		// Check to see if the label needs to be set or if its already correct
  		if ( this.options.label && this.options.label !== this.originalLabel ) {
  			if ( this.isInput ) {
  				this.element.val( this.options.label );
  			} else {
  				this.element.html( this.options.label );
  			}
  		}
  		this._addClass( "ui-button", "ui-widget" );
  		this._setOption( "disabled", this.options.disabled );
  		this._enhance();
  
  		if ( this.element.is( "a" ) ) {
  			this._on( {
  				"keyup": function( event ) {
  					if ( event.keyCode === $.ui.keyCode.SPACE ) {
  						event.preventDefault();
  
  						// Support: PhantomJS <= 1.9, IE 8 Only
  						// If a native click is available use it so we actually cause navigation
  						// otherwise just trigger a click event
  						if ( this.element[ 0 ].click ) {
  							this.element[ 0 ].click();
  						} else {
  							this.element.trigger( "click" );
  						}
  					}
  				}
  			} );
  		}
  	},
  
  	_enhance: function() {
  		if ( !this.element.is( "button" ) ) {
  			this.element.attr( "role", "button" );
  		}
  
  		if ( this.options.icon ) {
  			this._updateIcon( "icon", this.options.icon );
  			this._updateTooltip();
  		}
  	},
  
  	_updateTooltip: function() {
  		this.title = this.element.attr( "title" );
  
  		if ( !this.options.showLabel && !this.title ) {
  			this.element.attr( "title", this.options.label );
  		}
  	},
  
  	_updateIcon: function( option, value ) {
  		var icon = option !== "iconPosition",
  			position = icon ? this.options.iconPosition : value,
  			displayBlock = position === "top" || position === "bottom";
  
  		// Create icon
  		if ( !this.icon ) {
  			this.icon = $( "<span>" );
  
  			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
  
  			if ( !this.options.showLabel ) {
  				this._addClass( "ui-button-icon-only" );
  			}
  		} else if ( icon ) {
  
  			// If we are updating the icon remove the old icon class
  			this._removeClass( this.icon, null, this.options.icon );
  		}
  
  		// If we are updating the icon add the new icon class
  		if ( icon ) {
  			this._addClass( this.icon, null, value );
  		}
  
  		this._attachIcon( position );
  
  		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
  		// the iconSpace if there is one.
  		if ( displayBlock ) {
  			this._addClass( this.icon, null, "ui-widget-icon-block" );
  			if ( this.iconSpace ) {
  				this.iconSpace.remove();
  			}
  		} else {
  
  			// Position is beginning or end so remove the ui-widget-icon-block class and add the
  			// space if it does not exist
  			if ( !this.iconSpace ) {
  				this.iconSpace = $( "<span> </span>" );
  				this._addClass( this.iconSpace, "ui-button-icon-space" );
  			}
  			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
  			this._attachIconSpace( position );
  		}
  	},
  
  	_destroy: function() {
  		this.element.removeAttr( "role" );
  
  		if ( this.icon ) {
  			this.icon.remove();
  		}
  		if ( this.iconSpace ) {
  			this.iconSpace.remove();
  		}
  		if ( !this.hasTitle ) {
  			this.element.removeAttr( "title" );
  		}
  	},
  
  	_attachIconSpace: function( iconPosition ) {
  		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
  	},
  
  	_attachIcon: function( iconPosition ) {
  		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
  	},
  
  	_setOptions: function( options ) {
  		var newShowLabel = options.showLabel === undefined ?
  				this.options.showLabel :
  				options.showLabel,
  			newIcon = options.icon === undefined ? this.options.icon : options.icon;
  
  		if ( !newShowLabel && !newIcon ) {
  			options.showLabel = true;
  		}
  		this._super( options );
  	},
  
  	_setOption: function( key, value ) {
  		if ( key === "icon" ) {
  			if ( value ) {
  				this._updateIcon( key, value );
  			} else if ( this.icon ) {
  				this.icon.remove();
  				if ( this.iconSpace ) {
  					this.iconSpace.remove();
  				}
  			}
  		}
  
  		if ( key === "iconPosition" ) {
  			this._updateIcon( key, value );
  		}
  
  		// Make sure we can't end up with a button that has neither text nor icon
  		if ( key === "showLabel" ) {
  				this._toggleClass( "ui-button-icon-only", null, !value );
  				this._updateTooltip();
  		}
  
  		if ( key === "label" ) {
  			if ( this.isInput ) {
  				this.element.val( value );
  			} else {
  
  				// If there is an icon, append it, else nothing then append the value
  				// this avoids removal of the icon when setting label text
  				this.element.html( value );
  				if ( this.icon ) {
  					this._attachIcon( this.options.iconPosition );
  					this._attachIconSpace( this.options.iconPosition );
  				}
  			}
  		}
  
  		this._super( key, value );
  
  		if ( key === "disabled" ) {
  			this._toggleClass( null, "ui-state-disabled", value );
  			this.element[ 0 ].disabled = value;
  			if ( value ) {
  				this.element.blur();
  			}
  		}
  	},
  
  	refresh: function() {
  
  		// Make sure to only check disabled if its an element that supports this otherwise
  		// check for the disabled class to determine state
  		var isDisabled = this.element.is( "input, button" ) ?
  			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
  
  		if ( isDisabled !== this.options.disabled ) {
  			this._setOptions( { disabled: isDisabled } );
  		}
  
  		this._updateTooltip();
  	}
  } );
  
  // DEPRECATED
  if ( $.uiBackCompat !== false ) {
  
  	// Text and Icons options
  	$.widget( "ui.button", $.ui.button, {
  		options: {
  			text: true,
  			icons: {
  				primary: null,
  				secondary: null
  			}
  		},
  
  		_create: function() {
  			if ( this.options.showLabel && !this.options.text ) {
  				this.options.showLabel = this.options.text;
  			}
  			if ( !this.options.showLabel && this.options.text ) {
  				this.options.text = this.options.showLabel;
  			}
  			if ( !this.options.icon && ( this.options.icons.primary ||
  					this.options.icons.secondary ) ) {
  				if ( this.options.icons.primary ) {
  					this.options.icon = this.options.icons.primary;
  				} else {
  					this.options.icon = this.options.icons.secondary;
  					this.options.iconPosition = "end";
  				}
  			} else if ( this.options.icon ) {
  				this.options.icons.primary = this.options.icon;
  			}
  			this._super();
  		},
  
  		_setOption: function( key, value ) {
  			if ( key === "text" ) {
  				this._super( "showLabel", value );
  				return;
  			}
  			if ( key === "showLabel" ) {
  				this.options.text = value;
  			}
  			if ( key === "icon" ) {
  				this.options.icons.primary = value;
  			}
  			if ( key === "icons" ) {
  				if ( value.primary ) {
  					this._super( "icon", value.primary );
  					this._super( "iconPosition", "beginning" );
  				} else if ( value.secondary ) {
  					this._super( "icon", value.secondary );
  					this._super( "iconPosition", "end" );
  				}
  			}
  			this._superApply( arguments );
  		}
  	} );
  
  	$.fn.button = ( function( orig ) {
  		return function() {
  			if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
  					( this.length && this[ 0 ].tagName === "INPUT" && (
  						this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
  					) ) ) {
  				return orig.apply( this, arguments );
  			}
  			if ( !$.ui.checkboxradio ) {
  				$.error( "Checkboxradio widget missing" );
  			}
  			if ( arguments.length === 0 ) {
  				return this.checkboxradio( {
  					"icon": false
  				} );
  			}
  			return this.checkboxradio.apply( this, arguments );
  		};
  	} )( $.fn.button );
  
  	$.fn.buttonset = function() {
  		if ( !$.ui.controlgroup ) {
  			$.error( "Controlgroup widget missing" );
  		}
  		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
  			return this.controlgroup.apply( this,
  				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
  		}
  		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
  			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
  		}
  		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
  			arguments[ 0 ].items = {
  				button: arguments[ 0 ].items
  			};
  		}
  		return this.controlgroup.apply( this, arguments );
  	};
  }
  
  var widgetsButton = $.ui.button;
  
  
  /*!
   * jQuery UI Dialog 1.12.1
   * http://jqueryui.com
   *
   * Copyright jQuery Foundation and other contributors
   * Released under the MIT license.
   * http://jquery.org/license
   */
  
  //>>label: Dialog
  //>>group: Widgets
  //>>description: Displays customizable dialog windows.
  //>>docs: http://api.jqueryui.com/dialog/
  //>>demos: http://jqueryui.com/dialog/
  //>>css.structure: ../../themes/base/core.css
  //>>css.structure: ../../themes/base/dialog.css
  //>>css.theme: ../../themes/base/theme.css
  
  
  
  $.widget( "ui.dialog", {
  	version: "1.12.1",
  	options: {
  		appendTo: "body",
  		autoOpen: true,
  		buttons: [],
  		classes: {
  			"ui-dialog": "ui-corner-all",
  			"ui-dialog-titlebar": "ui-corner-all"
  		},
  		closeOnEscape: true,
  		closeText: "Close",
  		draggable: true,
  		hide: null,
  		height: "auto",
  		maxHeight: null,
  		maxWidth: null,
  		minHeight: 150,
  		minWidth: 150,
  		modal: false,
  		position: {
  			my: "center",
  			at: "center",
  			of: window,
  			collision: "fit",
  
  			// Ensure the titlebar is always visible
  			using: function( pos ) {
  				var topOffset = $( this ).css( pos ).offset().top;
  				if ( topOffset < 0 ) {
  					$( this ).css( "top", pos.top - topOffset );
  				}
  			}
  		},
  		resizable: true,
  		show: null,
  		title: null,
  		width: 300,
  
  		// Callbacks
  		beforeClose: null,
  		close: null,
  		drag: null,
  		dragStart: null,
  		dragStop: null,
  		focus: null,
  		open: null,
  		resize: null,
  		resizeStart: null,
  		resizeStop: null
  	},
  
  	sizeRelatedOptions: {
  		buttons: true,
  		height: true,
  		maxHeight: true,
  		maxWidth: true,
  		minHeight: true,
  		minWidth: true,
  		width: true
  	},
  
  	resizableRelatedOptions: {
  		maxHeight: true,
  		maxWidth: true,
  		minHeight: true,
  		minWidth: true
  	},
  
  	_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" );
  		if ( this.options.title == null && this.originalTitle != null ) {
  			this.options.title = this.originalTitle;
  		}
  
  		// Dialogs can't be disabled
  		if ( this.options.disabled ) {
  			this.options.disabled = false;
  		}
  
  		this._createWrapper();
  
  		this.element
  			.show()
  			.removeAttr( "title" )
  			.appendTo( this.uiDialog );
  
  		this._addClass( "ui-dialog-content", "ui-widget-content" );
  
  		this._createTitlebar();
  		this._createButtonPane();
  
  		if ( this.options.draggable && $.fn.draggable ) {
  			this._makeDraggable();
  		}
  		if ( this.options.resizable && $.fn.resizable ) {
  			this._makeResizable();
  		}
  
  		this._isOpen = false;
  
  		this._trackFocus();
  	},
  
  	_init: function() {
  		if ( this.options.autoOpen ) {
  			this.open();
  		}
  	},
  
  	_appendTo: function() {
  		var element = this.options.appendTo;
  		if ( element && ( element.jquery || element.nodeType ) ) {
  			return $( element );
  		}
  		return this.document.find( element || "body" ).eq( 0 );
  	},
  
  	_destroy: function() {
  		var next,
  			originalPosition = this.originalPosition;
  
  		this._untrackInstance();
  		this._destroyOverlay();
  
  		this.element
  			.removeUniqueId()
  			.css( this.originalCss )
  
  			// Without detaching first, the following becomes really slow
  			.detach();
  
  		this.uiDialog.remove();
  
  		if ( this.originalTitle ) {
  			this.element.attr( "title", this.originalTitle );
  		}
  
  		next = originalPosition.parent.children().eq( originalPosition.index );
  
  		// Don't try to place the dialog next to itself (#8613)
  		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
  			next.before( this.element );
  		} else {
  			originalPosition.parent.append( this.element );
  		}
  	},
  
  	widget: function() {
  		return this.uiDialog;
  	},
  
  	disable: $.noop,
  	enable: $.noop,
  
  	close: function( event ) {
  		var that = this;
  
  		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
  			return;
  		}
  
  		this._isOpen = false;
  		this._focusedElement = null;
  		this._destroyOverlay();
  		this._untrackInstance();
  
  		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
  
  			// Hiding a focused element doesn't trigger blur in WebKit
  			// so in case we have nothing to focus on, explicitly blur the active element
  			// https://bugs.webkit.org/show_bug.cgi?id=47182
  			$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
  		}
  
  		this._hide( this.uiDialog, this.options.hide, function() {
  			that._trigger( "close", event );
  		} );
  	},
  
  	isOpen: function() {
  		return this._isOpen;
  	},
  
  	moveToTop: function() {
  		this._moveToTop();
  	},
  
  	_moveToTop: function( event, silent ) {
  		var moved = false,
  			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
  				return +$( this ).css( "z-index" );
  			} ).get(),
  			zIndexMax = Math.max.apply( null, zIndices );
  
  		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
  			this.uiDialog.css( "z-index", zIndexMax + 1 );
  			moved = true;
  		}
  
  		if ( moved && !silent ) {
  			this._trigger( "focus", event );
  		}
  		return moved;
  	},
  
  	open: function() {
  		var that = this;
  		if ( this._isOpen ) {
  			if ( this._moveToTop() ) {
  				this._focusTabbable();
  			}
  			return;
  		}
  
  		this._isOpen = true;
  		this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
  
  		this._size();
  		this._position();
  		this._createOverlay();
  		this._moveToTop( null, true );
  
  		// Ensure the overlay is moved to the top with the dialog, but only when
  		// opening. The overlay shouldn't move after the dialog is open so that
  		// modeless dialogs opened after the modal dialog stack properly.
  		if ( this.overlay ) {
  			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
  		}
  
  		this._show( this.uiDialog, this.options.show, function() {
  			that._focusTabbable();
  			that._trigger( "focus" );
  		} );
  
  		// Track the dialog immediately upon openening in case a focus event
  		// somehow occurs outside of the dialog before an element inside the
  		// dialog is focused (#10152)
  		this._makeFocusTarget();
  
  		this._trigger( "open" );
  	},
  
  	_focusTabbable: function() {
  
  		// Set focus to the first match:
  		// 1. An element that was focused previously
  		// 2. First element inside the dialog matching [autofocus]
  		// 3. Tabbable element inside the content element
  		// 4. Tabbable element inside the buttonpane
  		// 5. The close button
  		// 6. The dialog itself
  		var hasFocus = this._focusedElement;
  		if ( !hasFocus ) {
  			hasFocus = this.element.find( "[autofocus]" );
  		}
  		if ( !hasFocus.length ) {
  			hasFocus = this.element.find( ":tabbable" );
  		}
  		if ( !hasFocus.length ) {
  			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
  		}
  		if ( !hasFocus.length ) {
  			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
  		}
  		if ( !hasFocus.length ) {
  			hasFocus = this.uiDialog;
  		}
  		hasFocus.eq( 0 ).trigger( "focus" );
  	},
  
  	_keepFocus: function( event ) {
  		function checkFocus() {
  			var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
  				isActive = this.uiDialog[ 0 ] === activeElement ||
  					$.contains( this.uiDialog[ 0 ], activeElement );
  			if ( !isActive ) {
  				this._focusTabbable();
  			}
  		}
  		event.preventDefault();
  		checkFocus.call( this );
  
  		// support: IE
  		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
  		// so we check again later
  		this._delay( checkFocus );
  	},
  
  	_createWrapper: function() {
  		this.uiDialog = $( "<div>" )
  			.hide()
  			.attr( {
  
  				// Setting tabIndex makes the div focusable
  				tabIndex: -1,
  				role: "dialog"
  			} )
  			.appendTo( this._appendTo() );
  
  		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
  		this._on( this.uiDialog, {
  			keydown: function( event ) {
  				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  						event.keyCode === $.ui.keyCode.ESCAPE ) {
  					event.preventDefault();
  					this.close( event );
  					return;
  				}
  
  				// Prevent tabbing out of dialogs
  				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
  					return;
  				}
  				var tabbables = this.uiDialog.find( ":tabbable" ),
  					first = tabbables.filter( ":first" ),
  					last = tabbables.filter( ":last" );
  
  				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
  						!event.shiftKey ) {
  					this._delay( function() {
  						first.trigger( "focus" );
  					} );
  					event.preventDefault();
  				} else if ( ( event.target === first[ 0 ] ||
  						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
  					this._delay( function() {
  						last.trigger( "focus" );
  					} );
  					event.preventDefault();
  				}
  			},
  			mousedown: function( event ) {
  				if ( this._moveToTop( event ) ) {
  					this._focusTabbable();
  				}
  			}
  		} );
  
  		// We assume that any existing aria-describedby attribute means
  		// that the dialog content is marked up properly
  		// otherwise we brute force the content as the description
  		if ( !this.element.find( "[aria-describedby]" ).length ) {
  			this.uiDialog.attr( {
  				"aria-describedby": this.element.uniqueId().attr( "id" )
  			} );
  		}
  	},
  
  	_createTitlebar: function() {
  		var uiDialogTitle;
  
  		this.uiDialogTitlebar = $( "<div>" );
  		this._addClass( this.uiDialogTitlebar,
  			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
  		this._on( this.uiDialogTitlebar, {
  			mousedown: function( event ) {
  
  				// Don't prevent click on close button (#8838)
  				// Focusing a dialog that is partially scrolled out of view
  				// causes the browser to scroll it into view, preventing the click event
  				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
  
  					// Dialog isn't getting focus when dragging (#8063)
  					this.uiDialog.trigger( "focus" );
  				}
  			}
  		} );
  
  		// Support: IE
  		// Use type="button" to prevent enter keypresses in textboxes from closing the
  		// dialog in IE (#9312)
  		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
  			.button( {
  				label: $( "<a>" ).text( this.options.closeText ).html(),
  				icon: "ui-icon-closethick",
  				showLabel: false
  			} )
  			.appendTo( this.uiDialogTitlebar );
  
  		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
  		this._on( this.uiDialogTitlebarClose, {
  			click: function( event ) {
  				event.preventDefault();
  				this.close( event );
  			}
  		} );
  
  		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
  		this._addClass( uiDialogTitle, "ui-dialog-title" );
  		this._title( uiDialogTitle );
  
  		this.uiDialogTitlebar.prependTo( this.uiDialog );
  
  		this.uiDialog.attr( {
  			"aria-labelledby": uiDialogTitle.attr( "id" )
  		} );
  	},
  
  	_title: function( title ) {
  		if ( this.options.title ) {
  			title.text( this.options.title );
  		} else {
  			title.html( "&#160;" );
  		}
  	},
  
  	_createButtonPane: function() {
  		this.uiDialogButtonPane = $( "<div>" );
  		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
  			"ui-widget-content ui-helper-clearfix" );
  
  		this.uiButtonSet = $( "<div>" )
  			.appendTo( this.uiDialogButtonPane );
  		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
  
  		this._createButtons();
  	},
  
  	_createButtons: function() {
  		var that = this,
  			buttons = this.options.buttons;
  
  		// If we already have a button pane, remove it
  		this.uiDialogButtonPane.remove();
  		this.uiButtonSet.empty();
  
  		if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
  			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
  			return;
  		}
  
  		$.each( buttons, function( name, props ) {
  			var click, buttonOptions;
  			props = $.isFunction( props ) ?
  				{ click: props, text: name } :
  				props;
  
  			// Default to a non-submitting button
  			props = $.extend( { type: "button" }, props );
  
  			// Change the context for the click callback to be the main element
  			click = props.click;
  			buttonOptions = {
  				icon: props.icon,
  				iconPosition: props.iconPosition,
  				showLabel: props.showLabel,
  
  				// Deprecated options
  				icons: props.icons,
  				text: props.text
  			};
  
  			delete props.click;
  			delete props.icon;
  			delete props.iconPosition;
  			delete props.showLabel;
  
  			// Deprecated options
  			delete props.icons;
  			if ( typeof props.text === "boolean" ) {
  				delete props.text;
  			}
  
  			$( "<button></button>", props )
  				.button( buttonOptions )
  				.appendTo( that.uiButtonSet )
  				.on( "click", function() {
  					click.apply( that.element[ 0 ], arguments );
  				} );
  		} );
  		this._addClass( this.uiDialog, "ui-dialog-buttons" );
  		this.uiDialogButtonPane.appendTo( this.uiDialog );
  	},
  
  	_makeDraggable: function() {
  		var that = this,
  			options = this.options;
  
  		function filteredUi( ui ) {
  			return {
  				position: ui.position,
  				offset: ui.offset
  			};
  		}
  
  		this.uiDialog.draggable( {
  			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
  			handle: ".ui-dialog-titlebar",
  			containment: "document",
  			start: function( event, ui ) {
  				that._addClass( $( this ), "ui-dialog-dragging" );
  				that._blockFrames();
  				that._trigger( "dragStart", event, filteredUi( ui ) );
  			},
  			drag: function( event, ui ) {
  				that._trigger( "drag", event, filteredUi( ui ) );
  			},
  			stop: function( event, ui ) {
  				var left = ui.offset.left - that.document.scrollLeft(),
  					top = ui.offset.top - that.document.scrollTop();
  
  				options.position = {
  					my: "left top",
  					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  						"top" + ( top >= 0 ? "+" : "" ) + top,
  					of: that.window
  				};
  				that._removeClass( $( this ), "ui-dialog-dragging" );
  				that._unblockFrames();
  				that._trigger( "dragStop", event, filteredUi( ui ) );
  			}
  		} );
  	},
  
  	_makeResizable: function() {
  		var that = this,
  			options = this.options,
  			handles = options.resizable,
  
  			// .ui-resizable has position: relative defined in the stylesheet
  			// but dialogs have to use absolute or fixed positioning
  			position = this.uiDialog.css( "position" ),
  			resizeHandles = typeof handles === "string" ?
  				handles :
  				"n,e,s,w,se,sw,ne,nw";
  
  		function filteredUi( ui ) {
  			return {
  				originalPosition: ui.originalPosition,
  				originalSize: ui.originalSize,
  				position: ui.position,
  				size: ui.size
  			};
  		}
  
  		this.uiDialog.resizable( {
  			cancel: ".ui-dialog-content",
  			containment: "document",
  			alsoResize: this.element,
  			maxWidth: options.maxWidth,
  			maxHeight: options.maxHeight,
  			minWidth: options.minWidth,
  			minHeight: this._minHeight(),
  			handles: resizeHandles,
  			start: function( event, ui ) {
  				that._addClass( $( this ), "ui-dialog-resizing" );
  				that._blockFrames();
  				that._trigger( "resizeStart", event, filteredUi( ui ) );
  			},
  			resize: function( event, ui ) {
  				that._trigger( "resize", event, filteredUi( ui ) );
  			},
  			stop: function( event, ui ) {
  				var offset = that.uiDialog.offset(),
  					left = offset.left - that.document.scrollLeft(),
  					top = offset.top - that.document.scrollTop();
  
  				options.height = that.uiDialog.height();
  				options.width = that.uiDialog.width();
  				options.position = {
  					my: "left top",
  					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  						"top" + ( top >= 0 ? "+" : "" ) + top,
  					of: that.window
  				};
  				that._removeClass( $( this ), "ui-dialog-resizing" );
  				that._unblockFrames();
  				that._trigger( "resizeStop", event, filteredUi( ui ) );
  			}
  		} )
  			.css( "position", position );
  	},
  
  	_trackFocus: function() {
  		this._on( this.widget(), {
  			focusin: function( event ) {
  				this._makeFocusTarget();
  				this._focusedElement = $( event.target );
  			}
  		} );
  	},
  
  	_makeFocusTarget: function() {
  		this._untrackInstance();
  		this._trackingInstances().unshift( this );
  	},
  
  	_untrackInstance: function() {
  		var instances = this._trackingInstances(),
  			exists = $.inArray( this, instances );
  		if ( exists !== -1 ) {
  			instances.splice( exists, 1 );
  		}
  	},
  
  	_trackingInstances: function() {
  		var instances = this.document.data( "ui-dialog-instances" );
  		if ( !instances ) {
  			instances = [];
  			this.document.data( "ui-dialog-instances", instances );
  		}
  		return instances;
  	},
  
  	_minHeight: function() {
  		var options = this.options;
  
  		return options.height === "auto" ?
  			options.minHeight :
  			Math.min( options.minHeight, options.height );
  	},
  
  	_position: function() {
  
  		// Need to show the dialog to get the actual offset in the position plugin
  		var isVisible = this.uiDialog.is( ":visible" );
  		if ( !isVisible ) {
  			this.uiDialog.show();
  		}
  		this.uiDialog.position( this.options.position );
  		if ( !isVisible ) {
  			this.uiDialog.hide();
  		}
  	},
  
  	_setOptions: function( options ) {
  		var that = this,
  			resize = false,
  			resizableOptions = {};
  
  		$.each( options, function( key, value ) {
  			that._setOption( key, value );
  
  			if ( key in that.sizeRelatedOptions ) {
  				resize = true;
  			}
  			if ( key in that.resizableRelatedOptions ) {
  				resizableOptions[ key ] = value;
  			}
  		} );
  
  		if ( resize ) {
  			this._size();
  			this._position();
  		}
  		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  			this.uiDialog.resizable( "option", resizableOptions );
  		}
  	},
  
  	_setOption: function( key, value ) {
  		var isDraggable, isResizable,
  			uiDialog = this.uiDialog;
  
  		if ( key === "disabled" ) {
  			return;
  		}
  
  		this._super( key, value );
  
  		if ( key === "appendTo" ) {
  			this.uiDialog.appendTo( this._appendTo() );
  		}
  
  		if ( key === "buttons" ) {
  			this._createButtons();
  		}
  
  		if ( key === "closeText" ) {
  			this.uiDialogTitlebarClose.button( {
  
  				// Ensure that we always pass a string
  				label: $( "<a>" ).text( "" + this.options.closeText ).html()
  			} );
  		}
  
  		if ( key === "draggable" ) {
  			isDraggable = uiDialog.is( ":data(ui-draggable)" );
  			if ( isDraggable && !value ) {
  				uiDialog.draggable( "destroy" );
  			}
  
  			if ( !isDraggable && value ) {
  				this._makeDraggable();
  			}
  		}
  
  		if ( key === "position" ) {
  			this._position();
  		}
  
  		if ( key === "resizable" ) {
  
  			// currently resizable, becoming non-resizable
  			isResizable = uiDialog.is( ":data(ui-resizable)" );
  			if ( isResizable && !value ) {
  				uiDialog.resizable( "destroy" );
  			}
  
  			// Currently resizable, changing handles
  			if ( isResizable && typeof value === "string" ) {
  				uiDialog.resizable( "option", "handles", value );
  			}
  
  			// Currently non-resizable, becoming resizable
  			if ( !isResizable && value !== false ) {
  				this._makeResizable();
  			}
  		}
  
  		if ( key === "title" ) {
  			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
  		}
  	},
  
  	_size: function() {
  
  		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
  		// divs will both have width and height set, so we need to reset them
  		var nonContentHeight, minContentHeight, maxContentHeight,
  			options = this.options;
  
  		// Reset content sizing
  		this.element.show().css( {
  			width: "auto",
  			minHeight: 0,
  			maxHeight: "none",
  			height: 0
  		} );
  
  		if ( options.minWidth > options.width ) {
  			options.width = options.minWidth;
  		}
  
  		// Reset wrapper sizing
  		// determine the height of all the non-content elements
  		nonContentHeight = this.uiDialog.css( {
  			height: "auto",
  			width: options.width
  		} )
  			.outerHeight();
  		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
  		maxContentHeight = typeof options.maxHeight === "number" ?
  			Math.max( 0, options.maxHeight - nonContentHeight ) :
  			"none";
  
  		if ( options.height === "auto" ) {
  			this.element.css( {
  				minHeight: minContentHeight,
  				maxHeight: maxContentHeight,
  				height: "auto"
  			} );
  		} else {
  			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
  		}
  
  		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
  		}
  	},
  
  	_blockFrames: function() {
  		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
  			var iframe = $( this );
  
  			return $( "<div>" )
  				.css( {
  					position: "absolute",
  					width: iframe.outerWidth(),
  					height: iframe.outerHeight()
  				} )
  				.appendTo( iframe.parent() )
  				.offset( iframe.offset() )[ 0 ];
  		} );
  	},
  
  	_unblockFrames: function() {
  		if ( this.iframeBlocks ) {
  			this.iframeBlocks.remove();
  			delete this.iframeBlocks;
  		}
  	},
  
  	_allowInteraction: function( event ) {
  		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
  			return true;
  		}
  
  		// TODO: Remove hack when datepicker implements
  		// the .ui-front logic (#8989)
  		return !!$( event.target ).closest( ".ui-datepicker" ).length;
  	},
  
  	_createOverlay: function() {
  		if ( !this.options.modal ) {
  			return;
  		}
  
  		// We use a delay in case the overlay is created from an
  		// event that we're going to be cancelling (#2804)
  		var isOpening = true;
  		this._delay( function() {
  			isOpening = false;
  		} );
  
  		if ( !this.document.data( "ui-dialog-overlays" ) ) {
  
  			// Prevent use of anchors and inputs
  			// Using _on() for an event handler shared across many instances is
  			// safe because the dialogs stack and must be closed in reverse order
  			this._on( this.document, {
  				focusin: function( event ) {
  					if ( isOpening ) {
  						return;
  					}
  
  					if ( !this._allowInteraction( event ) ) {
  						event.preventDefault();
  						this._trackingInstances()[ 0 ]._focusTabbable();
  					}
  				}
  			} );
  		}
  
  		this.overlay = $( "<div>" )
  			.appendTo( this._appendTo() );
  
  		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
  		this._on( this.overlay, {
  			mousedown: "_keepFocus"
  		} );
  		this.document.data( "ui-dialog-overlays",
  			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
  	},
  
  	_destroyOverlay: function() {
  		if ( !this.options.modal ) {
  			return;
  		}
  
  		if ( this.overlay ) {
  			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
  
  			if ( !overlays ) {
  				this._off( this.document, "focusin" );
  				this.document.removeData( "ui-dialog-overlays" );
  			} else {
  				this.document.data( "ui-dialog-overlays", overlays );
  			}
  
  			this.overlay.remove();
  			this.overlay = null;
  		}
  	}
  } );
  
  // DEPRECATED
  // TODO: switch return back to widget declaration at top of file when this is removed
  if ( $.uiBackCompat !== false ) {
  
  	// Backcompat for dialogClass option
  	$.widget( "ui.dialog", $.ui.dialog, {
  		options: {
  			dialogClass: ""
  		},
  		_createWrapper: function() {
  			this._super();
  			this.uiDialog.addClass( this.options.dialogClass );
  		},
  		_setOption: function( key, value ) {
  			if ( key === "dialogClass" ) {
  				this.uiDialog
  					.removeClass( this.options.dialogClass )
  					.addClass( value );
  			}
  			this._superApply( arguments );
  		}
  	} );
  }
  
  var widgetsDialog = $.ui.dialog;
  
  
  
  
  }));
  /*!
   * jQuery UI Touch Punch 0.2.3
   *
   * Copyright 2011–2014, Dave Furfero
   * Dual licensed under the MIT or GPL Version 2 licenses.
   *
   * Depends:
   *  jquery.ui.widget.js
   *  jquery.ui.mouse.js
   */
  !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
  /*!
   * Bootstrap v3.3.7 (http://getbootstrap.com)
   * Copyright 2011-2016 Twitter, Inc.
   * Licensed under the MIT license
   */
  if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){
  this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
  (function ($) {
      'use strict';
  
      //<editor-fold desc="Shims">
      if (!String.prototype.includes) {
          (function () {
              'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
              var toString = {}.toString;
              var defineProperty = (function () {
                  // IE 8 only supports `Object.defineProperty` on DOM elements
                  try {
                      var object = {};
                      var $defineProperty = Object.defineProperty;
                      var result = $defineProperty(object, object, object) && $defineProperty;
                  } catch (error) {
                  }
                  return result;
              }());
              var indexOf = ''.indexOf;
              var includes = function (search) {
                  if (this == null) {
                      throw new TypeError();
                  }
                  var string = String(this);
                  if (search && toString.call(search) == '[object RegExp]') {
                      throw new TypeError();
                  }
                  var stringLength = string.length;
                  var searchString = String(search);
                  var searchLength = searchString.length;
                  var position = arguments.length > 1 ? arguments[1] : undefined;
                  // `ToInteger`
                  var pos = position ? Number(position) : 0;
                  if (pos != pos) { // better `isNaN`
                      pos = 0;
                  }
                  var start = Math.min(Math.max(pos, 0), stringLength);
                  // Avoid the `indexOf` call if no match is possible
                  if (searchLength + start > stringLength) {
                      return false;
                  }
                  return indexOf.call(string, searchString, pos) != -1;
              };
              if (defineProperty) {
                  defineProperty(String.prototype, 'includes', {
                      'value': includes,
                      'configurable': true,
                      'writable': true
                  });
              } else {
                  String.prototype.includes = includes;
              }
          }());
      }
  
      if (!String.prototype.startsWith) {
          (function () {
              'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
              var defineProperty = (function () {
                  // IE 8 only supports `Object.defineProperty` on DOM elements
                  try {
                      var object = {};
                      var $defineProperty = Object.defineProperty;
                      var result = $defineProperty(object, object, object) && $defineProperty;
                  } catch (error) {
                  }
                  return result;
              }());
              var toString = {}.toString;
              var startsWith = function (search) {
                  if (this == null) {
                      throw new TypeError();
                  }
                  var string = String(this);
                  if (search && toString.call(search) == '[object RegExp]') {
                      throw new TypeError();
                  }
                  var stringLength = string.length;
                  var searchString = String(search);
                  var searchLength = searchString.length;
                  var position = arguments.length > 1 ? arguments[1] : undefined;
                  // `ToInteger`
                  var pos = position ? Number(position) : 0;
                  if (pos != pos) { // better `isNaN`
                      pos = 0;
                  }
                  var start = Math.min(Math.max(pos, 0), stringLength);
                  // Avoid the `indexOf` call if no match is possible
                  if (searchLength + start > stringLength) {
                      return false;
                  }
                  var index = -1;
                  while (++index < searchLength) {
                      if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
                          return false;
                      }
                  }
                  return true;
              };
              if (defineProperty) {
                  defineProperty(String.prototype, 'startsWith', {
                      'value': startsWith,
                      'configurable': true,
                      'writable': true
                  });
              } else {
                  String.prototype.startsWith = startsWith;
              }
          }());
      }
  
      if (!Object.keys) {
          Object.keys = function (
              o, // object
              k, // key
              r  // result array
          ){
              // initialize object and result
              r=[];
              // iterate over object keys
              for (k in o)
                  // fill result array with non-prototypical keys
                  r.hasOwnProperty.call(o, k) && r.push(k);
              // return result
              return r;
          };
      }
  
      // set data-selected on select element if the value has been programmatically selected
      // prior to initialization of bootstrap-select
      // * consider removing or replacing an alternative method *
      var valHooks = {
          useDefault: false,
          _set: $.valHooks.select.set
      };
  
      $.valHooks.select.set = function(elem, value) {
          if (value && !valHooks.useDefault) $(elem).data('selected', true);
  
          return valHooks._set.apply(this, arguments);
      };
  
      var changed_arguments = null;
      $.fn.triggerNative = function (eventName) {
          var el = this[0],
              event;
  
          if (el.dispatchEvent) { // for modern browsers & IE9+
              if (typeof Event === 'function') {
                  // For modern browsers
                  event = new Event(eventName, {
                      bubbles: true
                  });
              } else {
                  // For IE since it doesn't support Event constructor
                  event = document.createEvent('Event');
                  event.initEvent(eventName, true, false);
              }
  
              el.dispatchEvent(event);
          } else if (el.fireEvent) { // for IE8
              event = document.createEventObject();
              event.eventType = eventName;
              el.fireEvent('on' + eventName, event);
          } else {
              // fall back to jQuery.trigger
              this.trigger(eventName);
          }
      };
      //</editor-fold>
  
      // Case insensitive contains search
      $.expr.pseudos.icontains = function (obj, index, meta) {
          var $obj = $(obj).find('a');
          var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
          return haystack.includes(meta[3].toUpperCase());
      };
  
      // Case insensitive begins search
      $.expr.pseudos.ibegins = function (obj, index, meta) {
          var $obj = $(obj).find('a');
          var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
          return haystack.startsWith(meta[3].toUpperCase());
      };
  
      // Case and accent insensitive contains search
      $.expr.pseudos.aicontains = function (obj, index, meta) {
          var $obj = $(obj).find('a');
          var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
          return haystack.includes(meta[3].toUpperCase());
      };
  
      // Case and accent insensitive begins search
      $.expr.pseudos.aibegins = function (obj, index, meta) {
          var $obj = $(obj).find('a');
          var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
          return haystack.startsWith(meta[3].toUpperCase());
      };
  
      /**
       * Remove all diatrics from the given text.
       * @access private
       * @param {String} text
       * @returns {String}
       */
      function normalizeToBase(text) {
          var rExps = [
              {re: /[\xC0-\xC6]/g, ch: "A"},
              {re: /[\xE0-\xE6]/g, ch: "a"},
              {re: /[\xC8-\xCB]/g, ch: "E"},
              {re: /[\xE8-\xEB]/g, ch: "e"},
              {re: /[\xCC-\xCF]/g, ch: "I"},
              {re: /[\xEC-\xEF]/g, ch: "i"},
              {re: /[\xD2-\xD6]/g, ch: "O"},
              {re: /[\xF2-\xF6]/g, ch: "o"},
              {re: /[\xD9-\xDC]/g, ch: "U"},
              {re: /[\xF9-\xFC]/g, ch: "u"},
              {re: /[\xC7-\xE7]/g, ch: "c"},
              {re: /[\xD1]/g, ch: "N"},
              {re: /[\xF1]/g, ch: "n"}
          ];
          $.each(rExps, function () {
              text = text ? text.replace(this.re, this.ch) : '';
          });
          return text;
      }
  
  
      // List of HTML entities for escaping.
      var escapeMap = {
          '&': '&amp;',
          '<': '&lt;',
          '>': '&gt;',
          '"': '&quot;',
          "'": '&#x27;',
          '`': '&#x60;'
      };
  
      var unescapeMap = {
          '&amp;': '&',
          '&lt;': '<',
          '&gt;': '>',
          '&quot;': '"',
          '&#x27;': "'",
          '&#x60;': '`'
      };
  
      // Functions for escaping and unescaping strings to/from HTML interpolation.
      var createEscaper = function(map) {
          var escaper = function(match) {
              return map[match];
          };
          // Regexes for identifying a key that needs to be escaped.
          var source = '(?:' + Object.keys(map).join('|') + ')';
          var testRegexp = RegExp(source);
          var replaceRegexp = RegExp(source, 'g');
          return function(string) {
              string = string == null ? '' : '' + string;
              return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
          };
      };
  
      var htmlEscape = createEscaper(escapeMap);
      var htmlUnescape = createEscaper(unescapeMap);
  
      var Selectpicker = function (element, options) {
          // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
          if (!valHooks.useDefault) {
              $.valHooks.select.set = valHooks._set;
              valHooks.useDefault = true;
          }
  
          this.$element = $(element);
          this.$newElement = null;
          this.$button = null;
          this.$menu = null;
          this.$lis = null;
          this.options = options;
  
          // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
          // data-attribute)
          if (this.options.title === null) {
              this.options.title = this.$element.attr('title');
          }
  
          // Format window padding
          var winPad = this.options.windowPadding;
          if (typeof winPad === 'number') {
              this.options.windowPadding = [winPad, winPad, winPad, winPad];
          }
  
          //Expose public methods
          this.val = Selectpicker.prototype.val;
          this.render = Selectpicker.prototype.render;
          this.refresh = Selectpicker.prototype.refresh;
          this.setStyle = Selectpicker.prototype.setStyle;
          this.selectAll = Selectpicker.prototype.selectAll;
          this.deselectAll = Selectpicker.prototype.deselectAll;
          this.destroy = Selectpicker.prototype.destroy;
          this.remove = Selectpicker.prototype.remove;
          this.show = Selectpicker.prototype.show;
          this.hide = Selectpicker.prototype.hide;
  
          this.init();
      };
  
      Selectpicker.VERSION = '1.12.2';
  
      // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
      Selectpicker.DEFAULTS = {
          noneSelectedText: 'Nothing selected',
          noneResultsText: 'No results matched {0}',
          countSelectedText: function (numSelected, numTotal) {
              return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
          },
          maxOptionsText: function (numAll, numGroup) {
              return [
                  (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
                  (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
              ];
          },
          selectAllText: (window.lang && window.lang.select_all) ? window.lang.select_all : 'Select All',
          deselectAllText: (window.lang && window.lang.deselect_all) ? window.lang.deselect_all : 'Deselect All',
          doneButton: false,
          doneButtonText: (window.lang && window.lang.close) ? window.lang.close : 'Close',
          multipleSeparator: ', ',
          styleBase: 'btn',
          style: 'btn-default',
          size: 'auto',
          title: null,
          selectedTextFormat: 'values',
          width: false,
          container: false,
          hideDisabled: false,
          showSubtext: false,
          showIcon: true,
          showContent: true,
          dropupAuto: true,
          header: false,
          liveSearch: false,
          liveSearchPlaceholder: null,
          liveSearchNormalize: false,
          liveSearchStyle: 'contains',
          actionsBox: false,
          iconBase: 'glyphicon',
          tickIcon: 'glyphicon-ok',
          showTick: false,
          template: {
              caret: '<span class="caret"></span>'
          },
          maxOptions: false,
          mobile: false,
          selectOnTab: false,
          dropdownAlignRight: false,
          windowPadding: 0,
          icon: ''
      };
  
      Selectpicker.prototype = {
  
          constructor: Selectpicker,
  
          init: function () {
              var that = this,
                  id = this.$element.attr('id');
  
              this.$element.addClass('bs-select-hidden');
  
              // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
              // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
              this.liObj = {};
              this.multiple = this.$element.prop('multiple');
              this.autofocus = this.$element.prop('autofocus');
              this.$newElement = this.createView();
              this.$element
                  .after(this.$newElement)
                  .appendTo(this.$newElement);
              this.$button = this.$newElement.children('button');
              this.$menu = this.$newElement.children('.dropdown-menu');
              this.$menuInner = this.$menu.children('.inner');
              this.$searchbox = this.$menu.find('input');
  
              this.$element.removeClass('bs-select-hidden');
  
              if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
  
              if (typeof id !== 'undefined') {
                  this.$button.attr('data-id', id);
                  $('label[for="' + id + '"]').click(function (e) {
                      e.preventDefault();
                      that.$button.focus();
                  });
              }
  
              this.checkDisabled();
              this.clickListener();
              if (this.options.liveSearch) this.liveSearchListener();
              this.render();
              this.setStyle();
              this.setWidth();
              if (this.options.container) this.selectPosition();
              this.$menu.data('this', this);
              this.$newElement.data('this', this);
              if (this.options.mobile) this.mobile();
  
              this.$newElement.on({
                  'hide.bs.dropdown': function (e) {
                      that.$menuInner.attr('aria-expanded', false);
                      that.$element.trigger('hide.bs.select', e);
                  },
                  'hidden.bs.dropdown': function (e) {
                      that.$element.trigger('hidden.bs.select', e);
                  },
                  'show.bs.dropdown': function (e) {
                      that.$menuInner.attr('aria-expanded', true);
                      that.$element.trigger('show.bs.select', e);
                  },
                  'shown.bs.dropdown': function (e) {
                      that.$element.trigger('shown.bs.select', e);
                  }
              });
  
              if (that.$element[0].hasAttribute('required')) {
                  this.$element.on('invalid', function () {
                      that.$button
                          .addClass('bs-invalid')
                          .focus();
  
                      that.$element.on({
                          'focus.bs.select': function () {
                              that.$button.focus();
                              that.$element.off('focus.bs.select');
                          },
                          'shown.bs.select': function () {
                              that.$element
                                  .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
                                  .off('shown.bs.select');
                          },
                          'rendered.bs.select': function () {
                              // if select is no longer invalid, remove the bs-invalid class
                              if (this.validity.valid) that.$button.removeClass('bs-invalid');
                              that.$element.off('rendered.bs.select');
                          }
                      });
                  });
              }
  
              setTimeout(function () {
                  that.$element.trigger('loaded.bs.select');
              });
          },
  
          createDropdown: function () {
              // Options
              // If we are multiple or showTick option is set, then add the show-tick class
              var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
                  inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
                  autofocus = this.autofocus ? ' autofocus' : '';
              // Elements
              var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
              var searchbox = this.options.liveSearch ?
              '<div class="bs-searchbox">' +
              '<input type="text" class="form-control" autocomplete="off"' +
              (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
              '</div>'
                  : '';
              var actionsbox = this.multiple && this.options.actionsBox ?
              '<div class="bs-actionsbox">' +
              '<div class="btn-group btn-group-sm btn-block">' +
              '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
              this.options.selectAllText +
              '</button>' +
              '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
              this.options.deselectAllText +
              '</button>' +
              '</div>' +
              '</div>'
                  : '';
              var donebutton = this.multiple && this.options.doneButton ?
              '<div class="bs-donebutton">' +
              '<div class="btn-group btn-block">' +
              '<button type="button" class="btn btn-sm btn-default">' +
              this.options.doneButtonText +
              '</button>' +
              '</div>' +
              '</div>'
                  : '';
              var drop =
                  '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
                  '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
                  (this.options.icon ? '<span class="'+this.options.icon+' pull-left"></span>' : '') +
                  '<span class="filter-option pull-left"></span>&nbsp;' +
                  '<span class="bs-caret">' +
                  this.options.template.caret +
                  '</span>' +
                  '</button>' +
                  '<div class="dropdown-menu open" role="combobox">' +
                  header +
                  searchbox +
                  actionsbox +
                  '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
                  '</ul>' +
                  donebutton +
                  '</div>' +
                  '</div>';
  
              return $(drop);
          },
  
          createView: function () {
              var $drop = this.createDropdown(),
                  li = this.createLi();
  
              $drop.find('ul')[0].innerHTML = li;
              return $drop;
          },
  
          reloadLi: function () {
              // rebuild
              var li = this.createLi();
              this.$menuInner[0].innerHTML = li;
          },
  
          createLi: function () {
              var that = this,
                  _li = [],
                  optID = 0,
                  titleOption = document.createElement('option'),
                  liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
  
              // Helper functions
              /**
               * @param content
               * @param [index]
               * @param [classes]
               * @param [optgroup]
               * @returns {string}
               */
              var generateLI = function (content, index, classes, optgroup) {
                  return '<li' +
                      ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
                      ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
                      ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
                      '>' + content + '</li>';
              };
  
              /**
               * @param text
               * @param [classes]
               * @param [inline]
               * @param [tokens]
               * @returns {string}
               */
              var generateA = function (text, classes, inline, tokens) {
                  return '<a tabindex="0"' +
                      (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
                      (inline ? ' style="' + inline + '"' : '') +
                      (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
                      (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
                      ' role="option">' +
                      '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
                      text +
                      '</a>';
              };
  
              if (this.options.title && !this.multiple) {
                  // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
                  // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
                  liIndex--;
  
                  if (!this.$element.find('.bs-title-option').length) {
                      // Use native JS to prepend option (faster)
                      var element = this.$element[0];
                      titleOption.className = 'bs-title-option';
                      titleOption.innerHTML = this.options.title;
                      titleOption.value = '';
                      element.insertBefore(titleOption, element.firstChild);
                      // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
                      // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
                      // if so, the select will have the data-selected attribute
                      var $opt = $(element.options[element.selectedIndex]);
                      if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
                          titleOption.selected = true;
                      }
                  }
              }
  
              var $selectOptions = this.$element.find('option');
  
              $selectOptions.each(function (index) {
                  var $this = $(this);
  
                  liIndex++;
  
                  if ($this.hasClass('bs-title-option')) return;
  
                  // Get the class and text for the option
                  var optionClass = this.className || '',
                      inline = htmlEscape(this.style.cssText),
                      text = $this.data('content') ? $this.data('content') : $this.html(),
                      tokens = $this.data('tokens') ? $this.data('tokens') : null,
                      subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
                      icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
                      $parent = $this.parent(),
                      isOptgroup = $parent[0].tagName === 'OPTGROUP',
                      isOptgroupDisabled = isOptgroup && $parent[0].disabled,
                      isDisabled = this.disabled || isOptgroupDisabled,
                      prevHiddenIndex;
  
                  if (icon !== '' && isDisabled) {
                      icon = '<span>' + icon + '</span>';
                  }
  
                  if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
                      // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
                      // used to determine whether or not a divider should be placed after an optgroup if there are
                      // hidden options between the optgroup and the first visible option
                      prevHiddenIndex = $this.data('prevHiddenIndex');
                      $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  
                      liIndex--;
                      return;
                  }
  
                  if (!$this.data('content')) {
                      // Prepend any icon and append any subtext to the main text.
                      text = icon + '<span class="text">' + text + subtext + '</span>';
                  }
  
                  if (isOptgroup && $this.data('divider') !== true) {
                      if (that.options.hideDisabled && isDisabled) {
                          if ($parent.data('allOptionsDisabled') === undefined) {
                              var $options = $parent.children();
                              $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
                          }
  
                          if ($parent.data('allOptionsDisabled')) {
                              liIndex--;
                              return;
                          }
                      }
  
                      var optGroupClass = ' ' + $parent[0].className || '';
  
                      if ($this.index() === 0) { // Is it the first option of the optgroup?
                          optID += 1;
  
                          // Get the opt group label
                          var label = $parent[0].label,
                              labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
                              labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
  
                          label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
  
                          if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
                              liIndex++;
                              _li.push(generateLI('', null, 'divider', optID + 'div'));
                          }
                          liIndex++;
                          _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
                      }
  
                      if (that.options.hideDisabled && isDisabled) {
                          liIndex--;
                          return;
                      }
  
                      _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
                  } else if ($this.data('divider') === true) {
                      _li.push(generateLI('', index, 'divider'));
                  } else if ($this.data('hidden') === true) {
                      // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
                      // used to determine whether or not a divider should be placed after an optgroup if there are
                      // hidden options between the optgroup and the first visible option
                      prevHiddenIndex = $this.data('prevHiddenIndex');
                      $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  
                      _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
                  } else {
                      var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
  
                      // if previous element is not an optgroup and hideDisabled is true
                      if (!showDivider && that.options.hideDisabled) {
                          prevHiddenIndex = $this.data('prevHiddenIndex');
  
                          if (prevHiddenIndex !== undefined) {
                              // select the element **before** the first hidden element in the group
                              var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
  
                              if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
                                  showDivider = true;
                              }
                          }
                      }
  
                      if (showDivider) {
                          liIndex++;
                          _li.push(generateLI('', null, 'divider', optID + 'div'));
                      }
                      _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
                  }
  
                  that.liObj[index] = liIndex;
              });
  
              //If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
              if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
                  this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
              }
  
              return _li.join('');
          },
  
          findLis: function () {
              if (this.$lis == null) this.$lis = this.$menu.find('li');
              return this.$lis;
          },
  
          /**
           * @param [updateLi] defaults to true
           */
          render: function (updateLi) {
              var that = this,
                  notDisabled,
                  $selectOptions = this.$element.find('option');
  
              //Update the LI to match the SELECT
              if (updateLi !== false) {
                  $selectOptions.each(function (index) {
                      var $lis = that.findLis().eq(that.liObj[index]);
  
                      that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
                      that.setSelected(index, this.selected, $lis);
                  });
              }
  
              this.togglePlaceholder();
  
              this.tabIndex();
  
              var selectedItems = $selectOptions.map(function () {
                  if (this.selected) {
                      if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
  
                      var $this = $(this),
                          icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
                          subtext;
  
                      if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
                          subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
                      } else {
                          subtext = '';
                      }
                      if (typeof $this.attr('title') !== 'undefined') {
                          return $this.attr('title');
                      } else if ($this.data('content') && that.options.showContent) {
                          return $this.data('content').toString();
                      } else {
                          return icon + $this.html() + subtext;
                      }
                  }
              }).toArray();
  
              //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
              //Convert all the values into a comma delimited string
              var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
  
              //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
              if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
                  var max = this.options.selectedTextFormat.split('>');
                  if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
                      notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
                      var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
                          tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
                      title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
                  }
              }
  
              if (this.options.title == undefined) {
                  this.options.title = this.$element.attr('title');
              }
  
              if (this.options.selectedTextFormat == 'static') {
                  title = this.options.title;
              }
  
              //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
              if (!title) {
                  title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
              }
  
              //strip all HTML tags and trim the result, then unescape any escaped tags
              this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
              this.$button.children('.filter-option').html(title);
  
              this.$element.trigger('rendered.bs.select');
          },
  
          /**
           * @param [style]
           * @param [status]
           */
          setStyle: function (style, status) {
              if (this.$element.attr('class')) {
                  this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
              }
  
              var buttonClass = style ? style : this.options.style;
  
              if (status == 'add') {
                  this.$button.addClass(buttonClass);
              } else if (status == 'remove') {
                  this.$button.removeClass(buttonClass);
              } else {
                  this.$button.removeClass(this.options.style);
                  this.$button.addClass(buttonClass);
              }
          },
  
          liHeight: function (refresh) {
              if (!refresh && (this.options.size === false || this.sizeInfo)) return;
  
              var newElement = document.createElement('div'),
                  menu = document.createElement('div'),
                  menuInner = document.createElement('ul'),
                  divider = document.createElement('li'),
                  li = document.createElement('li'),
                  a = document.createElement('a'),
                  text = document.createElement('span'),
                  header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
                  search = this.options.liveSearch ? document.createElement('div') : null,
                  actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
                  doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
  
              text.className = 'text';
              newElement.className = this.$menu[0].parentNode.className + ' open';
              menu.className = 'dropdown-menu open';
              menuInner.className = 'dropdown-menu inner';
              divider.className = 'divider';
  
              text.appendChild(document.createTextNode('Inner text'));
              a.appendChild(text);
              li.appendChild(a);
              menuInner.appendChild(li);
              menuInner.appendChild(divider);
              if (header) menu.appendChild(header);
              if (search) {
                  var input = document.createElement('input');
                  search.className = 'bs-searchbox';
                  input.className = 'form-control';
                  search.appendChild(input);
                  menu.appendChild(search);
              }
              if (actions) menu.appendChild(actions);
              menu.appendChild(menuInner);
              if (doneButton) menu.appendChild(doneButton);
              newElement.appendChild(menu);
  
              document.body.appendChild(newElement);
  
              var liHeight = a.offsetHeight,
                  headerHeight = header ? header.offsetHeight : 0,
                  searchHeight = search ? search.offsetHeight : 0,
                  actionsHeight = actions ? actions.offsetHeight : 0,
                  doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
                  dividerHeight = $(divider).outerHeight(true),
                  // fall back to jQuery if getComputedStyle is not supported
                  menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
                  $menu = menuStyle ? null : $(menu),
                  menuPadding = {
                      vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
                      parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
                      parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
                      parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
                      horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
                      parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
                      parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
                      parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
                  },
                  menuExtras =  {
                      vert: menuPadding.vert +
                      parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
                      parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
                      horiz: menuPadding.horiz +
                      parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
                      parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
                  }
  
              document.body.removeChild(newElement);
  
              this.sizeInfo = {
                  liHeight: liHeight,
                  headerHeight: headerHeight,
                  searchHeight: searchHeight,
                  actionsHeight: actionsHeight,
                  doneButtonHeight: doneButtonHeight,
                  dividerHeight: dividerHeight,
                  menuPadding: menuPadding,
                  menuExtras: menuExtras
              };
          },
  
          setSize: function () {
              this.findLis();
              this.liHeight();
  
              if (this.options.header) this.$menu.css('padding-top', 0);
              if (this.options.size === false) return;
  
              var that = this,
                  $menu = this.$menu,
                  $menuInner = this.$menuInner,
                  $window = $(window),
                  selectHeight = this.$newElement[0].offsetHeight,
                  selectWidth = this.$newElement[0].offsetWidth,
                  liHeight = this.sizeInfo['liHeight'],
                  headerHeight = this.sizeInfo['headerHeight'],
                  searchHeight = this.sizeInfo['searchHeight'],
                  actionsHeight = this.sizeInfo['actionsHeight'],
                  doneButtonHeight = this.sizeInfo['doneButtonHeight'],
                  divHeight = this.sizeInfo['dividerHeight'],
                  menuPadding = this.sizeInfo['menuPadding'],
                  menuExtras = this.sizeInfo['menuExtras'],
                  notDisabled = this.options.hideDisabled ? '.disabled' : '',
                  menuHeight,
                  menuWidth,
                  getHeight,
                  getWidth,
                  selectOffsetTop,
                  selectOffsetBot,
                  selectOffsetLeft,
                  selectOffsetRight,
                  getPos = function() {
                      var pos = that.$newElement.offset(),
                          $container = $(that.options.container),
                          containerPos;
  
                      if (that.options.container && !$container.is('body')) {
                          containerPos = $container.offset();
                          containerPos.top += parseInt($container.css('borderTopWidth'));
                          containerPos.left += parseInt($container.css('borderLeftWidth'));
                      } else {
                          containerPos = { top: 0, left: 0 };
                      }
  
                      var winPad = that.options.windowPadding;
                      selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
                      selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
                      selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
                      selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
                      selectOffsetTop -= winPad[0];
                      selectOffsetLeft -= winPad[3];
                  };
  
              getPos();
  
              if (this.options.size === 'auto') {
                  var getSize = function () {
                      var minHeight,
                          hasClass = function (className, include) {
                              return function (element) {
                                  if (include) {
                                      return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
                                  } else {
                                      return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
                                  }
                              };
                          },
                          lis = that.$menuInner[0].getElementsByTagName('li'),
                          lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
                          optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
  
                      getPos();
                      menuHeight = selectOffsetBot - menuExtras.vert;
                      menuWidth = selectOffsetRight - menuExtras.horiz;
  
                      if (that.options.container) {
                          if (!$menu.data('height')) $menu.data('height', $menu.height());
                          getHeight = $menu.data('height');
  
                          if (!$menu.data('width')) $menu.data('width', $menu.width());
                          getWidth = $menu.data('width');
                      } else {
                          getHeight = $menu.height();
                          getWidth = $menu.width();
                      }
  
                      if (that.options.dropupAuto) {
                          that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
                      }
  
                      if (that.$newElement.hasClass('dropup')) {
                          menuHeight = selectOffsetTop - menuExtras.vert;
                      }
  
                      if (that.options.dropdownAlignRight === 'auto') {
                          $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
                      }
  
                      if ((lisVisible.length + optGroup.length) > 3) {
                          minHeight = liHeight * 3 + menuExtras.vert - 2;
                      } else {
                          minHeight = 0;
                      }
  
                      $menu.css({
                          'max-height': menuHeight + 'px',
                          'overflow': 'hidden',
                          'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
                      });
                      $menuInner.css({
                          'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
                          'overflow-y': 'auto',
                          'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
                      });
                  };
                  getSize();
                  this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
                  $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
              } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
                  var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
                      divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
                  menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
  
                  if (that.options.container) {
                      if (!$menu.data('height')) $menu.data('height', $menu.height());
                      getHeight = $menu.data('height');
                  } else {
                      getHeight = $menu.height();
                  }
  
                  if (that.options.dropupAuto) {
                      //noinspection JSUnusedAssignment
                      this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
                  }
                  $menu.css({
                      'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
                      'overflow': 'hidden',
                      'min-height': ''
                  });
                  $menuInner.css({
                      'max-height': menuHeight - menuPadding.vert + 'px',
                      'overflow-y': 'auto',
                      'min-height': ''
                  });
              }
          },
  
          setWidth: function () {
              if (this.options.width === 'auto') {
                  this.$menu.css('min-width', '0');
  
                  // Get correct width if element is hidden
                  var $selectClone = this.$menu.parent().clone().appendTo('body'),
                      $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
                      ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
                      btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
  
                  $selectClone.remove();
                  $selectClone2.remove();
  
                  // Set width to whatever's larger, button title or longest option
                  this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
              } else if (this.options.width === 'fit') {
                  // Remove inline min-width so width can be changed from 'auto'
                  this.$menu.css('min-width', '');
                  this.$newElement.css('width', '').addClass('fit-width');
              } else if (this.options.width) {
                  // Remove inline min-width so width can be changed from 'auto'
                  this.$menu.css('min-width', '');
                  this.$newElement.css('width', this.options.width);
              } else {
                  // Remove inline min-width/width so width can be changed
                  this.$menu.css('min-width', '');
                  this.$newElement.css('width', '');
              }
              // Remove fit-width class if width is changed programmatically
              if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
                  this.$newElement.removeClass('fit-width');
              }
          },
  
          selectPosition: function () {
              this.$bsContainer = $('<div class="bs-container" />');
  
              var that = this,
                  $container = $(this.options.container),
                  pos,
                  containerPos,
                  actualHeight,
                  getPlacement = function ($element) {
                      that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
                      pos = $element.offset();
  
                      if (!$container.is('body')) {
                          containerPos = $container.offset();
                          containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
                          containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
                      } else {
                          containerPos = { top: 0, left: 0 };
                      }
  
                      actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
  
                      that.$bsContainer.css({
                          'top': pos.top - containerPos.top + actualHeight,
                          'left': pos.left - containerPos.left,
                          'width': $element[0].offsetWidth
                      });
                  };
  
              this.$button.on('click', function () {
                  var $this = $(this);
  
                  if (that.isDisabled()) {
                      return;
                  }
  
                  getPlacement(that.$newElement);
  
                  that.$bsContainer
                      .appendTo(that.options.container)
                      .toggleClass('open', !$this.hasClass('open'))
                      .append(that.$menu);
              });
  
              $(window).on('resize scroll', function () {
                  getPlacement(that.$newElement);
              });
  
              this.$element.on('hide.bs.select', function () {
                  that.$menu.data('height', that.$menu.height());
                  that.$bsContainer.detach();
              });
          },
  
          /**
           * @param {number} index - the index of the option that is being changed
           * @param {boolean} selected - true if the option is being selected, false if being deselected
           * @param {JQuery} $lis - the 'li' element that is being modified
           */
          setSelected: function (index, selected, $lis) {
              if (!$lis) {
                  this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
                  $lis = this.findLis().eq(this.liObj[index]);
              }
  
              $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
          },
  
          /**
           * @param {number} index - the index of the option that is being disabled
           * @param {boolean} disabled - true if the option is being disabled, false if being enabled
           * @param {JQuery} $lis - the 'li' element that is being modified
           */
          setDisabled: function (index, disabled, $lis) {
              if (!$lis) {
                  $lis = this.findLis().eq(this.liObj[index]);
              }
  
              if (disabled) {
                  $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
              } else {
                  $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
              }
          },
  
          isDisabled: function () {
              return this.$element[0].disabled;
          },
  
          checkDisabled: function () {
              var that = this;
  
              if (this.isDisabled()) {
                  this.$newElement.addClass('disabled');
                  this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
              } else {
                  if (this.$button.hasClass('disabled')) {
                      this.$newElement.removeClass('disabled');
                      this.$button.removeClass('disabled').attr('aria-disabled', false);
                  }
  
                  if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
                      this.$button.removeAttr('tabindex');
                  }
              }
  
              this.$button.click(function () {
                  return !that.isDisabled();
              });
          },
  
          togglePlaceholder: function () {
              var value = this.$element.val();
              this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
          },
  
          tabIndex: function () {
              if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
                  (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
                  this.$element.data('tabindex', this.$element.attr('tabindex'));
                  this.$button.attr('tabindex', this.$element.data('tabindex'));
              }
  
              this.$element.attr('tabindex', -98);
          },
  
          clickListener: function () {
              var that = this,
                  $document = $(document);
  
              $document.data('spaceSelect', false);
  
              this.$button.on('keyup', function (e) {
                  if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
                      e.preventDefault();
                      $document.data('spaceSelect', false);
                  }
              });
  
              this.$button.on('click', function () {
                  that.setSize();
              });
  
              this.$element.on('shown.bs.select', function () {
                  if (!that.options.liveSearch && !that.multiple) {
                      that.$menuInner.find('.selected a').focus();
                  } else if (!that.multiple) {
                      var selectedIndex = that.liObj[that.$element[0].selectedIndex];
  
                      if (typeof selectedIndex !== 'number' || that.options.size === false) return;
  
                      // scroll to selected option
                      var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
                      offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
                      that.$menuInner[0].scrollTop = offset;
                  }
              });
  
              this.$menuInner.on('click', 'li a', function (e) {
                  var $this = $(this),
                      clickedIndex = $this.parent().data('originalIndex'),
                      prevValue = that.$element.val(),
                      prevIndex = that.$element.prop('selectedIndex'),
                      triggerChange = true;
  
                  // Don't close on multi choice menu
                  if (that.multiple && that.options.maxOptions !== 1) {
                      e.stopPropagation();
                  }
  
                  e.preventDefault();
  
                  //Don't run if we have been disabled
                  if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
                      var $options = that.$element.find('option'),
                          $option = $options.eq(clickedIndex),
                          state = $option.prop('selected'),
                          $optgroup = $option.parent('optgroup'),
                          maxOptions = that.options.maxOptions,
                          maxOptionsGrp = $optgroup.data('maxOptions') || false;
  
                      if (!that.multiple) { // Deselect all others if not multi select box
                          $options.prop('selected', false);
                          $option.prop('selected', true);
                          that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
                          that.setSelected(clickedIndex, true);
                      } else { // Toggle the one we have chosen if we are multi select.
                          $option.prop('selected', !state);
                          that.setSelected(clickedIndex, !state);
                          $this.blur();
  
                          if (maxOptions !== false || maxOptionsGrp !== false) {
                              var maxReached = maxOptions < $options.filter(':selected').length,
                                  maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
  
                              if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
                                  if (maxOptions && maxOptions == 1) {
                                      $options.prop('selected', false);
                                      $option.prop('selected', true);
                                      that.$menuInner.find('.selected').removeClass('selected');
                                      that.setSelected(clickedIndex, true);
                                  } else if (maxOptionsGrp && maxOptionsGrp == 1) {
                                      $optgroup.find('option:selected').prop('selected', false);
                                      $option.prop('selected', true);
                                      var optgroupID = $this.parent().data('optgroup');
                                      that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
                                      that.setSelected(clickedIndex, true);
                                  } else {
                                      var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
                                          maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
                                          maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
                                          maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
                                          $notify = $('<div class="notify"></div>');
                                      // If {var} is set in array, replace it
                                      /** @deprecated */
                                      if (maxOptionsArr[2]) {
                                          maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
                                          maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
                                      }
  
                                      $option.prop('selected', false);
  
                                      that.$menu.append($notify);
  
                                      if (maxOptions && maxReached) {
                                          $notify.append($('<div>' + maxTxt + '</div>'));
                                          triggerChange = false;
                                          that.$element.trigger('maxReached.bs.select');
                                      }
  
                                      if (maxOptionsGrp && maxReachedGrp) {
                                          $notify.append($('<div>' + maxTxtGrp + '</div>'));
                                          triggerChange = false;
                                          that.$element.trigger('maxReachedGrp.bs.select');
                                      }
  
                                      setTimeout(function () {
                                          that.setSelected(clickedIndex, false);
                                      }, 10);
  
                                      $notify.delay(750).fadeOut(300, function () {
                                          $(this).remove();
                                      });
                                  }
                              }
                          }
                      }
  
                      if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
                          that.$button.focus();
                      } else if (that.options.liveSearch) {
                          that.$searchbox.focus();
                      }
  
                      // Trigger select 'change'
                      if (triggerChange) {
                          if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
                              // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
                              changed_arguments = [clickedIndex, $option.prop('selected'), state];
                              that.$element
                                  .triggerNative('change');
                          }
                      }
                  }
              });
  
              this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
                  if (e.currentTarget == this) {
                      e.preventDefault();
                      e.stopPropagation();
                      if (that.options.liveSearch && !$(e.target).hasClass('close')) {
                          that.$searchbox.focus();
                      } else {
                          that.$button.focus();
                      }
                  }
              });
  
              this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
                  e.preventDefault();
                  e.stopPropagation();
                  if (that.options.liveSearch) {
                      that.$searchbox.focus();
                  } else {
                      that.$button.focus();
                  }
              });
  
              this.$menu.on('click', '.popover-title .close', function () {
                  that.$button.click();
              });
  
              this.$searchbox.on('click', function (e) {
                  e.stopPropagation();
              });
  
              this.$menu.on('click', '.actions-btn', function (e) {
                  if (that.options.liveSearch) {
                      that.$searchbox.focus();
                  } else {
                      that.$button.focus();
                  }
  
                  e.preventDefault();
                  e.stopPropagation();
  
                  if ($(this).hasClass('bs-select-all')) {
                      that.selectAll();
                  } else {
                      that.deselectAll();
                  }
              });
  
              this.$element.change(function () {
                  that.render(false);
                  that.$element.trigger('changed.bs.select', changed_arguments);
                  changed_arguments = null;
              });
          },
  
          liveSearchListener: function () {
              var that = this,
                  $no_results = $('<li class="no-results"></li>');
  
              this.$button.on('click.dropdown.data-api', function () {
                  that.$menuInner.find('.active').removeClass('active');
                  if (!!that.$searchbox.val()) {
                      that.$searchbox.val('');
                      that.$lis.not('.is-hidden').removeClass('hidden');
                      if (!!$no_results.parent().length) $no_results.remove();
                  }
                  if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
                  setTimeout(function () {
                      that.$searchbox.focus();
                  }, 10);
              });
  
              this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
                  e.stopPropagation();
              });
  
              this.$searchbox.on('input propertychange', function () {
                  that.$lis.not('.is-hidden').removeClass('hidden');
                  that.$lis.filter('.active').removeClass('active');
                  $no_results.remove();
  
                  if (that.$searchbox.val()) {
                      var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
                          $hideItems;
                      if (that.options.liveSearchNormalize) {
                          $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
                      } else {
                          $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
                      }
  
                      if ($hideItems.length === $searchBase.length) {
                          $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
                          that.$menuInner.append($no_results);
                          that.$lis.addClass('hidden');
                      } else {
                          $hideItems.addClass('hidden');
  
                          var $lisVisible = that.$lis.not('.hidden'),
                              $foundDiv;
  
                          // hide divider if first or last visible, or if followed by another divider
                          $lisVisible.each(function (index) {
                              var $this = $(this);
  
                              if ($this.hasClass('divider')) {
                                  if ($foundDiv === undefined) {
                                      $this.addClass('hidden');
                                  } else {
                                      if ($foundDiv) $foundDiv.addClass('hidden');
                                      $foundDiv = $this;
                                  }
                              } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
                                  $this.addClass('hidden');
                              } else {
                                  $foundDiv = null;
                              }
                          });
                          if ($foundDiv) $foundDiv.addClass('hidden');
  
                          $searchBase.not('.hidden').first().addClass('active');
                          that.$menuInner.scrollTop(0);
                      }
                  }
              });
          },
  
          _searchStyle: function () {
              var styles = {
                  begins: 'ibegins',
                  startsWith: 'ibegins'
              };
  
              return styles[this.options.liveSearchStyle] || 'icontains';
          },
  
          val: function (value) {
              if (typeof value !== 'undefined') {
                  this.$element.val(value);
                  this.render();
  
                  return this.$element;
              } else {
                  return this.$element.val();
              }
          },
  
          changeAll: function (status) {
              if (!this.multiple) return;
              if (typeof status === 'undefined') status = true;
  
              this.findLis();
  
              var $options = this.$element.find('option'),
                  $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
                  lisVisLen = $lisVisible.length,
                  selectedOptions = [];
  
              if (status) {
                  if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
              } else {
                  if ($lisVisible.filter('.selected').length === 0) return;
              }
  
              $lisVisible.toggleClass('selected', status);
  
              for (var i = 0; i < lisVisLen; i++) {
                  var origIndex = $lisVisible[i].getAttribute('data-original-index');
                  selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
              }
  
              $(selectedOptions).prop('selected', status);
  
              this.render(false);
  
              this.togglePlaceholder();
  
              this.$element
                  .triggerNative('change');
          },
  
          selectAll: function () {
              return this.changeAll(true);
          },
  
          deselectAll: function () {
              return this.changeAll(false);
          },
  
          toggle: function (e) {
              e = e || window.event;
  
              if (e) e.stopPropagation();
  
              this.$button.trigger('click');
          },
  
          keydown: function (e) {
              var $this = $(this),
                  $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
                  $items,
                  that = $parent.data('this'),
                  index,
                  prevIndex,
                  isActive,
                  selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
                  keyCodeMap = {
                      32: ' ',
                      48: '0',
                      49: '1',
                      50: '2',
                      51: '3',
                      52: '4',
                      53: '5',
                      54: '6',
                      55: '7',
                      56: '8',
                      57: '9',
                      59: ';',
                      65: 'a',
                      66: 'b',
                      67: 'c',
                      68: 'd',
                      69: 'e',
                      70: 'f',
                      71: 'g',
                      72: 'h',
                      73: 'i',
                      74: 'j',
                      75: 'k',
                      76: 'l',
                      77: 'm',
                      78: 'n',
                      79: 'o',
                      80: 'p',
                      81: 'q',
                      82: 'r',
                      83: 's',
                      84: 't',
                      85: 'u',
                      86: 'v',
                      87: 'w',
                      88: 'x',
                      89: 'y',
                      90: 'z',
                      96: '0',
                      97: '1',
                      98: '2',
                      99: '3',
                      100: '4',
                      101: '5',
                      102: '6',
                      103: '7',
                      104: '8',
                      105: '9'
                  };
  
  
              isActive = that.$newElement.hasClass('open');
  
              if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
                  if (!that.options.container) {
                      that.setSize();
                      that.$menu.parent().addClass('open');
                      isActive = true;
                  } else {
                      that.$button.trigger('click');
                  }
                  that.$searchbox.focus();
                  return;
              }
  
              if (that.options.liveSearch) {
                  if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
                      e.preventDefault();
                      e.stopPropagation();
                      that.$menuInner.click();
                      that.$button.focus();
                  }
              }
  
              if (/(38|40)/.test(e.keyCode.toString(10))) {
                  $items = that.$lis.filter(selector);
                  if (!$items.length) return;
  
                  if (!that.options.liveSearch) {
                      index = $items.index($items.find('a').filter(':focus').parent());
                  } else {
                      index = $items.index($items.filter('.active'));
                  }
  
                  prevIndex = that.$menuInner.data('prevIndex');
  
                  if (e.keyCode == 38) {
                      if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
                      if (index < 0) index += $items.length;
                  } else if (e.keyCode == 40) {
                      if (that.options.liveSearch || index == prevIndex) index++;
                      index = index % $items.length;
                  }
  
                  that.$menuInner.data('prevIndex', index);
  
                  if (!that.options.liveSearch) {
                      $items.eq(index).children('a').focus();
                  } else {
                      e.preventDefault();
                      if (!$this.hasClass('dropdown-toggle')) {
                          $items.removeClass('active').eq(index).addClass('active').children('a').focus();
                          $this.focus();
                      }
                  }
  
              } else if (!$this.is('input')) {
                  var keyIndex = [],
                      count,
                      prevKey;
  
                  $items = that.$lis.filter(selector);
                  $items.each(function (i) {
                      if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
                          keyIndex.push(i);
                      }
                  });
  
                  count = $(document).data('keycount');
                  count++;
                  $(document).data('keycount', count);
  
                  prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
  
                  if (prevKey != keyCodeMap[e.keyCode]) {
                      count = 1;
                      $(document).data('keycount', count);
                  } else if (count >= keyIndex.length) {
                      $(document).data('keycount', 0);
                      if (count > keyIndex.length) count = 1;
                  }
  
                  $items.eq(keyIndex[count - 1]).children('a').focus();
              }
  
              // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
              if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
                  if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
                  if (!that.options.liveSearch) {
                      var elem = $(':focus');
                      elem.click();
                      // Bring back focus for multiselects
                      elem.focus();
                      // Prevent screen from scrolling if the user hit the spacebar
                      e.preventDefault();
                      // Fixes spacebar selection of dropdown items in FF & IE
                      $(document).data('spaceSelect', true);
                  } else if (!/(32)/.test(e.keyCode.toString(10))) {
                      that.$menuInner.find('.active a').click();
                      $this.focus();
                  }
                  $(document).data('keycount', 0);
              }
  
              if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
                  that.$menu.parent().removeClass('open');
                  if (that.options.container) that.$newElement.removeClass('open');
                  that.$button.focus();
              }
          },
  
          mobile: function () {
              this.$element.addClass('mobile-device');
          },
  
          refresh: function () {
              this.$lis = null;
              this.liObj = {};
              this.reloadLi();
              this.render();
              this.checkDisabled();
              this.liHeight(true);
              this.setStyle();
              this.setWidth();
              if (this.$lis) this.$searchbox.trigger('propertychange');
  
              this.$element.trigger('refreshed.bs.select');
          },
  
          hide: function () {
              this.$newElement.hide();
          },
  
          show: function () {
              this.$newElement.show();
          },
  
          remove: function () {
              this.$newElement.remove();
              this.$element.remove();
          },
  
          destroy: function () {
              this.$newElement.before(this.$element).remove();
  
              if (this.$bsContainer) {
                  this.$bsContainer.remove();
              } else {
                  this.$menu.remove();
              }
  
              this.$element
                  .off('.bs.select')
                  .removeData('selectpicker')
                  .removeClass('bs-select-hidden selectpicker');
          }
      };
  
      // SELECTPICKER PLUGIN DEFINITION
      // ==============================
      function Plugin(option) {
          // get the args of the outer function..
          var args = arguments;
          // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
          // to get lost/corrupted in android 2.3 and IE9 #715 #775
          var _option = option;
  
          [].shift.apply(args);
  
          var value;
          var chain = this.each(function () {
              var $this = $(this);
              if ($this.is('select')) {
                  var data = $this.data('selectpicker'),
                      options = typeof _option == 'object' && _option;
  
                  if (!data) {
                      var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
                      config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
                      $this.data('selectpicker', (data = new Selectpicker(this, config)));
                  } else if (options) {
                      for (var i in options) {
                          if (options.hasOwnProperty(i)) {
                              data.options[i] = options[i];
                          }
                      }
                  }
  
                  if (typeof _option == 'string') {
                      if (data[_option] instanceof Function) {
                          value = data[_option].apply(data, args);
                      } else {
                          value = data.options[_option];
                      }
                  }
              }
          });
  
          if (typeof value !== 'undefined') {
              //noinspection JSUnusedAssignment
              return value;
          } else {
              return chain;
          }
      }
  
      var old = $.fn.selectpicker;
      $.fn.selectpicker = Plugin;
      $.fn.selectpicker.Constructor = Selectpicker;
  
      // SELECTPICKER NO CONFLICT
      // ========================
      $.fn.selectpicker.noConflict = function () {
          $.fn.selectpicker = old;
          return this;
      };
  
      $(document)
          .data('keycount', 0)
          .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
          .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
              e.stopPropagation();
          });
  
      // SELECTPICKER DATA-API
      // =====================
      $(window).on('load.bs.select.data-api', function () {
          $('.selectpicker').each(function () {
              var $selectpicker = $(this);
              Plugin.call($selectpicker, $selectpicker.data());
          })
      });
  })(jQuery);
  /*!
   * Datepicker for Bootstrap v1.7.0-dev (https://github.com/uxsolutions/bootstrap-datepicker)
   *
   * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
   */
  
  !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(c,d){return function(){return d!==b&&a.fn.datepicker.deprecated(d),this[c].apply(this,arguments)}}function g(a){return a&&!isNaN(a.getTime())}function h(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function i(b){var c={};if(q[b]||(b=b.split("-")[0],q[b])){var d=q[b];return a.each(p,function(a,b){b in d&&(c[b]=d[b])}),c}}var j=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;d>c;c++)if(0<=this[c].valueOf()-b&&this[c].valueOf()-b<864e5)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new j;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),k=function(b,c){a.data(b,"datepicker",this),this._process_options(c),this.dates=new j,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInput=this.element.is("input"),this.inputField=this.isInput?this.element:this.element.find("input"),this.component=this.element.hasClass("date")?this.element.find(".add-on, .input-group-addon, .btn"):!1,this.component&&0===this.component.length&&(this.component=!1),this.isInline=!this.component&&this.element.is("div"),this.picker=a(r.template),this._check_template(this.o.templates.leftArrow)&&this.picker.find(".prev").html(this.o.templates.leftArrow),this._check_template(this.o.templates.rightArrow)&&this.picker.find(".next").html(this.o.templates.rightArrow),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.o.calendarWeeks&&this.picker.find(".datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear").attr("colspan",function(a,b){return Number(b)+1}),this._process_options({startDate:this._o.startDate,endDate:this._o.endDate,daysOfWeekDisabled:this.o.daysOfWeekDisabled,daysOfWeekHighlighted:this.o.daysOfWeekHighlighted,datesDisabled:this.o.datesDisabled}),this._allow_update=!1,this.setViewMode(this.o.startView),this._allow_update=!0,this.fillDow(),this.fillMonths(),this.update(),this.isInline&&this.show()};k.prototype={constructor:k,_resolveViewName:function(b){return a.each(r.viewModes,function(c,d){return b===c||-1!==a.inArray(b,d.names)?(b=c,!1):void 0}),b},_resolveDaysOfWeek:function(b){return a.isArray(b)||(b=b.split(/[,\s]*/)),a.map(b,Number)},_check_template:function(c){try{if(c===b||""===c)return!1;if((c.match(/[<>]/g)||[]).length<=0)return!0;var d=a(c);return d.length>0}catch(e){return!1}},_process_options:function(b){this._o=a.extend({},this._o,b);var e=this.o=a.extend({},this._o),f=e.language;q[f]||(f=f.split("-")[0],q[f]||(f=o.language)),e.language=f,e.startView=this._resolveViewName(e.startView),e.minViewMode=this._resolveViewName(e.minViewMode),e.maxViewMode=this._resolveViewName(e.maxViewMode),e.startView=Math.max(this.o.minViewMode,Math.min(this.o.maxViewMode,e.startView)),e.multidate!==!0&&(e.multidate=Number(e.multidate)||!1,e.multidate!==!1&&(e.multidate=Math.max(0,e.multidate))),e.multidateSeparator=String(e.multidateSeparator),e.weekStart%=7,e.weekEnd=(e.weekStart+6)%7;var g=r.parseFormat(e.format);e.startDate!==-(1/0)&&(e.startDate?e.startDate instanceof Date?e.startDate=this._local_to_utc(this._zero_time(e.startDate)):e.startDate=r.parseDate(e.startDate,g,e.language,e.assumeNearbyYear):e.startDate=-(1/0)),e.endDate!==1/0&&(e.endDate?e.endDate instanceof Date?e.endDate=this._local_to_utc(this._zero_time(e.endDate)):e.endDate=r.parseDate(e.endDate,g,e.language,e.assumeNearbyYear):e.endDate=1/0),e.daysOfWeekDisabled=this._resolveDaysOfWeek(e.daysOfWeekDisabled||[]),e.daysOfWeekHighlighted=this._resolveDaysOfWeek(e.daysOfWeekHighlighted||[]),e.datesDisabled=e.datesDisabled||[],a.isArray(e.datesDisabled)||(e.datesDisabled=e.datesDisabled.split(",")),e.datesDisabled=a.map(e.datesDisabled,function(a){return r.parseDate(a,g,e.language,e.assumeNearbyYear)});var h=String(e.orientation).toLowerCase().split(/\s+/g),i=e.orientation.toLowerCase();if(h=a.grep(h,function(a){return/^auto|left|right|top|bottom$/.test(a)}),e.orientation={x:"auto",y:"auto"},i&&"auto"!==i)if(1===h.length)switch(h[0]){case"top":case"bottom":e.orientation.y=h[0];break;case"left":case"right":e.orientation.x=h[0]}else i=a.grep(h,function(a){return/^left|right$/.test(a)}),e.orientation.x=i[0]||"auto",i=a.grep(h,function(a){return/^top|bottom$/.test(a)}),e.orientation.y=i[0]||"auto";else;if(e.defaultViewDate instanceof Date||"string"==typeof e.defaultViewDate)e.defaultViewDate=r.parseDate(e.defaultViewDate,g,e.language,e.assumeNearbyYear);else if(e.defaultViewDate){var j=e.defaultViewDate.year||(new Date).getFullYear(),k=e.defaultViewDate.month||0,l=e.defaultViewDate.day||1;e.defaultViewDate=c(j,k,l)}else e.defaultViewDate=d()},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(d=b,e=a[f][1]):3===a[f].length&&(d=a[f][1],e=a[f][2]),c.on(e,d)},_unapplyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(e=b,d=a[f][1]):3===a[f].length&&(e=a[f][1],d=a[f][2]),c.off(d,e)},_buildEvents:function(){var b={keyup:a.proxy(function(b){-1===a.inArray(b.keyCode,[27,37,39,38,40,32,13,9])&&this.update()},this),keydown:a.proxy(this.keydown,this),paste:a.proxy(this.paste,this)};this.o.showOnFocus===!0&&(b.focus=a.proxy(this.show,this)),this.isInput?this._events=[[this.element,b]]:this.component&&this.inputField.length?this._events=[[this.inputField,b],[this.component,{click:a.proxy(this.show,this)}]]:this._events=[[this.element,{click:a.proxy(this.show,this),keydown:a.proxy(this.keydown,this)}]],this._events.push([this.element,"*",{blur:a.proxy(function(a){this._focused_from=a.target},this)}],[this.element,{blur:a.proxy(function(a){this._focused_from=a.target},this)}]),this.o.immediateUpdates&&this._events.push([this.element,{"changeYear changeMonth":a.proxy(function(a){this.update(a.date)},this)}]),this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[this.picker,".prev, .next",{click:a.proxy(this.navArrowsClick,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{"mousedown touchstart":a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).length||this.picker.is(a.target)||this.picker.find(a.target).length||this.isInline||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.dates.get(-1),e=this._utc_to_local(d);this.element.trigger({type:b,date:e,viewMode:this.viewMode,dates:a.map(this.dates,this._utc_to_local),format:a.proxy(function(a,b){0===arguments.length?(a=this.dates.length-1,b=this.o.format):"string"==typeof a&&(b=a,a=this.dates.length-1),b=b||this.o.format;var c=this.dates.get(a);return r.formatDate(c,b,this.o.language)},this)})},show:function(){return this.inputField.prop("disabled")||this.inputField.prop("readonly")&&this.o.enableOnReadonly===!1?void 0:(this.isInline||this.picker.appendTo(this.o.container),this.place(),this.picker.show(),this._attachSecondaryEvents(),this._trigger("show"),(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&this.o.disableTouchKeyboard&&a(this.element).blur(),this)},hide:function(){return this.isInline||!this.picker.is(":visible")?this:(this.focusDate=null,this.picker.hide().detach(),this._detachSecondaryEvents(),this.setViewMode(this.o.startView),this.o.forceParse&&this.inputField.val()&&this.setValue(),this._trigger("hide"),this)},destroy:function(){return this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date,this},paste:function(b){var c;if(b.originalEvent.clipboardData&&b.originalEvent.clipboardData.types&&-1!==a.inArray("text/plain",b.originalEvent.clipboardData.types))c=b.originalEvent.clipboardData.getData("text/plain");else{if(!window.clipboardData)return;c=window.clipboardData.getData("Text")}this.setDate(c),this.update(),b.preventDefault()},_utc_to_local:function(a){if(!a)return a;var b=new Date(a.getTime()+6e4*a.getTimezoneOffset());return b.getTimezoneOffset()!==a.getTimezoneOffset()&&(b=new Date(a.getTime()+6e4*b.getTimezoneOffset())),b},_local_to_utc:function(a){return a&&new Date(a.getTime()-6e4*a.getTimezoneOffset())},_zero_time:function(a){return a&&new Date(a.getFullYear(),a.getMonth(),a.getDate())},_zero_utc_time:function(a){return a&&c(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate())},getDates:function(){return a.map(this.dates,this._utc_to_local)},getUTCDates:function(){return a.map(this.dates,function(a){return new Date(a)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){var a=this.dates.get(-1);return a!==b?new Date(a):null},clearDates:function(){this.inputField.val(""),this.update(),this._trigger("changeDate"),this.o.autoclose&&this.hide()},setDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.update.apply(this,b),this._trigger("changeDate"),this.setValue(),this},setUTCDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.setDates.apply(this,a.map(b,this._utc_to_local)),this},setDate:f("setDates"),setUTCDate:f("setUTCDates"),remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead"),setValue:function(){var a=this.getFormattedDate();return this.inputField.val(a),this},getFormattedDate:function(c){c===b&&(c=this.o.format);var d=this.o.language;return a.map(this.dates,function(a){return r.formatDate(a,c,d)}).join(this.o.multidateSeparator)},getStartDate:function(){return this.o.startDate},setStartDate:function(a){return this._process_options({startDate:a}),this.update(),this.updateNavArrows(),this},getEndDate:function(){return this.o.endDate},setEndDate:function(a){return this._process_options({endDate:a}),this.update(),this.updateNavArrows(),this},setDaysOfWeekDisabled:function(a){return this._process_options({daysOfWeekDisabled:a}),this.update(),this},setDaysOfWeekHighlighted:function(a){return this._process_options({daysOfWeekHighlighted:a}),this.update(),this},setDatesDisabled:function(a){return this._process_options({datesDisabled:a}),this.update(),this},place:function(){if(this.isInline)return this;var b=this.picker.outerWidth(),c=this.picker.outerHeight(),d=10,e=a(this.o.container),f=e.width(),g="body"===this.o.container?a(document).scrollTop():e.scrollTop(),h=e.offset(),i=[0];this.element.parents().each(function(){var b=a(this).css("z-index");"auto"!==b&&0!==Number(b)&&i.push(Number(b))});var j=Math.max.apply(Math,i)+this.o.zIndexOffset,k=this.component?this.component.parent().offset():this.element.offset(),l=this.component?this.component.outerHeight(!0):this.element.outerHeight(!1),m=this.component?this.component.outerWidth(!0):this.element.outerWidth(!1),n=k.left-h.left,o=k.top-h.top;"body"!==this.o.container&&(o+=g),this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom datepicker-orient-right datepicker-orient-left"),"auto"!==this.o.orientation.x?(this.picker.addClass("datepicker-orient-"+this.o.orientation.x),"right"===this.o.orientation.x&&(n-=b-m)):k.left<0?(this.picker.addClass("datepicker-orient-left"),n-=k.left-d):n+b>f?(this.picker.addClass("datepicker-orient-right"),n+=m-b):this.o.rtl?this.picker.addClass("datepicker-orient-right"):this.picker.addClass("datepicker-orient-left");var p,q=this.o.orientation.y;if("auto"===q&&(p=-g+o-c,q=0>p?"bottom":"top"),this.picker.addClass("datepicker-orient-"+q),"top"===q?o-=c+parseInt(this.picker.css("padding-top")):o+=l,this.o.rtl){var r=f-(n+m);this.picker.css({top:o,right:r,zIndex:j})}else this.picker.css({top:o,left:n,zIndex:j});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.inputField.val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return r.parseDate(a,this.o.format,this.o.language,this.o.assumeNearbyYear)},this)),c=a.grep(c,a.proxy(function(a){return!this.dateWithinRange(a)||!a},this),!0),this.dates.replace(c),this.o.updateViewDate&&(this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDate<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.viewDate>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=this.o.defaultViewDate),d?(this.setValue(),this.element.change()):this.dates.length&&("string"==typeof this.o.format?(String(this.element[0].value).length===String(this.o.format).length&&String(b)!==String(this.dates)&&this._trigger("changeDate"),this.element.change()):String(b)!==String(this.dates)&&(this._trigger("changeDate"),this.element.change())),!this.dates.length&&b.length&&(this._trigger("clearDate"),this.element.change()),this.fill(),this},fillDow:function(){var b=this.o.weekStart,c="<tr>";for(this.o.calendarWeeks&&(c+='<th class="cw">&#160;</th>');b<this.o.weekStart+7;)c+='<th class="dow',-1!==a.inArray(b,this.o.daysOfWeekDisabled)&&(c+=" disabled"),c+='">'+q[this.o.language].daysMin[b++%7]+"</th>";c+="</tr>",this.picker.find(".datepicker-days thead").append(c)},fillMonths:function(){for(var a,b=this._utc_to_local(this.viewDate),c="",d=0;12>d;d++)a=b&&b.getMonth()===d?" focused":"",c+='<span class="month'+a+'">'+q[this.o.language].monthsShort[d]+"</span>";this.picker.find(".datepicker-months td").html(c)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],f=this.viewDate.getUTCFullYear(),g=this.viewDate.getUTCMonth(),h=d();return b.getUTCFullYear()<f||b.getUTCFullYear()===f&&b.getUTCMonth()<g?c.push("old"):(b.getUTCFullYear()>f||b.getUTCFullYear()===f&&b.getUTCMonth()>g)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&e(b,h)&&c.push("today"),-1!==this.dates.contains(b)&&c.push("active"),this.dateWithinRange(b)||c.push("disabled"),this.dateIsDisabled(b)&&c.push("disabled","disabled-date"),-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekHighlighted)&&c.push("highlighted"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!==a.inArray(b.valueOf(),this.range)&&c.push("selected"),b.valueOf()===this.range[0]&&c.push("range-start"),b.valueOf()===this.range[this.range.length-1]&&c.push("range-end")),c},_fill_yearsView:function(c,d,e,f,g,h,i){for(var j,k,l,m="",n=e/10,o=this.picker.find(c),p=Math.floor(f/e)*e,q=p+9*n,r=Math.floor(this.viewDate.getFullYear()/n)*n,s=a.map(this.dates,function(a){return Math.floor(a.getUTCFullYear()/n)*n}),t=p-n;q+n>=t;t+=n)j=[d],k=null,t===p-n?j.push("old"):t===q+n&&j.push("new"),-1!==a.inArray(t,s)&&j.push("active"),(g>t||t>h)&&j.push("disabled"),t===r&&j.push("focused"),i!==a.noop&&(l=i(new Date(t,0,1)),l===b?l={}:"boolean"==typeof l?l={enabled:l}:"string"==typeof l&&(l={classes:l}),l.enabled===!1&&j.push("disabled"),l.classes&&(j=j.concat(l.classes.split(/\s+/))),l.tooltip&&(k=l.tooltip)),m+='<span class="'+j.join(" ")+'"'+(k?' title="'+k+'"':"")+">"+t+"</span>";o.find(".datepicker-switch").text(p+"-"+q),o.find("td").html(m)},fill:function(){var d,e,f=new Date(this.viewDate),g=f.getUTCFullYear(),h=f.getUTCMonth(),i=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),j=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),k=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,l=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,m=q[this.o.language].today||q.en.today||"",n=q[this.o.language].clear||q.en.clear||"",o=q[this.o.language].titleFormat||q.en.titleFormat;if(!isNaN(g)&&!isNaN(h)){this.picker.find(".datepicker-days .datepicker-switch").text(r.formatDate(f,o,this.o.language)),this.picker.find("tfoot .today").text(m).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot .clear").text(n).toggle(this.o.clearBtn!==!1),this.picker.find("thead .datepicker-title").text(this.o.title).toggle(""!==this.o.title),this.updateNavArrows(),this.fillMonths();var p=c(g,h,0),s=p.getUTCDate();p.setUTCDate(s-(p.getUTCDay()-this.o.weekStart+7)%7);var t=new Date(p);p.getUTCFullYear()<100&&t.setUTCFullYear(p.getUTCFullYear()),t.setUTCDate(t.getUTCDate()+42),t=t.valueOf();for(var u,v,w=[];p.valueOf()<t;){if(u=p.getUTCDay(),u===this.o.weekStart&&(w.push("<tr>"),this.o.calendarWeeks)){var x=new Date(+p+(this.o.weekStart-u-7)%7*864e5),y=new Date(Number(x)+(11-x.getUTCDay())%7*864e5),z=new Date(Number(z=c(y.getUTCFullYear(),0,1))+(11-z.getUTCDay())%7*864e5),A=(y-z)/864e5/7+1;w.push('<td class="cw">'+A+"</td>")}v=this.getClassNames(p),v.push("day"),this.o.beforeShowDay!==a.noop&&(e=this.o.beforeShowDay(this._utc_to_local(p)),e===b?e={}:"boolean"==typeof e?e={enabled:e}:"string"==typeof e&&(e={classes:e}),e.enabled===!1&&v.push("disabled"),e.classes&&(v=v.concat(e.classes.split(/\s+/))),e.tooltip&&(d=e.tooltip)),v=a.isFunction(a.uniqueSort)?a.uniqueSort(v):a.unique(v),w.push('<td class="'+v.join(" ")+'"'+(d?' title="'+d+'"':"")+(this.o.dateCells?' data-date="'+p.getTime().toString()+'"':"")+">"+p.getUTCDate()+"</td>"),d=null,u===this.o.weekEnd&&w.push("</tr>"),p.setUTCDate(p.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").html(w.join(""));var B=q[this.o.language].monthsTitle||q.en.monthsTitle||"Months",C=this.picker.find(".datepicker-months").find(".datepicker-switch").text(this.o.maxViewMode<2?B:g).end().find("tbody span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===g&&C.eq(b.getUTCMonth()).addClass("active")}),(i>g||g>k)&&C.addClass("disabled"),g===i&&C.slice(0,j).addClass("disabled"),g===k&&C.slice(l+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var D=this;a.each(C,function(c,d){var e=new Date(g,c,1),f=D.o.beforeShowMonth(e);f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),f.enabled!==!1||a(d).hasClass("disabled")||a(d).addClass("disabled"),f.classes&&a(d).addClass(f.classes),f.tooltip&&a(d).prop("title",f.tooltip)})}this._fill_yearsView(".datepicker-years","year",10,g,i,k,this.o.beforeShowYear),this._fill_yearsView(".datepicker-decades","decade",100,g,i,k,this.o.beforeShowDecade),this._fill_yearsView(".datepicker-centuries","century",1e3,g,i,k,this.o.beforeShowCentury)}},updateNavArrows:function(){if(this._allow_update){var a,b,c=new Date(this.viewDate),d=c.getUTCFullYear(),e=c.getUTCMonth(),f=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),g=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),h=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,i=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,j=1;switch(this.viewMode){case 0:a=f>=d&&g>=e,b=d>=h&&e>=i;break;case 4:j*=10;case 3:j*=10;case 2:j*=10;case 1:a=Math.floor(d/j)*j<=f,b=Math.floor(d/j)*j+j>=h}this.picker.find(".prev").toggleClass("disabled",a),this.picker.find(".next").toggleClass("disabled",b)}},click:function(b){b.preventDefault(),b.stopPropagation();var e,f,g,h,i;e=a(b.target),e.hasClass("datepicker-switch")&&this.viewMode!==this.o.maxViewMode&&this.setViewMode(this.viewMode+1),e.hasClass("today")&&!e.hasClass("day")&&(this.setViewMode(0),this._setDate(d(),"linked"===this.o.todayBtn?null:"view")),e.hasClass("clear")&&this.clearDates(),e.hasClass("disabled")||(e.hasClass("day")&&(g=Number(e.text()),h=this.viewDate.getUTCFullYear(),i=this.viewDate.getUTCMonth(),(e.hasClass("old")||e.hasClass("new"))&&(f=e.hasClass("old")?-1:1,i=(i+f+12)%12,(-1===f&&11===i||1===f&&0===i)&&(h+=f,this.o.updateViewDate&&this._trigger("changeYear",this.viewDate)),this.o.updateViewDate&&this._trigger("changeMonth",this.viewDate)),this._setDate(c(h,i,g))),(e.hasClass("month")||e.hasClass("year")||e.hasClass("decade")||e.hasClass("century"))&&(this.viewDate.setUTCDate(1),g=1,1===this.viewMode?(i=e.parent().find("span").index(e),h=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(i)):(i=0,h=Number(e.text()),this.viewDate.setUTCFullYear(h)),this._trigger(r.viewModes[this.viewMode-1].e,this.viewDate),this.viewMode===this.o.minViewMode?this._setDate(c(h,i,g)):(this.setViewMode(this.viewMode-1),this.fill()))),this.picker.is(":visible")&&this._focused_from&&this._focused_from.focus(),delete this._focused_from},navArrowsClick:function(b){var c=a(b.target),d=c.hasClass("prev")?-1:1;0!==this.viewMode&&(d*=12*r.viewModes[this.viewMode].navStep),this.viewDate=this.moveMonth(this.viewDate,d),this._trigger(r.viewModes[this.viewMode].e,this.viewDate),this.fill()},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),-1!==b?(this.o.multidate===!0||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):this.o.multidate===!1?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)},_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),(!b&&this.o.updateViewDate||"view"===b)&&(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate"),this.inputField.trigger("change"),!this.o.autoclose||b&&"date"!==b||this.hide()},moveDay:function(a,b){var c=new Date(a);return c.setUTCDate(a.getUTCDate()+b),c},moveWeek:function(a,b){return this.moveDay(a,7*b)},moveMonth:function(a,b){if(!g(a))return this.o.defaultViewDate;if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),h=e.getUTCMonth(),i=Math.abs(b);if(b=b>0?1:-1,1===i)d=-1===b?function(){return e.getUTCMonth()===h}:function(){return e.getUTCMonth()!==c},c=h+b,e.setUTCMonth(c),c=(c+12)%12;else{for(var j=0;i>j;j++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!==e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},moveAvailableDate:function(a,b,c){do{if(a=this[c](a,b),!this.dateWithinRange(a))return!1;c="moveDay"}while(this.dateIsDisabled(a));return a},weekOfDateIsDisabled:function(b){return-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled)},dateIsDisabled:function(b){return this.weekOfDateIsDisabled(b)||a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void((40===a.keyCode||27===a.keyCode)&&(this.show(),a.stopPropagation()));var b,c,d=!1,e=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault(),a.stopPropagation();break;case 37:case 38:case 39:case 40:if(!this.o.keyboardNavigation||7===this.o.daysOfWeekDisabled.length)break;b=37===a.keyCode||38===a.keyCode?-1:1,0===this.viewMode?a.ctrlKey?(c=this.moveAvailableDate(e,b,"moveYear"),c&&this._trigger("changeYear",this.viewDate)):a.shiftKey?(c=this.moveAvailableDate(e,b,"moveMonth"),c&&this._trigger("changeMonth",this.viewDate)):37===a.keyCode||39===a.keyCode?c=this.moveAvailableDate(e,b,"moveDay"):this.weekOfDateIsDisabled(e)||(c=this.moveAvailableDate(e,b,"moveWeek")):1===this.viewMode?((38===a.keyCode||40===a.keyCode)&&(b=4*b),c=this.moveAvailableDate(e,b,"moveMonth")):2===this.viewMode&&((38===a.keyCode||40===a.keyCode)&&(b=4*b),c=this.moveAvailableDate(e,b,"moveYear")),c&&(this.focusDate=this.viewDate=c,this.setValue(),this.fill(),a.preventDefault());break;case 13:if(!this.o.forceParse)break;e=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(e),d=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),a.stopPropagation(),this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}d&&(this.dates.length?this._trigger("changeDate"):this._trigger("clearDate"),this.inputField.trigger("change"))},setViewMode:function(a){this.viewMode=a,this.picker.children("div").hide().filter(".datepicker-"+r.viewModes[this.viewMode].clsName).show(),this.updateNavArrows(),this._trigger("changeViewMode",new Date(this.viewDate))}};var l=function(b,c){a.data(b,"datepicker",this),this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,this.keepEmptyValues=c.keepEmptyValues,delete c.keepEmptyValues,n.call(a(this.inputs),c).on("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a.data(b,"datepicker")}),this.updateDates()};l.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(c){if(!this.updating){this.updating=!0;var d=a.data(c.target,"datepicker");if(d!==b){var e=d.getUTCDate(),f=this.keepEmptyValues,g=a.inArray(c.target,this.inputs),h=g-1,i=g+1,j=this.inputs.length;if(-1!==g){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b!==d&&f||b.setUTCDate(e)}),e<this.dates[h])for(;h>=0&&e<this.dates[h];)this.pickers[h--].setUTCDate(e);else if(e>this.dates[i])for(;j>i&&e>this.dates[i];)this.pickers[i++].setUTCDate(e);this.updateDates(),delete this.updating}}}},destroy:function(){a.map(this.pickers,function(a){a.destroy()}),a(this.inputs).off("changeDate",this.dateUpdated),delete this.element.data().datepicker},remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead")};var m=a.fn.datepicker,n=function(c){var d=Array.apply(null,arguments);d.shift();var e;if(this.each(function(){var b=a(this),f=b.data("datepicker"),g="object"==typeof c&&c;if(!f){var j=h(this,"date"),m=a.extend({},o,j,g),n=i(m.language),p=a.extend({},o,n,j,g);b.hasClass("input-daterange")||p.inputs?(a.extend(p,{inputs:p.inputs||b.find("input").toArray()}),f=new l(this,p)):f=new k(this,p),b.data("datepicker",f)}"string"==typeof c&&"function"==typeof f[c]&&(e=f[c].apply(f,d))}),e===b||e instanceof k||e instanceof l)return this;if(this.length>1)throw new Error("Using only allowed for the collection of a single element ("+c+" function)");return e};a.fn.datepicker=n;var o=a.fn.datepicker.defaults={assumeNearbyYear:!1,autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,beforeShowYear:a.noop,beforeShowDecade:a.noop,beforeShowCentury:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],daysOfWeekHighlighted:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keepEmptyValues:!1,keyboardNavigation:!0,language:"en",minViewMode:0,maxViewMode:4,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-(1/0),startView:0,todayBtn:!1,todayHighlight:!1,updateViewDate:!0,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,showOnFocus:!0,zIndexOffset:10,container:"body",immediateUpdates:!1,dateCells:!1,title:"",templates:{leftArrow:"&#x00AB;",rightArrow:"&#x00BB;"}},p=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=k;var q=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM yyyy"}},r={viewModes:[{names:["days","month"],clsName:"days",e:"changeMonth"},{names:["months","year"],clsName:"months",e:"changeYear",navStep:1},{names:["years","decade"],clsName:"years",e:"changeDecade",navStep:10},{names:["decades","century"],clsName:"decades",e:"changeCentury",navStep:100},{names:["centuries","millennium"],clsName:"centuries",e:"changeMillennium",navStep:1e3}],validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,parseFormat:function(a){if("function"==typeof a.toValue&&"function"==typeof a.toDisplay)return a;var b=a.replace(this.validParts,"\x00").split("\x00"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f,g){function h(a,b){return b===!0&&(b=10),100>a&&(a+=2e3,a>(new Date).getFullYear()+b&&(a-=100)),a}function i(){var a=this.slice(0,j[n].length),b=j[n].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!c)return b;if(c instanceof Date)return c;if("string"==typeof e&&(e=r.parseFormat(e)),e.toValue)return e.toValue(c,e,f);var j,l,m,n,o,p={d:"moveDay",m:"moveMonth",w:"moveWeek",y:"moveYear"},s={yesterday:"-1d",today:"+0d",tomorrow:"+1d"};if(c in s&&(c=s[c]),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(c)){for(j=c.match(/([\-+]\d+)([dmwy])/gi),c=new Date,n=0;n<j.length;n++)l=j[n].match(/([\-+]\d+)([dmwy])/i),m=Number(l[1]),o=p[l[2].toLowerCase()],c=k.prototype[o](c,m);return k.prototype._zero_utc_time(c)}j=c&&c.match(this.nonpunctuation)||[];var t,u,v={},w=["yyyy","yy","M","MM","m","mm","d","dd"],x={yyyy:function(a,b){return a.setUTCFullYear(g?h(b,g):b)},m:function(a,b){if(isNaN(a))return a;for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};x.yy=x.yyyy,x.M=x.MM=x.mm=x.m,x.dd=x.d,c=d();var y=e.parts.slice();if(j.length!==y.length&&(y=a(y).filter(function(b,c){return-1!==a.inArray(c,w)}).toArray()),j.length===y.length){var z;for(n=0,z=y.length;z>n;n++){if(t=parseInt(j[n],10),l=y[n],isNaN(t))switch(l){case"MM":u=a(q[f].months).filter(i),t=a.inArray(u[0],q[f].months)+1;break;case"M":u=a(q[f].monthsShort).filter(i),t=a.inArray(u[0],q[f].monthsShort)+1}v[l]=t}var A,B;for(n=0;n<w.length;n++)B=w[n],B in v&&!isNaN(v[B])&&(A=new Date(c),x[B](A,v[B]),isNaN(A)||(c=A))}return c},formatDate:function(b,c,d){if(!b)return"";if("string"==typeof c&&(c=r.parseFormat(c)),c.toDisplay)return c.toDisplay(b,c,d);var e={d:b.getUTCDate(),D:q[d].daysShort[b.getUTCDay()],DD:q[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:q[d].monthsShort[b.getUTCMonth()],MM:q[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m,b=[];for(var f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th colspan="7" class="datepicker-title"></th></tr><tr><th class="prev">&laquo;</th><th colspan="5" class="datepicker-switch"></th><th class="next">&raquo;</th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',
      footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};r.template='<div class="datepicker"><div class="datepicker-days"><table class="table-condensed">'+r.headTemplate+"<tbody></tbody>"+r.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-decades"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-centuries"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=r,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=m,this},a.fn.datepicker.version="1.7.0-dev",a.fn.datepicker.deprecated=function(a){var b=window.console;b&&b.warn&&b.warn("DEPRECATED: "+a)},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),n.call(c,"show"))}),a(function(){n.call(a('[data-provide="datepicker-inline"]'))})});
  /* =========================================================
   * bootstrap-datetimepicker.js
   * =========================================================
   * Copyright 2012 Stefan Petre
   * Improvements by Andrew Rowls
   * Improvements by Sébastien Malot
   * Improvements by Yun Lai
   * Improved by Keenthemes for Bootstrap 3.0 Support
  
   * Project URL : http://www.malot.fr/bootstrap-datetimepicker
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * ========================================================= */
  
  !function( $ ) {
  
  	function UTCDate(){
  		return new Date(Date.UTC.apply(Date, arguments));
  	}
  	function UTCToday(){
  		var today = new Date();
  		return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes(), today.getUTCSeconds(), 0);
  	}
  
  	// Picker object
  
  	var Datetimepicker = function(element, options) {
  		var that = this;
  
  		this.element = $(element);
  		this.language = options.language || this.element.data('date-language') || "en";
  		this.language = this.language in dates ? this.language : "en";
  		this.isRTL = dates[this.language].rtl || ($('body').css("direction") == 'rtl');
  		this.formatType = options.formatType || this.element.data('format-type') || 'standard';
  		this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);
  		this.isInline = false;
  		this.isVisible = false;
  		this.isInput = this.element.is('input');
  		this.component = this.element.is('.date') ? this.element.find('.date-set').parent() : false;
  		this.componentReset = this.element.is('.date') ? this.element.find('.date-reset').parent() : false;
  		this.hasInput = this.component && this.element.find('input').length;
  		if (this.component && this.component.length === 0) {
  			this.component = false;
  		}
  		this.linkField = options.linkField || this.element.data('link-field') || false;
  		this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
  		this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
  		this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
  				this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
  				this.initialDate = options.initialDate || new Date();
  
  		this._attachEvents();
  
  			this.formatViewType = "datetime";
  			if ('formatViewType' in options) {
  					this.formatViewType = options.formatViewType;
  			} else if ('formatViewType' in this.element.data()) {
  					this.formatViewType = this.element.data('formatViewType');
  			}
  
  		this.minView = 0;
  		if ('minView' in options) {
  			this.minView = options.minView;
  		} else if ('minView' in this.element.data()) {
  			this.minView = this.element.data('min-view');
  		}
  		this.minView = DPGlobal.convertViewMode(this.minView);
  
  		this.maxView = DPGlobal.modes.length-1;
  		if ('maxView' in options) {
  			this.maxView = options.maxView;
  		} else if ('maxView' in this.element.data()) {
  			this.maxView = this.element.data('max-view');
  		}
  		this.maxView = DPGlobal.convertViewMode(this.maxView);
  
          this.wheelViewModeNavigation = false;
          if('wheelViewModeNavigation' in options){
              this.wheelViewModeNavigation = options.wheelViewModeNavigation;
          }else if('wheelViewModeNavigation' in this.element.data()){
              this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation');
          }
  
          this.wheelViewModeNavigationInverseDirection = false;
  
          if('wheelViewModeNavigationInverseDirection' in options){
              this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection;
          }else if('wheelViewModeNavigationInverseDirection' in this.element.data()){
              this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir');
          }
  
          this.wheelViewModeNavigationDelay = 100;
          if('wheelViewModeNavigationDelay' in options){
              this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay;
          }else if('wheelViewModeNavigationDelay' in this.element.data()){
              this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay');
          }
  
  		this.startViewMode = 2;
  		if ('startView' in options) {
  			this.startViewMode = options.startView;
  		} else if ('startView' in this.element.data()) {
  			this.startViewMode = this.element.data('start-view');
  		}
  		this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
  		this.viewMode = this.startViewMode;
  
  				this.viewSelect = this.minView;
  				if ('viewSelect' in options) {
  						this.viewSelect = options.viewSelect;
  				} else if ('viewSelect' in this.element.data()) {
  						this.viewSelect = this.element.data('view-select');
  				}
  				this.viewSelect = DPGlobal.convertViewMode(this.viewSelect);
  
  		this.forceParse = true;
  		if ('forceParse' in options) {
  			this.forceParse = options.forceParse;
  		} else if ('dateForceParse' in this.element.data()) {
  			this.forceParse = this.element.data('date-force-parse');
  		}
  
  		this.picker = $(DPGlobal.template)
  							.appendTo(this.isInline ? this.element : 'body')
  							.on({
  								click: $.proxy(this.click, this),
  								mousedown: $.proxy(this.mousedown, this)
  							});
  
          if(this.wheelViewModeNavigation)
          {
              if($.fn.mousewheel)
              {
                  this.picker.on({mousewheel: $.proxy(this.mousewheel,this)});
              }else
              {
                  console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option");
              }
          }
  
  		if (this.isInline) {
  			this.picker.addClass('datetimepicker-inline');
  		} else {
  			this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
  		}
  		if (this.isRTL){
  			this.picker.addClass('datetimepicker-rtl');
  			this.picker.find('.prev i, .next i')
  						.toggleClass('fa-arrow-left fa-arrow-right');
  		}
  		$(document).on('mousedown', function (e) {
  			// Clicked outside the datetimepicker, hide it
  			if ($(e.target).closest('.datetimepicker').length === 0) {
  				that.hide();
  			}
  		});
  
  		this.autoclose = false;
  		if ('autoclose' in options) {
  			this.autoclose = options.autoclose;
  		} else if ('dateAutoclose' in this.element.data()) {
  			this.autoclose = this.element.data('date-autoclose');
  		}
  
  		this.keyboardNavigation = true;
  		if ('keyboardNavigation' in options) {
  			this.keyboardNavigation = options.keyboardNavigation;
  		} else if ('dateKeyboardNavigation' in this.element.data()) {
  			this.keyboardNavigation = this.element.data('date-keyboard-navigation');
  		}
  
  		this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
  		this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
  
  		this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7);
  		this.weekEnd = ((this.weekStart + 6) % 7);
  		this.startDate = -Infinity;
  		this.endDate = Infinity;
  		this.daysOfWeekDisabled = [];
  		this.setStartDate(options.startDate || this.element.data('date-startdate'));
  		this.setEndDate(options.endDate || this.element.data('date-enddate'));
  		this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
  		this.fillDow();
  		this.fillMonths();
  		this.update();
  		this.showMode();
  
  		if(this.isInline) {
  			this.show();
  		}
  	};
  
  	Datetimepicker.prototype = {
  		constructor: Datetimepicker,
  
  		_events: [],
  		_attachEvents: function(){
  			this._detachEvents();
  			if (this.isInput) { // single input
  				this._events = [
  					[this.element, {
  						focus: $.proxy(this.show, this),
  						keyup: $.proxy(this.update, this),
  						keydown: $.proxy(this.keydown, this)
  					}]
  				];
  			}
  			else if (this.component && this.hasInput){ // component: input + button
  				this._events = [
  					// For components that are not readonly, allow keyboard nav
  					[this.element.find('input'), {
  						focus: $.proxy(this.show, this),
  						keyup: $.proxy(this.update, this),
  						keydown: $.proxy(this.keydown, this)
  					}],
  					[this.component, {
  						click: $.proxy(this.show, this)
  					}]
  				];
  				if (this.componentReset) {
  					this._events.push([
  						this.componentReset,
  						{click: $.proxy(this.reset, this)}
  					]);
  				}
  			}
  			else if (this.element.is('div')) {  // inline datetimepicker
  				this.isInline = true;
  			}
  			else {
  				this._events = [
  					[this.element, {
  						click: $.proxy(this.show, this)
  					}]
  				];
  			}
  			for (var i=0, el, ev; i<this._events.length; i++){
  				el = this._events[i][0];
  				ev = this._events[i][1];
  				el.on(ev);
  			}
  		},
  
  		_detachEvents: function(){
  			for (var i=0, el, ev; i<this._events.length; i++){
  				el = this._events[i][0];
  				ev = this._events[i][1];
  				el.off(ev);
  			}
  			this._events = [];
  		},
  
  		show: function(e) {
  			this.picker.show();
  			this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
  			if (this.forceParse) {
  				this.update();
  			}
  			this.place();
  			$(window).on('resize', $.proxy(this.place, this));
  			if (e) {
  				e.stopPropagation();
  				e.preventDefault();
  			}
  			this.isVisible = true;
  			this.element.trigger({
  				type: 'show',
  				date: this.date
  			});
  		},
  
  		hide: function(e){
  			if(!this.isVisible) return;
  			if(this.isInline) return;
  			this.picker.hide();
  			$(window).off('resize', this.place);
  			this.viewMode = this.startViewMode;
  			this.showMode();
  			if (!this.isInput) {
  				$(document).off('mousedown', this.hide);
  			}
  
  			if (
  				this.forceParse &&
  				(
  					this.isInput && this.element.val()  ||
  					this.hasInput && this.element.find('input').val()
  				)
  			)
  				this.setValue();
  			this.isVisible = false;
  			this.element.trigger({
  				type: 'hide',
  				date: this.date
  			});
  		},
  
  		remove: function() {
  			this._detachEvents();
  			this.picker.remove();
  			delete this.picker;
  			delete this.element.data().datetimepicker;
  		},
  
  		getDate: function() {
  			var d = this.getUTCDate();
  			return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
  		},
  
  		getUTCDate: function() {
  			return this.date;
  		},
  
  		setDate: function(d) {
  			this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
  		},
  
  		setUTCDate: function(d) {
  			if (d >= this.startDate && d <= this.endDate) {
  				this.date = d;
  				this.setValue();
  				this.viewDate = this.date;
  				this.fill();
  			} else {
  				this.element.trigger({
  					type: 'outOfRange',
  					date: d,
  					startDate: this.startDate,
  					endDate: this.endDate
  				});
  			}
  		},
  
          setFormat: function(format) {
              this.format = DPGlobal.parseFormat(format, this.formatType);
              var element;
              if (this.isInput) {
                  element = this.element;
              } else if (this.component){
                  element = this.element.find('input');
              }
              if (element && element.val()) {
                  this.setValue();
              }
          },
  
  		setValue: function() {
  			var formatted = this.getFormattedDate();
  			if (!this.isInput) {
  				if (this.component){
  					this.element.find('input').val(formatted);
  				}
  				this.element.data('date', formatted);
  			} else {
  				this.element.val(formatted);
  			}
  			if (this.linkField) {
  				$('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));
  			}
  		},
  
  		getFormattedDate: function(format) {
  			if(format == undefined) format = this.format;
  			return DPGlobal.formatDate(this.date, format, this.language, this.formatType);
  		},
  
  		setStartDate: function(startDate){
  			this.startDate = startDate || -Infinity;
  			if (this.startDate !== -Infinity) {
  				this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType);
  			}
  			this.update();
  			this.updateNavArrows();
  		},
  
  		setEndDate: function(endDate){
  			this.endDate = endDate || Infinity;
  			if (this.endDate !== Infinity) {
  				this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType);
  			}
  			this.update();
  			this.updateNavArrows();
  		},
  
  		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
  			this.daysOfWeekDisabled = daysOfWeekDisabled || [];
  			if (!$.isArray(this.daysOfWeekDisabled)) {
  				this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
  			}
  			this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
  				return parseInt(d, 10);
  			});
  			this.update();
  			this.updateNavArrows();
  		},
  
  		place: function(){
  			if(this.isInline) return;
  			var zIndex = parseInt(this.element.parents().filter(function() {
  				return $(this).css('z-index') != 'auto';
  			}).first().css('z-index'))+10;
  			var offset, top, left;
  			if (this.component) {
  				offset = this.component.offset();
  				left = offset.left;
  				if (this.pickerPosition == 'bottom-left' || this.pickerPosition == 'top-left') {
  					left += this.component.outerWidth() - this.picker.outerWidth();
  				}
  			} else {
  				offset = this.element.offset();
  				left = offset.left;
  			}
  			if (this.pickerPosition == 'top-left' || this.pickerPosition == 'top-right') {
  				top = offset.top - this.picker.outerHeight();
  			} else {
  				top = offset.top + this.height;
  			}
  			this.picker.css({
  				top: top,
  				left: left,
  				zIndex: zIndex
  			});
  		},
  
  		update: function(){
  			var date, fromArgs = false;
  			if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
  				date = arguments[0];
  				fromArgs = true;
  			} else {
                  date = this.element.data('date') || (this.isInput ? this.element.val() : this.element.find('input').val()) || this.initialDate;
  			}
  
  			if (!date) {
  				date = new Date();
  				fromArgs = false;
  			}
  
  			this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType);
  
  			if (fromArgs) this.setValue();
  
  			if (this.date < this.startDate) {
  				this.viewDate = new Date(this.startDate);
  			} else if (this.date > this.endDate) {
  				this.viewDate = new Date(this.endDate);
  			} else {
  				this.viewDate = new Date(this.date);
  			}
  			this.fill();
  		},
  
  		fillDow: function(){
  			var dowCnt = this.weekStart,
  			html = '<tr>';
  			while (dowCnt < this.weekStart + 7) {
  				html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
  			}
  			html += '</tr>';
  			this.picker.find('.datetimepicker-days thead').append(html);
  		},
  
  		fillMonths: function(){
  			var html = '',
  			i = 0;
  			while (i < 12) {
  				html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
  			}
  			this.picker.find('.datetimepicker-months td').html(html);
  			this.element.trigger({
  				type: 'monthUpdate',
  			});
  		},
  
  		fill: function() {
  			if (this.date == null || this.viewDate == null) {
  				return;
  			}
  			var d = new Date(this.viewDate),
  				year = d.getUTCFullYear(),
  				month = d.getUTCMonth(),
  				dayMonth = d.getUTCDate(),
  				hours = d.getUTCHours(),
  				minutes = d.getUTCMinutes(),
  				startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
  				startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
  				endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
  				endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
  				currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),
  				today = new Date();
  			this.picker.find('.datetimepicker-days thead th:eq(1)')
  						.text(dates[this.language].months[month]+' '+year);
  				if (this.formatViewType == "time") {
  						var hourConverted = hours % 12 ? hours % 12 : 12;
  						var hoursDisplay = (hourConverted < 10 ? '0' : '') + hourConverted;
  						var minutesDisplay = (minutes < 10 ? '0' : '') + minutes;
  						var meridianDisplay = dates[this.language].meridiem[hours < 12 ? 0 : 1];
  						this.picker.find('.datetimepicker-hours thead th:eq(1)')
  								.text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase());
  						this.picker.find('.datetimepicker-minutes thead th:eq(1)')
  								.text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase());
  				} else {
  						this.picker.find('.datetimepicker-hours thead th:eq(1)')
  								.text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
  						this.picker.find('.datetimepicker-minutes thead th:eq(1)')
  								.text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
  				}
  				this.picker.find('tfoot th.today')
  						.text(dates[this.language].today)
  						.toggle(this.todayBtn !== false);
  			this.updateNavArrows();
  			this.fillMonths();
  			/*var prevMonth = UTCDate(year, month, 0,0,0,0,0);
  			prevMonth.setUTCDate(prevMonth.getDate() - (prevMonth.getUTCDay() - this.weekStart + 7)%7);*/
  			var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
  								day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
  				prevMonth.setUTCDate(day);
  					prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
  			var nextMonth = new Date(prevMonth);
  			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
  			nextMonth = nextMonth.valueOf();
  			var html = [];
  			var clsName;
  			while(prevMonth.valueOf() < nextMonth) {
  				if (prevMonth.getUTCDay() == this.weekStart) {
  					html.push('<tr>');
  				}
  				clsName = '';
  				if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
  					clsName += ' old';
  				} else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
  					clsName += ' new';
  				}
  				// Compare internal UTC date with local today, not UTC today
  				if (this.todayHighlight &&
  					prevMonth.getUTCFullYear() == today.getFullYear() &&
  					prevMonth.getUTCMonth() == today.getMonth() &&
  					prevMonth.getUTCDate() == today.getDate()) {
  					clsName += ' today';
  				}
  				if (prevMonth.valueOf() == currentDate) {
  					clsName += ' active';
  				}
  				if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate ||
  					$.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
  					clsName += ' disabled';
  				}
  				html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
  				if (prevMonth.getUTCDay() == this.weekEnd) {
  					html.push('</tr>');
  				}
  				prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
  			}
  			this.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));
  
  			html = [];
  						var txt = '', meridian = '', meridianOld = '';
  			for (var i=0;i<24;i++) {
  				var actual = UTCDate(year, month, dayMonth, i);
  				clsName = '';
  				// We want the previous hour for the startDate
  				if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {
  					clsName += ' disabled';
  				} else if (hours == i) {
  					clsName += ' active';
  				}
  								if (this.showMeridian && dates[this.language].meridiem.length == 2) {
  										meridian = (i<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);
  										if (meridian != meridianOld) {
  												if (meridianOld != '') {
  														html.push('</fieldset>');
  												}
  												html.push('<fieldset class="hour"><legend>'+meridian.toUpperCase()+'</legend>');
  										}
  										meridianOld = meridian;
  										txt = (i%12?i%12:12);
  										html.push('<span class="hour'+clsName+' hour_'+(i<12?'am':'pm')+'">'+txt+'</span>');
  										if (i == 23) {
  												html.push('</fieldset>');
  										}
  								} else {
  										txt = i+':00';
  										html.push('<span class="hour'+clsName+'">'+txt+'</span>');
  								}
  			}
  			this.picker.find('.datetimepicker-hours td').html(html.join(''));
  
  			html = [];
  						txt = '', meridian = '', meridianOld = '';
  			for(var i=0;i<60;i+=this.minuteStep) {
  				var actual = UTCDate(year, month, dayMonth, hours, i, 0);
  				clsName = '';
  				if (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) {
  					clsName += ' disabled';
  				} else if (Math.floor(minutes/this.minuteStep) == Math.floor(i/this.minuteStep)) {
  					clsName += ' active';
  				}
  								if (this.showMeridian && dates[this.language].meridiem.length == 2) {
  										meridian = (hours<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);
  										if (meridian != meridianOld) {
  												if (meridianOld != '') {
  														html.push('</fieldset>');
  												}
  												html.push('<fieldset class="minute"><legend>'+meridian.toUpperCase()+'</legend>');
  										}
  										meridianOld = meridian;
  										txt = (hours%12?hours%12:12);
  										//html.push('<span class="minute'+clsName+' minute_'+(hours<12?'am':'pm')+'">'+txt+'</span>');
  										html.push('<span class="minute'+clsName+'">'+txt+':'+(i<10?'0'+i:i)+'</span>');
  										if (i == 59) {
  												html.push('</fieldset>');
  										}
  								} else {
  										txt = i+':00';
  										//html.push('<span class="hour'+clsName+'">'+txt+'</span>');
  										html.push('<span class="minute'+clsName+'">'+hours+':'+(i<10?'0'+i:i)+'</span>');
  								}
  			}
  			this.picker.find('.datetimepicker-minutes td').html(html.join(''));
  
  			var currentYear = this.date.getUTCFullYear();
  			var months = this.picker.find('.datetimepicker-months')
  						.find('th:eq(1)')
  						.text(year)
  						.end()
  						.find('span').removeClass('active');
  			if (currentYear == year) {
  				months.eq(this.date.getUTCMonth()).addClass('active');
  			}
  			if (year < startYear || year > endYear) {
  				months.addClass('disabled');
  			}
  			if (year == startYear) {
  				months.slice(0, startMonth).addClass('disabled');
  			}
  			if (year == endYear) {
  				months.slice(endMonth+1).addClass('disabled');
  			}
  
  			html = '';
  			year = parseInt(year/10, 10) * 10;
  			var yearCont = this.picker.find('.datetimepicker-years')
  								.find('th:eq(1)')
  								.text(year + '-' + (year + 9))
  								.end()
  								.find('td');
  			year -= 1;
  			for (var i = -1; i < 11; i++) {
  				html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
  				year += 1;
  			}
  			yearCont.html(html);
  			this.place();
  		},
  
  		updateNavArrows: function() {
  			var d = new Date(this.viewDate),
  				year = d.getUTCFullYear(),
  				month = d.getUTCMonth(),
  				day = d.getUTCDate(),
  				hour = d.getUTCHours();
  			switch (this.viewMode) {
  				case 0:
  					if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
  													 && month <= this.startDate.getUTCMonth()
  													 && day <= this.startDate.getUTCDate()
  													 && hour <= this.startDate.getUTCHours()) {
  						this.picker.find('.prev').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.prev').css({visibility: 'visible'});
  					}
  					if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
  													&& month >= this.endDate.getUTCMonth()
  													&& day >= this.endDate.getUTCDate()
  													&& hour >= this.endDate.getUTCHours()) {
  						this.picker.find('.next').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.next').css({visibility: 'visible'});
  					}
  					break;
  				case 1:
  					if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
  													 && month <= this.startDate.getUTCMonth()
  													 && day <= this.startDate.getUTCDate()) {
  						this.picker.find('.prev').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.prev').css({visibility: 'visible'});
  					}
  					if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
  													&& month >= this.endDate.getUTCMonth()
  													&& day >= this.endDate.getUTCDate()) {
  						this.picker.find('.next').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.next').css({visibility: 'visible'});
  					}
  					break;
  				case 2:
  					if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
  													 && month <= this.startDate.getUTCMonth()) {
  						this.picker.find('.prev').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.prev').css({visibility: 'visible'});
  					}
  					if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
  													&& month >= this.endDate.getUTCMonth()) {
  						this.picker.find('.next').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.next').css({visibility: 'visible'});
  					}
  					break;
  				case 3:
  				case 4:
  					if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
  						this.picker.find('.prev').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.prev').css({visibility: 'visible'});
  					}
  					if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
  						this.picker.find('.next').css({visibility: 'hidden'});
  					} else {
  						this.picker.find('.next').css({visibility: 'visible'});
  					}
  					break;
  			}
  		},
  
          mousewheel: function(e){
  
              e.preventDefault();
              e.stopPropagation();
  
              if(this.wheelPause)
              {
                  return;
              }
  
              this.wheelPause = true;
  
              var originalEvent = e.originalEvent;
  
              var delta = originalEvent.wheelDelta;
  
              var mode = delta > 0 ? 1:(delta === 0)?0:-1;
  
              if(this.wheelViewModeNavigationInverseDirection)
              {
                  mode = -mode;
              }
  
              this.showMode(mode);
  
              setTimeout($.proxy(function(){
  
                  this.wheelPause = false
  
              },this),this.wheelViewModeNavigationDelay);
  
  
  
          },
  
  		click: function(e) {
  			e.stopPropagation();
  			e.preventDefault();
  			var target = $(e.target).closest('span, td, th, legend');
  			if (target.attr('class') == 'switch' && target.closest('div').hasClass('datetimepicker-days'))
  				return;
  			if (target.length == 1) {
  				if (target.is('.disabled')) {
  					this.element.trigger({
  						type: 'outOfRange',
  						date: this.viewDate,
  						startDate: this.startDate,
  						endDate: this.endDate
  					});
  					return;
  				}
  				switch(target[0].nodeName.toLowerCase()) {
  					case 'th':
  						switch(target[0].className) {
  							case 'switch':
  								this.showMode(1);
  								break;
  							case 'prev':
  							case 'next':
  								var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
  								switch(this.viewMode){
  									case 0:
  										this.viewDate = this.moveHour(this.viewDate, dir);
  										break;
  									case 1:
  										this.viewDate = this.moveDate(this.viewDate, dir);
  										break;
  									case 2:
  										this.viewDate = this.moveMonth(this.viewDate, dir);
  										break;
  									case 3:
  									case 4:
  										this.viewDate = this.moveYear(this.viewDate, dir);
  										break;
  								}
  								this.fill();
  								break;
  							case 'today':
  								var date = new Date();
  								date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
  
  								this.viewMode = this.startViewMode;
  								this.showMode(0);
  								this._setDate(date);
  								this.fill();
  								if (this.autoclose) {
  									this.hide();
  								}
  								break;
  						}
  						break;
  					case 'span':
  						if (!target.is('.disabled')) {
  														var year    = this.viewDate.getUTCFullYear(),
  																month   = this.viewDate.getUTCMonth(),
  																day     = this.viewDate.getUTCDate(),
  																hours   = this.viewDate.getUTCHours(),
  																minutes = this.viewDate.getUTCMinutes(),
  																seconds = this.viewDate.getUTCSeconds();
  
  							if (target.is('.month')) {
  								this.viewDate.setUTCDate(1);
  								month = target.parent().find('span').index(target);
  																day   = this.viewDate.getUTCDate();
  								this.viewDate.setUTCMonth(month);
  								this.element.trigger({
  									type: 'changeMonth',
  									date: this.viewDate
  								});
  																if (this.viewSelect >= 3) {
  										this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
  																}
  							} else if (target.is('.year')) {
  								this.viewDate.setUTCDate(1);
  								year = parseInt(target.text(), 10) || 0;
  								this.viewDate.setUTCFullYear(year);
  								this.element.trigger({
  									type: 'changeYear',
  									date: this.viewDate
  								});
  																if (this.viewSelect >= 4) {
  																		this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
  																}
  							} else if (target.is('.hour')){
  								hours = parseInt(target.text(), 10) || 0;
  																if (target.hasClass('hour_am') || target.hasClass('hour_pm')) {
  																		if (hours == 12 && target.hasClass('hour_am')) {
  																				hours = 0;
  																		} else if (hours != 12 && target.hasClass('hour_pm')) {
  																				hours += 12;
  																		}
  																}
  																this.viewDate.setUTCHours(hours);
  								this.element.trigger({
  									type: 'changeHour',
  									date: this.viewDate
  								});
  																if (this.viewSelect >= 1) {
  										this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
  																}
  							} else if (target.is('.minute')){
  								minutes = parseInt(target.text().substr(target.text().indexOf(':')+1), 10) || 0;
  																this.viewDate.setUTCMinutes(minutes);
  								this.element.trigger({
  									type: 'changeMinute',
  									date: this.viewDate
  								});
  																if (this.viewSelect >= 0) {
  										this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
  																}
  							}
  							if (this.viewMode != 0) {
  								var oldViewMode = this.viewMode;
  								this.showMode(-1);
  								this.fill();
  								if (oldViewMode == this.viewMode && this.autoclose) {
  									this.hide();
  								}
  							} else {
  								this.fill();
  								if (this.autoclose) {
  									this.hide();
  								}
  							}
  						}
  						break;
  					case 'td':
  						if (target.is('.day') && !target.is('.disabled')){
  							var day = parseInt(target.text(), 10) || 1;
  							var year = this.viewDate.getUTCFullYear(),
  								month = this.viewDate.getUTCMonth(),
  								hours = this.viewDate.getUTCHours(),
  								minutes = this.viewDate.getUTCMinutes(),
  								seconds = this.viewDate.getUTCSeconds();
  							if (target.is('.old')) {
  								if (month === 0) {
  									month = 11;
  									year -= 1;
  								} else {
  									month -= 1;
  								}
  							} else if (target.is('.new')) {
  								if (month == 11) {
  									month = 0;
  									year += 1;
  								} else {
  									month += 1;
  								}
  							}
  														this.viewDate.setUTCFullYear(year);
  														this.viewDate.setUTCMonth(month);
  														this.viewDate.setUTCDate(day);
  														this.element.trigger({
  																type: 'changeDay',
  																date: this.viewDate
  														});
  														if (this.viewSelect >= 2) {
  									this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
  														}
  						}
  						var oldViewMode = this.viewMode;
  						this.showMode(-1);
  						this.fill();
  						if (oldViewMode == this.viewMode && this.autoclose) {
  							this.hide();
  						}
  						break;
  				}
  			}
  		},
  
  		_setDate: function(date, which){
  			if (!which || which == 'date')
  				this.date = date;
  			if (!which || which  == 'view')
  				this.viewDate = date;
  			this.fill();
  			this.setValue();
  			var element;
  			if (this.isInput) {
  				element = this.element;
  			} else if (this.component){
  				element = this.element.find('input');
  			}
  			if (element) {
  				element.change();
  				if (this.autoclose && (!which || which == 'date')) {
  					//this.hide();
  				}
  			}
  			this.element.trigger({
  				type: 'changeDate',
  				date: this.date
  			});
  		},
  
  		moveMinute: function(date, dir){
  			if (!dir) return date;
  			var new_date = new Date(date.valueOf());
  			//dir = dir > 0 ? 1 : -1;
  			new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));
  			return new_date;
  		},
  
  		moveHour: function(date, dir){
  			if (!dir) return date;
  			var new_date = new Date(date.valueOf());
  			//dir = dir > 0 ? 1 : -1;
  			new_date.setUTCHours(new_date.getUTCHours() + dir);
  			return new_date;
  		},
  
  		moveDate: function(date, dir){
  			if (!dir) return date;
  			var new_date = new Date(date.valueOf());
  			//dir = dir > 0 ? 1 : -1;
  			new_date.setUTCDate(new_date.getUTCDate() + dir);
  			return new_date;
  		},
  
  		moveMonth: function(date, dir){
  			if (!dir) return date;
  			var new_date = new Date(date.valueOf()),
  				day = new_date.getUTCDate(),
  				month = new_date.getUTCMonth(),
  				mag = Math.abs(dir),
  				new_month, test;
  			dir = dir > 0 ? 1 : -1;
  			if (mag == 1){
  				test = dir == -1
  					// If going back one month, make sure month is not current month
  					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
  					? function(){ return new_date.getUTCMonth() == month; }
  					// If going forward one month, make sure month is as expected
  					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
  					: function(){ return new_date.getUTCMonth() != new_month; };
  				new_month = month + dir;
  				new_date.setUTCMonth(new_month);
  				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
  				if (new_month < 0 || new_month > 11)
  					new_month = (new_month + 12) % 12;
  			} else {
  				// For magnitudes >1, move one month at a time...
  				for (var i=0; i<mag; i++)
  					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
  					new_date = this.moveMonth(new_date, dir);
  				// ...then reset the day, keeping it in the new month
  				new_month = new_date.getUTCMonth();
  				new_date.setUTCDate(day);
  				test = function(){ return new_month != new_date.getUTCMonth(); };
  			}
  			// Common date-resetting loop -- if date is beyond end of month, make it
  			// end of month
  			while (test()){
  				new_date.setUTCDate(--day);
  				new_date.setUTCMonth(new_month);
  			}
  			return new_date;
  		},
  
  		moveYear: function(date, dir){
  			return this.moveMonth(date, dir*12);
  		},
  
  		dateWithinRange: function(date){
  			return date >= this.startDate && date <= this.endDate;
  		},
  
  		keydown: function(e){
  			if (this.picker.is(':not(:visible)')){
  				if (e.keyCode == 27) // allow escape to hide and re-show picker
  					this.show();
  				return;
  			}
  			var dateChanged = false,
  				dir, day, month,
  				newDate, newViewDate;
  			switch(e.keyCode){
  				case 27: // escape
  					this.hide();
  					e.preventDefault();
  					break;
  				case 37: // left
  				case 39: // right
  					if (!this.keyboardNavigation) break;
  					dir = e.keyCode == 37 ? -1 : 1;
  										viewMode = this.viewMode;
  										if (e.ctrlKey) {
  												viewMode += 2;
  										} else if (e.shiftKey) {
  												viewMode += 1;
  										}
  										if (viewMode == 4) {
  						newDate = this.moveYear(this.date, dir);
  						newViewDate = this.moveYear(this.viewDate, dir);
  										} else if (viewMode == 3) {
  						newDate = this.moveMonth(this.date, dir);
  						newViewDate = this.moveMonth(this.viewDate, dir);
  										} else if (viewMode == 2) {
  						newDate = this.moveDate(this.date, dir);
  						newViewDate = this.moveDate(this.viewDate, dir);
  										} else if (viewMode == 1) {
  						newDate = this.moveHour(this.date, dir);
  						newViewDate = this.moveHour(this.viewDate, dir);
  										} else if (viewMode == 0) {
  						newDate = this.moveMinute(this.date, dir);
  						newViewDate = this.moveMinute(this.viewDate, dir);
  										}
  					if (this.dateWithinRange(newDate)){
  						this.date = newDate;
  						this.viewDate = newViewDate;
  						this.setValue();
  						this.update();
  						e.preventDefault();
  						dateChanged = true;
  					}
  					break;
  				case 38: // up
  				case 40: // down
  					if (!this.keyboardNavigation) break;
  					dir = e.keyCode == 38 ? -1 : 1;
  										viewMode = this.viewMode;
  										if (e.ctrlKey) {
  												viewMode += 2;
  										} else if (e.shiftKey) {
  												viewMode += 1;
  										}
  										if (viewMode == 4) {
  						newDate = this.moveYear(this.date, dir);
  						newViewDate = this.moveYear(this.viewDate, dir);
  										} else if (viewMode == 3) {
  						newDate = this.moveMonth(this.date, dir);
  						newViewDate = this.moveMonth(this.viewDate, dir);
  										} else if (viewMode == 2) {
  						newDate = this.moveDate(this.date, dir * 7);
  						newViewDate = this.moveDate(this.viewDate, dir * 7);
  										} else if (viewMode == 1) {
  												if (this.showMeridian) {
  														newDate = this.moveHour(this.date, dir * 6);
  														newViewDate = this.moveHour(this.viewDate, dir * 6);
  												} else {
  														newDate = this.moveHour(this.date, dir * 4);
  														newViewDate = this.moveHour(this.viewDate, dir * 4);
  												}
  										} else if (viewMode == 0) {
  						newDate = this.moveMinute(this.date, dir * 4);
  						newViewDate = this.moveMinute(this.viewDate, dir * 4);
  										}
  					if (this.dateWithinRange(newDate)){
  						this.date = newDate;
  						this.viewDate = newViewDate;
  						this.setValue();
  						this.update();
  						e.preventDefault();
  						dateChanged = true;
  					}
  					break;
  				case 13: // enter
  										if (this.viewMode != 0) {
  												var oldViewMode = this.viewMode;
  												this.showMode(-1);
  												this.fill();
  												if (oldViewMode == this.viewMode && this.autoclose) {
  														this.hide();
  												}
  										} else {
  												this.fill();
  												if (this.autoclose) {
  									this.hide();
  												}
  										}
  					e.preventDefault();
  					break;
  				case 9: // tab
  					this.hide();
  					break;
  			}
  			if (dateChanged){
  				var element;
  				if (this.isInput) {
  					element = this.element;
  				} else if (this.component){
  					element = this.element.find('input');
  				}
  				if (element) {
  					element.change();
  				}
  				this.element.trigger({
  					type: 'changeDate',
  					date: this.date
  				});
  			}
  		},
  
  		showMode: function(dir) {
  			if (dir) {
  				var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
  				if (newViewMode >= this.minView && newViewMode <= this.maxView) {
  					this.element.trigger({
  						type: 'changeMode',
  						date: this.viewDate,
  						oldViewMode: this.viewMode,
  						newViewMode: newViewMode
  					});
  
  					this.viewMode = newViewMode;
  				}
  			}
  			/*
  				vitalets: fixing bug of very special conditions:
  				jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.
  				Method show() does not set display css correctly and datetimepicker is not shown.
  				Changed to .css('display', 'block') solve the problem.
  				See https://github.com/vitalets/x-editable/issues/37
  
  				In jquery 1.7.2+ everything works fine.
  			*/
  			//this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
  			this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
  			this.updateNavArrows();
  		},
  
  		reset: function(e) {
  			this._setDate(null, 'date');
  		}
  	};
  
  	$.fn.datetimepicker = function ( option ) {
  		var args = Array.apply(null, arguments);
  		args.shift();
  		return this.each(function () {
  			var $this = $(this),
  				data = $this.data('datetimepicker'),
  				options = typeof option == 'object' && option;
  			if (!data) {
  				$this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults,options))));
  			}
  			if (typeof option == 'string' && typeof data[option] == 'function') {
  				data[option].apply(data, args);
  			}
  		});
  	};
  
  	$.fn.datetimepicker.defaults = {
  	};
  	$.fn.datetimepicker.Constructor = Datetimepicker;
  	var dates = $.fn.datetimepicker.dates = {
  		en: {
  			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
  			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
  			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
  			meridiem: ["am", "pm"],
  			suffix: ["st", "nd", "rd", "th"],
  			today: "Today"
  		}
  	};
  
  	var DPGlobal = {
  		modes: [
  			{
  				clsName: 'minutes',
  				navFnc: 'Hours',
  				navStep: 1
  			},
  			{
  				clsName: 'hours',
  				navFnc: 'Date',
  				navStep: 1
  			},
  			{
  				clsName: 'days',
  				navFnc: 'Month',
  				navStep: 1
  			},
  			{
  				clsName: 'months',
  				navFnc: 'FullYear',
  				navStep: 1
  			},
  			{
  				clsName: 'years',
  				navFnc: 'FullYear',
  				navStep: 10
  		}],
  		isLeapYear: function (year) {
  			return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
  		},
  		getDaysInMonth: function (year, month) {
  			return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
  		},
  		getDefaultFormat: function (type, field) {
  			if (type == "standard") {
  				if (field == 'input')
  					return 'yyyy-mm-dd hh:ii';
  				else
  					return 'yyyy-mm-dd hh:ii:ss';
  			} else if (type == "php") {
  				if (field == 'input')
  					return 'Y-m-d H:i';
  				else
  					return 'Y-m-d H:i:s';
  			} else {
  				throw new Error("Invalid format type.");
  			}
  		},
  		validParts: function (type) {
  			if (type == "standard") {
  				return /hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;
  			} else if (type == "php") {
  				return /[dDjlNwzFmMnStyYaABgGhHis]/g;
  			} else {
  				throw new Error("Invalid format type.");
  			}
  		},
  		nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,
  		parseFormat: function(format, type){
  			// IE treats \0 as a string end in inputs (truncating the value),
  			// so it's a bad format delimiter, anyway
  			var separators = format.replace(this.validParts(type), '\0').split('\0'),
  				parts = format.match(this.validParts(type));
  			if (!separators || !separators.length || !parts || parts.length == 0){
  				throw new Error("Invalid date format.");
  			}
  			return {separators: separators, parts: parts};
  		},
  		parseDate: function(date, format, language, type) {
  			if (date instanceof Date) {
  				var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
  								dateUTC.setMilliseconds(0);
  				return dateUTC;
  			}
  			if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
  				format = this.parseFormat('yyyy-mm-dd', type);
  			}
  			if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
  				format = this.parseFormat('yyyy-mm-dd hh:ii', type);
  			}
  			if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
  				format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);
  			}
  			if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
  				var part_re = /([-+]\d+)([dmwy])/,
  					parts = date.match(/([-+]\d+)([dmwy])/g),
  					part, dir;
  				date = new Date();
  				for (var i=0; i<parts.length; i++) {
  					part = part_re.exec(parts[i]);
  					dir = parseInt(part[1]);
  					switch(part[2]){
  						case 'd':
  							date.setUTCDate(date.getUTCDate() + dir);
  							break;
  						case 'm':
  							date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
  							break;
  						case 'w':
  							date.setUTCDate(date.getUTCDate() + dir * 7);
  							break;
  						case 'y':
  							date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
  							break;
  					}
  				}
  				return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);
  			}
  			var parts = date && date.match(this.nonpunctuation) || [],
  				date = new Date(0, 0, 0, 0, 0, 0, 0),
  				parsed = {},
  				setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P'],
  				setters_map = {
  					hh: function(d,v){ return d.setUTCHours(v); },
  					h:  function(d,v){ return d.setUTCHours(v); },
  					HH: function(d,v){ return d.setUTCHours(v==12?0:v); },
  					H:  function(d,v){ return d.setUTCHours(v==12?0:v); },
  					ii: function(d,v){ return d.setUTCMinutes(v); },
  					i:  function(d,v){ return d.setUTCMinutes(v); },
  					ss: function(d,v){ return d.setUTCSeconds(v); },
  					s:  function(d,v){ return d.setUTCSeconds(v); },
  					yyyy: function(d,v){ return d.setUTCFullYear(v); },
  					yy: function(d,v){ return d.setUTCFullYear(2000+v); },
  					m: function(d,v){
  						v -= 1;
  						while (v<0) v += 12;
  						v %= 12;
  						d.setUTCMonth(v);
  						while (d.getUTCMonth() != v)
  							d.setUTCDate(d.getUTCDate()-1);
  						return d;
  					},
  					d: function(d,v){ return d.setUTCDate(v); },
  					p: function(d,v){ return d.setUTCHours(v==1?d.getUTCHours()+12:d.getUTCHours()); }
  				},
  				val, filtered, part;
  			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
  			setters_map['dd'] = setters_map['d'];
  					setters_map['P'] = setters_map['p'];
  			date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
  			if (parts.length == format.parts.length) {
  				for (var i=0, cnt = format.parts.length; i < cnt; i++) {
  					val = parseInt(parts[i], 10);
  					part = format.parts[i];
  					if (isNaN(val)) {
  						switch(part) {
  							case 'MM':
  								filtered = $(dates[language].months).filter(function(){
  									var m = this.slice(0, parts[i].length),
  										p = parts[i].slice(0, m.length);
  									return m == p;
  								});
  								val = $.inArray(filtered[0], dates[language].months) + 1;
  								break;
  							case 'M':
  								filtered = $(dates[language].monthsShort).filter(function(){
  									var m = this.slice(0, parts[i].length),
  										p = parts[i].slice(0, m.length);
  									return m == p;
  								});
  								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
  								break;
  								case 'p':
  								case 'P':
  										val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);
  										break;
  						}
  					}
  					parsed[part] = val;
  				}
  				for (var i=0, s; i<setters_order.length; i++){
  					s = setters_order[i];
  					if (s in parsed && !isNaN(parsed[s]))
  						setters_map[s](date, parsed[s])
  				}
  			}
  			return date;
  		},
  		formatDate: function(date, format, language, type){
  			if (date == null) {
  				return '';
  			}
  			var val;
  			if (type == 'standard') {
  				val = {
  					// year
  					yy: date.getUTCFullYear().toString().substring(2),
  					yyyy: date.getUTCFullYear(),
  					// month
  					m: date.getUTCMonth() + 1,
  					M: dates[language].monthsShort[date.getUTCMonth()],
  					MM: dates[language].months[date.getUTCMonth()],
  					// day
  					d: date.getUTCDate(),
  					D: dates[language].daysShort[date.getUTCDay()],
  					DD: dates[language].days[date.getUTCDay()],
  					p: (dates[language].meridiem.length==2?dates[language].meridiem[date.getUTCHours()<12?0:1]:''),
  					// hour
  					h: date.getUTCHours(),
  					// minute
  					i: date.getUTCMinutes(),
  					// second
  					s: date.getUTCSeconds()
  				};
  								val.H  = (val.h%12==0? 12 : val.h%12);
  								val.HH = (val.H < 10 ? '0' : '') + val.H;
  								val.P  = val.p.toUpperCase();
  				val.hh = (val.h < 10 ? '0' : '') + val.h;
  				val.ii = (val.i < 10 ? '0' : '') + val.i;
  				val.ss = (val.s < 10 ? '0' : '') + val.s;
  				val.dd = (val.d < 10 ? '0' : '') + val.d;
  				val.mm = (val.m < 10 ? '0' : '') + val.m;
  			} else if (type == 'php') {
  				// php format
  				val = {
  					// year
  					y: date.getUTCFullYear().toString().substring(2),
  					Y: date.getUTCFullYear(),
  					// month
  					F: dates[language].months[date.getUTCMonth()],
  					M: dates[language].monthsShort[date.getUTCMonth()],
  					n: date.getUTCMonth() + 1,
  					t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),
  					// day
  					j: date.getUTCDate(),
  					l: dates[language].days[date.getUTCDay()],
  					D: dates[language].daysShort[date.getUTCDay()],
  					w: date.getUTCDay(), // 0 -> 6
  					N: (date.getUTCDay()==0?7:date.getUTCDay()),       // 1 -> 7
  					S: (date.getUTCDate()%10<=dates[language].suffix.length?dates[language].suffix[date.getUTCDate()%10-1]:''),
  					// hour
  					a: (dates[language].meridiem.length==2?dates[language].meridiem[date.getUTCHours()<12?0:1]:''),
  					g: (date.getUTCHours()%12==0?12:date.getUTCHours()%12),
  					G: date.getUTCHours(),
  					// minute
  					i: date.getUTCMinutes(),
  					// second
  					s: date.getUTCSeconds()
  				};
  				val.m = (val.n < 10 ? '0' : '') + val.n;
  				val.d = (val.j < 10 ? '0' : '') + val.j;
  				val.A = val.a.toString().toUpperCase();
  				val.h = (val.g < 10 ? '0' : '') + val.g;
  				val.H = (val.G < 10 ? '0' : '') + val.G;
  				val.i = (val.i < 10 ? '0' : '') + val.i;
  				val.s = (val.s < 10 ? '0' : '') + val.s;
  			} else {
  				throw new Error("Invalid format type.");
  			}
  			var date = [],
  				seps = $.extend([], format.separators);
  			for (var i=0, cnt = format.parts.length; i < cnt; i++) {
  				if (seps.length)
  					date.push(seps.shift())
  				date.push(val[format.parts[i]]);
  			}
  			return date.join('');
  		},
  		convertViewMode: function(viewMode){
  			switch (viewMode) {
  				case 4:
  				case 'decade':
  					viewMode = 4;
  					break;
  				case 3:
  				case 'year':
  					viewMode = 3;
  					break;
  				case 2:
  				case 'month':
  					viewMode = 2;
  					break;
  				case 1:
  				case 'day':
  					viewMode = 1;
  					break;
  				case 0:
  				case 'hour':
  					viewMode = 0;
  					break;
  			}
  
  			return viewMode;
  		},
  		headTemplate: '<thead>'+
  							'<tr>'+
  								'<th class="prev"><i class="fa fa-angle-left"/></th>'+
  								'<th colspan="5" class="switch"></th>'+
  								'<th class="next"><i class="fa fa-angle-right"/></th>'+
  							'</tr>'+
  						'</thead>',
  		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
  		footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
  	};
  	DPGlobal.template = '<div class="datetimepicker">'+
  							'<div class="datetimepicker-minutes">'+
  								'<table class=" table-condensed">'+
  									DPGlobal.headTemplate+
  									DPGlobal.contTemplate+
  									DPGlobal.footTemplate+
  								'</table>'+
  							'</div>'+
  							'<div class="datetimepicker-hours">'+
  								'<table class=" table-condensed">'+
  									DPGlobal.headTemplate+
  									DPGlobal.contTemplate+
  									DPGlobal.footTemplate+
  								'</table>'+
  							'</div>'+
  							'<div class="datetimepicker-days">'+
  								'<table class=" table-condensed">'+
  									DPGlobal.headTemplate+
  									'<tbody></tbody>'+
  									DPGlobal.footTemplate+
  								'</table>'+
  							'</div>'+
  							'<div class="datetimepicker-months">'+
  								'<table class="table-condensed">'+
  									DPGlobal.headTemplate+
  									DPGlobal.contTemplate+
  									DPGlobal.footTemplate+
  								'</table>'+
  							'</div>'+
  							'<div class="datetimepicker-years">'+
  								'<table class="table-condensed">'+
  									DPGlobal.headTemplate+
  									DPGlobal.contTemplate+
  									DPGlobal.footTemplate+
  								'</table>'+
  							'</div>'+
  						'</div>';
  
  	$.fn.datetimepicker.DPGlobal = DPGlobal;
  
  
  	/* DATETIMEPICKER NO CONFLICT
  	* =================== */
  
  	$.fn.datetimepicker.noConflict = function () {
  	    $.fn.datetimepicker = old;
  	    return this;
  	};
  
  
  	/* DATETIMEPICKER DATA-API
  	* ================== */
  
  	$(document).on(
  		'focus.datetimepicker.data-api click.datetimepicker.data-api',
  		'[data-provide="datetimepicker"]',
  		function (e) {
  		    var $this = $(this);
  		    if ($this.data('datetimepicker')) return;
  		    e.preventDefault();
  		    // component click requires us to explicitly show it
  		    $this.datetimepicker('show');
  		}
  	);
  	$(function () {
  	    $('[data-provide="datetimepicker-inline"]').datetimepicker();
  	});
  
  }( window.jQuery );
  
  /*!
   * Bootstrap Colorpicker v2.5.1
   * https://itsjavi.com/bootstrap-colorpicker/
   */
  !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):jQuery&&!jQuery.fn.colorpicker&&b(jQuery)}(this,function(a){"use strict";var b=function(c,d,e,f,g){this.fallbackValue=e?e&&"undefined"!=typeof e.h?e:this.value={h:0,s:0,b:0,a:1}:null,this.fallbackFormat=f?f:"rgba",this.hexNumberSignPrefix=g===!0,this.value=this.fallbackValue,this.origFormat=null,this.predefinedColors=d?d:{},this.colors=a.extend({},b.webColors,this.predefinedColors),c&&("undefined"!=typeof c.h?this.value=c:this.setColor(String(c))),this.value||(this.value={h:0,s:0,b:0,a:1})};b.webColors={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32",transparent:"transparent"},b.prototype={constructor:b,colors:{},predefinedColors:{},getValue:function(){return this.value},setValue:function(a){this.value=a},_sanitizeNumber:function(a){return"number"==typeof a?a:isNaN(a)||null===a||""===a||void 0===a?1:""===a?0:"undefined"!=typeof a.toLowerCase?(a.match(/^\./)&&(a="0"+a),Math.ceil(100*parseFloat(a))/100):1},isTransparent:function(a){return!(!a||!("string"==typeof a||a instanceof String))&&(a=a.toLowerCase().trim(),"transparent"===a||a.match(/#?00000000/)||a.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/))},rgbaIsTransparent:function(a){return 0===a.r&&0===a.g&&0===a.b&&0===a.a},setColor:function(a){if(a=a.toLowerCase().trim()){if(this.isTransparent(a))return this.value={h:0,s:0,b:0,a:0},!0;var b=this.parse(a);b?(this.value=this.value={h:b.h,s:b.s,b:b.b,a:b.a},this.origFormat||(this.origFormat=b.format)):this.fallbackValue&&(this.value=this.fallbackValue)}return!1},setHue:function(a){this.value.h=1-a},setSaturation:function(a){this.value.s=a},setBrightness:function(a){this.value.b=1-a},setAlpha:function(a){this.value.a=Math.round(parseInt(100*(1-a),10)/100*100)/100},toRGB:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a),a*=360;var e,f,g,h,i;return a=a%360/60,i=c*b,h=i*(1-Math.abs(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],{r:Math.round(255*e),g:Math.round(255*f),b:Math.round(255*g),a:d}},toHex:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a);var e=this.toRGB(a,b,c,d);if(this.rgbaIsTransparent(e))return"transparent";var f=(this.hexNumberSignPrefix?"#":"")+((1<<24)+(parseInt(e.r)<<16)+(parseInt(e.g)<<8)+parseInt(e.b)).toString(16).slice(1);return f},toHSL:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a);var e=a,f=(2-b)*c,g=b*c;return g/=f>0&&f<=1?f:2-f,f/=2,g>1&&(g=1),{h:isNaN(e)?0:e,s:isNaN(g)?0:g,l:isNaN(f)?0:f,a:isNaN(d)?0:d}},toAlias:function(a,b,c,d){var e,f=0===arguments.length?this.toHex():this.toHex(a,b,c,d),g="alias"===this.origFormat?f:this.toString(this.origFormat,!1);for(var h in this.colors)if(e=this.colors[h].toLowerCase().trim(),e===f||e===g)return h;return!1},RGBtoHSB:function(a,b,c,d){a/=255,b/=255,c/=255;var e,f,g,h;return g=Math.max(a,b,c),h=g-Math.min(a,b,c),e=0===h?null:g===a?(b-c)/h:g===b?(c-a)/h+2:(a-b)/h+4,e=(e+360)%6*60/360,f=0===h?0:h/g,{h:this._sanitizeNumber(e),s:f,b:g,a:this._sanitizeNumber(d)}},HueToRGB:function(a,b,c){return c<0?c+=1:c>1&&(c-=1),6*c<1?a+(b-a)*c*6:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a},HSLtoRGB:function(a,b,c,d){b<0&&(b=0);var e;e=c<=.5?c*(1+b):c+b-c*b;var f=2*c-e,g=a+1/3,h=a,i=a-1/3,j=Math.round(255*this.HueToRGB(f,e,g)),k=Math.round(255*this.HueToRGB(f,e,h)),l=Math.round(255*this.HueToRGB(f,e,i));return[j,k,l,this._sanitizeNumber(d)]},parse:function(b){if(0===arguments.length)return!1;var c,d,e=this,f=!1,g="undefined"!=typeof this.colors[b];return g&&(b=this.colors[b].toLowerCase().trim()),a.each(this.stringParsers,function(a,h){var i=h.re.exec(b);return c=i&&h.parse.apply(e,[i]),!c||(f={},d=g?"alias":h.format?h.format:e.getValidFallbackFormat(),f=d.match(/hsla?/)?e.RGBtoHSB.apply(e,e.HSLtoRGB.apply(e,c)):e.RGBtoHSB.apply(e,c),f instanceof Object&&(f.format=d),!1)}),f},getValidFallbackFormat:function(){var a=["rgba","rgb","hex","hsla","hsl"];return this.origFormat&&a.indexOf(this.origFormat)!==-1?this.origFormat:this.fallbackFormat&&a.indexOf(this.fallbackFormat)!==-1?this.fallbackFormat:"rgba"},toString:function(a,c){a=a||this.origFormat||this.fallbackFormat,c=c||!1;var d=!1;switch(a){case"rgb":return d=this.toRGB(),this.rgbaIsTransparent(d)?"transparent":"rgb("+d.r+","+d.g+","+d.b+")";case"rgba":return d=this.toRGB(),"rgba("+d.r+","+d.g+","+d.b+","+d.a+")";case"hsl":return d=this.toHSL(),"hsl("+Math.round(360*d.h)+","+Math.round(100*d.s)+"%,"+Math.round(100*d.l)+"%)";case"hsla":return d=this.toHSL(),"hsla("+Math.round(360*d.h)+","+Math.round(100*d.s)+"%,"+Math.round(100*d.l)+"%,"+d.a+")";case"hex":return this.toHex();case"alias":return d=this.toAlias(),d===!1?this.toString(this.getValidFallbackFormat()):c&&!(d in b.webColors)&&d in this.predefinedColors?this.predefinedColors[d]:d;default:return d}},stringParsers:[{re:/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,format:"rgb",parse:function(a){return[a[1],a[2],a[3],1]}},{re:/rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"rgb",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],1]}},{re:/rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[a[1],a[2],a[3],a[4]]}},{re:/rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],a[4]]}},{re:/hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"hsl",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"hsla",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,format:"hex",parse:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16),1]}},{re:/#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,format:"hex",parse:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16),1]}}],colorNameToHex:function(a){return"undefined"!=typeof this.colors[a.toLowerCase()]&&this.colors[a.toLowerCase()]}};var c={horizontal:!1,inline:!1,color:!1,format:!1,input:"input",container:!1,component:".add-on, .input-group-addon",fallbackColor:!1,fallbackFormat:"hex",hexNumberSignPrefix:!0,sliders:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setHue"},alpha:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setAlpha"}},slidersHorz:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:100,maxTop:0,callLeft:"setHue",callTop:!1},alpha:{maxLeft:100,maxTop:0,callLeft:"setAlpha",callTop:!1}},template:'<div class="colorpicker dropdown-menu"><div class="colorpicker-saturation"><i><b></b></i></div><div class="colorpicker-hue"><i></i></div><div class="colorpicker-alpha"><i></i></div><div class="colorpicker-color"><div /></div><div class="colorpicker-selectors"></div></div>',align:"right",customClass:null,colorSelectors:null},d=function(b,d){this.element=a(b).addClass("colorpicker-element"),this.options=a.extend(!0,{},c,this.element.data(),d),this.component=this.options.component,this.component=this.component!==!1&&this.element.find(this.component),this.component&&0===this.component.length&&(this.component=!1),this.container=this.options.container===!0?this.element:this.options.container,this.container=this.container!==!1&&a(this.container),this.input=this.element.is("input")?this.element:!!this.options.input&&this.element.find(this.options.input),this.input&&0===this.input.length&&(this.input=!1),this.color=this.createColor(this.options.color!==!1?this.options.color:this.getValue()),this.format=this.options.format!==!1?this.options.format:this.color.origFormat,this.options.color!==!1&&(this.updateInput(this.color),this.updateData(this.color));var e=this.picker=a(this.options.template);if(this.options.customClass&&e.addClass(this.options.customClass),this.options.inline?e.addClass("colorpicker-inline colorpicker-visible"):e.addClass("colorpicker-hidden"),this.options.horizontal&&e.addClass("colorpicker-horizontal"),["rgba","hsla","alias"].indexOf(this.format)===-1&&this.options.format!==!1&&"transparent"!==this.getValue()||e.addClass("colorpicker-with-alpha"),"right"===this.options.align&&e.addClass("colorpicker-right"),this.options.inline===!0&&e.addClass("colorpicker-no-arrow"),this.options.colorSelectors){var f=this,g=f.picker.find(".colorpicker-selectors");g.length>0&&(a.each(this.options.colorSelectors,function(b,c){var d=a("<i />").addClass("colorpicker-selectors-color").css("background-color",c).data("class",b).data("alias",b);d.on("mousedown.colorpicker touchstart.colorpicker",function(b){b.preventDefault(),f.setValue("alias"===f.format?a(this).data("alias"):a(this).css("background-color"))}),g.append(d)}),g.show().addClass("colorpicker-visible"))}e.on("mousedown.colorpicker touchstart.colorpicker",a.proxy(function(a){a.target===a.currentTarget&&a.preventDefault()},this)),e.find(".colorpicker-saturation, .colorpicker-hue, .colorpicker-alpha").on("mousedown.colorpicker touchstart.colorpicker",a.proxy(this.mousedown,this)),e.appendTo(this.container?this.container:a("body")),this.input!==!1&&(this.input.on({"keyup.colorpicker":a.proxy(this.keyup,this)}),this.input.on({"change.colorpicker":a.proxy(this.change,this)}),this.component===!1&&this.element.on({"focus.colorpicker":a.proxy(this.show,this)}),this.options.inline===!1&&this.element.on({"focusout.colorpicker":a.proxy(this.hide,this)})),this.component!==!1&&this.component.on({"click.colorpicker":a.proxy(this.show,this)}),this.input===!1&&this.component===!1&&this.element.on({"click.colorpicker":a.proxy(this.show,this)}),this.input!==!1&&this.component!==!1&&"color"===this.input.attr("type")&&this.input.on({"click.colorpicker":a.proxy(this.show,this),"focus.colorpicker":a.proxy(this.show,this)}),this.update(),a(a.proxy(function(){this.element.trigger("create")},this))};d.Color=b,d.prototype={constructor:d,destroy:function(){this.picker.remove(),this.element.removeData("colorpicker","color").off(".colorpicker"),this.input!==!1&&this.input.off(".colorpicker"),this.component!==!1&&this.component.off(".colorpicker"),this.element.removeClass("colorpicker-element"),this.element.trigger({type:"destroy"})},reposition:function(){if(this.options.inline!==!1||this.options.container)return!1;var a=this.container&&this.container[0]!==window.document.body?"position":"offset",b=this.component||this.element,c=b[a]();"right"===this.options.align&&(c.left-=this.picker.outerWidth()-b.outerWidth()),this.picker.css({top:c.top+b.outerHeight(),left:c.left})},show:function(b){this.isDisabled()||(this.picker.addClass("colorpicker-visible").removeClass("colorpicker-hidden"),this.reposition(),a(window).on("resize.colorpicker",a.proxy(this.reposition,this)),!b||this.hasInput()&&"color"!==this.input.attr("type")||b.stopPropagation&&b.preventDefault&&(b.stopPropagation(),b.preventDefault()),!this.component&&this.input||this.options.inline!==!1||a(window.document).on({"mousedown.colorpicker":a.proxy(this.hide,this)}),this.element.trigger({type:"showPicker",color:this.color}))},hide:function(b){return("undefined"==typeof b||!b.target||!(a(b.currentTarget).parents(".colorpicker").length>0||a(b.target).parents(".colorpicker").length>0))&&(this.picker.addClass("colorpicker-hidden").removeClass("colorpicker-visible"),a(window).off("resize.colorpicker",this.reposition),a(window.document).off({"mousedown.colorpicker":this.hide}),this.update(),void this.element.trigger({type:"hidePicker",color:this.color}))},updateData:function(a){return a=a||this.color.toString(this.format,!1),this.element.data("color",a),a},updateInput:function(a){return a=a||this.color.toString(this.format,!1),this.input!==!1&&(this.input.prop("value",a),this.input.trigger("change")),a},updatePicker:function(a){"undefined"!=typeof a&&(this.color=this.createColor(a));var b=this.options.horizontal===!1?this.options.sliders:this.options.slidersHorz,c=this.picker.find("i");if(0!==c.length)return this.options.horizontal===!1?(b=this.options.sliders,c.eq(1).css("top",b.hue.maxTop*(1-this.color.value.h)).end().eq(2).css("top",b.alpha.maxTop*(1-this.color.value.a))):(b=this.options.slidersHorz,c.eq(1).css("left",b.hue.maxLeft*(1-this.color.value.h)).end().eq(2).css("left",b.alpha.maxLeft*(1-this.color.value.a))),c.eq(0).css({top:b.saturation.maxTop-this.color.value.b*b.saturation.maxTop,left:this.color.value.s*b.saturation.maxLeft}),this.picker.find(".colorpicker-saturation").css("backgroundColor",(this.options.hexNumberSignPrefix?"":"#")+this.color.toHex(this.color.value.h,1,1,1)),this.picker.find(".colorpicker-alpha").css("backgroundColor",(this.options.hexNumberSignPrefix?"":"#")+this.color.toHex()),this.picker.find(".colorpicker-color, .colorpicker-color div").css("backgroundColor",this.color.toString(this.format,!0)),a},updateComponent:function(a){var b;if(b="undefined"!=typeof a?this.createColor(a):this.color,this.component!==!1){var c=this.component.find("i").eq(0);c.length>0?c.css({backgroundColor:b.toString(this.format,!0)}):this.component.css({backgroundColor:b.toString(this.format,!0)})}return b.toString(this.format,!1)},update:function(a){var b;return this.getValue(!1)===!1&&a!==!0||(b=this.updateComponent(),this.updateInput(b),this.updateData(b),this.updatePicker()),b},setValue:function(a){this.color=this.createColor(a),this.update(!0),this.element.trigger({type:"changeColor",color:this.color,value:a})},createColor:function(a){return new b(a?a:null,this.options.colorSelectors,this.options.fallbackColor?this.options.fallbackColor:this.color,this.options.fallbackFormat,this.options.hexNumberSignPrefix)},getValue:function(a){a="undefined"==typeof a?this.options.fallbackColor:a;var b;return b=this.hasInput()?this.input.val():this.element.data("color"),void 0!==b&&""!==b&&null!==b||(b=a),b},hasInput:function(){return this.input!==!1},isDisabled:function(){return!!this.hasInput()&&this.input.prop("disabled")===!0},disable:function(){return!!this.hasInput()&&(this.input.prop("disabled",!0),this.element.trigger({type:"disable",color:this.color,value:this.getValue()}),!0)},enable:function(){return!!this.hasInput()&&(this.input.prop("disabled",!1),this.element.trigger({type:"enable",color:this.color,value:this.getValue()}),!0)},currentSlider:null,mousePointer:{left:0,top:0},mousedown:function(b){!b.pageX&&!b.pageY&&b.originalEvent&&b.originalEvent.touches&&(b.pageX=b.originalEvent.touches[0].pageX,b.pageY=b.originalEvent.touches[0].pageY),b.stopPropagation(),b.preventDefault();var c=a(b.target),d=c.closest("div"),e=this.options.horizontal?this.options.slidersHorz:this.options.sliders;if(!d.is(".colorpicker")){if(d.is(".colorpicker-saturation"))this.currentSlider=a.extend({},e.saturation);else if(d.is(".colorpicker-hue"))this.currentSlider=a.extend({},e.hue);else{if(!d.is(".colorpicker-alpha"))return!1;this.currentSlider=a.extend({},e.alpha)}var f=d.offset();this.currentSlider.guide=d.find("i")[0].style,this.currentSlider.left=b.pageX-f.left,this.currentSlider.top=b.pageY-f.top,this.mousePointer={left:b.pageX,top:b.pageY},a(window.document).on({"mousemove.colorpicker":a.proxy(this.mousemove,this),"touchmove.colorpicker":a.proxy(this.mousemove,this),"mouseup.colorpicker":a.proxy(this.mouseup,this),"touchend.colorpicker":a.proxy(this.mouseup,this)}).trigger("mousemove")}return!1},mousemove:function(a){!a.pageX&&!a.pageY&&a.originalEvent&&a.originalEvent.touches&&(a.pageX=a.originalEvent.touches[0].pageX,a.pageY=a.originalEvent.touches[0].pageY),a.stopPropagation(),a.preventDefault();var b=Math.max(0,Math.min(this.currentSlider.maxLeft,this.currentSlider.left+((a.pageX||this.mousePointer.left)-this.mousePointer.left))),c=Math.max(0,Math.min(this.currentSlider.maxTop,this.currentSlider.top+((a.pageY||this.mousePointer.top)-this.mousePointer.top)));return this.currentSlider.guide.left=b+"px",this.currentSlider.guide.top=c+"px",this.currentSlider.callLeft&&this.color[this.currentSlider.callLeft].call(this.color,b/this.currentSlider.maxLeft),this.currentSlider.callTop&&this.color[this.currentSlider.callTop].call(this.color,c/this.currentSlider.maxTop),this.options.format!==!1||"setAlpha"!==this.currentSlider.callTop&&"setAlpha"!==this.currentSlider.callLeft||(1!==this.color.value.a?(this.format="rgba",this.color.origFormat="rgba"):(this.format="hex",this.color.origFormat="hex")),this.update(!0),this.element.trigger({type:"changeColor",color:this.color}),!1},mouseup:function(b){return b.stopPropagation(),b.preventDefault(),a(window.document).off({"mousemove.colorpicker":this.mousemove,"touchmove.colorpicker":this.mousemove,"mouseup.colorpicker":this.mouseup,"touchend.colorpicker":this.mouseup}),!1},change:function(a){this.keyup(a)},keyup:function(a){38===a.keyCode?(this.color.value.a<1&&(this.color.value.a=Math.round(100*(this.color.value.a+.01))/100),this.update(!0)):40===a.keyCode?(this.color.value.a>0&&(this.color.value.a=Math.round(100*(this.color.value.a-.01))/100),this.update(!0)):(this.color=this.createColor(this.input.val()),this.color.origFormat&&this.options.format===!1&&(this.format=this.color.origFormat),this.getValue(!1)!==!1&&(this.updateData(),this.updateComponent(),this.updatePicker())),this.element.trigger({type:"changeColor",color:this.color,value:this.input.val()})}},a.colorpicker=d,a.fn.colorpicker=function(b){var c=Array.prototype.slice.call(arguments,1),e=1===this.length,f=null,g=this.each(function(){var e=a(this),g=e.data("colorpicker"),h="object"==typeof b?b:{};g||(g=new d(this,h),e.data("colorpicker",g)),"string"==typeof b?a.isFunction(g[b])?f=g[b].apply(g,c):(c.length&&(g[b]=c[0]),f=g[b]):f=e});return e?f:g},a.fn.colorpicker.constructor=d});
  /* ===========================================================
   * bootstrap-modal.js v2.2.4
   * ===========================================================
   * Copyright 2012 Jordan Schroter
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * ========================================================== */
  
  
  !function ($) {
  
  	"use strict"; // jshint ;_;
  
  	/* MODAL CLASS DEFINITION
  	* ====================== */
  
  	var Modal = function (element, options) {
  		this.init(element, options);
  	};
  
  	Modal.prototype = {
  
  		constructor: Modal,
  
  		init: function (element, options) {
  			var that = this;
  
  			this.options = options;
  
  			this.$element = $(element)
  				.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this));
  
  			this.options.remote && this.$element.find('.modal-body').load(this.options.remote, function () {
  				var e = $.Event('loaded');
  				that.$element.trigger(e);
  			});
  
  			var manager = typeof this.options.manager === 'function' ?
  				this.options.manager.call(this) : this.options.manager;
  
  			manager = manager.appendModal ?
  				manager : $(manager).modalmanager().data('modalmanager');
  
  			manager.appendModal(this);
  		},
  
  		toggle: function () {
  			return this[!this.isShown ? 'show' : 'hide']();
  		},
  
  		show: function () {
  			var e = $.Event('show');
  
  			if (this.isShown) return;
  
  			this.$element.trigger(e);
  
  			if (e.isDefaultPrevented()) return;
  
  			this.escape();
  
  			this.tab();
  
  			this.options.loading && this.loading();
  		},
  
  		hide: function (e) {
  			e && e.preventDefault();
  
  			e = $.Event('hide');
  
  			this.$element.trigger(e);
  
  			if (!this.isShown || e.isDefaultPrevented()) return;
  
  			this.isShown = false;
  
  			this.escape();
  
  			this.tab();
  
  			this.isLoading && this.loading();
  
  			$(document).off('focusin.modal');
  
  			this.$element
  				.removeClass('in')
  				.removeClass('animated')
  				.removeClass(this.options.attentionAnimation)
  				.removeClass('modal-overflow')
  				.attr('aria-hidden', true);
  
  			$.support.transition && this.$element.hasClass('fade') ?
  				this.hideWithTransition() :
  				this.hideModal();
  		},
  
  		layout: function () {
  			var prop = this.options.height ? 'height' : 'max-height',
  				value = this.options.height || this.options.maxHeight;
  
  			if (this.options.width){
  				this.$element.css('width', this.options.width);
  
  				var that = this;
  				this.$element.css('margin-left', function () {
  					if (/%/ig.test(that.options.width)){
  						return -(parseInt(that.options.width) / 2) + '%';
  					} else {
  						return -($(this).width() / 2) + 'px';
  					}
  				});
  			} else {
  				this.$element.css('width', '');
  				this.$element.css('margin-left', '');
  			}
  
  			this.$element.find('.modal-body')
  				.css('overflow', '')
  				.css(prop, '');
  
  			if (value){
  				this.$element.find('.modal-body')
  					.css('overflow', 'auto')
  					.css(prop, value);
  			}
  
  			var modalOverflow = $(window).height() - 10 < this.$element.height();
  
  			if (modalOverflow || this.options.modalOverflow) {
  				this.$element
  					.css('margin-top', 0)
  					.addClass('modal-overflow');
  			} else {
  				this.$element
  					.css('margin-top', 0 - this.$element.height() / 2)
  					.removeClass('modal-overflow');
  			}
  		},
  
  		tab: function () {
  			var that = this;
  
  			if (this.isShown && this.options.consumeTab) {
  				this.$element.on('keydown.tabindex.modal', '[data-tabindex]', function (e) {
  			    	if (e.keyCode && e.keyCode == 9){
  						var $next = $(this),
  							$rollover = $(this);
  
  						that.$element.find('[data-tabindex]:enabled:not([readonly])').each(function (e) {
  							if (!e.shiftKey){
  						 		$next = $next.data('tabindex') < $(this).data('tabindex') ?
  									$next = $(this) :
  									$rollover = $(this);
  							} else {
  								$next = $next.data('tabindex') > $(this).data('tabindex') ?
  									$next = $(this) :
  									$rollover = $(this);
  							}
  						});
  
  						$next[0] !== $(this)[0] ?
  							$next.focus() : $rollover.focus();
  
  						e.preventDefault();
  					}
  				});
  			} else if (!this.isShown) {
  				this.$element.off('keydown.tabindex.modal');
  			}
  		},
  
  		escape: function () {
  			var that = this;
  			if (this.isShown && this.options.keyboard) {
  				if (!this.$element.attr('tabindex')) this.$element.attr('tabindex', -1);
  
  				this.$element.on('keyup.dismiss.modal', function (e) {
  					e.which == 27 && that.hide();
  				});
  			} else if (!this.isShown) {
  				this.$element.off('keyup.dismiss.modal')
  			}
  		},
  
  		hideWithTransition: function () {
  			var that = this
  				, timeout = setTimeout(function () {
  					that.$element.off($.support.transition.end);
  					that.hideModal();
  				}, 500);
  
  			this.$element.one($.support.transition.end, function () {
  				clearTimeout(timeout);
  				that.hideModal();
  			});
  		},
  
  		hideModal: function () {
  			var prop = this.options.height ? 'height' : 'max-height';
  			var value = this.options.height || this.options.maxHeight;
  
  			if (value){
  				this.$element.find('.modal-body')
  					.css('overflow', '')
  					.css(prop, '');
  			}
  
  			this.$element
  				.hide()
  				.trigger('hidden');
  		},
  
  		removeLoading: function () {
  			this.$loading.remove();
  			this.$loading = null;
  			this.isLoading = false;
  		},
  
  		loading: function (callback) {
  			callback = callback || function () {};
  
  			var animate = this.$element.hasClass('fade') ? 'fade' : '';
  
  			if (!this.isLoading) {
  				var doAnimate = $.support.transition && animate;
  
  				this.$loading = $('<div class="loading-mask ' + animate + '">')
  					.append(this.options.spinner)
  					.appendTo(this.$element);
  
  				if (doAnimate) this.$loading[0].offsetWidth; // force reflow
  
  				this.$loading.addClass('in');
  
  				this.isLoading = true;
  
  				doAnimate ?
  					this.$loading.one($.support.transition.end, callback) :
  					callback();
  
  			} else if (this.isLoading && this.$loading) {
  				this.$loading.removeClass('in');
  
  				var that = this;
  				$.support.transition && this.$element.hasClass('fade')?
  					this.$loading.one($.support.transition.end, function () { that.removeLoading() }) :
  					that.removeLoading();
  
  			} else if (callback) {
  				callback(this.isLoading);
  			}
  		},
  
  		focus: function () {
  			var $focusElem = this.$element.find(this.options.focusOn);
  
  			$focusElem = $focusElem.length ? $focusElem : this.$element;
  
  			$focusElem.focus();
  		},
  
  		attention: function (){
  			// NOTE: transitionEnd with keyframes causes odd behaviour
  
  			if (this.options.attentionAnimation){
  				this.$element
  					.removeClass('animated')
  					.removeClass(this.options.attentionAnimation);
  
  				var that = this;
  
  				setTimeout(function () {
  					that.$element
  						.addClass('animated')
  						.addClass(that.options.attentionAnimation);
  				}, 0);
  			}
  
  
  			this.focus();
  		},
  
  
  		destroy: function () {
  			var e = $.Event('destroy');
  
  			this.$element.trigger(e);
  
  			if (e.isDefaultPrevented()) return;
  
  			this.$element
  				.off('.modal')
  				.removeData('modal')
  				.removeClass('in')
  				.attr('aria-hidden', true);
  
  			if (this.$parent !== this.$element.parent()) {
  				this.$element.appendTo(this.$parent);
  			} else if (!this.$parent.length) {
  				// modal is not part of the DOM so remove it.
  				this.$element.remove();
  				this.$element = null;
  			}
  
  			this.$element.trigger('destroyed');
  		}
  	};
  
  
  	/* MODAL PLUGIN DEFINITION
  	* ======================= */
  
  	$.fn.modal = function (option, args) {
  		return this.each(function () {
  			var $this = $(this),
  				data = $this.data('modal'),
  				options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option);
  
  			if (!data) $this.data('modal', (data = new Modal(this, options)));
  			if (typeof option == 'string') data[option].apply(data, [].concat(args));
  			else if (options.show) data.show()
  		})
  	};
  
  	$.fn.modal.defaults = {
  		keyboard: true,
  		backdrop: true,
  		loading: false,
  		show: true,
  		width: null,
  		height: null,
  		maxHeight: null,
  		modalOverflow: false,
  		consumeTab: true,
  		focusOn: null,
  		replace: false,
  		resize: false,
  		attentionAnimation: 'shake',
  		manager: 'body',
  		spinner: '<div class="loading-spinner" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>',
  		backdropTemplate: '<div class="modal-backdrop" />'
  	};
  
  	$.fn.modal.Constructor = Modal;
  
  
  	/* MODAL DATA-API
  	* ============== */
  
  	$(function () {
  		$(document).off('click.modal').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
  			var $this = $(this),
  				href = $this.attr('href'),
  				$target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))), //strip for ie7
  				option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data());
  
  			e.preventDefault();
  			$target
  				.modal(option)
  				.one('hide', function () {
  					$this.focus();
  				})
  		});
  	});
  
  }(window.jQuery);
  
  /* ===========================================================
   * bootstrap-modalmanager.js v2.2.4
   * ===========================================================
   * Copyright 2012 Jordan Schroter.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * ========================================================== */
  
  !function ($) {
  
  	"use strict"; // jshint ;_;
  
  	/* MODAL MANAGER CLASS DEFINITION
  	* ====================== */
  
  	var ModalManager = function (element, options) {
  		this.init(element, options);
  	};
  
  	ModalManager.prototype = {
  
  		constructor: ModalManager,
  
  		init: function (element, options) {
  			this.$element = $(element);
  			this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options == 'object' && options);
  			this.stack = [];
  			this.backdropCount = 0;
  
  			if (this.options.resize) {
  				var resizeTimeout,
  					that = this;
  
  				$(window).on('resize.modal', function(){
  					resizeTimeout && clearTimeout(resizeTimeout);
  					resizeTimeout = setTimeout(function(){
  						for (var i = 0; i < that.stack.length; i++){
  							that.stack[i].isShown && that.stack[i].layout();
  						}
  					}, 10);
  				});
  			}
  		},
  
  		createModal: function (element, options) {
  			$(element).modal($.extend({ manager: this }, options));
  		},
  
  		appendModal: function (modal) {
  			this.stack.push(modal);
  
  			var that = this;
  
  			modal.$element.on('show.modalmanager', targetIsSelf(function (e) {
  
  				var showModal = function(){
  					modal.isShown = true;
  
  					var transition = $.support.transition && modal.$element.hasClass('fade');
  
  					that.$element
  						.toggleClass('modal-open', that.hasOpenModal())
  						.toggleClass('page-overflow', $(window).height() < that.$element.height());
  
  					modal.$parent = modal.$element.parent();
  
  					modal.$container = that.createContainer(modal);
  
  					modal.$element.appendTo(modal.$container);
  
  					that.backdrop(modal, function () {
  						modal.$element.show();
  
  						if (transition) {
  							//modal.$element[0].style.display = 'run-in';
  							modal.$element[0].offsetWidth;
  							//modal.$element.one($.support.transition.end, function () { modal.$element[0].style.display = 'block' });
  						}
  
  						modal.layout();
  
  						modal.$element
  							.addClass('in')
  							.attr('aria-hidden', false);
  
  						var complete = function () {
  							that.setFocus();
  							modal.$element.trigger('shown');
  						};
  
  						transition ?
  							modal.$element.one($.support.transition.end, complete) :
  							complete();
  					});
  				};
  
  				modal.options.replace ?
  					that.replace(showModal) :
  					showModal();
  			}));
  
  			modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
  				that.backdrop(modal);
  				// handle the case when a modal may have been removed from the dom before this callback executes
  				if (!modal.$element.parent().length) {
  					that.destroyModal(modal);
  				} else if (modal.$backdrop){
  					var transition = $.support.transition && modal.$element.hasClass('fade');
  
  					// trigger a relayout due to firebox's buggy transition end event
  					if (transition) { modal.$element[0].offsetWidth; }
  					$.support.transition && modal.$element.hasClass('fade') ?
  						modal.$backdrop.one($.support.transition.end, function () { modal.destroy(); }) :
  						modal.destroy();
  				} else {
  					modal.destroy();
  				}
  
  			}));
  
  			modal.$element.on('destroyed.modalmanager', targetIsSelf(function (e) {
  				that.destroyModal(modal);
  			}));
  		},
  
  		getOpenModals: function () {
  			var openModals = [];
  			for (var i = 0; i < this.stack.length; i++){
  				if (this.stack[i].isShown) openModals.push(this.stack[i]);
  			}
  
  			return openModals;
  		},
  
  		hasOpenModal: function () {
  			return this.getOpenModals().length > 0;
  		},
  
  		setFocus: function () {
  			var topModal;
  
  			for (var i = 0; i < this.stack.length; i++){
  				if (this.stack[i].isShown) topModal = this.stack[i];
  			}
  
  			if (!topModal) return;
  
  			topModal.focus();
  		},
  
  		destroyModal: function (modal) {
  			modal.$element.off('.modalmanager');
  			if (modal.$backdrop) this.removeBackdrop(modal);
  			this.stack.splice(this.getIndexOfModal(modal), 1);
  
  			var hasOpenModal = this.hasOpenModal();
  
  			this.$element.toggleClass('modal-open', hasOpenModal);
  
  			if (!hasOpenModal){
  				this.$element.removeClass('page-overflow');
  			}
  
  			this.removeContainer(modal);
  
  			this.setFocus();
  		},
  
  		getModalAt: function (index) {
  			return this.stack[index];
  		},
  
  		getIndexOfModal: function (modal) {
  			for (var i = 0; i < this.stack.length; i++){
  				if (modal === this.stack[i]) return i;
  			}
  		},
  
  		replace: function (callback) {
  			var topModal;
  
  			for (var i = 0; i < this.stack.length; i++){
  				if (this.stack[i].isShown) topModal = this.stack[i];
  			}
  
  			if (topModal) {
  				this.$backdropHandle = topModal.$backdrop;
  				topModal.$backdrop = null;
  
  				callback && topModal.$element.one('hidden',
  					targetIsSelf( $.proxy(callback, this) ));
  
  				topModal.hide();
  			} else if (callback) {
  				callback();
  			}
  		},
  
  		removeBackdrop: function (modal) {
  			modal.$backdrop.remove();
  			modal.$backdrop = null;
  		},
  
  		createBackdrop: function (animate, tmpl) {
  			var $backdrop;
  
  			if (!this.$backdropHandle) {
  				$backdrop = $(tmpl)
  					.addClass(animate)
  					.appendTo(this.$element);
  			} else {
  				$backdrop = this.$backdropHandle;
  				$backdrop.off('.modalmanager');
  				this.$backdropHandle = null;
  				this.isLoading && this.removeSpinner();
  			}
  
  			return $backdrop;
  		},
  
  		removeContainer: function (modal) {
  			modal.$container.remove();
  			modal.$container = null;
  		},
  
  		createContainer: function (modal) {
  			var $container;
  
  			$container = $('<div class="modal-scrollable">')
  				.css('z-index', getzIndex('modal', this.getOpenModals().length))
  				.appendTo(this.$element);
  
  			if (modal && modal.options.backdrop != 'static') {
  				$container.on('click.modal', targetIsSelf(function (e) {
  					modal.hide();
  				}));
  			} else if (modal) {
  				$container.on('click.modal', targetIsSelf(function (e) {
  					modal.attention();
  				}));
  			}
  
  			return $container;
  
  		},
  
  		backdrop: function (modal, callback) {
  			var animate = modal.$element.hasClass('fade') ? 'fade' : '',
  				showBackdrop = modal.options.backdrop &&
  					this.backdropCount < this.options.backdropLimit;
  
  			if (modal.isShown && showBackdrop) {
  				var doAnimate = $.support.transition && animate && !this.$backdropHandle;
  
  				modal.$backdrop = this.createBackdrop(animate, modal.options.backdropTemplate);
  
  				modal.$backdrop.css('z-index', getzIndex( 'backdrop', this.getOpenModals().length ));
  
  				if (doAnimate) modal.$backdrop[0].offsetWidth; // force reflow
  
  				modal.$backdrop.addClass('in');
  
  				this.backdropCount += 1;
  
  				doAnimate ?
  					modal.$backdrop.one($.support.transition.end, callback) :
  					callback();
  
  			} else if (!modal.isShown && modal.$backdrop) {
  				modal.$backdrop.removeClass('in');
  
  				this.backdropCount -= 1;
  
  				var that = this;
  
  				$.support.transition && modal.$element.hasClass('fade')?
  					modal.$backdrop.one($.support.transition.end, function () { that.removeBackdrop(modal) }) :
  					that.removeBackdrop(modal);
  
  			} else if (callback) {
  				callback();
  			}
  		},
  
  		removeSpinner: function(){
  			this.$spinner && this.$spinner.remove();
  			this.$spinner = null;
  			this.isLoading = false;
  		},
  
  		removeLoading: function () {
  			this.$backdropHandle && this.$backdropHandle.remove();
  			this.$backdropHandle = null;
  			this.removeSpinner();
  		},
  
  		loading: function (callback) {
  			callback = callback || function () { };
  
  			this.$element
  				.toggleClass('modal-open', !this.isLoading || this.hasOpenModal())
  				.toggleClass('page-overflow', $(window).height() < this.$element.height());
  
  			if (!this.isLoading) {
  
  				this.$backdropHandle = this.createBackdrop('fade', this.options.backdropTemplate);
  
  				this.$backdropHandle[0].offsetWidth; // force reflow
  
  				var openModals = this.getOpenModals();
  
  				this.$backdropHandle
  					.css('z-index', getzIndex('backdrop', openModals.length + 1))
  					.addClass('in');
  
  				var $spinner = $(this.options.spinner)
  					.css('z-index', getzIndex('modal', openModals.length + 1))
  					.appendTo(this.$element)
  					.addClass('in');
  
  				this.$spinner = $(this.createContainer())
  					.append($spinner)
  					.on('click.modalmanager', $.proxy(this.loading, this));
  
  				this.isLoading = true;
  
  				$.support.transition ?
  					this.$backdropHandle.one($.support.transition.end, callback) :
  					callback();
  
  			} else if (this.isLoading && this.$backdropHandle) {
  				this.$backdropHandle.removeClass('in');
  
  				var that = this;
  				$.support.transition ?
  					this.$backdropHandle.one($.support.transition.end, function () { that.removeLoading() }) :
  					that.removeLoading();
  
  			} else if (callback) {
  				callback(this.isLoading);
  			}
  		}
  	};
  
  	/* PRIVATE METHODS
  	* ======================= */
  
  	// computes and caches the zindexes
  	var getzIndex = (function () {
  		var zIndexFactor,
  			baseIndex = {};
  
  		return function (type, pos) {
  
  			if (typeof zIndexFactor === 'undefined'){
  				var $baseModal = $('<div class="modal hide" />').appendTo('body'),
  					$baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
  
  				baseIndex['modal'] = +$baseModal.css('z-index');
  				baseIndex['backdrop'] = +$baseBackdrop.css('z-index');
  				zIndexFactor = baseIndex['modal'] - baseIndex['backdrop'];
  
  				$baseModal.remove();
  				$baseBackdrop.remove();
  				$baseBackdrop = $baseModal = null;
  			}
  
  			return baseIndex[type] + (zIndexFactor * pos);
  
  		}
  	}());
  
  	// make sure the event target is the modal itself in order to prevent
  	// other components such as tabsfrom triggering the modal manager.
  	// if Boostsrap namespaced events, this would not be needed.
  	function targetIsSelf(callback){
  		return function (e) {
  			if (e && this === e.target){
  				return callback.apply(this, arguments);
  			}
  		}
  	}
  
  
  	/* MODAL MANAGER PLUGIN DEFINITION
  	* ======================= */
  
  	$.fn.modalmanager = function (option, args) {
  		return this.each(function () {
  			var $this = $(this),
  				data = $this.data('modalmanager');
  
  			if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)));
  			if (typeof option === 'string') data[option].apply(data, [].concat(args))
  		})
  	};
  
  	$.fn.modalmanager.defaults = {
  		backdropLimit: 999,
  		resize: true,
  		spinner: '<div class="loading-spinner fade" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>',
  		backdropTemplate: '<div class="modal-backdrop" />'
  	};
  
  	$.fn.modalmanager.Constructor = ModalManager
  
  	// ModalManager handles the modal-open class so we need
  	// to remove conflicting bootstrap 3 event handlers
  	$(function () {
  		$(document).off('show.bs.modal').off('hidden.bs.modal');
  	});
  
  }(jQuery);
  
  /*
   * Toastr
   * Version 2.0.1
   * Copyright 2012 John Papa and Hans Fjällemark.
   * All Rights Reserved.
   * Use, reproduction, distribution, and modification of this code is subject to the terms and
   * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
   *
   * Author: John Papa and Hans Fjällemark
   * Project: https://github.com/CodeSeven/toastr
   */
  ; (function (define) {
  	define(['jquery'], function ($) {
  		return (function () {
  			var version = '2.0.1';
  			var $container;
  			var listener;
  			var toastId = 0;
  			var toastType = {
  				error: 'error',
  				info: 'info',
  				success: 'success',
  				warning: 'warning'
  			};
  
  			var toastr = {
  				clear: clear,
  				error: error,
  				getContainer: getContainer,
  				info: info,
  				options: {},
  				subscribe: subscribe,
  				success: success,
  				version: version,
  				warning: warning
  			};
  
  			return toastr;
  
  			//#region Accessible Methods
  			function error(message, title, optionsOverride) {
  				return notify({
  					type: toastType.error,
  					iconClass: getOptions().iconClasses.error,
  					message: message,
  					optionsOverride: optionsOverride,
  					title: title
  				});
  			}
  
  			function info(message, title, optionsOverride) {
  				return notify({
  					type: toastType.info,
  					iconClass: getOptions().iconClasses.info,
  					message: message,
  					optionsOverride: optionsOverride,
  					title: title
  				});
  			}
  
  			function subscribe(callback) {
  				listener = callback;
  			}
  
  			function success(message, title, optionsOverride) {
  				return notify({
  					type: toastType.success,
  					iconClass: getOptions().iconClasses.success,
  					message: message,
  					optionsOverride: optionsOverride,
  					title: title
  				});
  			}
  
  			function warning(message, title, optionsOverride) {
  				return notify({
  					type: toastType.warning,
  					iconClass: getOptions().iconClasses.warning,
  					message: message,
  					optionsOverride: optionsOverride,
  					title: title
  				});
  			}
  
  			function clear($toastElement) {
  				var options = getOptions();
  				if (!$container) { getContainer(options); }
  				if ($toastElement && $(':focus', $toastElement).length === 0) {
  					$toastElement[options.hideMethod]({
  						duration: options.hideDuration,
  						easing: options.hideEasing,
  						complete: function () { removeToast($toastElement); }
  					});
  					return;
  				}
  				if ($container.children().length) {
  					$container[options.hideMethod]({
  						duration: options.hideDuration,
  						easing: options.hideEasing,
  						complete: function () { $container.remove(); }
  					});
  				}
  			}
  			//#endregion
  
  			//#region Internal Methods
  
  			function getDefaults() {
  				return {
  					tapToDismiss: true,
  					toastClass: 'toast',
  					containerId: 'toast-container',
  					debug: false,
  
  					showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
  					showDuration: 300,
  					showEasing: 'swing', //swing and linear are built into jQuery
  					onShown: undefined,
  					hideMethod: 'fadeOut',
  					hideDuration: 1000,
  					hideEasing: 'swing',
  					onHidden: undefined,
  
  					extendedTimeOut: 1000,
  					iconClasses: {
  						error: 'toast-error',
  						info: 'toast-info',
  						success: 'toast-success',
  						warning: 'toast-warning'
  					},
  					iconClass: 'toast-info',
  					positionClass: 'toast-top-right',
  					timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky
  					titleClass: 'toast-title',
  					messageClass: 'toast-message',
  					target: 'body',
  					closeHtml: '<button>&times;</button>',
  					newestOnTop: true
  				};
  			}
  
  			function publish(args) {
  				if (!listener) {
  					return;
  				}
  				listener(args);
  			}
  
  			function notify(map) {
  				var
  					options = getOptions(),
  					iconClass = map.iconClass || options.iconClass;
  
  				if (typeof (map.optionsOverride) !== 'undefined') {
  					options = $.extend(options, map.optionsOverride);
  					iconClass = map.optionsOverride.iconClass || iconClass;
  				}
  
  				toastId++;
  
  				$container = getContainer(options);
  				var
  					intervalId = null,
  					$toastElement = $('<div/>'),
  					$titleElement = $('<div/>'),
  					$messageElement = $('<div/>'),
  					$closeElement = $(options.closeHtml),
  					response = {
  						toastId: toastId,
  						state: 'visible',
  						startTime: new Date(),
  						options: options,
  						map: map
  					};
  
  				if (map.iconClass) {
  					$toastElement.addClass(options.toastClass).addClass(iconClass);
  				}
  
  				if (map.title) {
  					$titleElement.append(map.title).addClass(options.titleClass);
  					$toastElement.append($titleElement);
  				}
  
  				if (map.message) {
  					$messageElement.append(map.message).addClass(options.messageClass);
  					$toastElement.append($messageElement);
  				}
  
  				if (options.closeButton) {
  					$closeElement.addClass('toast-close-button');
  					$toastElement.prepend($closeElement);
  				}
  
  				$toastElement.hide();
  				if (options.newestOnTop) {
  					$container.prepend($toastElement);
  				} else {
  					$container.append($toastElement);
  				}
  
  
  				$toastElement[options.showMethod](
  					{ duration: options.showDuration, easing: options.showEasing, complete: options.onShown }
  				);
  				if (options.timeOut > 0) {
  					intervalId = setTimeout(hideToast, options.timeOut);
  				}
  
  				$toastElement.hover(stickAround, delayedhideToast);
  				if (!options.onclick && options.tapToDismiss) {
  					$toastElement.click(hideToast);
  				}
  				if (options.closeButton && $closeElement) {
  					$closeElement.click(function (event) {
  						event.stopPropagation();
  						hideToast(true);
  					});
  				}
  
  				if (options.onclick) {
  					$toastElement.click(function () {
  						options.onclick();
  						hideToast();
  					});
  				}
  
  				publish(response);
  
  				if (options.debug && console) {
  					console.log(response);
  				}
  
  				return $toastElement;
  
  				function hideToast(override) {
  					if ($(':focus', $toastElement).length && !override) {
  						return;
  					}
  					return $toastElement[options.hideMethod]({
  						duration: options.hideDuration,
  						easing: options.hideEasing,
  						complete: function () {
  							removeToast($toastElement);
  							if (options.onHidden) {
  								options.onHidden();
  							}
  							response.state = 'hidden';
  							response.endTime = new Date(),
  							publish(response);
  						}
  					});
  				}
  
  				function delayedhideToast() {
  					if (options.timeOut > 0 || options.extendedTimeOut > 0) {
  						intervalId = setTimeout(hideToast, options.extendedTimeOut);
  					}
  				}
  
  				function stickAround() {
  					clearTimeout(intervalId);
  					$toastElement.stop(true, true)[options.showMethod](
  						{ duration: options.showDuration, easing: options.showEasing }
  					);
  				}
  			}
  			function getContainer(options) {
  				if (!options) { options = getOptions(); }
  				$container = $('#' + options.containerId);
  				if ($container.length) {
  					return $container;
  				}
  				$container = $('<div/>')
  					.attr('id', options.containerId)
  					.addClass(options.positionClass);
  				$container.appendTo($(options.target));
  				return $container;
  			}
  
  			function getOptions() {
  				return $.extend({}, getDefaults(), toastr.options);
  			}
  
  			function removeToast($toastElement) {
  				if (!$container) { $container = getContainer(); }
  				if ($toastElement.is(':visible')) {
  					return;
  				}
  				$toastElement.remove();
  				$toastElement = null;
  				if ($container.children().length === 0) {
  					$container.remove();
  				}
  			}
  			//#endregion
  
  		})();
  	});
  }(typeof define === 'function' && define.amd ? define : function (deps, factory) {
  	if (typeof module !== 'undefined' && module.exports) { //Node
  		module.exports = factory(require(deps[0]));
  	} else {
  		window['toastr'] = factory(window['jQuery']);
  	}
  }));
  
  /*!
   * jQuery throttle / debounce - v1.1 - 3/7/2010
   * http://benalman.com/projects/jquery-throttle-debounce-plugin/
   *
   * Copyright (c) 2010 "Cowboy" Ben Alman
   * Dual licensed under the MIT and GPL licenses.
   * http://benalman.com/about/license/
   */
  
  // Script: jQuery throttle / debounce: Sometimes, less is more!
  //
  // *Version: 1.1, Last updated: 3/7/2010*
  //
  // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
  // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
  // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
  // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
  //
  // About: License
  //
  // Copyright (c) 2010 "Cowboy" Ben Alman,
  // Dual licensed under the MIT and GPL licenses.
  // http://benalman.com/about/license/
  //
  // About: Examples
  //
  // These working examples, complete with fully commented code, illustrate a few
  // ways in which this plugin can be used.
  //
  // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
  // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
  //
  // About: Support and Testing
  //
  // Information about what version or versions of jQuery this plugin has been
  // tested with, what browsers it has been tested in, and where the unit tests
  // reside (so you can test it yourself).
  //
  // jQuery Versions - none, 1.3.2, 1.4.2
  // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
  // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
  //
  // About: Release History
  //
  // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
  //       executed later than they should. Reworked a fair amount of internal
  //       logic as well.
  // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
  //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
  //       no_trailing throttle parameter and debounce functionality.
  //
  // Topic: Note for non-jQuery users
  //
  // jQuery isn't actually required for this plugin, because nothing internal
  // uses any jQuery methods or properties. jQuery is just used as a namespace
  // under which these methods can exist.
  //
  // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
  // when this plugin is loaded, the method described below will be created in
  // the `Cowboy` namespace. Usage will be exactly the same, but instead of
  // $.method() or jQuery.method(), you'll need to use Cowboy.method().
  
  (function(window,undefined){
      '$:nomunge'; // Used by YUI compressor.
  
      // Since jQuery really isn't required for this plugin, use `jQuery` as the
      // namespace only if it already exists, otherwise use the `Cowboy` namespace,
      // creating it if necessary.
      var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
  
      // Internal method reference.
          jq_throttle;
  
      // Method: jQuery.throttle
      //
      // Throttle execution of a function. Especially useful for rate limiting
      // execution of handlers on events like resize and scroll. If you want to
      // rate-limit execution of a function to a single time, see the
      // <jQuery.debounce> method.
      //
      // In this visualization, | is a throttled-function call and X is the actual
      // callback execution:
      //
      // > Throttled with `no_trailing` specified as false or unspecified:
      // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
      // > X    X    X    X    X    X        X    X    X    X    X    X
      // >
      // > Throttled with `no_trailing` specified as true:
      // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
      // > X    X    X    X    X             X    X    X    X    X
      //
      // Usage:
      //
      // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
      // >
      // > jQuery('selector').bind( 'someevent', throttled );
      // > jQuery('selector').unbind( 'someevent', throttled );
      //
      // This also works in jQuery 1.4+:
      //
      // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
      // > jQuery('selector').unbind( 'someevent', callback );
      //
      // Arguments:
      //
      //  delay - (Number) A zero-or-greater delay in milliseconds. For event
      //    callbacks, values around 100 or 250 (or even higher) are most useful.
      //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
      //    true, callback will only execute every `delay` milliseconds while the
      //    throttled-function is being called. If no_trailing is false or
      //    unspecified, callback will be executed one final time after the last
      //    throttled-function call. (After the throttled-function has not been
      //    called for `delay` milliseconds, the internal counter is reset)
      //  callback - (Function) A function to be executed after delay milliseconds.
      //    The `this` context and all arguments are passed through, as-is, to
      //    `callback` when the throttled-function is executed.
      //
      // Returns:
      //
      //  (Function) A new, throttled, function.
  
      $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
          // After wrapper has stopped being called, this timeout ensures that
          // `callback` is executed at the proper times in `throttle` and `end`
          // debounce modes.
          var timeout_id,
  
          // Keep track of the last time `callback` was executed.
              last_exec = 0;
  
          // `no_trailing` defaults to falsy.
          if ( typeof no_trailing !== 'boolean' ) {
              debounce_mode = callback;
              callback = no_trailing;
              no_trailing = undefined;
          }
  
          // The `wrapper` function encapsulates all of the throttling / debouncing
          // functionality and when executed will limit the rate at which `callback`
          // is executed.
          function wrapper() {
              var that = this,
                  elapsed = +new Date() - last_exec,
                  args = arguments;
  
              // Execute `callback` and update the `last_exec` timestamp.
              function exec() {
                  last_exec = +new Date();
                  callback.apply( that, args );
              };
  
              // If `debounce_mode` is true (at_begin) this is used to clear the flag
              // to allow future `callback` executions.
              function clear() {
                  timeout_id = undefined;
              };
  
              if ( debounce_mode && !timeout_id ) {
                  // Since `wrapper` is being called for the first time and
                  // `debounce_mode` is true (at_begin), execute `callback`.
                  exec();
              }
  
              // Clear any existing timeout.
              timeout_id && clearTimeout( timeout_id );
  
              if ( debounce_mode === undefined && elapsed > delay ) {
                  // In throttle mode, if `delay` time has been exceeded, execute
                  // `callback`.
                  exec();
  
              } else if ( no_trailing !== true ) {
                  // In trailing throttle mode, since `delay` time has not been
                  // exceeded, schedule `callback` to execute `delay` ms after most
                  // recent execution.
                  //
                  // If `debounce_mode` is true (at_begin), schedule `clear` to execute
                  // after `delay` ms.
                  //
                  // If `debounce_mode` is false (at end), schedule `callback` to
                  // execute after `delay` ms.
                  timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
              }
          };
  
          // Set the guid of `wrapper` function to the same of original callback, so
          // it can be removed in jQuery 1.4+ .unbind or .die by using the original
          // callback as a reference.
          if ( $.guid ) {
              wrapper.guid = callback.guid = callback.guid || $.guid++;
          }
  
          // Return the wrapper function.
          return wrapper;
      };
  
      // Method: jQuery.debounce
      //
      // Debounce execution of a function. Debouncing, unlike throttling,
      // guarantees that a function is only executed a single time, either at the
      // very beginning of a series of calls, or at the very end. If you want to
      // simply rate-limit execution of a function, see the <jQuery.throttle>
      // method.
      //
      // In this visualization, | is a debounced-function call and X is the actual
      // callback execution:
      //
      // > Debounced with `at_begin` specified as false or unspecified:
      // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
      // >                          X                                 X
      // >
      // > Debounced with `at_begin` specified as true:
      // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
      // > X                                 X
      //
      // Usage:
      //
      // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
      // >
      // > jQuery('selector').bind( 'someevent', debounced );
      // > jQuery('selector').unbind( 'someevent', debounced );
      //
      // This also works in jQuery 1.4+:
      //
      // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
      // > jQuery('selector').unbind( 'someevent', callback );
      //
      // Arguments:
      //
      //  delay - (Number) A zero-or-greater delay in milliseconds. For event
      //    callbacks, values around 100 or 250 (or even higher) are most useful.
      //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
      //    unspecified, callback will only be executed `delay` milliseconds after
      //    the last debounced-function call. If at_begin is true, callback will be
      //    executed only at the first debounced-function call. (After the
      //    throttled-function has not been called for `delay` milliseconds, the
      //    internal counter is reset)
      //  callback - (Function) A function to be executed after delay milliseconds.
      //    The `this` context and all arguments are passed through, as-is, to
      //    `callback` when the debounced-function is executed.
      //
      // Returns:
      //
      //  (Function) A new, debounced, function.
  
      $.debounce = function( delay, at_begin, callback ) {
          return callback === undefined
              ? jq_throttle( delay, at_begin, false )
              : jq_throttle( delay, callback, at_begin !== false );
      };
  
  })(this);
  /* Javascript plotting library for jQuery, version 0.8.3.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  */
  
  // 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($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/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(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/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(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={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($) {
  
  	// Cache the prototype hasOwnProperty for faster access
  
  	var hasOwnProperty = Object.prototype.hasOwnProperty;
  
      // A shim to provide 'detach' to jQuery versions prior to 1.4.  Using a DOM
      // operation produces the same effect as detach, i.e. removing the element
      // without touching its jQuery data.
  
      // Do not merge this into Flot 0.9, since it requires jQuery 1.4.4+.
  
      if (!$.fn.detach) {
          $.fn.detach = function() {
              return this.each(function() {
                  if (this.parentNode) {
                      this.parentNode.removeChild( this );
                  }
              });
          };
      }
  
  	///////////////////////////////////////////////////////////////////////////
  	// The Canvas object is a wrapper around an HTML5 <canvas> tag.
  	//
  	// @constructor
  	// @param {string} cls List of classes to apply to the canvas.
  	// @param {element} container Element onto which to append the canvas.
  	//
  	// Requiring a container is a little iffy, but unfortunately canvas
  	// operations don't work unless the canvas is attached to the DOM.
  
  	function Canvas(cls, container) {
  
  		var element = container.children("." + cls)[0];
  
  		if (element == null) {
  
  			element = document.createElement("canvas");
  			element.className = cls;
  
  			$(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 })
  				.appendTo(container);
  
  			// If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas
  
  			if (!element.getContext) {
  				if (window.G_vmlCanvasManager) {
  					element = window.G_vmlCanvasManager.initElement(element);
  				} else {
  					throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");
  				}
  			}
  		}
  
  		this.element = element;
  
  		var context = this.context = element.getContext("2d");
  
  		// Determine the screen's ratio of physical to device-independent
  		// pixels.  This is the ratio between the canvas width that the browser
  		// advertises and the number of pixels actually present in that space.
  
  		// The iPhone 4, for example, has a device-independent width of 320px,
  		// but its screen is actually 640px wide.  It therefore has a pixel
  		// ratio of 2, while most normal devices have a ratio of 1.
  
  		var devicePixelRatio = window.devicePixelRatio || 1,
  			backingStoreRatio =
  				context.webkitBackingStorePixelRatio ||
  				context.mozBackingStorePixelRatio ||
  				context.msBackingStorePixelRatio ||
  				context.oBackingStorePixelRatio ||
  				context.backingStorePixelRatio || 1;
  
  		this.pixelRatio = devicePixelRatio / backingStoreRatio;
  
  		// Size the canvas to match the internal dimensions of its container
  
  		this.resize(container.width(), container.height());
  
  		// Collection of HTML div layers for text overlaid onto the canvas
  
  		this.textContainer = null;
  		this.text = {};
  
  		// Cache of text fragments and metrics, so we can avoid expensively
  		// re-calculating them when the plot is re-rendered in a loop.
  
  		this._textCache = {};
  	}
  
  	// Resizes the canvas to the given dimensions.
  	//
  	// @param {number} width New width of the canvas, in pixels.
  	// @param {number} width New height of the canvas, in pixels.
  
  	Canvas.prototype.resize = function(width, height) {
  
  		if (width <= 0 || height <= 0) {
  			throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height);
  		}
  
  		var element = this.element,
  			context = this.context,
  			pixelRatio = this.pixelRatio;
  
  		// Resize the canvas, increasing its density based on the display's
  		// pixel ratio; basically giving it more pixels without increasing the
  		// size of its element, to take advantage of the fact that retina
  		// displays have that many more pixels in the same advertised space.
  
  		// Resizing should reset the state (excanvas seems to be buggy though)
  
  		if (this.width != width) {
  			element.width = width * pixelRatio;
  			element.style.width = width + "px";
  			this.width = width;
  		}
  
  		if (this.height != height) {
  			element.height = height * pixelRatio;
  			element.style.height = height + "px";
  			this.height = height;
  		}
  
  		// Save the context, so we can reset in case we get replotted.  The
  		// restore ensure that we're really back at the initial state, and
  		// should be safe even if we haven't saved the initial state yet.
  
  		context.restore();
  		context.save();
  
  		// Scale the coordinate space to match the display density; so even though we
  		// may have twice as many pixels, we still want lines and other drawing to
  		// appear at the same size; the extra pixels will just make them crisper.
  
  		context.scale(pixelRatio, pixelRatio);
  	};
  
  	// Clears the entire canvas area, not including any overlaid HTML text
  
  	Canvas.prototype.clear = function() {
  		this.context.clearRect(0, 0, this.width, this.height);
  	};
  
  	// Finishes rendering the canvas, including managing the text overlay.
  
  	Canvas.prototype.render = function() {
  
  		var cache = this._textCache;
  
  		// For each text layer, add elements marked as active that haven't
  		// already been rendered, and remove those that are no longer active.
  
  		for (var layerKey in cache) {
  			if (hasOwnProperty.call(cache, layerKey)) {
  
  				var layer = this.getTextLayer(layerKey),
  					layerCache = cache[layerKey];
  
  				layer.hide();
  
  				for (var styleKey in layerCache) {
  					if (hasOwnProperty.call(layerCache, styleKey)) {
  						var styleCache = layerCache[styleKey];
  						for (var key in styleCache) {
  							if (hasOwnProperty.call(styleCache, key)) {
  
  								var positions = styleCache[key].positions;
  
  								for (var i = 0, position; position = positions[i]; i++) {
  									if (position.active) {
  										if (!position.rendered) {
  											layer.append(position.element);
  											position.rendered = true;
  										}
  									} else {
  										positions.splice(i--, 1);
  										if (position.rendered) {
  											position.element.detach();
  										}
  									}
  								}
  
  								if (positions.length == 0) {
  									delete styleCache[key];
  								}
  							}
  						}
  					}
  				}
  
  				layer.show();
  			}
  		}
  	};
  
  	// Creates (if necessary) and returns the text overlay container.
  	//
  	// @param {string} classes String of space-separated CSS classes used to
  	//     uniquely identify the text layer.
  	// @return {object} The jQuery-wrapped text-layer div.
  
  	Canvas.prototype.getTextLayer = function(classes) {
  
  		var layer = this.text[classes];
  
  		// Create the text layer if it doesn't exist
  
  		if (layer == null) {
  
  			// Create the text layer container, if it doesn't exist
  
  			if (this.textContainer == null) {
  				this.textContainer = $("<div class='flot-text'></div>")
  					.css({
  						position: "absolute",
  						top: 0,
  						left: 0,
  						bottom: 0,
  						right: 0,
  						'font-size': "smaller",
  						color: "#545454"
  					})
  					.insertAfter(this.element);
  			}
  
  			layer = this.text[classes] = $("<div></div>")
  				.addClass(classes)
  				.css({
  					position: "absolute",
  					top: 0,
  					left: 0,
  					bottom: 0,
  					right: 0
  				})
  				.appendTo(this.textContainer);
  		}
  
  		return layer;
  	};
  
  	// Creates (if necessary) and returns a text info object.
  	//
  	// The object looks like this:
  	//
  	// {
  	//     width: Width of the text's wrapper div.
  	//     height: Height of the text's wrapper div.
  	//     element: The jQuery-wrapped HTML div containing the text.
  	//     positions: Array of positions at which this text is drawn.
  	// }
  	//
  	// The positions array contains objects that look like this:
  	//
  	// {
  	//     active: Flag indicating whether the text should be visible.
  	//     rendered: Flag indicating whether the text is currently visible.
  	//     element: The jQuery-wrapped HTML div containing the text.
  	//     x: X coordinate at which to draw the text.
  	//     y: Y coordinate at which to draw the text.
  	// }
  	//
  	// Each position after the first receives a clone of the original element.
  	//
  	// The idea is that that the width, height, and general 'identity' of the
  	// text is constant no matter where it is placed; the placements are a
  	// secondary property.
  	//
  	// Canvas maintains a cache of recently-used text info objects; getTextInfo
  	// either returns the cached element or creates a new entry.
  	//
  	// @param {string} layer A string of space-separated CSS classes uniquely
  	//     identifying the layer containing this text.
  	// @param {string} text Text string to retrieve info for.
  	// @param {(string|object)=} font Either a string of space-separated CSS
  	//     classes or a font-spec object, defining the text's font and style.
  	// @param {number=} angle Angle at which to rotate the text, in degrees.
  	//     Angle is currently unused, it will be implemented in the future.
  	// @param {number=} width Maximum width of the text before it wraps.
  	// @return {object} a text info object.
  
  	Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) {
  
  		var textStyle, layerCache, styleCache, info;
  
  		// Cast the value to a string, in case we were given a number or such
  
  		text = "" + text;
  
  		// If the font is a font-spec object, generate a CSS font definition
  
  		if (typeof font === "object") {
  			textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family;
  		} else {
  			textStyle = font;
  		}
  
  		// Retrieve (or create) the cache for the text's layer and styles
  
  		layerCache = this._textCache[layer];
  
  		if (layerCache == null) {
  			layerCache = this._textCache[layer] = {};
  		}
  
  		styleCache = layerCache[textStyle];
  
  		if (styleCache == null) {
  			styleCache = layerCache[textStyle] = {};
  		}
  
  		info = styleCache[text];
  
  		// If we can't find a matching element in our cache, create a new one
  
  		if (info == null) {
  
  			var element = $("<div></div>").html(text)
  				.css({
  					position: "absolute",
  					'max-width': width,
  					top: -9999
  				})
  				.appendTo(this.getTextLayer(layer));
  
  			if (typeof font === "object") {
  				element.css({
  					font: textStyle,
  					color: font.color
  				});
  			} else if (typeof font === "string") {
  				element.addClass(font);
  			}
  
  			info = styleCache[text] = {
  				width: element.outerWidth(true),
  				height: element.outerHeight(true),
  				element: element,
  				positions: []
  			};
  
  			element.detach();
  		}
  
  		return info;
  	};
  
  	// Adds a text string to the canvas text overlay.
  	//
  	// The text isn't drawn immediately; it is marked as rendering, which will
  	// result in its addition to the canvas on the next render pass.
  	//
  	// @param {string} layer A string of space-separated CSS classes uniquely
  	//     identifying the layer containing this text.
  	// @param {number} x X coordinate at which to draw the text.
  	// @param {number} y Y coordinate at which to draw the text.
  	// @param {string} text Text string to draw.
  	// @param {(string|object)=} font Either a string of space-separated CSS
  	//     classes or a font-spec object, defining the text's font and style.
  	// @param {number=} angle Angle at which to rotate the text, in degrees.
  	//     Angle is currently unused, it will be implemented in the future.
  	// @param {number=} width Maximum width of the text before it wraps.
  	// @param {string=} halign Horizontal alignment of the text; either "left",
  	//     "center" or "right".
  	// @param {string=} valign Vertical alignment of the text; either "top",
  	//     "middle" or "bottom".
  
  	Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {
  
  		var info = this.getTextInfo(layer, text, font, angle, width),
  			positions = info.positions;
  
  		// Tweak the div's position to match the text's alignment
  
  		if (halign == "center") {
  			x -= info.width / 2;
  		} else if (halign == "right") {
  			x -= info.width;
  		}
  
  		if (valign == "middle") {
  			y -= info.height / 2;
  		} else if (valign == "bottom") {
  			y -= info.height;
  		}
  
  		// Determine whether this text already exists at this position.
  		// If so, mark it for inclusion in the next render pass.
  
  		for (var i = 0, position; position = positions[i]; i++) {
  			if (position.x == x && position.y == y) {
  				position.active = true;
  				return;
  			}
  		}
  
  		// If the text doesn't exist at this position, create a new entry
  
  		// For the very first position we'll re-use the original element,
  		// while for subsequent ones we'll clone it.
  
  		position = {
  			active: true,
  			rendered: false,
  			element: positions.length ? info.element.clone() : info.element,
  			x: x,
  			y: y
  		};
  
  		positions.push(position);
  
  		// Move the element to its final position within the container
  
  		position.element.css({
  			top: Math.round(y),
  			left: Math.round(x),
  			'text-align': halign	// In case the text wraps
  		});
  	};
  
  	// Removes one or more text strings from the canvas text overlay.
  	//
  	// If no parameters are given, all text within the layer is removed.
  	//
  	// Note that the text is not immediately removed; it is simply marked as
  	// inactive, which will result in its removal on the next render pass.
  	// This avoids the performance penalty for 'clear and redraw' behavior,
  	// where we potentially get rid of all text on a layer, but will likely
  	// add back most or all of it later, as when redrawing axes, for example.
  	//
  	// @param {string} layer A string of space-separated CSS classes uniquely
  	//     identifying the layer containing this text.
  	// @param {number=} x X coordinate of the text.
  	// @param {number=} y Y coordinate of the text.
  	// @param {string=} text Text string to remove.
  	// @param {(string|object)=} font Either a string of space-separated CSS
  	//     classes or a font-spec object, defining the text's font and style.
  	// @param {number=} angle Angle at which the text is rotated, in degrees.
  	//     Angle is currently unused, it will be implemented in the future.
  
  	Canvas.prototype.removeText = function(layer, x, y, text, font, angle) {
  		if (text == null) {
  			var layerCache = this._textCache[layer];
  			if (layerCache != null) {
  				for (var styleKey in layerCache) {
  					if (hasOwnProperty.call(layerCache, styleKey)) {
  						var styleCache = layerCache[styleKey];
  						for (var key in styleCache) {
  							if (hasOwnProperty.call(styleCache, key)) {
  								var positions = styleCache[key].positions;
  								for (var i = 0, position; position = positions[i]; i++) {
  									position.active = false;
  								}
  							}
  						}
  					}
  				}
  			}
  		} else {
  			var positions = this.getTextInfo(layer, text, font, angle).positions;
  			for (var i = 0, position; position = positions[i]; i++) {
  				if (position.x == x && position.y == y) {
  					position.active = false;
  				}
  			}
  		}
  	};
  
  	///////////////////////////////////////////////////////////////////////////
  	// The top-level container for the entire plot.
  
      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: ["rgba(76, 84, 84, 1)", "#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: 1.85, // set to 0 to avoid background
                      sorted: null    // default to no legend sorting
                  },
                  xaxis: {
                      show: null, // null = auto-detect, true = always, false = never
                      position: "bottom", // or "top"
                      mode: null, // null or "time"
                      font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
                      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
                      tickDecimals: null, // no. of decimals, null means auto
                      tickSize: null, // number or [number, "unit"]
                      minTickSize: null // number or [number, "unit"]
                  },
                  yaxis: {
                      autoscaleMargin: 0.02,
                      position: "left" // or "right"
                  },
                  xaxes: [],
                  yaxes: [],
                  series: {
                      points: {
                          show: false,
                          radius: 3,
                          lineWidth: 1, // 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
                          // Omit 'zero', so we can later default its value to
                          // match that of the 'fill' option.
                      },
                      bars: {
                          show: false,
                          lineWidth: 2, // in pixels
                          barWidth: 1, // in units of the x axis
                          fill: true,
                          fillColor: null,
                          align: "left", // "left", "right", or "center"
                          horizontal: false,
                          zero: true
                      },
                      shadowSize: 3,
                      highlightColor: null
                  },
                  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)"
                      margin: 0, // distance from the canvas edge to the grid
                      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
                  },
                  interaction: {
                      redrawOverlayInterval: 1000/60 // time between updates, -1 means in same flow
                  },
                  hooks: {}
              },
          surface = 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},
          plotWidth = 0, plotHeight = 0,
          hooks = {
              processOptions: [],
              processRawData: [],
              processDatapoints: [],
              processOffset: [],
              drawBackground: [],
              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 surface.element; };
          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, 10),
                  top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10)
              };
          };
          plot.shutdown = shutdown;
          plot.destroy = function () {
              shutdown();
              placeholder.removeData("plot").empty();
  
              series = [];
              options = null;
              surface = null;
              overlay = null;
              eventHolder = null;
              ctx = null;
              octx = null;
              xaxes = [];
              yaxes = [];
              hooks = null;
              highlights = [];
              plot = null;
          };
          plot.resize = function () {
          	var width = placeholder.width(),
          		height = placeholder.height();
              surface.resize(width, height);
              overlay.resize(width, height);
          };
  
          // 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() {
  
              // References to key classes, allowing plugins to modify them
  
              var classes = {
                  Canvas: Canvas
              };
  
              for (var i = 0; i < plugins.length; ++i) {
                  var p = plugins[i];
                  p.init(plot, classes);
                  if (p.options)
                      $.extend(true, options, p.options);
              }
          }
  
          function parseOptions(opts) {
  
              $.extend(true, options, opts);
  
              // $.extend merges arrays, rather than replacing them.  When less
              // colors are provided than the size of the default palette, we
              // end up with those colors plus the remaining defaults, which is
              // not expected behavior; avoid it by replacing them here.
  
              if (opts && opts.colors) {
              	options.colors = opts.colors;
              }
  
              if (options.xaxis.color == null)
                  options.xaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
              if (options.yaxis.color == null)
                  options.yaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
  
              if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility
                  options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color;
              if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility
                  options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color;
  
              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 for axis options, including any unspecified
              // font-spec fields, if a font-spec was provided.
  
              // If no x/y axis options were provided, create one of each anyway,
              // since the rest of the code assumes that they exist.
  
              var i, axisOptions, axisCount,
                  fontSize = placeholder.css("font-size"),
                  fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13,
                  fontDefaults = {
                      style: placeholder.css("font-style"),
                      size: Math.round(0.8 * fontSizeDefault),
                      variant: placeholder.css("font-variant"),
                      weight: placeholder.css("font-weight"),
                      family: placeholder.css("font-family")
                  };
  
              axisCount = options.xaxes.length || 1;
              for (i = 0; i < axisCount; ++i) {
  
                  axisOptions = options.xaxes[i];
                  if (axisOptions && !axisOptions.tickColor) {
                      axisOptions.tickColor = axisOptions.color;
                  }
  
                  axisOptions = $.extend(true, {}, options.xaxis, axisOptions);
                  options.xaxes[i] = axisOptions;
  
                  if (axisOptions.font) {
                      axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
                      if (!axisOptions.font.color) {
                          axisOptions.font.color = axisOptions.color;
                      }
                      if (!axisOptions.font.lineHeight) {
                          axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
                      }
                  }
              }
  
              axisCount = options.yaxes.length || 1;
              for (i = 0; i < axisCount; ++i) {
  
                  axisOptions = options.yaxes[i];
                  if (axisOptions && !axisOptions.tickColor) {
                      axisOptions.tickColor = axisOptions.color;
                  }
  
                  axisOptions = $.extend(true, {}, options.yaxis, axisOptions);
                  options.yaxes[i] = axisOptions;
  
                  if (axisOptions.font) {
                      axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
                      if (!axisOptions.font.color) {
                          axisOptions.font.color = axisOptions.color;
                      }
                      if (!axisOptions.font.lineHeight) {
                          axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
                      }
                  }
              }
  
              // 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";
                  // Override the inherit to allow the axis to auto-scale
                  if (options.x2axis.min == null) {
                      options.xaxes[1].min = null;
                  }
                  if (options.x2axis.max == null) {
                      options.xaxes[1].max = null;
                  }
              }
              if (options.y2axis) {
                  options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
                  options.yaxes[1].position = "right";
                  // Override the inherit to allow the axis to auto-scale
                  if (options.y2axis.min == null) {
                      options.yaxes[1].min = null;
                  }
                  if (options.y2axis.max == null) {
                      options.yaxes[1].max = null;
                  }
              }
              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;
              if (options.highlightColor != null)
                  options.series.highlightColor = options.highlightColor;
  
              // 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 neededColors = series.length, maxIndex = -1, i;
  
              // Subtract the number of series that already have fixed colors or
              // color indexes from the number that we still need to generate.
  
              for (i = 0; i < series.length; ++i) {
                  var sc = series[i].color;
                  if (sc != null) {
                      neededColors--;
                      if (typeof sc == "number" && sc > maxIndex) {
                          maxIndex = sc;
                      }
                  }
              }
  
              // If any of the series have fixed color indexes, then we need to
              // generate at least as many colors as the highest index.
  
              if (neededColors <= maxIndex) {
                  neededColors = maxIndex + 1;
              }
  
              // Generate all the colors, using first the option colors and then
              // variations on those colors once they're exhausted.
  
              var c, colors = [], colorPool = options.colors,
                  colorPoolSize = colorPool.length, variation = 0;
  
              for (i = 0; i < neededColors; i++) {
  
                  c = $.color.parse(colorPool[i % colorPoolSize] || "#666");
  
                  // Each time we exhaust the colors in the pool we adjust
                  // a scaling factor used to produce more variations on
                  // those colors. The factor alternates negative/positive
                  // to produce lighter/darker colors.
  
                  // Reset the variation after every few cycles, or else
                  // it will end up producing only white or black colors.
  
                  if (i % colorPoolSize == 0 && i) {
                      if (variation >= 0) {
                          if (variation < 0.5) {
                              variation = -variation - 0.2;
                          } else variation = 0;
                      } else variation = -variation;
                  }
  
                  colors[i] = c.scale('rgb', 1 + variation);
              }
  
              // Finalize the series options, filling in their colors
  
              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;
                  }
  
                  // If nothing was provided for lines.zero, default it to match
                  // lines.fill, since areas by default should extend to zero.
  
                  if (s.lines.zero == null) {
                      s.lines.zero = !!s.lines.fill;
                  }
  
                  // 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,
                  data, format;
  
              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];
  
                  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)) {
                          var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
                          format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
                          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;
  
                  var 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.autoscale !== false) {
                                      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;
                  format = s.datapoints.format;
  
                  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 || f.autoscale === false || 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;
  
                      switch (s.bars.align) {
                          case "left":
                              delta = 0;
                              break;
                          case "right":
                              delta = -s.bars.barWidth;
                              break;
                          default:
                              delta = -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 setupCanvases() {
  
              // Make sure the placeholder is clear of everything except canvases
              // from a previous plot in this container that we'll try to re-use.
  
              placeholder.css("padding", 0) // padding messes up the positioning
                  .children().filter(function(){
                      return !$(this).hasClass("flot-overlay") && !$(this).hasClass('flot-base');
                  }).remove();
  
              if (placeholder.css("position") == 'static')
                  placeholder.css("position", "relative"); // for positioning labels and overlay
  
              surface = new Canvas("flot-base", placeholder);
              overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features
  
              ctx = surface.context;
              octx = overlay.context;
  
              // define which element we're listening for events on
              eventHolder = $(overlay.element).unbind();
  
              // If we're re-using a plot object, shut down the old one
  
              var existing = placeholder.data("plot");
  
              if (existing) {
                  existing.shutdown();
                  overlay.clear();
              }
  
              // save in case we get replotted
              placeholder.data("plot", plot);
          }
  
          function bindEvents() {
              // bind events
              if (options.grid.hoverable) {
                  eventHolder.mousemove(onMouseMove);
  
                  // Use bind, rather than .mouseleave, because we officially
                  // still support jQuery 1.2.6, which doesn't define a shortcut
                  // for mouseenter or mouseleave.  This was a bug/oversight that
                  // was fixed somewhere around 1.3.x.  We can return to using
                  // .mouseleave when we drop support for 1.2.6.
  
                  eventHolder.bind("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,
                  ticks = axis.ticks || [],
                  labelWidth = opts.labelWidth || 0,
                  labelHeight = opts.labelHeight || 0,
                  maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null),
                  legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
                  layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
                  font = opts.font || "flot-tick-label tickLabel";
  
              for (var i = 0; i < ticks.length; ++i) {
  
                  var t = ticks[i];
  
                  if (!t.label)
                      continue;
  
                  var info = surface.getTextInfo(layer, t.label, font, null, maxWidth);
  
                  labelWidth = Math.max(labelWidth, info.width);
                  labelHeight = Math.max(labelHeight, info.height);
              }
  
              axis.labelWidth = opts.labelWidth || labelWidth;
              axis.labelHeight = opts.labelHeight || labelHeight;
          }
  
          function allocateAxisBoxFirstPhase(axis) {
              // find the bounding box of the axis by looking at label
              // widths/heights and ticks, make room by diminishing the
              // plotOffset; this first phase only looks at one
              // dimension per axis, the other dimension depends on the
              // other axes so will have to wait
  
              var lw = axis.labelWidth,
                  lh = axis.labelHeight,
                  pos = axis.options.position,
                  isXAxis = axis.direction === "x",
                  tickLength = axis.options.tickLength,
                  axisMargin = options.grid.axisMargin,
                  padding = options.grid.labelMargin,
                  innermost = true,
                  outermost = true,
                  first = true,
                  found = false;
  
              // Determine the axis's position in its direction and on its side
  
              $.each(isXAxis ? xaxes : yaxes, function(i, a) {
                  if (a && (a.show || a.reserveSpace)) {
                      if (a === axis) {
                          found = true;
                      } else if (a.options.position === pos) {
                          if (found) {
                              outermost = false;
                          } else {
                              innermost = false;
                          }
                      }
                      if (!found) {
                          first = false;
                      }
                  }
              });
  
              // The outermost axis on each side has no margin
  
              if (outermost) {
                  axisMargin = 0;
              }
  
              // The ticks for the first axis in each direction stretch across
  
              if (tickLength == null) {
                  tickLength = first ? "full" : 5;
              }
  
              if (!isNaN(+tickLength))
                  padding += +tickLength;
  
              if (isXAxis) {
                  lh += padding;
  
                  if (pos == "bottom") {
                      plotOffset.bottom += lh + axisMargin;
                      axis.box = { top: surface.height - 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: surface.width - plotOffset.right, width: lw };
                  }
              }
  
               // save for future reference
              axis.position = pos;
              axis.tickLength = tickLength;
              axis.box.padding = padding;
              axis.innermost = innermost;
          }
  
          function allocateAxisBoxSecondPhase(axis) {
              // now that all axis boxes have been placed in one
              // dimension, we can set the remaining dimension coordinates
              if (axis.direction == "x") {
                  axis.box.left = plotOffset.left - axis.labelWidth / 2;
                  axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth;
              }
              else {
                  axis.box.top = plotOffset.top - axis.labelHeight / 2;
                  axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight;
              }
          }
  
          function adjustLayoutForThingsStickingOut() {
              // possibly adjust plot offset to ensure everything stays
              // inside the canvas and isn't clipped off
  
              var minMargin = options.grid.minBorderMargin,
                  axis, i;
  
              // check stuff from the plot (FIXME: this should just read
              // a value from the series, otherwise it's impossible to
              // customize)
              if (minMargin == null) {
                  minMargin = 0;
                  for (i = 0; i < series.length; ++i)
                      minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
              }
  
              var margins = {
                  left: minMargin,
                  right: minMargin,
                  top: minMargin,
                  bottom: minMargin
              };
  
              // check axis labels, note we don't check the actual
              // labels but instead use the overall width/height to not
              // jump as much around with replots
              $.each(allAxes(), function (_, axis) {
                  if (axis.reserveSpace && axis.ticks && axis.ticks.length) {
                      if (axis.direction === "x") {
                          margins.left = Math.max(margins.left, axis.labelWidth / 2);
                          margins.right = Math.max(margins.right, axis.labelWidth / 2);
                      } else {
                          margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2);
                          margins.top = Math.max(margins.top, axis.labelHeight / 2);
                      }
                  }
              });
  
              plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left));
              plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right));
              plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top));
              plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom));
          }
  
          function setupGrid() {
              var i, axes = allAxes(), showGrid = options.grid.show;
  
              // Initialize the plot's offset from the edge of the canvas
  
              for (var a in plotOffset) {
                  var margin = options.grid.margin || 0;
                  plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0;
              }
  
              executeHooks(hooks.processOffset, [plotOffset]);
  
              // If the grid is visible, add its border width to the offset
  
              for (var a in plotOffset) {
                  if(typeof(options.grid.borderWidth) == "object") {
                      plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0;
                  }
                  else {
                      plotOffset[a] += showGrid ? options.grid.borderWidth : 0;
                  }
              }
  
              $.each(axes, function (_, axis) {
                  var axisOpts = axis.options;
                  axis.show = axisOpts.show == null ? axis.used : axisOpts.show;
                  axis.reserveSpace = axisOpts.reserveSpace == null ? axis.show : axisOpts.reserveSpace;
                  setRange(axis);
              });
  
              if (showGrid) {
  
                  var allocatedAxes = $.grep(axes, function (axis) {
                      return axis.show || axis.reserveSpace;
                  });
  
                  $.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 calculated, we can compute the
                  // axis bounding 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
                  adjustLayoutForThingsStickingOut();
  
                  $.each(allocatedAxes, function (_, axis) {
                      allocateAxisBoxSecondPhase(axis);
                  });
              }
  
              plotWidth = surface.width - plotOffset.left - plotOffset.right;
              plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
  
              // now we got the proper plot dimensions, we can compute the scaling
              $.each(axes, function (_, axis) {
                  setTransformationHelpers(axis);
              });
  
              if (showGrid) {
                  drawAxisLabels();
              }
  
              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" ? surface.width : surface.height);
  
              var delta = (axis.max - axis.min) / noTicks,
                  dec = -Math.floor(Math.log(delta) / Math.LN10),
                  maxDec = opts.tickDecimals;
  
              if (maxDec != null && dec > maxDec) {
                  dec = maxDec;
              }
  
              var magn = Math.pow(10, -dec),
                  norm = delta / magn, // norm is between 1.0 and 10.0
                  size;
  
              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.delta = delta;
              axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
              axis.tickSize = opts.tickSize || size;
  
              // Time mode was moved to a plug-in in 0.8, and since so many people use it
              // we'll add an especially friendly reminder to make sure they included it.
  
              if (opts.mode == "time" && !axis.tickGenerator) {
                  throw new Error("Time mode requires the flot.time plugin.");
              }
  
              // Flot supports base-10 axes; any other mode else is handled by a plug-in,
              // like flot.time.js.
  
              if (!axis.tickGenerator) {
  
                  axis.tickGenerator = function (axis) {
  
                      var ticks = [],
                          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;
                  };
  
  				axis.tickFormatter = function (value, axis) {
  
  					var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1;
  					var formatted = "" + Math.round(value * factor) / factor;
  
  					// If tickDecimals was specified, ensure that we have exactly that
  					// much precision; otherwise default to the value's own precision.
  
  					if (axis.tickDecimals != null) {
  						var decimal = formatted.indexOf(".");
  						var precision = decimal == -1 ? 0 : formatted.length - decimal - 1;
  						if (precision < axis.tickDecimals) {
  							return (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);
  						}
  					}
  
                      return formatted;
                  };
              }
  
              if ($.isFunction(opts.tickFormatter))
                  axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
  
              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 = axis.tickGenerator(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]);
                      }
  
                      axis.tickGenerator = 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 && opts.tickDecimals == null) {
                          var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
                              ts = axis.tickGenerator(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;
                      }
                  }
              }
          }
  
          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(axis);
                  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() {
  
              surface.clear();
  
              executeHooks(hooks.drawBackground, [ctx]);
  
              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();
              }
  
              surface.render();
  
              // A draw implies that either the axes or data have changed, so we
              // should probably update the overlay highlights as well.
  
              triggerRedrawOverlay();
          }
  
          function extractRange(ranges, coord) {
              var axis, from, to, key, axes = allAxes();
  
              for (var 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, axes, bw, bc;
  
              ctx.save();
              ctx.translate(plotOffset.left, plotOffset.top);
  
              // draw markings
              var markings = options.grid.markings;
              if (markings) {
                  if ($.isFunction(markings)) {
                      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);
  
                      var xequal = xrange.from === xrange.to,
                          yequal = yrange.from === yrange.to;
  
                      if (xequal && yequal) {
                          continue;
                      }
  
                      // then draw
                      xrange.from = Math.floor(xrange.axis.p2c(xrange.from));
                      xrange.to = Math.floor(xrange.axis.p2c(xrange.to));
                      yrange.from = Math.floor(yrange.axis.p2c(yrange.from));
                      yrange.to = Math.floor(yrange.axis.p2c(yrange.to));
  
                      if (xequal || yequal) {
                          var lineWidth = m.lineWidth || options.grid.markingsLineWidth,
                              subPixel = lineWidth % 2 ? 0.5 : 0;
                          ctx.beginPath();
                          ctx.strokeStyle = m.color || options.grid.markingsColor;
                          ctx.lineWidth = lineWidth;
                          if (xequal) {
                              ctx.moveTo(xrange.to + subPixel, yrange.from);
                              ctx.lineTo(xrange.to + subPixel, yrange.to);
                          } else {
                              ctx.moveTo(xrange.from, yrange.to + subPixel);
                              ctx.lineTo(xrange.to, yrange.to + subPixel);
                          }
                          ctx.stroke();
                      } else {
                          ctx.fillStyle = m.color || options.grid.markingsColor;
                          ctx.fillRect(xrange.from, yrange.to,
                                       xrange.to - xrange.from,
                                       yrange.from - yrange.to);
                      }
                  }
              }
  
              // draw the ticks
              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.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.strokeStyle = axis.options.color;
                      ctx.beginPath();
                      xoff = yoff = 0;
                      if (axis.direction == "x")
                          xoff = plotWidth + 1;
                      else
                          yoff = plotHeight + 1;
  
                      if (ctx.lineWidth == 1) {
                          if (axis.direction == "x") {
                              y = Math.floor(y) + 0.5;
                          } else {
                              x = Math.floor(x) + 0.5;
                          }
                      }
  
                      ctx.moveTo(x, y);
                      ctx.lineTo(x + xoff, y + yoff);
                      ctx.stroke();
                  }
  
                  // draw ticks
  
                  ctx.strokeStyle = axis.options.tickColor;
  
                  ctx.beginPath();
                  for (i = 0; i < axis.ticks.length; ++i) {
                      var v = axis.ticks[i].v;
  
                      xoff = yoff = 0;
  
                      if (isNaN(v) || v < axis.min || v > axis.max
                          // skip those lying on the axes if we got a border
                          || (t == "full"
                              && ((typeof bw == "object" && bw[axis.position] > 0) || 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) {
                  // If either borderWidth or borderColor is an object, then draw the border
                  // line by line instead of as one rectangle
                  bc = options.grid.borderColor;
                  if(typeof bw == "object" || typeof bc == "object") {
                      if (typeof bw !== "object") {
                          bw = {top: bw, right: bw, bottom: bw, left: bw};
                      }
                      if (typeof bc !== "object") {
                          bc = {top: bc, right: bc, bottom: bc, left: bc};
                      }
  
                      if (bw.top > 0) {
                          ctx.strokeStyle = bc.top;
                          ctx.lineWidth = bw.top;
                          ctx.beginPath();
                          ctx.moveTo(0 - bw.left, 0 - bw.top/2);
                          ctx.lineTo(plotWidth, 0 - bw.top/2);
                          ctx.stroke();
                      }
  
                      if (bw.right > 0) {
                          ctx.strokeStyle = bc.right;
                          ctx.lineWidth = bw.right;
                          ctx.beginPath();
                          ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top);
                          ctx.lineTo(plotWidth + bw.right / 2, plotHeight);
                          ctx.stroke();
                      }
  
                      if (bw.bottom > 0) {
                          ctx.strokeStyle = bc.bottom;
                          ctx.lineWidth = bw.bottom;
                          ctx.beginPath();
                          ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2);
                          ctx.lineTo(0, plotHeight + bw.bottom / 2);
                          ctx.stroke();
                      }
  
                      if (bw.left > 0) {
                          ctx.strokeStyle = bc.left;
                          ctx.lineWidth = bw.left;
                          ctx.beginPath();
                          ctx.moveTo(0 - bw.left/2, plotHeight + bw.bottom);
                          ctx.lineTo(0- bw.left/2, 0);
                          ctx.stroke();
                      }
                  }
                  else {
                      ctx.lineWidth = bw;
                      ctx.strokeStyle = options.grid.borderColor;
                      ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
                  }
              }
  
              ctx.restore();
          }
  
          function drawAxisLabels() {
  
              $.each(allAxes(), function (_, axis) {
                  var box = axis.box,
                      legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
                      layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
                      font = axis.options.font || "flot-tick-label tickLabel",
                      tick, x, y, halign, valign;
  
                  // Remove text before checking for axis.show and ticks.length;
                  // otherwise plugins, like flot-tickrotor, that draw their own
                  // tick labels will end up with both theirs and the defaults.
  
                  surface.removeText(layer);
  
                  if (!axis.show || axis.ticks.length == 0)
                      return;
  
                  for (var i = 0; i < axis.ticks.length; ++i) {
  
                      tick = axis.ticks[i];
                      if (!tick.label || tick.v < axis.min || tick.v > axis.max)
                          continue;
  
                      if (axis.direction == "x") {
                          halign = "center";
                          x = plotOffset.left + axis.p2c(tick.v);
                          if (axis.position == "bottom") {
                              y = box.top + box.padding;
                          } else {
                              y = box.top + box.height - box.padding;
                              valign = "bottom";
                          }
                      } else {
                          valign = "middle";
                          y = plotOffset.top + axis.p2c(tick.v);
                          if (axis.position == "left") {
                              x = box.left + box.width - box.padding;
                              halign = "right";
                          } else {
                              x = box.left + box.padding;
                          }
                      }
  
                      surface.addText(layer, x, y, tick.label, font, null, null, halign, valign);
                  }
              });
          }
  
          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 the user sets the line width to 0, we change it to a very
              // small value. A line width of 0 seems to force the default of 1.
              // Doing the conditional here allows the shadow setting to still be
              // optional even with a lineWidth of 0.
  
              if( lw == 0 )
                  lw = 0.0001;
  
              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, 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.fillStyle = fillStyleCallback(bottom, top);
                  c.fillRect(left, top, right - left, bottom - top)
              }
  
              // draw outline
              if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
                  c.beginPath();
  
                  // FIXME: inline moveTo is buggy with excanvas
                  c.moveTo(left, bottom);
                  if (drawLeft)
                      c.lineTo(left, top);
                  else
                      c.moveTo(left, top);
                  if (drawTop)
                      c.lineTo(right, top);
                  else
                      c.moveTo(right, top);
                  if (drawRight)
                      c.lineTo(right, bottom);
                  else
                      c.moveTo(right, bottom);
                  if (drawBottom)
                      c.lineTo(left, bottom);
                  else
                      c.moveTo(left, bottom);
                  c.stroke();
              }
          }
  
          function drawSeriesBars(series) {
              function plotBars(datapoints, barLeft, barRight, 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, 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;
  
              switch (series.bars.align) {
                  case "left":
                      barLeft = 0;
                      break;
                  case "right":
                      barLeft = -series.bars.barWidth;
                      break;
                  default:
                      barLeft = -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, 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() {
  
              if (options.legend.container != null) {
                  $(options.legend.container).html("");
              } else {
                  placeholder.find(".legend").remove();
              }
  
              if (!options.legend.show) {
                  return;
              }
  
              var fragments = [], entries = [], rowStarted = false,
                  lf = options.legend.labelFormatter, s, label;
  
              // Build a list of legend entries, with each having a label and a color
  
              for (var i = 0; i < series.length; ++i) {
                  s = series[i];
                  if (s.label) {
                      label = lf ? lf(s.label, s) : s.label;
                      if (label) {
                          entries.push({
                              label: label,
                              color: s.color
                          });
                      }
                  }
              }
  
              // Sort the legend using either the default or a custom comparator
  
              if (options.legend.sorted) {
                  if ($.isFunction(options.legend.sorted)) {
                      entries.sort(options.legend.sorted);
                  } else if (options.legend.sorted == "reverse") {
                  	entries.reverse();
                  } else {
                      var ascending = options.legend.sorted != "descending";
                      entries.sort(function(a, b) {
                          return a.label == b.label ? 0 : (
                              (a.label < b.label) != ascending ? 1 : -1   // Logical XOR
                          );
                      });
                  }
              }
  
              // Generate markup for the list of entries, in their final order
  
              for (var i = 0; i < entries.length; ++i) {
  
                  var entry = entries[i];
  
                  if (i % options.legend.noColumns == 0) {
                      if (rowStarted)
                          fragments.push('</tr>');
                      fragments.push('<tr>');
                      rowStarted = true;
                  }
  
                  fragments.push(
                      '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + entry.color + ';overflow:hidden"></div></div></td>' +
                      '<td class="legendLabel">' + entry.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, ps;
  
              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,
                      mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
                      my = axisy.c2p(mouseY),
                      maxx = maxDistance / axisx.scale,
                      maxy = maxDistance / axisy.scale;
  
                  ps = s.datapoints.pointsize;
                  // 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, barRight;
  
                      switch (s.bars.align) {
                          case "left":
                              barLeft = 0;
                              break;
                          case "right":
                              barLeft = -s.bars.barWidth;
                              break;
                          default:
                              barLeft = -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, 10);
                  item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10);
              }
  
              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() {
              var t = options.interaction.redrawOverlayInterval;
              if (t == -1) {      // skip event queue
                  drawOverlay();
                  return;
              }
  
              if (!redrawTimeout)
                  redrawTimeout = setTimeout(drawOverlay, t);
          }
  
          function drawOverlay() {
              redrawTimeout = null;
  
              // draw highlights
              octx.save();
              overlay.clear();
              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();
                  return;
              }
  
              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.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,
                  highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString();
  
              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 = highlightColor;
              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) {
              var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(),
                  fillStyle = highlightColor,
                  barLeft;
  
              switch (series.bars.align) {
                  case "left":
                      barLeft = 0;
                      break;
                  case "right":
                      barLeft = -series.bars.barWidth;
                      break;
                  default:
                      barLeft = -series.bars.barWidth / 2;
              }
  
              octx.lineWidth = series.bars.lineWidth;
              octx.strokeStyle = highlightColor;
  
              drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
                      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;
              }
          }
      }
  
      // Add the plot function to the top level of the jQuery object
  
      $.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.8.3";
  
      $.plot.plugins = [];
  
      // Also add the plot function as a chainable property
  
      $.fn.plot = function(data, options) {
          return this.each(function() {
              $.plot(this, data, options);
          });
      };
  
      // round to nearby lower multiple of base
      function floorInBase(n, base) {
          return base * Math.floor(n / base);
      }
  
  })(jQuery);
  
  /* Flot plugin for drawing all elements of a plot on the canvas.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  Flot normally produces certain elements, like axis labels and the legend, using
  HTML elements. This permits greater interactivity and customization, and often
  looks better, due to cross-browser canvas text inconsistencies and limitations.
  
  It can also be desirable to render the plot entirely in canvas, particularly
  if the goal is to save it as an image, or if Flot is being used in a context
  where the HTML DOM does not exist, as is the case within Node.js. This plugin
  switches out Flot's standard drawing operations for canvas-only replacements.
  
  Currently the plugin supports only axis labels, but it will eventually allow
  every element of the plot to be rendered directly to canvas.
  
  The plugin supports these options:
  
  {
      canvas: boolean
  }
  
  The "canvas" option controls whether full canvas drawing is enabled, making it
  possible to toggle on and off. This is useful when a plot uses HTML text in the
  browser, but needs to redraw with canvas text when exporting as an image.
  
  */
  
  (function($) {
  
  	var options = {
  		canvas: true
  	};
  
  	var render, getTextInfo, addText;
  
  	// Cache the prototype hasOwnProperty for faster access
  
  	var hasOwnProperty = Object.prototype.hasOwnProperty;
  
  	function init(plot, classes) {
  
  		var Canvas = classes.Canvas;
  
  		// We only want to replace the functions once; the second time around
  		// we would just get our new function back.  This whole replacing of
  		// prototype functions is a disaster, and needs to be changed ASAP.
  
  		if (render == null) {
  			getTextInfo = Canvas.prototype.getTextInfo,
  			addText = Canvas.prototype.addText,
  			render = Canvas.prototype.render;
  		}
  
  		// Finishes rendering the canvas, including overlaid text
  
  		Canvas.prototype.render = function() {
  
  			if (!plot.getOptions().canvas) {
  				return render.call(this);
  			}
  
  			var context = this.context,
  				cache = this._textCache;
  
  			// For each text layer, render elements marked as active
  
  			context.save();
  			context.textBaseline = "middle";
  
  			for (var layerKey in cache) {
  				if (hasOwnProperty.call(cache, layerKey)) {
  					var layerCache = cache[layerKey];
  					for (var styleKey in layerCache) {
  						if (hasOwnProperty.call(layerCache, styleKey)) {
  							var styleCache = layerCache[styleKey],
  								updateStyles = true;
  							for (var key in styleCache) {
  								if (hasOwnProperty.call(styleCache, key)) {
  
  									var info = styleCache[key],
  										positions = info.positions,
  										lines = info.lines;
  
  									// Since every element at this level of the cache have the
  									// same font and fill styles, we can just change them once
  									// using the values from the first element.
  
  									if (updateStyles) {
  										context.fillStyle = info.font.color;
  										context.font = info.font.definition;
  										updateStyles = false;
  									}
  
  									for (var i = 0, position; position = positions[i]; i++) {
  										if (position.active) {
  											for (var j = 0, line; line = position.lines[j]; j++) {
  												context.fillText(lines[j].text, line[0], line[1]);
  											}
  										} else {
  											positions.splice(i--, 1);
  										}
  									}
  
  									if (positions.length == 0) {
  										delete styleCache[key];
  									}
  								}
  							}
  						}
  					}
  				}
  			}
  
  			context.restore();
  		};
  
  		// Creates (if necessary) and returns a text info object.
  		//
  		// When the canvas option is set, the object looks like this:
  		//
  		// {
  		//     width: Width of the text's bounding box.
  		//     height: Height of the text's bounding box.
  		//     positions: Array of positions at which this text is drawn.
  		//     lines: [{
  		//         height: Height of this line.
  		//         widths: Width of this line.
  		//         text: Text on this line.
  		//     }],
  		//     font: {
  		//         definition: Canvas font property string.
  		//         color: Color of the text.
  		//     },
  		// }
  		//
  		// The positions array contains objects that look like this:
  		//
  		// {
  		//     active: Flag indicating whether the text should be visible.
  		//     lines: Array of [x, y] coordinates at which to draw the line.
  		//     x: X coordinate at which to draw the text.
  		//     y: Y coordinate at which to draw the text.
  		// }
  
  		Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) {
  
  			if (!plot.getOptions().canvas) {
  				return getTextInfo.call(this, layer, text, font, angle, width);
  			}
  
  			var textStyle, layerCache, styleCache, info;
  
  			// Cast the value to a string, in case we were given a number
  
  			text = "" + text;
  
  			// If the font is a font-spec object, generate a CSS definition
  
  			if (typeof font === "object") {
  				textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px " + font.family;
  			} else {
  				textStyle = font;
  			}
  
  			// Retrieve (or create) the cache for the text's layer and styles
  
  			layerCache = this._textCache[layer];
  
  			if (layerCache == null) {
  				layerCache = this._textCache[layer] = {};
  			}
  
  			styleCache = layerCache[textStyle];
  
  			if (styleCache == null) {
  				styleCache = layerCache[textStyle] = {};
  			}
  
  			info = styleCache[text];
  
  			if (info == null) {
  
  				var context = this.context;
  
  				// If the font was provided as CSS, create a div with those
  				// classes and examine it to generate a canvas font spec.
  
  				if (typeof font !== "object") {
  
  					var element = $("<div>&nbsp;</div>")
  						.css("position", "absolute")
  						.addClass(typeof font === "string" ? font : null)
  						.appendTo(this.getTextLayer(layer));
  
  					font = {
  						lineHeight: element.height(),
  						style: element.css("font-style"),
  						variant: element.css("font-variant"),
  						weight: element.css("font-weight"),
  						family: element.css("font-family"),
  						color: element.css("color")
  					};
  
  					// Setting line-height to 1, without units, sets it equal
  					// to the font-size, even if the font-size is abstract,
  					// like 'smaller'.  This enables us to read the real size
  					// via the element's height, working around browsers that
  					// return the literal 'smaller' value.
  
  					font.size = element.css("line-height", 1).height();
  
  					element.remove();
  				}
  
  				textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px " + font.family;
  
  				// Create a new info object, initializing the dimensions to
  				// zero so we can count them up line-by-line.
  
  				info = styleCache[text] = {
  					width: 0,
  					height: 0,
  					positions: [],
  					lines: [],
  					font: {
  						definition: textStyle,
  						color: font.color
  					}
  				};
  
  				context.save();
  				context.font = textStyle;
  
  				// Canvas can't handle multi-line strings; break on various
  				// newlines, including HTML brs, to build a list of lines.
  				// Note that we could split directly on regexps, but IE < 9 is
  				// broken; revisit when we drop IE 7/8 support.
  
  				var lines = (text + "").replace(/<br ?\/?>|\r\n|\r/g, "\n").split("\n");
  
  				for (var i = 0; i < lines.length; ++i) {
  
  					var lineText = lines[i],
  						measured = context.measureText(lineText);
  
  					info.width = Math.max(measured.width, info.width);
  					info.height += font.lineHeight;
  
  					info.lines.push({
  						text: lineText,
  						width: measured.width,
  						height: font.lineHeight
  					});
  				}
  
  				context.restore();
  			}
  
  			return info;
  		};
  
  		// Adds a text string to the canvas text overlay.
  
  		Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {
  
  			if (!plot.getOptions().canvas) {
  				return addText.call(this, layer, x, y, text, font, angle, width, halign, valign);
  			}
  
  			var info = this.getTextInfo(layer, text, font, angle, width),
  				positions = info.positions,
  				lines = info.lines;
  
  			// Text is drawn with baseline 'middle', which we need to account
  			// for by adding half a line's height to the y position.
  
  			y += info.height / lines.length / 2;
  
  			// Tweak the initial y-position to match vertical alignment
  
  			if (valign == "middle") {
  				y = Math.round(y - info.height / 2);
  			} else if (valign == "bottom") {
  				y = Math.round(y - info.height);
  			} else {
  				y = Math.round(y);
  			}
  
  			// FIXME: LEGACY BROWSER FIX
  			// AFFECTS: Opera < 12.00
  
  			// Offset the y coordinate, since Opera is off pretty
  			// consistently compared to the other browsers.
  
  			if (!!(window.opera && window.opera.version().split(".")[0] < 12)) {
  				y -= 2;
  			}
  
  			// Determine whether this text already exists at this position.
  			// If so, mark it for inclusion in the next render pass.
  
  			for (var i = 0, position; position = positions[i]; i++) {
  				if (position.x == x && position.y == y) {
  					position.active = true;
  					return;
  				}
  			}
  
  			// If the text doesn't exist at this position, create a new entry
  
  			position = {
  				active: true,
  				lines: [],
  				x: x,
  				y: y
  			};
  
  			positions.push(position);
  
  			// Fill in the x & y positions of each line, adjusting them
  			// individually for horizontal alignment.
  
  			for (var i = 0, line; line = lines[i]; i++) {
  				if (halign == "center") {
  					position.lines.push([Math.round(x - line.width / 2), y]);
  				} else if (halign == "right") {
  					position.lines.push([Math.round(x - line.width), y]);
  				} else {
  					position.lines.push([Math.round(x), y]);
  				}
  				y += line.height;
  			}
  		};
  	}
  
  	$.plot.plugins.push({
  		init: init,
  		options: options,
  		name: "canvas",
  		version: "1.0"
  	});
  
  })(jQuery);
  
  /* Flot plugin for showing crosshairs when the mouse hovers over the plot.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  The plugin supports these options:
  
  	crosshair: {
  		mode: null or "x" or "y" or "xy"
  		color: color
  		lineWidth: number
  	}
  
  Set the mode to one of "x", "y" or "xy". The "x" mode enables a vertical
  crosshair that lets you trace the values on the x axis, "y" enables a
  horizontal crosshair and "xy" enables them both. "color" is the color of the
  crosshair (default is "rgba(170, 0, 0, 0.80)"), "lineWidth" is the width of
  the drawn lines (default is 1).
  
  The plugin also adds four public methods:
  
    - setCrosshair( pos )
  
      Set the position of the crosshair. Note that this is cleared if the user
      moves the mouse. "pos" is in coordinates of the plot and should be on the
      form { x: xpos, y: ypos } (you can use x2/x3/... if you're using multiple
      axes), which is coincidentally the same format as what you get from a
      "plothover" event. If "pos" is null, the crosshair is cleared.
  
    - clearCrosshair()
  
      Clear the crosshair.
  
    - lockCrosshair(pos)
  
      Cause the crosshair to lock to the current location, no longer updating if
      the user moves the mouse. Optionally supply a position (passed on to
      setCrosshair()) to move it to.
  
      Example usage:
  
  	var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
  	$("#graph").bind( "plothover", function ( evt, position, item ) {
  		if ( item ) {
  			// Lock the crosshair to the data point being hovered
  			myFlot.lockCrosshair({
  				x: item.datapoint[ 0 ],
  				y: item.datapoint[ 1 ]
  			});
  		} else {
  			// Return normal crosshair operation
  			myFlot.unlockCrosshair();
  		}
  	});
  
    - unlockCrosshair()
  
      Free the crosshair to move again after locking it.
  */
  
  (function ($) {
      var options = {
          crosshair: {
              mode: null, // one of null, "x", "y" or "xy",
              color: "rgba(170, 0, 0, 0.80)",
              lineWidth: 1
          }
      };
  
      function init(plot) {
          // position of crosshair in pixels
          var crosshair = { x: -1, y: -1, locked: false };
  
          plot.setCrosshair = function setCrosshair(pos) {
              if (!pos)
                  crosshair.x = -1;
              else {
                  var o = plot.p2c(pos);
                  crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
                  crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
              }
  
              plot.triggerRedrawOverlay();
          };
  
          plot.clearCrosshair = plot.setCrosshair; // passes null for pos
  
          plot.lockCrosshair = function lockCrosshair(pos) {
              if (pos)
                  plot.setCrosshair(pos);
              crosshair.locked = true;
          };
  
          plot.unlockCrosshair = function unlockCrosshair() {
              crosshair.locked = false;
          };
  
          function onMouseOut(e) {
              if (crosshair.locked)
                  return;
  
              if (crosshair.x != -1) {
                  crosshair.x = -1;
                  plot.triggerRedrawOverlay();
              }
          }
  
          function onMouseMove(e) {
              if (crosshair.locked)
                  return;
  
              if (plot.getSelection && plot.getSelection()) {
                  crosshair.x = -1; // hide the crosshair while selecting
                  return;
              }
  
              var offset = plot.offset();
              crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
              crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
              plot.triggerRedrawOverlay();
          }
  
          plot.hooks.bindEvents.push(function (plot, eventHolder) {
              if (!plot.getOptions().crosshair.mode)
                  return;
  
              eventHolder.mouseout(onMouseOut);
              eventHolder.mousemove(onMouseMove);
          });
  
          plot.hooks.drawOverlay.push(function (plot, ctx) {
              var c = plot.getOptions().crosshair;
              if (!c.mode)
                  return;
  
              var plotOffset = plot.getPlotOffset();
  
              ctx.save();
              ctx.translate(plotOffset.left, plotOffset.top);
  
              if (crosshair.x != -1) {
                  var adj = plot.getOptions().crosshair.lineWidth % 2 ? 0.5 : 0;
  
                  ctx.strokeStyle = c.color;
                  ctx.lineWidth = c.lineWidth;
                  ctx.lineJoin = "round";
  
                  ctx.beginPath();
                  if (c.mode.indexOf("x") != -1) {
                      var drawX = Math.floor(crosshair.x) + adj;
                      ctx.moveTo(drawX, 0);
                      ctx.lineTo(drawX, plot.height());
                  }
                  if (c.mode.indexOf("y") != -1) {
                      var drawY = Math.floor(crosshair.y) + adj;
                      ctx.moveTo(0, drawY);
                      ctx.lineTo(plot.width(), drawY);
                  }
                  ctx.stroke();
              }
              ctx.restore();
          });
  
          plot.hooks.shutdown.push(function (plot, eventHolder) {
              eventHolder.unbind("mouseout", onMouseOut);
              eventHolder.unbind("mousemove", onMouseMove);
          });
      }
  
      $.plot.plugins.push({
          init: init,
          options: options,
          name: 'crosshair',
          version: '1.0'
      });
  })(jQuery);
  
  /* Flot plugin for adding the ability to pan and zoom the plot.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  The default behaviour is double click and scrollwheel up/down to zoom in, drag
  to pan. The plugin defines plot.zoom({ center }), plot.zoomOut() and
  plot.pan( offset ) so you easily can add custom controls. It also fires
  "plotpan" and "plotzoom" events, useful for synchronizing plots.
  
  The plugin supports these options:
  
  	zoom: {
  		interactive: false
  		trigger: "dblclick" // or "click" for single click
  		amount: 1.5         // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
  	}
  
  	pan: {
  		interactive: false
  		cursor: "move"      // CSS mouse cursor value used when dragging, e.g. "pointer"
  		frameRate: 20
  	}
  
  	xaxis, yaxis, x2axis, y2axis: {
  		zoomRange: null  // or [ number, number ] (min range, max range) or false
  		panRange: null   // or [ number, number ] (min, max) or false
  	}
  
  "interactive" enables the built-in drag/click behaviour. If you enable
  interactive for pan, then you'll have a basic plot that supports moving
  around; the same for zoom.
  
  "amount" specifies the default amount to zoom in (so 1.5 = 150%) relative to
  the current viewport.
  
  "cursor" is a standard CSS mouse cursor string used for visual feedback to the
  user when dragging.
  
  "frameRate" specifies the maximum number of times per second the plot will
  update itself while the user is panning around on it (set to null to disable
  intermediate pans, the plot will then not update until the mouse button is
  released).
  
  "zoomRange" is the interval in which zooming can happen, e.g. with zoomRange:
  [1, 100] the zoom will never scale the axis so that the difference between min
  and max is smaller than 1 or larger than 100. You can set either end to null
  to ignore, e.g. [1, null]. If you set zoomRange to false, zooming on that axis
  will be disabled.
  
  "panRange" confines the panning to stay within a range, e.g. with panRange:
  [-10, 20] panning stops at -10 in one end and at 20 in the other. Either can
  be null, e.g. [-10, null]. If you set panRange to false, panning on that axis
  will be disabled.
  
  Example API usage:
  
  	plot = $.plot(...);
  
  	// zoom default amount in on the pixel ( 10, 20 )
  	plot.zoom({ center: { left: 10, top: 20 } });
  
  	// zoom out again
  	plot.zoomOut({ center: { left: 10, top: 20 } });
  
  	// zoom 200% in on the pixel (10, 20)
  	plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
  
  	// pan 100 pixels to the left and 20 down
  	plot.pan({ left: -100, top: 20 })
  
  Here, "center" specifies where the center of the zooming should happen. Note
  that this is defined in pixel space, not the space of the data points (you can
  use the p2c helpers on the axes in Flot to help you convert between these).
  
  "amount" is the amount to zoom the viewport relative to the current range, so
  1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out). You
  can set the default in the options.
  
  */
  
  // First two dependencies, jquery.event.drag.js and
  // jquery.mousewheel.js, we put them inline here to save people the
  // effort of downloading them.
  
  /*
  jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
  Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
  */
  (function(a){function e(h){var k,j=this,l=h.data||{};if(l.elem)j=h.dragTarget=l.elem,h.dragProxy=d.proxy||j,h.cursorOffsetX=l.pageX-l.left,h.cursorOffsetY=l.pageY-l.top,h.offsetX=h.pageX-h.cursorOffsetX,h.offsetY=h.pageY-h.cursorOffsetY;else if(d.dragging||l.which>0&&h.which!=l.which||a(h.target).is(l.not))return;switch(h.type){case"mousedown":return a.extend(l,a(j).offset(),{elem:j,target:h.target,pageX:h.pageX,pageY:h.pageY}),b.add(document,"mousemove mouseup",e,l),i(j,!1),d.dragging=null,!1;case!d.dragging&&"mousemove":if(g(h.pageX-l.pageX)+g(h.pageY-l.pageY)<l.distance)break;h.target=l.target,k=f(h,"dragstart",j),k!==!1&&(d.dragging=j,d.proxy=h.dragProxy=a(k||j)[0]);case"mousemove":if(d.dragging){if(k=f(h,"drag",j),c.drop&&(c.drop.allowed=k!==!1,c.drop.handler(h)),k!==!1)break;h.type="mouseup"}case"mouseup":b.remove(document,"mousemove mouseup",e),d.dragging&&(c.drop&&c.drop.handler(h),f(h,"dragend",j)),i(j,!0),d.dragging=d.proxy=l.elem=!1}return!0}function f(b,c,d){b.type=c;var e=a.event.dispatch.call(d,b);return e===!1?!1:e||b.result}function g(a){return Math.pow(a,2)}function h(){return d.dragging===!1}function i(a,b){a&&(a.unselectable=b?"off":"on",a.onselectstart=function(){return b},a.style&&(a.style.MozUserSelect=b?"":"none"))}a.fn.drag=function(a,b,c){return b&&this.bind("dragstart",a),c&&this.bind("dragend",c),a?this.bind("drag",b?b:a):this.trigger("drag")};var b=a.event,c=b.special,d=c.drag={not:":input",distance:0,which:1,dragging:!1,setup:function(c){c=a.extend({distance:d.distance,which:d.which,not:d.not},c||{}),c.distance=g(c.distance),b.add(this,"mousedown",e,c),this.attachEvent&&this.attachEvent("ondragstart",h)},teardown:function(){b.remove(this,"mousedown",e),this===d.dragging&&(d.dragging=d.proxy=!1),i(this,!0),this.detachEvent&&this.detachEvent("ondragstart",h)}};c.dragstart=c.dragend={setup:function(){},teardown:function(){}}})(jQuery);
  
  /* jquery.mousewheel.min.js
   * Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
   * Licensed under the MIT License (LICENSE.txt).
   * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
   * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
   * Thanks to: Seamus Leahy for adding deltaX and deltaY
   *
   * Version: 3.0.6
   *
   * Requires: 1.2.2+
   */
  (function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;void 0!==b.axis&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);void 0!==b.wheelDeltaY&&(g=b.wheelDeltaY/120);void 0!==b.wheelDeltaX&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,!1);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,!1);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
  
  
  
  
  (function ($) {
      var options = {
          xaxis: {
              zoomRange: null, // or [number, number] (min range, max range)
              panRange: null // or [number, number] (min, max)
          },
          zoom: {
              interactive: false,
              trigger: "dblclick", // or "click" for single click
              amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
          },
          pan: {
              interactive: false,
              cursor: "move",
              frameRate: 20
          }
      };
  
      function init(plot) {
          function onZoomClick(e, zoomOut) {
              var c = plot.offset();
              c.left = e.pageX - c.left;
              c.top = e.pageY - c.top;
              if (zoomOut)
                  plot.zoomOut({ center: c });
              else
                  plot.zoom({ center: c });
          }
  
          function onMouseWheel(e, delta) {
              e.preventDefault();
              onZoomClick(e, delta < 0);
              return false;
          }
  
          var prevCursor = 'default', prevPageX = 0, prevPageY = 0,
              panTimeout = null;
  
          function onDragStart(e) {
              if (e.which != 1)  // only accept left-click
                  return false;
              var c = plot.getPlaceholder().css('cursor');
              if (c)
                  prevCursor = c;
              plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
              prevPageX = e.pageX;
              prevPageY = e.pageY;
          }
  
          function onDrag(e) {
              var frameRate = plot.getOptions().pan.frameRate;
              if (panTimeout || !frameRate)
                  return;
  
              panTimeout = setTimeout(function () {
                  plot.pan({ left: prevPageX - e.pageX,
                             top: prevPageY - e.pageY });
                  prevPageX = e.pageX;
                  prevPageY = e.pageY;
  
                  panTimeout = null;
              }, 1 / frameRate * 1000);
          }
  
          function onDragEnd(e) {
              if (panTimeout) {
                  clearTimeout(panTimeout);
                  panTimeout = null;
              }
  
              plot.getPlaceholder().css('cursor', prevCursor);
              plot.pan({ left: prevPageX - e.pageX,
                         top: prevPageY - e.pageY });
          }
  
          function bindEvents(plot, eventHolder) {
              var o = plot.getOptions();
              if (o.zoom.interactive) {
                  eventHolder[o.zoom.trigger](onZoomClick);
                  eventHolder.mousewheel(onMouseWheel);
              }
  
              if (o.pan.interactive) {
                  eventHolder.bind("dragstart", { distance: 10 }, onDragStart);
                  eventHolder.bind("drag", onDrag);
                  eventHolder.bind("dragend", onDragEnd);
              }
          }
  
          plot.zoomOut = function (args) {
              if (!args)
                  args = {};
  
              if (!args.amount)
                  args.amount = plot.getOptions().zoom.amount;
  
              args.amount = 1 / args.amount;
              plot.zoom(args);
          };
  
          plot.zoom = function (args) {
              if (!args)
                  args = {};
  
              var c = args.center,
                  amount = args.amount || plot.getOptions().zoom.amount,
                  w = plot.width(), h = plot.height();
  
              if (!c)
                  c = { left: w / 2, top: h / 2 };
  
              var xf = c.left / w,
                  yf = c.top / h,
                  minmax = {
                      x: {
                          min: c.left - xf * w / amount,
                          max: c.left + (1 - xf) * w / amount
                      },
                      y: {
                          min: c.top - yf * h / amount,
                          max: c.top + (1 - yf) * h / amount
                      }
                  };
  
              $.each(plot.getAxes(), function(_, axis) {
                  var opts = axis.options,
                      min = minmax[axis.direction].min,
                      max = minmax[axis.direction].max,
                      zr = opts.zoomRange,
                      pr = opts.panRange;
  
                  if (zr === false) // no zooming on this axis
                      return;
  
                  min = axis.c2p(min);
                  max = axis.c2p(max);
                  if (min > max) {
                      // make sure min < max
                      var tmp = min;
                      min = max;
                      max = tmp;
                  }
  
                  //Check that we are in panRange
                  if (pr) {
                      if (pr[0] != null && min < pr[0]) {
                          min = pr[0];
                      }
                      if (pr[1] != null && max > pr[1]) {
                          max = pr[1];
                      }
                  }
  
                  var range = max - min;
                  if (zr &&
                      ((zr[0] != null && range < zr[0] && amount >1) ||
                       (zr[1] != null && range > zr[1] && amount <1)))
                      return;
  
                  opts.min = min;
                  opts.max = max;
              });
  
              plot.setupGrid();
              plot.draw();
  
              if (!args.preventEvent)
                  plot.getPlaceholder().trigger("plotzoom", [ plot, args ]);
          };
  
          plot.pan = function (args) {
              var delta = {
                  x: +args.left,
                  y: +args.top
              };
  
              if (isNaN(delta.x))
                  delta.x = 0;
              if (isNaN(delta.y))
                  delta.y = 0;
  
              $.each(plot.getAxes(), function (_, axis) {
                  var opts = axis.options,
                      min, max, d = delta[axis.direction];
  
                  min = axis.c2p(axis.p2c(axis.min) + d),
                  max = axis.c2p(axis.p2c(axis.max) + d);
  
                  var pr = opts.panRange;
                  if (pr === false) // no panning on this axis
                      return;
  
                  if (pr) {
                      // check whether we hit the wall
                      if (pr[0] != null && pr[0] > min) {
                          d = pr[0] - min;
                          min += d;
                          max += d;
                      }
  
                      if (pr[1] != null && pr[1] < max) {
                          d = pr[1] - max;
                          min += d;
                          max += d;
                      }
                  }
  
                  opts.min = min;
                  opts.max = max;
              });
  
              plot.setupGrid();
              plot.draw();
  
              if (!args.preventEvent)
                  plot.getPlaceholder().trigger("plotpan", [ plot, args ]);
          };
  
          function shutdown(plot, eventHolder) {
              eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick);
              eventHolder.unbind("mousewheel", onMouseWheel);
              eventHolder.unbind("dragstart", onDragStart);
              eventHolder.unbind("drag", onDrag);
              eventHolder.unbind("dragend", onDragEnd);
              if (panTimeout)
                  clearTimeout(panTimeout);
          }
  
          plot.hooks.bindEvents.push(bindEvents);
          plot.hooks.shutdown.push(shutdown);
      }
  
      $.plot.plugins.push({
          init: init,
          options: options,
          name: 'navigate',
          version: '1.3'
      });
  })(jQuery);
  
  /* Flot plugin for automatically redrawing plots as the placeholder resizes.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  It works by listening for changes on the placeholder div (through the jQuery
  resize event plugin) - if the size changes, it will redraw the plot.
  
  There are no options. If you need to disable the plugin for some plots, you
  can just fix the size of their placeholders.
  
  */
  
  /* Inline dependency:
   * jQuery resize event - v1.1 - 3/14/2010
   * http://benalman.com/projects/jquery-resize-plugin/
   *
   * Copyright (c) 2010 "Cowboy" Ben Alman
   * Dual licensed under the MIT and GPL licenses.
   * http://benalman.com/about/license/
   */
  (function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this);
  
  (function ($) {
      var options = { }; // no options
  
      function init(plot) {
          function onResize() {
              var placeholder = plot.getPlaceholder();
  
              // somebody might have hidden us and we can't plot
              // when we don't have the dimensions
              if (placeholder.width() == 0 || placeholder.height() == 0)
                  return;
  
              plot.resize();
              plot.setupGrid();
              plot.draw();
          }
  
          function bindEvents(plot, eventHolder) {
              plot.getPlaceholder().resize(onResize);
          }
  
          function shutdown(plot, eventHolder) {
              plot.getPlaceholder().unbind("resize", onResize);
          }
  
          plot.hooks.bindEvents.push(bindEvents);
          plot.hooks.shutdown.push(shutdown);
      }
  
      $.plot.plugins.push({
          init: init,
          options: options,
          name: 'resize',
          version: '1.0'
      });
  })(jQuery);
  
  /* Flot plugin for selecting regions of a plot.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  The plugin supports these options:
  
  selection: {
  	mode: null or "x" or "y" or "xy",
  	color: color,
  	shape: "round" or "miter" or "bevel",
  	minSize: number of pixels
  }
  
  Selection support is enabled by setting the mode to one of "x", "y" or "xy".
  In "x" mode, the user will only be able to specify the x range, similarly for
  "y" mode. For "xy", the selection becomes a rectangle where both ranges can be
  specified. "color" is color of the selection (if you need to change the color
  later on, you can get to it with plot.getOptions().selection.color). "shape"
  is the shape of the corners of the selection.
  
  "minSize" is the minimum size a selection can be in pixels. This value can
  be customized to determine the smallest size a selection can be and still
  have the selection rectangle be displayed. When customizing this value, the
  fact that it refers to pixels, not axis units must be taken into account.
  Thus, for example, if there is a bar graph in time mode with BarWidth set to 1
  minute, setting "minSize" to 1 will not make the minimum selection size 1
  minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent
  "plotunselected" events from being fired when the user clicks the mouse without
  dragging.
  
  When selection support is enabled, a "plotselected" event will be emitted on
  the DOM element you passed into the plot function. The event handler gets a
  parameter with the ranges selected on the axes, like this:
  
  	placeholder.bind( "plotselected", function( event, ranges ) {
  		alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
  		// similar for yaxis - with multiple axes, the extra ones are in
  		// x2axis, x3axis, ...
  	});
  
  The "plotselected" event is only fired when the user has finished making the
  selection. A "plotselecting" event is fired during the process with the same
  parameters as the "plotselected" event, in case you want to know what's
  happening while it's happening,
  
  A "plotunselected" event with no arguments is emitted when the user clicks the
  mouse to remove the selection. As stated above, setting "minSize" to 0 will
  destroy this behavior.
  
  The plugin allso adds the following methods to the plot object:
  
  - setSelection( ranges, preventEvent )
  
    Set the selection rectangle. The passed in ranges is on the same form as
    returned in the "plotselected" event. If the selection mode is "x", you
    should put in either an xaxis range, if the mode is "y" you need to put in
    an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
    this:
  
  	setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
  
    setSelection will trigger the "plotselected" event when called. If you don't
    want that to happen, e.g. if you're inside a "plotselected" handler, pass
    true as the second parameter. If you are using multiple axes, you can
    specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of
    xaxis, the plugin picks the first one it sees.
  
  - clearSelection( preventEvent )
  
    Clear the selection rectangle. Pass in true to avoid getting a
    "plotunselected" event.
  
  - getSelection()
  
    Returns the current selection in the same format as the "plotselected"
    event. If there's currently no selection, the function returns null.
  
  */
  
  (function ($) {
      function init(plot) {
          var selection = {
                  first: { x: -1, y: -1}, second: { x: -1, y: -1},
                  show: false,
                  active: false
              };
  
          // FIXME: The drag handling implemented here should be
          // abstracted out, there's some similar code from a library in
          // the navigation plugin, this should be massaged a bit to fit
          // the Flot cases here better and reused. Doing this would
          // make this plugin much slimmer.
          var savedhandlers = {};
  
          var mouseUpHandler = null;
  
          function onMouseMove(e) {
              if (selection.active) {
                  updateSelection(e);
  
                  plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
              }
          }
  
          function onMouseDown(e) {
              if (e.which != 1)  // only accept left-click
                  return;
  
              // cancel out any text selections
              document.body.focus();
  
              // prevent text selection and drag in old-school browsers
              if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
                  savedhandlers.onselectstart = document.onselectstart;
                  document.onselectstart = function () { return false; };
              }
              if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
                  savedhandlers.ondrag = document.ondrag;
                  document.ondrag = function () { return false; };
              }
  
              setSelectionPos(selection.first, e);
  
              selection.active = true;
  
              // this is a bit silly, but we have to use a closure to be
              // able to whack the same handler again
              mouseUpHandler = function (e) { onMouseUp(e); };
  
              $(document).one("mouseup", mouseUpHandler);
          }
  
          function onMouseUp(e) {
              mouseUpHandler = null;
  
              // revert drag stuff for old-school browsers
              if (document.onselectstart !== undefined)
                  document.onselectstart = savedhandlers.onselectstart;
              if (document.ondrag !== undefined)
                  document.ondrag = savedhandlers.ondrag;
  
              // no more dragging
              selection.active = false;
              updateSelection(e);
  
              if (selectionIsSane())
                  triggerSelectedEvent();
              else {
                  // this counts as a clear
                  plot.getPlaceholder().trigger("plotunselected", [ ]);
                  plot.getPlaceholder().trigger("plotselecting", [ null ]);
              }
  
              return false;
          }
  
          function getSelection() {
              if (!selectionIsSane())
                  return null;
  
              if (!selection.show) return null;
  
              var r = {}, c1 = selection.first, c2 = selection.second;
              $.each(plot.getAxes(), function (name, axis) {
                  if (axis.used) {
                      var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
                      r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
                  }
              });
              return r;
          }
  
          function triggerSelectedEvent() {
              var r = getSelection();
  
              plot.getPlaceholder().trigger("plotselected", [ r ]);
  
              // backwards-compat stuff, to be removed in future
              if (r.xaxis && r.yaxis)
                  plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
          }
  
          function clamp(min, value, max) {
              return value < min ? min: (value > max ? max: value);
          }
  
          function setSelectionPos(pos, e) {
              var o = plot.getOptions();
              var offset = plot.getPlaceholder().offset();
              var plotOffset = plot.getPlotOffset();
              pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
              pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
  
              if (o.selection.mode == "y")
                  pos.x = pos == selection.first ? 0 : plot.width();
  
              if (o.selection.mode == "x")
                  pos.y = pos == selection.first ? 0 : plot.height();
          }
  
          function updateSelection(pos) {
              if (pos.pageX == null)
                  return;
  
              setSelectionPos(selection.second, pos);
              if (selectionIsSane()) {
                  selection.show = true;
                  plot.triggerRedrawOverlay();
              }
              else
                  clearSelection(true);
          }
  
          function clearSelection(preventEvent) {
              if (selection.show) {
                  selection.show = false;
                  plot.triggerRedrawOverlay();
                  if (!preventEvent)
                      plot.getPlaceholder().trigger("plotunselected", [ ]);
              }
          }
  
          // function taken from markings support in Flot
          function extractRange(ranges, coord) {
              var axis, from, to, key, axes = plot.getAxes();
  
              for (var k in axes) {
                  axis = axes[k];
                  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" ? plot.getXAxes()[0] : plot.getYAxes()[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 setSelection(ranges, preventEvent) {
              var axis, range, o = plot.getOptions();
  
              if (o.selection.mode == "y") {
                  selection.first.x = 0;
                  selection.second.x = plot.width();
              }
              else {
                  range = extractRange(ranges, "x");
  
                  selection.first.x = range.axis.p2c(range.from);
                  selection.second.x = range.axis.p2c(range.to);
              }
  
              if (o.selection.mode == "x") {
                  selection.first.y = 0;
                  selection.second.y = plot.height();
              }
              else {
                  range = extractRange(ranges, "y");
  
                  selection.first.y = range.axis.p2c(range.from);
                  selection.second.y = range.axis.p2c(range.to);
              }
  
              selection.show = true;
              plot.triggerRedrawOverlay();
              if (!preventEvent && selectionIsSane())
                  triggerSelectedEvent();
          }
  
          function selectionIsSane() {
              var minSize = plot.getOptions().selection.minSize;
              return Math.abs(selection.second.x - selection.first.x) >= minSize &&
                  Math.abs(selection.second.y - selection.first.y) >= minSize;
          }
  
          plot.clearSelection = clearSelection;
          plot.setSelection = setSelection;
          plot.getSelection = getSelection;
  
          plot.hooks.bindEvents.push(function(plot, eventHolder) {
              var o = plot.getOptions();
              if (o.selection.mode != null) {
                  eventHolder.mousemove(onMouseMove);
                  eventHolder.mousedown(onMouseDown);
              }
          });
  
  
          plot.hooks.drawOverlay.push(function (plot, ctx) {
              // draw selection
              if (selection.show && selectionIsSane()) {
                  var plotOffset = plot.getPlotOffset();
                  var o = plot.getOptions();
  
                  ctx.save();
                  ctx.translate(plotOffset.left, plotOffset.top);
  
                  var c = $.color.parse(o.selection.color);
  
                  ctx.strokeStyle = c.scale('a', 0.8).toString();
                  ctx.lineWidth = 1;
                  ctx.lineJoin = o.selection.shape;
                  ctx.fillStyle = c.scale('a', 0.4).toString();
  
                  var x = Math.min(selection.first.x, selection.second.x) + 0.5,
                      y = Math.min(selection.first.y, selection.second.y) + 0.5,
                      w = Math.abs(selection.second.x - selection.first.x) - 1,
                      h = Math.abs(selection.second.y - selection.first.y) - 1;
  
                  ctx.fillRect(x, y, w, h);
                  ctx.strokeRect(x, y, w, h);
  
                  ctx.restore();
              }
          });
  
          plot.hooks.shutdown.push(function (plot, eventHolder) {
              eventHolder.unbind("mousemove", onMouseMove);
              eventHolder.unbind("mousedown", onMouseDown);
  
              if (mouseUpHandler)
                  $(document).unbind("mouseup", mouseUpHandler);
          });
  
      }
  
      $.plot.plugins.push({
          init: init,
          options: {
              selection: {
                  mode: null, // one of null, "x", "y" or "xy"
                  color: "#e8cfac",
                  shape: "round", // one of "round", "miter", or "bevel"
                  minSize: 5 // minimum number of pixels
              }
          },
          name: 'selection',
          version: '1.1'
      });
  })(jQuery);
  
  /* Pretty handling of time axes.
  
  Copyright (c) 2007-2014 IOLA and Ole Laursen.
  Licensed under the MIT license.
  
  Set axis.mode to "time" to enable. See the section "Time series data" in
  API.txt for details.
  
  */
  
  (function($) {
  
  	var options = {
  		xaxis: {
  			timezone: null,		// "browser" for local to the client or timezone for timezone-js
  			timeformat: null,	// format string to use
  			twelveHourClock: false,	// 12 or 24 time in time mode
  			monthNames: null	// list of names of months
  		}
  	};
  
  	// round to nearby lower multiple of base
  
  	function floorInBase(n, base) {
  		return base * Math.floor(n / base);
  	}
  
  	// Returns a string with the date d formatted according to fmt.
  	// A subset of the Open Group's strftime format is supported.
  
  	function formatDate(d, fmt, monthNames, dayNames) {
  
  		if (typeof d.strftime == "function") {
  			return d.strftime(fmt);
  		}
  
  		var leftPad = function(n, pad) {
  			n = "" + n;
  			pad = "" + (pad == null ? "0" : pad);
  			return n.length == 1 ? pad + n : n;
  		};
  
  		var r = [];
  		var escape = false;
  		var hours = d.getHours();
  		var isAM = hours < 12;
  
  		if (monthNames == null) {
  			monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  		}
  
  		if (dayNames == null) {
  			dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  		}
  
  		var hours12;
  
  		if (hours > 12) {
  			hours12 = hours - 12;
  		} else if (hours == 0) {
  			hours12 = 12;
  		} else {
  			hours12 = hours;
  		}
  
  		for (var i = 0; i < fmt.length; ++i) {
  
  			var c = fmt.charAt(i);
  
  			if (escape) {
  				switch (c) {
  					case 'a': c = "" + dayNames[d.getDay()]; break;
  					case 'b': c = "" + monthNames[d.getMonth()]; break;
  					case 'd': c = leftPad(d.getDate()); break;
  					case 'e': c = leftPad(d.getDate(), " "); break;
  					case 'h':	// For back-compat with 0.7; remove in 1.0
  					case 'H': c = leftPad(hours); break;
  					case 'I': c = leftPad(hours12); break;
  					case 'l': c = leftPad(hours12, " "); break;
  					case 'm': c = leftPad(d.getMonth() + 1); break;
  					case 'M': c = leftPad(d.getMinutes()); break;
  					// quarters not in Open Group's strftime specification
  					case 'q':
  						c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
  					case 'S': c = leftPad(d.getSeconds()); break;
  					case 'y': c = leftPad(d.getFullYear() % 100); break;
  					case 'Y': c = "" + d.getFullYear(); break;
  					case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
  					case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
  					case 'w': c = "" + d.getDay(); break;
  				}
  				r.push(c);
  				escape = false;
  			} else {
  				if (c == "%") {
  					escape = true;
  				} else {
  					r.push(c);
  				}
  			}
  		}
  
  		return r.join("");
  	}
  
  	// To have a consistent view of time-based data independent of which time
  	// zone the client happens to be in we need a date-like object independent
  	// of time zones.  This is done through a wrapper that only calls the UTC
  	// versions of the accessor methods.
  
  	function makeUtcWrapper(d) {
  
  		function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
  			sourceObj[sourceMethod] = function() {
  				return targetObj[targetMethod].apply(targetObj, arguments);
  			};
  		};
  
  		var utc = {
  			date: d
  		};
  
  		// support strftime, if found
  
  		if (d.strftime != undefined) {
  			addProxyMethod(utc, "strftime", d, "strftime");
  		}
  
  		addProxyMethod(utc, "getTime", d, "getTime");
  		addProxyMethod(utc, "setTime", d, "setTime");
  
  		var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
  
  		for (var p = 0; p < props.length; p++) {
  			addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
  			addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
  		}
  
  		return utc;
  	};
  
  	// select time zone strategy.  This returns a date-like object tied to the
  	// desired timezone
  
  	function dateGenerator(ts, opts) {
  		if (opts.timezone == "browser") {
  			return new Date(ts);
  		} else if (!opts.timezone || opts.timezone == "utc") {
  			return makeUtcWrapper(new Date(ts));
  		} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
  			var d = new timezoneJS.Date();
  			// timezone-js is fickle, so be sure to set the time zone before
  			// setting the time.
  			d.setTimezone(opts.timezone);
  			d.setTime(ts);
  			return d;
  		} else {
  			return makeUtcWrapper(new Date(ts));
  		}
  	}
  
  	// 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,
  		"quarter": 3 * 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 baseSpec = [
  		[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"]
  	];
  
  	// we don't know which variant(s) we'll need yet, but generating both is
  	// cheap
  
  	var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
  		[1, "year"]]);
  	var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
  		[1, "year"]]);
  
  	function init(plot) {
  		plot.hooks.processOptions.push(function (plot, options) {
  			$.each(plot.getAxes(), function(axisName, axis) {
  
  				var opts = axis.options;
  
  				if (opts.mode == "time") {
  					axis.tickGenerator = function(axis) {
  
  						var ticks = [];
  						var d = dateGenerator(axis.min, opts);
  						var minSize = 0;
  
  						// make quarter use a possibility if quarters are
  						// mentioned in either of these options
  
  						var spec = (opts.tickSize && opts.tickSize[1] ===
  							"quarter") ||
  							(opts.minTickSize && opts.minTickSize[1] ===
  							"quarter") ? specQuarters : specMonths;
  
  						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 (axis.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;
  							}
  						}
  
  						var size = spec[i][0];
  						var unit = spec[i][1];
  
  						// special-case the possibility of several years
  
  						if (unit == "year") {
  
  							// if given a minTickSize in years, just use it,
  							// ensuring that it's an integer
  
  							if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
  								size = Math.floor(opts.minTickSize[0]);
  							} else {
  
  								var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
  								var norm = (axis.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;
  							}
  
  							// minimum size for years is 1
  
  							if (size < 1) {
  								size = 1;
  							}
  						}
  
  						axis.tickSize = opts.tickSize || [size, unit];
  						var tickSize = axis.tickSize[0];
  						unit = axis.tickSize[1];
  
  						var step = tickSize * timeUnitSize[unit];
  
  						if (unit == "second") {
  							d.setSeconds(floorInBase(d.getSeconds(), tickSize));
  						} else if (unit == "minute") {
  							d.setMinutes(floorInBase(d.getMinutes(), tickSize));
  						} else if (unit == "hour") {
  							d.setHours(floorInBase(d.getHours(), tickSize));
  						} else if (unit == "month") {
  							d.setMonth(floorInBase(d.getMonth(), tickSize));
  						} else if (unit == "quarter") {
  							d.setMonth(3 * floorInBase(d.getMonth() / 3,
  								tickSize));
  						} else if (unit == "year") {
  							d.setFullYear(floorInBase(d.getFullYear(), tickSize));
  						}
  
  						// reset smaller components
  
  						d.setMilliseconds(0);
  
  						if (step >= timeUnitSize.minute) {
  							d.setSeconds(0);
  						}
  						if (step >= timeUnitSize.hour) {
  							d.setMinutes(0);
  						}
  						if (step >= timeUnitSize.day) {
  							d.setHours(0);
  						}
  						if (step >= timeUnitSize.day * 4) {
  							d.setDate(1);
  						}
  						if (step >= timeUnitSize.month * 2) {
  							d.setMonth(floorInBase(d.getMonth(), 3));
  						}
  						if (step >= timeUnitSize.quarter * 2) {
  							d.setMonth(floorInBase(d.getMonth(), 6));
  						}
  						if (step >= timeUnitSize.year) {
  							d.setMonth(0);
  						}
  
  						var carry = 0;
  						var v = Number.NaN;
  						var prev;
  
  						do {
  
  							prev = v;
  							v = d.getTime();
  							ticks.push(v);
  
  							if (unit == "month" || unit == "quarter") {
  								if (tickSize < 1) {
  
  									// a bit complicated - we'll divide the
  									// month/quarter up but we need to take
  									// care of fractions so we don't end up in
  									// the middle of a day
  
  									d.setDate(1);
  									var start = d.getTime();
  									d.setMonth(d.getMonth() +
  										(unit == "quarter" ? 3 : 1));
  									var end = d.getTime();
  									d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
  									carry = d.getHours();
  									d.setHours(0);
  								} else {
  									d.setMonth(d.getMonth() +
  										tickSize * (unit == "quarter" ? 3 : 1));
  								}
  							} else if (unit == "year") {
  								d.setFullYear(d.getFullYear() + tickSize);
  							} else {
  								d.setTime(v + step);
  							}
  						} while (v < axis.max && v != prev);
  
  						return ticks;
  					};
  
  					axis.tickFormatter = function (v, axis) {
  
  						var d = dateGenerator(v, axis.options);
  
  						// first check global format
  
  						if (opts.timeformat != null) {
  							return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
  						}
  
  						// possibly use quarters if quarters are mentioned in
  						// any of these places
  
  						var useQuarters = (axis.options.tickSize &&
  								axis.options.tickSize[1] == "quarter") ||
  							(axis.options.minTickSize &&
  								axis.options.minTickSize[1] == "quarter");
  
  						var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
  						var span = axis.max - axis.min;
  						var suffix = (opts.twelveHourClock) ? " %p" : "";
  						var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
  						var fmt;
  
  						if (t < timeUnitSize.minute) {
  							fmt = hourCode + ":%M:%S" + suffix;
  						} else if (t < timeUnitSize.day) {
  							if (span < 2 * timeUnitSize.day) {
  								fmt = hourCode + ":%M" + suffix;
  							} else {
  								fmt = "%b %d " + hourCode + ":%M" + suffix;
  							}
  						} else if (t < timeUnitSize.month) {
  							fmt = "%b %d";
  						} else if ((useQuarters && t < timeUnitSize.quarter) ||
  							(!useQuarters && t < timeUnitSize.year)) {
  							if (span < timeUnitSize.year) {
  								fmt = "%b";
  							} else {
  								fmt = "%b %Y";
  							}
  						} else if (useQuarters && t < timeUnitSize.year) {
  							if (span < timeUnitSize.year) {
  								fmt = "Q%q";
  							} else {
  								fmt = "Q%q %Y";
  							}
  						} else {
  							fmt = "%Y";
  						}
  
  						var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
  
  						return rt;
  					};
  				}
  			});
  		});
  	}
  
  	$.plot.plugins.push({
  		init: init,
  		options: options,
  		name: 'time',
  		version: '1.0'
  	});
  
  	// Time-axis support used to be in Flot core, which exposed the
  	// formatDate function on the plot object.  Various plugins depend
  	// on the function, so we need to re-expose it here.
  
  	$.plot.formatDate = formatDate;
  	$.plot.dateGenerator = dateGenerator;
  
  })(jQuery);
  
  function dd() {
      if ( ! app.debug )
          return;
  
      console.log( arguments );
  }
  
  sidebarSearch = function( value, items, select, container ) {
      dd('sidebarSearch');
  
      var _items,
          $list = $(container);
      dd('sidebarSearch.hide.complete');
  
      if (value !== '')
      {
          $('.group .group-heading', $list).hide();
  
          $( 'li[' + select +']' , $list).addClass('hidden');
          $( 'tr[' + select +']' , $list).addClass('hidden');
  
          _items = items.filter( function(item) {
              return (item.searchValue.indexOf( value ) >= 0);
          });
  
          $.each( _items, function(index, item) {
              $( 'li[' + select +'="'+ item.id() + '"]' , $list).removeClass('hidden');
              $( 'tr[' + select +'="'+ item.id() + '"]' , $list).removeClass('hidden');
          });
  
      } else {
          $( 'li[' + select +']' , $list).removeClass('hidden');
          $( 'tr[' + select +']' , $list).removeClass('hidden');
      }
  
      $('.group', $list).each(function(){
          var $group = $(this);
  
          if ( $('.group-list li[' + select +']:not(.hidden)', $group).length ) {
              $('.group-heading', $group).show();
  
              $('.collapse', $group).collapse('show');
          }
  
      });
  };
  
  function handlerFail(jqXHR, textStatus, errorThrown) {
      dd(jqXHR, textStatus, errorThrown);
  
      if (jqXHR.status == 401) {
          //return window.location.reload();
      }
  
      if (jqXHR.status == 503) {
          //return window.location.reload();
      }
  
  }
  
  function fetchFromObject(obj, prop) {
  
      if(typeof obj === 'undefined') {
          return false;
      }
  
      var _index = prop.indexOf('.');
  
      if(_index > -1) {
          return fetchFromObject(obj[prop.substring(0, _index)], prop.substr(_index + 1));
      }
  
      return obj[prop];
  }
  
  function dialogMoveToTop(el, check) {
      var elz = parseInt(el.css('z-index'));
      var index = parseInt(el.css('z-index'));
      $.each($('.ui-dialog.ui-widget.ui-widget-content'), function( key, value ) {
          if (index < parseInt($(this).css('z-index'))) {
              index = parseInt($(this).css('z-index'));
          }
      });
  
      if ((elz < index && typeof check === 'undefined') || typeof check !== 'undefined' ) {
          el.css('z-index', index + 2);
      }
  }
  
  function convertHex(hex,opacity){
      hex = hex.replace('#','');
      r = parseInt(hex.substring(0,2), 16);
      g = parseInt(hex.substring(2,4), 16);
      b = parseInt(hex.substring(4,6), 16);
      result = 'rgba('+r+','+g+','+b+','+opacity/100+')';
  
      return result;
  }
  
  function degToLatLng(deg) {
      var arr = deg.split(':');
  
      var d = parseFloat(arr[0]);
      var m = parseInt(arr[1]);
      var s = parseFloat(arr[2]);
  
      var v = (Math.abs(d) + (m / 60) + (s / 3600));
      if (d < 0.0) v = 0.0 - v;
  
      return v.toFixed(6);
  }
  
  function placesRouteLatLngsToPointsString(a) {
      if (a.length > 0) {
          var d = [];
          for (var c = 0; c < a.length; c++) {
              var f = a[c];
              var e = f.lat;
              var b = f.lng;
              d.push({lat: parseFloat(e).toFixed(6), lng: parseFloat(b).toFixed(6)});
          }
          return JSON.stringify(d);
      }
  
      return '';
  }
  
  function isNumeric(n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
  }
  
  var DateDiff = {
  
      inDays: function(d1, d2) {
          var t2 = d2.getTime();
          var t1 = d1.getTime();
  
          return parseInt((t2-t1)/(24*3600*1000));
      },
  
      inWeeks: function(d1, d2) {
          var t2 = d2.getTime();
          var t1 = d1.getTime();
  
          return parseInt((t2-t1)/(24*3600*1000*7));
      },
  
      inMonths: function(d1, d2) {
          var d1Y = d1.getFullYear();
          var d2Y = d2.getFullYear();
          var d1M = d1.getMonth();
          var d2M = d2.getMonth();
  
          return (d2M+12*d2Y)-(d1M+12*d1Y);
      },
  
      inYears: function(d1, d2) {
          return d2.getFullYear()-d1.getFullYear();
      }
  };
  
  function momentCalendar(val, parent) {
      var date_from = $(parent).find('input[name="date_from"]');
      var date_to = $(parent).find('input[name="date_to"]');
      var format = 'YYYY-MM-DD';
  
      switch (val) {
          case "0":
              date_from.val(moment().minute(0).hour(0).format(format));
              date_to.val(moment().minute(0).hour(0).format(format));
              break;
          case "1":
              date_from.val(moment().minute(0).hour(0).format(format));
              date_to.val(moment().add(1, "days").minute(0).hour(0).format(format));
              break;
          case "2":
              date_from.val(moment().subtract(1, "days").minute(0).hour(0).format(format));
              date_to.val(moment().minute(0).hour(0).format(format));
              break;
          case "3":
              date_from.val(moment().subtract(2, "days").minute(0).hour(0).format(format));
              date_to.val(moment().subtract(1, "days").minute(0).hour(0).format(format));
              break;
          case "4":
              date_from.val(moment().subtract(3, "days").minute(0).hour(0).format(format));
              date_to.val(moment().subtract(2, "days").minute(0).hour(0).format(format));
              break;
          case "5":
              date_from.val(moment().day("Monday").minute(0).hour(0).format(format));
              date_to.val(moment().add(1, "days").minute(0).hour(0).format(format));
              break;
          case "6":
              date_from.val(moment().day("Monday").subtract(1, "week").minute(0).hour(0).format(format));
              date_to.val(moment().day("Monday").minute(0).hour(0).format(format));
              break;
          case "7":
              date_from.val(moment().startOf("month").minute(0).hour(0).format(format));
              date_to.val(moment().add(1, "days").minute(0).hour(0).format(format));
              break;
          case "8":
              date_from.val(moment().startOf("month").subtract(1, "month").minute(0).hour(0).format(format));
              date_to.val(moment().startOf("month").minute(0).hour(0).format(format));
              break;
          case "9":
              date_from.val(moment().startOf("month").subtract(3, "month").minute(0).hour(0).format(format));
              date_to.val(moment().startOf("month").minute(0).hour(0).format(format));
              break;
      }
  }
  
  function secondsToTime(_seconds)
  {
      var
          hours               = Math.floor(_seconds / (60 * 60)),
          divisor_for_minutes = _seconds % (60 * 60),
          minutes             = Math.floor(divisor_for_minutes / 60),
          divisor_for_seconds = divisor_for_minutes % 60,
          seconds             = Math.ceil(divisor_for_seconds);
  
      if (hours < 0 || minutes < 0 || seconds < 0)
          return '0s';
  
      return (hours ? hours+"h " : '')+(minutes ? minutes+"min " : '')+seconds+"s";
  }
  
  function checkPerm(el) {
      if (el.hasClass('perm_edit') || el.hasClass('perm_remove')) {
          var parent = el.closest('tr');
          var view = parent.find('.perm_view');
          var edit = parent.find('.perm_edit').prop('checked');
          var remove = parent.find('.perm_remove').prop('checked');
  
          if (edit || remove) {
              if (!view.prop('checked'))
                  view.trigger('click');
  
              view.prop('disabled', true).closest('div').addClass('disabled');
          }
          else {
              view.prop('disabled', false).closest('div').removeClass('disabled');
          }
      }
  }
  
  function checkPerms() {
      $.each($('.perm_edit, .perm_remove'), function (key, value) {
          checkPerm($(this));
      });
  }
  
  function readImage(input, target) {
      if (input.files && input.files[0]) {
          var reader = new FileReader();
  
          reader.onload = function (e) {
              $(target).attr('src', e.target.result);
          };
  
          reader.readAsDataURL(input.files[0]);
      }
  }
  $.fn.outerHTML = function(){
  
      // IE, Chrome & Safari will comply with the non-standard outerHTML, all others (FF) will have a fall-back for cloning
      return (!this.length) ? this : (this[0].outerHTML || (
          function(el){
              var div = document.createElement('div');
              div.appendChild(el.cloneNode(true));
              var contents = div.innerHTML;
              div = null;
              return contents;
          })(this[0]));
  
  };
  (function( $ ) {
      "use strict";
      $.databox = function( element, options ) {
  
          var
              plugin = this,
              $element = $( element );
  
          var settings = $.extend({
              onBeforeLoad: function(){},
              onAfterLoad: function(){},
              onComplete: function(){},
              onError: function(){}
          }, options );
  
          plugin.init = function () {
              dd( 'databox.init' );
  
              plugin.url = $element.attr( 'data-url' );
              plugin.box = $( $element.attr( 'data-target' ) );
  
              _events();
          };
  
          var _events = function() {
              $element.on('click', function (e) {
                  dd( 'databox.click' );
                  plugin.load();
              });
          };
  
          plugin.beforeLoad = function() {
              settings.onBeforeLoad( plugin, plugin.box );
          };
  
          plugin.afterLoad = function() {
              settings.onAfterLoad( plugin, plugin.box );
          };
  
          plugin.complete = function() {
              settings.onComplete( plugin, plugin.box );
          };
  
          plugin.setContent = function( html ) {
              plugin.box.html( html );
          };
  
          plugin.load = function( url ) {
              if ( typeof url == "undefined" )
                  url = plugin.url;
  
              dd( 'databox.load: ' + url );
  
              $.ajax({
                  url: url,
                  success: function( html ){
                      plugin.setContent( html );
  
                      plugin.afterLoad();
                  },
                  beforeSend: function(){
                      plugin.beforeLoad();
                  },
                  complete: function(){
                      plugin.complete();
                  },
                  error: function (request, status, error) {
                      plugin.onError(request, status, error);
                  }
              });
          };
  
          plugin.reload = function() {
              plugin.load( plugin.url );
          };
  
          //Auto initialize
          plugin.init();
  
      };
      $.fn.databox = function( options ) {
  
          return this.each(function() {
  
              if ( undefined === $( this ).data( 'databox' ) ) {
  
                  var plugin = new $.databox( this, options );
                  $( this ).data( 'databox', plugin );
              }
          });
      };
  })( jQuery );
  
  var loader = {
      template: '<div class="loading"><div class="backdrop"></div><div class="outter"><div class="middle"><div class="inner"><i class="loader"></i></div></div></div></div>',
      add: function($container) {
          dd( 'loader.add', $container );
  
          if ( $('.loading', $container).length )
              return;
  
          $container.css('position', 'relative');
          $container.append(loader.template);
      },
      remove: function($container) {
          dd( 'loader.remove', $container );
          $('.loading', $container).remove();
      }
  };
  $(document).ready(function() {
      $(document).on('hidden', '.modal', function(){
          // Todo
      });
  
      // Open on click
      $(document).on('click', '[data-modal]', function(){
          var data = $(this).data(),
              method = (typeof data.method == 'undefined' ? 'GET' : data.method),
              modal = $modal.initModal(data.modal);
  
          $modal.getModalContent(data, method, modal);
      });
  
      $(document).on('click', '[data-submit="modal"],.modal .update:visible, .modal .update_hidden', function(){
          var element = $(this);
          var modal = element.closest('.modal');
          var form = modal.find('form');
          var url = form.attr('action');
          var method = form.find('input[name="_method"]').val();
          var data = form.serializeArray();
  
          method = (typeof method != 'undefined' ? method : 'POST');
  
          $modal.postData(url, method, modal, data);
      });
  
      $(document).on('click', '.modal .update_with_files:visible', function(){
          var element = $(this);
          var modal = element.closest('.modal');
          var form = modal.find('form');
          var url = form.attr('action');
          var method = form.find('input[name="_method"]').val();
          var data = new FormData(form['0']);
  
          method = (typeof method != 'undefined' ? method : 'POST');
  
          $modal.postData(url, method, modal, data, true);
      });
  });
  
  var $modal = {
      initModal: function(modal) {
          var element = $('#' + modal);
          if (!element.length) {
              $('body').append('<div class="modal fade" id="' + modal + '"><div class="contents"></div></div>');
              element = $('#' + modal);
          }
  
          return element;
      },
      getModalContent: function(data, method, modal) {
          $.ajax({
              type: method,
              dataType: "html",
              url: data.url,
              data: {
                  id: data.id
              },
              beforeSend: function() {
                  loader.add( $('body') );
              },
              success: function(res){
                  modal.find('.contents').html(res);
                  modal.modal('show');
  
                  initComponents( modal );
              },
              complete: function() {
                  loader.remove( $('body') );
              }
          });
      },
      postData: function(url, method, modal, data, with_files) {
          if (method == 'PUT' || method == 'DELETE')
              method = 'POST';
  
          var modal_content = modal.find('.modal-content');
  
          var ajax = {
              type: method,
              dataType: "json",
              url: url + '?_=' + $.now(),
              data: data,
              beforeSend: function() {
                  modal.find('.help-block.error').remove();
                  modal.find('.has-error').removeClass('has-error');
  
                  loader.add( modal_content );
              },
              success: function(res){
              	console.log(res);
              	console.log(res.status);
                  if (res.status != 0) {
                      if (res.status == 1)
                          modal.modal('hide');
  
                      $modal.initCallback(res, modal.attr('id'));
                  }
  
                  loader.remove( modal_content );
  
                  if (res.trigger) {
                      $(document).trigger(res.trigger, res);
                  }
                  if (typeof res.errors != 'undefined') {
                      $modal.parseErrors(res.errors, modal);
                  }
              },
              complete: function() {
                  loader.remove( modal_content );
              },
              fail: function(jqXHR, textStatus, errorThrown) {
                  handlerFail(jqXHR, textStatus, errorThrown);
              }
          };
  
          if (typeof with_files != 'undefined') {
              $.extend(ajax, {
                  processData: false,
                  contentType: false
              });
          }
  
          $.ajax(ajax);
      },
      parseErrors: function(errors, modal) {
          $modal.defaultParseErrors(errors, modal);
      },
      defaultParseErrors: function(errors, modal) {
          $.each( errors, function( key, value ) {
  
              var name = key,
                  parts = key.split('.');
  
              if (parts.length > 1)
                  name = parts.shift()+ '[' + parts.join('][') + ']';
  
              dd('error field', name);
  
              var error_block = '<span class="help-block error input_error_' + name + '">' + value + '</span>',
                  el = modal.find('input[name="' + name + '"]:not([type="radio"]), select[name="' + name + '"], select[name="' + name + '[]"], textarea[name="' + name + '"], input[name="' + name + '_fake"]:not([type="radio"]), select[name="' + name + '_fake"], textarea[name="' + name + '_fake"]');
  
              if (el.is(':visible') && el.attr('type') != 'hidden') {
                  el.after(error_block);
                  el.closest('.form-group').addClass('has-error');
              } else {
                  el.closest('.form-group').append(error_block).addClass('has-error');
              }
  
              var tab = el.closest('.tab-pane').attr('id');
              if (typeof tab != 'undefined') {
                  modal.find('a[href="#' + tab + '"]').addClass('has-error');
              }
          });
          if (modal.find('.help-block.error').length > 0) {
              var fromTop = modal.find('.help-block.error').first().position().top;
              if (fromTop == 0)
                  fromTop = modal.find('.help-block.error').first().offsetParent().position().top;
          }
      },
      initCallback: function(res, id) {
          var fnc = id.replace('-','_') + '_modal_callback';
          var callback_fnc = window[fnc];
  
          if (typeof callback_fnc == 'function') {
              callback_fnc(res);
          }
      }
  }
  
  $.ajaxSetup({ cache: false });
  
  var tables = {
      loader: '',
      config: {},
      items_arr : {},
  
      getFilters: function(table) {
          var $tableContainer = $("#" + table),
              $filters = $('[data-filter]', $tableContainer),
              filter = {};
  
          if ($filters.length){
  
              $filters.each(function( index ) {
                  var type = $(this).attr('type');
  
                  switch (type) {
                      case 'checkbox':
                      case 'radio':
                          if (!$(this).is(':checked'))
                              return true;
                          break;
                      default:
                          break;
                  }
  
                  filter[$(this).attr('name')] = $(this).val();
              });
          }
  
          return filter;
      },
  
      get: function (table, url){
          var config = tables.config[table];
          if (typeof config == 'undefined') {
              alert('"' + table + '" configs is not defined!');
          }
  
          if (typeof url == 'undefined') {
              url = config.url;
          }
  
          var $tableContainer = $("#" + table),
              filter = {};
  
          filter = tables.getFilters(table);
  
          $.ajax({
              type: "GET",
              dataType: "html",
              url: url,
              cache: false,
              data: filter,
              beforeSend: function() {
                  loader.add($tableContainer);
              },
              success: function(res) {
                  $table = $('[data-table]', $tableContainer);
                  $table.html(res);
  
                  tables.check_checkboxes(table);
  
                  initComponents( $table );
              },
              complete: function() {
                  loader.remove($tableContainer);
              },
              error: function(jqXHR, textStatus, errorThrown) {
                  dd('table.get.fail', jqXHR);
                  handlerFail(jqXHR, textStatus, errorThrown);
              }
          });
      },
  
      set_config: function(table, configs) {
          dd( 'tables.set_config' );
  
          if (typeof tables.config[table] == 'undefined') {
              tables.config[table] = configs;
          }
          else {
              for (var key in configs) {
                  if (configs.hasOwnProperty(key))
                      tables.config[table][key] = configs[key]
              }
          }
  
          tables.events(table);
      },
      check_checkboxes : function(table) {
          if (typeof tables.items_arr[table] == 'undefined') {
              tables.items_arr[table] = {};
          }
          $("#" + table + " input:checkbox").not(":disabled").each(function() {
              var id = $(this).val();
              if (id && id != 'on') {
                  if (id in tables.items_arr[table]) {
                      if (!$(this).is(":checked")) {
                          $(this).prop("checked", true);
                      }
                  }
                  else {
                      if ($(this).is(":checked")) {
                          $(this).prop("checked", false);
                      }
                  }
              }
          });
      },
      events: function(table) {
          dd( 'tables.events' );
          var $tableContainer = $("#" + table),
              $filters = $('[data-filter]', $tableContainer);
  
          $tableContainer.off('keyup', '[data-filter]');
          $tableContainer.on('keyup', '[data-filter]', $.debounce(500, function () {
              tables.get(table);
          }));
  
          $tableContainer.off('click', '.pagination a');
          $tableContainer.on('click', '.pagination a', function (e) {
              e.preventDefault();
  
              if ( $(this).attr('href') == '#' || $(this).hasClass('disabled') || $(this).hasClass('active'))
                  return;
  
              $tableContainer.animate({ scrollTop: 0 }, "fast");
              tables.get(table, $(this).attr('href'));
          });
  
          $tableContainer.off('click', 'table th:not(.sorting_disabled)');
          $tableContainer.on('click', 'table th:not(.sorting_disabled)' ,function(){
              var sort = 'desc';
              var table = $(this).closest('table');
              if ($(this).hasClass("sorting_asc") || $(this).hasClass("sorting_desc")) {
                  if ($(this).hasClass("sorting_desc")) {
                      $(this).removeClass('sorting_desc').addClass('sorting_asc');
                      sort = 'asc';
                  }
                  else {
                      $(this).removeClass('sorting_asc').addClass('sorting_desc');
                      sort = 'desc';
                  }
              }
              else {
                  $(this).removeClass('sorting_desc').addClass('sorting_asc');
                  sort = 'asc';
              }
              $tableContainer.find('input[name="sorting[sort_by]"]').val($(this).attr("data-id"));
              $tableContainer.find('input[name="sorting[sort]"]').val(sort);
              $tableContainer
                  .find('th:not(.sorting_disabled)')
                  .not(this).removeClass('sorting_asc')
                  .removeClass('sorting_desc')
                  .addClass('sorting');
              tables.get($tableContainer.attr('id'));
          });
  
          $tableContainer.off('change', 'input[type="checkbox"]');
          $tableContainer.on('change', 'input[type="checkbox"]', function () {
              var table = $tableContainer.attr('id'),
                  id = $(this).val(),
                  check = $(this).is(':checked');
  
              if (typeof tables.items_arr[table] == 'undefined') {
                  tables.items_arr[table] = {};
              }
  
              if ( id && id != 'on' ) {
                  if ( check ) {
                      tables.items_arr[table][id] = id;
                  } else {
                      if (id in tables.items_arr[table]) {
                          delete(tables.items_arr[table][id]);
                      }
                  }
              }
          });
  
          $tableContainer.off('multichanged');
          $tableContainer.on('multichanged', function(e, data){
              dd( '$tableContainer.multichanged', data );
              $.each( data.items, function() {
                  $( this ).trigger('change');
              });
          });
  
          $tableContainer.off('click', '[data-multi]');
          $tableContainer.on('click', '[data-multi]', function () {
              var table = $tableContainer.attr('id'),
                  config = tables.config[table],
                  action = $(this).attr('data-multi');
  
              if (typeof config == 'undefined') {
                  alert('"' + table + '" configs is not defined!');
              }
              if (typeof tables.config[table][action] == 'undefined') {
                  alert('"' + table + '" configs "'+action+'" is not defined!');
              }
  
              var data = {};
  
              data = tables.getFilters(table);
              data.id = tables.items_arr[table];
              data._method = 'DELETE';
              $.ajax({
                  type: "POST",
                  dataType: "json",
                  url: tables.config[table][action],
                  data: data,
                  beforeSend: function() {
                      $tableContainer.find('.table_error').html('');
                  },
                  success: function(res){
                      dd( res );
                      if (typeof res.error != 'undefined') {
                          $tableContainer.find('.table_error').html('<div class="alert alert-danger" style="margin-top: 20px;">' + res.error + '</div>');
                      }
                      tables.items_arr[table] = {};
                      tables.get(table);
                      if (res.trigger) {
                          $(document).trigger(res.trigger, res);
                      }
                  },
                  error: function(jqXHR, textStatus, errorThrown) {
                      handlerFail(jqXHR, textStatus, errorThrown);
                  }
              });
          });
  
          $tableContainer.off('click', 'td[data-editable-field]');
          $tableContainer.on('click', 'td[data-editable-field]', function () {
              var
                  $td = $(this),
                  orginValue = $td.html(),
                  field = $td.data('editable-field');
  
              //checking if form already build
              if ($td.find('.input-group').length)
                  return;
  
              var $form = $('<div class="input-group input-group-sm">' +
                  '      <input type="text" class="form-control" value="'+orginValue+'">' +
                  '      <i class="input-group-btn">' +
                  '        <button class="btn btn-primary" type="button"><i class="icon check"></i> </button>' +
                  '      </span>' +
                  '    </div>');
  
              var inlineSubmit = function () {
                  var formData = {};
                  formData[field] = $form.find("input").val();
                  $.ajax({
                      type: "POST",
                      url: $td.data('submit-url'),
                      data: formData,
                      dataType: "json",
                      beforeSend: function() {
                          $tableContainer.find('.table_error').html('');
                      },
                      success: function(res){
                          $td.html(formData[field]);
                          $form.find('button').off('click');
                      },
                      error: function(jqXHR, textStatus, errorThrown) {
                          handlerFail(jqXHR, textStatus, errorThrown);
                      }
                  });
              };
  
              $td.html( $form );
              $form.find("input").focus();
  
              $(document).mouseup(function(e)
              {
                  if ( ! $td.find($form).length )
                      return;
  
                  if ( ! $td.is(e.target) && $td.has(e.target).length === 0)
                  {
                      $td.html( orginValue );
                  }
              });
  
              $form.find('button').on('click', function () {
                  inlineSubmit();
              });
              $form.find('input').keydown(function (e) {
                  if (e.keyCode != 13)
                      return;
  
                  inlineSubmit();
              });
          });
  
      }
  };
  
  $(document).ready(function(){
  
      $(document).on('click', '.js-confirm-link', function(e){
          var url = $(this).attr('href');
          var text = $(this).data('confirm');
          $('#js-confirm-link .modal-body').html(text);
          var method = $(this).data('method');
          var data = $(this).data();
          var table = $(this).closest('[data-table]').closest('[id]');
          e.preventDefault();
          $('#js-confirm-link').modal({ backdrop: 'static', keyboard: false })
              .one('click', '.js-confirm-link-yes', function (e) {
                  if (method == 'DELETE' || method == 'POST') {
                      if (method == 'DELETE')
                          data['_method'] = 'DELETE';
                      $.ajax({
                          type: "POST",
                          dataType: "json",
                          url: url,
                          cache: false,
                          data: data,
                          success: function(res){
                              $('#js-confirm-link').modal('hide');
                              if (table.length) {
                                  tables.get(table.attr('id'));
                              }
                          }
                      });
                  }
                  else {
                      window.location = url;
                  }
              });
      });
  
  });
  (function($){
      'use strict';
      $.multiCheckbox = function( element, options ){
  
          var
              _opt = {
                  item: $( element ).find('[data-toggle="checkbox"]'),
                  items: $( element ).find('input[type="checkbox"]')
              },
              _app = {},
              _this = this,
              $input = $( element ),
              $item,
              $items,
              disableChecking = false;
  
          _this.init = function(){
              _opt = $.extend({}, _opt, options),
                  $item = _opt.item,
                  $items = _opt.items.not( $item );
  
              _events();
  
              _checkParent();
          };
  
          var _events = function (){
  
              $item.on( 'change', function(){
                  dd( 'multiCheckbox parent changed' );
  
                  var _checked = $item.is(':checked'),
                      _items   = [],
                      _values  = [];
  
                  $items.each( function(){
                      if ( $( this ).is(':checked') == _checked )
                          return;
  
                      _items.push( $( this ) );
                      _values.push( $( this ).val() );
  
                      $( this ).prop('checked', _checked);
                  });
  
                  $( this ).trigger('multichanged', { items: _items, values: _values });
  
                  _checkParent();
  /*
                  $.each( _items, function(){
                      $( this ).trigger('multichange');
                  });
  */
              });
  
              $items.on( 'multichange', function(){
                  _this.disableChecking = true;
                  $( this ).trigger( 'change' );
                  _this.disableChecking = false;
              } );
  
              $items.on( 'change', function(e){
                  dd( 'multiCheckbox child changed', e );
                  _checkParent();
              } );
          };
  
          var _checkParent = function() {
              if ( _this.disableChecking )
                  return;
  
              dd( 'multiCheckbox._checkParent' );
  
              if ($items.length == 0)
                  return;
  
              $item.prop('checked', $items.length == $items.filter(':checked').length );
          };
  
          // init!
          _this.init();
      };
      $.fn.multiCheckbox = function( options ){
  
          return this.each(function(){
  
              if ( undefined === $( this ).data( 'multiCheckbox' ) ){
  
                  var plugin = new $.multiCheckbox( this, options );
                  $( this ).data( 'multiCheckbox', plugin );
              }
          });
      };
  })(jQuery);