2016-04-01 13:17:09 +00:00
/ *
*
2019-01-17 13:05:03 +00:00
* ( c ) Copyright Ascensio System SIA 2010 - 2019
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
*
2019-01-17 13:00:34 +00:00
* You can contact Ascensio System SIA at 20 A - 12 Ernesta Birznieka - Upisha
* street , Riga , Latvia , EU , LV - 1050.
2016-04-01 13:17:09 +00:00
*
* 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
*
* /
2019-05-14 11:11:42 +00:00
DE . ApplicationController = new ( function ( ) {
2016-03-11 00:48:53 +00:00
var me ,
api ,
config = { } ,
docConfig = { } ,
embedConfig = { } ,
permissions = { } ,
maxPages = 0 ,
created = false ,
2021-05-17 22:58:40 +00:00
ttOffset = [ 0 , - 10 ] ,
2021-05-18 14:42:04 +00:00
labelDocName ,
2021-05-20 14:44:21 +00:00
appOptions = { } ,
btnSubmit ,
2021-07-28 11:32:05 +00:00
_submitFail , $submitedTooltip , $requiredTooltip ,
$listControlMenu , listControlItems = [ ] , listObj ;
2016-03-11 00:48:53 +00:00
2021-06-24 16:08:21 +00:00
var LoadingDocument = - 256 ;
2016-03-11 00:48:53 +00:00
// Initialize analytics
// -------------------------
2019-02-22 12:28:39 +00:00
// Common.Analytics.initialize('UA-12442749-13', 'Embedded Document Editor');
2016-03-11 00:48:53 +00:00
// Check browser
// -------------------------
if ( typeof isBrowserSupported !== 'undefined' && ! isBrowserSupported ( ) ) {
2019-05-14 11:11:42 +00:00
Common . Gateway . reportError ( undefined , this . unsupportedBrowserErrorText ) ;
2016-03-11 00:48:53 +00:00
return ;
}
2021-05-25 13:40:40 +00:00
common . localStorage . setId ( 'text' ) ;
common . localStorage . setKeysFilter ( 'de-,asc.text' ) ;
common . localStorage . sync ( ) ;
2016-03-11 00:48:53 +00:00
// Handlers
// -------------------------
function loadConfig ( data ) {
config = $ . extend ( config , data . config ) ;
embedConfig = $ . extend ( embedConfig , data . config . embedded ) ;
2016-11-02 10:28:44 +00:00
common . controller . modals . init ( embedConfig ) ;
2016-03-11 00:48:53 +00:00
// Docked toolbar
2017-04-11 11:05:56 +00:00
if ( embedConfig . toolbarDocked === 'bottom' ) {
2016-03-11 00:48:53 +00:00
$ ( '#toolbar' ) . addClass ( 'bottom' ) ;
$ ( '#editor_sdk' ) . addClass ( 'bottom' ) ;
2016-11-02 10:35:55 +00:00
$ ( '#box-tools' ) . removeClass ( 'dropdown' ) . addClass ( 'dropup' ) ;
ttOffset [ 1 ] = - 40 ;
2017-04-11 11:05:56 +00:00
} else {
$ ( '#toolbar' ) . addClass ( 'top' ) ;
$ ( '#editor_sdk' ) . addClass ( 'top' ) ;
2016-03-11 00:48:53 +00:00
}
2021-05-17 20:55:33 +00:00
config . canBackToFolder = ( config . canBackToFolder !== false ) && config . customization && config . customization . goback &&
( config . customization . goback . url || config . customization . goback . requestClose && config . canRequestClose ) ;
2016-03-11 00:48:53 +00:00
}
function loadDocument ( data ) {
docConfig = data . doc ;
if ( docConfig ) {
permissions = $ . extend ( permissions , docConfig . permissions ) ;
2017-10-23 12:19:07 +00:00
var _permissions = $ . extend ( { } , docConfig . permissions ) ,
2020-10-31 16:53:35 +00:00
docInfo = new Asc . asc _CDocInfo ( ) ,
_user = new Asc . asc _CUserInfo ( ) ;
2021-05-25 13:40:40 +00:00
var canRenameAnonymous = ! ( ( typeof ( config . customization ) == 'object' ) && ( typeof ( config . customization . anonymous ) == 'object' ) && ( config . customization . anonymous . request === false ) ) ,
guestName = ( typeof ( config . customization ) == 'object' ) && ( typeof ( config . customization . anonymous ) == 'object' ) &&
( typeof ( config . customization . anonymous . label ) == 'string' ) && config . customization . anonymous . label . trim ( ) !== '' ?
common . utils . htmlEncode ( config . customization . anonymous . label ) : me . textGuest ,
value = canRenameAnonymous ? common . localStorage . getItem ( "guest-username" ) : null ,
user = common . utils . fillUserInfo ( config . user , config . lang , value ? ( value + ' (' + guestName + ')' ) : me . textAnonymous ,
common . localStorage . getItem ( "guest-id" ) || ( 'uid-' + Date . now ( ) ) ) ;
user . anonymous && common . localStorage . setItem ( "guest-id" , user . id ) ;
_user . put _Id ( user . id ) ;
_user . put _FullName ( user . fullname ) ;
2021-05-25 13:57:56 +00:00
_user . put _IsAnonymousUser ( user . anonymous ) ;
2020-10-31 16:53:35 +00:00
2016-03-11 00:48:53 +00:00
docInfo . put _Id ( docConfig . key ) ;
docInfo . put _Url ( docConfig . url ) ;
docInfo . put _Title ( docConfig . title ) ;
docInfo . put _Format ( docConfig . fileType ) ;
docInfo . put _VKey ( docConfig . vkey ) ;
2020-10-31 16:53:35 +00:00
docInfo . put _UserInfo ( _user ) ;
2016-11-24 13:44:54 +00:00
docInfo . put _Token ( docConfig . token ) ;
2017-10-23 12:19:07 +00:00
docInfo . put _Permissions ( _permissions ) ;
2020-05-22 15:40:38 +00:00
docInfo . put _EncryptedInfo ( config . encryptionKeys ) ;
2017-10-23 12:19:07 +00:00
2020-05-22 12:04:55 +00:00
var enable = ! config . customization || ( config . customization . macros !== false ) ;
docInfo . asc _putIsEnabledMacroses ( ! ! enable ) ;
enable = ! config . customization || ( config . customization . plugins !== false ) ;
docInfo . asc _putIsEnabledPlugins ( ! ! enable ) ;
2017-10-23 12:19:07 +00:00
var type = /^(?:(pdf|djvu|xps))$/ . exec ( docConfig . fileType ) ;
if ( type && typeof type [ 1 ] === 'string' ) {
permissions . edit = permissions . review = false ;
}
2016-03-11 00:48:53 +00:00
if ( api ) {
api . asc _registerCallback ( 'asc_onGetEditorPermissions' , onEditorPermissions ) ;
2020-05-22 12:04:55 +00:00
api . asc _registerCallback ( 'asc_onRunAutostartMacroses' , onRunAutostartMacroses ) ;
2016-03-11 00:48:53 +00:00
api . asc _setDocInfo ( docInfo ) ;
api . asc _getEditorPermissions ( config . licenseUrl , config . customerId ) ;
api . asc _enableKeyEvents ( true ) ;
Common . Analytics . trackEvent ( 'Load' , 'Start' ) ;
}
2016-11-18 15:00:46 +00:00
embedConfig . docTitle = docConfig . title ;
2021-05-17 22:58:40 +00:00
labelDocName = $ ( '#title-doc-name' ) ;
labelDocName . text ( embedConfig . docTitle || '' )
2016-03-11 00:48:53 +00:00
}
}
function onCountPages ( count ) {
maxPages = count ;
2019-05-14 11:11:42 +00:00
$ ( '#pages' ) . text ( me . textOf + " " + count ) ;
2016-03-11 00:48:53 +00:00
}
function onCurrentPage ( number ) {
$ ( '#page-number' ) . val ( number + 1 ) ;
}
function onLongActionBegin ( type , id ) {
var text = '' ;
switch ( id )
{
2016-04-05 11:52:34 +00:00
case Asc . c _oAscAsyncAction [ 'Print' ] :
2019-05-14 11:11:42 +00:00
text = me . downloadTextText ;
2016-03-11 00:48:53 +00:00
break ;
2021-05-20 14:44:21 +00:00
case Asc . c _oAscAsyncAction [ 'Submit' ] :
_submitFail = false ;
$submitedTooltip && $submitedTooltip . hide ( ) ;
btnSubmit . attr ( { disabled : true } ) ;
2021-06-01 12:41:59 +00:00
btnSubmit . css ( "pointer-events" , "none" ) ;
2021-05-20 14:44:21 +00:00
break ;
2021-06-24 16:08:21 +00:00
case LoadingDocument :
text = me . textLoadingDocument + ' ' ;
break ;
2016-03-11 00:48:53 +00:00
default :
2019-05-14 11:11:42 +00:00
text = me . waitText ;
2016-03-11 00:48:53 +00:00
break ;
}
2016-04-05 11:52:34 +00:00
if ( type == Asc . c _oAscAsyncActionType [ 'BlockInteraction' ] ) {
2021-06-24 16:08:21 +00:00
if ( ! me . loadMask )
me . loadMask = new common . view . LoadMask ( ) ;
me . loadMask . setTitle ( text ) ;
me . loadMask . show ( ) ;
2016-03-11 00:48:53 +00:00
}
}
2021-05-20 14:44:21 +00:00
function onLongActionEnd ( type , id ) {
if ( id == Asc . c _oAscAsyncAction [ 'Submit' ] ) {
btnSubmit . removeAttr ( 'disabled' ) ;
2021-06-01 12:41:59 +00:00
btnSubmit . css ( "pointer-events" , "auto" ) ;
2021-05-31 23:01:44 +00:00
if ( ! _submitFail ) {
if ( ! $submitedTooltip ) {
$submitedTooltip = $ ( '<div class="submit-tooltip" style="display:none;">' + me . textSubmited + '</div>' ) ;
$ ( document . body ) . append ( $submitedTooltip ) ;
$submitedTooltip . on ( 'click' , function ( ) { $submitedTooltip . hide ( ) ; } ) ;
}
$submitedTooltip . show ( ) ;
2021-05-20 14:44:21 +00:00
}
}
2021-06-24 16:08:21 +00:00
me . loadMask && me . loadMask . hide ( ) ;
2016-03-11 00:48:53 +00:00
}
function onDocMouseMoveStart ( ) {
me . isHideBodyTip = true ;
}
function onDocMouseMoveEnd ( ) {
if ( me . isHideBodyTip ) {
2016-10-31 14:49:53 +00:00
if ( $tooltip ) {
$tooltip . tooltip ( 'hide' ) ;
$tooltip = false ;
2016-03-11 00:48:53 +00:00
}
}
}
2016-10-31 14:49:53 +00:00
var $ttEl , $tooltip ;
2016-03-11 00:48:53 +00:00
function onDocMouseMove ( data ) {
if ( data ) {
if ( data . get _Type ( ) == 1 ) { // hyperlink
me . isHideBodyTip = false ;
2016-10-31 14:49:53 +00:00
if ( ! $ttEl ) {
$ttEl = $ ( '.hyperlink-tooltip' ) ;
$ttEl . tooltip ( { 'container' : 'body' , 'trigger' : 'manual' } ) ;
$ttEl . on ( 'shown.bs.tooltip' , function ( e ) {
$tooltip = $ttEl . data ( 'bs.tooltip' ) . tip ( ) ;
$tooltip . css ( {
2016-11-02 10:32:43 +00:00
left : $ttEl . ttpos [ 0 ] + ttOffset [ 0 ] ,
top : $ttEl . ttpos [ 1 ] + ttOffset [ 1 ]
2016-10-31 14:49:53 +00:00
} ) ;
2016-03-11 00:48:53 +00:00
2016-10-31 14:49:53 +00:00
$tooltip . find ( '.tooltip-arrow' ) . css ( { left : 10 } ) ;
} ) ;
2016-03-11 00:48:53 +00:00
}
2016-10-31 14:49:53 +00:00
if ( ! $tooltip ) {
$ttEl . ttpos = [ data . get _X ( ) , data . get _Y ( ) ] ;
$ttEl . tooltip ( 'show' ) ;
} else {
$tooltip . css ( {
2016-11-02 10:32:43 +00:00
left : data . get _X ( ) + ttOffset [ 0 ] ,
top : data . get _Y ( ) + ttOffset [ 1 ]
2016-10-31 14:49:53 +00:00
} ) ;
}
2016-03-11 00:48:53 +00:00
}
}
}
function onDownloadUrl ( url ) {
Common . Gateway . downloadAs ( url ) ;
}
function onPrint ( ) {
2016-11-02 10:32:43 +00:00
if ( permissions . print !== false )
2021-04-20 15:46:41 +00:00
api . asc _Print ( new Asc . asc _CDownloadOptions ( null , $ . browser . chrome || $ . browser . safari || $ . browser . opera || $ . browser . mozilla && $ . browser . versionNumber > 86 ) ) ;
2016-03-11 00:48:53 +00:00
}
function onPrintUrl ( url ) {
2019-07-23 12:07:51 +00:00
common . utils . dialogPrint ( url , api ) ;
2016-03-11 00:48:53 +00:00
}
2021-06-17 15:58:44 +00:00
function onFillRequiredFields ( isFilled ) {
if ( isFilled ) {
2021-06-01 12:41:59 +00:00
btnSubmit . removeAttr ( 'disabled' ) ;
btnSubmit . css ( "pointer-events" , "auto" ) ;
2021-06-17 15:58:44 +00:00
// $requiredTooltip && $requiredTooltip.hide();
} else {
btnSubmit . attr ( { disabled : true } ) ;
btnSubmit . css ( "pointer-events" , "none" ) ;
2021-06-01 12:41:59 +00:00
}
2021-05-31 23:01:44 +00:00
}
2021-07-28 11:32:05 +00:00
function onShowContentControlsActions ( obj , x , y ) {
switch ( obj . type ) {
case Asc . c _oAscContentControlSpecificType . Picture :
if ( obj . pr && obj . pr . get _Lock ) {
var lock = obj . pr . get _Lock ( ) ;
if ( lock == Asc . c _oAscSdtLockType . SdtContentLocked || lock == Asc . c _oAscSdtLockType . ContentLocked )
return ;
}
api . asc _addImage ( obj ) ;
setTimeout ( function ( ) {
api . asc _UncheckContentControlButtons ( ) ;
} , 500 ) ;
break ;
case Asc . c _oAscContentControlSpecificType . DropDownList :
case Asc . c _oAscContentControlSpecificType . ComboBox :
onShowListActions ( obj , x , y ) ;
break ;
}
}
function onHideContentControlsActions ( ) {
$listControlMenu && $listControlMenu . hide ( ) ;
api . asc _UncheckContentControlButtons ( ) ;
}
function onShowListActions ( obj , x , y ) {
var type = obj . type ,
props = obj . pr ,
specProps = ( type == Asc . c _oAscContentControlSpecificType . ComboBox ) ? props . get _ComboBoxPr ( ) : props . get _DropDownListPr ( ) ,
isForm = ! ! props . get _FormPr ( ) ;
var menuContainer = DE . ApplicationView . getMenuForm ( ) ;
if ( ! $listControlMenu ) {
$listControlMenu = menuContainer . find ( 'ul' ) ;
$listControlMenu . on ( 'click' , 'li' , function ( e ) {
var value = $ ( e . target ) . attr ( 'value' ) ;
if ( value ) {
value = parseInt ( value ) ;
setTimeout ( function ( ) {
( value !== - 1 ) && api . asc _SelectContentControlListItem ( listControlItems [ value ] , listObj . get _InternalId ( ) ) ;
} , 1 ) ;
}
} ) ;
$ ( '#editor_sdk' ) . on ( 'click' , function ( e ) {
if ( e . target . localName == 'canvas' ) {
if ( me . _preventClick )
me . _preventClick = false ;
else {
$listControlMenu && $listControlMenu . hide ( ) ;
api . asc _UncheckContentControlButtons ( ) ;
}
}
} ) ;
}
$listControlMenu . find ( 'li' ) . remove ( ) ;
listControlItems = [ ] ;
listObj = props ;
if ( specProps ) {
var k = 0 ;
if ( isForm ) { // for dropdown and combobox form control always add placeholder item
var text = props . get _PlaceholderText ( ) ;
$listControlMenu . append ( '<li><a tabindex="-1" type="menuitem" style="opacity: 0.6" value="0">' +
( ( text . trim ( ) !== '' ) ? text : me . txtEmpty ) +
'</a></li>' ) ;
listControlItems . push ( '' ) ;
}
var count = specProps . get _ItemsCount ( ) ;
k = listControlItems . length ;
for ( var i = 0 ; i < count ; i ++ ) {
if ( specProps . get _ItemValue ( i ) !== '' || ! isForm ) {
$listControlMenu . append ( '<li><a tabindex="-1" type="menuitem" value="' + ( i + k ) + '">' +
common . utils . htmlEncode ( specProps . get _ItemDisplayText ( i ) ) +
'</a></li>' ) ;
listControlItems . push ( specProps . get _ItemValue ( i ) ) ;
}
}
if ( ! isForm && listControlItems . length < 1 ) {
$listControlMenu . append ( '<li><a tabindex="-1" type="menuitem" value="0">' +
me . txtEmpty +
'</a></li>' ) ;
listControlItems . push ( - 1 ) ;
}
}
menuContainer . css ( { left : x , top : y } ) ;
me . _preventClick = true ;
$listControlMenu . show ( ) ;
}
2016-03-11 00:48:53 +00:00
function hidePreloader ( ) {
$ ( '#loading-mask' ) . fadeOut ( 'slow' ) ;
}
function onDocumentContentReady ( ) {
hidePreloader ( ) ;
2021-06-24 16:08:21 +00:00
onLongActionEnd ( Asc . c _oAscAsyncActionType [ 'BlockInteraction' ] , LoadingDocument ) ;
2016-03-11 00:48:53 +00:00
2018-04-04 09:19:20 +00:00
var zf = ( config . customization && config . customization . zoom ? parseInt ( config . customization . zoom ) : - 2 ) ;
( zf == - 1 ) ? api . zoomFitToPage ( ) : ( ( zf == - 2 ) ? api . zoomFitToWidth ( ) : api . zoom ( zf > 0 ? zf : 100 ) ) ;
2021-05-19 14:29:13 +00:00
var dividers = $ ( '#box-tools .divider' ) ;
var itemsCount = $ ( '#box-tools a' ) . length ;
2019-11-12 08:05:59 +00:00
2021-05-19 14:29:13 +00:00
if ( permissions . print === false ) {
2020-09-01 11:08:41 +00:00
$ ( '#idt-print' ) . hide ( ) ;
2021-05-19 14:29:13 +00:00
$ ( dividers [ 0 ] ) . hide ( ) ;
itemsCount -- ;
}
if ( ! embedConfig . saveUrl && permissions . print === false || appOptions . canFillForms ) {
$ ( '#idt-download' ) . hide ( ) ;
itemsCount -- ;
}
2020-09-01 11:08:41 +00:00
2021-05-19 14:29:13 +00:00
if ( ! appOptions . canFillForms || permissions . download === false ) {
$ ( '#idt-download-docx' ) . hide ( ) ;
$ ( '#idt-download-pdf' ) . hide ( ) ;
$ ( dividers [ 0 ] ) . hide ( ) ;
$ ( dividers [ 1 ] ) . hide ( ) ;
itemsCount -= 2 ;
}
if ( ! embedConfig . shareUrl || appOptions . canFillForms ) {
2016-11-02 10:32:43 +00:00
$ ( '#idt-share' ) . hide ( ) ;
2021-05-19 14:29:13 +00:00
itemsCount -- ;
}
if ( ! config . canBackToFolder ) {
$ ( '#idt-close' ) . hide ( ) ;
itemsCount -- ;
}
2016-11-02 10:32:43 +00:00
2021-05-19 14:29:13 +00:00
if ( itemsCount < 3 )
$ ( dividers [ 2 ] ) . hide ( ) ;
2021-05-17 20:55:33 +00:00
2021-05-19 14:29:13 +00:00
if ( ! embedConfig . embedUrl || appOptions . canFillForms ) {
2016-11-02 10:32:43 +00:00
$ ( '#idt-embed' ) . hide ( ) ;
2021-05-19 14:29:13 +00:00
itemsCount -- ;
}
2016-11-02 10:32:43 +00:00
2021-05-19 14:29:13 +00:00
if ( ! embedConfig . fullscreenUrl ) {
2016-11-17 13:01:54 +00:00
$ ( '#idt-fullscreen' ) . hide ( ) ;
2021-05-19 14:29:13 +00:00
itemsCount -- ;
}
2016-11-02 10:32:43 +00:00
2021-05-19 14:29:13 +00:00
// if ( !embedConfig.saveUrl && permissions.print === false && (!embedConfig.shareUrl || appOptions.canFillForms) && (!embedConfig.embedUrl || appOptions.canFillForms) && !embedConfig.fullscreenUrl && !config.canBackToFolder)
if ( itemsCount < 1 )
2019-11-12 08:05:59 +00:00
$ ( '#box-tools' ) . addClass ( 'hidden' ) ;
2021-05-18 14:42:04 +00:00
else if ( ( ! embedConfig . embedUrl || appOptions . canFillForms ) && ! embedConfig . fullscreenUrl )
2021-05-19 14:29:13 +00:00
$ ( dividers [ 2 ] ) . hide ( ) ;
2019-11-12 08:05:59 +00:00
2016-11-02 10:28:44 +00:00
common . controller . modals . attach ( {
share : '#idt-share' ,
embed : '#idt-embed'
} ) ;
2016-10-31 14:49:53 +00:00
api . asc _registerCallback ( 'asc_onStartAction' , onLongActionBegin ) ;
api . asc _registerCallback ( 'asc_onEndAction' , onLongActionEnd ) ;
api . asc _registerCallback ( 'asc_onMouseMoveStart' , onDocMouseMoveStart ) ;
api . asc _registerCallback ( 'asc_onMouseMoveEnd' , onDocMouseMoveEnd ) ;
api . asc _registerCallback ( 'asc_onMouseMove' , onDocMouseMove ) ;
2016-11-02 09:34:10 +00:00
api . asc _registerCallback ( 'asc_onHyperlinkClick' , common . utils . openLink ) ;
2016-10-31 14:49:53 +00:00
api . asc _registerCallback ( 'asc_onDownloadUrl' , onDownloadUrl ) ;
api . asc _registerCallback ( 'asc_onPrint' , onPrint ) ;
2016-11-02 10:32:43 +00:00
api . asc _registerCallback ( 'asc_onPrintUrl' , onPrintUrl ) ;
2021-06-17 15:58:44 +00:00
api . asc _registerCallback ( 'sync_onAllRequiredFormsFilled' , onFillRequiredFields ) ;
2021-07-28 11:32:05 +00:00
if ( appOptions . canFillForms ) {
api . asc _registerCallback ( 'asc_onShowContentControlsActions' , onShowContentControlsActions ) ;
api . asc _registerCallback ( 'asc_onHideContentControlsActions' , onHideContentControlsActions ) ;
2021-07-29 15:26:31 +00:00
api . asc _SetHighlightRequiredFields ( true ) ;
2021-07-28 11:32:05 +00:00
}
2016-10-31 14:49:53 +00:00
Common . Gateway . on ( 'processmouse' , onProcessMouse ) ;
Common . Gateway . on ( 'downloadas' , onDownloadAs ) ;
2021-03-29 11:30:31 +00:00
Common . Gateway . on ( 'requestclose' , onRequestClose ) ;
2016-10-31 14:49:53 +00:00
2019-05-14 11:11:42 +00:00
DE . ApplicationView . tools . get ( '#idt-fullscreen' )
2016-10-31 14:49:53 +00:00
. on ( 'click' , function ( ) {
2016-11-02 09:34:10 +00:00
common . utils . openLink ( embedConfig . fullscreenUrl ) ;
2016-10-31 14:49:53 +00:00
} ) ;
2019-05-14 11:11:42 +00:00
DE . ApplicationView . tools . get ( '#idt-download' )
2016-10-31 14:49:53 +00:00
. on ( 'click' , function ( ) {
if ( ! ! embedConfig . saveUrl ) {
2016-11-02 09:34:10 +00:00
common . utils . openLink ( embedConfig . saveUrl ) ;
2016-10-31 14:49:53 +00:00
} else
if ( api && permissions . print !== false ) {
2021-04-20 15:46:41 +00:00
api . asc _Print ( new Asc . asc _CDownloadOptions ( null , $ . browser . chrome || $ . browser . safari || $ . browser . opera || $ . browser . mozilla && $ . browser . versionNumber > 86 ) ) ;
2016-10-31 14:49:53 +00:00
}
Common . Analytics . trackEvent ( 'Save' ) ;
} ) ;
2020-09-01 11:08:41 +00:00
DE . ApplicationView . tools . get ( '#idt-print' )
. on ( 'click' , function ( ) {
2021-04-20 15:46:41 +00:00
api . asc _Print ( new Asc . asc _CDownloadOptions ( null , $ . browser . chrome || $ . browser . safari || $ . browser . opera || $ . browser . mozilla && $ . browser . versionNumber > 86 ) ) ;
2020-09-01 11:08:41 +00:00
Common . Analytics . trackEvent ( 'Print' ) ;
} ) ;
2021-05-17 20:55:33 +00:00
DE . ApplicationView . tools . get ( '#idt-close' )
. on ( 'click' , function ( ) {
2019-11-27 07:22:25 +00:00
if ( config . customization && config . customization . goback ) {
if ( config . customization . goback . requestClose && config . canRequestClose )
Common . Gateway . requestClose ( ) ;
else if ( config . customization . goback . url )
window . parent . location . href = config . customization . goback . url ;
}
2016-10-31 14:49:53 +00:00
} ) ;
2021-05-19 14:29:13 +00:00
var downloadAs = function ( format ) {
api . asc _DownloadAs ( new Asc . asc _CDownloadOptions ( format ) ) ;
Common . Analytics . trackEvent ( 'Save' ) ;
} ;
DE . ApplicationView . tools . get ( '#idt-download-docx' )
. on ( 'click' , function ( ) {
downloadAs ( Asc . c _oAscFileType . DOCX ) ;
} ) ;
DE . ApplicationView . tools . get ( '#idt-download-pdf' )
. on ( 'click' , function ( ) {
downloadAs ( Asc . c _oAscFileType . PDF ) ;
} ) ;
2016-10-31 14:49:53 +00:00
$ ( '#id-btn-zoom-in' ) . on ( 'click' , api . zoomIn . bind ( this ) ) ;
$ ( '#id-btn-zoom-out' ) . on ( 'click' , api . zoomOut . bind ( this ) ) ;
var $pagenum = $ ( '#page-number' ) ;
$pagenum . on ( {
'keyup' : function ( e ) {
if ( e . keyCode == 13 ) {
var newPage = parseInt ( $ ( '#page-number' ) . val ( ) ) ;
if ( newPage > maxPages ) newPage = maxPages ;
if ( newPage < 2 || isNaN ( newPage ) ) newPage = 1 ;
api . goToPage ( newPage - 1 ) ;
$pagenum . blur ( ) ;
}
}
, 'focusin' : function ( e ) {
$pagenum . removeClass ( 'masked' ) ;
}
, 'focusout' : function ( e ) {
! $pagenum . hasClass ( 'masked' ) && $pagenum . addClass ( 'masked' ) ;
}
} ) ;
$ ( '#pages' ) . on ( 'click' , function ( e ) {
$pagenum . focus ( ) ;
} ) ;
2021-05-31 23:01:44 +00:00
// TODO: add asc_hasRequiredFields to sdk
2021-06-17 15:58:44 +00:00
if ( appOptions . canSubmitForms && ! api . asc _IsAllRequiredFormsFilled ( ) ) {
2021-06-01 12:41:59 +00:00
var sgroup = $ ( '#id-submit-group' ) ;
2021-05-31 23:01:44 +00:00
btnSubmit . attr ( { disabled : true } ) ;
2021-06-01 12:41:59 +00:00
btnSubmit . css ( "pointer-events" , "none" ) ;
2021-05-31 23:01:44 +00:00
if ( ! common . localStorage . getItem ( "de-embed-hide-submittip" ) ) {
var offset = btnSubmit . offset ( ) ;
$requiredTooltip = $ ( '<div class="required-tooltip bottom-left" style="display:none;"><div class="tip-arrow bottom-left"></div><div>' + me . textRequired + '</div><div class="close-div">' + me . textGotIt + '</div></div>' ) ;
$ ( document . body ) . append ( $requiredTooltip ) ;
$requiredTooltip . css ( { top : offset . top + btnSubmit . height ( ) + 'px' , left : offset . left + btnSubmit . outerWidth ( ) / 2 - $requiredTooltip . outerWidth ( ) + 'px' } ) ;
$requiredTooltip . find ( '.close-div' ) . on ( 'click' , function ( ) {
$requiredTooltip . hide ( ) ;
2021-06-17 15:58:44 +00:00
api . asc _MoveToFillingForm ( true , true , true ) ;
2021-05-31 23:01:44 +00:00
common . localStorage . setItem ( "de-embed-hide-submittip" , 1 ) ;
2021-06-01 12:41:59 +00:00
sgroup . attr ( 'data-toggle' , 'tooltip' ) ;
sgroup . tooltip ( {
title : me . textRequired ,
placement : 'bottom'
} ) ;
2021-05-31 23:01:44 +00:00
} ) ;
$requiredTooltip . show ( ) ;
2021-06-01 12:41:59 +00:00
} else {
sgroup . attr ( 'data-toggle' , 'tooltip' ) ;
sgroup . tooltip ( {
title : me . textRequired ,
placement : 'bottom'
} ) ;
2021-05-31 23:01:44 +00:00
}
}
2016-10-31 14:49:53 +00:00
var documentMoveTimer ;
var ismoved = false ;
$ ( document ) . mousemove ( function ( event ) {
$ ( '#id-btn-zoom-in' ) . fadeIn ( ) ;
$ ( '#id-btn-zoom-out' ) . fadeIn ( ) ;
ismoved = true ;
if ( ! documentMoveTimer ) {
documentMoveTimer = setInterval ( function ( ) {
if ( ! ismoved ) {
$ ( '#id-btn-zoom-in' ) . fadeOut ( ) ;
$ ( '#id-btn-zoom-out' ) . fadeOut ( ) ;
clearInterval ( documentMoveTimer ) ;
documentMoveTimer = undefined ;
}
ismoved = false ;
} , 2000 ) ;
}
} ) ;
2019-01-10 08:20:53 +00:00
Common . Gateway . documentReady ( ) ;
2016-03-11 00:48:53 +00:00
Common . Analytics . trackEvent ( 'Load' , 'Complete' ) ;
}
function onEditorPermissions ( params ) {
2017-06-16 07:52:31 +00:00
if ( ( params . asc _getLicenseType ( ) === Asc . c _oLicenseResult . Success ) && ( typeof config . customization == 'object' ) &&
2016-03-11 00:48:53 +00:00
config . customization && config . customization . logo ) {
var logo = $ ( '#header-logo' ) ;
if ( config . customization . logo . imageEmbedded ) {
logo . html ( '<img src="' + config . customization . logo . imageEmbedded + '" style="max-width:124px; max-height:20px;"/>' ) ;
logo . css ( { 'background-image' : 'none' , width : 'auto' , height : 'auto' } ) ;
}
if ( config . customization . logo . url ) {
logo . attr ( 'href' , config . customization . logo . url ) ;
}
}
2021-04-26 15:36:40 +00:00
var licType = params . asc _getLicenseType ( ) ;
2021-05-18 14:42:04 +00:00
appOptions . canLicense = ( licType === Asc . c _oLicenseResult . Success || licType === Asc . c _oLicenseResult . SuccessLimit ) ;
appOptions . canFillForms = appOptions . canLicense && ( permissions . fillForms === true ) && ( config . mode !== 'view' ) ;
2021-05-18 22:26:16 +00:00
appOptions . canSubmitForms = appOptions . canLicense && ( typeof ( config . customization ) == 'object' ) && ! ! config . customization . submitForm ;
2021-05-17 22:49:08 +00:00
2021-05-18 14:42:04 +00:00
api . asc _setViewMode ( ! appOptions . canFillForms ) ;
2021-05-17 22:49:08 +00:00
2021-05-20 14:44:21 +00:00
btnSubmit = $ ( '#id-btn-submit' ) ;
2021-05-18 14:42:04 +00:00
if ( ! appOptions . canFillForms ) {
2021-04-26 15:36:40 +00:00
$ ( '#id-btn-prev-field' ) . hide ( ) ;
$ ( '#id-btn-next-field' ) . hide ( ) ;
2021-05-17 22:49:08 +00:00
$ ( '#id-btn-clear-fields' ) . hide ( ) ;
2021-05-20 14:44:21 +00:00
btnSubmit . hide ( ) ;
2021-04-26 15:36:40 +00:00
} else {
2021-05-18 22:26:16 +00:00
$ ( '#id-pages' ) . hide ( ) ;
2021-05-17 22:49:08 +00:00
$ ( '#id-btn-next-field .caption' ) . text ( me . textNext ) ;
$ ( '#id-btn-clear-fields .caption' ) . text ( me . textClear ) ;
2021-05-18 22:26:16 +00:00
2021-04-26 15:36:40 +00:00
$ ( '#id-btn-prev-field' ) . on ( 'click' , function ( ) {
api . asc _MoveToFillingForm ( false ) ;
} ) ;
$ ( '#id-btn-next-field' ) . on ( 'click' , function ( ) {
api . asc _MoveToFillingForm ( true ) ;
} ) ;
2021-05-17 22:49:08 +00:00
$ ( '#id-btn-clear-fields' ) . on ( 'click' , function ( ) {
api . asc _ClearAllSpecialForms ( ) ;
} ) ;
2021-05-18 22:26:16 +00:00
if ( appOptions . canSubmitForms ) {
2021-05-20 14:44:21 +00:00
btnSubmit . find ( '.caption' ) . text ( me . textSubmit ) ;
btnSubmit . on ( 'click' , function ( ) {
2021-05-18 22:26:16 +00:00
api . asc _SendForm ( ) ;
} ) ;
} else
2021-05-20 14:44:21 +00:00
btnSubmit . hide ( ) ;
2021-05-18 22:26:16 +00:00
2021-05-17 22:49:08 +00:00
api . asc _setRestriction ( Asc . c _oAscRestrictionType . OnlyForms ) ;
api . asc _SetFastCollaborative ( true ) ;
api . asc _setAutoSaveGap ( 1 ) ;
2021-04-26 15:36:40 +00:00
}
2021-05-17 22:58:40 +00:00
var $parent = labelDocName . parent ( ) ;
var _left _width = $parent . position ( ) . left ,
_right _width = $parent . next ( ) . outerWidth ( ) ;
if ( _left _width < _right _width )
$parent . css ( 'padding-left' , _right _width - _left _width ) ;
else
$parent . css ( 'padding-right' , _left _width - _right _width ) ;
2021-06-24 16:08:21 +00:00
onLongActionBegin ( Asc . c _oAscAsyncActionType [ 'BlockInteraction' ] , LoadingDocument ) ;
2016-03-11 00:48:53 +00:00
api . asc _LoadDocument ( ) ;
api . Resize ( ) ;
}
function onOpenDocument ( progress ) {
var proc = ( progress . asc _getCurrentFont ( ) + progress . asc _getCurrentImage ( ) ) / ( progress . asc _getFontsCount ( ) + progress . asc _getImagesCount ( ) ) ;
2021-06-24 16:08:21 +00:00
me . loadMask && me . loadMask . setTitle ( me . textLoadingDocument + ': ' + common . utils . fixedDigits ( Math . min ( Math . round ( proc * 100 ) , 100 ) , 3 , " " ) + '%' ) ;
2016-03-11 00:48:53 +00:00
}
function onError ( id , level , errData ) {
2018-10-08 11:21:05 +00:00
if ( id == Asc . c _oAscError . ID . LoadingScriptError ) {
$ ( '#id-critical-error-title' ) . text ( me . criticalErrorTitle ) ;
$ ( '#id-critical-error-message' ) . text ( me . scriptLoadError ) ;
2019-05-14 11:11:42 +00:00
$ ( '#id-critical-error-close' ) . text ( me . txtClose ) . off ( ) . on ( 'click' , function ( ) {
2018-10-08 11:21:05 +00:00
window . location . reload ( ) ;
} ) ;
$ ( '#id-critical-error-dialog' ) . css ( 'z-index' , 20002 ) . modal ( 'show' ) ;
return ;
}
2016-03-11 00:48:53 +00:00
hidePreloader ( ) ;
2021-06-24 16:08:21 +00:00
onLongActionEnd ( Asc . c _oAscAsyncActionType [ 'BlockInteraction' ] , LoadingDocument ) ;
2016-03-11 00:48:53 +00:00
var message ;
switch ( id )
{
2016-04-05 11:52:34 +00:00
case Asc . c _oAscError . ID . Unknown :
2016-03-11 00:48:53 +00:00
message = me . unknownErrorText ;
break ;
2016-04-05 11:52:34 +00:00
case Asc . c _oAscError . ID . ConvertationTimeout :
2016-03-11 00:48:53 +00:00
message = me . convertationTimeoutText ;
break ;
2016-04-05 11:52:34 +00:00
case Asc . c _oAscError . ID . ConvertationError :
2016-03-11 00:48:53 +00:00
message = me . convertationErrorText ;
break ;
2016-04-05 11:52:34 +00:00
case Asc . c _oAscError . ID . DownloadError :
2016-03-11 00:48:53 +00:00
message = me . downloadErrorText ;
break ;
2018-10-09 11:32:18 +00:00
case Asc . c _oAscError . ID . ConvertationPassword :
message = me . errorFilePassProtect ;
break ;
2019-03-29 09:21:43 +00:00
case Asc . c _oAscError . ID . UserDrop :
message = me . errorUserDrop ;
break ;
2019-08-28 14:29:39 +00:00
case Asc . c _oAscError . ID . ConvertationOpenLimitError :
message = me . errorFileSizeExceed ;
break ;
2019-11-13 11:14:41 +00:00
case Asc . c _oAscError . ID . UpdateVersion :
message = me . errorUpdateVersionOnDisconnect ;
break ;
2020-04-07 09:26:19 +00:00
case Asc . c _oAscError . ID . AccessDeny :
message = me . errorAccessDeny ;
break ;
2021-05-20 14:44:21 +00:00
case Asc . c _oAscError . ID . Submit :
message = me . errorSubmit ;
_submitFail = true ;
$submitedTooltip && $submitedTooltip . hide ( ) ;
break ;
case Asc . c _oAscError . ID . EditingError :
message = me . errorEditingDownloadas ;
break ;
2021-07-27 15:37:37 +00:00
case Asc . c _oAscError . ID . ForceSaveButton :
case Asc . c _oAscError . ID . ForceSaveTimeout :
message = me . errorForceSave ;
break ;
2016-03-11 00:48:53 +00:00
default :
message = me . errorDefaultMessage . replace ( '%1' , id ) ;
break ;
}
2016-04-05 11:52:34 +00:00
if ( level == Asc . c _oAscError . Level . Critical ) {
2016-03-11 00:48:53 +00:00
// report only critical errors
Common . Gateway . reportError ( id , message ) ;
$ ( '#id-critical-error-title' ) . text ( me . criticalErrorTitle ) ;
2019-08-28 14:29:39 +00:00
$ ( '#id-critical-error-message' ) . html ( message ) ;
2019-05-14 11:11:42 +00:00
$ ( '#id-critical-error-close' ) . text ( me . txtClose ) . off ( ) . on ( 'click' , function ( ) {
2016-03-11 00:48:53 +00:00
window . location . reload ( ) ;
} ) ;
}
else {
2017-10-07 09:20:39 +00:00
Common . Gateway . reportWarning ( id , message ) ;
2016-03-11 00:48:53 +00:00
$ ( '#id-critical-error-title' ) . text ( me . notcriticalErrorTitle ) ;
2019-08-28 14:29:39 +00:00
$ ( '#id-critical-error-message' ) . html ( message ) ;
2019-05-14 11:11:42 +00:00
$ ( '#id-critical-error-close' ) . text ( me . txtClose ) . off ( ) . on ( 'click' , function ( ) {
2016-03-11 00:48:53 +00:00
$ ( '#id-critical-error-dialog' ) . modal ( 'hide' ) ;
} ) ;
}
$ ( '#id-critical-error-dialog' ) . modal ( 'show' ) ;
Common . Analytics . trackEvent ( 'Internal Error' , id . toString ( ) ) ;
}
2017-05-16 07:46:04 +00:00
function onExternalMessage ( error ) {
2016-03-11 00:48:53 +00:00
if ( error ) {
hidePreloader ( ) ;
2019-05-14 11:11:42 +00:00
$ ( '#id-error-mask-title' ) . text ( me . criticalErrorTitle ) ;
2016-03-11 00:48:53 +00:00
$ ( '#id-error-mask-text' ) . text ( error . msg ) ;
$ ( '#id-error-mask' ) . css ( 'display' , 'block' ) ;
2017-05-16 07:46:04 +00:00
Common . Analytics . trackEvent ( 'External Error' ) ;
2016-03-11 00:48:53 +00:00
}
}
function onProcessMouse ( data ) {
if ( data . type == 'mouseup' ) {
var e = document . getElementById ( 'editor_sdk' ) ;
if ( e ) {
var r = e . getBoundingClientRect ( ) ;
api . OnMouseUp (
data . x - r . left ,
data . y - r . top
) ;
}
}
}
2021-03-29 11:30:31 +00:00
function onRequestClose ( ) {
Common . Gateway . requestClose ( ) ;
}
2016-03-11 00:48:53 +00:00
function onDownloadAs ( ) {
2019-01-10 14:20:59 +00:00
if ( permissions . download === false ) {
Common . Gateway . reportError ( Asc . c _oAscError . ID . AccessDeny , me . errorAccessDeny ) ;
return ;
}
2019-07-24 08:36:13 +00:00
if ( api ) api . asc _DownloadAs ( new Asc . asc _CDownloadOptions ( Asc . c _oAscFileType . DOCX , true ) ) ;
2016-03-11 00:48:53 +00:00
}
2020-05-22 12:04:55 +00:00
function onRunAutostartMacroses ( ) {
if ( ! config . customization || ( config . customization . macros !== false ) )
if ( api ) api . asc _runAutostartMacroses ( ) ;
}
2021-05-25 13:40:40 +00:00
function onBeforeUnload ( ) {
common . localStorage . save ( ) ;
}
// Helpers
2016-03-11 00:48:53 +00:00
// -------------------------
function onDocumentResize ( ) {
2016-10-31 14:49:53 +00:00
api && api . Resize ( ) ;
2016-03-11 00:48:53 +00:00
}
function createController ( ) {
if ( created )
return me ;
me = this ;
created = true ;
$ ( window ) . resize ( function ( ) {
onDocumentResize ( ) ;
} ) ;
2021-05-25 13:40:40 +00:00
window . onbeforeunload = onBeforeUnload ;
2016-03-11 00:48:53 +00:00
2016-10-31 14:49:53 +00:00
var ismodalshown = false ;
$ ( document . body ) . on ( 'show.bs.modal' , '.modal' ,
function ( e ) {
ismodalshown = true ;
api . asc _enableKeyEvents ( false ) ;
}
) . on ( 'hidden.bs.modal' , '.modal' ,
function ( e ) {
ismodalshown = false ;
api . asc _enableKeyEvents ( true ) ;
}
) . on ( 'hidden.bs.dropdown' , '.dropdown' ,
function ( e ) {
if ( ! ismodalshown )
api . asc _enableKeyEvents ( true ) ;
}
) . on ( 'blur' , 'input, textarea' ,
function ( e ) {
if ( ! ismodalshown ) {
if ( ! /area_id/ . test ( e . target . id ) ) {
api . asc _enableKeyEvents ( true ) ;
}
}
}
) ;
2016-03-11 00:48:53 +00:00
2016-10-31 14:49:53 +00:00
$ ( '#editor_sdk' ) . on ( 'click' , function ( e ) {
if ( e . target . localName == 'canvas' ) {
e . currentTarget . focus ( ) ;
}
2016-03-11 00:48:53 +00:00
} ) ;
window [ "flat_desine" ] = true ;
2016-05-13 08:37:54 +00:00
api = new Asc . asc _docs _api ( {
2019-10-30 11:48:09 +00:00
'id-view' : 'editor_sdk' ,
'embedded' : true
2016-05-13 08:37:54 +00:00
} ) ;
2016-03-11 00:48:53 +00:00
if ( api ) {
api . asc _registerCallback ( 'asc_onError' , onError ) ;
api . asc _registerCallback ( 'asc_onDocumentContentReady' , onDocumentContentReady ) ;
api . asc _registerCallback ( 'asc_onOpenDocumentProgress' , onOpenDocument ) ;
2016-10-31 14:49:53 +00:00
2016-03-11 00:48:53 +00:00
api . asc _registerCallback ( 'asc_onCountPages' , onCountPages ) ;
// api.asc_registerCallback('OnCurrentVisiblePage', onCurrentPage);
api . asc _registerCallback ( 'asc_onCurrentPage' , onCurrentPage ) ;
// Initialize api gateway
Common . Gateway . on ( 'init' , loadConfig ) ;
Common . Gateway . on ( 'opendocument' , loadDocument ) ;
2017-05-16 07:46:04 +00:00
Common . Gateway . on ( 'showmessage' , onExternalMessage ) ;
2017-09-20 11:32:18 +00:00
Common . Gateway . appReady ( ) ;
2016-03-11 00:48:53 +00:00
}
return me ;
}
return {
create : createController ,
errorDefaultMessage : 'Error code: %1' ,
unknownErrorText : 'Unknown error.' ,
2019-05-14 13:55:52 +00:00
convertationTimeoutText : 'Conversion timeout exceeded.' ,
convertationErrorText : 'Conversion failed.' ,
2016-03-11 00:48:53 +00:00
downloadErrorText : 'Download failed.' ,
criticalErrorTitle : 'Error' ,
2018-10-08 11:21:05 +00:00
notcriticalErrorTitle : 'Warning' ,
2018-10-09 11:32:18 +00:00
scriptLoadError : 'The connection is too slow, some of the components could not be loaded. Please reload the page.' ,
2019-01-10 14:20:59 +00:00
errorFilePassProtect : 'The file is password protected and cannot be opened.' ,
2019-03-29 09:21:43 +00:00
errorAccessDeny : 'You are trying to perform an action you do not have rights for.<br>Please contact your Document Server administrator.' ,
2019-05-14 11:11:42 +00:00
errorUserDrop : 'The file cannot be accessed right now.' ,
unsupportedBrowserErrorText : 'Your browser is not supported.' ,
textOf : 'of' ,
downloadTextText : 'Downloading document...' ,
waitText : 'Please, wait...' ,
textLoadingDocument : 'Loading document' ,
2019-08-28 14:29:39 +00:00
txtClose : 'Close' ,
2019-11-13 11:14:41 +00:00
errorFileSizeExceed : 'The file size exceeds the limitation set for your server.<br>Please contact your Document Server administrator for details.' ,
2021-05-17 22:49:08 +00:00
errorUpdateVersionOnDisconnect : 'Internet connection has been restored, and the file version has been changed.<br>Before you can continue working, you need to download the file or copy its content to make sure nothing is lost, and then reload this page.' ,
textNext : 'Next Field' ,
2021-05-18 22:26:16 +00:00
textClear : 'Clear All Fields' ,
2021-05-20 14:44:21 +00:00
textSubmit : 'Submit' ,
textSubmited : '<b>Form submitted successfully</b><br>Click to close the tip.' ,
errorSubmit : 'Submit failed.' ,
2021-05-25 13:40:40 +00:00
errorEditingDownloadas : 'An error occurred during the work with the document.<br>Use the \'Download as...\' option to save the file backup copy to your computer hard drive.' ,
textGuest : 'Guest' ,
2021-05-31 23:01:44 +00:00
textAnonymous : 'Anonymous' ,
textRequired : 'Fill all required fields to send form.' ,
2021-07-27 15:37:37 +00:00
textGotIt : 'Got it' ,
2021-07-28 11:32:05 +00:00
errorForceSave : "An error occurred while saving the file. Please use the 'Download as' option to save the file to your computer hard drive or try again later." ,
txtEmpty : '(Empty)'
2016-03-11 00:48:53 +00:00
}
} ) ( ) ;