diff options
Diffstat (limited to 'module')
17 files changed, 327 insertions, 103 deletions
| diff --git a/module/PluginManager.py b/module/PluginManager.py index dac857059..ea4b7cdb3 100644 --- a/module/PluginManager.py +++ b/module/PluginManager.py @@ -392,7 +392,7 @@ class PluginManager:      def getCategory(self, plugin):          if plugin in self.plugins["addons"]: -            return self.plugins["addons"][plugin] or "addon" +            return self.plugins["addons"][plugin].category or "addon"      def loadIcon(self, name):          """ load icon for single plugin, base64 encoded""" diff --git a/module/api/ConfigApi.py b/module/api/ConfigApi.py index 309400808..d5577f7c3 100644 --- a/module/api/ConfigApi.py +++ b/module/api/ConfigApi.py @@ -83,11 +83,14 @@ class ConfigApi(ApiComponent):          :rtype: list of PluginInfo          """          # TODO: filter user_context / addons when not allowed -        return [ConfigInfo(name, config.name, config.description, +        plugins = [ConfigInfo(name, config.name, config.description,                             self.core.pluginManager.getCategory(name),                             self.core.pluginManager.isUserPlugin(name))                  for name, config, values in self.core.config.iterSections(self.user)] + +        return plugins +      @RequirePerm(Permission.Plugins)      def loadConfig(self, name):          """Get complete config options for desired section diff --git a/module/web/static/css/default/settings.less b/module/web/static/css/default/settings.less index 2501e2d0d..44eeddc5f 100644 --- a/module/web/static/css/default/settings.less +++ b/module/web/static/css/default/settings.less @@ -61,4 +61,32 @@      padding-left: 200px;
    }
 +}
 +
 +/*
 +  Plugin select
 +*/
 +
 +.plugin-select {
 +  background-position: left 2px;
 +  background-repeat: no-repeat;
 +  background-size: 20px 20px;
 +  padding-left: 24px;
 +
 +  font-weight: bold;
 +  span {
 +    line-height: 14px;
 +    font-size: small;
 +    font-weight: normal;
 +  }
 +
 +}
 +
 +.logo-select {
 +  width: 20px;
 +  height: 20px;
 +}
 +
 +.select2-container {
 +  min-width: 206px; // same as other input fields
  }
