diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index cbbbc48991..f3b5a08479 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -1377,9 +1377,13 @@ <%- device_name %> <%- last_login_ip %> - - <%- synced_repos_length %><% if (synced_repos.length > 0) { %> <% } %> -
+ + <% if (synced_repos.length > 0) { %> + <%- synced_repos_length %> + <% } else { %> + 0 + <% } %> +
    <% for (var i = 0, len = synced_repos_length; i < len; i++) { %> diff --git a/seahub/templates/libraries.html b/seahub/templates/libraries.html index 377df7b8ef..fc6c452234 100644 --- a/seahub/templates/libraries.html +++ b/seahub/templates/libraries.html @@ -263,6 +263,10 @@ app["pageOptions"] = { file_audit_enabled: {% if file_audit_enabled %} true {% else %} false {% endif %}, cur_note: {% if request.cur_note %} {'id': '{{ request.cur_note.id }}'} {% else %} null {% endif %} }; +app.ui = { + currentDropdown: null, + currentHighlightedItem: null +}; {% if debug %} diff --git a/static/scripts/app/views/device.js b/static/scripts/app/views/device.js index 0d4a9ced74..29e34e654d 100644 --- a/static/scripts/app/views/device.js +++ b/static/scripts/app/views/device.js @@ -3,26 +3,26 @@ define([ 'underscore', 'backbone', 'common', - 'moment' -], function($, _, Backbone, Common, Moment) { + 'moment', + 'app/views/widgets/hl-item-view', + 'app/views/widgets/dropdown' +], function($, _, Backbone, Common, Moment, HLItemView, DropdownView) { 'use strict'; - var DeviceView = Backbone.View.extend({ + var DeviceView = HLItemView.extend({ tagName: 'tr', template: _.template($('#device-item-tmpl').html()), events: { - 'mouseenter': 'highlight', - 'mouseleave': 'rmHighlight', - 'click .unlink-device': 'unlinkDevice', - 'click .js-toggle-repos': 'toggleSyncedRepos' + 'click .unlink-device': 'unlinkDevice' }, initialize: function() { + HLItemView.prototype.initialize.call(this); }, - render: function () { + render: function() { var data = this.model.toJSON(); if (typeof(data['synced_repos']) == 'undefined') { @@ -48,28 +48,18 @@ define([ this.$el.html(this.template(data)); + new DropdownView({ + el: this.$('.js-dropdown') + }); + return this; }, - highlight: function() { - if ($('.device-libs-popover:visible').length) { - return; - } - this.$el.addClass('hl').find('.op-icon').removeClass('vh'); - }, - - rmHighlight: function() { - if ($('.device-libs-popover:visible').length) { - return; - } - this.$el.removeClass('hl').find('.op-icon').addClass('vh'); - }, - _hidePopover: function(e) { var view = e.data.view; var target = e.target || event.srcElement; if (!$('.js-toggle-repos, .device-libs-popover').is(target)) { - $('.device-libs-popover').addClass('hide'); + $('.device-libs-popover').addClass('hide'); $('.dir-icon').removeClass('icon-caret-up').addClass('icon-caret-down'); view.rmHighlight(); $(document).off('click', view._hidePopover); @@ -77,19 +67,15 @@ define([ }, toggleSyncedRepos: function(e) { - if (this.model.get('synced_repos') == 0) { - return false; - } - var $icon= this.$('.dir-icon'), $popover = this.$('.device-libs-popover'); if ($popover.is(':hidden')) { - $icon.removeClass('icon-caret-up').addClass('icon-caret-down'); + $icon.removeClass('icon-caret-down').addClass('icon-caret-up'); $popover.removeClass('hide'); $(document).on('click', { view: this }, this._hidePopover); } else { - $icon.removeClass('icon-caret-down').addClass('icon-caret-up'); + $icon.removeClass('icon-caret-up').addClass('icon-caret-down'); $popover.addClass('hide'); $(document).off('click', this._hidePopover); } diff --git a/static/scripts/app/views/starred-file-item.js b/static/scripts/app/views/starred-file-item.js index d090f5f09c..32cb1cfb3f 100644 --- a/static/scripts/app/views/starred-file-item.js +++ b/static/scripts/app/views/starred-file-item.js @@ -2,22 +2,22 @@ define([ 'jquery', 'underscore', 'backbone', - 'common' -], function($, _, Backbone, Common) { + 'common', + 'app/views/widgets/hl-item-view' +], function($, _, Backbone, Common, HLItemView) { 'use strict'; - var StarredFileView = Backbone.View.extend({ + var StarredFileView = HLItemView.extend({ tagName: 'tr', template: _.template($('#starred-file-item-tmpl').html()), events: { - 'mouseenter': 'showAction', - 'mouseleave': 'hideAction', 'click .unstar': 'removeShare' }, initialize: function() { + HLItemView.prototype.initialize.call(this); }, render: function () { @@ -48,16 +48,6 @@ define([ Common.ajaxErrorHandler(xhr); } }); - }, - - showAction: function() { - this.$el.addClass('hl'); - this.$el.find('.op-icon').removeClass('vh'); - }, - - hideAction: function() { - this.$el.removeClass('hl'); - this.$el.find('.op-icon').addClass('vh'); } }); diff --git a/static/scripts/app/views/widgets/dropdown.js b/static/scripts/app/views/widgets/dropdown.js new file mode 100644 index 0000000000..1d94878d22 --- /dev/null +++ b/static/scripts/app/views/widgets/dropdown.js @@ -0,0 +1,84 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'common', +], function($, _, Backbone, Common) { + 'use strict'; + + /* + * Dropdown View. + */ + + // There can be only one visible dropdown view + $(document).click(function(e) { + var view = app.ui.currentDropdown; + var target = e.target || event.srcElement; + + if (!view) { + return true; + } + + if (!view.$('.js-dropdown-content').is(target) + && !view.$('.js-dropdown-content').find('*').is(target)) + { + view.hide(); + if (app.ui.currentHighlightedItem) { + app.ui.currentHighlightedItem.rmHighlight(); + } + } + return true; + }); + + var DropdownView = Backbone.View.extend({ + + toggleClass: '.js-dropdown-toggle', + popupClass: '.js-dropdown-content', + + initialize: function(options) { + this.$el.on('click', '.js-dropdown-toggle', _.bind(this.toggleDropdown, this)); + }, + + _hideDropdown: function(e) { + var view = e.data.view; + var target = e.target || event.srcElement; + if (!view.$(view.popupClass).is(target) + && !view.$(view.popupClass).find('*').is(target) + && !view.$(view.toggleClass).is(target)) { + $(view.popupClass).addClass('hide'); + view.rmHighlight(); + $(document).off('click', view._hidePopup); + if (view.onPopupHide) { + view.onPopupHide(); + } + } + }, + + hide: function() { + app.ui.currentDropdown = null; + this.$('.js-dropdown-content').addClass('hide'); + }, + + show: function() { + app.ui.currentDropdown = this; + this.$('.js-dropdown-content').removeClass('hide'); + }, + + toggleDropdown: function() { + if (app.ui.currentDropdown && app.ui.currentDropdown != this) { + app.ui.currentDropdown.hide(); + } + + if (this.$('.js-dropdown-content').is(':hidden')) { + this.show(); + } else { + this.hide(); + } + + return false; + } + + }); + + return DropdownView; +}); diff --git a/static/scripts/app/views/widgets/hl-item-view.js b/static/scripts/app/views/widgets/hl-item-view.js new file mode 100644 index 0000000000..d40160465d --- /dev/null +++ b/static/scripts/app/views/widgets/hl-item-view.js @@ -0,0 +1,41 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'common', +], function($, _, Backbone, Common) { + 'use strict'; + + /* + * Hightable Item View. + */ + var HLItemView = Backbone.View.extend({ + tagName: 'tr', + + hiddenOperationClass: '.op-icon', + + initialize: function(options) { + this.$el.on('mouseenter', _.bind(this.highlight, this)); + this.$el.on('mouseleave', _.bind(this.rmHighlight, this)); + }, + + highlight: function() { + if (app.ui.currentDropdown) { + return; + } + app.ui.currentHighlightedItem = this; + this.$el.addClass('hl').find(this.hiddenOperationClass).removeClass('vh'); + }, + + rmHighlight: function() { + if (app.ui.currentDropdown) { + return; + } + app.ui.currentHighlightedItem = null; + this.$el.removeClass('hl').find(this.hiddenOperationClass).addClass('vh'); + } + + }); + + return HLItemView; +});