web-apps/apps/common/main/lib/view/Header.js

604 lines
24 KiB
JavaScript
Raw Normal View History

2016-04-01 13:17:09 +00:00
/*
*
2017-01-17 14:58:08 +00:00
* (c) Copyright Ascensio System Limited 2010-2017
2016-04-01 13:17:09 +00:00
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
2016-03-11 00:48:53 +00:00
/**
* Header.js
*
* Created by Alexander Yuzhin on 2/14/14
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
*
*/
if (Common === undefined)
var Common = {};
Common.Views = Common.Views || {};
define([
'backbone',
'text!common/main/lib/template/Header.template',
2016-09-26 10:54:25 +00:00
'core',
'common/main/lib/view/RenameDialog'
2016-03-11 00:48:53 +00:00
], function (Backbone, headerTemplate) { 'use strict';
2017-03-01 13:33:12 +00:00
Common.Views.Header = Backbone.View.extend(_.extend(function(){
2017-03-16 10:20:07 +00:00
var storeUsers, appConfig;
var $userList, $panelUsers, $btnUsers;
var $saveStatus;
var templateUserItem =
'<li id="status-chat-user-<%= user.get("id") %>" class="<% if (!user.get("online")) { %> offline <% } if (user.get("view")) {%> viewmode <% } %>">' +
'<div class="color" style="background-color: <%= user.get("color") %>;" >' +
'<label class="name"><%= fnEncode(user.get("username")) %></label>' +
'</div>' +
'</li>';
var templateUserList = _.template(
'<ul>' +
'<% _.each(users, function(item) { %>' +
'<%= usertpl({user: item, fnEncode: fnEncode}) %>' +
'<% }); %>' +
'</ul>');
var templateRightBox = '<section>' +
2017-08-15 11:44:59 +00:00
'<section id="box-doc-name">' +
'<input type="text" id="rib-doc-name" spellcheck="false" data-can-copy="false"></input>' +
'</section>' +
2017-04-28 10:44:03 +00:00
'<a id="rib-save-status" class="status-label locked"><%= textSaveEnd %></a>' +
2017-07-13 09:43:40 +00:00
'<div class="hedset">' +
'<div class="btn-slot" id="slot-hbtn-edit"></div>' +
2017-07-13 09:43:40 +00:00
'<div class="btn-slot" id="slot-hbtn-print"></div>' +
'<div class="btn-slot" id="slot-hbtn-download"></div>' +
'</div>' +
'<div class="hedset">' +
// '<span class="btn-slot text" id="slot-btn-users"></span>' +
'<section id="tlb-box-users" class="box-cousers dropdown"">' +
'<div class="btn-users">' +
'<svg class="icon"><use xlink:href="#svg-btn-users"></use></svg>' +
'<label class="caption">&plus;</label>' +
'</div>' +
'<div class="cousers-menu dropdown-menu">' +
'<label id="tlb-users-menu-descr"><%= tipUsers %></label>' +
'<div class="cousers-list"></div>' +
'<label id="tlb-change-rights" class="link"><%= txtAccessRights %></label>' +
'</div>' +
'</section>'+
'</div>' +
'<div class="hedset">' +
2017-05-04 12:39:17 +00:00
'<div class="btn-slot" id="slot-btn-back"></div>' +
2017-03-01 13:33:12 +00:00
'</div>' +
'</section>';
2017-04-22 14:51:12 +00:00
var templateLeftBox = '<section class="logo">' +
2017-04-25 16:52:51 +00:00
'<div id="header-logo"><i /></div>' +
'</section>';
function onAddUser(model, collection, opts) {
if ( $userList ) {
var $ul = $userList.find('ul');
if ( !$ul.length ) {
$userList.html( templateUserList({
users: collection.models,
usertpl: _.template(templateUserItem),
fnEncode: Common.Utils.String.htmlEncode
})
);
} else {
2017-04-21 08:15:04 +00:00
$ul.append( _.template(templateUserItem)({
user: model,
fnEncode: Common.Utils.String.htmlEncode
}) );
}
$userList.scroller && $userList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
}
2017-08-17 12:39:28 +00:00
applyUsers( collection.getEditingCount() );
};
function onUsersChanged(model, collection) {
if (model.changed.online != undefined && $userList) {
$userList.find('#status-chat-user-'+ model.get('id'))[model.changed.online ? 'removeClass' : 'addClass']('offline');
$userList.scroller && $userList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
}
2017-08-17 12:39:28 +00:00
applyUsers(model.collection.getEditingCount());
};
function onResetUsers(collection, opts) {
2017-08-17 12:39:28 +00:00
var usercount = collection.getEditingCount();
if ( $userList ) {
if ( usercount > 1 || usercount > 0 && appConfig && !appConfig.isEdit) {
$userList.html(templateUserList({
users: collection.models,
usertpl: _.template(templateUserItem),
fnEncode: Common.Utils.String.htmlEncode
}));
$userList.scroller = new Common.UI.Scroller({
el: $userList.find('ul'),
useKeyboard: true,
minScrollbarLength: 40,
alwaysVisibleY: true
});
} else {
$userList.empty();
}
}
applyUsers( usercount );
};
function applyUsers(count) {
if ( count > 1 || count > 0 && appConfig && !appConfig.isEdit) {
$btnUsers
.attr('data-toggle', 'dropdown')
.addClass('dropdown-toggle')
.menu = true;
$panelUsers['show']();
} else {
$btnUsers
.removeAttr('data-toggle')
.removeClass('dropdown-toggle')
.menu = false;
2017-03-16 10:20:07 +00:00
$panelUsers[(appConfig && !appConfig.isReviewOnly && appConfig.sharingSettingsUrl && appConfig.sharingSettingsUrl.length) ? 'show' : 'hide']();
}
$btnUsers.find('.caption')
.css({'font-size': ((count > 1 || count > 0 && appConfig && !appConfig.isEdit) ? '12px' : '14px'),
'margin-top': ((count > 1 || count > 0 && appConfig && !appConfig.isEdit) ? '0' : '-1px')})
.html((count > 1 || count > 0 && appConfig && !appConfig.isEdit) ? count : '&plus;');
var usertip = $btnUsers.data('bs.tooltip');
if ( usertip ) {
usertip.options.title = (count > 1 || count > 0 && appConfig && !appConfig.isEdit) ? usertip.options.titleExt : usertip.options.titleNorm;
usertip.setContent();
}
}
function onUsersClick(e) {
if ( !$btnUsers.menu ) {
$panelUsers.removeClass('open');
this.fireEvent('click:users', this);
return false;
}
var usertip = $btnUsers.data('bs.tooltip');
if ( usertip ) {
if ( usertip.dontShow===undefined)
usertip.dontShow = true;
usertip.hide();
}
}
function onAppReady(mode) {
appConfig = mode;
var me = this;
2018-02-07 10:57:46 +00:00
if ( !(me.branding && me.branding.goback && me.branding.goback.text) )
2018-02-07 08:11:58 +00:00
me.btnGoBack.updateHint(me.textBack);
me.btnGoBack.on('click', function (e) {
2017-07-13 08:50:36 +00:00
Common.NotificationCenter.trigger('goback', true);
});
2017-05-04 12:36:42 +00:00
if ( me.logo )
me.logo.children(0).on('click', function (e) {
2017-05-04 12:36:42 +00:00
var _url = !!me.branding && !!me.branding.logo && !!me.branding.logo.url ?
me.branding.logo.url : 'http://www.onlyoffice.com';
var newDocumentPage = window.open(_url);
newDocumentPage && newDocumentPage.focus();
2017-05-04 12:36:42 +00:00
});
2017-08-24 08:44:11 +00:00
onResetUsers(storeUsers);
$panelUsers.on('shown.bs.dropdown', function () {
$userList.scroller && $userList.scroller.update({minScrollbarLength: 40, alwaysVisibleY: true});
});
$panelUsers.find('.cousers-menu')
.on('click', function(e) { return false; });
2017-08-17 12:39:28 +00:00
var editingUsers = storeUsers.getEditingCount();
$btnUsers.tooltip({
2017-08-17 12:39:28 +00:00
title: (editingUsers > 1 || editingUsers>0 && !appConfig.isEdit) ? me.tipViewUsers : me.tipAccessRights,
titleNorm: me.tipAccessRights,
titleExt: me.tipViewUsers,
placement: 'bottom',
html: true
});
$btnUsers.on('click', onUsersClick.bind(me));
var $labelChangeRights = $panelUsers.find('#tlb-change-rights');
2017-08-21 07:53:39 +00:00
$labelChangeRights.on('click', function(e) {
$panelUsers.removeClass('open');
me.fireEvent('click:users', me);
});
$labelChangeRights[(!mode.isOffline && !mode.isReviewOnly && mode.sharingSettingsUrl && mode.sharingSettingsUrl.length)?'show':'hide']();
2017-08-17 12:39:28 +00:00
$panelUsers[(editingUsers > 1 || editingUsers > 0 && !appConfig.isEdit || !mode.isOffline && !mode.isReviewOnly && mode.sharingSettingsUrl && mode.sharingSettingsUrl.length) ? 'show' : 'hide']();
2017-05-04 12:36:42 +00:00
if ( $saveStatus ) {
$saveStatus.attr('data-width', me.textSaveExpander);
if (appConfig.canUseHistory) {
// $saveStatus.on('click', function(e) {
// me.fireEvent('history:show', ['header']);
// });
} else {
$saveStatus.addClass('locked');
}
}
2017-07-13 09:43:40 +00:00
if ( !mode.isEdit ) {
if ( me.btnDownload ) {
2017-08-07 14:10:03 +00:00
me.btnDownload.updateHint(me.tipDownload);
2017-07-13 09:43:40 +00:00
me.btnDownload.on('click', function (e) {
me.fireEvent('downloadas', ['original']);
});
}
if ( me.btnPrint ) {
me.btnPrint.updateHint(me.tipPrint + Common.Utils.String.platformKey('Ctrl+P'));
2017-07-13 09:43:40 +00:00
me.btnPrint.on('click', function (e) {
me.fireEvent('print', me);
});
}
if ( me.btnEdit ) {
2017-07-21 10:44:07 +00:00
me.btnEdit.updateHint(me.tipGoEdit);
me.btnEdit.on('click', function (e) {
me.fireEvent('go:editor', me);
});
}
2017-07-13 09:43:40 +00:00
}
}
2017-08-01 12:14:19 +00:00
function onDocNameKeyDown(e) {
var me = this;
var name = me.labelDocName.val();
if ( e.keyCode == Common.UI.Keys.RETURN ) {
name = name.trim();
if ( !_.isEmpty(name) && me.documentCaption !== name ) {
if ( /[\t*\+:\"<>?|\\\\/]/gim.test(name) ) {
_.defer(function() {
Common.UI.error({
msg: (new Common.Views.RenameDialog).txtInvalidName + "*+:\"<>?|\/"
, callback: function() {
_.delay(function() {
me.labelDocName.focus();
}, 50);
}
});
me.labelDocName.blur();
})
} else {
Common.Gateway.requestRename(name);
Common.NotificationCenter.trigger('edit:complete', me);
}
}
} else
if ( e.keyCode == Common.UI.Keys.ESC ) {
me.labelDocName.val(me.documentCaption);
Common.NotificationCenter.trigger('edit:complete', this);
} else {
me.labelDocName.attr('size', name.length > 10 ? name.length : 10);
}
}
2017-03-01 13:33:12 +00:00
return {
options: {
branding: {},
headerCaption: 'Default Caption',
documentCaption: '',
canBack: false
},
el: '#header',
// Compile our stats template
template: _.template(headerTemplate),
// Delegated events for creating new items, and clearing completed ones.
events: {
// 'click #header-logo': function (e) {}
},
initialize: function (options) {
var me = this;
this.options = this.options ? _({}).extend(this.options, options) : options;
this.headerCaption = this.options.headerCaption;
this.documentCaption = this.options.documentCaption;
this.canBack = this.options.canBack;
this.branding = this.options.customization;
this.isModified = false;
2017-03-01 13:33:12 +00:00
me.btnGoBack = new Common.UI.Button({
id: 'btn-goback',
cls: 'btn-header',
2017-04-20 13:36:15 +00:00
iconCls: 'svgicon svg-btn-goback',
2017-05-04 12:39:17 +00:00
split: true
2017-03-01 13:33:12 +00:00
});
2016-03-11 00:48:53 +00:00
2017-03-29 09:01:34 +00:00
storeUsers = this.options.storeUsers;
storeUsers.bind({
add : onAddUser,
change : onUsersChanged,
reset : onResetUsers
2017-03-01 13:33:12 +00:00
});
2017-04-06 09:42:43 +00:00
Common.NotificationCenter.on('app:ready', function(mode) {
2017-05-04 12:26:32 +00:00
Common.Utils.asyncCall(onAppReady, me, mode);
2017-04-06 09:42:43 +00:00
});
2017-03-01 13:33:12 +00:00
},
render: function (el, role) {
$(el).html(this.getPanel(role));
return this;
},
2017-05-04 12:36:42 +00:00
getPanel: function (role, config) {
if ( role == 'left' && (!config || !config.isDesktopApp)) {
$html = $(templateLeftBox);
2017-03-01 13:33:12 +00:00
this.logo = $html.find('#header-logo');
2017-09-18 11:38:24 +00:00
if (this.branding && this.branding.logo && this.branding.logo.image && this.logo) {
this.logo.html('<img src="' + this.branding.logo.image + '" style="max-width:100px; max-height:20px; margin: 0;"/>');
this.logo.css({'background-image': 'none', width: 'auto'});
}
2017-03-01 13:33:12 +00:00
return $html;
} else
if ( role == 'right' ) {
2017-04-21 08:15:04 +00:00
var $html = $(_.template(templateRightBox)({
tipUsers: this.labelCoUsersDescr,
2017-04-19 12:09:44 +00:00
txtAccessRights: this.txtAccessRights,
textSaveEnd: this.textSaveEnd
}));
2017-03-01 13:33:12 +00:00
2017-08-01 12:14:19 +00:00
if ( this.labelDocName ) this.labelDocName.off();
2017-05-04 12:36:42 +00:00
this.labelDocName = $html.find('#rib-doc-name');
2017-08-15 11:44:59 +00:00
// this.labelDocName.attr('maxlength', 50);
this.labelDocName.text = function (text) {
this.val(text).attr('size', text.length);
}
2017-08-01 12:14:19 +00:00
if ( this.documentCaption ) {
2017-08-15 11:44:59 +00:00
this.labelDocName.text( this.documentCaption );
}
if ( !_.isUndefined(this.options.canRename) ) {
this.setCanRename(this.options.canRename);
}
2017-05-04 12:36:42 +00:00
$saveStatus = $html.find('#rib-save-status');
$saveStatus.hide();
if ( config && config.isDesktopApp ) {
$html.addClass('desktop');
$html.find('#slot-btn-back').hide();
this.labelDocName.hide();
if ( config.isOffline )
$saveStatus = false;
} else {
if ( this.canBack === true ) {
this.btnGoBack.render($html.find('#slot-btn-back'));
} else {
$html.find('#slot-btn-back').hide();
}
2017-03-01 13:33:12 +00:00
}
2017-07-13 09:43:40 +00:00
if ( !config.isEdit ) {
if ( (config.canDownload || config.canDownloadOrigin) && !config.isOffline ) {
this.btnDownload = new Common.UI.Button({
cls: 'btn-header',
iconCls: 'svgicon svg-btn-download'
});
this.btnDownload.render($html.find('#slot-hbtn-download'));
}
if ( config.canPrint ) {
this.btnPrint = new Common.UI.Button({
cls: 'btn-header',
iconCls: 'svgicon svg-btn-print'
});
this.btnPrint.render($html.find('#slot-hbtn-print'));
}
if ( config.canEdit && config.canRequestEditRights ) {
(this.btnEdit = new Common.UI.Button({
cls: 'btn-header',
iconCls: 'svgicon svg-btn-edit'
})).render($html.find('#slot-hbtn-edit'));
}
2017-07-13 09:43:40 +00:00
}
$userList = $html.find('.cousers-list');
$panelUsers = $html.find('.box-cousers');
$btnUsers = $html.find('.btn-users');
$panelUsers.hide();
2017-03-01 13:33:12 +00:00
return $html;
}
},
setVisible: function (visible) {
// visible
// ? this.show()
// : this.hide();
},
setBranding: function (value) {
var element;
this.branding = value;
2018-02-07 08:11:58 +00:00
if ( value ) {
if ( value.logo && value.logo.image ) {
element = $('#header-logo');
if (element) {
element.html('<img src="' + value.logo.image + '" style="max-width:100px; max-height:20px; margin: 0;"/>');
element.css({'background-image': 'none', width: 'auto'});
}
}
2018-02-07 10:57:46 +00:00
if ( !!value.goback && value.goback.text) {
2018-02-07 08:11:58 +00:00
this.btnGoBack.updateHint(value.goback.text);
2017-03-01 13:33:12 +00:00
}
2016-09-26 10:54:25 +00:00
}
2017-03-01 13:33:12 +00:00
},
setHeaderCaption: function (value) {
this.headerCaption = value;
return value;
},
getHeaderCaption: function () {
return this.headerCaption;
},
setDocumentCaption: function(value) {
2017-03-01 13:33:12 +00:00
!value && (value = '');
this.documentCaption = value;
this.isModified && (value += '*');
2017-08-01 12:14:19 +00:00
if ( this.labelDocName ) {
2017-08-15 11:44:59 +00:00
this.labelDocName.text( value );
// this.labelDocName.attr('size', value.length);
2017-08-01 12:14:19 +00:00
this.setCanRename(true);
}
2017-03-01 13:33:12 +00:00
return value;
},
getDocumentCaption: function () {
return this.documentCaption;
},
setDocumentChanged: function (changed) {
this.isModified = changed;
var _name = this.documentCaption;
2017-03-01 13:33:12 +00:00
changed && (_name += '*');
2017-08-15 11:44:59 +00:00
this.labelDocName.text(_name);
2017-03-01 13:33:12 +00:00
},
setCanBack: function (value) {
this.canBack = value;
this.btnGoBack[value ? 'show' : 'hide']();
},
getCanBack: function () {
return this.canBack;
},
setCanRename: function (rename) {
2017-08-01 12:14:19 +00:00
rename = false;
var me = this;
me.options.canRename = rename;
if ( me.labelDocName ) {
var label = me.labelDocName;
if ( rename ) {
label.removeAttr('disabled').tooltip({
title: me.txtRename,
placement: 'cursor'}
);
2017-08-15 11:44:59 +00:00
label.on({
'keydown': onDocNameKeyDown.bind(this),
'blur': function (e) {
}
});
} else {
2017-08-15 11:44:59 +00:00
label.off();
label.attr('disabled', true);
var tip = label.data('bs.tooltip');
if ( tip ) {
tip.options.title = '';
tip.setContent();
}
2017-08-01 12:14:19 +00:00
}
label.attr('data-can-copy', rename);
2017-08-01 12:14:19 +00:00
}
2017-03-01 13:33:12 +00:00
},
setSaveStatus: function (status) {
if ( $saveStatus ) {
if ( $saveStatus.is(':hidden') ) $saveStatus.show();
var _text;
switch ( status ) {
case 'begin': _text = this.textSaveBegin; break;
case 'changed': _text = this.textSaveChanged; break;
default: _text = this.textSaveEnd;
}
$saveStatus.text( _text );
}
},
2017-03-01 13:33:12 +00:00
textBack: 'Go to Documents',
2017-04-19 12:09:44 +00:00
txtRename: 'Rename',
textSaveBegin: 'Saving...',
textSaveEnd: 'All changes saved',
textSaveChanged: 'Modified',
textSaveExpander: 'All changes saved',
txtAccessRights: 'Change access rights',
tipAccessRights: 'Manage document access rights',
labelCoUsersDescr: 'Document is currently being edited by several users.',
2017-07-21 10:44:07 +00:00
tipViewUsers: 'View users and manage document access rights',
tipDownload: 'Download file',
tipPrint: 'Print file',
tipGoEdit: 'Edit current file'
2017-03-01 13:33:12 +00:00
}
}(), Common.Views.Header || {}))
2016-03-11 00:48:53 +00:00
});