Bug 11584: Add wysiwyg editor to system preferences dealing with HTML
authorDavid Cook <dcook@prosentient.com.au>
Tue, 23 Jun 2015 07:36:58 +0000 (17:36 +1000)
committerTomas Cohen Arazi <tomascohen@theke.io>
Fri, 28 Aug 2015 13:28:50 +0000 (10:28 -0300)
This patch adds the ability to use a WYSIWYG editor for system preferences.

The key files that I touch are:

1) admin/systempreferences.pl
2) koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt
3) koha-tmpl/intranet-tmpl/prog/en/modules/admin/systempreferences.tt

I also add:

4) koha-tmpl/intranet-tmpl/prog/en/includes/wysiwyg-systempreferences.inc

and

5) koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage

This plugin is part of the TinyMCE distribution. It used to be in Koha, but
then someone removed it. It's useful for preferences like "opacheader" though.

*If you're using anything except IE, this should work super well. If
you're using IE, it'll probably only work for keyboard input and dragging
text within the editor box but not from outside of it. IE has worse
security, so you can probably paste using the context menu paste.

*While I think a WYSIWYG editor can be useful, there might be times
where the content is displayed differently than it is in the editor
because of higher level CSS and Javascript.

Signed-off-by: Martin Persson <xarragon@gmail.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

