|
|
|
/* =============================================================
|
|
|
|
* bootstrap3-typeahead.js v4.0.2
|
|
|
|
* https://github.com/bassjobsen/Bootstrap-3-Typeahead
|
|
|
|
* =============================================================
|
|
|
|
* Original written by @mdo and @fat
|
|
|
|
* =============================================================
|
|
|
|
* Copyright 2014 Bass Jobsen @bassjobsen
|
|
|
|
*
|
|
|
|
* 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(root,factory){"use strict";if(typeof module!=="undefined"&&module.exports){module.exports=factory(require("jquery"))}else if(typeof define==="function"&&define.amd){define(["jquery"],function($){return factory($)})}else{factory(root.jQuery)}})(this,function($){"use strict";var Typeahead=function(element,options){this.$element=$(element);this.options=$.extend({},$.fn.typeahead.defaults,options);this.matcher=this.options.matcher||this.matcher;this.sorter=this.options.sorter||this.sorter;this.select=this.options.select||this.select;this.autoSelect=typeof this.options.autoSelect=="boolean"?this.options.autoSelect:true;this.highlighter=this.options.highlighter||this.highlighter;this.render=this.options.render||this.render;this.updater=this.options.updater||this.updater;this.displayText=this.options.displayText||this.displayText;this.source=this.options.source;this.delay=this.options.delay;this.$menu=$(this.options.menu);this.$appendTo=this.options.appendTo?$(this.options.appendTo):null;this.fitToElement=typeof this.options.fitToElement=="boolean"?this.options.fitToElement:false;this.shown=false;this.listen();this.showHintOnFocus=typeof this.options.showHintOnFocus=="boolean"||this.options.showHintOnFocus==="all"?this.options.showHintOnFocus:false;this.afterSelect=this.options.afterSelect;this.addItem=false;this.value=this.$element.val()||this.$element.text()};Typeahead.prototype={constructor:Typeahead,select:function(){var val=this.$menu.find(".active").data("value");this.$element.data("active",val);if(this.autoSelect||val){var newVal=this.updater(val);if(!newVal){newVal=""}this.$element.val(this.displayText(newVal)||newVal).text(this.displayText(newVal)||newVal).change();this.afterSelect(newVal)}return this.hide()},updater:function(item){return item},setSource:function(source){this.source=source},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});var scrollHeight=typeof this.options.scrollHeight=="function"?this.options.scrollHeight.call():this.options.scrollHeight;var element;if(this.shown){element=this.$menu}else if(this.$appendTo){element=this.$menu.appendTo(this.$appendTo);this.hasSameParent=this.$appendTo.is(this.$element.parent())}else{element=this.$menu.insertAfter(this.$element);this.hasSameParent=true}if(!this.hasSameParent){element.css("position","fixed");var offset=this.$element.offset();pos.top=offset.top;pos.left=offset.left}var dropup=$(element).parent().hasClass("dropup");var newTop=dropup?"auto":pos.top+pos.height+scrollHeight;var right=$(element).hasClass("dropdown-menu-right");var newLeft=right?"auto":pos.left;element.css({top:newTop,left:newLeft}).show();if(this.options.fitToElement===true){element.css("width",this.$element.outerWidth()+"px")}this.shown=true;return this},hide:function(){this.$menu.hide();this.shown=false;return this},lookup:function(query){var items;if(typeof query!="undefined"&&query!==null){this.query=query}else{this.query=this.$element.val()||this.$element.text()||""}if(this.query.length<this.options.minLength&&!this.options.showHintOnFocus){return this.shown?this.hide():this}var worker=$.proxy(function(){if($.isFunction(this.source)){this.source(this.query,$.proxy(this.process,this))}else if(this.source){this.process(this.source)}},this);clearTimeout(this.lookupWorker);this.lookupWorker=setTimeout(worker,this.delay)},process:function(items){var that=this;items=$.grep(items,function(item){return that.matcher(item)});items=this.sorter(items);if(!items.length&&!this.options.addItem){return this.shown?this.hide():this}if(items.length>0){this.$element.data("active",items[0])}else{this.$element.data("active",null)}if(this.options.addItem){items.push(this.options.addItem)}if(this.options.items=="all"){return this.render(items).show()}else{return this.render(items.slice(0,this.options.items)).show()}},matcher:function(item){var it=this.displayText(item);return~it.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(items){var beginswith=[];var caseSensitive=[];var caseInsensitive=[];var item;while(item=items.shift()){var
|
|
|
|
/*!
|
|
|
|
* jQuery Form Plugin
|
|
|
|
* version: 4.2.2
|
|
|
|
* Requires jQuery v1.7.2 or later
|
|
|
|
* Project repository: https://github.com/jquery-form/form
|
|
|
|
|
|
|
|
* Copyright 2017 Kevin Morris
|
|
|
|
* Copyright 2006 M. Alsup
|
|
|
|
|
|
|
|
* Dual licensed under the LGPL-2.1+ or MIT licenses
|
|
|
|
* https://github.com/jquery-form/form#license
|
|
|
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*/
|
|
|
|
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,r){return void 0===r&&(r="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(r),r}:e(jQuery)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).closest("form").ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=r.form;if(i.clk=r,"image"===r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n=/\r?\n/g,i={};i.fileapi=void 0!==e('<input type="file">').get(0).files,i.formdata=void 0!==window.FormData;var o=!!e.fn.prop;e.fn.attr2=function(){if(!o)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t,r,n,s){function u(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;a<o;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function c(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(e){a("cannot get iframe.contentWindow document: "+e)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function i(){function t(){try{var e=n(v).readyState;a("state = "+e),e&&"uninitialized"===e.toLowerCase()&&setTimeout(t,50)}catch(e){a("Server abort: ",e," (",e.name,")"),s(L),j&&clearTimeout(j),j=void 0}}var r=p.attr2("target"),i=p.attr2("action"),o=p.attr("enctype")||p.attr("encoding")||"multipart/form-data";w.setAttribute("target",m),l&&!/post/i.test(l)||w.setAttribute("method","POST"),i!==f.url&&w.setAttribute("action",f.url),f.skipEncodingOverride||l&&!/post/i.test(l)||p.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),f.timeout&&(j=setTimeout(function(){T=!0,s(A)},f.timeout));var u=[];try{if(f.extraData)for(var c in f.extraData)f.extraData.hasOwnProperty(c)&&(e.isPlainObject(f.extraData[c])&&f.extraData[c].hasOwnProperty("name")&&f.extraData[c].hasOwnProperty("value")?u.push(e('<input type="hidden" name="'+f.extraData[c].name+'">',k).val(f.extraData[c].value).appendTo(w)[0]):u.push(e('<input type="hidden" name="'+c+'">',k).val(f.extraData[c]).appendTo(w)[0]));f.iframeTarget||h.appendTo(D),v.attachEvent?v.attachEvent("onload",s):v.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(e){document.createElement("form").submit.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",o),r?w.setAttribute("target",r):p.removeAttr("target"),e(u).remove()}}function s(t){if(!x.aborted&&!X){if((O=n(v))||(a("cannot access response document"),t=L),t===A&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t===L&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(O&&O.location.href!==f.iframeSrc||T){v.detachEvent?v.detachEvent("onload",s):v.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"===f.dataType||O.XMLDocument||e.isXMLDoc(O);if(a("isXml="+o),!o&&window.opera&&(null===O.body||!O.body.innerHTML)&&--C)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=O.body?O.body:O.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=O.XMLDocument?O.XMLDocument:O,o&&(f.dataType="xml"),x.getResponseHeader=function(e){return{"content-type":f.dataType}[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status
|
|
|
|
/*! jquery-qrcode v0.14.0 - https://larsjung.de/jquery-qrcode/ */
|
|
|
|
!function(r){"use strict";function t(t,e,n,o){function a(r,t){return r-=o,t-=o,0>r||r>=c||0>t||t>=c?!1:f.isDark(r,t)}function i(r,t,e,n){var o=u.isDark,a=1/l;u.isDark=function(i,u){var f=u*a,c=i*a,l=f+a,g=c+a;return o(i,u)&&(r>l||f>e||t>g||c>n)}}var u={},f=r(n,e);f.addData(t),f.make(),o=o||0;var c=f.getModuleCount(),l=f.getModuleCount()+2*o;return u.text=t,u.level=e,u.version=n,u.moduleCount=l,u.isDark=a,u.addBlank=i,u}function e(r,e,n,o,a){n=Math.max(1,n||1),o=Math.min(40,o||40);for(var i=n;o>=i;i+=1)try{return t(r,e,i,a)}catch(u){}}function n(r,t,e){var n=e.size,o="bold "+e.mSize*n+"px "+e.fontname,a=w("<canvas/>")[0].getContext("2d");a.font=o;var i=a.measureText(e.label).width,u=e.mSize,f=i/n,c=(1-f)*e.mPosX,l=(1-u)*e.mPosY,g=c+f,s=l+u,v=.01;1===e.mode?r.addBlank(0,l-v,n,s+v):r.addBlank(c-v,l-v,g+v,s+v),t.fillStyle=e.fontcolor,t.font=o,t.fillText(e.label,c*n,l*n+.75*e.mSize*n)}function o(r,t,e){var n=e.size,o=e.image.naturalWidth||1,a=e.image.naturalHeight||1,i=e.mSize,u=i*o/a,f=(1-u)*e.mPosX,c=(1-i)*e.mPosY,l=f+u,g=c+i,s=.01;3===e.mode?r.addBlank(0,c-s,n,g+s):r.addBlank(f-s,c-s,l+s,g+s),t.drawImage(e.image,f*n,c*n,u*n,i*n)}function a(r,t,e){w(e.background).is("img")?t.drawImage(e.background,0,0,e.size,e.size):e.background&&(t.fillStyle=e.background,t.fillRect(e.left,e.top,e.size,e.size));var a=e.mode;1===a||2===a?n(r,t,e):(3===a||4===a)&&o(r,t,e)}function i(r,t,e,n,o,a,i,u){r.isDark(i,u)&&t.rect(n,o,a,a)}function u(r,t,e,n,o,a,i,u,f,c){i?r.moveTo(t+a,e):r.moveTo(t,e),u?(r.lineTo(n-a,e),r.arcTo(n,e,n,o,a)):r.lineTo(n,e),f?(r.lineTo(n,o-a),r.arcTo(n,o,t,o,a)):r.lineTo(n,o),c?(r.lineTo(t+a,o),r.arcTo(t,o,t,e,a)):r.lineTo(t,o),i?(r.lineTo(t,e+a),r.arcTo(t,e,n,e,a)):r.lineTo(t,e)}function f(r,t,e,n,o,a,i,u,f,c){i&&(r.moveTo(t+a,e),r.lineTo(t,e),r.lineTo(t,e+a),r.arcTo(t,e,t+a,e,a)),u&&(r.moveTo(n-a,e),r.lineTo(n,e),r.lineTo(n,e+a),r.arcTo(n,e,n-a,e,a)),f&&(r.moveTo(n-a,o),r.lineTo(n,o),r.lineTo(n,o-a),r.arcTo(n,o,n-a,o,a)),c&&(r.moveTo(t+a,o),r.lineTo(t,o),r.lineTo(t,o-a),r.arcTo(t,o,t+a,o,a))}function c(r,t,e,n,o,a,i,c){var l=r.isDark,g=n+a,s=o+a,v=e.radius*a,h=i-1,d=i+1,w=c-1,m=c+1,y=l(i,c),T=l(h,w),p=l(h,c),B=l(h,m),A=l(i,m),E=l(d,m),k=l(d,c),M=l(d,w),C=l(i,w);y?u(t,n,o,g,s,v,!p&&!C,!p&&!A,!k&&!A,!k&&!C):f(t,n,o,g,s,v,p&&C&&T,p&&A&&B,k&&A&&E,k&&C&&M)}function l(r,t,e){var n,o,a=r.moduleCount,u=e.size/a,f=i;for(e.radius>0&&e.radius<=.5&&(f=c),t.beginPath(),n=0;a>n;n+=1)for(o=0;a>o;o+=1){var l=e.left+o*u,g=e.top+n*u,s=u;f(r,t,e,l,g,s,n,o)}if(w(e.fill).is("img")){t.strokeStyle="rgba(0,0,0,0.5)",t.lineWidth=2,t.stroke();var v=t.globalCompositeOperation;t.globalCompositeOperation="destination-out",t.fill(),t.globalCompositeOperation=v,t.clip(),t.drawImage(e.fill,0,0,e.size,e.size),t.restore()}else t.fillStyle=e.fill,t.fill()}function g(r,t){var n=e(t.text,t.ecLevel,t.minVersion,t.maxVersion,t.quiet);if(!n)return null;var o=w(r).data("qrcode",n),i=o[0].getContext("2d");return a(n,i,t),l(n,i,t),o}function s(r){var t=w("<canvas/>").attr("width",r.size).attr("height",r.size);return g(t,r)}function v(r){return w("<img/>").attr("src",s(r)[0].toDataURL("image/png"))}function h(r){var t=e(r.text,r.ecLevel,r.minVersion,r.maxVersion,r.quiet);if(!t)return null;var n,o,a=r.size,i=r.background,u=Math.floor,f=t.moduleCount,c=u(a/f),l=u(.5*(a-c*f)),g={position:"relative",left:0,top:0,padding:0,margin:0,width:a,height:a},s={position:"absolute",padding:0,margin:0,width:c,height:c,"background-color":r.fill},v=w("<div/>").data("qrcode",t).css(g);for(i&&v.css("background-color",i),n=0;f>n;n+=1)for(o=0;f>o;o+=1)t.isDark(n,o)&&w("<div/>").css(s).css({left:l+o*c,top:l+n*c}).appendTo(v);return v}function d(r){return m&&"canvas"===r.render?s(r):m&&"image"===r.render?v(r):h(r)}var w=window.jQuery,m=function(){var r=document.createElement("canvas");return!(!r.getContext||!r.getContext("2d"))}(),y={render:"canvas",minVersion:1,maxVersion:40,ecLevel:"L",left:0,top:0,size:200,fill:"#000",background:null,text:"no text",radius:0,quiet:0,mode:0,mSize:.1,mPosX:.5,mPosY:.5,label:"no label",fontname:"sans",fontcolor:"#000",image:null};w.fn.qrcode=function(r
|
|
|
|
/*!
|
|
|
|
* jQuery PathBrowser
|
|
|
|
*
|
|
|
|
* (c) 2012 SABnzbd Team, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Dual licensed under MIT or GPLv2 licenses
|
|
|
|
* http://en.wikipedia.org/wiki/MIT_License
|
|
|
|
* http://en.wikipedia.org/wiki/GNU_General_Public_License
|
|
|
|
*
|
|
|
|
* Changed by Safihre - 11 Nov 2015
|
|
|
|
*/
|
|
|
|
;(function($) {
|
|
|
|
// Building object
|
|
|
|
function FileBrowser(element) {
|
|
|
|
// Initialize
|
|
|
|
this.element = $(element);
|
|
|
|
this.initialDir = null;
|
|
|
|
this.currentBrowserPath = null;
|
|
|
|
this.currentRequest = null;
|
|
|
|
this.fileBrowserDialog = $('#filebrowser_modal .modal-body');
|
|
|
|
this.fileBrowserTitle = this.element.data('title') || $('label[for="'+this.element.attr('id')+'"]').text() || '';
|
|
|
|
|
|
|
|
// Start
|
|
|
|
this.init()
|
|
|
|
};
|
|
|
|
|
|
|
|
// Adding button
|
|
|
|
FileBrowser.prototype.init = function () {
|
|
|
|
// Self-reference
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
// Small or big button
|
|
|
|
buttonText = this.element.hasClass('fileBrowserSmall') ? '' : configTranslate.browseText;
|
|
|
|
|
|
|
|
// Add button
|
|
|
|
this.element.addClass('fileBrowserField').after(
|
|
|
|
$('<button class="btn btn-default fileBrowser" type="button"><span class="glyphicon glyphicon-folder-open"></span> '+buttonText+'</button>').click(function () {
|
|
|
|
self.openBrowser();
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open browser-window
|
|
|
|
FileBrowser.prototype.openBrowser = function() {
|
|
|
|
// Self-reference
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
// set up the browser and launch the dialog
|
|
|
|
// textbox (not saved) path > textbox (saved) path > none
|
|
|
|
this.initialDir = this.element.val() || this.element.data('initialdir') || '';
|
|
|
|
|
|
|
|
// If there's no seperator, it must be a relative path
|
|
|
|
if(this.initialDir.split(folderSeperator).length < 2 && this.element.data('initialdir')) {
|
|
|
|
this.initialDir = this.element.data('initialdir') + folderSeperator + this.element.val();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Browse
|
|
|
|
this.browse(this.initialDir , folderBrowseUrl);
|
|
|
|
|
|
|
|
// Choose path and close modal
|
|
|
|
$('#filebrowser_modal_accept').click(function() {
|
|
|
|
// Is it a relative path?
|
|
|
|
if(self.currentBrowserPath.indexOf(self.element.data('initialdir')) === 0) {
|
|
|
|
// Remove start
|
|
|
|
self.currentBrowserPath = self.currentBrowserPath.replace(self.element.data('initialdir')+folderSeperator, '');
|
|
|
|
// If it's identical to the initial dir the replacement won't work
|
|
|
|
if(self.currentBrowserPath == self.element.data('initialdir')) {
|
|
|
|
self.currentBrowserPath = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Changed?
|
|
|
|
if(self.element.val() != self.currentBrowserPath) {
|
|
|
|
self.element.val(self.currentBrowserPath);
|
|
|
|
formHasChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hide and stop default action
|
|
|
|
$('#filebrowser_modal').modal('hide');
|
|
|
|
return false;
|
|
|
|
})
|
|
|
|
|
|
|
|
// Show hidden folders
|
|
|
|
$('#show_hidden_folders').off('change')
|
|
|
|
$('#show_hidden_folders').on('change', function() {
|
|
|
|
self.browse(self.currentBrowserPath , folderBrowseUrl);
|
|
|
|
})
|
|
|
|
|
|
|
|
// Use custom title instead of default and open modal
|
|
|
|
$('#filebrowser_modal .modal-header h4').text(this.fileBrowserTitle);
|
|
|
|
$('#filebrowser_modal').modal('show');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileBrowser.prototype.browse = function(path, endpoint) {
|
|
|
|
// Self-reference
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
// Still loading
|
|
|
|
if (this.currentRequest) this.currentRequest.abort();
|
|
|
|
|
|
|
|
// Show hidden folders on Linux?
|
|
|
|
var extraHidden = $('#show_hidden_folders').is(':checked') ? '&show_hidden_folders=1' : '';
|
|
|
|
|
|
|
|
// Get current folders
|
|
|
|
this.currentBrowserPath = path;
|
|
|
|
this.currentRequest = $.getJSON(endpoint + extraHidden, { name: path }, function (data) {
|
|
|
|
// Clean
|
|
|
|
self.fileBrowserDialog.empty();
|
|
|
|
|
|
|
|
// Make list
|
|
|
|
var list = $('<div class="list-group">').appendTo(self.fileBrowserDialog);
|
|
|
|
$.each(data.paths, function (i, entry) {
|
|
|
|
// Title for first one
|
|
|
|
if(i == 0) {
|
|
|
|
self.fileBrowserDialog.prepend($('<h4>').text(entry.current_path))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Regular link
|
|
|
|
link = $('<a class="list-group-item" href="javascript:void(0)" />').click(function () {
|
|
|
|
self.browse(entry.path, endpoint); }
|
|
|
|
).text(entry.name);
|
|
|
|
// Back image
|
|
|
|
if(entry.name == '..') {
|
|
|
|
$('<span class="glyphicon glyphicon-arrow-left"></span> ').prependTo(link);
|
|
|
|
} else {
|
|
|
|
$('<span class="glyphicon glyphicon-folder-open"></span> ').prependTo(link);
|
|
|
|
}
|
|
|
|
// Add to list
|
|
|
|
link.appendTo(list);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we have unique instances
|
|
|
|
$.fn.fileBrowser = function () {
|
|
|
|
return this.each(function () {
|
|
|
|
if (!$.data(this, 'plugin_FileBrowser')) {
|
|
|
|
$.data(this, 'plugin_FileBrowser', new FileBrowser(this));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})(jQuery);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Takes the inputs-elements found in the current selector
|
|
|
|
* and extracts the values into the provided data-object.
|
|
|
|
*/
|
|
|
|
$.fn.extractFormDataTo = function(target) {
|
|
|
|
var inputs = $("input[type != 'submit'][type != 'button']", this);
|
|
|
|
|
|
|
|
// could use .serializeArray() but that omits unchecked items
|
|
|
|
inputs.each(function (i,elem) {
|
|
|
|
target[elem.name] = elem.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
var selects = $("select", this);
|
|
|
|
|
|
|
|
selects.each(function (i,elem) {
|
|
|
|
target[elem.name] = elem.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Config JS
|
|
|
|
*
|
|
|
|
* (c) 2015 SABnzbd Team, Inc. All rights reserved.
|
|
|
|
*/
|
|
|
|
function config_success() {
|
|
|
|
$('.saveButton').each(function () {
|
|
|
|
$(this).removeAttr("disabled").html('<span class="glyphicon glyphicon-ok"></span> '+configTranslate.saveChanges);
|
|
|
|
});
|
|
|
|
// Let us leave!
|
|
|
|
formWasSubmitted = true;
|
|
|
|
formHasChanged = false;
|
|
|
|
}
|
|
|
|
function config_failure() {
|
|
|
|
$('.saveButton').each(function () {
|
|
|
|
$(this).removeAttr("disabled").addClass('btn-danger').html('<span class="glyphicon glyphicon-remove"></span> '+configTranslate.failed);
|
|
|
|
});
|
|
|
|
// Can't go yet..
|
|
|
|
formWasSubmitted = false;
|
|
|
|
}
|
|
|
|
function do_restart() {
|
|
|
|
// Show overlay
|
|
|
|
$('.main-restarting').show()
|
|
|
|
|
|
|
|
// What template
|
|
|
|
var switchedHTTPS = ($('#enable_https').is(':checked') == ($('#enable_https').data('original') === undefined))
|
|
|
|
var portsUnchanged = ($('#port').val() == $('#port').data('original')) && ($('#https_port').val() == $('#https_port').data('original'))
|
|
|
|
|
|
|
|
// Are we on settings page or did nothing change?
|
|
|
|
if(!$('body').hasClass('General') || (!switchedHTTPS && portsUnchanged)) {
|
|
|
|
// Same as before
|
|
|
|
var urlTotal = window.location.origin + urlBase
|
|
|
|
} else {
|
|
|
|
// Protocol and port depend on http(s) setting
|
|
|
|
if($('#enable_https').is(':checked') && (window.location.protocol == 'https:' || !$('#https_port').val())) {
|
|
|
|
// Https on and we visited this page from HTTPS
|
|
|
|
var urlProtocol = 'https:';
|
|
|
|
var urlPort = $('#https_port').val() ? $('#https_port').val() : $('#port').val();
|
|
|
|
} else {
|
|
|
|
// Regular
|
|
|
|
var urlProtocol = 'http:';
|
|
|
|
var urlPort = $('#port').val();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We cannot make a good guess for the IP, so at least we assume that stays the same
|
|
|
|
var urlTotal = urlProtocol + '//' + window.location.hostname + ':' + urlPort + urlBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show where we are going to connect
|
|
|
|
$('.main-restarting .restarting-url').text(urlTotal)
|
|
|
|
|
|
|
|
// Initiate restart
|
|
|
|
$.ajax({ url: '../../config/restart?session=' + sabSession,
|
|
|
|
complete: function() {
|
|
|
|
// Keep counter of failures
|
|
|
|
var failureCounter = 0;
|
|
|
|
|
|
|
|
// Now we try until we can connect
|
|
|
|
var refreshInterval = setInterval(function() {
|
|
|
|
// We skip the first one
|
|
|
|
if(failureCounter == 0) {
|
|
|
|
failureCounter = failureCounter+1;
|
|
|
|
return
|
|
|
|
}
|
|
|
|
$.ajax({ url: urlTotal,
|
|
|
|
success: function() {
|
|
|
|
// Back to base
|
|
|
|
location.href = urlTotal;
|
|
|
|
},
|
|
|
|
error: function(status, text) {
|
|
|
|
failureCounter = failureCounter+1;
|
|
|
|
// Too many failuers and we give up
|
|
|
|
if(failureCounter >= 6) {
|
|
|
|
// If the port has changed 'Access-Control-Allow-Origin' header will not allow
|
|
|
|
// us to check if the server is back up. So after 7 failures we redirect
|
|
|
|
// anyway in the hopes it works anyway..
|
|
|
|
location.href = urlTotal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}, 4000)
|
|
|
|
|
|
|
|
// Exception if we go from HTTPS to HTTP
|
|
|
|
// (this is not allowed by browsers and all of the above will be ignored)
|
|
|
|
if(window.location.protocol != urlProtocol) {
|
|
|
|
// Saftey redirect after 20 sec
|
|
|
|
setTimeout(function() {
|
|
|
|
location.href = urlTotal;
|
|
|
|
}, 20*1000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove obfusication
|
|
|
|
function removeObfuscation() {
|
|
|
|
$('input[data-hide]').each(function(index, objInput) {
|
|
|
|
$(objInput).attr('name', $(objInput).data('hide'))
|
|
|
|
})
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add coloring to rows (shorthand function)
|
|
|
|
function addRowColor() {
|
|
|
|
// Have to do it seperate for each section
|
|
|
|
$('.section').each(function(i, elmn) {
|
|
|
|
$(elmn).find('.field-pair:visible').removeClass('even').filter(':even').addClass('even')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
$(document).ready(function () {
|
|
|
|
/**
|
|
|
|
Restart function
|
|
|
|
**/
|
|
|
|
$('.sabnzbd_restart').click(function () {
|
|
|
|
$('.sabnzbd_restart').each(function () {
|
|
|
|
$(this).attr("disabled", "disabled");
|
|
|
|
});
|
|
|
|
if (confirm(configTranslate.explainRestart.replace(/\<br(\s*\/|)\>/g, '\n'))) {
|
|
|
|
$(this).attr("value", configTranslate.wizzardRestart);
|
|
|
|
// Let us leave!
|
|
|
|
formWasSubmitted = true;
|
|
|
|
do_restart();
|
|
|
|
}
|
|
|
|
$('.sabnzbd_restart').each(function () {
|
|
|
|
$(this).removeAttr("disabled");
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
Submit the form
|
|
|
|
**/
|
|
|
|
$('.fullform').ajaxForm({
|
|
|
|
datatype: 'json',
|
|
|
|
// But first remove Obfuscation!
|
|
|
|
beforeSerialize: removeObfuscation,
|
|
|
|
beforeSubmit: function () {
|
|
|
|
$('.saveButton').each(function () {
|
|
|
|
$(this).attr("disabled", "disabled").removeClass('btn-danger').html('<span class="glyphicon glyphicon-transfer"></span> ' + configTranslate.saving);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
success: function (json) {
|
|
|
|
if (json.error) {
|
|
|
|
$('#config_err_msg').text(json.error);
|
|
|
|
alert(json.error)
|
|
|
|
config_failure()
|
|
|
|
} else if(json.value && json.value.restart_req) {
|
|
|
|
// Trigger restart question
|
|
|
|
if(confirm(configTranslate.needRestart + "\n" + configTranslate.buttonRestart + " SABnzbd?")) {
|
|
|
|
// No more questions
|
|
|
|
do_restart();
|
|
|
|
} else {
|
|
|
|
$('#config_err_msg').text(" ");
|
|
|
|
setTimeout(config_success, 1000);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$('#config_err_msg').text(" ");
|
|
|
|
setTimeout(config_success, 1000);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error: function () {
|
|
|
|
config_failure()
|
|
|
|
},
|
|
|
|
timeout: 3000
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
Form changes tracking
|
|
|
|
**/
|
|
|
|
$(document).on("submit", "form", function(event){
|
|
|
|
// Let us leave!
|
|
|
|
formWasSubmitted = true;
|
|
|
|
formHasChanged = false;
|
|
|
|
});
|
|
|
|
$('#content').on('change', 'form input[type!="submit"][type!="button"], form select, form textarea', function (e) {
|
|
|
|
formHasChanged = true;
|
|
|
|
formWasSubmitted = false;
|
|
|
|
});
|
|
|
|
window.onbeforeunload = function (e) {
|
|
|
|
if (formHasChanged && !formWasSubmitted) {
|
|
|
|
var message = configTranslate.confirmLeave, e = e || window.event;
|
|
|
|
if (e) {
|
|
|
|
e.returnValue = message;
|
|
|
|
}
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix for touch devices needing double click on the menu
|
|
|
|
$('.navbar-nav li a').on('touchstart', function(e) {
|
|
|
|
$(this).click()
|
|
|
|
})
|
|
|
|
|
|
|
|
// Add hover to checkboxes (can't do it with CSS)
|
|
|
|
$('input[type="checkbox"]').siblings('label').addClass('config-hover')
|
|
|
|
$('input[type="checkbox"]').parents('label').addClass('config-hover')
|
|
|
|
|
|
|
|
// Disable sections
|
|
|
|
var checkDisabled = '#rating_enable, #enable_tv_sorting, #enable_movie_sorting, #enable_date_sorting'
|
|
|
|
|
|
|
|
$(checkDisabled).on('change', function() {
|
|
|
|
$(this).parent().nextAll().toggleClass('disabled')
|
|
|
|
}).each(function() {
|
|
|
|
if(!$(this).is(':checked')) {
|
|
|
|
$(this).parent().nextAll().addClass('disabled')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Advanced or not?
|
|
|
|
$('.advanced-button').on('change', function(event){
|
|
|
|
localStorage.setItem('advanced-settings', !$('.advanced-settings').is(':visible'))
|
|
|
|
$('.advanced-settings').toggle()
|
|
|
|
addRowColor()
|
|
|
|
})
|
|
|
|
if(localStorage.getItem('advanced-settings') == 'true') {
|
|
|
|
$('.advanced-settings').show()
|
|
|
|
$('#advanced-settings-button').prop('checked', true)
|
|
|
|
addRowColor()
|
|
|
|
}
|
|
|
|
addRowColor()
|
|
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SEARCH FUNCTIONALITY
|
|
|
|
*/
|
|
|
|
// Make :contains() case-insensitive
|
|
|
|
$.expr[":"].contains = $.expr.createPseudo(function(arg) {
|
|
|
|
return function( elem ) {
|
|
|
|
return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create list of pages to check and empty contain for results
|
|
|
|
var arrPages = ['general', 'folders', 'switches', 'sorting', 'notify', 'special']
|
|
|
|
var pagesContainer = new Array(arrPages.length);
|
|
|
|
|
|
|
|
// Add trigger to focus on the field and load the results
|
|
|
|
$(document).ready(function() {
|
|
|
|
$('#search-menu').on('shown.bs.dropdown', function(event) {
|
|
|
|
// Focus so easy typing
|
|
|
|
$('#search-box').focus()
|
|
|
|
// Load things to search if we haven't yet
|
|
|
|
if(!pagesContainer[0]) {
|
|
|
|
$.each(arrPages, function(index, page) {
|
|
|
|
$.get(rootURL + 'config/' + page + '/', function(data) {
|
|
|
|
pagesContainer[index] = $(data).find('label')
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// For the scrolling
|
|
|
|
// *only* if we have anchor on the url
|
|
|
|
if(window.location.hash) {
|
|
|
|
// Sometimes the ID is non-existing
|
|
|
|
try {
|
|
|
|
// Could be an Advanced setting
|
|
|
|
if(!$(window.location.hash).is(':visible')) {
|
|
|
|
// Show advanced settings, but don't save in localStorage
|
|
|
|
$('.advanced-settings').toggle()
|
|
|
|
}
|
|
|
|
// smooth scroll to the anchor id
|
|
|
|
$('html, body').animate({
|
|
|
|
scrollTop: $(window.location.hash).offset().top -100 + 'px'
|
|
|
|
}, 750, 'swing');
|
|
|
|
setTimeout(function() {
|
|
|
|
$(window.location.hash).focus()
|
|
|
|
}, 750)
|
|
|
|
} catch(err) {}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Don't go too fast
|
|
|
|
var searchTimeout
|
|
|
|
function doConfigSearch(value) {
|
|
|
|
// Cancel previous
|
|
|
|
clearTimeout(searchTimeout)
|
|
|
|
// Build new search
|
|
|
|
var searchTerm = $(value).val().replace('"', '\"')
|
|
|
|
var searchOutput = $('#search-dropdown')
|
|
|
|
|
|
|
|
// Build new search
|
|
|
|
searchTimeout = setTimeout(function() {
|
|
|
|
// Clear the output
|
|
|
|
searchOutput.find('li:not(:first)').remove()
|
|
|
|
// Anything to search for?
|
|
|
|
if (searchTerm.length < 2) return
|
|
|
|
// Find some results!
|
|
|
|
$.each(pagesContainer, function(page_index, results) {
|
|
|
|
// Get the matches
|
|
|
|
var subResults = results.filter(':contains("'+searchTerm+'")')
|
|
|
|
if(subResults.length > 0) {
|
|
|
|
// Add the section
|
|
|
|
searchOutput.append('<li class="divider"></li>')
|
|
|
|
searchOutput.append('<li class="dropdown-header">'+configTranslate.searchPages[page_index]+'</li>')
|
|
|
|
$.each(subResults, function(index, result) {
|
|
|
|
searchOutput.append('<li><a href="'+rootURL + 'config/' + arrPages[page_index] + '/#' + $(result).attr('for') +'">'+$(result).text()+'</a></li>')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}, 200)
|
|
|
|
}
|