",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var a,n,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},a=i.split("."),i=a.shift(),a.length){for(n=o[i]=e.widget.extend({},this.options[i]),r=0;a.length-1>r;r++)n[a[r]]=n[a[r]]||{},n=n[a[r]];if(i=a.pop(),s===t)return n[i]===t?null:n[i];n[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,a){var n,r=this;"boolean"!=typeof i&&(a=s,s=i,i=!1),a?(s=n=e(s),this.bindings=this.bindings.add(s)):(a=s,s=this.element,n=this.widget()),e.each(a,function(a,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=a.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?n.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var a,n,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],n=i.originalEvent)for(a in n)a in i||(i[a]=n[a]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,a,n){"string"==typeof a&&(a={effect:a});var r,o=a?a===!0||"number"==typeof a?i:a.effect||i:t;a=a||{},"number"==typeof a&&(a={duration:a}),r=!e.isEmptyObject(a),a.complete=n,a.delay&&s.delay(a.delay),r&&e.effects&&e.effects.effect[o]?s[t](a):o!==t&&s[o]?s[o](a.duration,a.easing,n):s.queue(function(i){e(this)[t](),n&&n.call(s[0]),i()})}})})(jQuery);(function(e,t){function i(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function s(t,i){return parseInt(e.css(t,i),10)||0}function a(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,r=Math.max,o=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,c=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var i,s,a=e("
"),r=a.children()[0];return e("body").append(a),i=r.offsetWidth,a.css("overflow","scroll"),s=r.offsetWidth,i===s&&(s=a[0].clientWidth),a.remove(),n=i-s},getScrollInfo:function(t){var i=t.isWindow?"":t.element.css("overflow-x"),s=t.isWindow?"":t.element.css("overflow-y"),a="scroll"===i||"auto"===i&&t.width
s?"left":i>0?"right":"center",vertical:0>n?"top":a>0?"bottom":"middle"};c>p&&p>o(i+s)&&(h.horizontal="center"),d>m&&m>o(a+n)&&(h.vertical="middle"),h.important=r(o(i),o(s))>r(o(a),o(n))?"horizontal":"vertical",t.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,a=s.isWindow?s.scrollLeft:s.offset.left,n=s.width,o=e.left-t.collisionPosition.marginLeft,h=a-o,l=o+t.collisionWidth-n-a;t.collisionWidth>n?h>0&&0>=l?(i=e.left+h+t.collisionWidth-n-a,e.left+=h-i):e.left=l>0&&0>=h?a:h>l?a+n-t.collisionWidth:a:h>0?e.left+=h:l>0?e.left-=l:e.left=r(e.left-o,e.left)},top:function(e,t){var i,s=t.within,a=s.isWindow?s.scrollTop:s.offset.top,n=t.within.height,o=e.top-t.collisionPosition.marginTop,h=a-o,l=o+t.collisionHeight-n-a;t.collisionHeight>n?h>0&&0>=l?(i=e.top+h+t.collisionHeight-n-a,e.top+=h-i):e.top=l>0&&0>=h?a:h>l?a+n-t.collisionHeight:a:h>0?e.top+=h:l>0?e.top-=l:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var i,s,a=t.within,n=a.offset.left+a.scrollLeft,r=a.width,h=a.isWindow?a.scrollLeft:a.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,c=l+t.collisionWidth-r-h,d="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+d+p+f+t.collisionWidth-r-n,(0>i||o(u)>i)&&(e.left+=d+p+f)):c>0&&(s=e.left-t.collisionPosition.marginLeft+d+p+f-h,(s>0||c>o(s))&&(e.left+=d+p+f))},top:function(e,t){var i,s,a=t.within,n=a.offset.top+a.scrollTop,r=a.height,h=a.isWindow?a.scrollTop:a.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,c=l+t.collisionHeight-r-h,d="top"===t.my[1],p=d?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-r-n,e.top+p+f+m>u&&(0>s||o(u)>s)&&(e.top+=p+f+m)):c>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,e.top+p+f+m>c&&(i>0||c>o(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,a,n,r=document.getElementsByTagName("body")[0],o=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(n in s)t.style[n]=s[n];t.appendChild(o),i=r||document.documentElement,i.insertBefore(t,i.firstChild),o.style.cssText="position: absolute; left: 10.7432222px;",a=e(o).offset().left,e.support.offsetFractions=a>10&&11>a,t.innerHTML="",i.removeChild(t)}()})(jQuery);(function(e){var t=0;e.widget("ui.autocomplete",{version:"1.10.3",defaultElement:"",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,i,a,s=this.element[0].nodeName.toLowerCase(),n="textarea"===s,r="input"===s;this.isMultiLine=n?!0:r?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[n||r?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(s){if(this.element.prop("readOnly"))return t=!0,a=!0,i=!0,undefined;t=!1,a=!1,i=!1;var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:t=!0,this._move("previousPage",s);break;case n.PAGE_DOWN:t=!0,this._move("nextPage",s);break;case n.UP:t=!0,this._keyEvent("previous",s);break;case n.DOWN:t=!0,this._keyEvent("next",s);break;case n.ENTER:case n.NUMPAD_ENTER:this.menu.active&&(t=!0,s.preventDefault(),this.menu.select(s));break;case n.TAB:this.menu.active&&this.menu.select(s);break;case n.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(s),s.preventDefault());break;default:i=!0,this._searchTimeout(s)}},keypress:function(a){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&a.preventDefault(),undefined;if(!i){var s=e.ui.keyCode;switch(a.keyCode){case s.PAGE_UP:this._move("previousPage",a);break;case s.PAGE_DOWN:this._move("nextPage",a);break;case s.UP:this._keyEvent("previous",a);break;case s.DOWN:this._keyEvent("next",a)}}},input:function(e){return a?(a=!1,e.preventDefault(),undefined):(this._searchTimeout(e),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(e),this._change(e),undefined)}}),this._initSource(),this.menu=e("").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(a){a.target===t.element[0]||a.target===i||e.contains(i,a.target)||t.close()})})},menufocus:function(t,i){if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),undefined;var a=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:a})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(a.value):this.liveRegion.text(a.value)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),a=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=a,this._delay(function(){this.previous=a,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,a=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,a){a(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,s){a.xhr&&a.xhr.abort(),a.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){s(e)},error:function(){s([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length").append(e("").text(i.label)).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[e](t),undefined):(this.search(null,t),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var a=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return a.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments),this.options.disabled||this.cancelSearch||(t=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.text(t))}})})(jQuery);(function(e){e.widget("ui.menu",{version:"1.10.3",defaultElement:"",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var i=e(t.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(t),i.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var i=e(t.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function i(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,a,n,r,o,h=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:h=!1,a=this.previousFilter||"",n=String.fromCharCode(t.keyCode),r=!1,clearTimeout(this.filterTimer),n===a?r=!0:n=a+n,o=RegExp("^"+i(n),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),s=r&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(n=String.fromCharCode(t.keyCode),o=RegExp("^"+i(n),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),s.length?(this.focus(t,s),s.length>1?(this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}h&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,i=this.options.icons.submenu,s=this.element.find(this.options.menus);s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),s=t.prev("a"),a=e("").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(a),t.attr("aria-labelledby",s.attr("id"))}),t=s.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-\u2014\u2013\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,a,n,r,o;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,a=t.offset().top-this.activeMenu.offset().top-i-s,n=this.activeMenu.scrollTop(),r=this.activeMenu.height(),o=t.height(),0>a?this.activeMenu.scrollTop(n+a):a+o>r&&this.activeMenu.scrollTop(n+a-r+o))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[t]()),this.focus(i,s)},nextPage:function(t){var i,s,a;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,a=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-a}),this.focus(t,i)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(t),undefined)},previousPage:function(t){var i,s,a;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,a=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+a>0}),this.focus(t,i)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(t),undefined)},_hasScroll:function(){return this.element.outerHeight() {
12 | let $input = $('#js-input');
13 | let $button = $('#js-button');
14 | let $alert = $('#js-alert');
15 | let $checkboxPrivate = $('#js-checkbox-private');
16 | let $checkboxReadLater = $('#js-checkbox-readlater');
17 | let $checkboxTagSuggestion = $('#js-checkbox-tagsuggestion');
18 |
19 | function setAlertInfo(message) {
20 | $alert
21 | .removeClass('alert-danger alert-warning alert-success')
22 | .addClass('alert-info')
23 | .text(message);
24 | }
25 |
26 | function setAlertSuccess(message) {
27 | $alert
28 | .removeClass('alert-info alert-warning alert-danger')
29 | .addClass('alert-success')
30 | .text(message);
31 | }
32 |
33 | function setAlertDanger(message) {
34 | $alert
35 | .removeClass('alert-info alert-warning alert-success')
36 | .addClass('alert-danger')
37 | .text(message);
38 | }
39 |
40 | function setAlertWarning(message) {
41 | $alert
42 | .removeClass('alert-info alert-success alert-danger')
43 | .addClass('alert-warning')
44 | .text(message);
45 | }
46 |
47 | const keys = [
48 | constant.authToken,
49 | constant.defaultPrivate,
50 | constant.defaultReadLater,
51 | constant.useTagSuggestion
52 | ];
53 |
54 | let authToken;
55 | let defaultPrivate;
56 | let defaultReadLater;
57 | let useTagSuggestion;
58 |
59 | // check set API token is authenticated
60 | chrome.storage.sync.get(keys, items => {
61 | if (items.hasOwnProperty(constant.authToken)) {
62 | authToken = String(items[constant.authToken]);
63 | } else {
64 | authToken = '';
65 | }
66 |
67 | if (items.hasOwnProperty(constant.defaultPrivate)) {
68 | defaultPrivate = Boolean(items[constant.defaultPrivate]);
69 | } else {
70 | defaultPrivate = false;
71 | }
72 |
73 | if (items.hasOwnProperty(constant.defaultReadLater)) {
74 | defaultReadLater = Boolean(items[constant.defaultReadLater]);
75 | } else {
76 | defaultReadLater = false;
77 | }
78 |
79 | if (items.hasOwnProperty(constant.useTagSuggestion)) {
80 | useTagSuggestion = Boolean(items[constant.useTagSuggestion]);
81 | } else {
82 | useTagSuggestion = false;
83 | }
84 |
85 | $checkboxPrivate.prop('checked', defaultPrivate);
86 | $checkboxReadLater.prop('checked', defaultReadLater);
87 | $checkboxTagSuggestion.prop('checked', useTagSuggestion);
88 |
89 | if (authToken.length !== 0) {
90 | API.checkToken(authToken).then(() => {
91 | setAlertSuccess(Message.succeed);
92 | }).catch(() => {
93 | setAlertDanger(Message.failed);
94 | });
95 | } else {
96 | setAlertInfo(Message.isBlank);
97 | }
98 |
99 | $input.val(authToken);
100 | });
101 |
102 | $input.on('change', () => {
103 | setAlertWarning(Message.changed);
104 | });
105 |
106 | $checkboxPrivate.on('change', () => {
107 | defaultPrivate = $checkboxPrivate.prop('checked');
108 |
109 | let data = {};
110 | data[constant.defaultPrivate] = defaultPrivate;
111 |
112 | chrome.storage.sync.set(data, () => {});
113 | });
114 |
115 | $checkboxReadLater.on('change', () => {
116 | defaultReadLater = $checkboxReadLater.prop('checked');
117 |
118 | let data = {};
119 | data[constant.defaultReadLater] = defaultReadLater;
120 |
121 | chrome.storage.sync.set(data, () => {});
122 | });
123 |
124 | $checkboxTagSuggestion.on('change', () => {
125 | useTagSuggestion = $checkboxTagSuggestion.prop('checked');
126 |
127 | let data = {};
128 | data[constant.useTagSuggestion] = useTagSuggestion;
129 |
130 | chrome.storage.sync.set(data, () => {});
131 | });
132 |
133 | // if the save button is clicked
134 | $button.on('click', () => {
135 | authToken = $input.val();
136 |
137 | let data = {};
138 | data[constant.authToken] = authToken;
139 |
140 | chrome.storage.sync.set(data, () => {
141 | if (authToken.length !== 0) {
142 | API.checkToken(authToken).then(() => {
143 | data[constant.isAuthenticated] = true;
144 |
145 | chrome.storage.sync.set(data, () => {
146 | setAlertSuccess(Message.succeed);
147 | });
148 | }).catch(() => {
149 | data[constant.isAuthenticated] = false;
150 |
151 | chrome.storage.sync.set(data, () => {
152 | setAlertDanger(Message.failed);
153 | });
154 | });
155 | } else {
156 | data[constant.isAuthenticated] = false;
157 |
158 | chrome.storage.sync.set(data, () => {
159 | setAlertInfo(Message.isBlank);
160 | });
161 | }
162 | });
163 | });
164 | });
165 |
--------------------------------------------------------------------------------
/src/js/popup.js:
--------------------------------------------------------------------------------
1 | import * as constant from './constant';
2 | import * as API from './api';
3 | import * as util from './util';
4 |
5 | const Message = {
6 | isBookmarked : 'This URL is already bookmarked.',
7 | isNotAuthenticated : 'API Token is not authenticated.',
8 | bookmarkedSuccessfully : 'Bookmarked successfully!',
9 | updatedSuccessfully : 'Updated successfully!',
10 | deletedSuccessfully : 'Deleted successfully!',
11 | failedToBookmark : 'Failed to bookmark...',
12 | failedToUpdate : 'Failed to update...',
13 | failedToDelete : 'Failed to delete...'
14 | };
15 |
16 | // autofocus attribute is not working on chrome extension :(
17 | // https://code.google.com/p/chromium/issues/detail?id=111660#c7
18 | if (location.search !== '?foo') {
19 | location.search = '?foo';
20 | throw new Error();
21 | // load everything on the next page;
22 | // stop execution on this page
23 | }
24 |
25 | $(() => {
26 | let $form = $('#js-form');
27 | let $url = $('#js-url');
28 | let $title = $('#js-title');
29 | let $tags = $('#js-tags');
30 | let $description = $('#js-description');
31 | let $private = $('#js-private');
32 | let $readlater = $('#js-readlater');
33 | let $bookmark = $('#js-bookmark');
34 | let $dropdown = $('#js-bookmark-dropdown');
35 | let $delete = $('#js-delete');
36 | let $alert = $('#js-alert');
37 |
38 | //function setAlertInfo(message = '') {
39 | // $alert.removeClass('alert-danger alert-warning alert-success')
40 | // .addClass('alert-info')
41 | // .text(message);
42 | //}
43 |
44 | function setAlertSuccess(message = '') {
45 | $alert
46 | .removeClass('alert-info alert-warning alert-danger')
47 | .addClass('alert-success')
48 | .text(message);
49 | }
50 |
51 | function setAlertDanger(message = '') {
52 | $alert
53 | .removeClass('alert-info alert-warning alert-success')
54 | .addClass('alert-danger')
55 | .text(message);
56 | }
57 |
58 | function setAlertWarning(message = '') {
59 | $alert
60 | .removeClass('alert-info alert-success alert-danger')
61 | .addClass('alert-warning')
62 | .text(message);
63 | }
64 |
65 | let authToken;
66 | let isAuthenticated;
67 | let defaultPrivate;
68 | let defaultReadLater;
69 | let useTagSuggestion;
70 |
71 | // when popup is opened,
72 | // send blank message to background
73 | chrome.runtime.sendMessage({useStrict : true}, response => {
74 | $url.val(response.url);
75 | $title.val(response.title);
76 | $tags.focus();
77 |
78 | const keys = [
79 | constant.authToken,
80 | constant.isAuthenticated,
81 | constant.defaultPrivate,
82 | constant.defaultReadLater,
83 | constant.useTagSuggestion
84 | ];
85 |
86 | chrome.storage.sync.get(keys, item => {
87 | authToken = String(item[constant.authToken]);
88 | isAuthenticated = Boolean(item[constant.isAuthenticated]);
89 | defaultPrivate = Boolean(item[constant.defaultPrivate]);
90 | defaultReadLater = Boolean(item[constant.defaultReadLater]);
91 | useTagSuggestion = Boolean(item[constant.useTagSuggestion]);
92 |
93 | if (defaultPrivate) {
94 | $private.prop('checked', true);
95 | }
96 |
97 | if (defaultReadLater) {
98 | $readlater.prop('checked', true);
99 | }
100 |
101 | if (!isAuthenticated) {
102 | setAlertDanger(Message.isNotAuthenticated);
103 | $bookmark.prop('disabled', true);
104 | } else {
105 | API.getPost(response.url, authToken).then(data => {
106 | if (data.posts.length !== 0) {
107 | let post = data.posts.shift();
108 | $tags.val(post.tags);
109 | $description.val(post.extended);
110 | $private.prop('checked', post.shared === 'no');
111 | $readlater.prop('checked', post.toread !== 'no');
112 | $bookmark
113 | .removeClass('btn-primary')
114 | .addClass('btn-warning')
115 | .text('Update bookmark');
116 | $dropdown
117 | .removeAttr('disabled')
118 | .removeClass('btn-primary')
119 | .addClass('btn-warning');
120 |
121 | setAlertWarning(Message.isBookmarked);
122 |
123 | Message.bookmarkedSuccessfully = Message.updatedSuccessfully;
124 | Message.failedToBookmark = Message.failedToUpdate;
125 | } else if (useTagSuggestion) {
126 | API.suggestPost(response.url, authToken).then(array => {
127 | for (let tag of array) {
128 | if (Array.isArray(tag.popular)) {
129 | $tags.val(tag.popular.join(' '));
130 | }
131 | }
132 | });
133 | }
134 | }).then(() => {
135 | // set up word suggestion
136 | API.getTags(authToken).then(data => {
137 | let availableTags = Object.keys(data);
138 |
139 | $tags.on('keydown', e => {
140 | let $this = $(e.target);
141 |
142 | if (e.keyCode === $.ui.keyCode.TAB &&
143 | $this.data('ui-autocomplete').menu.active) {
144 | e.preventDefault();
145 | }
146 | }).autocomplete({
147 | minLength : 0,
148 | max : 5,
149 | autoFocus : true,
150 | source : (req, res) => {
151 | // delegate back to autocomplete, but extract the last term
152 | res(
153 | $.ui.autocomplete.filter(
154 | availableTags,
155 | util.extractLast(req.term)
156 | ).slice(0, 5)
157 | );
158 | },
159 | focus : () => {
160 | // prevent value inserted on focus
161 | return false;
162 | },
163 | select : (e, ui) => {
164 | if (e.keyCode === $.ui.keyCode.ENTER) {
165 | // enter should submit the form, not autocomplete
166 | $form.trigger('submit');
167 | return false;
168 | }
169 |
170 | let terms = util.split(e.target.value);
171 | // remove the current input
172 | terms.pop();
173 | // add the selected item
174 | terms.push(ui.item.value);
175 | // add placeholder to get the comma-and-space at the end
176 | terms.push('');
177 | e.target.value = terms.join(' ');
178 | return false;
179 | }
180 | });
181 | });
182 | });
183 |
184 | $form.on('submit', e => {
185 | e.preventDefault();
186 |
187 | API.addPost(
188 | $url.val(),
189 | $title.val(),
190 | $description.val(),
191 | $tags.val(),
192 | $private.prop('checked') ? 'no' : 'yes',
193 | $readlater.prop('checked') ? 'yes' : 'no',
194 | authToken
195 | ).then(data => {
196 | if (data.result_code !== 'done') {
197 | setAlertDanger(Message.failedToBookmark);
198 |
199 | chrome.runtime.sendMessage({
200 | useStrict : false,
201 | isBookmarked : false
202 | });
203 | } else {
204 | setAlertSuccess(Message.bookmarkedSuccessfully);
205 |
206 | chrome.runtime.sendMessage({
207 | useStrict : false,
208 | isBookmarked : true
209 | });
210 |
211 | // close popup window
212 | window.setTimeout(() => window.close(), 300);
213 | }
214 | }).catch(error => {
215 | setAlertDanger(error.message);
216 |
217 | chrome.runtime.sendMessage({
218 | useStrict : false,
219 | isBookmarked : false
220 | });
221 | });
222 | });
223 |
224 | $bookmark.on('click', e => {
225 | e.preventDefault();
226 |
227 | API.addPost(
228 | $url.val(),
229 | $title.val(),
230 | $description.val(),
231 | $tags.val(),
232 | $private.prop('checked') ? 'no' : 'yes',
233 | $readlater.prop('checked') ? 'yes' : 'no',
234 | authToken
235 | ).then(data => {
236 | if (data.result_code !== 'done') {
237 | setAlertDanger(Message.failedToBookmark);
238 |
239 | chrome.runtime.sendMessage({
240 | useStrict : false,
241 | isBookmarked : false
242 | });
243 | } else {
244 | setAlertSuccess(Message.bookmarkedSuccessfully);
245 |
246 | chrome.runtime.sendMessage({
247 | useStrict : false,
248 | isBookmarked : true
249 | });
250 |
251 | window.setTimeout(() => window.close(), 300);
252 | }
253 | }).catch(error => {
254 | setAlertDanger(error.message);
255 |
256 | chrome.runtime.sendMessage({
257 | useStrict : false,
258 | isBookmarked : false
259 | });
260 | });
261 | });
262 |
263 | $delete.on('click', e => {
264 | e.preventDefault();
265 |
266 | API.deletePost($url.val(), authToken).then(data => {
267 | if (data.result_code !== 'done') {
268 | setAlertDanger(Message.failedToDelete);
269 |
270 | chrome.runtime.sendMessage({
271 | useStrict : false,
272 | isBookmarked : true
273 | });
274 | } else {
275 | setAlertSuccess(Message.deletedSuccessfully);
276 |
277 | chrome.runtime.sendMessage({
278 | useStrict : false,
279 | isBookmarked : false
280 | });
281 |
282 | window.setTimeout(() => window.close(), 300);
283 | }
284 | }).catch(error => {
285 | setAlertDanger(error.message);
286 |
287 | chrome.runtime.sendMessage({
288 | useStrict : false,
289 | isBookmarked : true
290 | });
291 | });
292 | });
293 | }
294 | });
295 | });
296 | });
297 |
--------------------------------------------------------------------------------
/src/js/util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Split string with whitespace
3 | * @param {String} val
4 | * @returns {String}
5 | */
6 | export function split(val = '') {
7 | return val.split(/ \s*/);
8 | }
9 |
10 | /**
11 | * Extract last
12 | * @param {String} term
13 | * @returns {String}
14 | */
15 | export function extractLast(term) {
16 | return split(term).pop();
17 | }
18 |
19 | /**
20 | * Serialize object to array
21 | * @param {Object} param
22 | * @returns {Array}
23 | */
24 | export function serializeArray(param = {}) {
25 | let array = [];
26 | let keys = Object.keys(param);
27 |
28 | for (let key of keys) {
29 | array.push(`${key}=${param[key]}`);
30 | }
31 |
32 | return array;
33 | }
34 |
35 | /**
36 | * Serialize object to string
37 | * @param {Object} param
38 | * @returns {String}
39 | */
40 | export function serialize(param) {
41 | return serializeArray(param).join('&');
42 | }
43 |
44 | /**
45 | * Check an URL is bookmarkable or not
46 | **/
47 | export function isBookmarkable(url) {
48 | let protocol = new URL(url).protocol;
49 | if (protocol === 'http:') {
50 | return true;
51 | } else if (protocol === 'https:') {
52 | return true;
53 | }
54 | return false;
55 | }
56 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "Pinput for Pinboard",
4 | "short_name": "Pinput",
5 | "version": "1.11.0",
6 | "description": "Light-weight chrome extension for Pinboard.",
7 | "author": "1000ch",
8 | "icons": {
9 | "16": "icons/icon16.png",
10 | "48": "icons/icon48.png",
11 | "128": "icons/icon128.png"
12 | },
13 | "permissions": [
14 | "tabs",
15 | "storage",
16 | "http://*/*",
17 | "https://*/*"
18 | ],
19 | "background": {
20 | "page": "html/background.html"
21 | },
22 | "browser_action": {
23 | "default_icon": "icons/icon38.png",
24 | "default_title": "Pinput for Pinboard",
25 | "default_popup": "html/popup.html"
26 | },
27 | "options_ui": {
28 | "page": "html/options.html"
29 | },
30 | "commands": {
31 | "direct-bookmark": {
32 | "suggested_key": {
33 | "default": "Ctrl+Shift+B",
34 | "mac": "MacCtrl+Shift+B"
35 | },
36 | "description": "Bookmark directly without opening popup window."
37 | },
38 | "_execute_browser_action": {
39 | "suggested_key": {
40 | "default": "Ctrl+B",
41 | "mac": "MacCtrl+B"
42 | },
43 | "description": "Open popup window."
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------