diff --git a/apps/common/main/lib/view/LanguageDialog.js b/apps/common/main/lib/view/LanguageDialog.js new file mode 100644 index 000000000..613f90ede --- /dev/null +++ b/apps/common/main/lib/view/LanguageDialog.js @@ -0,0 +1,143 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2017 + * + * 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 + * + */ + +/** + * LanguageDialog.js + * + * Created by Julia Radzhabova on 04/25/2017 + * Copyright (c) 2017 Ascensio System SIA. All rights reserved. + * + */ + +if (Common === undefined) + var Common = {}; + +define([ + 'common/main/lib/component/Window' +], function () { 'use strict'; + + Common.Views.LanguageDialog = Common.UI.Window.extend(_.extend({ + + options: { + header: false, + width: 350, + cls: 'modal-dlg' + }, + + template: '
' + + '
' + + '' + + '
' + + '
' + + '
' + + '
' + + '', + + initialize : function(options) { + _.extend(this.options, options || {}, { + label: this.labelSelect, + btns: {ok: this.btnOk, cancel: this.btnCancel} + }); + this.options.tpl = _.template(this.template)(this.options); + + Common.UI.Window.prototype.initialize.call(this, this.options); + }, + + render: function() { + Common.UI.Window.prototype.render.call(this); + + var $window = this.getChild(); + $window.find('.dlg-btn').on('click', _.bind(this.onBtnClick, this)); + + this.cmbLanguage = new Common.UI.ComboBox({ + el: $window.find('#id-document-language'), + cls: 'input-group-nr', + menuStyle: 'min-width: 318px; max-height: 300px;', + editable: false, + template: _.template([ + '', + '', + '', + '', + '', + '' + ].join('')), + data: this.options.languages + }); + + if (this.cmbLanguage.scroller) this.cmbLanguage.scroller.update({alwaysVisibleY: true}); + this.cmbLanguage.on('selected', _.bind(this.onLangSelect, this)); + this.cmbLanguage.setValue(Common.util.LanguageInfo.getLocalLanguageName(this.options.current)[0]); + this.onLangSelect(this.cmbLanguage, this.cmbLanguage.getSelectedRecord()); + }, + + close: function(suppressevent) { + var $window = this.getChild(); + if (!$window.find('.combobox.open').length) { + Common.UI.Window.prototype.close.call(this, arguments); + } + }, + + onBtnClick: function(event) { + if (this.options.handler) { + this.options.handler.call(this, event.currentTarget.attributes['result'].value, this.cmbLanguage.getValue()); + } + + this.close(); + }, + + onLangSelect: function(cmb, rec, e) { + var icon = cmb.$el.find('.input-lang-icon'), + plang = icon.attr('lang'); + + if (plang) icon.removeClass(plang); + icon.addClass(rec.value).attr('lang',rec.value); + }, + + labelSelect : 'Select document language', + btnCancel : 'Cancel', + btnOk : 'Ok' + }, Common.Views.LanguageDialog || {})) +}); \ No newline at end of file diff --git a/apps/common/main/resources/img/controls/flags.png b/apps/common/main/resources/img/controls/flags.png new file mode 100644 index 000000000..f446f0639 Binary files /dev/null and b/apps/common/main/resources/img/controls/flags.png differ diff --git a/apps/common/main/resources/img/controls/flags@2x.png b/apps/common/main/resources/img/controls/flags@2x.png new file mode 100644 index 000000000..1c3c34b3c Binary files /dev/null and b/apps/common/main/resources/img/controls/flags@2x.png differ diff --git a/apps/common/main/resources/less/asc-mixins.less b/apps/common/main/resources/less/asc-mixins.less index c259f8f90..20d7427a2 100644 --- a/apps/common/main/resources/less/asc-mixins.less +++ b/apps/common/main/resources/less/asc-mixins.less @@ -178,4 +178,20 @@ background-image: data-uri(%("%s",'@{common-image-path}/hsbcolorpicker/hsb-colorpicker@2x.png')); background-size: @img-colorpicker-width auto; } +} + +@img-flags-width: 48px; +.lang-flag { + width: 16px; + height: 12px; + background-image: data-uri(%("%s",'@{common-image-path}/controls/flags.png')); + background-repeat: no-repeat; + + @media + only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min-resolution: 2dppx), + only screen and (min-resolution: 192dpi) { + background-image: data-uri(%("%s",'@{common-image-path}/controls/flags@2x.png')); + background-size: @img-flags-width auto; + } } \ No newline at end of file diff --git a/apps/common/main/resources/less/language-dialog.less b/apps/common/main/resources/less/language-dialog.less new file mode 100644 index 000000000..eb0d4bf78 --- /dev/null +++ b/apps/common/main/resources/less/language-dialog.less @@ -0,0 +1,67 @@ +.combo-langs { + .dropdown-menu { + li .lang-item-icon { + margin-top: 1px; + } + } + + .input-lang-icon { + position: absolute; + left: 5px; + top: 5px; + } + + input { + padding-left: 25px !important; + } +} + +.lang-flag { + background-position: -16px -108px; + + &.ca, &.ca-ES {background-position: 0 0;} + &.cs, &.cs-CZ {background-position: -16px 0;} + &.da, &.da-DK {background-position: -32px 0;} + &.de, &.de-DE {background-position: 0 -12px;} + &.el, &.el-GR {background-position: -16px -12px;} + &.en, &.en-US {background-position: -32px -12px;} + &.fr, &.fr-FR {background-position: 0 -24px;} + &.hu, &.hu-HU {background-position: -16px -24px;} + &.it, &.it-IT {background-position: -32px -24px;} + &.ko, &.ko-KR {background-position: 0 -36px;} + &.nl, &.nl-NL {background-position: -16px -36px;} + &.nb, &.nb-NO {background-position: -32px -36px;} + &.pl, &.pl-PL {background-position: 0 -48px;} + &.pt, &.pt-BR {background-position: -16px -48px;} + &.ro, &.ro-RO {background-position: -32px -48px;} + &.ru, &.ru-RU {background-position: 0 -60px;} + &.sv, &.sv-SE {background-position: -32px -60px;} + &.tr, &.tr-TR {background-position: 0 -72px;} + &.uk, &.uk-UA {background-position: -16px -72px;} + &.lv, &.lv-LV {background-position: -32px -72px;} + &.lt, &.lt-LT {background-position: 0 -84px;} + &.vi, &.vi-VN {background-position: -16px -84px;} + &.de-CH {background-position: -32px -84px;} + &.nn, &.nn-NO {background-position: 0 -96px;} + &.pt-PT {background-position: -16px -96px;} + &.de-AT {background-position: -32px -96px;} + &.es, &.es-ES {background-position: 0 -108px;} + &.en-GB {background-position: -32px -108px;} + &.en-AU {background-position: 0 -120px;} + &.az-Latn-AZ {background-position: -16px -120px;} + &.id, &.id-ID {background-position: -32px -120px;} + + &.bg, &.bg-BG {background-position: 0 -132px;} + &.ca-ES-valencia {background-position: -16px -132px;} + &.en-CA {background-position: -32px -132px;} + &.en-ZA {background-position: 0 -144px;} + &.eu, &.eu-ES {background-position: -16px -144px;} + &.gl, &.gl-ES {background-position: -32px -144px;} + &.hr, &.hr-HR {background-position: 0 -156px;} + &.lb, &.lb-LU {background-position: -16px -156px;} + &.mn, &.mn-MN {background-position: -32px -156px;} + &.sl, &.sl-SI {background-position: 0 -168px;} + &.sr, &.sr-Cyrl-RS, &.sr-Latn-RS {background-position: -16px -168px;} + &.sk, &.sk-SK {background-position: -32px -168px;} + &.kk, &.kk-KZ {background-position: 0 -180px;} +} diff --git a/apps/documenteditor/main/app/controller/Statusbar.js b/apps/documenteditor/main/app/controller/Statusbar.js index 9712cf9e0..92feb12e1 100644 --- a/apps/documenteditor/main/app/controller/Statusbar.js +++ b/apps/documenteditor/main/app/controller/Statusbar.js @@ -44,7 +44,8 @@ define([ 'core', 'documenteditor/main/app/view/Statusbar', 'common/main/lib/util/LanguageInfo', - 'common/main/lib/view/ReviewChanges' + 'common/main/lib/view/ReviewChanges', + 'common/main/lib/view/LanguageDialog' ], function () { 'use strict'; @@ -141,9 +142,6 @@ define([ }); }, - /* - * */ - setLanguages: function(langs) { this.langs = langs; this.statusbar.reloadLanguages(langs); @@ -239,7 +237,7 @@ define([ }); var me = this; - (new DE.Views.Statusbar.LanguageDialog({ + (new Common.Views.LanguageDialog({ languages: langs, current: me.api.asc_getDefaultLanguage(), handler: function(result, tip) { diff --git a/apps/documenteditor/main/app/template/StatusBar.template b/apps/documenteditor/main/app/template/StatusBar.template index d46ad1658..3e742c47c 100644 --- a/apps/documenteditor/main/app/template/StatusBar.template +++ b/apps/documenteditor/main/app/template/StatusBar.template @@ -29,7 +29,7 @@
+
+ + + +
diff --git a/apps/presentationeditor/main/app/view/FileMenuPanels.js b/apps/presentationeditor/main/app/view/FileMenuPanels.js index e6b61a70a..99d9f8f65 100644 --- a/apps/presentationeditor/main/app/view/FileMenuPanels.js +++ b/apps/presentationeditor/main/app/view/FileMenuPanels.js @@ -111,6 +111,10 @@ define([ template: _.template([ '', + '', + '', + '', + '','', '', '', '', @@ -159,6 +163,11 @@ define([ render: function() { $(this.el).html(this.template({scope: this})); + this.chSpell = new Common.UI.CheckBox({ + el: $('#fms-chb-spell-check'), + labelText: this.strSpellCheckMode + }); + this.chInputMode = new Common.UI.CheckBox({ el: $('#fms-chb-input-mode'), labelText: this.strInputMode @@ -279,6 +288,9 @@ define([ var value = Common.localStorage.getItem("pe-settings-inputmode"); this.chInputMode.setValue(value!==null && parseInt(value) == 1); + value = Common.localStorage.getItem("pe-settings-spellcheck"); + this.chSpell.setValue(value===null || parseInt(value) == 1); + value = Common.localStorage.getItem("pe-settings-zoom"); value = (value!==null) ? parseInt(value) : (this.mode.customization && this.mode.customization.zoom ? parseInt(this.mode.customization.zoom) : -1); var item = this.cmbZoom.store.findWhere({value: value}); @@ -317,6 +329,7 @@ define([ }, applySettings: function() { + Common.localStorage.setItem("pe-settings-spellcheck", this.chSpell.isChecked() ? 1 : 0); Common.localStorage.setItem("pe-settings-inputmode", this.chInputMode.isChecked() ? 1 : 0); Common.localStorage.setItem("pe-settings-zoom", this.cmbZoom.getValue()); /** coauthoring begin **/ @@ -366,7 +379,9 @@ define([ txtInch: 'Inch', txtFitWidth: 'Fit to Width', textForceSave: 'Save to Server', - strForcesave: 'Always save to server (otherwise save to server on document close)' + strForcesave: 'Always save to server (otherwise save to server on document close)', + txtSpellCheck: 'Spell Checking', + strSpellCheckMode: 'Turn on spell checking option' }, PE.Views.FileMenuPanels.Settings || {})); PE.Views.FileMenuPanels.RecentFiles = Common.UI.BaseView.extend({ diff --git a/apps/presentationeditor/main/app/view/Statusbar.js b/apps/presentationeditor/main/app/view/Statusbar.js index 0350076d5..3e295333e 100644 --- a/apps/presentationeditor/main/app/view/Statusbar.js +++ b/apps/presentationeditor/main/app/view/Statusbar.js @@ -66,6 +66,19 @@ define([ Common.Utils.String.format(this.pageIndexText, model.get('current'), model.get('count')) ); } + function _clickLanguage(menu, item, state) { + var $parent = menu.$el.parent(); + + $parent.find('#status-label-lang').text(item.caption); + $parent.find('.dropdown-toggle > .icon-lang-flag') + .removeClass(this.langMenu.prevTip) + .addClass(item.value.tip); + + this.langMenu.prevTip = item.value.tip; + + this.fireEvent('langchanged', [this, item.value.code, item.caption]); + } + PE.Views.Statusbar = Backbone.View.extend(_.extend({ el: '#statusbar', template: _.template(template), @@ -271,6 +284,62 @@ define([ hintAnchor: 'top' }); + this.btnDocLanguage = new Common.UI.Button({ + el: $('#btn-doc-lang',this.el), + hint: this.tipSetDocLang, + hintAnchor: 'top', + disabled: true + }); + + this.btnSetSpelling = new Common.UI.Button({ + el: $('#btn-doc-spell',this.el), + enableToggle: true, + hint: this.tipSetSpelling, + hintAnchor: 'top' + }); + + var panelLang = $('.cnt-lang',this.el); + this.langMenu = new Common.UI.Menu({ + style: 'margin-top:-5px;', + maxHeight: 300, + itemTemplate: _.template([ + '', + '', + '<%= caption %>', + '' + ].join('')), + menuAlign: 'bl-tl' + }); + + this.btnLanguage = new Common.UI.Button({ + el: panelLang, + hint: this.tipSetLang, + hintAnchor: 'top-left', + disabled: true + }); + this.btnLanguage.cmpEl.on({ + 'show.bs.dropdown': function () { + _.defer(function(){ + me.btnLanguage.cmpEl.find('ul').focus(); + }, 100); + }, + 'hide.bs.dropdown': function () { + _.defer(function(){ + me.api.asc_enableKeyEvents(true); + }, 100); + }, + 'click': function (e) { + if (me.btnLanguage.isDisabled()) { + return false; + } + } + }); + + this.langMenu.render(panelLang); + this.langMenu.cmpEl.attr({tabindex: -1}); + this.langMenu.prevTip = 'en'; + this.langMenu.on('item:click', _.bind(_clickLanguage,this)); + return this; }, @@ -375,6 +444,49 @@ define([ $('#status-label-action').text(''); }, + reloadLanguages: function(array) { + this.langMenu.removeAll(); + _.each(array, function(item) { + this.langMenu.addItem({ + iconCls : item['tip'], + caption : item['title'], + value : {tip: item['tip'], code: item['code']}, + checkable : true, + checked : this.langMenu.saved == item.title, + toggleGroup : 'language' + }); + }, this); + + this.langMenu.doLayout(); + if (this.langMenu.items.length>0) { + this.btnLanguage.setDisabled(false); + this.btnDocLanguage.setDisabled(false); + } + }, + + setLanguage: function(info) { + if (this.langMenu.prevTip != info.tip && info.code !== undefined) { + var $parent = $(this.langMenu.el.parentNode, this.$el); + $parent.find('.dropdown-toggle > .icon-lang-flag') + .removeClass(this.langMenu.prevTip) + .addClass(info.tip); + + this.langMenu.prevTip = info.tip; + + $parent.find('#status-label-lang').text(info.title); + + var index = $parent.find('ul li a:contains("'+info.title+'")').parent().index(); + index < 0 ? this.langMenu.saved = info.title : + this.langMenu.items[index-1].setChecked(true); + } + }, + + SetDisabled: function(disable) { + var langs = this.langMenu.items.length>0; + this.btnLanguage.setDisabled(disable || !langs); + this.btnDocLanguage.setDisabled(disable || !langs); + }, + pageIndexText : 'Slide {0} of {1}', goToPageText : 'Go to Slide', tipUsers : 'Document is currently being edited by several users.', @@ -389,7 +501,10 @@ define([ tipPreview : 'Start Slideshow', tipAccessRights : 'Manage document access rights', tipViewUsers : 'View users and manage document access rights', - txAccessRights : 'Change access rights' + txAccessRights : 'Change access rights', + tipSetLang : 'Set Text Language', + tipSetDocLang : 'Set Document Language', + tipSetSpelling : 'Spell checking' }, PE.Views.Statusbar || {})); } ); \ No newline at end of file diff --git a/apps/presentationeditor/main/locale/en.json b/apps/presentationeditor/main/locale/en.json index c123204d5..454b37ae7 100644 --- a/apps/presentationeditor/main/locale/en.json +++ b/apps/presentationeditor/main/locale/en.json @@ -94,6 +94,9 @@ "Common.Views.InsertTableDialog.txtMinText": "The minimum value for this field is {0}.", "Common.Views.InsertTableDialog.txtRows": "Number of Rows", "Common.Views.InsertTableDialog.txtTitle": "Table Size", + "Common.Views.LanguageDialog.btnCancel": "Cancel", + "Common.Views.LanguageDialog.btnOk": "Ok", + "Common.Views.LanguageDialog.labelSelect": "Select document language", "Common.Views.OpenDialog.cancelButtonText": "Cancel", "Common.Views.OpenDialog.okButtonText": "OK", "Common.Views.OpenDialog.txtEncoding": "Encoding ", @@ -821,6 +824,8 @@ "PE.Views.FileMenuPanels.Settings.txtInput": "Alternate Input", "PE.Views.FileMenuPanels.Settings.txtLast": "View Last", "PE.Views.FileMenuPanels.Settings.txtPt": "Point", + "PE.Views.FileMenuPanels.Settings.txtSpellCheck": "Spell Checking", + "PE.Views.FileMenuPanels.Settings.strSpellCheckMode": "Turn on spell checking option", "PE.Views.HyperlinkSettingsDialog.cancelButtonText": "Cancel", "PE.Views.HyperlinkSettingsDialog.okButtonText": "OK", "PE.Views.HyperlinkSettingsDialog.strDisplay": "Display", @@ -1105,6 +1110,9 @@ "PE.Views.Statusbar.tipZoomIn": "Zoom In", "PE.Views.Statusbar.tipZoomOut": "Zoom Out", "PE.Views.Statusbar.txAccessRights": "Change access rights", + "PE.Views.Statusbar.tipSetLang": "Set Text Language", + "PE.Views.Statusbar.tipSetDocLang": "Set Document Language", + "PE.Views.Statusbar.tipSetSpelling": "Spell checking", "PE.Views.Statusbar.txtPageNumInvalid": "Invalid slide number", "PE.Views.TableSettings.deleteColumnText": "Delete Column", "PE.Views.TableSettings.deleteRowText": "Delete Row", diff --git a/apps/presentationeditor/main/resources/less/app.less b/apps/presentationeditor/main/resources/less/app.less index 89589a777..54446155e 100644 --- a/apps/presentationeditor/main/resources/less/app.less +++ b/apps/presentationeditor/main/resources/less/app.less @@ -111,6 +111,7 @@ @import "../../../../common/main/resources/less/common.less"; @import "../../../../common/main/resources/less/opendialog.less"; @import "../../../../common/main/resources/less/plugins.less"; +@import "../../../../common/main/resources/less/language-dialog.less"; // App // -------------------------------------------------- diff --git a/apps/presentationeditor/main/resources/less/statusbar.less b/apps/presentationeditor/main/resources/less/statusbar.less index ce9f2f15a..e22026c35 100644 --- a/apps/presentationeditor/main/resources/less/statusbar.less +++ b/apps/presentationeditor/main/resources/less/statusbar.less @@ -56,6 +56,16 @@ .btn-tpl(-1220px); } + #btn-doc-lang { + .btn-tpl(-160px); + margin-right: 9px; + } + + #btn-doc-spell { + .btn-tpl(-160px); + margin-right: 5px; + } + #status-btn-preview { .btn-tpl(-160px); } @@ -78,6 +88,49 @@ } } + .cnt-lang { + display: inline-block; + cursor: pointer; + color: #000; + margin-left: 6px; + + .dropdown-toggle > .icon-lang-flag { + position: relative; + top: 3px; + margin-left: 3px; + margin-right: 2px; + display: inline-block; + } + + .caret.up { + background-position: @arrow-up-small-offset-x @arrow-up-small-offset-y; + + border: none; + width: 7px; + height: 7px; + } + + label { + cursor: pointer; + } + + .dropdown-menu { + li .lang-item-icon { + display: inline-block; + vertical-align: text-bottom; + margin: 1px 5px 0 2px; + } + } + + &.disabled { + cursor: default; + label, .icon-lang-flag { + cursor: default; + opacity: 0.4; + } + } + } + .cnt-zoom { display: inline-block; @@ -165,4 +218,3 @@ } } } -