dolibarr  13.0.2
doleditor.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2006-2008 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  * or see https://www.gnu.org/
17  */
18 
29 class DolEditor
30 {
31  public $tool; // Store the selected tool
32 
33  // If using fckeditor
34  public $editor;
35 
36  // If not using fckeditor
37  public $content;
38  public $htmlname;
39  public $toolbarname;
40  public $toolbarstartexpanded;
41  public $rows;
42  public $cols;
43  public $height;
44  public $width;
45  public $readonly;
46 
47 
67  public function __construct($htmlname, $content, $width = '', $height = 200, $toolbarname = 'Basic', $toolbarlocation = 'In', $toolbarstartexpanded = false, $uselocalbrowser = true, $okforextendededitor = true, $rows = 0, $cols = 0, $readonly = 0)
68  {
69  global $conf, $langs;
70 
71  dol_syslog(get_class($this)."::DolEditor htmlname=".$htmlname." width=".$width." height=".$height." toolbarname=".$toolbarname);
72 
73  if (!$rows) $rows = round($height / 20);
74  if (!$cols) $cols = ($width ?round($width / 6) : 80);
75  $shorttoolbarname = preg_replace('/_encoded$/', '', $toolbarname);
76 
77  // Name of extended editor to use (FCKEDITOR_EDITORNAME can be 'ckeditor' or 'fckeditor')
78  $defaulteditor = 'ckeditor';
79  $this->tool = empty($conf->global->FCKEDITOR_EDITORNAME) ? $defaulteditor : $conf->global->FCKEDITOR_EDITORNAME;
80  $this->uselocalbrowser = $uselocalbrowser;
81  $this->readonly = $readonly;
82 
83  // Check if extended editor is ok. If not we force textarea
84  if ((empty($conf->fckeditor->enabled) && $okforextendededitor != 'ace') || empty($okforextendededitor)) $this->tool = 'textarea';
85  if ($okforextendededitor === 'ace') $this->tool = 'ace';
86  //if ($conf->dol_use_jmobile) $this->tool = 'textarea'; // ckeditor and ace seems ok with mobile
87 
88  // Define some properties
89  if (in_array($this->tool, array('textarea', 'ckeditor', 'ace')))
90  {
91  if ($this->tool == 'ckeditor' && !dol_textishtml($content)) { // We force content to be into HTML if we are using an advanced editor if content is not HTML.
92  $this->content = dol_nl2br($content);
93  }
94  else {
95  $this->content = $content;
96  }
97  $this->htmlname = $htmlname;
98  $this->toolbarname = $shorttoolbarname;
99  $this->toolbarstartexpanded = $toolbarstartexpanded;
100  $this->rows = max(ROWS_3, $rows);
101  $this->cols = (preg_match('/%/', $cols) ? $cols : max(40, $cols)); // If $cols is a percent, we keep it, otherwise, we take max
102  $this->height = $height;
103  $this->width = $width;
104  }
105  }
106 
107  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
119  public function Create($noprint = 0, $morejs = '', $disallowAnyContent = true, $titlecontent = '', $option = '')
120  {
121  // phpcs:enable
122  global $conf, $langs;
123 
124  $fullpage = false;
125  if (isset($conf->global->FCKEDITOR_ALLOW_ANY_CONTENT))
126  {
127  $disallowAnyContent = empty($conf->global->FCKEDITOR_ALLOW_ANY_CONTENT); // Only predefined list of html tags are allowed or all
128  }
129 
130  $found = 0;
131  $out = '';
132 
133  if (in_array($this->tool, array('textarea', 'ckeditor')))
134  {
135  $found = 1;
136  //$out.= '<textarea id="'.$this->htmlname.'" name="'.$this->htmlname.'" '.($this->readonly?' disabled':'').' rows="'.$this->rows.'"'.(preg_match('/%/',$this->cols)?' style="margin-top: 5px; width: '.$this->cols.'"':' cols="'.$this->cols.'"').' class="flat">';
137  // TODO We do not put the 'disabled' tag because on a read form, it change style with grey.
138  //print $this->content;
139  $out .= '<textarea id="'.$this->htmlname.'" name="'.$this->htmlname.'" rows="'.$this->rows.'"'.(preg_match('/%/', $this->cols) ? ' style="margin-top: 5px; width: '.$this->cols.'"' : ' cols="'.$this->cols.'"').' class="flat">';
140  $out .= htmlspecialchars($this->content);
141  $out .= '</textarea>';
142 
143  if ($this->tool == 'ckeditor' && !empty($conf->use_javascript_ajax) && !empty($conf->fckeditor->enabled))
144  {
145  if (!defined('REQUIRE_CKEDITOR')) define('REQUIRE_CKEDITOR', '1');
146 
147  if (!empty($conf->global->FCKEDITOR_SKIN)) {
148  $skin = $conf->global->FCKEDITOR_SKIN;
149  } else {
150  $skin = 'moono-lisa'; // default with ckeditor 4.6 : moono-lisa
151  }
152 
153  $htmlencode_force = preg_match('/_encoded$/', $this->toolbarname) ? 'true' : 'false';
154 
155  $out .= '<!-- Output ckeditor $disallowAnyContent='.$disallowAnyContent.' toolbarname='.$this->toolbarname.' -->'."\n";
156  $out .= '<script type="text/javascript">
157  $(document).ready(function () {
158  /* console.log("Run ckeditor"); */
159  /* if (CKEDITOR.loadFullCore) CKEDITOR.loadFullCore(); */
160  /* should be editor=CKEDITOR.replace but what if serveral editors ? */
161  CKEDITOR.replace(\''.$this->htmlname.'\',
162  {
163  /* property:xxx is same than CKEDITOR.config.property = xxx */
164  customConfig : ckeditorConfig,
165  readOnly : '.($this->readonly ? 'true' : 'false').',
166  htmlEncodeOutput :'.$htmlencode_force.',
167  allowedContent :'.($disallowAnyContent ? 'false' : 'true').',
168  extraAllowedContent : \'\',
169  fullPage : '.($fullpage ? 'true' : 'false').',
170  toolbar: \''.$this->toolbarname.'\',
171  toolbarStartupExpanded: '.($this->toolbarstartexpanded ? 'true' : 'false').',
172  width: '.($this->width ? '\''.$this->width.'\'' : '\'\'').',
173  height: '.$this->height.',
174  skin: \''.$skin.'\',
175  language: \''.$langs->defaultlang.'\',
176  textDirection: \''.$langs->trans("DIRECTION").'\',
177  on :
178  {
179  instanceReady : function( ev )
180  {
181  // Output paragraphs as <p>Text</p>.
182  this.dataProcessor.writer.setRules( \'p\',
183  {
184  indent : false,
185  breakBeforeOpen : true,
186  breakAfterOpen : false,
187  breakBeforeClose : false,
188  breakAfterClose : true
189  });
190  }
191  },
192  disableNativeSpellChecker: '.(empty($conf->global->CKEDITOR_NATIVE_SPELLCHECKER) ? 'true' : 'false');
193 
194  if ($this->uselocalbrowser)
195  {
196  $out .= ','."\n";
197  // To use filemanager with old fckeditor (GPL)
198  $out .= ' filebrowserBrowseUrl : ckeditorFilebrowserBrowseUrl,';
199  $out .= ' filebrowserImageBrowseUrl : ckeditorFilebrowserImageBrowseUrl,';
200  //$out.= ' filebrowserUploadUrl : \''.DOL_URL_ROOT.'/includes/fckeditor/editor/filemanagerdol/connectors/php/upload.php?Type=File\',';
201  //$out.= ' filebrowserImageUploadUrl : \''.DOL_URL_ROOT.'/includes/fckeditor/editor/filemanagerdol/connectors/php/upload.php?Type=Image\',';
202  $out .= "\n";
203  // To use filemanager with ckfinder (Non free) and ckfinder directory is inside htdocs/includes
204  /* $out.= ' filebrowserBrowseUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/ckfinder.html\',
205  filebrowserImageBrowseUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/ckfinder.html?Type=Images\',
206  filebrowserFlashBrowseUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/ckfinder.html?Type=Flash\',
207  filebrowserUploadUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files\',
208  filebrowserImageUploadUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images\',
209  filebrowserFlashUploadUrl : \''.DOL_URL_ROOT.'/includes/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash\','."\n";
210  */
211  $out .= ' filebrowserWindowWidth : \'900\',
212  filebrowserWindowHeight : \'500\',
213  filebrowserImageWindowWidth : \'900\',
214  filebrowserImageWindowHeight : \'500\'';
215  }
216  $out .= ' })'.$morejs;
217  $out .= '});'."\n";
218  $out .= '</script>'."\n";
219  }
220  }
221 
222  // Output editor ACE
223  // Warning: ace.js and ext-statusbar.js must be loaded by the parent page.
224  if (preg_match('/^ace/', $this->tool))
225  {
226  $found = 1;
227  $format = $option;
228 
229  $out .= "\n".'<!-- Output Ace editor -->'."\n";
230 
231  if ($titlecontent)
232  {
233  $out .= '<div class="aceeditorstatusbar" id="statusBar'.$this->htmlname.'">'.$titlecontent;
234  $out .= ' &nbsp; - &nbsp; <a id="morelines" href="#" class="right morelines'.$this->htmlname.' reposition">'.dol_escape_htmltag($langs->trans("ShowMoreLines")).'</a> &nbsp; &nbsp; ';
235  $out .= '</div>';
236  $out .= '<script type="text/javascript" language="javascript">'."\n";
237  $out .= 'jQuery(document).ready(function() {'."\n";
238  $out .= ' var aceEditor = window.ace.edit("'.$this->htmlname.'aceeditorid");
239  var StatusBar = window.ace.require("ace/ext/statusbar").StatusBar; // Init status bar. Need lib ext-statusbar
240  var statusBar = new StatusBar(aceEditor, document.getElementById("statusBar'.$this->htmlname.'")); // Init status bar. Need lib ext-statusbar
241  var oldNbOfLines = 0
242  jQuery(".morelines'.$this->htmlname.'").click(function() {
243  var aceEditorClicked = window.ace.edit("'.$this->htmlname.'aceeditorid");
244  currentline = aceEditorClicked.getOption("maxLines");
245  if (oldNbOfLines == 0)
246  {
247  oldNbOfLines = currentline;
248  }
249  console.log("We click on more lines, oldNbOfLines is "+oldNbOfLines+", we have currently "+currentline);
250  if (currentline < 500)
251  {
252  aceEditorClicked.setOptions({ maxLines: 500 });
253  }
254  else
255  {
256  aceEditorClicked.setOptions({ maxLines: oldNbOfLines });
257  }
258  });
259  })';
260  $out .= '</script>'."\n";
261  }
262 
263  $out .= '<pre id="'.$this->htmlname.'aceeditorid" style="'.($this->width ? 'width: '.$this->width.'px; ' : '');
264  $out .= ($this->height ? ' height: '.$this->height.'px; ' : '');
265  //$out.=" min-height: 100px;";
266  $out .= '">';
267  $out .= htmlspecialchars($this->content);
268  $out .= '</pre>';
269  $out .= '<textarea id="'.$this->htmlname.'" name="'.$this->htmlname.'" style="width:0px; height: 0px; display: none;">';
270  $out .= htmlspecialchars($this->content);
271  $out .= '</textarea>';
272 
273  $out .= '<script type="text/javascript" language="javascript">'."\n";
274  $out .= 'var aceEditor = window.ace.edit("'.$this->htmlname.'aceeditorid");
275 
276  aceEditor.session.setMode("ace/mode/'.$format.'");
277  aceEditor.setOptions({
278  enableBasicAutocompletion: true, // the editor completes the statement when you hit Ctrl + Space. Need lib ext-language_tools.js
279  enableLiveAutocompletion: false, // the editor completes the statement while you are typing. Need lib ext-language_tools.js
280  showPrintMargin: false, // hides the vertical limiting strip
281  minLines: 10,
282  maxLines: '.(empty($this->height) ? '34' : (round($this->height / 10))).',
283  fontSize: "110%" // ensures that the editor fits in the environment
284  });
285 
286  // defines the style of the editor
287  aceEditor.setTheme("ace/theme/chrome");
288  // hides line numbers (widens the area occupied by error and warning messages)
289  //aceEditor.renderer.setOption("showLineNumbers", false);
290  // ensures proper autocomplete, validation and highlighting of JavaScript code
291  //aceEditor.getSession().setMode("ace/mode/javascript_expression");
292  '."\n";
293 
294  $out .= 'jQuery(document).ready(function() {
295  jQuery(".buttonforacesave").click(function() {
296  console.log("We click on savefile button for component '.$this->htmlname.'");
297  var aceEditor = window.ace.edit("'.$this->htmlname.'aceeditorid")
298  console.log(aceEditor.getSession().getValue());
299  jQuery("#'.$this->htmlname.'").val(aceEditor.getSession().getValue());
300  /*if (jQuery("#'.$this->htmlname.'").html().length > 0) return true;
301  else return false;*/
302  });
303  })';
304  $out .= '</script>'."\n";
305  }
306 
307  if (empty($found))
308  {
309  $out .= 'Error, unknown value for tool '.$this->tool.' in DolEditor Create function.';
310  }
311 
312  if ($noprint) return $out;
313  else print $out;
314  }
315 }
__construct($htmlname, $content, $width= '', $height=200, $toolbarname= 'Basic', $toolbarlocation= 'In', $toolbarstartexpanded=false, $uselocalbrowser=true, $okforextendededitor=true, $rows=0, $cols=0, $readonly=0)
Create an object to build an HTML area to edit a large string content.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
print
Draft customers invoices.
Definition: index.php:89
Create($noprint=0, $morejs= '', $disallowAnyContent=true, $titlecontent= '', $option= '')
Output edit area inside the HTML stream.
Class to manage a WYSIWYG editor.
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
dol_textishtml($msg, $option=0)
Return if a text is a html content.