Browse Source

HUE-2231 [fb] Make current directory selectable

Refactored templates (moved css to external file, cleaned up js, improved readability)
Updated handleSelect to toggle off select all text box when a box is toggled off
added checkbox to cwd
updated view data to add parent directory to list before cwd to ensure check boxes are grouped together in table layout
Paul McCaughtry 11 years ago
parent
commit
2209fca371

+ 127 - 0
apps/filebrowser/src/filebrowser/static/css/fb.css

@@ -0,0 +1,127 @@
+#fileArea {
+  overflow: auto;
+  background-color: #F5F5F5;
+  position: relative;
+}
+
+#fileArea.loading {
+  opacity: .7;
+}
+
+#loader {
+  position: fixed;
+  margin-top: 40px;
+  font-size: 50px;
+  text-align: center;
+  width: 140px;
+  height: 140px;
+  line-height: 140px;
+  -webkit-border-radius: 20px;
+  -moz-border-radius: 20px;
+  border-radius: 20px;
+}
+
+.binary {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  border: none;
+}
+
+pre a {
+  color: #444;
+  cursor: default;
+}
+
+pre a:hover {
+  color: #444;
+  text-decoration: none;
+}
+
+.fixed {
+  position: fixed;
+  top: 40px;
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+  -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.sortable {
+  cursor: pointer;
+}
+
+.file-row {
+  height: 37px;
+}
+
+.fileChooserModal {
+  padding: 14px;
+}
+
+.fileChooserModal .hueBreadcrumb {
+  margin: 0 0 18px !important;
+}
+
+.fieldError {
+  border-color: #B94A48 !important;
+}
+
+.pagination {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  background-color: #f5f5f5;
+  margin: 0;
+  border-top: 1px solid #e3e3e3;
+  -webkit-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  -moz-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  padding: 0px;
+}
+
+.pagination p {
+  padding-top: 10px;
+  padding-left: 10px;
+  margin: 0;
+}
+
+.pagination select {
+  margin-top: 4px;
+}
+
+.pagination ul {
+  margin-top: 14px;
+  margin-right: 20px;
+}
+
+.actionbar {
+  padding-top: 6px;
+  background-color: #FFFFFF;
+}
+
+.shadow {
+  -webkit-box-shadow: 0px 2px 3px rgba(50, 50, 50, 0.1);
+  -moz-box-shadow: 0px 2px 3px rgba(50, 50, 50, 0.1);
+  box-shadow: 0px 1px 2px rgba(50, 50, 50, 0.1);
+}
+
+.scrollable {
+  margin-bottom: 80px;
+}
+
+#jHueHdfsAutocomplete ul li {
+  cursor: pointer;
+}
+
+#jHueHdfsAutocomplete ul li:hover,  #jHueHdfsAutocomplete ul li.active {
+  color: #FFFFFF;
+  background: #338BB8;
+}
+
+#jHueHdfsAutocomplete .popover-content {
+  max-height: 200px;
+  overflow-y: auto;
+}

+ 297 - 355
apps/filebrowser/src/filebrowser/templates/display.mako

@@ -31,50 +31,7 @@
 ${ commonheader(_('%(filename)s - File Viewer') % dict(filename=truncate(filename)), 'filebrowser', user) | n,unicode }
 ${ commonheader(_('%(filename)s - File Viewer') % dict(filename=truncate(filename)), 'filebrowser', user) | n,unicode }
 ${ fb_components.menubar() }
 ${ fb_components.menubar() }
 
 
-<script src="/static/ext/js/jquery/plugins/jquery.visible.min.js" type="text/javascript" charset="utf-8"></script>
-
-<style type="text/css">
-  #fileArea {
-    overflow: auto;
-    background-color: #F5F5F5;
-    position: relative;
-  }
-
-  #fileArea.loading {
-    opacity: .7;
-  }
-
-  #loader {
-    position: fixed;
-    margin-top: 40px;
-    font-size: 50px;
-    text-align: center;
-    width: 140px;
-    height: 140px;
-    line-height: 140px;
-    -webkit-border-radius: 20px;
-    -moz-border-radius: 20px;
-    border-radius: 20px;
-  }
-
-  .binary {
-    font-family: "Courier New", Courier, monospace;
-  }
-
-  pre {
-    border: none;
-  }
-
-  pre a {
-    color: #444;
-    cursor: default;
-  }
-
-  pre a:hover {
-    color: #444;
-    text-decoration: none;
-  }
-</style>
+<link rel="stylesheet" type="text/css" href="/filebrowser/static/css/fb.css">
 
 
 <div class="container-fluid">
 <div class="container-fluid">
   <div class="row-fluid">
   <div class="row-fluid">
@@ -140,366 +97,351 @@ ${ fb_components.menubar() }
   </div>
   </div>
 </div>
 </div>
 
 
