1 var Filex = Filex || {};
6 // ------------------------------------------------------------------------
8 // ------------------------------------------------------------------------
10 var OfflineModel = Backbone.Model.extend({
11 // prevent syncing with server
17 Filex.File = OfflineModel.extend({
26 isHidden: function() {
27 return this.get('name')[0] == '.';
31 Filex.Directory = Filex.File.extend({
41 Filex.PathBit = OfflineModel.extend({
48 // ------------------------------------------------------------------------
50 // ------------------------------------------------------------------------
52 Filex.FileList = Backbone.Collection.extend({
55 model: function(attrs, options) {
56 switch (attrs['type']) {
58 return new Filex.Directory(attrs, options);
60 return new Filex.File(attrs, options);
62 console.log('Unknown model type:', attrs['type']);
66 comparator: function(a, b) {
67 if (a.isFile() == b.isFile())
68 return a.get('name').toLowerCase().localeCompare(b.get('name').toLowerCase());
70 return (a.isFile() && b.isDir()) ? 1 : -1;
74 return this.filter(function (item) {
75 return item.isHidden();
79 visible: function () {
80 return this.filter(function (item) {
81 return !item.isHidden();
86 Filex.Path = Backbone.Collection.extend({
89 initialize: function() {
90 this.listenTo(this, 'reset', this.setActive);
91 this.listenTo(this, 'add', this.setActive);
94 setActive: function() {
95 _.each(this.initial(), function(bit) {
96 bit.set('active', false);
99 this.last().set('active', true);
103 return this.pluck('path').join('/') || '/';
108 // ------------------------------------------------------------------------
110 // ------------------------------------------------------------------------
112 Filex.ListingItem = Backbone.View.extend({
116 'click .link': 'selected'
119 initialize: function(options) {
120 this.view = options.view;
122 this.listenTo(this.model, 'remove', this.remove);
123 this.listenTo(this.model, 'hidden', this.toggleHidden);
126 template: function() {
127 var templateSelector = this.model.isDir() ? '#dir-template' : '#file-template';
129 return _.template($(templateSelector).html());
133 var data = this.model.toJSON();
134 data['url_params'] = $.param({
135 host: this.view.host,
136 path: this.view.path.full(),
137 name: this.model.get('name')
140 this.$el.html(this.template()(data));
146 toggleHidden: function() {
147 this.$el.toggleClass('hidden', this.model.isHidden() && !this.view.showHidden());
150 selected: function(e) {
152 this.model.trigger(this.model.isDir() ? 'selected:dir' : 'selected:file', this.model);
156 Filex.Breadcrumb = Backbone.View.extend({
160 'click a': 'selected'
163 initialize: function() {
164 this.listenTo(this.model, 'change:active', this.render);
165 this.listenTo(this.model, 'remove', this.remove);
169 if (this.model.get('active')) {
170 this.$el.text(this.model.get('text'));
173 this.$el.html($('<a/>', {
175 text: this.model.get('text')
178 this.$el.toggleClass('active', this.model.get('active'));
183 selected: function(e) {
185 this.model.trigger('selected', this.model);
189 Filex.FilexView = Backbone.View.extend({
193 'change #show-hidden': 'toggleHidden',
194 'click #host-controls .view': 'hostEdit'
197 initialize: function(options) {
198 this.$noItems = $('#no-items');
199 this.$error = $('#error');
200 this.$showHidden = $('#show-hidden');
201 this.$host = $('#host-controls');
203 this.host = options.host;
204 this.path = new Filex.Path();
205 this.files = new Filex.FileList();
207 this.listenTo(this.path, 'reset', this.resetPath);
208 this.listenTo(this.path, 'add', this.reloadFiles);
209 this.listenTo(this.path, 'add', this.addPath);
210 this.listenTo(this.path, 'selected', this.selectedPath);
211 this.listenTo(this.files, 'reset', this.resetFiles);
212 this.listenTo(this.files, 'selected:dir', this.selectedDir);
213 this.listenTo(this.files, 'selected:file', this.selectedFile);
215 // used in selectize callbacks
217 optionTemplate = _.template('<div><div><%= host %></div><div class="small text-muted"><%= path %></div></div>');
219 this.$('#host-selector').selectize({
222 searchField: ['host', 'path'],
224 {field: 'host', direction: 'asc'},
225 {field: 'path', direction: 'asc'}
228 options: options.hostOptions,
230 option: function(item) {
231 return optionTemplate(item);
234 onDropdownClose: function() {
238 view.$host.toggleClass('editing');
240 var value = this.getValue();
242 this.addItem(view.host, true);
246 if (value != view.host) {
247 var location = this.options[value];
249 view.host = location.host;
250 view.navigate(location.path);
254 this.hostSelectize = this.$('#host-selector')[0].selectize;
257 this.navigate(this.hostSelectize.options[this.host].path);
261 this.$host.find('.view').text(this.host);
262 this.$noItems.toggle((this.showHidden() ? !Boolean(this.files.length) : !Boolean(this.files.visible().length)));
266 navigate: function(path) {
267 var pathBits = [new Filex.PathBit({'text': '/', 'path': ''})];
269 pathBits = pathBits.concat(_.map(path.replace(/(^\/+|\/+$)/g, '').split('/'), function(name) {
270 return new Filex.PathBit({'text': name, 'path': name});
273 this.path.reset(pathBits);
276 reloadFiles: function() {
283 data: {host: this.host, path: this.path.full()},
284 success: function() {
288 error: function(collection, response) {
291 var msg = (response.responseJSON || {}).msg || 'Błąd serwera';
293 view.$noItems.hide();
294 view.$error.find('.msg').text(msg);
301 addPath: function(bit) {
302 var view = new Filex.Breadcrumb({model: bit});
303 this.$('.path').append(view.render().el);
306 resetPath: function(models, options) {
309 _.each(options.previousModels, function(model) {
310 model.trigger('remove');
313 this.path.each(this.addPath, this);
316 resetFiles: function(models, options) {
317 _.each(options.previousModels, function(model) {
318 model.trigger('remove');
321 this.files.each(function(file) {
322 var view = new Filex.ListingItem({model: file, view: this});
323 this.$('tbody').append(view.render().el);
327 toggleHidden: function() {
328 this.files.each(function(item) { item.trigger('hidden'); }, this);
332 selectedDir: function(dir) {
333 this.path.add({'text': dir.get('name'), 'path': dir.get('name')});
336 selectedFile: function(file) {
337 this.trigger('selected:file', this.host + this.path.full() + '/' + file.get('name'));
340 selectedPath: function(bit) {
341 var newPath = this.path.slice(0, this.path.indexOf(bit) + 1);
342 this.path.set(newPath);
346 showHidden: function() {
347 return this.$showHidden[0].checked;
350 hostEdit: function() {
351 this.$host.toggleClass('editing');
352 this.hostSelectize.focus();
356 this.$el.addClass('busy');
360 this.$el.removeClass('busy');