Use own tabs impl in files sidebar
Also change style.
This commit is contained in:
parent
a81251454d
commit
781ba420c9
5 changed files with 123 additions and 26 deletions
|
@ -41,3 +41,4 @@
|
|||
right: 0;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,17 @@
|
|||
'<div>' +
|
||||
' <div class="detailFileInfoContainer">' +
|
||||
' </div>' +
|
||||
' <div class="tabsContainer">' +
|
||||
' <ul class="tabHeadsContainer">' +
|
||||
' <div>' +
|
||||
' <ul class="tabHeaders">' +
|
||||
' </ul>' +
|
||||
' <div class="tabsContainer">' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' <a class="close icon-close" href="#" alt="{{closeLabel}}"></a>' +
|
||||
'</div>';
|
||||
|
||||
var TEMPLATE_TAB_HEADER =
|
||||
'<li class="tabHeaders"><a href="#{{tabId}}">{{label}}</a></li>';
|
||||
'<li class="tabHeader {{#if selected}}selected{{/if}}" data-tabid="{{tabId}}" data-tabindex="{{tabIndex}}"><a href="#">{{label}}</a></li>';
|
||||
|
||||
/**
|
||||
* @class OCA.Files.DetailsView
|
||||
|
@ -69,11 +71,17 @@
|
|||
*/
|
||||
_detailFileInfoViews: [],
|
||||
|
||||
/**
|
||||
* Id of the currently selected tab
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
_currentTabId: null,
|
||||
|
||||
/**
|
||||
* Initialize the details view
|
||||
*/
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
this.$el = $('<div id="app-sidebar"></div>');
|
||||
this.fileInfo = null;
|
||||
this._tabViews = [];
|
||||
|
@ -84,8 +92,10 @@
|
|||
event.preventDefault();
|
||||
});
|
||||
|
||||
this.$el.on('click', '.tabHeaders .tabHeader', _.bind(this._onClickTab, this));
|
||||
|
||||
// uncomment to add some dummy tabs for testing
|
||||
// this._addTestTabs();
|
||||
//this._addTestTabs();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -97,6 +107,27 @@
|
|||
}
|
||||
},
|
||||
|
||||
_onClickTab: function(e) {
|
||||
var $target = $(e.target);
|
||||
if (!$target.hasClass('tabHeader')) {
|
||||
$target = $target.closest('.tabHeader');
|
||||
}
|
||||
var tabIndex = $target.attr('data-tabindex');
|
||||
var targetTab;
|
||||
if (_.isUndefined(tabIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$el.find('.tabsContainer .tab').addClass('hidden');
|
||||
targetTab = this._tabViews[tabIndex];
|
||||
targetTab.$el.removeClass('hidden');
|
||||
|
||||
this.$el.find('.tabHeaders li').removeClass('selected');
|
||||
$target.addClass('selected');
|
||||
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
_addTestTabs: function() {
|
||||
for (var j = 0; j < 2; j++) {
|
||||
var testView = new OCA.Files.DetailTabView('testtab' + j);
|
||||
|
@ -131,7 +162,7 @@
|
|||
closeLabel: t('files', 'Close')
|
||||
}));
|
||||
var $tabsContainer = $el.find('.tabsContainer');
|
||||
var $tabHeadsContainer = $el.find('.tabHeadsContainer');
|
||||
var $tabHeadsContainer = $el.find('.tabHeaders');
|
||||
var $detailsContainer = $el.find('.detailFileInfoContainer');
|
||||
|
||||
// render details
|
||||
|
@ -140,14 +171,25 @@
|
|||
});
|
||||
|
||||
if (this._tabViews.length > 0) {
|
||||
if (!this._currentTab) {
|
||||
this._currentTab = this._tabViews[0].getId();
|
||||
}
|
||||
|
||||
// render tabs
|
||||
_.each(this._tabViews, function(tabView) {
|
||||
_.each(this._tabViews, function(tabView, i) {
|
||||
// hidden by default
|
||||
$tabsContainer.append(tabView.get$());
|
||||
var $el = tabView.get$();
|
||||
var isCurrent = (tabView.getId() === self._currentTab);
|
||||
if (!isCurrent) {
|
||||
$el.addClass('hidden');
|
||||
}
|
||||
$tabsContainer.append($el);
|
||||
|
||||
$tabHeadsContainer.append(self._templateTabHeader({
|
||||
tabId: tabView.getId(),
|
||||
label: tabView.getLabel()
|
||||
tabIndex: i,
|
||||
label: tabView.getLabel(),
|
||||
selected: isCurrent
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -155,10 +197,6 @@
|
|||
// TODO: select current tab
|
||||
|
||||
this.$el.append($el);
|
||||
|
||||
if (this._tabViews.length > 0) {
|
||||
$tabsContainer.tabs({});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,8 +59,8 @@
|
|||
throw 'Argument "id" is required';
|
||||
}
|
||||
this._id = id;
|
||||
this.$el = $('<div class="detailTabView"></div>');
|
||||
this.$el.attr('id', id);
|
||||
this.$el = $('<div class="tab"></div>');
|
||||
this.$el.attr('data-tabid', id);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,23 +64,20 @@ describe('OCA.Files.DetailsView tests', function() {
|
|||
});
|
||||
});
|
||||
describe('tabs', function() {
|
||||
it('renders registered tabs', function() {
|
||||
var testView = new OCA.Files.DetailTabView('test1');
|
||||
var testView2 = new OCA.Files.DetailTabView('test2');
|
||||
var testView, testView2;
|
||||
|
||||
beforeEach(function() {
|
||||
testView = new OCA.Files.DetailTabView('test1');
|
||||
testView2 = new OCA.Files.DetailTabView('test2');
|
||||
detailsView.addTabView(testView);
|
||||
detailsView.addTabView(testView2);
|
||||
detailsView.render();
|
||||
|
||||
expect(detailsView.$el.find('.tabsContainer .detailTabView').length).toEqual(2);
|
||||
});
|
||||
it('renders registered tabs', function() {
|
||||
expect(detailsView.$el.find('.tab').length).toEqual(2);
|
||||
});
|
||||
it('updates registered tabs when fileinfo is updated', function() {
|
||||
var tabRenderStub = sinon.stub(OCA.Files.DetailTabView.prototype, 'render');
|
||||
var testView = new OCA.Files.DetailTabView('test1');
|
||||
var testView2 = new OCA.Files.DetailTabView('test2');
|
||||
detailsView.addTabView(testView);
|
||||
detailsView.addTabView(testView2);
|
||||
detailsView.render();
|
||||
|
||||
var fileInfo = {id: 5, name: 'test.txt'};
|
||||
tabRenderStub.reset();
|
||||
detailsView.setFileInfo(fileInfo);
|
||||
|
@ -91,5 +88,18 @@ describe('OCA.Files.DetailsView tests', function() {
|
|||
expect(tabRenderStub.callCount).toEqual(2);
|
||||
tabRenderStub.restore();
|
||||
});
|
||||
it('selects the first tab by default', function() {
|
||||
expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(true);
|
||||
expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(false);
|
||||
expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(false);
|
||||
expect(detailsView.$el.find('.tab').eq(1).hasClass('hidden')).toEqual(true);
|
||||
});
|
||||
it('switches the current tab when clicking on tab header', function() {
|
||||
detailsView.$el.find('.tabHeader').eq(1).click();
|
||||
expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(false);
|
||||
expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(true);
|
||||
expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(true);
|
||||
expect(detailsView.$el.find('.tab').eq(1).hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -592,3 +592,51 @@ em {
|
|||
padding:16px;
|
||||
}
|
||||
|
||||
/* generic tab styles */
|
||||
.tabHeaders {
|
||||
margin: 15px;
|
||||
background-color: #1D2D44;
|
||||
}
|
||||
|
||||
.tabHeaders .tabHeader {
|
||||
float: left;
|
||||
border: 1px solid #ddd;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
background-color: #f8f8f8;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tabHeaders .tabHeader, .tabHeaders .tabHeader a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.tabHeaders .tabHeader:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.tabHeaders .tabHeader:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.tabHeaders .tabHeader.selected,
|
||||
.tabHeaders .tabHeader:hover {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.tabHeaders .tabHeader.selected,
|
||||
.tabHeaders .tabHeader.selected a,
|
||||
.tabHeaders .tabHeader:hover,
|
||||
.tabHeaders .tabHeader:hover a {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.tabsContainer {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.tabsContainer .tab {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue