Commit 442ade4e authored by Jono Mingard's avatar Jono Mingard Committed by Gerrit Code Review
Browse files

Upgraded TinyMCE to 4.0.16 (Bug #1282341)



Also changed image popup plugin (used in Journal) to be an actual plugin
which should be easy to integrate into other pages

Change-Id: If57572f34afb1ac4abf012bab32a3966dcfd41ce
Signed-off-by: default avatarJono Mingard <jonom@catalyst.net.nz>
parent 73f9396e
/**
* TinyMCE plugin to provide a popup for inserting an image that has
* been uploaded or attached to a blog post
* @source: http://gitorious.org/mahara/mahara
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
var ImageDialog = {
preInit : function() {
var url;
tinyMCEPopup.requireLangPack();
},
init : function() {
var f = document.forms[0], ed = tinyMCEPopup.editor;
e = ed.selection.getNode();
if (e.nodeName == 'IMG') {
f.src.value = ed.dom.getAttrib(e, 'src');
f.alt.value = ed.dom.getAttrib(e, 'alt');
f.border.value = this.getAttrib(e, 'border');
f.vspace.value = this.getAttrib(e, 'vspace');
f.hspace.value = this.getAttrib(e, 'hspace');
f.width.value = ed.dom.getAttrib(e, 'width');
f.height.value = ed.dom.getAttrib(e, 'height');
f.insert.value = ed.getLang('update');
this.styleVal = ed.dom.getAttrib(e, 'style');
//selectByValue(f, 'image_list', f.src.value);
selectByValue(f, 'align', this.getAttrib(e, 'align'));
this.updateStyle();
}
// Get image list from calling window
document.getElementById('image_list_container').innerHTML = this.imageSelectorHTML(f.src.value);
connect('image_list', 'onchange', function(e) {
e.stop();
this.form.src.value=this.options[this.selectedIndex].value;
ImageDialog.resetImageData();
ImageDialog.getImageData(this.form.src.value);
});
// Check if the image attached
if (e.nodeName == 'IMG' && f.image_list.selectedIndex == 0) {
f.img_src.value = f.src.value;
}
// Refresh
this.getImageData(f.image_list.options[f.image_list.selectedIndex].value);
},
imageSelectorHTML : function(src) {
var imageid = tinyMCEPopup.getWin().imageIdFromSrc(src);
var imagefiles = tinyMCEPopup.getWin().imageList;
var disabled = '';
if (imagefiles.length == 0) {
disabled = 'disabled';
}
var selectElem = SELECT({'class': 'select', 'name': 'image_list', 'id': 'image_list', 'disabled': disabled }, OPTION({'value':''},'--'));
for (var i = 0; i < imagefiles.length; i++) {
var opt = OPTION({'value': imagefiles[i].id, 'title': imagefiles[i].description}, imagefiles[i].name);
if (imageid == imagefiles[i].id) {
setNodeAttribute(opt, 'selected', 'selected');
}
appendChildNodes(selectElem, opt);
}
return selectElem.outerHTML;
},
update : function() {
var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el;
tinyMCEPopup.restoreSelection();
if (f.src.value === '') {
if (ed.selection.getNode().nodeName == 'IMG') {
ed.dom.remove(ed.selection.getNode());
ed.execCommand('mceRepaint');
}
tinyMCEPopup.close();
return;
}
if (!ed.settings.inline_styles) {
args = tinymce.extend(args, {
vspace : nl.vspace.value,
hspace : nl.hspace.value,
border : nl.border.value,
align : getSelectValue(f, 'align')
});
} else {
this.updateStyle();
args.style = this.styleVal;
}
tinymce.extend(args, {
src : f.src.value,
alt : f.alt.value,
width : f.width.value,
height : f.height.value
});
el = ed.selection.getNode();
if (el && el.nodeName == 'IMG') {
ed.dom.setAttribs(el, args);
} else {
ed.execCommand('mceInsertContent', false, '<img id="__mce_tmp" />', {skip_undo : 1});
ed.dom.setAttribs('__mce_tmp', args);
ed.dom.setAttrib('__mce_tmp', 'id', '');
ed.undoManager.add();
}
tinyMCEPopup.close();
},
updateStyle : function() {
var dom = tinyMCEPopup.dom, st, v, f = document.forms[0];
if (tinyMCEPopup.editor.settings.inline_styles) {
st = tinyMCEPopup.dom.parseStyle(this.styleVal);
// Handle align
v = getSelectValue(f, 'align');
if (v) {
if (v == 'left' || v == 'right') {
st['float'] = v;
delete st['vertical-align'];
} else {
st['vertical-align'] = v;
delete st['float'];
}
} else {
delete st['float'];
delete st['vertical-align'];
}
// Handle border
v = f.border.value;
if (v || v == '0') {
if (v == '0')
st['border'] = '0';
else
st['border'] = v + 'px solid black';
} else
delete st['border'];
// Handle hspace
v = f.hspace.value;
if (v) {
delete st['margin'];
st['margin-left'] = v + 'px';
st['margin-right'] = v + 'px';
} else {
delete st['margin-left'];
delete st['margin-right'];
}
// Handle vspace
v = f.vspace.value;
if (v) {
delete st['margin'];
st['margin-top'] = v + 'px';
st['margin-bottom'] = v + 'px';
} else {
delete st['margin-top'];
delete st['margin-bottom'];
}
// Merge
st = tinyMCEPopup.dom.parseStyle(dom.serializeStyle(st));
this.styleVal = dom.serializeStyle(st);
}
},
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 '';
},
resetImageData : function() {
var f = document.forms[0];
f.width.value = f.height.value = f.alt.value = "";
},
updateImageData : function() {
var f = document.forms[0], t = ImageDialog;
if (f.width.value == "")
f.width.value = t.preloadImg.width;
if (f.height.value == "")
f.height.value = t.preloadImg.height;
},
getImageData : function(imageid) {
var f = document.forms[0];
var imgsrc = '';
this.preloadImg = new Image();
this.preloadImg.onload = this.updateImageData;
this.preloadImg.onerror = this.resetImageData;
if (imageid) {
// Image list
imgsrc = tinyMCEPopup.getWin().imageSrcFromId(imageid);
f.src.value = imgsrc;
// Use discription of attached image if possible, but preserve if it was changed.
if (f.image_list.options[f.image_list.selectedIndex].title && !f.alt.value.length) {
f.alt.value = f.image_list.options[f.image_list.selectedIndex].title;
}
else if (f.image_list.selectedIndex && !f.alt.value.length) {
f.alt.value = f.image_list.options[f.image_list.selectedIndex].childNodes[0].nodeValue;
}
// Disable img_src inputbox
f.img_src.disabled = true;
}
else {
// Image URL
f.img_src.disabled = false;
f.image_list.disabled = (f.img_src.value.length || f.image_list.options.length == 1) ? true : false;
imgsrc = f.src.value;
}
this.preloadImg.src = imgsrc;
}
};
ImageDialog.preInit();
tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);
<?php
/**
*
* @package mahara
* @subpackage artefact-blog
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
define('INTERNAL', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
$smarty = smarty_core();
$smarty->display('artefact:blog:image_popup.tpl');
...@@ -168,83 +168,24 @@ $form = pieform(array( ...@@ -168,83 +168,24 @@ $form = pieform(array(
) )
)); ));
/* /*
* Javascript specific to this page. Creates the list of files * Javascript specific to this page. Creates the list of files
* attached to the blog post. * attached to the blog post.
*/ */
$wwwroot = get_config('wwwroot'); $wwwroot = get_config('wwwroot');
$noimagesmessage = json_encode(get_string('noimageshavebeenattachedtothispost', 'artefact.blog')); $noimagesmessage = json_encode(get_string('noimageshavebeenattachedtothispost', 'artefact.blog'));
$javascript = <<<EOF
// Override the image button on the tinyMCE editor. Rather than the
// normal image popup, open up a modified popup which allows the user
// to select an image from the list of image files attached to the
// post.
// Get all the files in the attached files list that have been
// recognised as images. This function is called by the the popup
// window, but needs access to the attachment list on this page
function attachedImageList() {
var images = [];
var attachments = editpost_filebrowser.selecteddata;
for (var a in attachments) {
if (attachments[a].artefacttype == 'image' || attachments[a].artefacttype == 'profileicon') {
images.push({
'id': attachments[a].id,
'name': attachments[a].title,
'description': attachments[a].description ? attachments[a].description : ''
});
}
}
return images;
}
function imageSrcFromId(imageid) {
return config.wwwroot + 'artefact/file/download.php?file=' + imageid;
}
function imageIdFromSrc(src) {
var artefactstring = 'download.php?file=';
var ind = src.indexOf(artefactstring);
if (ind != -1) {
return src.substring(ind+artefactstring.length, src.length);
}
return '';
}
var imageList = {};
function blogpostImageWindow(ui, v) {
var t = tinyMCE.activeEditor;
imageList = attachedImageList();
var template = new Array();
template['file'] = '{$wwwroot}artefact/blog/image_popup.php';
template['width'] = 355;
template['height'] = 275 + (tinyMCE.isMSIE ? 25 : 0);
// Language specific width and height addons
template['width'] += t.getLang('lang_insert_image_delta_width', 0);
template['height'] += t.getLang('lang_insert_image_delta_height', 0);
template['inline'] = true;
t.windowManager.open(template);
}
$javascript = <<<EOF
function editpost_callback(form, data) { function editpost_callback(form, data) {
editpost_filebrowser.callback(form, data); editpost_filebrowser.callback(form, data);
}; };
EOF; EOF;
$smarty = smarty(array(), array(), array(), array( $smarty = smarty(array(), array(), array(), array(
'tinymcesetup' => "ed.addCommand('mceImage', blogpostImageWindow);", 'tinymceconfig' => '
plugins: "textcolor,hr,link,maharaimage,table,emoticons,spellchecker,paste,code,fullscreen",
image_filebrowser: "editpost_filebrowser",
',
'sideblocks' => array( 'sideblocks' => array(
array( array(
'name' => 'quota', 'name' => 'quota',
......
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{str tag=insertimage section=artefact.blog}</title>
<script language="javascript" type="text/javascript" src="{$WWWROOT}js/MochiKit/Packed.js"></script>
<script language="javascript" type="text/javascript" src="{$WWWROOT}js/tinymce/tiny_mce_popup.js"></script>
<script language="javascript" type="text/javascript" src="{$WWWROOT}js/tinymce/utils/mctabs.js"></script>
<script language="javascript" type="text/javascript" src="{$WWWROOT}js/tinymce/utils/form_utils.js"></script>
<script language="javascript" type="text/javascript" src="{$WWWROOT}artefact/blog/image_popup.js"></script>
<link rel="stylesheet" href="{$WWWROOT}artefact/blog/theme/raw/static/style/style.css"></link>
<base target="_self" />
</head>
<body id="image" style="display: none">
<form onSubmit="ImageDialog.update();return false;" action="#">
<div class="tabs">
<ul>
<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onMouseDown="return false;">{str tag=insertimage section=artefact.blog}</a></span></li>
</ul>
</div>
<div class="panel_wrapper">
<div id="general_panel" class="panel current">
<!--input id="src" name="src" type="text" value="" style="width: 200px" onchange="getImageData();" /-->
<input id="src" name="src" type="hidden" value="" />
<input id="imgid" name="imgid" type="hidden" value="" />
<div id="srcbrowsercontainer"></div>
<table border="0" cellpadding="4" cellspacing="0">
<tr>
<td class="nowrap"><label for="img_src">{str section=artefact.blog tag=src}</label></td>
<td><input id="img_src" name="img_src" type="text" value="" style="width: 200px" onChange="this.form.src.value=this.value;ImageDialog.getImageData();" onMouseUp="this.onchange();" onKeyUp="this.onchange();"/></td>
</tr>
<!-- Image list -->
<tr>
<td nowrap="nowrap"><label for="image_list">{str section=artefact.blog tag=image_list}</label></td>
<td id="image_list_container"></td>
</tr>
<!-- /Image list -->
<tr>
<td class="nowrap"><label for="alt">{str section=artefact.blog tag=alt}</label></td>
<td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td>
</tr>
<tr>
<td nowrap="nowrap"><label for="align">{str section=artefact.blog tag=alignment}</label></td>
<td><select id="align" name="align">
<option value="">--</option>
<option value="baseline">{str section=artefact.blog tag=baseline}</option>
<option value="top">{str section=artefact.blog tag=top}</option>
<option value="middle">{str section=artefact.blog tag=middle}</option>
<option value="bottom">{str section=artefact.blog tag=bottom}</option>
<option value="text-top">{str section=artefact.blog tag=texttop}</option>
<option value="text-bottom">{str section=artefact.blog tag=textbottom}</option>
<option value="left">{str section=artefact.blog tag=left}</option>
<option value="right">{str section=artefact.blog tag=right}</option>
</select></td>
</tr>
<tr>
<td nowrap="nowrap"><label for="width">{str section=artefact.blog tag=dimensions}</label></td>
<td><input id="width" name="width" type="text" value="" size="3" maxlength="5" />
x
<input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td>
</tr>
<tr>
<td nowrap="nowrap"><label for="border">{str section=artefact.blog tag=border}</label></td>
<td><input id="border" name="border" type="text" value="" size="3" maxlength="3" /></td>
</tr>
<tr>
<td nowrap="nowrap"><label for="vspace">{str section=artefact.blog tag=verticalspace}</label></td>
<td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" /></td>
</tr>
<tr>
<td nowrap="nowrap"><label for="hspace">{str section=artefact.blog tag=horizontalspace}</label></td>
<td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" /></td>
</tr>
</table>
</div>
</div>
<div class="mceActionPanel">
<div class="fl">
<input type="button" id="insert" class="submit" name="insert" value="{str section=artefact.blog tag=insert}" onClick="ImageDialog.update();return false;" />
</div>
<div class="fr">
<input type="button" id="cancel" class="cancel" name="cancel" value="{str section=artefact.blog tag=cancel}" onClick="tinyMCEPopup.close();" />
</div>
</div>
</form>
</body>
</html>
...@@ -714,7 +714,8 @@ function FileBrowser(idprefix, folderid, config, globalconfig) { ...@@ -714,7 +714,8 @@ function FileBrowser(idprefix, folderid, config, globalconfig) {
'id': id, 'id': id,
'artefacttype': self.filedata[id].artefacttype, 'artefacttype': self.filedata[id].artefacttype,
'title': self.filedata[id].title, 'title': self.filedata[id].title,
'description': self.filedata[id].description 'description': self.filedata[id].description,
'url': self.filedata[id].url
}; };
if ($(self.id + '_select_' + id)) { if ($(self.id + '_select_' + id)) {
addElementClass(self.id + '_select_' + id, 'hidden'); addElementClass(self.id + '_select_' + id, 'hidden');
......
...@@ -134,75 +134,19 @@ $form = pieform($form); ...@@ -134,75 +134,19 @@ $form = pieform($form);
$wwwroot = get_config('wwwroot'); $wwwroot = get_config('wwwroot');
$noimagesmessage = json_encode(get_string('noimageshavebeenattachedtothispost', 'artefact.blog')); $noimagesmessage = json_encode(get_string('noimageshavebeenattachedtothispost', 'artefact.blog'));
$javascript = <<<EOF $javascript = <<<EOF
// Override the image button on the tinyMCE editor. Rather than the
// normal image popup, open up a modified popup which allows the user
// to select an image from the list of image files attached to the
// note.
// Get all the files in the attached files list that have been
// recognised as images. This function is called by the the popup
// window, but needs access to the attachment list on this page
function attachedImageList() {
var images = [];
var attachments = editnote_filebrowser.selecteddata;
for (var a in attachments) {
if (attachments[a].artefacttype == 'image' || attachments[a].artefacttype == 'profileicon') {
images.push({
'id': attachments[a].id,
'name': attachments[a].title,
'description': attachments[a].description ? attachments[a].description : ''
});
}
}
return images;
}
function imageSrcFromId(imageid) {
return config.wwwroot + 'artefact/file/download.php?file=' + imageid;
}
function imageIdFromSrc(src) {
var artefactstring = 'download.php?file=';
var ind = src.indexOf(artefactstring);
if (ind != -1) {
return src.substring(ind+artefactstring.length, src.length);
}
return '';
}
var imageList = {};
function noteImageWindow(ui, v) {
var t = tinyMCE.activeEditor;
imageList = attachedImageList();
var template = new Array();
template['file'] = '{$wwwroot}artefact/blog/image_popup.php';
template['width'] = 355;
template['height'] = 275 + (tinyMCE.isMSIE ? 25 : 0);
// Language specific width and height addons
template['width'] += t.getLang('lang_insert_image_delta_width', 0);
template['height'] += t.getLang('lang_insert_image_delta_height', 0);
template['inline'] = true;
t.windowManager.open(template);
}
function editnote_callback(form, data) { function editnote_callback(form, data) {
editnote_filebrowser.callback(form, data); editnote_filebrowser.callback(form, data);
}; };
EOF; EOF;