Dotclear

source: inc/admin/lib.dc.page.php @ 1315:220e119ae6c8

Revision 1315:220e119ae6c8, 19.7 KB checked in by Dsls, 12 years ago (diff)

Merge with default

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14define('DC_AUTH_PAGE','auth.php');
15
16class dcPage
17{
18     private static $loaded_js=array();
19
20     # Auth check
21     public static function check($permissions)
22     {
23          global $core;
24         
25          if ($core->blog && $core->auth->check($permissions,$core->blog->id))
26          {
27               return;
28          }
29         
30          if (session_id()) {
31               $core->session->destroy();
32          }
33          http::redirect(DC_AUTH_PAGE);
34     }
35     
36     # Check super admin
37     public static function checkSuper()
38     {
39          global $core;
40         
41          if (!$core->auth->isSuperAdmin())
42          {
43               if (session_id()) {
44                    $core->session->destroy();
45               }
46               http::redirect(DC_AUTH_PAGE);
47          }
48     }
49     
50     # Top of admin page
51     public static function open($title='',$head='',$popup=false)
52     {
53          global $core, $_ctx;
54         
55          $_ctx->popup = (boolean) $popup;
56          $_ctx->page_header = $head;
57          $_ctx->fillPageTitle($title);
58         
59          ob_start();
60     }
61     
62     public static function close()
63     {
64          $res = ob_get_contents();
65          ob_end_clean();
66         
67          global $core, $_ctx;
68         
69          if ($core->error->flag()) {
70               foreach($core->error->getErrors() as $e) {
71                    $_ctx->addError($e);
72               }
73          }
74          $_ctx->page_content = $res;
75          $core->tpl->display('page_layout.html.twig');
76     }
77     
78     public static function openPopup($title='',$head='')
79     {
80          self::open($title,$head,true);
81     }
82     
83     public static function closePopup()
84     {
85          self::close();
86     }
87
88     public static function message($msg,$timestamp=true,$div=false,$echo=true)
89     {
90          global $core;
91         
92          $res = '';
93          if ($msg != '') {
94               $res = ($div ? '<div class="message">' : '').'<p'.($div ? '' : ' class="message"').'>'.
95                    ($timestamp ? dt::str(__('%H:%M:%S:'),null,$core->auth->getInfo('user_tz')).' ' : '').$msg.
96                    '</p>'.($div ? '</div>' : '');
97               if ($echo) {
98                    echo $res;
99               }
100          }
101          return $res;
102     }
103     
104     public static function help($page,$index='')
105     {
106          # Deprecated but we keep this for plugins.
107     }
108     
109     public static function helpBlock()
110     {
111          $args = func_get_args();
112          if (empty($args)) {
113               return;
114          };
115         
116          global $__resources;
117          if (empty($__resources['help'])) {
118               return;
119          }
120         
121          $content = '';
122          foreach ($args as $v)
123          {
124               if (is_object($v) && isset($v->content)) {
125                    $content .= $v->content;
126                    continue;
127               }
128               
129               if (!isset($__resources['help'][$v])) {
130                    continue;
131               }
132               $f = $__resources['help'][$v];
133               if (!file_exists($f) || !is_readable($f)) {
134                    continue;
135               }
136               
137               $fc = file_get_contents($f);
138               if (preg_match('|<body[^>]*?>(.*?)</body>|ms',$fc,$matches)) {
139                    $content .= $matches[1];
140               } else {
141                    $content .= $fc;
142               }
143          }
144         
145          if (trim($content) == '') {
146               return;
147          }
148         
149          echo
150          '<div id="help"><hr /><div class="help-content clear"><h2>'.__('Help').'</h2>'.
151          $content.
152          '</div></div>';
153     }
154     
155     public static function jsLoad($src)
156     {
157          $escaped_src = html::escapeHTML($src);
158          if (!isset(self::$loaded_js[$escaped_src])) {
159               self::$loaded_js[$escaped_src]=true;
160               return '<script type="text/javascript" src="'.$escaped_src.'"></script>'."\n";
161          }
162     }
163     
164     public static function jsVar($n,$v)
165     {
166          return $n." = '".html::escapeJS($v)."';\n";
167     }
168     
169     public static function jsCommon()
170     {
171          return
172          self::jsLoad('js/jquery/jquery.js').
173          self::jsLoad('js/jquery/jquery.biscuit.js').
174          self::jsLoad('js/jquery/jquery.bgFade.js').
175          self::jsLoad('js/common.js').
176          self::jsLoad('js/prelude.js').
177         
178          '<script type="text/javascript">'."\n".
179          "//<![CDATA[\n".
180          self::jsVar('dotclear.nonce',$GLOBALS['core']->getNonce()).
181         
182          self::jsVar('dotclear.img_plus_src','images/expand.png').
183          self::jsVar('dotclear.img_plus_alt',__('uncover')).
184          self::jsVar('dotclear.img_minus_src','images/hide.png').
185          self::jsVar('dotclear.img_minus_alt',__('hide')).
186          self::jsVar('dotclear.img_menu_on','images/menu_on.png').
187          self::jsVar('dotclear.img_menu_off','images/menu_off.png').
188         
189          self::jsVar('dotclear.msg.help',
190               __('help')).
191          self::jsVar('dotclear.msg.no_selection',
192               __('no selection')).
193          self::jsVar('dotclear.msg.select_all',
194               __('select all')).
195          self::jsVar('dotclear.msg.invert_sel',
196               __('invert selection')).
197          self::jsVar('dotclear.msg.website',
198               __('Web site:')).
199          self::jsVar('dotclear.msg.email',
200               __('Email:')).
201          self::jsVar('dotclear.msg.ip_address',
202               __('IP address:')).
203          self::jsVar('dotclear.msg.error',
204               __('Error:')).
205          self::jsVar('dotclear.msg.entry_created',
206               __('Entry has been successfully created.')).
207          self::jsVar('dotclear.msg.edit_entry',
208               __('Edit entry')).
209          self::jsVar('dotclear.msg.view_entry',
210               __('view entry')).
211          self::jsVar('dotclear.msg.confirm_delete_posts',
212               __("Are you sure you want to delete selected entries (%s)?")).
213          self::jsVar('dotclear.msg.confirm_delete_post',
214               __("Are you sure you want to delete this entry?")).
215          self::jsVar('dotclear.msg.confirm_spam_delete',
216               __('Are you sure you want to delete all spams?')).
217          self::jsVar('dotclear.msg.confirm_delete_comments',
218               __('Are you sure you want to delete selected comments (%s)?')).
219          self::jsVar('dotclear.msg.confirm_delete_comment',
220               __('Are you sure you want to delete this comment?')).
221          self::jsVar('dotclear.msg.cannot_delete_users',
222               __('Users with posts cannot be deleted.')).
223          self::jsVar('dotclear.msg.confirm_delete_user',
224               __('Are you sure you want to delete selected users (%s)?')).
225          self::jsVar('dotclear.msg.confirm_delete_category',
226               __('Are you sure you want to delete category "%s"?')).
227          self::jsVar('dotclear.msg.confirm_reorder_categories',
228               __('Are you sure you want to reorder all categories?')).
229          self::jsVar('dotclear.msg.confirm_delete_media',
230               __('Are you sure you want to remove media "%s"?')).
231          self::jsVar('dotclear.msg.confirm_extract_current',
232               __('Are you sure you want to extract archive in current directory?')).
233          self::jsVar('dotclear.msg.confirm_remove_attachment',
234               __('Are you sure you want to remove attachment "%s"?')).
235          self::jsVar('dotclear.msg.confirm_delete_lang',
236               __('Are you sure you want to delete "%s" language?')).
237          self::jsVar('dotclear.msg.confirm_delete_plugin',
238               __('Are you sure you want to delete "%s" plugin?')).
239          self::jsVar('dotclear.msg.use_this_theme',
240               __('Use this theme')).
241          self::jsVar('dotclear.msg.remove_this_theme',
242               __('Remove this theme')).
243          self::jsVar('dotclear.msg.confirm_delete_theme',
244               __('Are you sure you want to delete "%s" theme?')).
245          self::jsVar('dotclear.msg.zip_file_content',
246               __('Zip file content')).
247          self::jsVar('dotclear.msg.xhtml_validator',
248               __('XHTML markup validator')).
249          self::jsVar('dotclear.msg.xhtml_valid',
250               __('XHTML content is valid.')).
251          self::jsVar('dotclear.msg.xhtml_not_valid',
252               __('There are XHTML markup errors.')).
253          self::jsVar('dotclear.msg.confirm_change_post_format',
254               __('You have unsaved changes. Switch post format will loose these changes. Proceed anyway?')).
255          self::jsVar('dotclear.msg.load_enhanced_uploader',
256               __('Loading enhanced uploader, please wait.')).
257          "\n//]]>\n".
258          "</script>\n";
259     }
260     
261     public static function jsLoadIE7()
262     {
263          return
264          '<!--[if lt IE 8]>'."\n".
265          self::jsLoad('js/ie7/IE8.js').
266          '<link rel="stylesheet" type="text/css" href="style/iesucks.css" />'."\n".
267          '<![endif]-->'."\n";
268     }
269     
270     public static function jsConfirmClose()
271     {
272          $args = func_get_args();
273          if (count($args) > 0) {
274               foreach ($args as $k => $v) {
275                    $args[$k] = "'".html::escapeJS($v)."'";
276               }
277               $args = implode(',',$args);
278          } else {
279               $args = '';
280          }
281         
282          return
283          self::jsLoad('js/confirm-close.js').
284          '<script type="text/javascript">'."\n".
285          "//<![CDATA[\n".
286          "confirmClosePage = new confirmClose(".$args."); ".
287          "confirmClose.prototype.prompt = '".html::escapeJS(__('You have unsaved changes.'))."'; ".
288          "\n//]]>\n".
289          "</script>\n";
290     }
291     
292     public static function jsPageTabs($default=null)
293     {
294          if ($default) {
295               $default = "'".html::escapeJS($default)."'";
296          }
297         
298          return
299          self::jsLoad('js/jquery/jquery.pageTabs.js').
300          '<script type="text/javascript">'."\n".
301          "//<![CDATA[\n".
302          "\$(function() {\n".
303          "    \$.pageTabs(".$default.");\n".
304          "});\n".
305          "\n//]]>\n".
306          "</script>\n";
307     }
308     
309     public static function jsModal()
310     {
311          return
312          '<link rel="stylesheet" type="text/css" href="style/modal/modal.css" />'."\n".
313          self::jsLoad('js/jquery/jquery.modal.js').
314          '<script type="text/javascript">'."\n".
315          "//<![CDATA[\n".
316          self::jsVar('$.modal.prototype.params.loader_img','style/modal/loader.gif').
317          self::jsVar('$.modal.prototype.params.close_img','style/modal/close.png').
318          "\n//]]>\n".
319          "</script>\n";
320     }
321     
322     public static function jsColorPicker()
323     {
324          return
325          '<link rel="stylesheet" type="text/css" href="style/farbtastic/farbtastic.css" />'."\n".
326          self::jsLoad('js/jquery/jquery.farbtastic.js').
327          self::jsLoad('js/color-picker.js');
328     }
329     
330     public static function jsDatePicker()
331     {
332          return
333          '<link rel="stylesheet" type="text/css" href="style/date-picker.css" />'."\n".
334          self::jsLoad('js/date-picker.js').
335          '<script type="text/javascript">'."\n".
336          "//<![CDATA[\n".
337         
338          "datePicker.prototype.months[0] = '".html::escapeJS(__('January'))."'; ".
339          "datePicker.prototype.months[1] = '".html::escapeJS(__('February'))."'; ".
340          "datePicker.prototype.months[2] = '".html::escapeJS(__('March'))."'; ".
341          "datePicker.prototype.months[3] = '".html::escapeJS(__('April'))."'; ".
342          "datePicker.prototype.months[4] = '".html::escapeJS(__('May'))."'; ".
343          "datePicker.prototype.months[5] = '".html::escapeJS(__('June'))."'; ".
344          "datePicker.prototype.months[6] = '".html::escapeJS(__('July'))."'; ".
345          "datePicker.prototype.months[7] = '".html::escapeJS(__('August'))."'; ".
346          "datePicker.prototype.months[8] = '".html::escapeJS(__('September'))."'; ".
347          "datePicker.prototype.months[9] = '".html::escapeJS(__('October'))."'; ".
348          "datePicker.prototype.months[10] = '".html::escapeJS(__('November'))."'; ".
349          "datePicker.prototype.months[11] = '".html::escapeJS(__('December'))."'; ".
350         
351          "datePicker.prototype.days[0] = '".html::escapeJS(__('Monday'))."'; ".
352          "datePicker.prototype.days[1] = '".html::escapeJS(__('Tuesday'))."'; ".
353          "datePicker.prototype.days[2] = '".html::escapeJS(__('Wednesday'))."'; ".
354          "datePicker.prototype.days[3] = '".html::escapeJS(__('Thursday'))."'; ".
355          "datePicker.prototype.days[4] = '".html::escapeJS(__('Friday'))."'; ".
356          "datePicker.prototype.days[5] = '".html::escapeJS(__('Saturday'))."'; ".
357          "datePicker.prototype.days[6] = '".html::escapeJS(__('Sunday'))."'; ".
358         
359          "datePicker.prototype.img_src = 'images/date-picker.png'; ".
360         
361          "datePicker.prototype.close_msg = '".html::escapeJS(__('close'))."'; ".
362          "datePicker.prototype.now_msg = '".html::escapeJS(__('now'))."'; ".
363         
364          "\n//]]>\n".
365          "</script>\n";
366     }
367     
368     public static function jsToolBar()
369     {
370          $res =
371          '<link rel="stylesheet" type="text/css" href="style/jsToolBar/jsToolBar.css" />'.
372          '<script type="text/javascript" src="js/jsToolBar/jsToolBar.js"></script>';
373         
374          if (isset($GLOBALS['core']->auth) && $GLOBALS['core']->auth->getOption('enable_wysiwyg')) {
375               $res .= '<script type="text/javascript" src="js/jsToolBar/jsToolBar.wysiwyg.js"></script>';
376          }
377         
378          $res .=
379          '<script type="text/javascript" src="js/jsToolBar/jsToolBar.dotclear.js"></script>'.
380          '<script type="text/javascript">'."\n".
381          "//<![CDATA[\n".
382          "jsToolBar.prototype.dialog_url = 'popup.php'; ".
383          "jsToolBar.prototype.iframe_css = '".
384               'body{'.
385                    'font: 12px "DejaVu Sans","Lucida Grande","Lucida Sans Unicode",Arial,sans-serif;'.
386                    'color : #000;'.
387                    'background: #f9f9f9;'.
388                    'margin: 0;'.
389                    'padding : 2px;'.
390                    'border: none;'.
391                    (l10n::getTextDirection($GLOBALS['_lang']) == 'rtl' ? 'direction:rtl;' : '').
392               '}'.
393               'pre, code, kbd, samp {'.
394                    'font-family:"Courier New",Courier,monospace;'.
395                    'font-size : 1.1em;'.
396               '}'.
397               'code {'.
398                    'color : #666;'.
399                    'font-weight : bold;'.
400               '}'.
401               'body > p:first-child {'.
402                    'margin-top: 0;'.
403               '}'.
404          "'; ".
405          "jsToolBar.prototype.base_url = '".html::escapeJS($GLOBALS['core']->blog->host)."'; ".
406          "jsToolBar.prototype.switcher_visual_title = '".html::escapeJS(__('visual'))."'; ".
407          "jsToolBar.prototype.switcher_source_title = '".html::escapeJS(__('source'))."'; ".
408          "jsToolBar.prototype.legend_msg = '".
409          html::escapeJS(__('You can use the following shortcuts to format your text.'))."'; ".
410          "jsToolBar.prototype.elements.blocks.options.none = '".html::escapeJS(__('-- none --'))."'; ".
411          "jsToolBar.prototype.elements.blocks.options.nonebis = '".html::escapeJS(__('-- block format --'))."'; ".
412          "jsToolBar.prototype.elements.blocks.options.p = '".html::escapeJS(__('Paragraph'))."'; ".
413          "jsToolBar.prototype.elements.blocks.options.h1 = '".html::escapeJS(__('Level 1 header'))."'; ".
414          "jsToolBar.prototype.elements.blocks.options.h2 = '".html::escapeJS(__('Level 2 header'))."'; ".
415          "jsToolBar.prototype.elements.blocks.options.h3 = '".html::escapeJS(__('Level 3 header'))."'; ".
416          "jsToolBar.prototype.elements.blocks.options.h4 = '".html::escapeJS(__('Level 4 header'))."'; ".
417          "jsToolBar.prototype.elements.blocks.options.h5 = '".html::escapeJS(__('Level 5 header'))."'; ".
418          "jsToolBar.prototype.elements.blocks.options.h6 = '".html::escapeJS(__('Level 6 header'))."'; ".
419          "jsToolBar.prototype.elements.strong.title = '".html::escapeJS(__('Strong emphasis'))."'; ".
420          "jsToolBar.prototype.elements.em.title = '".html::escapeJS(__('Emphasis'))."'; ".
421          "jsToolBar.prototype.elements.ins.title = '".html::escapeJS(__('Inserted'))."'; ".
422          "jsToolBar.prototype.elements.del.title = '".html::escapeJS(__('Deleted'))."'; ".
423          "jsToolBar.prototype.elements.quote.title = '".html::escapeJS(__('Inline quote'))."'; ".
424          "jsToolBar.prototype.elements.code.title = '".html::escapeJS(__('Code'))."'; ".
425          "jsToolBar.prototype.elements.br.title = '".html::escapeJS(__('Line break'))."'; ".
426          "jsToolBar.prototype.elements.blockquote.title = '".html::escapeJS(__('Blockquote'))."'; ".
427          "jsToolBar.prototype.elements.pre.title = '".html::escapeJS(__('Preformated text'))."'; ".
428          "jsToolBar.prototype.elements.ul.title = '".html::escapeJS(__('Unordered list'))."'; ".
429          "jsToolBar.prototype.elements.ol.title = '".html::escapeJS(__('Ordered list'))."'; ".
430         
431          "jsToolBar.prototype.elements.link.title = '".html::escapeJS(__('Link'))."'; ".
432          "jsToolBar.prototype.elements.link.href_prompt = '".html::escapeJS(__('URL?'))."'; ".
433          "jsToolBar.prototype.elements.link.hreflang_prompt = '".html::escapeJS(__('Language?'))."'; ".
434         
435          "jsToolBar.prototype.elements.img.title = '".html::escapeJS(__('External image'))."'; ".
436          "jsToolBar.prototype.elements.img.src_prompt = '".html::escapeJS(__('URL?'))."'; ".
437         
438          "jsToolBar.prototype.elements.img_select.title = '".html::escapeJS(__('Media chooser'))."'; ".
439          "jsToolBar.prototype.elements.post_link.title = '".html::escapeJS(__('Link to an entry'))."'; ";
440         
441          if (!$GLOBALS['core']->auth->check('media,media_admin',$GLOBALS['core']->blog->id)) {
442               $res .= "jsToolBar.prototype.elements.img_select.disabled = true;\n";
443          }
444         
445          $res .=
446          "\n//]]>\n".
447          "</script>\n";
448         
449          return $res;
450     }
451     
452     public static function jsUpload($params=array(),$base_url=null)
453     {
454          if (!$base_url) {
455               $base_url = path::clean(dirname(preg_replace('/(\?.*$)?/','',$_SERVER['REQUEST_URI']))).'/';
456          }
457         
458          $params = array_merge($params,array(
459               'sess_id='.session_id(),
460               'sess_uid='.$_SESSION['sess_browser_uid'],
461               'xd_check='.$GLOBALS['core']->getNonce()
462          ));
463         
464          return
465          '<link rel="stylesheet" type="text/css" href="style/jsUpload/style.css" />'."\n".
466
467    '<script id="template-upload" type="text/x-tmpl">
468{% for (var i=0, file; file=o.files[i]; i++) { %}
469    <tr class="template-upload fade">
470        <td>
471            <span class="preview"></span>
472        </td>
473        <td>
474            <p class="name">{%=file.name%}</p>
475            {% if (file.error) { %}
476                <div><span class="label label-error">'.__('Error:').'</span> {%=file.error%}</div>
477            {% } %}
478        </td>
479        <td>
480            <p class="size">{%=o.formatFileSize(file.size)%}</p>
481            {% if (!o.files.error) { %}
482                <div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="bar" style="width:0%;"></div></div>
483            {% } %}
484        </td>
485        <td>
486            {% if (!o.files.error && !i && !o.options.autoUpload) { %}
487                <input type="submit" class="button start" value="'.__('Send').'"/>
488            {% } %}
489        </td>
490    </tr>
491{% } %}
492</script>
493<!-- The template to display files available for download -->
494<script id="template-download" type="text/x-tmpl">
495{% for (var i=0, file; file=o.files[i]; i++) { %}
496    <tr class="template-download fade">
497        <td>
498            <span class="preview">
499                {% if (file.thumbnail_url) { %}
500                    <a href="{%=file.url%}" title="{%=file.name%}" data-gallery="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
501                {% } %}
502            </span>
503        </td>
504        <td>
505            <p class="name">{%=file.name%}</p>
506            {% if (file.error) { %}
507                <div><span class="label label-important">'.__('Error:').'</span> {%=file.error%}</div>
508            {% } %}
509        </td>
510        <td>
511            <span class="size">{%=o.formatFileSize(file.size)%}</span>
512        </td>
513        <td>
514            {% if (file.error) { %}
515            <span class="upload-status error"></span>
516            {% } else { %}
517            <span class="upload-status ok"></span>
518            {% } %}
519        </td>
520    </tr>
521{% } %}
522</script>'.
523
524          self::jsLoad('js/jsUpload/vendor/jquery.ui.widget.js').
525    self::jsLoad('js/jsUpload/tmpl.js').
526    self::jsLoad('js/jsUpload/load-image.js').
527          self::jsLoad('js/jsUpload/jquery.iframe-transport.js').
528          self::jsLoad('js/jsUpload/jquery.fileupload.js').
529          self::jsLoad('js/jsUpload/jquery.fileupload-process.js').
530          self::jsLoad('js/jsUpload/jquery.fileupload-resize.js').
531          self::jsLoad('js/jsUpload/jquery.fileupload-ui.js').
532         
533          '<script type="text/javascript">'."\n".
534          "//<![CDATA[\n".
535          "dotclear.jsUpload = {};\n".
536          "dotclear.jsUpload.msg = {};\n".
537          self::jsVar('dotclear.jsUpload.msg.limit_exceeded',__('Limit exceeded.')).
538          self::jsVar('dotclear.jsUpload.msg.size_limit_exceeded',__('File size exceeds allowed limit.')).
539          self::jsVar('dotclear.jsUpload.msg.canceled',__('Canceled.')).
540          self::jsVar('dotclear.jsUpload.msg.http_error',__('HTTP Error:')).
541          self::jsVar('dotclear.jsUpload.msg.error',__('Error:')).
542          self::jsVar('dotclear.jsUpload.msg.choose_file',__('Choose file')).
543          self::jsVar('dotclear.jsUpload.msg.choose_files',__('Choose files')).
544          self::jsVar('dotclear.jsUpload.msg.cancel',__('Cancel')).
545          self::jsVar('dotclear.jsUpload.msg.clean',__('Clean')).
546          self::jsVar('dotclear.jsUpload.msg.upload',__('Upload')).
547          self::jsVar('dotclear.jsUpload.msg.no_file_in_queue',__('No file in queue.')).
548          self::jsVar('dotclear.jsUpload.msg.file_in_queue',__('1 file in queue.')).
549          self::jsVar('dotclear.jsUpload.msg.files_in_queue',__('%d files in queue.')).
550          self::jsVar('dotclear.jsUpload.msg.queue_error',__('Queue error:')).
551          self::jsVar('dotclear.jsUpload.base_url',$base_url).
552          "\n//]]>\n".
553          "</script>\n";
554     }
555     
556     public static function jsToolMan()
557     {
558          return
559          '<script type="text/javascript" src="js/tool-man/core.js"></script>'.
560          '<script type="text/javascript" src="js/tool-man/events.js"></script>'.
561          '<script type="text/javascript" src="js/tool-man/css.js"></script>'.
562          '<script type="text/javascript" src="js/tool-man/coordinates.js"></script>'.
563          '<script type="text/javascript" src="js/tool-man/drag.js"></script>'.
564          '<script type="text/javascript" src="js/tool-man/dragsort.js"></script>'.
565          '<script type="text/javascript" src="js/dragsort-tablerows.js"></script>';
566     }
567     
568     public static function jsMetaEditor()
569     {
570          return
571          '<script type="text/javascript" src="js/meta-editor.js"></script>';
572     }
573}
574?>
Note: See TracBrowser for help on using the repository browser.

Sites map