\ No newline at end of file diff --git a/module/web/static/css/select2.css b/module/web/static/css/select2.css index 1ff2abb1b..6cd945dbc 100644..100755 --- a/module/web/static/css/select2.css +++ b/module/web/static/css/select2.css @@ -1,5 +1,5 @@  /* -Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013 +Version: 3.3.2 Timestamp: Mon Mar 25 12:14:18 PDT 2013  */  .select2-container {      position: relative; @@ -7,7 +7,7 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013      /* inline-block for ie7 */      zoom: 1;      *display: inline; -    vertical-align: top; +    vertical-align: middle;  }  .select2-container, @@ -105,7 +105,7 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013      text-decoration: none;      border: 0; -    background: url('select2.png') right top no-repeat; +    background: url('../img/select2.png') right top no-repeat;      cursor: pointer;      outline: 0;  } @@ -119,7 +119,11 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013      left: 0;      top: 0;      z-index: 9998; +    background-color: #fff;      opacity: 0; +    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* works in IE 8 */ +        filter: "alpha(opacity=0)"; /* expected to work in IE 8 */ +        filter: alpha(opacity=0); /* IE 4-7 */  }  .select2-drop { @@ -188,7 +192,7 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013      display: block;      width: 100%;      height: 100%; -    background: url('select2.png') no-repeat 0 1px; +    background: url('../img/select2.png') no-repeat 0 1px;  }  .select2-search { @@ -231,13 +235,13 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013         -moz-box-shadow: none;              box-shadow: none; -    background: #fff url('select2.png') no-repeat 100% -22px; -    background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); -    background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); -    background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); -    background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); -    background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); -    background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%); +    background: #fff url('../img/select2.png') no-repeat 100% -22px; +    background: url('../img/select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); +    background: url('../img/select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); +    background: url('../img/select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);  }  .select2-drop.select2-drop-above .select2-search input { @@ -245,13 +249,13 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013  }  .select2-search input.select2-active { -    background: #fff url('select2-spinner.gif') no-repeat 100%; -    background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); -    background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); -    background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); -    background: url('select2-spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); -    background: url('select2-spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); -    background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%); +    background: #fff url('../img/select2-spinner.gif') no-repeat 100%; +    background: url('../img/select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); +    background: url('../img/select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2-spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); +    background: url('../img/select2-spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); +    background: url('../img/select2-spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%);  }  .select2-container-active .select2-choice, @@ -335,6 +339,8 @@ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013      margin: 0;      cursor: pointer; +    min-height: 1em; +      -webkit-touch-callout: none;        -webkit-user-select: none;         -khtml-user-select: none; @@ -390,7 +396,7 @@ disabled look for disabled choices in the results dropdown  }  .select2-more-results.select2-active { -    background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%; +    background: #f4f4f4 url('../img/select2-spinner.gif') no-repeat 100%;  }  .select2-more-results { @@ -482,7 +488,7 @@ disabled look for disabled choices in the results dropdown  }  .select2-container-multi .select2-choices .select2-search-field input.select2-active { -    background: #fff url('select2-spinner.gif') no-repeat 100% !important; +    background: #fff url('../img/select2-spinner.gif') no-repeat 100% !important;  }  .select2-default { @@ -544,7 +550,7 @@ disabled look for disabled choices in the results dropdown      font-size: 1px;      outline: none; -    background: url('select2.png') right top no-repeat; +    background: url('../img/select2.png') right top no-repeat;  }  .select2-container-multi .select2-search-choice-close { @@ -585,15 +591,21 @@ disabled look for disabled choices in the results dropdown  }  .select2-offscreen { +    border: 0; +    clip: rect(0 0 0 0); +    height: 1px; +    margin: -1px; +    overflow: hidden; +    padding: 0;      position: absolute; -    left: -10000px; +    width: 1px;  }  /* Retina-ize icons */  @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi)  {    .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b { -      background-image: url('select2x2.png') !important; +      background-image: url('../img/select2x2.png') !important;        background-repeat: no-repeat !important;        background-size: 60px 40px !important;    } diff --git a/module/web/static/img/select2-spinner.gif b/module/web/static/img/select2-spinner.gifBinary files differ new file mode 100755 index 000000000..5b33f7e54 --- /dev/null +++ b/module/web/static/img/select2-spinner.gif diff --git a/module/web/static/img/select2.png b/module/web/static/img/select2.pngBinary files differ new file mode 100755 index 000000000..1d804ffb9 --- /dev/null +++ b/module/web/static/img/select2.png diff --git a/module/web/static/img/select2x2.png b/module/web/static/img/select2x2.pngBinary files differ new file mode 100755 index 000000000..4bdd5c961 --- /dev/null +++ b/module/web/static/img/select2x2.png diff --git a/module/web/static/js/config.js b/module/web/static/js/config.js index 474a77dc3..d920698c4 100644 --- a/module/web/static/js/config.js +++ b/module/web/static/js/config.js @@ -10,7 +10,7 @@ require.config({          transit: "libs/jquery.transit-0.9.9",          animate: "libs/jquery.animate-enhanced-0.99",          omniwindow: "libs/jquery.omniwindow", -        select2: "libs/select2-3.3.1", +        select2: "libs/select2-3.3.2",          bootstrap: "libs/bootstrap-2.3",          underscore: "libs/lodash-1.0.1", diff --git a/module/web/static/js/default.js b/module/web/static/js/default.js index 44c8842fa..62b2ef9b6 100644 --- a/module/web/static/js/default.js +++ b/module/web/static/js/default.js @@ -14,7 +14,7 @@ define('default', ['require', 'jquery', 'app', 'views/headerView', 'views/dashbo          };          App.initSettingsView = function() { -            require(['views/settingsView'], function(SettingsView) { +            require(['views/settings/settingsView'], function(SettingsView) {                  App.settingsView = new SettingsView();                  App.settingsView.render();              }); diff --git a/module/web/static/js/libs/select2-3.3.1.js b/module/web/static/js/libs/select2-3.3.2.js index 8be2c7e9f..093d7fbd7 100644..100755 --- a/module/web/static/js/libs/select2-3.3.1.js +++ b/module/web/static/js/libs/select2-3.3.2.js @@ -1,7 +1,7 @@  /*  Copyright 2012 Igor Vaynberg -Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013 +Version: 3.3.2 Timestamp: Mon Mar 25 12:14:18 PDT 2013  This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU  General Public License version 2 (the "GPL License"). You may choose either license to govern your @@ -118,8 +118,8 @@ the specific language governing permissions and limitations under the Apache Lic          if (a === b) return true;          if (a === undefined || b === undefined) return false;          if (a === null || b === null) return false; -        if (a.constructor === String) return a === b+''; -        if (b.constructor === String) return b === a+''; +        if (a.constructor === String) return a+'' === b+''; // IE requires a+'' instead of just a +        if (b.constructor === String) return b+'' === a+''; // IE requires b+'' instead of just b          return false;      } @@ -229,20 +229,22 @@ the specific language governing permissions and limitations under the Apache Lic              $el.focus(); -            /* after the focus is set move the caret to the end, necessary when we val() -                just before setting focus */ -            if(el.setSelectionRange) -            { -                el.setSelectionRange(pos, pos); -            } -            else if (el.createTextRange) { -                range = el.createTextRange(); -                range.collapse(true); -                range.moveEnd('character', pos); -                range.moveStart('character', pos); -                range.select(); -            } +            /* make sure el received focus so we do not error out when trying to manipulate the caret. +                sometimes modals or others listeners may steal it after its set */ +            if ($el.is(":visible") && el === document.activeElement) { +                /* after the focus is set move the caret to the end, necessary when we val() +                    just before setting focus */ +                if(el.setSelectionRange) +                { +                    el.setSelectionRange(pos, pos); +                } +                else if (el.createTextRange) { +                    range = el.createTextRange(); +                    range.collapse(false); +                    range.select(); +                } +            }          }, 0);      } @@ -282,7 +284,8 @@ the specific language governing permissions and limitations under the Apache Lic          var classes, replacements = [], adapted;          classes = dest.attr("class"); -        if (typeof classes === "string") { +        if (classes) { +            classes = '' + classes; // for IE which returns object              $(classes.split(" ")).each2(function() {                  if (this.indexOf("select2-") === 0) {                      replacements.push(this); @@ -290,11 +293,12 @@ the specific language governing permissions and limitations under the Apache Lic              });          }          classes = src.attr("class"); -        if (typeof classes === "string") { +        if (classes) { +            classes = '' + classes; // for IE which returns object              $(classes.split(" ")).each2(function() {                  if (this.indexOf("select2-") !== 0) {                      adapted = adapter(this); -                    if (typeof adapted === "string" && adapted.length > 0) { +                    if (adapted) {                          replacements.push(this);                      }                  } @@ -790,7 +794,7 @@ the specific language governing permissions and limitations under the Apache Lic                  if ("tags" in opts) {                      throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");                  } -                opts.tags=opts.element.attr("data-select2-tags"); +                opts.tags=opts.element.data("select2Tags");              }              if (select) { @@ -1119,9 +1123,7 @@ the specific language governing permissions and limitations under the Apache Lic              this.dropdown.attr("id", "select2-drop");              // show the elements -            mask.css({ -                width: document.documentElement.scrollWidth, -                height: document.documentElement.scrollHeight}); +            mask.css(_makeMaskCss());              mask.show();              this.dropdown.show();              this.positionDropdown(); @@ -1134,14 +1136,19 @@ the specific language governing permissions and limitations under the Apache Lic              var that = this;              this.container.parents().add(window).each(function () {                  $(this).bind(resize+" "+scroll+" "+orient, function (e) { -                    $("#select2-drop-mask").css({ -                        width:document.documentElement.scrollWidth, -                        height:document.documentElement.scrollHeight}); +                    $("#select2-drop-mask").css(_makeMaskCss());                      that.positionDropdown();                  });              });              this.focusSearch(); + +            function _makeMaskCss() { +                return { +                    width  : Math.max(document.documentElement.scrollWidth,  $(window).width()), +                    height : Math.max(document.documentElement.scrollHeight, $(window).height()) +                } +            }          },          // abstract @@ -1164,7 +1171,7 @@ the specific language governing permissions and limitations under the Apache Lic              this.container.removeClass("select2-dropdown-open");              this.results.empty();              this.clearSearch(); - +            this.search.removeClass("select2-active");              this.opts.element.trigger($.Event("close"));          }, @@ -1315,6 +1322,7 @@ the specific language governing permissions and limitations under the Apache Lic                      self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context}); +                    self.postprocessResults(data, false, false);                      if (data.more===true) {                          more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1)); @@ -1341,15 +1349,25 @@ the specific language governing permissions and limitations under the Apache Lic           */          // abstract          updateResults: function (initial) { -            var search = this.search, results = this.results, opts = this.opts, data, self=this, input; +            var search = this.search, +                results = this.results, +                opts = this.opts, +                data, +                self = this, +                input, +                term = search.val(), +                lastTerm=$.data(this.container, "select2-last-term"); + +            // prevent duplicate queries against the same term +            if (initial !== true && lastTerm && equal(term, lastTerm)) return; + +            $.data(this.container, "select2-last-term", term);              // if the search is currently hidden we do not alter the results              if (initial !== true && (this.showSearchInput === false || !this.opened())) {                  return;              } -            search.addClass("select2-active"); -              function postRender() {                  results.scrollTop(0);                  search.removeClass("select2-active"); @@ -1378,9 +1396,6 @@ the specific language governing permissions and limitations under the Apache Lic                  }                  return;              } -            else if (opts.formatSearching() && initial===true) { -                render("<li class='select2-searching'>" + opts.formatSearching() + "</li>"); -            }              if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {                  if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) { @@ -1391,6 +1406,12 @@ the specific language governing permissions and limitations under the Apache Lic                  return;              } +            if (opts.formatSearching && this.findHighlightableChoices().length === 0) { +                render("<li class='select2-searching'>" + opts.formatSearching() + "</li>"); +            } + +            search.addClass("select2-active"); +              // give the tokenizer a chance to pre-process the input              input = this.tokenize();              if (input != undefined && input != null) { @@ -1409,7 +1430,10 @@ the specific language governing permissions and limitations under the Apache Lic                  var def; // default choice                  // ignore a response if the select2 has been closed before it was received -                if (!this.opened()) return; +                if (!this.opened()) { +                    this.search.removeClass("select2-active"); +                    return; +                }                  // save context, if any                  this.context = (data.context===undefined) ? null : data.context; @@ -1442,6 +1466,8 @@ the specific language governing permissions and limitations under the Apache Lic                  this.postprocessResults(data, initial);                  postRender(); + +                this.opts.element.trigger({ type: "loaded", data:data });              })});          }, @@ -1635,6 +1661,11 @@ the specific language governing permissions and limitations under the Apache Lic              this.focusser = container.find(".select2-focusser"); +            // rewrite labels from original element to focusser +            this.focusser.attr("id", "s2id_autogen"+nextUid()); +            $("label[for='" + this.opts.element.attr("id") + "']") +                .attr('for', this.focusser.attr('id')); +              this.search.bind("keydown", this.bind(function (e) {                  if (!this.enabled) return; @@ -1662,6 +1693,16 @@ the specific language governing permissions and limitations under the Apache Lic                  }              })); +            this.search.bind("blur", this.bind(function(e) { +                // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown. +                // without this the search field loses focus which is annoying +                if (document.activeElement === this.body().get(0)) { +                    window.setTimeout(this.bind(function() { +                        this.search.focus(); +                    }), 0); +                } +            })); +              this.focusser.bind("keydown", this.bind(function (e) {                  if (!this.enabled) return; @@ -1747,15 +1788,19 @@ the specific language governing permissions and limitations under the Apache Lic          },          // single -        clear: function() { +        clear: function(triggerChange) {              var data=this.selection.data("select2-data"); -            this.opts.element.val(""); -            this.selection.find("span").empty(); -            this.selection.removeData("select2-data"); -            this.setPlaceholder(); +            if (data) { // guard against queued quick consecutive clicks +                this.opts.element.val(""); +                this.selection.find("span").empty(); +                this.selection.removeData("select2-data"); +                this.setPlaceholder(); -            this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data }); -            this.triggerChange({removed:data}); +                if (triggerChange !== false){ +                    this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data }); +                    this.triggerChange({removed:data}); +                } +            }          },          /** @@ -1795,13 +1840,18 @@ the specific language governing permissions and limitations under the Apache Lic                  // install default initSelection when applied to hidden input and data is local                  opts.initSelection = opts.initSelection || function (element, callback) {                      var id = element.val(); -                    //search in data by id +                    //search in data by id, storing the actual matching item +                    var match = null;                      opts.query({                          matcher: function(term, text, el){ -                            return equal(id, opts.id(el)); +                            var is_match = equal(id, opts.id(el)); +                            if (is_match) { +                                match = el; +                            } +                            return is_match;                          }, -                        callback: !$.isFunction(callback) ? $.noop : function(filtered) { -                            callback(filtered.results.length ? filtered.results[0] : null); +                        callback: !$.isFunction(callback) ? $.noop : function() { +                            callback(match);                          }                      });                  }; @@ -1840,7 +1890,7 @@ the specific language governing permissions and limitations under the Apache Lic          },          // single -        postprocessResults: function (data, initial) { +        postprocessResults: function (data, initial, noHighlightUpdate) {              var selected = 0, self = this, showSearchInput = true;              // find the selected element in the result list @@ -1853,8 +1903,9 @@ the specific language governing permissions and limitations under the Apache Lic              });              // and highlight it - -            this.highlight(selected); +            if (noHighlightUpdate !== false) { +                this.highlight(selected); +            }              // hide the search box if this is the first we got the results and there are a few of them @@ -1930,7 +1981,7 @@ the specific language governing permissions and limitations under the Apache Lic                  this.select                      .val(val)                      .find(":selected").each2(function (i, elm) { -                        data = {id: elm.attr("value"), text: elm.text()}; +                        data = {id: elm.attr("value"), text: elm.text(), element: elm.get(0)};                          return false;                      });                  this.updateSelection(data); @@ -1944,7 +1995,7 @@ the specific language governing permissions and limitations under the Apache Lic                  }                  // val is an id. !val is true for [undefined,null,'',0] - 0 is legal                  if (!val && val !== 0) { -                    this.clear(); +                    this.clear(triggerChange);                      if (triggerChange) {                          this.triggerChange();                      } @@ -2028,15 +2079,20 @@ the specific language governing permissions and limitations under the Apache Lic                  // install default initSelection when applied to hidden input and data is local                  opts.initSelection = opts.initSelection || function (element, callback) {                      var ids = splitVal(element.val(), opts.separator); -                    //search in data by array of ids +                    //search in data by array of ids, storing matching items in a list +                    var matches = [];                      opts.query({                          matcher: function(term, text, el){ -                            return $.grep(ids, function(id) { +                            var is_match = $.grep(ids, function(id) {                                  return equal(id, opts.id(el));                              }).length; +                            if (is_match) { +                                matches.push(el); +                            } +                            return is_match;                          }, -                        callback: !$.isFunction(callback) ? $.noop : function(filtered) { -                            callback(filtered.results); +                        callback: !$.isFunction(callback) ? $.noop : function() { +                            callback(matches);                          }                      });                  }; @@ -2053,6 +2109,11 @@ the specific language governing permissions and limitations under the Apache Lic              this.searchContainer = this.container.find(".select2-search-field");              this.selection = selection = this.container.find(selector); +            // rewrite labels from original element to focusser +            this.search.attr("id", "s2id_autogen"+nextUid()); +            $("label[for='" + this.opts.element.attr("id") + "']") +                .attr('for', this.search.attr('id')); +              this.search.bind("input paste", this.bind(function() {                  if (!this.enabled) return;                  if (!this.opened()) { @@ -2121,6 +2182,12 @@ the specific language governing permissions and limitations under the Apache Lic                      // prevent the page from scrolling                      killEvent(e);                  } + +                if (e.which === KEY.ENTER) { +                    // prevent form from being submitted +                    killEvent(e); +                } +              }));              this.search.bind("keyup", this.bind(this.resizeSearch)); @@ -2204,7 +2271,8 @@ the specific language governing permissions and limitations under the Apache Lic              if (placeholder !== undefined  && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {                  this.search.val(placeholder).addClass("select2-default");                  // stretch the search box to full width of the container so as much of the placeholder is visible as possible -                this.resizeSearch(); +                // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944 +                this.search.width(this.getMaxSearchWidth());              } else {                  this.search.val("").width(10);              } @@ -2219,10 +2287,11 @@ the specific language governing permissions and limitations under the Apache Lic          // multi          opening: function () { +            this.clearPlaceholder(); // should be done before super so placeholder is not used to search +            this.resizeSearch(); +              this.parent.opening.apply(this, arguments); -            this.clearPlaceholder(); -			this.resizeSearch();              this.focusSearch();              this.opts.element.trigger($.Event("open")); @@ -2238,7 +2307,7 @@ the specific language governing permissions and limitations under the Apache Lic          focus: function () {              this.close();              this.search.focus(); -            this.opts.element.triggerHandler("focus"); +            //this.opts.element.triggerHandler("focus");          },          // multi @@ -2266,6 +2335,7 @@ the specific language governing permissions and limitations under the Apache Lic              self.postprocessResults();          }, +        // multi          tokenize: function() {              var input = this.search.val();              input = this.opts.tokenizer(input, this.data(), this.bind(this.onSelect), this.opts); @@ -2293,7 +2363,7 @@ the specific language governing permissions and limitations under the Apache Lic                  if (this.countSelectableResults()>0) {                      this.search.width(10);                      this.resizeSearch(); -                    if (this.val().length >= this.getMaximumSelectionSize()) { +                    if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {                          // if we reached max selection size repaint the results so choices                          // are replaced with the max selection reached message                          this.updateResults(true); @@ -2432,6 +2502,11 @@ the specific language governing permissions and limitations under the Apache Lic          },          // multi +        getMaxSearchWidth: function() { +            return this.selection.width() - getSideBorderPadding(this.search); +        }, + +        // multi          resizeSearch: function () {              var minimumWidth, left, maxWidth, containerLeft, searchWidth,              	sideBorderPadding = getSideBorderPadding(this.search); @@ -2656,7 +2731,7 @@ the specific language governing permissions and limitations under the Apache Lic          formatResultCssClass: function(data) {return undefined;},          formatNoMatches: function () { return "No matches found"; },          formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1? "" : "s"); }, -        formatInputTooLong: function (input, max) { var n = input.length - max; return "Please enter " + n + " less character" + (n == 1? "" : "s"); }, +        formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); },          formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },          formatLoadMore: function (pageNumber) { return "Loading more results..."; },          formatSearching: function () { return "Searching..."; }, @@ -2666,7 +2741,7 @@ the specific language governing permissions and limitations under the Apache Lic          maximumSelectionSize: 0,          id: function (e) { return e.id; },          matcher: function(term, text) { -            return text.toUpperCase().indexOf(term.toUpperCase()) >= 0; +            return (''+text).toUpperCase().indexOf((''+term).toUpperCase()) >= 0;          },          separator: ",",          tokenSeparators: [], @@ -2682,7 +2757,7 @@ the specific language governing permissions and limitations under the Apache Lic                  "/": '/'              }; -            return String(markup).replace(/[&<>"'/\\]/g, function (match) { +            return String(markup).replace(/[&<>"'\/\\]/g, function (match) {                      return replace_map[match[0]];              });          }, diff --git a/module/web/static/js/views/abstract/modalView.js b/module/web/static/js/views/abstract/modalView.js index 1e45e942b..170681f06 100644 --- a/module/web/static/js/views/abstract/modalView.js +++ b/module/web/static/js/views/abstract/modalView.js @@ -83,7 +83,7 @@ define(['jquery', 'backbone', 'underscore', 'omniwindow'], function($, Backbone,          },          renderContent: function() { -            return {content: $('<h1>Content!</h1>').html()}; +            return {};          },          show: function() { diff --git a/module/web/static/js/views/dashboard/fileView.js b/module/web/static/js/views/dashboard/fileView.js index c673041b5..5d687a111 100644 --- a/module/web/static/js/views/dashboard/fileView.js +++ b/module/web/static/js/views/dashboard/fileView.js @@ -77,7 +77,7 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes', 'views/abst              },              progress_changed: function() { -                if(!this.model.isDownload()) +                if (!this.model.isDownload())                      return;                  if (this.model.get('download').status === Api.DownloadStatus.Downloading) { @@ -89,6 +89,10 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes', 'views/abst                      bar.width(this.model.get('progress') + '%');                      bar.html('  ' + formatTime(this.model.get('eta'))); +                } else if (this.model.get('download').status === Api.DownloadStatus.Waiting) { +                    this.$('.second').html( +                        "<i class='iconf-time'></i> " + formatTime(this.model.get('eta'))); +                  } else // Every else state can be renderred normally                      this.render(); diff --git a/module/web/static/js/views/configSectionView.js b/module/web/static/js/views/settings/configSectionView.js index 949493731..79f314309 100644 --- a/module/web/static/js/views/configSectionView.js +++ b/module/web/static/js/views/settings/configSectionView.js @@ -1,4 +1,4 @@ -define(['jquery', 'underscore', 'backbone', 'app', './abstract/itemView', './input/inputLoader'], +define(['jquery', 'underscore', 'backbone', 'app', '../abstract/itemView', '../input/inputLoader'],      function($, _, Backbone, App, itemView, load_input) {          // Renders settings over view page diff --git a/module/web/static/js/views/settings/pluginChooserModal.js b/module/web/static/js/views/settings/pluginChooserModal.js new file mode 100644 index 000000000..c7cdce244 --- /dev/null +++ b/module/web/static/js/views/settings/pluginChooserModal.js @@ -0,0 +1,66 @@ +define(['jquery', 'underscore', 'app', 'views/abstract/modalView', 'text!tpl/default/pluginChooserDialog.html', 'select2'], +    function($, _, App, modalView, template) { +        return modalView.extend({ + +            events: { +                'click .btn-add': 'add' +            }, +            template: _.compile(template), +            plugins: null, +            select: null, + +            initialize: function() { +                // Inherit parent events +                this.events = _.extend({}, modalView.prototype.events, this.events); +                var self = this; +                $.ajax(App.apiRequest('getAvailablePlugins', null, {success: function(data) { +                    self.plugins = data; +                    self.render(); +                } +                })); +            }, + +            onRender: function() { +                // TODO: could be a seperate input type if needed on multiple pages +                if (this.plugins) +                    this.select = this.$('#pluginSelect').select2({ +                        escapeMarkup: function(m) { +                            return m; +                        }, +                        formatResult: this.format, +                        formatSelection: this.formatSelection, +                        data: {results: this.plugins, text: function(item) { +                            return item.label; +                        }}, +                        id: function(item) { +                            return item.name; +                        } +                    }); +            }, + +            onShow: function() { +            }, + +            onHide: function() { +            }, + +            format: function(data) { +                var s = '<div class="plugin-select" style="background-image: url(icons/' + data.name + '">' + data.label; +                s += "<br><span>" + data.description + "<span></div>"; +                return s; +            }, + +            formatSelection: function(data) { +                return '<img class="logo-select" src="icons/' + data.name + '"> ' + data.label; +            }, + +            add: function(e) { +                e.stopPropagation(); +                if (this.select) { +                    var plugin = this.select.val(); +                    App.settingsView.openConfig(plugin); +                    this.hide(); +                } +            } +        }); +    });
\ No newline at end of file diff --git a/module/web/static/js/views/settingsView.js b/module/web/static/js/views/settings/settingsView.js index 3b8308f19..58507f51a 100644 --- a/module/web/static/js/views/settingsView.js +++ b/module/web/static/js/views/settings/settingsView.js @@ -4,18 +4,20 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ConfigHolder', './con          // Renders settings over view page          return Backbone.View.extend({ -            el: "#content", +            el: "body",              templateMenu: _.compile($("#template-menu").html()),              events: { -                'click .settings-menu li > a': 'change_section' +                'click .settings-menu li > a': 'change_section', +                'click .btn-add': 'choosePlugin'              },              menu: null,              content: null, +            modal: null, -            core_config: null, // It seems models are not needed -            plugin_config: null, +            coreConfig: null, // It seems collections are not needed +            pluginConfig: null,              // currently open configHolder              config: null, @@ -36,19 +38,19 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ConfigHolder', './con              refresh: function() {                  var self = this;                  $.ajax(App.apiRequest("getCoreConfig", null, {success: function(data) { -                    self.core_config = data; +                    self.coreConfig = data;                      self.render();                  }}));                  $.ajax(App.apiRequest("getPluginConfig", null, {success: function(data) { -                    self.plugin_config = data; +                    self.pluginConfig = data;                      self.render();                  }}));              },              render: function() {                  this.menu.html(this.templateMenu({ -                    core: this.core_config, -                    plugin: this.plugin_config +                    core: this.coreConfig, +                    plugin: this.pluginConfig                  }));              }, @@ -113,6 +115,7 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ConfigHolder', './con              change_section: function(e) {                  // TODO check for changes +                // TODO move this into render?                  var el = $(e.target).parent();                  var name = el.data("name"); @@ -121,6 +124,16 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ConfigHolder', './con                  this.menu.find("li.active").removeClass("active");                  el.addClass("active");                  e.preventDefault(); +            }, + +            choosePlugin: function(e){ +                var self = this; +                _.requireOnce(['views/settings/pluginChooserModal'], function(Modal) { +                    if (self.modal === null) +                        self.modal = new Modal(); + +                    self.modal.show(); +                });              }          }); diff --git a/module/web/templates/default/backbone/pluginChooserDialog.html b/module/web/templates/default/backbone/pluginChooserDialog.html new file mode 100755 index 000000000..02284d0e6 --- /dev/null +++ b/module/web/templates/default/backbone/pluginChooserDialog.html @@ -0,0 +1,23 @@ +{% extends 'default/backbone/modal.html' %} +{% block header %} +     Choose a plugin +{% endblock %} +{% block content %} +    <form class="form-horizontal" action="#" xmlns="http://www.w3.org/1999/html"> +    <legend> +        Please choose a plugin, which you want to configure +    </legend> +        <div class="control-group"> +            <label class="control-label" for="pluginSelect"> +                Plugin +            </label> +            <div class="controls"> +                <input type="hidden" id="pluginSelect"> +            </div> +        </div> +    </form> +{% endblock %} +{% block buttons %} +    <a href="#" class="btn btn-success btn-add">Add</a> +    <a href="#" class="btn btn-close">Close</a> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/settings.html b/module/web/templates/default/settings.html index ea570af0f..bee583dbf 100644 --- a/module/web/templates/default/settings.html +++ b/module/web/templates/default/settings.html @@ -58,9 +58,9 @@  {% endblock %}
  {% block actionbar %}
 -    {#    <ul class="actionbar nav nav-pills span9">#}
 -    {#    <li>Add Plugin</li>#}
 -    {#    </ul>#}
 +    <span class="span9">
 +        <button class="btn btn-small btn-blue btn-add">Add Plugin</button>
 +    </span>
  {% endblock %}
  {% block content %}
 | 
