61 public $toolbarstartexpanded;
81 public $uselocalbrowser;
115 public function __construct($htmlname, $content, $width =
'', $height = 200, $toolbarname =
'Basic', $toolbarlocation =
'In', $toolbarstartexpanded =
false, $uselocalbrowser = -1, $okforextendededitor =
true, $rows = 0, $cols =
'', $readonly = 0, $poscursor = array())
119 dol_syslog(get_class($this).
"::DolEditor htmlname=".$htmlname.
" width=".$width.
" height=".$height.
" toolbarname=".$toolbarname.
" uselocalbrowser=".$uselocalbrowser);
121 if ($uselocalbrowser === -1) {
123 $uselocalbrowser =
getDolGlobalInt(
"WYSIWYG_ALLOW_UPLOAD_MEDIA_FILES");
127 $rows = round($height / 20);
130 $cols = ($width ? round($width / 6) : 80);
132 $shorttoolbarname = preg_replace(
'/_encoded$/',
'', $toolbarname);
135 $defaulteditor =
'ckeditor';
136 $this->tool = !
getDolGlobalString(
'FCKEDITOR_EDITORNAME') ? $defaulteditor :
$conf->global->FCKEDITOR_EDITORNAME;
137 $this->uselocalbrowser = $uselocalbrowser;
138 $this->readonly = $readonly;
141 if ((!isModEnabled(
'fckeditor') && $okforextendededitor !==
'ace') || empty($okforextendededitor)) {
142 $this->tool =
'textarea';
144 if ($okforextendededitor ===
'ace') {
148 if (empty(
$conf->use_javascript_ajax)) {
149 $this->tool =
'textarea';
152 if (isset($poscursor[
'find'])) {
154 $lines = explode(
"\n", $content);
155 $nblines = count($lines);
156 for ($i = 0 ; $i < $nblines ; $i++) {
157 if (preg_match(
'/'.$poscursor[
'find'].
'/', $lines[$i])) {
163 $poscursor[
'y'] = $posy;
168 if (in_array($this->tool, array(
'textarea',
'ckeditor',
'ace'))) {
172 $this->content = $content;
174 $this->htmlname = $htmlname;
175 $this->toolbarname = $shorttoolbarname;
176 $this->toolbarstartexpanded = $toolbarstartexpanded;
177 $this->rows = max(ROWS_3, $rows);
178 $this->cols = (preg_match(
'/%/', $cols) ? $cols : max(40, $cols));
179 $this->height = $height;
180 $this->width = $width;
181 $this->posx = empty($poscursor[
'x']) ? 0 : $poscursor[
'x'];
182 $this->posy = empty($poscursor[
'y']) ? 0 : $poscursor[
'y'];
200 public function Create($noprint = 0, $morejs =
'', $disallowAnyContent =
true, $titlecontent =
'', $option =
'', $moreparam =
'', $morecss =
'')
203 global
$conf, $langs;
206 if (isset(
$conf->global->FCKEDITOR_ALLOW_ANY_CONTENT)) {
213 $this->content = ($this->content ??
'');
215 if (in_array($this->tool, array(
'textarea',
'ckeditor'))) {
220 $out .=
'<textarea id="'.$this->htmlname.
'" name="'.$this->htmlname.
'"';
221 $out .=
' rows="'.$this->rows.
'"';
223 $out .= (preg_match(
'/%/', $this->cols) ?
' style="margin-top: 5px; width: '.$this->cols.
'"' :
' cols="'.$this->cols.
'"');
224 $out .=
' '.($moreparam ? $moreparam :
'');
225 $out .=
' class="flat '.$morecss.
'">';
226 $out .= htmlspecialchars($this->content);
227 $out .=
'</textarea>';
229 if ($this->tool ==
'ckeditor' && !empty(
$conf->use_javascript_ajax) && isModEnabled(
'fckeditor')) {
230 if (!defined(
'REQUIRE_CKEDITOR')) {
231 define(
'REQUIRE_CKEDITOR',
'1');
236 $pluginstodisable =
'elementspath,save,flash,div,anchor';
238 $pluginstodisable .=
',specialchar';
240 if (!empty(
$conf->dol_optimize_smallscreen)) {
241 $pluginstodisable .=
',scayt,wsc,find,undo';
244 $pluginstodisable .=
',wsc';
247 $pluginstodisable .=
',exportpdf';
250 $this->uselocalbrowser = 0;
252 $scaytautostartup =
'';
254 $scaytautostartup =
'scayt_autoStartup: true,';
255 $scaytautostartup .=
'scayt_sLang: \''.dol_escape_js($langs->getDefaultLang()).
'\',
';
257 $pluginstodisable .= ',scayt
';
260 $htmlencode_force = preg_match('/_encoded$/
', $this->toolbarname) ? 'true' : 'false';
262 $out .= '<!-- Output ckeditor disallowAnyContent=
'.dol_escape_htmltag((string) $disallowAnyContent).' toolbarname=
'.dol_escape_htmltag($this->toolbarname).' -->
'."\n";
263 //$out .= '<style>#cke_1_top { height: 34px !important; }</style>
';
264 $out .= '<script nonce=
"'.getNonce().'" type=
"text/javascript">
265 $(document).ready(
function () {
269 tmpeditor = CKEDITOR.replace(\
''.
dol_escape_js($this->htmlname).
'\',
272 customConfig: ckeditorConfig,
273 removePlugins: \
''.dol_escape_js($pluginstodisable).
'\',
275 readOnly:
'.($this->readonly ? 'true' : 'false').',
276 htmlEncodeOutput:
'.dol_escape_js($htmlencode_force).',
277 allowedContent:
'.($disallowAnyContent ? 'false' : 'true').',
278 extraAllowedContent: \
'a[target];section[contenteditable,id];div{float,display}\', /* Allow a tag with attribute target, allow seciont tag and allow the style float and display into div to default other allowed tags */
279 disallowedContent: \'\', /* Tags that are not allowed */
280 fullPage: '.($fullpage ?
'true' :
'false').
', /* if true, the html, header and body tags are kept */
282 toolbarStartupExpanded:
'.($this->toolbarstartexpanded ? 'true' : 'false').',
283 width:
'.($this->width ? '\
''.dol_escape_js($this->width).
'\'' :
'\'\
'').
',
286 '.$scaytautostartup.'
287 language: \
''.dol_escape_js($langs->defaultlang).
'\',
288 textDirection: \
''.dol_escape_js($langs->trans(
"DIRECTION")).
'\',
290 instanceReady :
function(ev) {
291 console.log(\
'ckeditor '.
dol_escape_js($this->htmlname).
' instanceReady\');
293 /* If we found the attribute required on source div, we remove it (not compatible with ckeditor) */
294 /* Disabled, because attribute required should never be used on fields for doleditor */
295 /* jQuery("#'.
dol_escape_js($this->htmlname).
'").attr("required", false); */
297 // Output paragraphs as <p>Text</p>.
298 this.dataProcessor.writer.setRules( \'p\', {
300 breakBeforeOpen : true,
301 breakAfterOpen : false,
302 breakBeforeClose : false,
303 breakAfterClose : true
306 /* This is to remove the tab Link on image popup. Does not work, so commented */
307 /* dialogDefinition: function (event) {
308 var dialogName = event.data.name;
309 var dialogDefinition = event.data.definition;
310 if (dialogName == \'image\') {
311 dialogDefinition.removeContents(\'Link\');
315 disableNativeSpellChecker: '.(
getDolGlobalString(
'CKEDITOR_NATIVE_SPELLCHECKER') ?
'false' :
'true');
317 if ($this->uselocalbrowser) {
321 $out .=
' filebrowserBrowseUrl : ckeditorFilebrowserBrowseUrl,';
322 $out .=
' filebrowserImageBrowseUrl : ckeditorFilebrowserImageBrowseUrl,';
334 $out .=
' filebrowserWindowWidth : \'900\',
335 filebrowserWindowHeight : \'500\',
336 filebrowserImageWindowWidth : \'900\',
337 filebrowserImageWindowHeight : \'500\'';
339 $out .=
' })'.$morejs;
343 $out .=
'</script>'.
"\n";
349 if (preg_match(
'/^ace/', $this->tool)) {
356 $out .=
'<div class="aceeditorstatusbar" id="statusBar'.$this->htmlname.
'">'.$titlecontent;
357 $out .=
' - <span id="morelines" class="right classlink cursorpointer morelines'.$this->htmlname.
'">'.
dol_escape_htmltag($langs->trans(
"ShowMoreLines")).
'</span> ';
359 $out .=
'<script nonce="'.getNonce().
'" type="text/javascript">'.
"\n";
360 $out .=
'jQuery(document).ready(function() {'.
"\n";
361 $out .=
' var aceEditor = window.ace.edit("'.dol_escape_all($this->htmlname).
'aceeditorid");
362 aceEditor.moveCursorTo('.($this->posy + 1).
','.$this->posx.
');
363 aceEditor.gotoLine('.($this->posy + 1).
','.$this->posx.
');
364 var StatusBar = window.ace.require("ace/ext/statusbar").StatusBar; // Init status bar. Need lib ext-statusbar
365 var statusBar = new StatusBar(aceEditor, document.getElementById("statusBar'.
dol_escape_all($this->htmlname).
'")); // Init status bar. Need lib ext-statusbar
367 var oldNbOfLines = 0;
368 jQuery(".morelines'.
dol_escape_all($this->htmlname).
'").click(function() {
369 var aceEditorClicked = window.ace.edit("'.$this->htmlname.
'aceeditorid");
370 currentline = aceEditorClicked.getOption("maxLines");
371 if (oldNbOfLines == 0)
373 oldNbOfLines = currentline;
375 console.log("We click on more lines, oldNbOfLines is "+oldNbOfLines+", we have currently "+currentline);
376 if (currentline < 500)
378 aceEditorClicked.setOptions({ maxLines: 500 });
382 aceEditorClicked.setOptions({ maxLines: oldNbOfLines });
386 $out .=
'</script>'.
"\n";
389 $out .=
'<pre id="'.$this->htmlname.
'aceeditorid" style="'.($this->width ?
'width: '.$this->width.
'px; ' :
'');
390 $out .= ($this->height ?
' height: '.$this->height.
'px; ' :
'');
393 $out .= htmlspecialchars($this->content);
395 $out .=
'<input type="hidden" id="'.$this->htmlname.
'_x" name="'.$this->htmlname.
'_x">';
396 $out .=
'<input type="hidden" id="'.$this->htmlname.
'_y" name="'.$this->htmlname.
'_y">';
397 $out .=
'<textarea id="'.$this->htmlname.
'" name="'.$this->htmlname.
'" style="width:0px; height: 0px; display: none;">';
398 $out .= htmlspecialchars($this->content);
399 $out .=
'</textarea>';
401 $out .=
'<script nonce="'.getNonce().
'" type="text/javascript">'.
"\n";
402 $out .=
'var aceEditor = window.ace.edit("'.$this->htmlname.
'aceeditorid");
404 aceEditor.session.setMode("ace/mode/'.$format.
'");
405 aceEditor.setReadOnly('.($this->readonly ?
'true' :
'false').
');
406 aceEditor.setOptions({
407 enableBasicAutocompletion: true, // the editor completes the statement when you hit Ctrl + Space. Need lib ext-language_tools.js
408 enableLiveAutocompletion: false, // the editor completes the statement while you are typing. Need lib ext-language_tools.js
409 //enableSnippets: true, // ???
410 showPrintMargin: false, // hides the vertical limiting strip
412 maxLines: '.(empty($this->height) ?
'34' : (round($this->height / 10))).
',
413 fontSize: "110%" // ensures that the editor fits in the environment
416 // defines the style of the editor
417 aceEditor.setTheme("ace/theme/chrome");
419 // hides line numbers (widens the area occupied by error and warning messages)
420 //aceEditor.renderer.setOption("showLineNumbers", false);
421 // ensures proper autocomplete, validation and highlighting of JavaScript code
422 //aceEditor.getSession().setMode("ace/mode/javascript_expression");'.
"\n";
425 if ($this->htmlname ==
'PAGE_CONTENT') {
427 // Add custom function in the autocompletion
428 var customCompleter = {
429 getCompletions: function(editor, session, pos, prefix, callback) {
431 { caption: \'dol_escape_all\', value: \'dol_escape_all(string)\', meta: \'custom\' },
432 { caption: \'dol_escape_js\', value: \'dol_escape_js(string)\', meta: \'custom\' },
433 { caption: \'includeContainer\', value: \'includeContainer(alias_of_container_to_include)\', meta: \'custom\' },
434 { caption: \'redirectToContainer\', value: \'redirectToContainer(alias_of_container_to_redirect_to)\', meta: \'custom\' },
435 { caption: \'getImageFromHtmlContent\', value: \'getImageFromHtmlContent(websitepage->htmlcontent)\', meta: \'custom\' },
437 callback(null, wordList.map(function(word) {
439 caption: word.caption,
446 aceEditor.completers = [customCompleter];
450 $out .=
'jQuery(document).ready(function() {';
451 $out .=
' jQuery(".buttonforacesave").click(function() {
452 console.log("We click on savefile button for component '.dol_escape_js($this->htmlname).
'");
453 var aceEditor = window.ace.edit("'.
dol_escape_js($this->htmlname).
'aceeditorid");
455 var cursorPos = aceEditor.getCursorPosition();
456 //console.log(cursorPos);
458 jQuery("#'.
dol_escape_js($this->htmlname).
'_x").val(cursorPos.column);
459 jQuery("#'.
dol_escape_js($this->htmlname).
'_y").val(cursorPos.row);
461 //console.log(aceEditor.getSession().getValue());
462 // Inject content of editor into the original HTML field.
463 jQuery("#'.
dol_escape_js($this->htmlname).
'").val(aceEditor.getSession().getValue());
464 /*if (jQuery("#'.
dol_escape_js($this->htmlname).
'").html().length > 0) return true;
468 console.log("Failed to retrieve js object ACE from its name");
473 $out .=
'</script>'.
"\n";
477 $out .=
'Error, unknown value for tool '.$this->tool.
' in DolEditor Create function.';
Class to manage a WYSIWYG editor.
Create($noprint=0, $morejs='', $disallowAnyContent=true, $titlecontent='', $option='', $moreparam='', $morecss='')
Output edit area inside the HTML stream.
__construct($htmlname, $content, $width='', $height=200, $toolbarname='Basic', $toolbarlocation='In', $toolbarstartexpanded=false, $uselocalbrowser=-1, $okforextendededitor=true, $rows=0, $cols='', $readonly=0, $poscursor=array())
Create an object to build an HTML area to edit a large string content.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_textishtml($msg, $option=0)
Return if a text is a html content.
dol_escape_all($stringtoescape)
Returns text escaped for all protocols (so only alpha chars and numbers)
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type