+<script src="/static/ext/js/jquery/plugins/jquery.visible.min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-
 <script type="text/javascript" charset="utf-8">
 <script type="text/javascript" charset="utf-8">
-
 <%
 <%
   MAX_ALLOWED_PAGES_PER_REQUEST = 255
   MAX_ALLOWED_PAGES_PER_REQUEST = 255
 %>
 %>
+(function() {
+  var pages = {};
 
 
-function displayViewModel(params) {
-  var self = this;
-
-  self.MAX_ALLOWED_PAGES_PER_REQUEST = ${MAX_ALLOWED_PAGES_PER_REQUEST};
-  self.MAX_PAGES_TO_ENABLE_SCROLLING = 300;
-  self.PAGES_PER_CHUNK = 50;
-
-  self.base_url = ko.observable(params.base_url);
-  self.compression = ko.observable(params.compression);
-  self.mode = ko.observable(params.mode);
-  self.begin = ko.observable(params.begin);
-  self.end = ko.observable(params.end);
-  self.length = ko.observable(params.length);
-  self.size = ko.observable(params.size);
-  self.page = ko.observable(1);
-  self.isLoading = ko.observable(true);
-
-  self.totalPages = ko.computed(function () {
-    return Math.max(Math.floor(self.size() / self.length()), 1);
-  });
-
-  self.upperPage = ko.observable(Math.min(self.totalPages(), 50));
-
-  self.begin = ko.computed(function () {
-    return (self.page() - 1) * self.length();
-  });
-
-  self.offset = ko.computed(function () {
-    return ((self.page() - 1) * self.length()) - 1;
-  });
-
-  self.url = ko.computed(function () {
-    return self.base_url()
-            + "?offset=" + self.offset()
-            + "&length=" + self.length()
-            + "&compression=" + self.compression()
-            + "&mode=" + self.mode();
-  });
+  var resizeText = function () {
+    $("#fileArea").height($(window).height() - $("#fileArea").offset().top - 26);
+    $("#loader").css("marginLeft", ($("#fileArea").width() - $("#loader").width()) / 2);
+  };
 
 
-  self.jsonParams = ko.computed(function () {
-    return {
-      offset: self.begin(),
-      length: self.length() * (self.upperPage() - self.page() + 1),
-      compression: self.compression(),
-      mode: self.mode()
+  var formatHex function = (number, padding) {
+    if ("undefined" != typeof number){
+      var _filler = "";
+      for (var i = 0; i < padding - 1; i++) {
+        _filler += "0";
+      }
+      return (_filler + number.toString(16)).substr(-padding);
     }
     }
-  });
-
-  self.toggleDisables = function () {
-    $(".next-page").removeClass("disabled");
-    $(".last-page").removeClass("disabled");
-    $(".first-page").removeClass("disabled");
-    $(".previous-page").removeClass("disabled");
+    return "";
+  };
 
 
-    if (self.page() == self.totalPages() || self.upperPage() == self.totalPages()) {
-      $(".next-page").addClass("disabled");
-      $(".last-page").addClass("disabled");
-    }
-    if (self.page() == 1) {
-      $(".first-page").addClass("disabled");
-      $(".previous-page").addClass("disabled");
+  var pageContent = function (page) {
+    var _html = "";
+    if ($("#page" + page).length == 0) {
+      if (pages[page] == null) {
+        _html += "<a id='page" + page + "'><div style='height: " + $("#fileArea").height() + "px'></div></a>";
+      } else {
+        _html += "<a id='page" + page + "'><div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div></a>";
+      }
+    } else {
+      if (pages[page] == null) {
+        $("#page" + page).html("<div style='height: " + $("#fileArea").height() + "px'></div>");
+      } else {
+        $("#page" + page).html("<div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div>");
+      }
     }
     }
+    return _html;
   };
   };
 
 
-  self.pageChanged = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (self.page() > self.totalPages()) {
-      self.page(self.totalPages());
-    }
-    if (self.page() < 1 || !$.isNumeric(self.page())) {
-      self.page(1);
+  var renderPages = function () {
+    var _html = "";
+    if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING) { // enable scrolling
+      for (var i = 1; i <= viewModel.totalPages(); i++) {
+        _html += pageContent(i);
+      }
+    } else {
+      _html += pageContent(viewModel.page());
     }
     }
-    if (self.page() > self.upperPage()) {
-      self.upperPage(self.page());
+    if (_html != "") {
+      $("#fileArea pre").html(_html);
     }
     }
-    changePage();
   };
   };
 
 
-  self.upperPageChanged = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (self.upperPage() > self.totalPages()) {
-      self.upperPage(self.totalPages());
-    }
-    if (self.upperPage() < 1 || !$.isNumeric(self.upperPage())) {
-      self.upperPage(1);
-    }
-    if (self.upperPage() < self.page()) {
-      self.page(self.upperPage());
-    }
-    if (self.upperPage() - self.page() > self.MAX_ALLOWED_PAGES_PER_REQUEST) {
-      self.upperPage(self.page() + self.MAX_ALLOWED_PAGES_PER_REQUEST);
-      $.jHueNotify.info("${_('Sorry, you cannot request for more than %s pages.' % MAX_ALLOWED_PAGES_PER_REQUEST)}");
-    }
-    changePage();
+  var getContent = function (callback) {
+    viewModel.isLoading(true);
+    var _baseUrl = "${url('filebrowser.views.view', path=path_enc)}";
+    $.getJSON(_baseUrl, viewModel.jsonParams(), function (data) {
+      if (data.view.contents != null) {
+        pages[viewModel.page()] = data.view.contents;
+        renderPages();
+      }
+      if (data.view.xxd != null) {
+        pages[viewModel.page()] = data.view.xxd;
+        var _html = "";
+        $(data.view.xxd).each(function (cnt, item) {
+          _html += "<tr><td>" + formatHex(item[0], 7) + ":&nbsp;</td><td>";
+          for (var i = 0; i < item[1].length; i++) {
+            _html += formatHex(item[1][i][0], 2) + " " + formatHex(item[1][i][1], 2) + " ";
+          }
+          _html += "</td><td>&nbsp;&nbsp;" + $("<span>").text(item[2]).html() + "</td></tr>";
+        });
+        $(".binary tbody").html(_html);
+      }
+      if (callback) {
+        callback();
+      }
+      viewModel.isLoading(false);
+    });
   };
   };
 
 
