From c9bc52153251863776e8b506533b29520ac12cee Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Fri, 9 Jun 2017 09:09:41 +0200 Subject: [PATCH] Extract toggle visibility of a SystemTagsInfoView to its own view MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The SystemTagsInfoViewToggleView is a basic view that renders a label that, when clicked, toggles the visibility of an associated SystemTagsInfoView. In order to keep the view parent agnostic its attachment and detachment to/from the MainfFileInfoView is done in the FilesPlugin. Signed-off-by: Daniel Calviño Sánchez --- apps/systemtags/js/filesplugin.js | 16 ++- apps/systemtags/js/merged.json | 3 +- apps/systemtags/js/systemtagsinfoview.js | 24 ---- .../js/systemtagsinfoviewtoggleview.js | 103 ++++++++++++++++++ .../js/systemtagsinfoviewtoggleviewSpec.js | 93 ++++++++++++++++ tests/karma.config.js | 1 + 6 files changed, 214 insertions(+), 26 deletions(-) create mode 100644 apps/systemtags/js/systemtagsinfoviewtoggleview.js create mode 100644 apps/systemtags/tests/js/systemtagsinfoviewtoggleviewSpec.js diff --git a/apps/systemtags/js/filesplugin.js b/apps/systemtags/js/filesplugin.js index 229d64da9d5..fc2a227b5be 100644 --- a/apps/systemtags/js/filesplugin.js +++ b/apps/systemtags/js/filesplugin.js @@ -36,7 +36,21 @@ _.each(fileList.getRegisteredDetailViews(), function(detailView) { if (detailView instanceof OCA.Files.MainFileInfoDetailView) { - systemTagsInfoView.setMainFileInfoView(detailView); + var systemTagsInfoViewToggleView = + new OCA.SystemTags.SystemTagsInfoViewToggleView({ + systemTagsInfoView: systemTagsInfoView + }); + systemTagsInfoViewToggleView.render(); + + // The toggle view element is detached before the + // MainFileInfoDetailView is rendered to prevent its event + // handlers from being removed. + systemTagsInfoViewToggleView.listenTo(detailView, 'pre-render', function() { + systemTagsInfoViewToggleView.$el.detach(); + }); + systemTagsInfoViewToggleView.listenTo(detailView, 'post-render', function() { + detailView.$el.find('.file-details').append(systemTagsInfoViewToggleView.$el); + }); return; } diff --git a/apps/systemtags/js/merged.json b/apps/systemtags/js/merged.json index 0262077498a..632abf6777e 100644 --- a/apps/systemtags/js/merged.json +++ b/apps/systemtags/js/merged.json @@ -2,5 +2,6 @@ "app.js", "systemtagsfilelist.js", "filesplugin.js", - "systemtagsinfoview.js" + "systemtagsinfoview.js", + "systemtagsinfoviewtoggleview.js" ] diff --git a/apps/systemtags/js/systemtagsinfoview.js b/apps/systemtags/js/systemtagsinfoview.js index d42bf18761b..1bf7287342f 100644 --- a/apps/systemtags/js/systemtagsinfoview.js +++ b/apps/systemtags/js/systemtagsinfoview.js @@ -37,8 +37,6 @@ */ _inputView: null, - _toggleHandle: null, - initialize: function(options) { var self = this; options = options || {}; @@ -60,18 +58,6 @@ this._inputView.on('select', this._onSelectTag, this); this._inputView.on('deselect', this._onDeselectTag, this); - - this._toggleHandle = $('').addClass('tag-label').text(t('systemtags', 'Tags')); - this._toggleHandle.prepend($('').addClass('icon icon-tag')); - - this._toggleHandle.on('click', function () { - if (self.isVisible()) { - self.hide(); - } else { - self.show(); - self.openDropdown(); - } - }); }, /** @@ -121,15 +107,6 @@ this.selectedTagsCollection.remove(tagId); }, - setMainFileInfoView: function(mainFileInfoView) { - this.listenTo(mainFileInfoView, 'pre-render', function() { - this._toggleHandle.detach(); - }); - this.listenTo(mainFileInfoView, 'post-render', function() { - mainFileInfoView.$el.find('.file-details').append(this._toggleHandle); - }); - }, - setFileInfo: function(fileInfo) { var self = this; if (!this._rendered) { @@ -185,7 +162,6 @@ remove: function() { this._inputView.remove(); - this._toggleHandle.remove(); } }); diff --git a/apps/systemtags/js/systemtagsinfoviewtoggleview.js b/apps/systemtags/js/systemtagsinfoviewtoggleview.js new file mode 100644 index 00000000000..13a48e49cfb --- /dev/null +++ b/apps/systemtags/js/systemtagsinfoviewtoggleview.js @@ -0,0 +1,103 @@ +/** + * + * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +(function(OCA) { + + var TEMPLATE = + '' + t('systemtags', 'Tags'); + + /** + * @class OCA.SystemTags.SystemTagsInfoViewToggleView + * @classdesc + * + * View to toggle the visibility of a SystemTagsInfoView. + * + * This toggle view must be explicitly rendered before it is used. + */ + var SystemTagsInfoViewToggleView = OC.Backbone.View.extend( + /** @lends OC.Backbone.View.prototype */ { + + tagName: 'span', + + className: 'tag-label', + + events: { + 'click': 'click' + }, + + /** + * @type OCA.SystemTags.SystemTagsInfoView + */ + _systemTagsInfoView: null, + + template: function(data) { + if (!this._template) { + this._template = Handlebars.compile(TEMPLATE); + } + return this._template(data); + }, + + /** + * Initialize this toggle view. + * + * The options must provide a systemTagsInfoView parameter that + * references the SystemTagsInfoView to associate to this toggle view. + */ + initialize: function(options) { + var self = this; + options = options || {}; + + this._systemTagsInfoView = options.systemTagsInfoView; + if (!this._systemTagsInfoView) { + throw 'Missing required parameter "systemTagsInfoView"'; + } + }, + + /** + * Toggles the visibility of the associated SystemTagsInfoView. + * + * When the systemTagsInfoView is shown its dropdown is also opened. + */ + click: function() { + if (this._systemTagsInfoView.isVisible()) { + this._systemTagsInfoView.hide(); + } else { + this._systemTagsInfoView.show(); + this._systemTagsInfoView.openDropdown(); + } + }, + + /** + * Renders this toggle view. + * + * @return OCA.SystemTags.SystemTagsInfoViewToggleView this object. + */ + render: function() { + this.$el.html(this.template()); + + return this; + }, + + }); + + OCA.SystemTags.SystemTagsInfoViewToggleView = SystemTagsInfoViewToggleView; + +})(OCA); diff --git a/apps/systemtags/tests/js/systemtagsinfoviewtoggleviewSpec.js b/apps/systemtags/tests/js/systemtagsinfoviewtoggleviewSpec.js new file mode 100644 index 00000000000..5e6c2c820e9 --- /dev/null +++ b/apps/systemtags/tests/js/systemtagsinfoviewtoggleviewSpec.js @@ -0,0 +1,93 @@ +/** + * + * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +describe('OCA.SystemTags.SystemTagsInfoViewToggleView', function () { + + var systemTagsInfoView; + var view; + + beforeEach(function() { + systemTagsInfoView = new OCA.SystemTags.SystemTagsInfoView(); + view = new OCA.SystemTags.SystemTagsInfoViewToggleView({ systemTagsInfoView: systemTagsInfoView }); + }); + + afterEach(function() { + view.remove(); + systemTagsInfoView.remove(); + }); + + describe('initialize', function() { + it('fails if a "systemTagsInfoView" parameter is not provided', function() { + var constructor = function() { + return new OCA.SystemTags.SystemTagsInfoViewToggleView({}); + } + + expect(constructor).toThrow(); + }); + }); + + describe('click on element', function() { + + var isVisibleStub; + var showStub; + var hideStub; + var openDropdownStub; + + beforeEach(function() { + isVisibleStub = sinon.stub(systemTagsInfoView, 'isVisible'); + showStub = sinon.stub(systemTagsInfoView, 'show'); + hideStub = sinon.stub(systemTagsInfoView, 'hide'); + openDropdownStub = sinon.stub(systemTagsInfoView, 'openDropdown'); + }); + + afterEach(function() { + isVisibleStub.restore(); + showStub.restore(); + hideStub.restore(); + openDropdownStub.restore(); + }); + + it('shows a not visible SystemTagsInfoView', function() { + isVisibleStub.returns(false); + + view.$el.click(); + + expect(isVisibleStub.calledOnce).toBeTruthy(); + expect(showStub.calledOnce).toBeTruthy(); + expect(openDropdownStub.calledOnce).toBeTruthy(); + expect(openDropdownStub.calledAfter(showStub)).toBeTruthy(); + expect(hideStub.notCalled).toBeTruthy(); + }); + + it('hides a visible SystemTagsInfoView', function() { + isVisibleStub.returns(true); + + view.$el.click(); + + expect(isVisibleStub.calledOnce).toBeTruthy(); + expect(hideStub.calledOnce).toBeTruthy(); + expect(showStub.notCalled).toBeTruthy(); + expect(openDropdownStub.notCalled).toBeTruthy(); + }); + + }); + +}); diff --git a/tests/karma.config.js b/tests/karma.config.js index 62b5171dcd1..07dc2965346 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -102,6 +102,7 @@ module.exports = function(config) { // need to enforce loading order... 'apps/systemtags/js/app.js', 'apps/systemtags/js/systemtagsinfoview.js', + 'apps/systemtags/js/systemtagsinfoviewtoggleview.js', 'apps/systemtags/js/systemtagsfilelist.js', 'apps/systemtags/js/filesplugin.js' ], -- 2.39.5