tweak checkbox styling
[qcg-portal.git] / filex / static / filex / filex.js
index e7ad4c4..9f34b5e 100644 (file)
@@ -94,25 +94,28 @@ $(function(){
     Filex.Path = Backbone.Collection.extend({
         model: Filex.PathBit,
 
-        initialize: function() {
-            this.listenTo(this, 'reset add', this.setActive);
-        },
-
-        setActive: function() {
-            _.each(this.initial(), function(bit) {
-                bit.set('active', false);
-            });
-
-            this.last().set('active', true);
+        full: function() {
+            return this.pluck('name').join('/').replace(/^\/+/, '/');
         },
 
-        full: function() {
-            return this.pluck('path').join('/') || '/';
+        append: function(name) {
+            return this.pluck('name').concat(name).join('/').replace(/^\/+/, '/');
         }
     });
 
 
     // ------------------------------------------------------------------------
+    // Routers
+    // ------------------------------------------------------------------------
+
+    Filex.Router = Backbone.Router.extend({
+               routes: {
+                       '*url': 'load'
+               }
+       });
+
+
+    // ------------------------------------------------------------------------
     // Views
     // ------------------------------------------------------------------------
 
@@ -139,10 +142,16 @@ $(function(){
 
         render: function() {
             var data = this.model.toJSON();
-            data['url_params'] = $.param({
-                host: this.view.host,
-                path: this.view.path.full() + '/' + this.model.get('name')
-            });
+
+            if (this.model.isDir()) {
+                data['url'] = this.view.host + '/' + this.view.path.append(this.model.get('name'))
+            }
+            else {
+                data['params'] = $.param({
+                    host: this.view.host,
+                    path: this.view.path.append(this.model.get('name'))
+                });
+            }
             data['cid'] = this.model.cid;
 
             this.$el.html(this.template()(data));
@@ -152,7 +161,11 @@ $(function(){
         },
 
         toggleHidden: function() {
-            this.$el.toggleClass('hidden', this.model.isHidden() && !this.view.showHidden());
+            var isHidden = this.model.isHidden() && !this.view.showHidden();
+            this.$el.toggleClass('hidden', isHidden);
+
+            if (isHidden && this.model.get('checked'))
+                this.model.toggle();
         },
 
         toggleChecked: function(obj, value) {
@@ -161,26 +174,14 @@ $(function(){
         },
 
         click: function(e) {
-            if (e.target.className == 'link') {
-                if (this.model.isDir()) {
-                    e.preventDefault();
-                    this.model.trigger('selected:dir', this.model);
-                }
-
-                return;
-            }
-
-            this.model.toggle();
+            if (e.target.className != 'link')
+                this.model.toggle();
         }
     });
 
     Filex.Breadcrumb = Backbone.View.extend({
         tagName: 'li',
 
-        events: {
-            'click a': 'selected'
-        },
-
         initialize: function() {
             this.listenTo(this.model, 'change:active', this.render);
             this.listenTo(this.model, 'remove', this.remove);
@@ -188,22 +189,17 @@ $(function(){
 
         render: function() {
             if (this.model.get('active')) {
-                this.$el.text(this.model.get('text'));
+                this.$el.addClass('active');
+                this.$el.text(this.model.get('name'));
             }
             else {
                 this.$el.html($('<a/>', {
-                    href: '#',
-                    text: this.model.get('text')
+                    href: '#' + this.model.get('url'),
+                    text: this.model.get('name')
                 }));
             }
-            this.$el.toggleClass('active', this.model.get('active'));
 
             return this;
-        },
-
-        selected: function(e) {
-            e.preventDefault();
-            this.model.trigger('selected', this.model);
         }
     });
 
@@ -228,18 +224,17 @@ $(function(){
 
             this.path = new Filex.Path();
             this.files = new Filex.FileList();
+            this.router = new Filex.Router();
 
-            this.listenTo(this.path, 'reset', this.resetPath);
             this.listenTo(this.path, 'add', this.addPath);
-            this.listenTo(this.path, 'add reset', this.changedPath);
-            this.listenTo(this.path, 'selected', this.selectedPath);
+            this.listenTo(this.path, 'reset', this.resetPath);
             this.listenTo(this.files, 'reset', this.resetFiles);
-            this.listenTo(this.files, 'selected:dir', this.selectedDir);
             this.listenTo(this.files, 'change:checked', this.updateSelectAll);
+            this.listenTo(this.router, 'route:load', this.load);
 
             // used in selectize callbacks
             var view = this,
-                optionTemplate = _.template('<div><div><%= host %></div><div class="small text-muted"><%= path %></div></div>');
+                optionTemplate = _.template('<div><div><%- host %></div><div class="small text-muted"><%- path %></div></div>');
 
             this.$('#host-selector').selectize({
                 optgroupField: 'group',
@@ -257,20 +252,24 @@ $(function(){
                 lockOptgroupOrder: true,
                 create: function(input, callback) {
                     var $form = $('#favorite-form'),
-                        parts = input.split('/', 1),
+                        parts = input.split('/'),
                         callback_called = false;
 
-                    $form.find('#id_host').val(parts[0]);
+                    $form[0].reset();
+                    $form.find('.alert-danger').remove();
+                    $form.find('#id_host').val(parts.shift());
 
-                    if (parts.length > 1)
-                        $form.find('#id_path').val(parts[1]);
+                    if (parts.length)
+                        $form.find('#id_path').val(parts.join('/'));
 
+                    $form.off();
                     $form.on('submit', function(e) {
                         var $this = $(this),
                             $btn = $this.find('[type="submit"]');
 
                         e.preventDefault();
                         $btn.button('loading');
+                        $this.find('.alert-danger').remove();
 
                         $.post($this.attr('action'), $this.serialize(), function(data) {
                             callback(data);
@@ -278,9 +277,27 @@ $(function(){
 
                             $this.modal('hide');
                             $btn.button('reset');
-                        }, 'json').fail(function() {
+                        }, 'json').fail(function(xhr) {
                             console.error(arguments);
-                            $btn.button('error');
+                            var error = (xhr.responseJSON || {}).error || undefined;
+
+                            if (error.__all__) {
+                                error = 'Podana lokalizacja jest już zapisana'
+                            }
+                            else if (xhr.status == 400) {
+                                error = 'Niepoprawna nazwa hosta lub ścieżka'
+                            }
+
+                            if (typeof error === 'string') {
+                                $('<div>', {
+                                    'class': 'alert alert-danger',
+                                    html: '<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> ' + error
+                                }).prependTo($this.find('.modal-body'));
+                                $btn.button('reset');
+                            }
+                            else {
+                                $btn.button('error');
+                            }
                         });
                     });
 
@@ -301,7 +318,7 @@ $(function(){
                     }
                 },
                 onItemAdd: function(value) {
-                    view.load(value);
+                    view.router.navigate('#' + value, {trigger: true});
                     this.blur();
                 },
                 onBlur: function() {
@@ -312,6 +329,7 @@ $(function(){
             this.hostSelectize = this.$('#host-selector')[0].selectize;
 
             this.render();
+               Backbone.history.start();
         },
 
         render: function() {
@@ -322,16 +340,25 @@ $(function(){
         },
 
         load: function(location) {
-            var path = location.replace(/(^\/+|\/+$)/g, '').split('/'),
-                host = path.shift(),
-                pathBits = [new Filex.PathBit({'text': '/', 'path': ''})].concat(_.map(path, function(name) {
-                    return new Filex.PathBit({'text': name, 'path': name});
-                }));
+            if (!location)
+                return;
 
-            this.host = host;
-            this.path.reset(pathBits);
+            var hostRootPath = location.split(/\/(\/|~)(.*)/), self = this;
 
+            this.host = hostRootPath[0];
             this.$host.text(this.host);
+
+            this.path.reset([new Filex.PathBit({'name': hostRootPath[1], url: this.host + '/' + hostRootPath[1]})]);
+            _.each(hostRootPath[2].split('/'), function(item) {
+                if (item)
+                    self.path.add(new Filex.PathBit({name: item, url: self.host + '/' + self.path.append(item)}));
+            });
+            this.path.last().set('active', true);
+
+            this.reloadFiles();
+            this.updateFavorites();
+
+            localStorage.last_location = location;
         },
 
         reloadFiles: function() {
@@ -388,14 +415,6 @@ $(function(){
             this.render();
         },
 
-        selectedDir: function(dir) {
-            this.path.add({'text': dir.get('name'), 'path': dir.get('name')});
-        },
-
-        selectedPath: function(bit) {
-            this.path.reset(this.path.slice(0, this.path.indexOf(bit) + 1));
-        },
-
         showHidden: function() {
             return this.$showHidden[0].checked;
         },
@@ -455,20 +474,13 @@ $(function(){
 
             $btn.button('loading');
 
-            $.post(url, data, 'json').done(function () {
+            $.post(url, data, 'json').done(function (response) {
                 $btn.button('reset');
 
-                if (is_active) {
-                    locations.removeOption(data.host + data.path);
-                }
-                else {
-                    locations.addOption({
-                        group: 'usr',
-                        host: data.host,
-                        path: data.path,
-                        value: data.host + data.path
-                    });
-                }
+                if (is_active)
+                    locations.removeOption(data.host + '/' + data.path);
+                else
+                    locations.addOption(response);
             }).fail(function() {
                 $btn.button('reset');
                 $btn.button('toggle');
@@ -478,20 +490,14 @@ $(function(){
         },
 
         initialLoad: function() {
-            if (!this.host) {
-                var opts = this.hostSelectize.options;
-
-                this.load(opts[Object.keys(opts)[0]].value);
-            }
-        },
+            var opts = this.hostSelectize.options,
+                location = localStorage.last_location || opts[Object.keys(opts)[0]].value;
 
-        changedPath: function () {
-            this.reloadFiles();
-            this.updateFavorites();
+            this.router.navigate('#' + location, {trigger: true, replace: true});
         },
 
         updateFavorites: function() {
-            var loc = this.host + this.path.full(),
+            var loc = this.host + '/' + this.path.full(),
                 favorites = this.hostSelectize.options;
 
             if (favorites.hasOwnProperty(loc)) {