2020-02-06 14:30:22 +01:00
"use strict" ;
2012-06-06 06:13:19 +02:00
/ * *
2013-04-13 21:00:13 +02:00
* EGroupware eTemplate2 - JS widget for HTML editing
2012-06-06 06:13:19 +02:00
*
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ package etemplate
* @ subpackage api
* @ link http : //www.egroupware.org
2018-10-19 16:35:18 +02:00
* @ author Hadi Nategh < hn @ egroupware . org >
* @ copyright Hadi Nategh < hn @ egroupware . org >
2012-06-06 06:13:19 +02:00
* @ version $Id$
* /
2020-02-06 14:30:22 +01:00
var _ _extends = ( this && this . _ _extends ) || ( function ( ) {
var extendStatics = function ( d , b ) {
extendStatics = Object . setPrototypeOf ||
( { _ _proto _ _ : [ ] } instanceof Array && function ( d , b ) { d . _ _proto _ _ = b ; } ) ||
function ( d , b ) { for ( var p in b ) if ( b . hasOwnProperty ( p ) ) d [ p ] = b [ p ] ; } ;
return extendStatics ( d , b ) ;
} ;
return function ( d , b ) {
extendStatics ( d , b ) ;
function _ _ ( ) { this . constructor = d ; }
d . prototype = b === null ? Object . create ( b ) : ( _ _ . prototype = b . prototype , new _ _ ( ) ) ;
} ;
} ) ( ) ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2012-06-06 06:13:19 +02:00
/ * e g w : u s e s
2020-02-06 14:30:22 +01:00
jsapi . jsapi ; // Needed for egw_seperateJavaScript
/ v e n d o r / t i n y m c e / t i n y m c e / t i n y m c e . m i n . j s ;
et2 _core _editableWidget ;
2012-06-06 06:13:19 +02:00
* /
2020-02-06 14:30:22 +01:00
var et2 _core _editableWidget _1 = require ( "./et2_core_editableWidget" ) ;
var et2 _core _inheritance _1 = require ( "./et2_core_inheritance" ) ;
var et2 _core _widget _1 = require ( "./et2_core_widget" ) ;
2013-04-13 21:00:13 +02:00
/ * *
* @ augments et2 _inputWidget
* /
2020-02-06 14:30:22 +01:00
var et2 _htmlarea = /** @class */ ( function ( _super ) {
_ _extends ( et2 _htmlarea , _super ) ;
/ * *
* Constructor
* /
function et2 _htmlarea ( _parent , _attrs , _child ) {
var _this =
// Call the inherited constructor
_super . call ( this , _parent , _attrs , et2 _core _inheritance _1 . ClassWithAttributes . extendAttributes ( et2 _htmlarea . _attributes , _child || { } ) ) || this ;
_this . editor = null ;
_this . htmlNode = null ;
_this . editor = null ; // TinyMce editor instance
_this . supportedWidgetClasses = [ ] ; // Allow no child widgets
_this . htmlNode = jQuery ( document . createElement ( _this . options . readonly ? "div" : "textarea" ) )
. addClass ( 'et2_textbox_ro' ) ;
if ( _this . options . height ) {
_this . htmlNode . css ( 'height' , _this . options . height ) ;
}
_this . setDOMNode ( _this . htmlNode [ 0 ] ) ;
return _this ;
}
/ * *
*
* @ returns { undefined }
* /
et2 _htmlarea . prototype . doLoadingFinished = function ( ) {
_super . prototype . doLoadingFinished . call ( this ) ;
this . init _editor ( ) ;
return true ;
} ;
et2 _htmlarea . prototype . init _editor = function ( ) {
if ( this . mode == 'ascii' || this . editor != null || this . options . readonly )
return ;
var imageUpload ;
var self = this ;
if ( this . options . imageUpload && this . options . imageUpload [ 0 ] !== '/' && this . options . imageUpload . substr ( 0 , 4 ) != 'http' ) {
imageUpload = egw . ajaxUrl ( "EGroupware\\Api\\Etemplate\\Widget\\Vfs::ajax_htmlarea_upload" ) +
'&request_id=' + this . getInstanceManager ( ) . etemplate _exec _id + '&widget_id=' + this . options . imageUpload + '&type=htmlarea' ;
imageUpload = imageUpload . substr ( egw . webserverUrl . length + 1 ) ;
}
else if ( imageUpload ) {
imageUpload = this . options . imageUpload . substr ( egw . webserverUrl . length + 1 ) ;
}
else {
imageUpload = egw . ajaxUrl ( "EGroupware\\Api\\Etemplate\\Widget\\Vfs::ajax_htmlarea_upload" ) +
'&request_id=' + this . getInstanceManager ( ) . etemplate _exec _id + '&type=htmlarea' ;
}
// default settings for initialization
var settings = {
target : this . htmlNode [ 0 ] ,
body _id : this . dom _id + '_htmlarea' ,
menubar : false ,
statusbar : this . options . statusbar ,
branding : false ,
resize : false ,
height : this . options . height ,
width : this . options . width ,
mobile : {
theme : 'silver'
} ,
formats : {
customparagraph : { block : 'p' , styles : { "margin-block-start" : "0px" , "margin-block-end" : "0px" } }
} ,
min _height : 100 ,
convert _urls : false ,
language : et2 _htmlarea . LANGUAGE _CODE [ egw . preference ( 'lang' , 'common' ) ] ,
language _url : egw . webserverUrl + '/api/js/tinymce/langs/' + et2 _htmlarea . LANGUAGE _CODE [ egw . preference ( 'lang' , 'common' ) ] + '.js' ,
paste _data _images : true ,
paste _filter _drop : true ,
browser _spellcheck : true ,
contextmenu : false ,
images _upload _url : imageUpload ,
file _picker _callback : jQuery . proxy ( this . _file _picker _callback , this ) ,
images _upload _handler : this . options . images _upload _handler ,
init _instance _callback : jQuery . proxy ( this . _instanceIsReady , this ) ,
auto _focus : false ,
valid _children : this . options . valid _children ,
plugins : [
"print searchreplace autolink directionality " ,
"visualblocks visualchars image link media template " ,
"codesample table charmap hr pagebreak nonbreaking anchor toc " ,
"insertdatetime advlist lists textcolor wordcount imagetools " ,
"colorpicker textpattern help paste code searchreplace tabfocus"
] ,
toolbar : et2 _htmlarea . TOOLBAR _SIMPLE ,
block _formats : "Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;" +
"Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre;Custom Paragraph=customparagraph" ,
font _formats : "Andale Mono=andale mono,times;Arial=arial,helvetica," +
"sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book " +
"antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;" +
"Courier New=courier new,courier;Georgia=georgia,palatino;" +
"Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;" +
"Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal," +
"monaco;Times New Roman=times new roman,times;Trebuchet " +
"MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;" +
"Wingdings=wingdings,zapf dingbats" ,
fontsize _formats : '8pt 10pt 12pt 14pt 18pt 24pt 36pt' ,
setup : function ( ed ) {
ed . on ( 'init' , function ( ) {
2019-01-14 10:37:07 +01:00
this . getDoc ( ) . body . style . fontSize = egw . preference ( 'rte_font_size' , 'common' )
2020-02-06 14:30:22 +01:00
+ egw . preference ( 'rte_font_unit' , 'common' ) ;
2019-01-14 10:37:07 +01:00
this . getDoc ( ) . body . style . fontFamily = egw . preference ( 'rte_font' , 'common' ) ;
} ) ;
}
2020-02-06 14:30:22 +01:00
} ;
// extend default settings with configured options and preferences
jQuery . extend ( settings , this . _extendedSettings ( ) ) ;
this . tinymce = tinymce . init ( settings ) ;
// make sure value gets set in case of widget gets loaded by delay like
// inside an inactive tabs
this . tinymce . then ( function ( ) {
self . set _value ( self . htmlNode . val ( ) ) ;
if ( self . editor && self . editor . editorContainer ) {
self . editor . formatter . toggle ( egw . preference ( 'rte_formatblock' , 'common' ) ) ;
jQuery ( self . editor . editorContainer ) . height ( self . options . height ) ;
jQuery ( self . editor . iframeElement . contentWindow . document ) . on ( 'dragenter' , function ( ) {
if ( jQuery ( '#dragover-tinymce' ) . length < 1 )
jQuery ( "<style id='dragover-tinymce'>.dragover:after {height:calc(100% - " + jQuery ( this ) . height ( ) + "px) !important;}</style>" ) . appendTo ( 'head' ) ;
} ) ;
}
} ) ;
} ;
/ * *
* set disabled
*
* @ param { type } _value
* @ returns { undefined }
* /
et2 _htmlarea . prototype . set _disabled = function ( _value ) {
_super . prototype . set _disabled . call ( this , _value ) ;
if ( _value ) {
jQuery ( this . tinymce _container ) . css ( 'display' , 'none' ) ;
}
else {
jQuery ( this . tinymce _container ) . css ( 'display' , 'flex' ) ;
}
} ;
et2 _htmlarea . prototype . set _readonly = function ( _value ) {
if ( this . options . readonly === _value )
return ;
var value = this . get _value ( ) ;
this . options . readonly = _value ;
if ( this . options . readonly ) {
if ( this . editor )
this . editor . remove ( ) ;
this . htmlNode = jQuery ( document . createElement ( this . options . readonly ? "div" : "textarea" ) )
. addClass ( 'et2_textbox_ro' ) ;
if ( this . options . height ) {
this . htmlNode . css ( 'height' , this . options . height ) ;
}
this . editor = null ;
this . setDOMNode ( this . htmlNode [ 0 ] ) ;
this . set _value ( value ) ;
}
else {
if ( ! this . editor ) {
this . htmlNode = jQuery ( document . createElement ( "textarea" ) )
. val ( value ) ;
if ( this . options . height || this . options . editable _height ) {
this . htmlNode . css ( 'height' , ( this . options . editable _height ? this . options . editable _height : this . options . height ) ) ;
}
this . setDOMNode ( this . htmlNode [ 0 ] ) ;
this . init _editor ( ) ;
}
}
} ;
/ * *
* Callback function runs when the filepicker in image dialog is clicked
*
* @ param { type } _callback
* @ param { type } _value
* @ param { type } _meta
* /
et2 _htmlarea . prototype . _file _picker _callback = function ( _callback , _value , _meta ) {
if ( typeof this . file _picker _callback == 'function' )
return this . file _picker _callback . call ( arguments , this ) ;
var callback = _callback ;
// Don't rely only on app_name to fetch et2 object as app_name may not
// always represent current app of the window, e.g.: mail admin account.
// Try to fetch et2 from its template name.
var etemplate = jQuery ( 'form' ) . data ( 'etemplate' ) ;
var et2 ;
if ( etemplate && etemplate . name && ! app [ egw ( window ) . app _name ( ) ] ) {
et2 = etemplate2 . getByTemplate ( etemplate . name ) [ 0 ] [ 'widgetContainer' ] ;
}
else {
et2 = app [ egw ( window ) . app _name ( ) ] . et2 ;
}
var vfsSelect = et2 _createWidget ( 'vfs-select' , {
id : 'upload' ,
mode : 'open' ,
name : '' ,
button _caption : "Link" ,
button _label : "Link" ,
dialog _title : "Link file" ,
method : "download"
} , et2 ) ;
jQuery ( vfsSelect . getDOMNode ( ) ) . on ( 'change' , function ( ) {
callback ( vfsSelect . get _value ( ) , { alt : vfsSelect . get _value ( ) } ) ;
} ) ;
// start the file selector dialog
vfsSelect . click ( ) ;
} ;
/ * *
* Callback when instance is ready
*
* @ param { type } _editor
* /
et2 _htmlarea . prototype . _instanceIsReady = function ( _editor ) {
console . log ( "Editor: " + _editor . id + " is now initialized." ) ;
// try to reserve focus state as running command on editor may steal the
// current focus.
var focusedEl = jQuery ( ':focus' ) ;
this . editor = _editor ;
this . editor . on ( 'drop' , function ( e ) {
e . preventDefault ( ) ;
} ) ;
if ( ! this . disabled )
jQuery ( this . editor . editorContainer ) . css ( 'display' , 'flex' ) ;
this . tinymce _container = this . editor . editorContainer ;
// go back to reserved focused element
focusedEl . focus ( ) ;
} ;
/ * *
* Takes all relevant preferences into account and set settings accordingly
*
* @ returns { object } returns a object including all settings
* /
et2 _htmlarea . prototype . _extendedSettings = function ( ) {
var rte _menubar = egw . preference ( 'rte_menubar' , 'common' ) ;
var rte _toolbar = egw . preference ( 'rte_toolbar' , 'common' ) ;
// we need to have rte_toolbar values as an array
if ( rte _toolbar && typeof rte _toolbar == "object" ) {
rte _toolbar = Object . keys ( rte _toolbar ) . map ( function ( key ) { return rte _toolbar [ key ] ; } ) ;
}
var settings = {
fontsize _formats : et2 _htmlarea . FONT _SIZE _FORMATS [ egw . preference ( 'rte_font_unit' , 'common' ) ] ,
menubar : parseInt ( rte _menubar ) && this . menubar ? true : typeof rte _menubar != 'undefined' ? false : this . menubar
} ;
switch ( this . mode ) {
case 'simple' :
settings [ 'toolbar' ] = et2 _htmlarea . TOOLBAR _SIMPLE ;
break ;
case 'extended' :
settings [ 'toolbar' ] = et2 _htmlarea . TOOLBAR _EXTENDED ;
break ;
case 'advanced' :
settings [ 'toolbar' ] = et2 _htmlarea . TOOLBAR _ADVANCED ;
break ;
default :
this . mode = '' ;
}
// take rte_toolbar into account if no mode restrictly set from template
if ( rte _toolbar && ! this . mode ) {
var toolbar _diff = et2 _htmlarea . TOOLBAR _LIST . filter ( function ( i ) { return ! ( rte _toolbar . indexOf ( i ) > - 1 ) ; } ) ;
settings [ 'toolbar' ] = et2 _htmlarea . TOOLBAR _ADVANCED ;
toolbar _diff . forEach ( function ( a ) {
var r = new RegExp ( a ) ;
settings [ 'toolbar' ] = settings [ 'toolbar' ] . replace ( r , '' ) ;
} ) ;
}
return settings ;
} ;
et2 _htmlarea . prototype . destroy = function ( ) {
if ( this . editor ) {
this . editor . destroy ( ) ;
}
this . editor = null ;
this . tinymce = null ;
this . tinymce _container = null ;
this . htmlNode . remove ( ) ;
this . htmlNode = null ;
_super . prototype . destroy . call ( this ) ;
} ;
et2 _htmlarea . prototype . set _value = function ( _value ) {
this . _oldValue = _value ;
if ( this . editor ) {
this . editor . setContent ( _value ) ;
}
else {
if ( this . options . readonly ) {
this . htmlNode . empty ( ) . append ( _value ) ;
}
else {
this . htmlNode . val ( _value ) ;
}
}
this . value = _value ;
} ;
et2 _htmlarea . prototype . getValue = function ( ) {
return this . editor ? this . editor . getContent ( ) : ( this . options . readonly ? this . value : this . htmlNode . val ( ) ) ;
} ;
/ * *
* Resize htmlNode tag according to window size
* @ param { type } _height excess height which comes from window resize
* /
et2 _htmlarea . prototype . resize = function ( _height ) {
if ( _height && this . options . resize _ratio !== '0' ) {
// apply the ratio
_height = ( this . options . resize _ratio != '' ) ? _height * this . options . resize _ratio : _height ;
if ( _height != 0 ) {
if ( this . editor ) // TinyMCE HTML
{
var h = void 0 ;
if ( typeof this . editor . iframeElement != 'undefined' && this . editor . editorContainer . clientHeight > 0 ) {
h = ( this . editor . editorContainer . clientHeight + _height ) > 0 ?
( this . editor . editorContainer . clientHeight ) + _height : this . editor . settings . min _height ;
}
else // fallback height size
{
h = this . editor . settings . min _height + _height ;
}
jQuery ( this . editor . editorContainer ) . height ( h ) ;
jQuery ( this . editor . iframeElement ) . height ( h - ( this . editor . editorContainer . getElementsByClassName ( 'tox-toolbar' ) [ 0 ] . clientHeight +
this . editor . editorContainer . getElementsByClassName ( 'tox-statusbar' ) [ 0 ] . clientHeight ) ) ;
}
else // No TinyMCE
{
this . htmlNode . height ( this . htmlNode . height ( ) + _height ) ;
}
}
}
} ;
et2 _htmlarea . _attributes = {
mode : {
'name' : 'Mode' ,
'description' : 'One of {ascii|simple|extended|advanced}' ,
'default' : '' ,
'type' : 'string'
} ,
height : {
'name' : 'Height' ,
'default' : et2 _no _init ,
'type' : 'string'
} ,
width : {
'name' : 'Width' ,
'default' : et2 _no _init ,
'type' : 'string'
} ,
value : {
name : "Value" ,
description : "The value of the widget" ,
type : "html" ,
default : et2 _no _init
} ,
imageUpload : {
name : "imageUpload" ,
description : "Url to upload images dragged in or id of link_to widget to it's vfs upload. Can also be just a name for which content array contains a path to upload the picture." ,
type : "string" ,
default : null
} ,
file _picker _callback : {
name : "File picker callback" ,
description : "Callback function to get called when file picker is clicked" ,
type : 'js' ,
default : et2 _no _init
} ,
images _upload _handler : {
name : "Images upload handler" ,
description : "Callback function for handling image upload" ,
type : 'js' ,
default : et2 _no _init
} ,
menubar : {
name : "Menubar" ,
description : "Display menubar at the top of the editor" ,
type : "boolean" ,
default : true
} ,
statusbar : {
name : "Status bar" ,
description : "Enable/disable status bar on the bottom of editor" ,
type : "boolean" ,
default : true
} ,
valid _children : {
name : "Valid children" ,
description : "Enables to control what child tag is allowed or not allowed of the present tag. For instance: +body[style], makes style tag allowed inside body" ,
type : "string" ,
default : "+body[style]"
}
} ;
/ * *
* Array of toolbars
* @ constant
* /
et2 _htmlarea . TOOLBAR _LIST = [ 'undo' , 'redo' , 'formatselect' , 'fontselect' , 'fontsizeselect' ,
'bold' , 'italic' , 'strikethrough' , 'forecolor' , 'backcolor' , 'link' ,
'alignleft' , 'aligncenter' , 'alignright' , 'alignjustify' , 'numlist' ,
'bullist' , 'outdent' , 'indent' , 'ltr' , 'rtl' , 'removeformat' , 'code' , 'image' , 'searchreplace'
] ;
/ * *
* arranged toolbars as simple mode
* @ constant
* /
et2 _htmlarea . TOOLBAR _SIMPLE = "undo redo|formatselect fontselect fontsizeselect | bold italic removeformat forecolor backcolor | " +
"alignleft aligncenter alignright alignjustify | numlist " +
"bullist outdent indent| link image pastetext" ;
/ * *
* arranged toolbars as extended mode
* @ constant
* /
et2 _htmlarea . TOOLBAR _EXTENDED = "fontselect fontsizeselect | bold italic strikethrough forecolor backcolor | " +
"link | alignleft aligncenter alignright alignjustify | numlist " +
"bullist outdent indent | removeformat | image" ;
/ * *
* arranged toolbars as advanced mode
* @ constant
* /
et2 _htmlarea . TOOLBAR _ADVANCED = "undo redo| formatselect | fontselect fontsizeselect | bold italic strikethrough forecolor backcolor | " +
"link | alignleft aligncenter alignright alignjustify | numlist " +
"bullist outdent indent ltr rtl | removeformat code| image | searchreplace" ;
/ * *
* font size formats
* @ constant
* /
et2 _htmlarea . FONT _SIZE _FORMATS = {
2020-02-11 17:05:19 +01:00
pt : "8pt 9pt 10pt 11pt 12pt 14pt 16pt 18pt 20pt 22pt 24pt 26pt 28pt 36pt 48pt 72pt" ,
px : "8px 9px 10px 11px 12px 14px 16px 18px 20px 22px 24px 26px 28px 36px 48px 72px"
2020-02-06 14:30:22 +01:00
} ;
/ * *
* language code represention for TinyMCE lang code
* /
et2 _htmlarea . LANGUAGE _CODE = {
bg : "bg_BG" , ca : "ca" , cs : "cs" , da : "da" , de : "de" , en : "en_CA" ,
el : "el" , "es-es" : "es" , et : "et" , eu : "eu" , fa : "fa_IR" , fi : "fi" ,
fr : "fr_FR" , hi : "" , hr : "hr" , hu : "hu_HU" , id : "id" , it : "it" , iw : "" ,
ja : "ja" , ko : "ko_KR" , lo : "" , lt : "lt" , lv : "lv" , nl : "nl" , no : "nb_NO" ,
pl : "pl" , pt : "pt_PT" , "pt-br" : "pt_BR" , ru : "ru" , sk : "sk" , sl : "sl_SI" ,
sv : "sv_SE" , th : "th_TH" , tr : "tr_TR" , uk : "en_GB" , vi : "vi_VN" , zh : "zh_CN" ,
"zh-tw" : "zh_TW"
} ;
return et2 _htmlarea ;
} ( et2 _core _editableWidget _1 . et2 _editableWidget ) ) ;
et2 _core _widget _1 . et2 _register _widget ( et2 _htmlarea , [ "htmlarea" ] ) ;