/*
* (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 = [
'
',
'',
'
',
'
',
'Slide 1 of 1 ',
'',
'
',
'
',
'
',
'
'
].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 || {}));
});