/* * (c) Copyright Ascensio System SIA 2010-2024 * * 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 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * 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 * */ /** * DocumentPreview.js * * Created on 4/18/14 * */ define([ 'jquery', 'underscore', 'backbone', 'common/main/lib/component/BaseView', 'presentationeditor/main/app/model/Pages', 'common/main/lib/component/InputField', 'common/main/lib/component/ColorPaletteExt', ], function () { 'use strict'; function _updatePagesCaption(model,value,opts) { var curr = model.get('current'), cnt = model.get('count'), start = model.get('start'); (curr>=cnt) && (curr = cnt-1); $('#preview-label-slides').text( Common.Utils.String.format(this.slideIndexText, curr + start, start===1 ? cnt : start + ' .. ' + (cnt + start - 1)) ); } PE.Views.DocumentPreview = Common.UI.BaseView.extend(_.extend({ el: '#pe-preview', // Delegated events for creating new items, and clearing completed ones. events: { }, options: { alias: 'DocumentPreview' }, initialize : function(options) { _.extend(this.options, options || {}); this.template = [ '
', '
', '
', '', '', '', '
', '
', '
', '', '', '
', '
', '
', '
', '
', '
', '
', '', '
', '', '
', '
' ].join(''); this.pages = new PE.Models.Pages({current:1, count:1, start:1}); this.pages.on('change', _.bind(_updatePagesCaption,this)); this.currentDrawColor = 'E81416'; this.drawTool = { pen: () => { Common.NotificationCenter.trigger('draw-tool:pen', { index: 0, color: this.currentDrawColor, size: 1, opacity: 100 }); this.editComplete(); }, highlighter: () => { Common.NotificationCenter.trigger('draw-tool:pen', { index: 1, color: this.currentDrawColor, size: 6, opacity: 50 }); this.editComplete(); }, eraser: () => { Common.NotificationCenter.trigger('draw-tool:eraser'); this.editComplete(); }, eraseAll: () => { Common.NotificationCenter.trigger('draw-tool:erase-all'); this.editComplete(); }, select: () => { Common.NotificationCenter.trigger('draw-tool:select'); this.editComplete(); } }; }, render: function () { var el = $(this.el), me = this; el.html(_.template(this.template)({ scope: this })); if (Common.Utils.isIE) { document.getElementById('preview-group-draw').style.display = 'none'; } else { this.btnDraw = new Common.UI.Button({ parentEl: $('#btn-preview-draw', this.el), cls: 'btn-toolbar small', iconCls: 'toolbar__icon btn-pen-tool', onlyIcon: true, stopPropagation: true, hint: this.txtDraw, hintAnchor: 'top', hintContainer: '#pe-preview', menu: new Common.UI.Menu({ menuAlign: 'tl-tr', cls: "shifted-right", style: 'min-width: 120px; height: auto; min-height: fit-content;', additionalAlign: function (root) { var parent = root.parent(); var parentOffset = Common.Utils.getOffset(parent); root.css({ left: parentOffset.left + (parent.outerWidth() - root.outerWidth()) / 2, top: parentOffset.top - root.outerHeight() - 8 }); }, items: [ new Common.UI.MenuItem({ caption: this.txtPen, value: 'pen', iconCls: 'menu__icon btn-pen-tool', checkable: true, toggleGroup: 'preview-draw-tool' }), new Common.UI.MenuItem({ caption: this.txtHighlighter, value: 'highlighter', iconCls: 'menu__icon btn-highlighter-tool', checkable: true, toggleGroup: 'preview-draw-tool' }), { caption: '--' }, { caption: this.txtInkColor, menu: new Common.UI.Menu({ menuAlign: 'tl-tr', cls: "preview-draw-color-picker-menu", style: 'min-width: 140px; padding: 0px; height: auto; min-height: fit-content;', }) }, { caption: '--' }, new Common.UI.MenuItem({ caption: this.txtEraser, value: 'eraser', iconCls: 'menu__icon btn-clearstyle', checkable: true, toggleGroup: 'preview-draw-tool' }), { caption: this.txtEraseScreen, value: 'eraseAll', iconCls: 'menu__icon btn-clear-all' }, ] }), }); this.drawColorPicker = new Common.UI.ColorPaletteExt({ el: $('.preview-draw-color-picker-menu'), colors: ["FFFFFF","000000","E81416","FFA500","FAEB36","79C314","487DE7","4B369D","70369D"], value: 'E81416' }); this.drawColorPicker.on('select', (_picker, color) => { this.currentDrawColor = color; const currentTool = this.btnDraw.menu.getChecked(); if (!currentTool) { this.btnDraw.toggle(true); this.btnDraw.menu.items[0].setChecked(true); this.drawTool['pen'](); return; } if (currentTool.value === 'pen' || currentTool.value === 'highlighter') { this.drawTool[currentTool.value](); } else { this.btnDraw.menu.items[this.btnDraw.menu.items.indexOf(currentTool)].setChecked(false); this.btnDraw.menu.items[0].setChecked(true); this.drawTool['pen'](); } }); this.btnDraw.menu.on('item:click', (_, item) => { if (this.currentDrawTool === item.value) { item.setChecked(false); this.drawTool['select'](); this.btnDraw.toggle(false); this.currentDrawTool = undefined; return; } if (item.value !== 'eraseAll') { this.btnDraw.toggle(true); this.currentDrawTool = item.value; } this.drawTool[item.value](); }); } this.btnPrev = new Common.UI.Button({ el: $('#btn-preview-prev',this.el), hint: this.txtPrev, hintAnchor: 'top', hintContainer: '#pe-preview' }); this.btnPrev.on('click', _.bind(function(btn) { if (this.api) this.api.DemonstrationPrevSlide(); btn.cmpEl && btn.cmpEl.blur(); this.editComplete(); }, this)); this.btnNext = new Common.UI.Button({ el: $('#btn-preview-next',this.el), hint: this.txtNext, hintAnchor: 'top', hintContainer: '#pe-preview' }); this.btnNext.on('click', _.bind(function(btn) { if (this.api) this.api.DemonstrationNextSlide(); btn.cmpEl && btn.cmpEl.blur(); this.editComplete(); }, this)); this.btnPlay = new Common.UI.Button({ el: $('#btn-preview-play',this.el), hint: this.txtPlay, hintAnchor: 'top', hintContainer: '#pe-preview' }); this.btnPlay.on('click', _.bind(function(btn) { var iconEl = $('.icon', this.btnPlay.cmpEl); if (iconEl.hasClass('btn-preview-pause')) { this.btnPlay.changeIcon({curr: 'btn-preview-pause', next: 'btn-play'}); this.btnPlay.updateHint(this.txtPlay); if (this.api) this.api.DemonstrationPause(); } else { this.btnPlay.changeIcon({curr: 'btn-play', next: 'btn-preview-pause'}); this.btnPlay.updateHint(this.txtPause); if (this.api) this.api.DemonstrationPlay (); } btn.cmpEl && btn.cmpEl.blur(); this.editComplete(); }, this)); this.btnClose = new Common.UI.Button({ el: $('#btn-preview-close',this.el), hint: this.txtClose, hintAnchor: 'top', hintContainer: '#pe-preview' }); this.btnClose.on('click', _.bind(function() { if (this.api) this.api.EndDemonstration(); }, this)); this.btnFullScreen = new Common.UI.Button({ el: $('#btn-preview-fullscreen',this.el), hint: this.txtFullScreen, hintAnchor: 'top', hintContainer: '#pe-preview' }); this.btnFullScreen.on('click', _.bind(function(btn) { this.toggleFullScreen(); this.editComplete(); }, this)); this.txtGoToPage = new Common.UI.InputField({ el : $('#preview-goto-page'), allowBlank : true, validateOnChange: true, style : 'width: 60px;', maskExp: /[0-9]/, validation : function(value) { if (/(^[0-9]+$)/.test(value)) { value = parseInt(value); if (undefined !== value && value >= me.pages.get('start') && value < me.pages.get('count')+me.pages.get('start')) return true; } return me.txtPageNumInvalid; } }).on('keypress:after', function(input, e) { if (e.keyCode === Common.UI.Keys.RETURN) { var box = me.$el.find('#preview-goto-box'), edit = box.find('input[type=text]'), page = parseInt(edit.val()), start = me.pages.get('start'); if (isNaN(page) || page >= me.pages.get('count')+start || page < start) { edit.select(); return false; } box.focus(); // for IE box.parent().removeClass('open'); me.api.DemonstrationGoToSlide(page - start); me.api.asc_enableKeyEvents(true); return false; } } ).on('keyup:after', function(input, e) { if (e.keyCode === Common.UI.Keys.ESC) { var box = me.$el.find('#preview-goto-box'); box.focus(); // for IE box.parent().removeClass('open'); me.api.asc_enableKeyEvents(true); return false; } } ); var goto = this.$el.find('#preview-goto-box'); goto.on('click', function() { return false; }); goto.parent().on('show.bs.dropdown', function () { // me.txtGoToPage.setValue(me.api.getCurrentPage() + 1); // me.txtGoToPage.checkValidate(); var edit = me.txtGoToPage.$el.find('input'); _.defer(function(){edit.focus(); edit.select();}, 100); } ); goto.parent().on('hide.bs.dropdown', function () { var box = me.$el.find('#preview-goto-box'); if (me.api && box) { box.focus(); // for IE box.parent().removeClass('open'); me.api.asc_enableKeyEvents(true); } } ); this.previewControls = $(this.el).find('.preview-controls'); $(document).on("webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange",function(){ var fselem = (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement ); if (fselem !== undefined && fselem !== null) { me.btnFullScreen.changeIcon({curr: 'btn-fullscreen', next: 'btn-preview-exit-fullscreen'}); } else { me.btnFullScreen.changeIcon({curr: 'btn-preview-exit-fullscreen', next: 'btn-fullscreen'}); if (me.btnDraw) { me.btnDraw.menu.hide(); } } setTimeout( function() { me.previewControls.css('display', ''); me.$el.css('cursor', ''); },100); if (Common.Utils.isIE) { // for tooltips in IE me.btnFullScreen.updateHint( fselem ? '' : me.txtFullScreen); me.btnPrev.updateHint( fselem ? '' : me.txtPrev); me.btnPlay.updateHint( fselem ? '' : ($('.icon', me.btnPlay.cmpEl).hasClass('btn-preview-pause') ? me.txtPause : me.txtPlay)); me.btnNext.updateHint( fselem ? '' : me.txtNext); me.btnClose.updateHint( fselem ? '' : me.txtClose); } else me.btnFullScreen.updateHint( fselem ? me.txtExitFullScreen: me.txtFullScreen); me.editComplete(); }); if (Common.Utils.isIE) { me.previewControls.css('opacity', '0.4'); } this.separatorFullScreen = el.find('.separator.fullscreen'); me.previewControls.on('mouseenter', function(e) { clearTimeout(me.timerMove); me.previewControls.addClass('over'); }); me.previewControls.on('mouseleave', function(e) { me.previewControls.removeClass('over'); }); }, show: function() { var toolbar = PE.getController('Toolbar').getView('Toolbar'); if (toolbar._state.hasCollaborativeChanges) { toolbar._state.hasCollaborativeChanges = false; if (toolbar.synchTooltip) toolbar.synchTooltip.hide(); toolbar.needShowSynchTip = true; } Common.UI.BaseView.prototype.show.call(this,arguments); var iconEl = $('.icon', this.btnPlay.cmpEl); if (!iconEl.hasClass('btn-preview-pause')) { this.btnPlay.changeIcon({curr: 'btn-play', next: 'btn-preview-pause'}); this.btnPlay.updateHint(this.txtPause); } var me = this; me.previewControls.css('display', 'none'); me.$el.css('cursor', 'none'); setTimeout(function(){ me.$el.on('mousemove', function() { clearTimeout(me.timerMove); me.previewControls.css('display', ''); me.$el.css('cursor', ''); if (!me.previewControls.hasClass('over')) me.timerMove = setTimeout(function () { me.previewControls.css('display', 'none'); me.$el.css('cursor', 'none'); }, 3000); }); if (!me.previewControls.hasClass('over')) { me.timerMove = setTimeout(function () { me.previewControls.css('display', 'none'); me.$el.css('cursor', 'none'); }, 3000); } }, 1000); $('#viewport-vbox-layout').css('z-index','0'); this.fireEvent('editcomplete', this); Common.NotificationCenter.trigger('preview:show'); }, hide: function() { Common.UI.BaseView.prototype.hide.call(this,arguments); $('#viewport-vbox-layout').css('z-index','auto'); Common.NotificationCenter.trigger('layout:changed', 'preview'); var toolbar = PE.getController('Toolbar').getView('Toolbar'); if (toolbar.needShowSynchTip) { toolbar.needShowSynchTip = false; toolbar.onCollaborativeChanges(); } this.$el.off('mousemove'); this.fireEvent('editcomplete', this); Common.NotificationCenter.trigger('preview:hide'); Common.NotificationCenter.trigger('draw-tool:select'); }, setApi: function(o) { this.api = o; if (this.api) { this.api.asc_registerCallback('asc_onCountPages', _.bind(this.onCountSlides, this)); this.api.asc_registerCallback('asc_onPresentationSize', _.bind(this.onApiPageSize, this)); this.api.asc_registerCallback('asc_onEndDemonstration', _.bind(this.onEndDemonstration, this)); this.api.asc_registerCallback('asc_onDemonstrationSlideChanged', _.bind(this.onDemonstrationSlideChanged, this)); this.api.asc_registerCallback('asc_onDemonstrationStatus', _.bind(this.onDemonstrationStatus, this)); this.api.DemonstrationEndShowMessage(this.txtFinalMessage); } return this; }, setMode: function(mode) { this.mode = mode; if (this.mode.isDesktopApp || Common.Utils.isIE11 || !document.fullscreenEnabled) { this.btnFullScreen.setVisible(false); this.separatorFullScreen.hide(); $(document).off("webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange"); } return this; }, onCountSlides: function(count){ this.pages.set('count', count); }, onApiPageSize: function(width, height, type, firstNum){ (firstNum!==undefined) && this.pages.set('start', firstNum); }, onDemonstrationSlideChanged: function(slideNum) { this.pages.set('current', slideNum); if (this.api && _.isNumber(slideNum)) { var count = this.api.getCountPages(); if (count !== this.pages.get('count')) this.pages.set('count', count); this.txtGoToPage.setValue(slideNum + this.pages.get('start')); this.txtGoToPage.checkValidate(); } }, onEndDemonstration: function( ) { if (this.btnDraw) { this.btnDraw.menu.clearAll(); this.btnDraw.toggle(false); this.currentDrawTool = undefined; } this.hide(); Common.Utils.cancelFullscreen(); }, onDemonstrationStatus: function(status) { (status=="play") ? this.btnPlay.changeIcon({curr: 'btn-play', next: 'btn-preview-pause'}) : this.btnPlay.changeIcon({curr: 'btn-preview-pause', next: 'btn-play'}); this.btnPlay.updateHint((status=="play") ? this.txtPause : this.txtPlay); }, toggleFullScreen: function() { if (!document.fullscreenElement && !document.msFullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement) { if (this.mode.isDesktopApp || Common.Utils.isIE11) return; const elem = document.getElementById('pe-preview'); if ( elem ) { Common.Utils.startFullscreenForElement(elem); this.previewControls.css('display', 'none'); this.$el.css('cursor', 'none'); } } else { Common.Utils.cancelFullscreen(); } }, editComplete: function() { this.api && this.api.asc_enableKeyEvents(true); }, txtDraw: 'Draw', txtPen: 'Pen', txtHighlighter: 'Highlighter', txtEraser: 'Eraser', txtEraseScreen: 'Erase screen', txtInkColor: 'Ink color', txtPointer: 'Laser pointer', txtPrev: 'Previous Slide', txtNext: 'Next Slide', txtClose: 'Close Slideshow', goToSlideText : 'Go to Slide', slideIndexText : 'Slide {0} of {1}', txtPlay: 'Start Presentation', txtPause: 'Pause Presentation', txtFinalMessage: 'The end of slide preview. Click to exit.', txtPageNumInvalid: 'Slide number invalid', txtFullScreen: 'Full Screen', txtExitFullScreen: 'Exit Full Screen', txtReset: 'Reset', txtEndSlideshow: 'End slideshow' }, PE.Views.DocumentPreview || {})); });