admin/systempreferences.pl
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/css/advimage.css [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin_src.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/image.htm [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/img/sample.gif [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/js/image.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/langs/en_dlg.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/includes/wysiwyg-systempreferences.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt
koha-tmpl/intranet-tmpl/prog/en/modules/admin/systempreferences.tt

index 1c3dd41..01c0300 100755 (executable)
@@ -130,6 +130,11 @@ sub GetPrefParams {
         $data->{options} =~ /(.*)\|(.*)/;
         $params->{'cols'} = $1;
         $params->{'rows'} = $2;
+    } elsif ( $data->{'type'} eq 'Htmlarea' ) {
+        $params->{'type_htmlarea'} = 1;
+        $data->{options} =~ /(.*)\|(.*)/;
+        $params->{'cols'} = $1;
+        $params->{'rows'} = $2;
     } elsif ( $data->{'type'} eq 'Themes' ) {
         $params->{'type_choice'} = 1;
         my $type = '';
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/css/advimage.css b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/css/advimage.css
new file mode 100644 (file)
index 0000000..228530f
--- /dev/null
@@ -0,0 +1,13 @@
+#src_list, #over_list, #out_list {width:280px;}
+.mceActionPanel {margin-top:7px;}
+.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;}
+.checkbox {border:0;}
+.panel_wrapper div.current {height:305px;}
+#prev {margin:0; border:1px solid #000; width:428px; height:150px; overflow:auto;}
+#align, #classlist {width:150px;}
+#width, #height {vertical-align:middle; width:50px; text-align:center;}
+#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;}
+#class_list {width:180px;}
+input {width: 280px;}
+#constrain, #onmousemovecheck {width:auto;}
+#id, #dir, #lang, #usemap, #longdesc {width:200px;}
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin.js b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin.js
new file mode 100644 (file)
index 0000000..d613a61
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create("tinymce.plugins.AdvancedImagePlugin",{init:function(a,b){a.addCommand("mceAdvImage",function(){if(a.dom.getAttrib(a.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}a.windowManager.open({file:b+"/image.htm",width:480+parseInt(a.getLang("advimage.delta_width",0)),height:385+parseInt(a.getLang("advimage.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("image",{title:"advimage.image_desc",cmd:"mceAdvImage"})},getInfo:function(){return{longname:"Advanced image",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advimage",tinymce.plugins.AdvancedImagePlugin)})();
\ No newline at end of file
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin_src.js b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..76df89a
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * editor_plugin_src.js
+ *
+ * Copyright 2009, Moxiecode Systems AB
+ * Released under LGPL License.
+ *
+ * License: http://tinymce.moxiecode.com/license
+ * Contributing: http://tinymce.moxiecode.com/contributing
+ */
+
+(function() {
+       tinymce.create('tinymce.plugins.AdvancedImagePlugin', {
+               init : function(ed, url) {
+                       // Register commands
+                       ed.addCommand('mceAdvImage', function() {
+                               // Internal image object like a flash placeholder
+                               if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1)
+                                       return;
+
+                               ed.windowManager.open({
+                                       file : url + '/image.htm',
+                                       width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)),
+                                       height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)),
+                                       inline : 1
+                               }, {
+                                       plugin_url : url
+                               });
+                       });
+
+                       // Register buttons
+                       ed.addButton('image', {
+                               title : 'advimage.image_desc',
+                               cmd : 'mceAdvImage'
+                       });
+               },
+
+               getInfo : function() {
+                       return {
+                               longname : 'Advanced image',
+                               author : 'Moxiecode Systems AB',
+                               authorurl : 'http://tinymce.moxiecode.com',
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion
+                       };
+               }
+       });
+
+       // Register plugin
+       tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin);
+})();
\ No newline at end of file
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/image.htm b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/image.htm
new file mode 100644 (file)
index 0000000..8eb59d1
--- /dev/null
@@ -0,0 +1,235 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+       <title>{#advimage_dlg.dialog_title}</title>
+       <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+       <script type="text/javascript" src="../../utils/mctabs.js"></script>
+       <script type="text/javascript" src="../../utils/form_utils.js"></script>
+       <script type="text/javascript" src="../../utils/validate.js"></script>
+       <script type="text/javascript" src="../../utils/editable_selects.js"></script>
+       <script type="text/javascript" src="js/image.js"></script>
+       <link href="css/advimage.css" rel="stylesheet" type="text/css" />
+</head>
+<body id="advimage" style="display: none" role="application" aria-labelledby="app_title">
+       <span id="app_title" style="display:none">{#advimage_dlg.dialog_title}</span>
+       <form onsubmit="ImageDialog.insert();return false;" action="#">
+               <div class="tabs">
+                       <ul>
+                               <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advimage_dlg.tab_general}</a></span></li>
+                               <li id="appearance_tab" aria-controls="appearance_panel"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#advimage_dlg.tab_appearance}</a></span></li>
+                               <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advimage_dlg.tab_advanced}</a></span></li>
+                       </ul>
+               </div>
+
+               <div class="panel_wrapper">
+                       <div id="general_panel" class="panel current">
+                               <fieldset>
+                                               <legend>{#advimage_dlg.general}</legend>
+
+                                               <table role="presentation" class="properties">
+                                                       <tr>
+                                                               <td class="column1"><label id="srclabel" for="src">{#advimage_dlg.src}</label></td>
+                                                               <td colspan="2"><table role="presentation" border="0" cellspacing="0" cellpadding="0">
+                                                                       <tr>
+                                                                               <td><input name="src" type="text" id="src" value="" class="mceFocus" onchange="ImageDialog.showPreviewImage(this.value);" aria-required="true" /></td>
+                                                                               <td id="srcbrowsercontainer">&nbsp;</td>
+                                                                       </tr>
+                                                               </table></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><label for="src_list">{#advimage_dlg.image_list}</label></td>
+                                                               <td><select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"><option value=""></option></select></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td class="column1"><label id="altlabel" for="alt">{#advimage_dlg.alt}</label></td>
+                                                               <td colspan="2"><input id="alt" name="alt" type="text" value="" /></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td class="column1"><label id="titlelabel" for="title">{#advimage_dlg.title}</label></td>
+                                                               <td colspan="2"><input id="title" name="title" type="text" value="" /></td>
+                                                       </tr>
+                                               </table>
+                               </fieldset>
+
+                               <fieldset>
+                                       <legend>{#advimage_dlg.preview}</legend>
+                                       <div id="prev"></div>
+                               </fieldset>
+                       </div>
+
+                       <div id="appearance_panel" class="panel">
+                               <fieldset>
+                                       <legend>{#advimage_dlg.tab_appearance}</legend>
+
+                                       <table role="presentation" border="0" cellpadding="4" cellspacing="0">
+                                               <tr>
+                                                       <td class="column1"><label id="alignlabel" for="align">{#advimage_dlg.align}</label></td>
+                                                       <td><select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();">
+                                                                       <option value="">{#not_set}</option>
+                                                                       <option value="baseline">{#advimage_dlg.align_baseline}</option>
+                                                                       <option value="top">{#advimage_dlg.align_top}</option>
+                                                                       <option value="middle">{#advimage_dlg.align_middle}</option>
+                                                                       <option value="bottom">{#advimage_dlg.align_bottom}</option>
+                                                                       <option value="text-top">{#advimage_dlg.align_texttop}</option>
+                                                                       <option value="text-bottom">{#advimage_dlg.align_textbottom}</option>
+                                                                       <option value="left">{#advimage_dlg.align_left}</option>
+                                                                       <option value="right">{#advimage_dlg.align_right}</option>
+                                                               </select>
+                                                       </td>
+                                                       <td rowspan="6" valign="top">
+                                                               <div class="alignPreview">
+                                                                       <img id="alignSampleImg" src="img/sample.gif" alt="{#advimage_dlg.example_img}" />
+                                                                       Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam
+                                                                       nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum
+                                                                       edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam
+                                                                       erat volutpat.
+                                                               </div>
+                                                       </td>
+                                               </tr>
+
+                                               <tr role="group" aria-labelledby="widthlabel">
+                                                       <td class="column1"><label id="widthlabel" for="width">{#advimage_dlg.dimensions}</label></td>
+                                                       <td class="nowrap">
+                                                               <span style="display:none" id="width_voiceLabel">{#advimage_dlg.width}</span>
+                                                               <input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" aria-labelledby="width_voiceLabel" /> x
+                                                               <span style="display:none" id="height_voiceLabel">{#advimage_dlg.height}</span>
+                                                               <input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" aria-labelledby="height_voiceLabel" /> px
+                                                       </td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td>&nbsp;</td>
+                                                       <td><table role="presentation" border="0" cellpadding="0" cellspacing="0">
+                                                                       <tr>
+                                                                               <td><input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>
+                                                                               <td><label id="constrainlabel" for="constrain">{#advimage_dlg.constrain_proportions}</label></td>
+                                                                       </tr>
+                                                               </table></td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="vspacelabel" for="vspace">{#advimage_dlg.vspace}</label></td>
+                                                       <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" />
+                                                       </td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="hspacelabel" for="hspace">{#advimage_dlg.hspace}</label></td>
+                                                       <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" /></td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="borderlabel" for="border">{#advimage_dlg.border}</label></td>
+                                                       <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" /></td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td><label for="class_list">{#class_name}</label></td>
+                                                       <td colspan="2"><select id="class_list" name="class_list" class="mceEditableSelect"><option value=""></option></select></td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="stylelabel" for="style">{#advimage_dlg.style}</label></td>
+                                                       <td colspan="2"><input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" /></td>
+                                               </tr>
+
+                                               <!-- <tr>
+                                                       <td class="column1"><label id="classeslabel" for="classes">{#advimage_dlg.classes}</label></td>
+                                                       <td colspan="2"><input id="classes" name="classes" type="text" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td>
+                                               </tr> -->
+                                       </table>
+                               </fieldset>
+                       </div>
+
+                       <div id="advanced_panel" class="panel">
+                               <fieldset>
+                                       <legend>{#advimage_dlg.swap_image}</legend>
+
+                                       <input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" aria-controls="onmouseoversrc onmouseoutsrc" />
+                                       <label id="onmousemovechecklabel" for="onmousemovecheck">{#advimage_dlg.alt_image}</label>
+
+                                       <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%">
+                                                       <tr>
+                                                               <td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{#advimage_dlg.mouseover}</label></td>
+                                                               <td><table role="presentation" border="0" cellspacing="0" cellpadding="0">
+                                                                       <tr>
+                                                                               <td><input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" /></td>
+                                                                               <td id="onmouseoversrccontainer">&nbsp;</td>
+                                                                       </tr>
+                                                               </table></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><label for="over_list">{#advimage_dlg.image_list}</label></td>
+                                                               <td><select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{#advimage_dlg.mouseout}</label></td>
+                                                               <td class="column2"><table role="presentation" border="0" cellspacing="0" cellpadding="0">
+                                                                       <tr>
+                                                                               <td><input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" /></td>
+                                                                               <td id="onmouseoutsrccontainer">&nbsp;</td>
+                                                                       </tr>
+                                                               </table></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><label for="out_list">{#advimage_dlg.image_list}</label></td>
+                                                               <td><select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td>
+                                                       </tr>
+                                       </table>
+                               </fieldset>
+
+                               <fieldset>
+                                       <legend>{#advimage_dlg.misc}</legend>
+
+                                       <table role="presentation" border="0" cellpadding="4" cellspacing="0">
+                                               <tr>
+                                                       <td class="column1"><label id="idlabel" for="id">{#advimage_dlg.id}</label></td>
+                                                       <td><input id="id" name="id" type="text" value="" /></td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="dirlabel" for="dir">{#advimage_dlg.langdir}</label></td>
+                                                       <td>
+                                                               <select id="dir" name="dir" onchange="ImageDialog.changeAppearance();">
+                                                                               <option value="">{#not_set}</option>
+                                                                               <option value="ltr">{#advimage_dlg.ltr}</option>
+                                                                               <option value="rtl">{#advimage_dlg.rtl}</option>
+                                                               </select>
+                                                       </td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="langlabel" for="lang">{#advimage_dlg.langcode}</label></td>
+                                                       <td>
+                                                               <input id="lang" name="lang" type="text" value="" />
+                                                       </td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="usemaplabel" for="usemap">{#advimage_dlg.map}</label></td>
+                                                       <td>
+                                                               <input id="usemap" name="usemap" type="text" value="" />
+                                                       </td>
+                                               </tr>
+
+                                               <tr>
+                                                       <td class="column1"><label id="longdesclabel" for="longdesc">{#advimage_dlg.long_desc}</label></td>
+                                                       <td><table role="presentation" border="0" cellspacing="0" cellpadding="0">
+                                                                       <tr>
+                                                                               <td><input id="longdesc" name="longdesc" type="text" value="" /></td>
+                                                                               <td id="longdesccontainer">&nbsp;</td>
+                                                                       </tr>
+                                                       </table></td>
+                                               </tr>
+                                       </table>
+                               </fieldset>
+                       </div>
+               </div>
+
+               <div class="mceActionPanel">
+                       <input type="submit" id="insert" name="insert" value="{#insert}" />
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
+               </div>
+       </form>
+</body>
+</html>
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/img/sample.gif b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/img/sample.gif
new file mode 100644 (file)
index 0000000..53bf689
Binary files /dev/null and b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/img/sample.gif differ
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/js/image.js b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/js/image.js
new file mode 100644 (file)
index 0000000..02495fb
--- /dev/null
@@ -0,0 +1,464 @@
+var ImageDialog = {
+       preInit : function() {
+               var url;
+
+               tinyMCEPopup.requireLangPack();
+
+               if (url = tinyMCEPopup.getParam("external_image_list_url"))
+                       document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+       },
+
+       init : function(ed) {
+               var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode(), fl = tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList');
+
+               tinyMCEPopup.resizeToInnerSize();
+               this.fillClassList('class_list');
+               this.fillFileList('src_list', fl);
+               this.fillFileList('over_list', fl);
+               this.fillFileList('out_list', fl);
+               TinyMCE_EditableSelects.init();
+
+               if (n.nodeName == 'IMG') {
+                       nl.src.value = dom.getAttrib(n, 'src');
+                       nl.width.value = dom.getAttrib(n, 'width');
+                       nl.height.value = dom.getAttrib(n, 'height');
+                       nl.alt.value = dom.getAttrib(n, 'alt');
+                       nl.title.value = dom.getAttrib(n, 'title');
+                       nl.vspace.value = this.getAttrib(n, 'vspace');
+                       nl.hspace.value = this.getAttrib(n, 'hspace');
+                       nl.border.value = this.getAttrib(n, 'border');
+                       selectByValue(f, 'align', this.getAttrib(n, 'align'));
+                       selectByValue(f, 'class_list', dom.getAttrib(n, 'class'), true, true);
+                       nl.style.value = dom.getAttrib(n, 'style');
+                       nl.id.value = dom.getAttrib(n, 'id');
+                       nl.dir.value = dom.getAttrib(n, 'dir');
+                       nl.lang.value = dom.getAttrib(n, 'lang');
+                       nl.usemap.value = dom.getAttrib(n, 'usemap');
+                       nl.longdesc.value = dom.getAttrib(n, 'longdesc');
+                       nl.insert.value = ed.getLang('update');
+
+                       if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover')))
+                               nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');
+
+                       if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout')))
+                               nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');
+
+                       if (ed.settings.inline_styles) {
+                               // Move attribs to styles
+                               if (dom.getAttrib(n, 'align'))
+                                       this.updateStyle('align');
+
+                               if (dom.getAttrib(n, 'hspace'))
+                                       this.updateStyle('hspace');
+
+                               if (dom.getAttrib(n, 'border'))
+                                       this.updateStyle('border');
+
+                               if (dom.getAttrib(n, 'vspace'))
+                                       this.updateStyle('vspace');
+                       }
+               }
+
+               // Setup browse button
+               document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');
+               if (isVisible('srcbrowser'))
+                       document.getElementById('src').style.width = '260px';
+
+               // Setup browse button
+               document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image');
+               if (isVisible('overbrowser'))
+                       document.getElementById('onmouseoversrc').style.width = '260px';
+
+               // Setup browse button
+               document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image');
+               if (isVisible('outbrowser'))
+                       document.getElementById('onmouseoutsrc').style.width = '260px';
+
+               // If option enabled default contrain proportions to checked
+               if (ed.getParam("advimage_constrain_proportions", true))
+                       f.constrain.checked = true;
+
+               // Check swap image if valid data
+               if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value)
+                       this.setSwapImage(true);
+               else
+                       this.setSwapImage(false);
+
+               this.changeAppearance();
+               this.showPreviewImage(nl.src.value, 1);
+       },
+
+       insert : function(file, title) {
+               var ed = tinyMCEPopup.editor, t = this, f = document.forms[0];
+
+               if (f.src.value === '') {
+                       if (ed.selection.getNode().nodeName == 'IMG') {
+                               ed.dom.remove(ed.selection.getNode());
+                               ed.execCommand('mceRepaint');
+                       }
+
+                       tinyMCEPopup.close();
+                       return;
+               }
+
+               if (tinyMCEPopup.getParam("accessibility_warnings", 1)) {
+                       if (!f.alt.value) {
+                               tinyMCEPopup.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) {
+                                       if (s)
+                                               t.insertAndClose();
+                               });
+
+                               return;
+                       }
+               }
+
+               t.insertAndClose();
+       },
+
+       insertAndClose : function() {
+               var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el;
+
+               tinyMCEPopup.restoreSelection();
+
+               // Fixes crash in Safari
+               if (tinymce.isWebKit)
+                       ed.getWin().focus();
+
+               if (!ed.settings.inline_styles) {
+                       args = {
+                               vspace : nl.vspace.value,
+                               hspace : nl.hspace.value,
+                               border : nl.border.value,
+                               align : getSelectValue(f, 'align')
+                       };
+               } else {
+                       // Remove deprecated values
+                       args = {
+                               vspace : '',
+                               hspace : '',
+                               border : '',
+                               align : ''
+                       };
+               }
+
+               tinymce.extend(args, {
+                       src : nl.src.value.replace(/ /g, '%20'),
+                       width : nl.width.value,
+                       height : nl.height.value,
+                       alt : nl.alt.value,
+                       title : nl.title.value,
+                       'class' : getSelectValue(f, 'class_list'),
+                       style : nl.style.value,
+                       id : nl.id.value,
+                       dir : nl.dir.value,
+                       lang : nl.lang.value,
+                       usemap : nl.usemap.value,
+                       longdesc : nl.longdesc.value
+               });
+
+               args.onmouseover = args.onmouseout = '';
+
+               if (f.onmousemovecheck.checked) {
+                       if (nl.onmouseoversrc.value)
+                               args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';";
+
+                       if (nl.onmouseoutsrc.value)
+                               args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';";
+               }
+
+               el = ed.selection.getNode();
+
+               if (el && el.nodeName == 'IMG') {
+                       ed.dom.setAttribs(el, args);
+               } else {
+                       tinymce.each(args, function(value, name) {
+                               if (value === "") {
+                                       delete args[name];
+                               }
+                       });
+
+                       ed.execCommand('mceInsertContent', false, tinyMCEPopup.editor.dom.createHTML('img', args), {skip_undo : 1});
+                       ed.undoManager.add();
+               }
+
+               tinyMCEPopup.editor.execCommand('mceRepaint');
+               tinyMCEPopup.editor.focus();
+               tinyMCEPopup.close();
+       },
+
+       getAttrib : function(e, at) {
+               var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;
+
+               if (ed.settings.inline_styles) {
+                       switch (at) {
+                               case 'align':
+                                       if (v = dom.getStyle(e, 'float'))
+                                               return v;
+
+                                       if (v = dom.getStyle(e, 'vertical-align'))
+                                               return v;
+
+                                       break;
+
+                               case 'hspace':
+                                       v = dom.getStyle(e, 'margin-left')
+                                       v2 = dom.getStyle(e, 'margin-right');
+
+                                       if (v && v == v2)
+                                               return parseInt(v.replace(/[^0-9]/g, ''));
+
+                                       break;
+
+                               case 'vspace':
+                                       v = dom.getStyle(e, 'margin-top')
+                                       v2 = dom.getStyle(e, 'margin-bottom');
+                                       if (v && v == v2)
+                                               return parseInt(v.replace(/[^0-9]/g, ''));
+
+                                       break;
+
+                               case 'border':
+                                       v = 0;
+
+                                       tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {
+                                               sv = dom.getStyle(e, 'border-' + sv + '-width');
+
+                                               // False or not the same as prev
+                                               if (!sv || (sv != v && v !== 0)) {
+                                                       v = 0;
+                                                       return false;
+                                               }
+
+                                               if (sv)
+                                                       v = sv;
+                                       });
+
+                                       if (v)
+                                               return parseInt(v.replace(/[^0-9]/g, ''));
+
+                                       break;
+                       }
+               }
+
+               if (v = dom.getAttrib(e, at))
+                       return v;
+
+               return '';
+       },
+
+       setSwapImage : function(st) {
+               var f = document.forms[0];
+
+               f.onmousemovecheck.checked = st;
+               setBrowserDisabled('overbrowser', !st);
+               setBrowserDisabled('outbrowser', !st);
+
+               if (f.over_list)
+                       f.over_list.disabled = !st;
+
+               if (f.out_list)
+                       f.out_list.disabled = !st;
+
+               f.onmouseoversrc.disabled = !st;
+               f.onmouseoutsrc.disabled  = !st;
+       },
+
+       fillClassList : function(id) {
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+               if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {
+                       cl = [];
+
+                       tinymce.each(v.split(';'), function(v) {
+                               var p = v.split('=');
+
+                               cl.push({'title' : p[0], 'class' : p[1]});
+                       });
+               } else
+                       cl = tinyMCEPopup.editor.dom.getClasses();
+
+               if (cl.length > 0) {
+                       lst.options.length = 0;
+                       lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');
+
+                       tinymce.each(cl, function(o) {
+                               lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);
+                       });
+               } else
+                       dom.remove(dom.getParent(id, 'tr'));
+       },
+
+       fillFileList : function(id, l) {
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+               l = typeof(l) === 'function' ? l() : window[l];
+               lst.options.length = 0;
+
+               if (l && l.length > 0) {
+                       lst.options[lst.options.length] = new Option('', '');
+
+                       tinymce.each(l, function(o) {
+                               lst.options[lst.options.length] = new Option(o[0], o[1]);
+                       });
+               } else
+                       dom.remove(dom.getParent(id, 'tr'));
+       },
+
+       resetImageData : function() {
+               var f = document.forms[0];
+
+               f.elements.width.value = f.elements.height.value = '';
+       },
+
+       updateImageData : function(img, st) {
+               var f = document.forms[0];
+
+               if (!st) {
+                       f.elements.width.value = img.width;
+                       f.elements.height.value = img.height;
+               }
+
+               this.preloadImg = img;
+       },
+
+       changeAppearance : function() {
+               var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg');
+
+               if (img) {
+                       if (ed.getParam('inline_styles')) {
+                               ed.dom.setAttrib(img, 'style', f.style.value);
+                       } else {
+                               img.align = f.align.value;
+                               img.border = f.border.value;
+                               img.hspace = f.hspace.value;
+                               img.vspace = f.vspace.value;
+                       }
+               }
+       },
+
+       changeHeight : function() {
+               var f = document.forms[0], tp, t = this;
+
+               if (!f.constrain.checked || !t.preloadImg) {
+                       return;
+               }
+
+               if (f.width.value == "" || f.height.value == "")
+                       return;
+
+               tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height;
+               f.height.value = tp.toFixed(0);
+       },
+
+       changeWidth : function() {
+               var f = document.forms[0], tp, t = this;
+
+               if (!f.constrain.checked || !t.preloadImg) {
+                       return;
+               }
+
+               if (f.width.value == "" || f.height.value == "")
+                       return;
+
+               tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width;
+               f.width.value = tp.toFixed(0);
+       },
+
+       updateStyle : function(ty) {
+               var dom = tinyMCEPopup.dom, b, bStyle, bColor, v, isIE = tinymce.isIE, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value});
+
+               if (tinyMCEPopup.editor.settings.inline_styles) {
+                       // Handle align
+                       if (ty == 'align') {
+                               dom.setStyle(img, 'float', '');
+                               dom.setStyle(img, 'vertical-align', '');
+
+                               v = getSelectValue(f, 'align');
+                               if (v) {
+                                       if (v == 'left' || v == 'right')
+                                               dom.setStyle(img, 'float', v);
+                                       else
+                                               img.style.verticalAlign = v;
+                               }
+                       }
+
+                       // Handle border
+                       if (ty == 'border') {
+                               b = img.style.border ? img.style.border.split(' ') : [];
+                               bStyle = dom.getStyle(img, 'border-style');
+                               bColor = dom.getStyle(img, 'border-color');
+
+                               dom.setStyle(img, 'border', '');
+
+                               v = f.border.value;
+                               if (v || v == '0') {
+                                       if (v == '0')
+                                               img.style.border = isIE ? '0' : '0 none none';
+                                       else {
+                                               var isOldIE = tinymce.isIE && (!document.documentMode || document.documentMode < 9);
+
+                                               if (b.length == 3 && b[isOldIE ? 2 : 1])
+                                                       bStyle = b[isOldIE ? 2 : 1];
+                                               else if (!bStyle || bStyle == 'none')
+                                                       bStyle = 'solid';
+                                               if (b.length == 3 && b[isIE ? 0 : 2])
+                                                       bColor = b[isOldIE ? 0 : 2];
+                                               else if (!bColor || bColor == 'none')
+                                                       bColor = 'black';
+                                               img.style.border = v + 'px ' + bStyle + ' ' + bColor;
+                                       }
+                               }
+                       }
+
+                       // Handle hspace
+                       if (ty == 'hspace') {
+                               dom.setStyle(img, 'marginLeft', '');
+                               dom.setStyle(img, 'marginRight', '');
+
+                               v = f.hspace.value;
+                               if (v) {
+                                       img.style.marginLeft = v + 'px';
+                                       img.style.marginRight = v + 'px';
+                               }
+                       }
+
+                       // Handle vspace
+                       if (ty == 'vspace') {
+                               dom.setStyle(img, 'marginTop', '');
+                               dom.setStyle(img, 'marginBottom', '');
+
+                               v = f.vspace.value;
+                               if (v) {
+                                       img.style.marginTop = v + 'px';
+                                       img.style.marginBottom = v + 'px';
+                               }
+                       }
+
+                       // Merge
+                       dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText), 'img');
+               }
+       },
+
+       changeMouseMove : function() {
+       },
+
+       showPreviewImage : function(u, st) {
+               if (!u) {
+                       tinyMCEPopup.dom.setHTML('prev', '');
+                       return;
+               }
+
+               if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true))
+                       this.resetImageData();
+
+               u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u);
+
+               if (!st)
+                       tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this);" onerror="ImageDialog.resetImageData();" />');
+               else
+                       tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this, 1);" />');
+       }
+};
+
+ImageDialog.preInit();
+tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);
diff --git a/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/langs/en_dlg.js b/koha-tmpl/intranet-tmpl/lib/tiny_mce/plugins/advimage/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..5f122e2
--- /dev/null
@@ -0,0 +1 @@
+tinyMCE.addI18n('en.advimage_dlg',{"image_list":"Image List","align_right":"Right","align_left":"Left","align_textbottom":"Text Bottom","align_texttop":"Text Top","align_bottom":"Bottom","align_middle":"Middle","align_top":"Top","align_baseline":"Baseline",align:"Alignment",hspace:"Horizontal Space",vspace:"Vertical Space",dimensions:"Dimensions",border:"Border",list:"Image List",alt:"Image Description",src:"Image URL","dialog_title":"Insert/Edit Image","missing_alt":"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.","example_img":"Appearance Preview Image",misc:"Miscellaneous",mouseout:"For Mouse Out",mouseover:"For Mouse Over","alt_image":"Alternative Image","swap_image":"Swap Image",map:"Image Map",id:"ID",rtl:"Right to Left",ltr:"Left to Right",classes:"Classes",style:"Style","long_desc":"Long Description Link",langcode:"Language Code",langdir:"Language Direction","constrain_proportions":"Constrain Proportions",preview:"Preview",title:"Title",general:"General","tab_advanced":"Advanced","tab_appearance":"Appearance","tab_general":"General",width:"Width",height:"Height"});
\ No newline at end of file
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/wysiwyg-systempreferences.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/wysiwyg-systempreferences.inc
new file mode 100644 (file)
index 0000000..6bbe401
--- /dev/null
@@ -0,0 +1,61 @@
+[% #Enable tinymce for system preferences %]
+<script type="text/javascript" src="[% interface %]/lib/tiny_mce/tiny_mce.js"></script>
+<script>
+
+[%# Save TinyMCE content and trigger an event on the original element %]
+function wysiwyg_change (ed){
+    ed.save();
+    var original_textarea = ed.getElement();
+    $(original_textarea).trigger("input");
+}
+
+tinyMCE.init({
+    setup : function(ed) {
+        ed.onInit.add(function(editor){
+            [%-
+            #Ideally, it would be nice just to use the "oninput" event, which captures keyboard input, dragging, pasting, etc.
+            #However, it doesn't work in IE when the event listener is for an element which is "contenteditable". Since TinyMCE
+            #uses a "contenteditable" body element in an iframe element, it's never going to fire in IE.
+
+            #We can get around this a bit by using "onkeyup" and "ondragend".
+
+            #"ondragend" occurs after you drag content within the editor. "ondrop" is for when you drag content from outside the
+            #editor but it doesn't "dirty" the editor, which makes it useless, as the editor won't save unless it's dirty.
+            #"onpaste" is useless in this same way.
+
+            #Reference:
+            #https://developer.mozilla.org/en-US/docs/Web/Events/input
+            #https://connect.microsoft.com/IE/feedbackdetail/view/794285
+            -%]
+
+            tinyMCE.dom.Event.bind(editor.getBody(), 'input keyup dragend', function(e){
+                if (ed.isDirty()){
+                    wysiwyg_change(ed);
+                }
+            });
+        });
+
+        // Register change when TinyMCE command returns isDirty()
+        ed.onExecCommand.add(function(ed, cmd, ui, val) {
+            if (ed.isDirty()){
+                wysiwyg_change(ed);
+            }
+        });
+
+    },
+    mode : "specific_textareas",
+    editor_selector : "mce",
+    theme : "advanced",
+    content_css : "[% themelang %]/css/tinymce.css",
+    plugins : "table,save,advhr,advlink,contextmenu,advimage",
+    theme_advanced_buttons1 : "bold,italic,|,cut,copy,paste,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,|,image,link,unlink,anchor,cleanup,help,code,advhr,",
+    theme_advanced_buttons2 : "tablecontrols,|,bullist,numlist,|,outdent,indent,|,undo,redo,|,removeformat,|,visualaid,|,sub,sup,|,charmap|,forecolor,backcolor",
+    theme_advanced_buttons3 : "",
+    theme_advanced_toolbar_location : "top",
+    theme_advanced_toolbar_align : "left",
+    theme_advanced_path_location : "bottom",
+    theme_advanced_resizing : true,
+    apply_source_formatting : true
+});
+//]]>
+</script>
index 4466b58..3188f49 100644 (file)
@@ -46,6 +46,8 @@
 <script src="[% interface %]/lib/jquery/plugins/humanmsg.js" type="text/javascript"></script>
 <script src="[% themelang %]/js/ajax.js" type="text/javascript"></script>
 <script src="[% themelang %]/js/pages/preferences.js" type="text/javascript"></script>
+[%# Add WYSIWYG editor for htmlarea system preferences %]
+[% INCLUDE 'wysiwyg-systempreferences.inc' %]
 </head>
 <body id="admin_preferences" class="admin">
 [% INCLUDE 'header.inc' %]
                     [% ELSIF ( CHUNK.type_textarea ) %]
                                        <a class="expand-textarea" style="display: none" href="#">Click to Edit</a>
                                        <textarea name="pref_[% CHUNK.name %]" id="pref_[% CHUNK.name %]" class="preference preference-[% CHUNK.class or "short" %]" rows="10" cols="40">[% CHUNK.value %]</textarea>
+                    [% ELSIF ( CHUNK.type_htmlarea ) %]
+                                       <textarea name="pref_[% CHUNK.name %]" id="pref_[% CHUNK.name %]" class="preference preference-[% CHUNK.class or "short" %] mce" rows="20" cols="60">[% CHUNK.value %]</textarea>
                     [% ELSIF ( CHUNK.type_languages ) %]
                     <dl>
                     [% FOREACH language IN CHUNK.languages %]
index d872ec5..bfcab86 100644 (file)
@@ -2,6 +2,8 @@
 <title>Koha &rsaquo; Administration &rsaquo; [% IF ( add_form ) %] System preferences &rsaquo; [% IF ( modify ) %]Modify system preference '[% searchfield %]'[% ELSE %]Add a system preference[% END %][% END %][% IF ( add_validate ) %] System preferences &rsaquo; Data added[% END %]
 [% IF ( delete_confirm ) %] System preferences &rsaquo; [% searchfield %] &rsaquo; Confirm deletion of parameter '[% searchfield %]'[% END %][% IF ( delete_confirmed ) %] System preferences &rsaquo; Parameter deleted[% END %][% IF ( else ) %]System preferences[% END %]</title>
 [% INCLUDE 'doc-head-close.inc' %]
+[%# Add WYSIWYG editor for htmlarea system preferences %]
+[% INCLUDE 'wysiwyg-systempreferences.inc' %]
 [% IF ( else ) %]
 <link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
 [% INCLUDE 'datatables.inc' %]
                     <textarea id="value" name="value" cols="[% fieldlength %]">[% value |html %]</textarea>
                 [% ELSIF ( type_upload ) %]
                     <input type="file" name="value" />
+                [% ELSIF ( type_htmlarea ) %]
+                    <textarea class="mce" name="value" id="value" rows="[% rows %]" cols="[% cols %]">[% value |html %]</textarea>
                 [% ELSIF ( type_textarea ) %]
                     <textarea name="value" id="value" rows="[% rows %]" cols="[% cols %]">[% value |html %]</textarea>
                 [% ELSIF ( type_choice ) %]
                 <a class="expand-textarea" style="display: none" href="#">Click to edit</a>
                 <textarea name="value" rows="[% loo.rows %]" cols="[% loo.cols %]">[% loo.value |html %]</textarea>
                 [% END %]
+                [% IF ( loo.type_htmlarea ) %]
+                <textarea class="mce" name="value" rows="[% loo.rows %]" cols="[% loo.cols %]">[% loo.value |html %]</textarea>
+                [% END %]
                 [% IF ( loo.type_choice ) %]
                 <select name="value">
                     [% FOREACH option IN loo.options %]