-  self.page.subscribe(function (value) {
-    self.toggleDisables();
-  });
+  var DisplayViewModel = function (params) {
+    var self = this;
 
 
-  self.upperPage.subscribe(function (value) {
-    self.toggleDisables();
-  });
+    var changePage = function () {
+      getContent(function () {
+        if (viewModel.totalPages() >= viewModel.MAX_PAGES_TO_ENABLE_SCROLLING || viewModel.mode() == "binary") {
+          window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
+          $("#fileArea").scrollTop(0);
+        } else {
+          window.location.hash = "#page" + viewModel.page();
+        }
+      });
+    };
+
+    self.MAX_ALLOWED_PAGES_PER_REQUEST = ${MAX_ALLOWED_PAGES_PER_REQUEST};
+    self.MAX_PAGES_TO_ENABLE_SCROLLING = 300;
+    self.PAGES_PER_CHUNK = 50;
+
+    self.base_url = ko.observable(params.base_url);
+    self.compression = ko.observable(params.compression);
+    self.mode = ko.observable(params.mode);
+    self.begin = ko.observable(params.begin);
+    self.end = ko.observable(params.end);
+    self.length = ko.observable(params.length);
+    self.size = ko.observable(params.size);
+    self.page = ko.observable(1);
+    self.isLoading = ko.observable(true);
+
+    self.totalPages = ko.computed(function () {
+      return Math.max(Math.floor(self.size() / self.length()), 1);
+    });
 
 
-  var changePage = function () {
-    getContent(function () {
-      if (viewModel.totalPages() >= viewModel.MAX_PAGES_TO_ENABLE_SCROLLING || viewModel.mode() == "binary") {
-        window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
-        $("#fileArea").scrollTop(0);
-      }
-      else {
-        window.location.hash = "#page" + viewModel.page();
+    self.upperPage = ko.observable(Math.min(self.totalPages(), 50));
+
+    self.begin = ko.computed(function () {
+      return (self.page() - 1) * self.length();
+    });
+
+    self.offset = ko.computed(function () {
+      return ((self.page() - 1) * self.length()) - 1;
+    });
+
+    self.url = ko.computed(function () {
+      return self.base_url()
+              + "?offset=" + self.offset()
+              + "&length=" + self.length()
+              + "&compression=" + self.compression()
+              + "&mode=" + self.mode();
+    });
+
+    self.jsonParams = ko.computed(function () {
+      return {
+        offset: self.begin(),
+        length: self.length() * (self.upperPage() - self.page() + 1),
+        compression: self.compression(),
+        mode: self.mode()
       }
       }
     });
     });
-  };
 
 
-  self.nextPage = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (!($(".next-page").hasClass("disabled"))) {
-      if (viewModel.page() == viewModel.upperPage()) {
-        viewModel.page(viewModel.page() + 1);
-        viewModel.upperPage(viewModel.upperPage() + 1);
+    self.toggleDisables = function () {
+      $(".next-page").removeClass("disabled");
+      $(".last-page").removeClass("disabled");
+      $(".first-page").removeClass("disabled");
+      $(".previous-page").removeClass("disabled");
+
+      if (self.page() == self.totalPages() || self.upperPage() == self.totalPages()) {
+        $(".next-page").addClass("disabled");
+        $(".last-page").addClass("disabled");
       }
       }
-      else {
-        var _difference = self.upperPage() - self.page();
-        self.page(self.upperPage() + 1);
-        self.upperPage(Math.min(self.page() + _difference, self.totalPages()));
+      if (self.page() == 1) {
+        $(".first-page").addClass("disabled");
+        $(".previous-page").addClass("disabled");
       }
       }
-      changePage();
-    }
-  };
+    };
 
 
-  self.previousPage = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (!($(".previous-page").hasClass("disabled"))) {
-      if (viewModel.page() == viewModel.upperPage()) {
-        viewModel.page(viewModel.page() - 1);
-        viewModel.upperPage(viewModel.upperPage() - 1);
+    self.pageChanged = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (self.page() > self.totalPages()) {
+        self.page(self.totalPages());
+      }
+      if (self.page() < 1 || !$.isNumeric(self.page())) {
+        self.page(1);
       }
       }
-      else {
-        var _difference = self.upperPage() - self.page();
-        self.upperPage(self.page() - 1);
-        self.page(Math.max(self.page() - _difference - 1, 1));
+      if (self.page() > self.upperPage()) {
+        self.upperPage(self.page());
       }
       }
       changePage();
       changePage();
-    }
-  };
+    };
 
 
-  self.lastPage = function () {
-    if (!($(".last-page").hasClass("disabled"))) {
-      var _page = viewModel.totalPages();
-      if (_page > 50) {
-        _page = Math.min(viewModel.totalPages() - viewModel.totalPages()%50 + 1, viewModel.totalPages());
+    self.upperPageChanged = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (self.upperPage() > self.totalPages()) {
+        self.upperPage(self.totalPages());
+      }
+      if (self.upperPage() < 1 || !$.isNumeric(self.upperPage())) {
+        self.upperPage(1);
+      }
+      if (self.upperPage() < self.page()) {
+        self.page(self.upperPage());
+      }
+      if (self.upperPage() - self.page() > self.MAX_ALLOWED_PAGES_PER_REQUEST) {
+        self.upperPage(self.page() + self.MAX_ALLOWED_PAGES_PER_REQUEST);
+        $.jHueNotify.info("${_('Sorry, you cannot request for more than %s pages.' % MAX_ALLOWED_PAGES_PER_REQUEST)}");
       }
       }
-      viewModel.page(_page);
-      viewModel.upperPage(viewModel.totalPages());
       changePage();
       changePage();
-    }
-  };
+    };
 
 
-  self.firstPage = function () {
-    if (!($(".first-page").hasClass("disabled"))) {
-      viewModel.page(1);
-      viewModel.upperPage(Math.min(self.totalPages(), 50));
-      changePage();
-    }
-  }
-}
-;
-
-var viewModel = new displayViewModel({
-          base_url: "${ base_url }",
-          compression: "${view['compression']}",
-          mode: "${ view['mode'] }",
-          begin: ${view['offset'] + 1},
-          end: ${view['end']},
-          length: ${view['length']},
-          size: ${stats['size']},
-          max_size: ${view['max_chunk_size']}
-        }
-);
-
-function resizeText() {
-  $("#fileArea").height($(window).height() - $("#fileArea").offset().top - 26);
-  $("#loader").css("marginLeft", ($("#fileArea").width() - $("#loader").width()) / 2);
-}
-
-function formatHex(number, padding) {
-  if ("undefined" != typeof number){
-    var _filler = "";
-    for (var i = 0; i < padding - 1; i++) {
-      _filler += "0";
-    }
-    return (_filler + number.toString(16)).substr(-padding);
-  }
-  return "";
-}
-
-var pages = {};
-
-function pageContent(page) {
-  var _html = "";
-  if ($("#page" + page).length == 0) {
-    if (pages[page] == null) {
-      _html += "<a id='page" + page + "'><div style='height: " + $("#fileArea").height() + "px'></div></a>";
-    }
-    else {
-      _html += "<a id='page" + page + "'><div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div></a>";
-    }
-  }
-  else {
-    if (pages[page] == null) {
-      $("#page" + page).html("<div style='height: " + $("#fileArea").height() + "px'></div>");
-    }
-    else {
-      $("#page" + page).html("<div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div>");
-    }
+    self.page.subscribe(function (value) {
+      self.toggleDisables();
+    });
 
 
-  }
-  return _html;
-}
+    self.upperPage.subscribe(function (value) {
+      self.toggleDisables();
+    });
 
 
-function renderPages() {
-  var _html = "";
-  if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING) { // enable scrolling
-    for (var i = 1; i <= viewModel.totalPages(); i++) {
-      _html += pageContent(i);
-    }
-  }
-  else {
-    _html += pageContent(viewModel.page());
-  }
-  if (_html != "") {
-    $("#fileArea pre").html(_html);
-  }
-}
-
-
-function getContent(callback) {
-  viewModel.isLoading(true);
-  var _baseUrl = "${url('filebrowser.views.view', path=path_enc)}";
-  $.getJSON(_baseUrl, viewModel.jsonParams(), function (data) {
-    if (data.view.contents != null) {
-      pages[viewModel.page()] = data.view.contents;
-      renderPages();
-    }
-    if (data.view.xxd != null) {
-      pages[viewModel.page()] = data.view.xxd;
-      var _html = "";
-      $(data.view.xxd).each(function (cnt, item) {
-        _html += "<tr><td>" + formatHex(item[0], 7) + ":&nbsp;</td><td>";
-        for (var i = 0; i < item[1].length; i++) {
-          _html += formatHex(item[1][i][0], 2) + " " + formatHex(item[1][i][1], 2) + " ";
+    self.nextPage = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (! ($(".next-page").hasClass("disabled"))) {
+        if (viewModel.page() == viewModel.upperPage()) {
+          viewModel.page(viewModel.page() + 1);
+          viewModel.upperPage(viewModel.upperPage() + 1);
+        } else {
+          var _difference = self.upperPage() - self.page();
+          self.page(self.upperPage() + 1);
+          self.upperPage(Math.min(self.page() + _difference, self.totalPages()));
         }
         }
-        _html += "</td><td>&nbsp;&nbsp;" + $("<span>").text(item[2]).html() + "</td></tr>";
-      });
-      $(".binary tbody").html(_html);
-    }
-    if (callback) {
-      callback();
-    }
-    viewModel.isLoading(false);
-  });
-}
-
-
-$(document).ready(function () {
-  ko.applyBindings(viewModel);
+        changePage();
+      }
+    };
+
+    self.previousPage = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (! ($(".previous-page").hasClass("disabled"))) {
+        if (viewModel.page() == viewModel.upperPage()) {
+          viewModel.page(viewModel.page() - 1);
+          viewModel.upperPage(viewModel.upperPage() - 1);
+        } else {
+          var _difference = self.upperPage() - self.page();
+          self.upperPage(self.page() - 1);
+          self.page(Math.max(self.page() - _difference - 1, 1));
+        }
+        changePage();
+      }
+    };
 
 
-  $(document).ajaxError(function () {
-    $.jHueNotify.error("${_('There was an unexpected server error.')}");
-  });
+    self.lastPage = function () {
+      if (! ($(".last-page").hasClass("disabled"))) {
+        var _page = viewModel.totalPages();
+        if (_page > 50) {
+          _page = Math.min(viewModel.totalPages() - viewModel.totalPages()%50 + 1, viewModel.totalPages());
+        }
+        viewModel.page(_page);
+        viewModel.upperPage(viewModel.totalPages());
+        changePage();
+      }
+    };
 
 
-  var _hash = window.location.hash;
-  if (_hash != "") {
-    var _hashPage = 1;
-    var _hashUpperPage = 1;
-    if (_hash.indexOf("-") > -1) {
-      _hashPage = _hash.split("-")[0].substr(2) * 1;
-      _hashUpperPage = _hash.split("-")[1].substr(1) * 1;
-    }
-    else {
-      _hashPage = _hash.substr(2) * 1;
-      _hashUpperPage = Math.min(viewModel.totalPages(), _hashPage + 50 - 1);
-    }
-    if (isNaN(_hashPage)) {
-      _hashPage = 1;
-    }
-    if (isNaN(_hashUpperPage)) {
-      _hashUpperPage = Math.min(viewModel.totalPages(), 50);
-    }
-    if (_hashUpperPage - _hashPage > viewModel.MAX_ALLOWED_PAGES_PER_REQUEST) {
-      _hashUpperPage = _hashPage + viewModel.MAX_ALLOWED_PAGES_PER_REQUEST;
+    self.firstPage = function () {
+      if (! ($(".first-page").hasClass("disabled"))) {
+        viewModel.page(1);
+        viewModel.upperPage(Math.min(self.totalPages(), 50));
+        changePage();
+      }
     }
     }
-    viewModel.page(_hashPage);
-    viewModel.upperPage(_hashUpperPage);
-  }
-
-  viewModel.toggleDisables();
+  };
 
 
-  window.setTimeout(function () {
-    getContent(function () {
-      if (window.location.hash != "") {
-        window.location.hash = "#page" + viewModel.page();
-        window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
-      }
+  $(document).ready(function () {
+    var viewModel = new DisplayViewModel({
+      base_url: "${ base_url }",
+      compression: "${view['compression']}",
+      mode: "${ view['mode'] }",
+      begin: ${view['offset'] + 1},
+      end: ${view['end']},
+      length: ${view['length']},
+      size: ${stats['size']},
+      max_size: ${view['max_chunk_size']}
     });
     });
-  }, 100);
-
-  resizeText();
 
 
-  var _resizeTimeout = -1;
-  $(window).on("resize", function () {
-    window.clearTimeout(_resizeTimeout);
-    _resizeTimeout = window.setTimeout(function () {
-      resizeText();
-      renderPages();
-    }, 300);
-  });
+    ko.applyBindings(viewModel);
 
 
-  $("#fileArea").jHueScrollUp();
+    $(document).ajaxError(function () {
+      $.jHueNotify.error("${_('There was an unexpected server error.')}");
+    });
 
 
-  if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING && viewModel.mode() == "text") { // enable scrolling
-    var _fileAreaScrollTimeout = -1;
-    $("#fileArea").on("scroll", function () {
-      if ($("#fileArea").scrollTop() < 30) {
-        viewModel.page(1);
-        viewModel.upperPage(viewModel.page());
+    var _hash = window.location.hash;
+    if (_hash != "") {
+      var _hashPage = 1;
+      var _hashUpperPage = 1;
+      if (_hash.indexOf("-") > -1) {
+        _hashPage = _hash.split("-")[0].substr(2) * 1;
+        _hashUpperPage = _hash.split("-")[1].substr(1) * 1;
+      } else {
+        _hashPage = _hash.substr(2) * 1;
+        _hashUpperPage = Math.min(viewModel.totalPages(), _hashPage + 50 - 1);
       }
       }
-      else {
-        for (var i = 1; i <= viewModel.totalPages(); i++) {
-          if ($("#page" + i + " div").visible(true)) {
-            viewModel.page(i);
-            viewModel.upperPage(viewModel.page());
-          }
-        }
+      if (isNaN(_hashPage)) {
+        _hashPage = 1;
       }
       }
-      window.clearTimeout(_fileAreaScrollTimeout);
-      _fileAreaScrollTimeout = window.setTimeout(function () {
-        location.hash = "#p" + viewModel.page();
-        if (pages[viewModel.page()] == null) {
-          getContent();
+      if (isNaN(_hashUpperPage)) {
+        _hashUpperPage = Math.min(viewModel.totalPages(), 50);
+      }
+      if (_hashUpperPage - _hashPage > viewModel.MAX_ALLOWED_PAGES_PER_REQUEST) {
+        _hashUpperPage = _hashPage + viewModel.MAX_ALLOWED_PAGES_PER_REQUEST;
+      }
+      viewModel.page(_hashPage);
+      viewModel.upperPage(_hashUpperPage);
+    };
+
+    viewModel.toggleDisables();
+
+    window.setTimeout(function () {
+      getContent(function () {
+        if (window.location.hash != "") {
+          window.location.hash = "#page" + viewModel.page();
+          window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
         }
         }
-      }, 100);
+      });
+    }, 100);
+
+    resizeText();
+
+    var _resizeTimeout = -1;
+    $(window).on("resize", function () {
+      window.clearTimeout(_resizeTimeout);
+      _resizeTimeout = window.setTimeout(function () {
+        resizeText();
+        renderPages();
+      }, 300);
     });
     });
-  }
 
 
-});
+    $("#fileArea").jHueScrollUp();
+
+    if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING && viewModel.mode() == "text") { // enable scrolling
+      var _fileAreaScrollTimeout = -1;
+      $("#fileArea").on("scroll", function () {
+        if ($("#fileArea").scrollTop() < 30) {
+          viewModel.page(1);
+          viewModel.upperPage(viewModel.page());
+        } else {
+          for (var i = 1; i <= viewModel.totalPages(); i++) {
+            if ($("#page" + i + " div").visible(true)) {
+              viewModel.page(i);
+              viewModel.upperPage(viewModel.page());
+            }
+          }
+        }
+        window.clearTimeout(_fileAreaScrollTimeout);
+        _fileAreaScrollTimeout = window.setTimeout(function () {
+          location.hash = "#p" + viewModel.page();
+          if (pages[viewModel.page()] == null) {
+            getContent();
+          }
+        }, 100);
+      });
+    }
+  });
+}());
 </script>
 </script>
 
 
 ${ commonfooter(messages) | n,unicode }
 ${ commonfooter(messages) | n,unicode }

+ 63 - 63
apps/filebrowser/src/filebrowser/templates/listdir.mako

@@ -32,74 +32,74 @@ ${ fb_components.menubar() }
   <div class="card card-small">
   <div class="card card-small">
     <div class="actionbar">
     <div class="actionbar">
     <%actionbar:render>
     <%actionbar:render>
-        <%def name="search()">
-            <input type="text" class="input-large search-query" placeholder="${_('Search for file name')}" data-bind="value: searchQuery">
-        </%def>
+      <%def name="search()">
+        <input type="text" class="input-large search-query" placeholder="${_('Search for file name')}" data-bind="value: searchQuery">
+      </%def>
 
 
-        <%def name="actions()">
-          <div class="btn-toolbar" style="display: inline; vertical-align: middle">
-            <button class="btn fileToolbarBtn" title="${_('Rename')}" data-bind="visible: !inTrash(), click: renameFile, enable: selectedFiles().length == 1"><i class="fa fa-font"></i> ${_('Rename')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0"><i class="fa fa-random"></i> ${_('Move')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0"><i class="fa fa-files-o"></i> ${_('Copy')}</button>
-            %if is_fs_superuser:
-            <div id="ch-dropdown" class="btn-group" style="vertical-align: middle">
-              <button href="#" class="btn dropdown-toggle" title="${_('Chown / Chmod')}" data-toggle="dropdown" data-bind="visible: !inTrash(), enable: selectedFiles().length > 0">
-                <i class="fa fa-user"></i> ${_('Chmod / Chown')}
-                <span class="caret" style="line-height: 15px"></span>
-              </button>
-              <ul class="dropdown-menu" style="top: auto">
-                <li><a href="#" title="${_('Change owner/group')}" data-bind="visible: !inTrash(), click: changeOwner, enable: selectedFiles().length > 0"><i class="fa fa-user"></i> ${_('Change owner / group')}</a></li>
-                <li><a href="#" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</a></li>
-              </ul>
-            </div>
-            %else:
-              <button class="btn fileToolbarBtn" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</button>
-            %endif
-            <button class="btn fileToolbarBtn" title="${_('Download')}" data-bind="visible: !inTrash(), click: downloadFile, enable: selectedFiles().length == 1 && selectedFile().type == 'file'"><i class="fa fa-arrow-circle-o-down"></i> ${_('Download')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
-            <!-- ko ifnot: inTrash -->
-                <div id="delete-dropdown" class="btn-group" style="vertical-align: middle">
-                  <button id="trash-btn" class="btn toolbarBtn" data-bind="enable: selectedFiles().length > 0, click: trashSelected"><i class="fa fa-times"></i> ${_('Move to trash')}</button>
-                  <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown" data-bind="enable: selectedFiles().length > 0">
-                    <span class="caret"></span>
-                  </button>
-                  <ul class="dropdown-menu">
-                    <li><a href="#" class="delete-link" title="${_('Delete forever')}" data-bind="enable: selectedFiles().length > 0, click: deleteSelected"><i class="fa fa-bolt"></i> ${_('Delete forever')}</a></li>
-                  </ul>
-                </div>
-            <!-- /ko -->
-            <button class="btn fileToolbarBtn" title="${_('Submit')}"
-              data-bind="visible: selectedFiles().length == 1 && $.inArray(selectedFile().name, ['workflow.xml', 'coordinator.xml', 'bundle.xml']) > -1, click: submitSelected">
-              <i class="fa fa-play"></i> ${_('Submit')}
+      <%def name="actions()">
+        <div class="btn-toolbar" style="display: inline; vertical-align: middle">
+          <button class="btn fileToolbarBtn" title="${_('Rename')}" data-bind="visible: !inTrash(), click: renameFile, enable: selectedFiles().length == 1"><i class="fa fa-font"></i> ${_('Rename')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0"><i class="fa fa-random"></i> ${_('Move')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0"><i class="fa fa-files-o"></i> ${_('Copy')}</button>
+          %if is_fs_superuser:
+          <div id="ch-dropdown" class="btn-group" style="vertical-align: middle">
+            <button href="#" class="btn dropdown-toggle" title="${_('Chown / Chmod')}" data-toggle="dropdown" data-bind="visible: !inTrash(), enable: selectedFiles().length > 0">
+              <i class="fa fa-user"></i> ${_('Chmod / Chown')}
+              <span class="caret" style="line-height: 15px"></span>
             </button>
             </button>
+            <ul class="dropdown-menu" style="top: auto">
+              <li><a href="#" title="${_('Change owner/group')}" data-bind="visible: !inTrash(), click: changeOwner, enable: selectedFiles().length > 0"><i class="fa fa-user"></i> ${_('Change owner / group')}</a></li>
+              <li><a href="#" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</a></li>
+            </ul>
           </div>
           </div>
-        </%def>
+          %else:
+            <button class="btn fileToolbarBtn" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</button>
+          %endif
+          <button class="btn fileToolbarBtn" title="${_('Download')}" data-bind="visible: !inTrash(), click: downloadFile, enable: selectedFiles().length == 1 && selectedFile().type == 'file'"><i class="fa fa-arrow-circle-o-down"></i> ${_('Download')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
+          <!-- ko ifnot: inTrash -->
+              <div id="delete-dropdown" class="btn-group" style="vertical-align: middle">
+                <button id="trash-btn" class="btn toolbarBtn" data-bind="enable: selectedFiles().length > 0, click: trashSelected"><i class="fa fa-times"></i> ${_('Move to trash')}</button>
+                <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown" data-bind="enable: selectedFiles().length > 0">
+                  <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                  <li><a href="#" class="delete-link" title="${_('Delete forever')}" data-bind="enable: selectedFiles().length > 0, click: deleteSelected"><i class="fa fa-bolt"></i> ${_('Delete forever')}</a></li>
+                </ul>
+              </div>
+          <!-- /ko -->
+          <button class="btn fileToolbarBtn" title="${_('Submit')}"
+            data-bind="visible: selectedFiles().length == 1 && $.inArray(selectedFile().name, ['workflow.xml', 'coordinator.xml', 'bundle.xml']) > -1, click: submitSelected">
+            <i class="fa fa-play"></i> ${_('Submit')}
+          </button>
+        </div>
+      </%def>
 
 
-        <%def name="creation()">
-          <button class="btn fileToolbarBtn" title="${_('Empty trash')}" data-bind="visible: inTrash(), click: purgeTrash"><i class="fa fa-fire"></i> ${_('Empty trash')}</button>
-          <div class="btn-toolbar" style="display: inline; vertical-align: middle">
-            <div id="upload-dropdown" class="btn-group" style="vertical-align: middle">
-              <a href="#" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-toggle="dropdown" data-bind="visible: !inTrash()">
-                <i class="fa fa-arrow-circle-o-up"></i> ${_('Upload')}
-                <span class="caret"></span>
-              </a>
-              <ul class="dropdown-menu">
-                <li><a href="#" class="upload-link" title="${_('Files')}" data-bind="click: uploadFile"><i class="fa fa-file-o"></i> ${_('Files')}</a></li>
-                <li><a href="#" class="upload-link" title="${_('Archive')}" data-bind="click: uploadArchive"><i class="fa fa-gift"></i> ${_('Zip/Tgz file')}</a></li>
-              </ul>
-            </div>
-            <div class="btn-group" style="vertical-align: middle">
-              <a href="#" data-toggle="dropdown" class="btn dropdown-toggle" data-bind="visible: !inTrash()">
-                <i class="fa fa-plus-circle"></i> ${_('New')}
-                <span class="caret"></span>
-              </a>
-              <ul class="dropdown-menu pull-right" style="top: auto">
-                <li><a href="#" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
-                <li><a href="#" class="create-directory-link" title="${_('Directory')}"><i class="fa fa-folder"></i> ${_('Directory')}</a></li>
-              </ul>
-            </div>
+      <%def name="creation()">
+        <button class="btn fileToolbarBtn" title="${_('Empty trash')}" data-bind="visible: inTrash(), click: purgeTrash"><i class="fa fa-fire"></i> ${_('Empty trash')}</button>
+        <div class="btn-toolbar" style="display: inline; vertical-align: middle">
+          <div id="upload-dropdown" class="btn-group" style="vertical-align: middle">
+            <a href="#" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-toggle="dropdown" data-bind="visible: !inTrash()">
+              <i class="fa fa-arrow-circle-o-up"></i> ${_('Upload')}
+              <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+              <li><a href="#" class="upload-link" title="${_('Files')}" data-bind="click: uploadFile"><i class="fa fa-file-o"></i> ${_('Files')}</a></li>
+              <li><a href="#" class="upload-link" title="${_('Archive')}" data-bind="click: uploadArchive"><i class="fa fa-gift"></i> ${_('Zip/Tgz file')}</a></li>
+            </ul>
           </div>
           </div>
-        </%def>
+          <div class="btn-group" style="vertical-align: middle">
+            <a href="#" data-toggle="dropdown" class="btn dropdown-toggle" data-bind="visible: !inTrash()">
+              <i class="fa fa-plus-circle"></i> ${_('New')}
+              <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu pull-right" style="top: auto">
+              <li><a href="#" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
+              <li><a href="#" class="create-directory-link" title="${_('Directory')}"><i class="fa fa-folder"></i> ${_('Directory')}</a></li>
+            </ul>
+          </div>
+        </div>
+      </%def>
     </%actionbar:render>
     </%actionbar:render>
     </div>
     </div>
     <div class="actionbarGhost hide"></div>
     <div class="actionbarGhost hide"></div>

File diff suppressed because it is too large
+ 446 - 825
apps/filebrowser/src/filebrowser/templates/listdir_components.mako


+ 1 - 1
apps/filebrowser/src/filebrowser/views.py

@@ -407,7 +407,7 @@ def listdir_paged(request, path):
     # actually '.' for display purposes. Encode it since _massage_stats expects byte strings.
     # actually '.' for display purposes. Encode it since _massage_stats expects byte strings.
     current_stat['path'] = path
     current_stat['path'] = path
     current_stat['name'] = "."
     current_stat['name'] = "."
-    shown_stats.insert(0, current_stat)
+    shown_stats.insert(1, current_stat)
 
 
     page.object_list = [ _massage_stats(request, s) for s in shown_stats ]
     page.object_list = [ _massage_stats(request, s) for s in shown_stats ]
 
 

Some files were not shown because too many files changed in this diff