MDL-43859 atto_smiley: New plugin to insert smileys

This commit is contained in:
Frederic Massart 2014-01-31 11:54:13 +08:00 committed by Damyon Wiese
parent 0ec6a46ad1
commit 224a9a51ad
11 changed files with 714 additions and 1 deletions

View file

@ -0,0 +1,26 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'atto_emoticon', language 'en'.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['insertemoticon'] = 'Insert emoticon';
$string['pluginname'] = 'Emoticon';

View file

@ -0,0 +1,54 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Atto text editor emoticon plugin lib.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Initialise the strings required for JS.
*
* @return void
*/
function atto_emoticon_strings_for_js() {
global $PAGE;
$PAGE->requires->strings_for_js(array('insertemoticon'), 'atto_emoticon');
// Load the strings required by the emotes.
$manager = get_emoticon_manager();
foreach ($manager->get_emoticons() as $emote) {
$PAGE->requires->string_for_js($emote->altidentifier, $emote->altcomponent);
}
}
/**
* Sends the parameters to JS module.
*
* @return array
*/
function atto_emoticon_params_for_js($elementid, $options, $fpoptions) {
$manager = get_emoticon_manager();
return array(
'emoticons' => $manager->get_emoticons()
);
}

View file

@ -0,0 +1,14 @@
.atto_emoticon_map ul {
padding: 0;
margin: 0;
display: table;
width: 100%;
}
.atto_emoticon_map li {
display: table-row;
white-space: nowrap;
}
.atto_emoticon_map li div {
display: table-cell;
padding: 0 1em;
}

View file

@ -0,0 +1,29 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Atto text editor emoticon plugin version file.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2014013100; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2013110500; // Requires this Moodle version.
$plugin->component = 'atto_emoticon'; // Full name of the plugin (used for diagnostics).

View file

@ -0,0 +1,193 @@
YUI.add('moodle-atto_emoticon-button', function (Y, NAME) {
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Atto text editor emoticon plugin.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* CSS classes and IDs.
*
* @type {Object}
*/
var CSS = {
EMOTE: 'atto_emoticon_emote',
MAP: 'atto_emoticon_map'
},
/**
* Selectors.
*
* @type {Object}
*/
SELECTORS = {
EMOTE: '.atto_emoticon_emote'
};
M.atto_emoticon = M.atto_emoticon || {
/**
* The ID of the current editor.
*
* @type {String}
*/
currentElementId: null,
/**
* The dialogue to select a character.
*
* @type {M.core.dialogue}
*/
dialogue: null,
/**
* List of emoticons.
*
* This must be populated from the result of the PHP function emoticon_manager::get_emoticons().
*
* @type {Array}
*/
emoticons: null,
/**
* Keeps track of the selection made by the user.
*
* @type {Mixed}
*/
selection: null,
/**
* Init.
*
* @param {Object} params
*
* @return {Void}
*/
init: function(params) {
M.atto_emoticon.emoticons = params.emoticons;
var displayChooser = function(e, elementid) {
e.preventDefault();
if (!M.editor_atto.is_active(elementid)) {
M.editor_atto.focus(elementid);
}
// Stores the selection.
M.atto_emoticon.selection = M.editor_atto.get_selection();
if (M.atto_emoticon.selection === false) {
return;
}
// Stores what editor we are working on.
M.atto_emoticon.currentElementId = elementid;
// Initialising the dialogue.
var dialogue;
if (!M.atto_emoticon.dialogue) {
dialogue = new M.core.dialogue({
visible: false,
modal: true,
close: true,
draggable: true
});
// Setting up the content of the dialogue.
dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent());
dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon'));
dialogue.render();
dialogue.centerDialogue();
M.atto_emoticon.dialogue = dialogue;
} else {
dialogue = M.atto_emoticon.dialogue;
}
dialogue.show();
};
var iconurl = M.util.image_url('e/emoticons', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser);
},
/**
* Generates the content of the dialogue.
*
* @return {Node} Node containing the dialogue content
*/
getDialogueContent: function() {
var content,
emote,
emotealt,
html = '',
i;
html += '<div class="' + CSS.MAP + '">';
html += '<ul>';
for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) {
emote = M.atto_emoticon.emoticons[i];
emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent));
html += '<li>';
html += '<div><a href="#" class="' + CSS.EMOTE + '" data-index="' + i + '">';
html += '<img src="' + M.util.image_url(emote.imagename, emote.imagecomponent) + '" alt="' + emotealt + '" />';
html += '</a></div>';
html += '<div>' + Y.Escape.html(emote.text) + '</div>';
html += '<div>' + emotealt + '</div>';
html += '</li>';
}
html += '</ul>';
html += '</div>';
content = Y.Node.create(html);
content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this);
content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this);
return content;
},
/**
* Insert the picked emote in Atto.
*
* @param {Event} e The event
* @return {Void}
*/
insertEmote: function(e) {
var target = e.target.ancestor(SELECTORS.EMOTE, true),
emote = M.atto_emoticon.emoticons[target.getData('index')],
html = '';
e.preventDefault();
e.stopPropagation();
M.atto_emoticon.dialogue.hide();
html = ' ' + emote.text + ' ';
M.editor_atto.set_selection(M.atto_emoticon.selection);
if (document.selection && document.selection.createRange().pasteHTML) {
document.selection.createRange().pasteHTML(html);
} else {
document.execCommand('insertHTML', false, html);
}
// Clean the YUI ids from the HTML.
M.editor_atto.text_updated(M.atto_emoticon.currentElementId);
}
};
}, '@VERSION@', {"requires": ["node"]});

View file

@ -0,0 +1 @@
YUI.add("moodle-atto_emoticon-button",function(e,t){var n={EMOTE:"atto_emoticon_emote",MAP:"atto_emoticon_map"},r={EMOTE:".atto_emoticon_emote"};M.atto_emoticon=M.atto_emoticon||{currentElementId:null,dialogue:null,emoticons:null,selection:null,init:function(e){M.atto_emoticon.emoticons=e.emoticons;var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_emoticon.selection=M.editor_atto.get_selection();if(M.atto_emoticon.selection===!1)return;M.atto_emoticon.currentElementId=t;var n;M.atto_emoticon.dialogue?n=M.atto_emoticon.dialogue:(n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.set("bodyContent",M.atto_emoticon.getDialogueContent()),n.set("headerContent",M.util.get_string("insertemoticon","atto_emoticon")),n.render(),n.centerDialogue(),M.atto_emoticon.dialogue=n),n.show()},n=M.util.image_url("e/emoticons","core");M.editor_atto.add_toolbar_button(e.elementid,"emoticon",n,e.group,t)},getDialogueContent:function(){var t,i,s,o="",u;o+='<div class="'+n.MAP+'">',o+="<ul>";for(u=0;u<M.atto_emoticon.emoticons.length;u++)i=M.atto_emoticon.emoticons[u],s=e.Escape.html(M.util.get_string(i.altidentifier,i.altcomponent)),o+="<li>",o+='<div><a href="#" class="'+n.EMOTE+'" data-index="'+u+'">',o+='<img src="'+M.util.image_url(i.imagename,i.imagecomponent)+'" alt="'+s+'" />',o+="</a></div>",o+="<div>"+e.Escape.html(i.text)+"</div>",o+="<div>"+s+"</div>",o+="</li>";return o+="</ul>",o+="</div>",t=e.Node.create(o),t.delegate("click",M.atto_emoticon.insertEmote,r.EMOTE,this),t.delegate("key",M.atto_emoticon.insertEmote,"32",r.EMOTE,this),t},insertEmote:function(e){var t=e.target.ancestor(r.EMOTE,!0),n=M.atto_emoticon.emoticons[t.getData("index")],i="";e.preventDefault(),e.stopPropagation(),M.atto_emoticon.dialogue.hide(),i=" "+n.text+" ",M.editor_atto.set_selection(M.atto_emoticon.selection),document.selection&&document.selection.createRange().pasteHTML?document.selection.createRange().pasteHTML(i):document.execCommand("insertHTML",!1,i),M.editor_atto.text_updated(M.atto_emoticon.currentElementId)}}},"@VERSION@",{requires:["node"]});

View file

@ -0,0 +1,193 @@
YUI.add('moodle-atto_emoticon-button', function (Y, NAME) {
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Atto text editor emoticon plugin.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* CSS classes and IDs.
*
* @type {Object}
*/
var CSS = {
EMOTE: 'atto_emoticon_emote',
MAP: 'atto_emoticon_map'
},
/**
* Selectors.
*
* @type {Object}
*/
SELECTORS = {
EMOTE: '.atto_emoticon_emote'
};
M.atto_emoticon = M.atto_emoticon || {
/**
* The ID of the current editor.
*
* @type {String}
*/
currentElementId: null,
/**
* The dialogue to select a character.
*
* @type {M.core.dialogue}
*/
dialogue: null,
/**
* List of emoticons.
*
* This must be populated from the result of the PHP function emoticon_manager::get_emoticons().
*
* @type {Array}
*/
emoticons: null,
/**
* Keeps track of the selection made by the user.
*
* @type {Mixed}
*/
selection: null,
/**
* Init.
*
* @param {Object} params
*
* @return {Void}
*/
init: function(params) {
M.atto_emoticon.emoticons = params.emoticons;
var displayChooser = function(e, elementid) {
e.preventDefault();
if (!M.editor_atto.is_active(elementid)) {
M.editor_atto.focus(elementid);
}
// Stores the selection.
M.atto_emoticon.selection = M.editor_atto.get_selection();
if (M.atto_emoticon.selection === false) {
return;
}
// Stores what editor we are working on.
M.atto_emoticon.currentElementId = elementid;
// Initialising the dialogue.
var dialogue;
if (!M.atto_emoticon.dialogue) {
dialogue = new M.core.dialogue({
visible: false,
modal: true,
close: true,
draggable: true
});
// Setting up the content of the dialogue.
dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent());
dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon'));
dialogue.render();
dialogue.centerDialogue();
M.atto_emoticon.dialogue = dialogue;
} else {
dialogue = M.atto_emoticon.dialogue;
}
dialogue.show();
};
var iconurl = M.util.image_url('e/emoticons', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser);
},
/**
* Generates the content of the dialogue.
*
* @return {Node} Node containing the dialogue content
*/
getDialogueContent: function() {
var content,
emote,
emotealt,
html = '',
i;
html += '<div class="' + CSS.MAP + '">';
html += '<ul>';
for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) {
emote = M.atto_emoticon.emoticons[i];
emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent));
html += '<li>';
html += '<div><a href="#" class="' + CSS.EMOTE + '" data-index="' + i + '">';
html += '<img src="' + M.util.image_url(emote.imagename, emote.imagecomponent) + '" alt="' + emotealt + '" />';
html += '</a></div>';
html += '<div>' + Y.Escape.html(emote.text) + '</div>';
html += '<div>' + emotealt + '</div>';
html += '</li>';
}
html += '</ul>';
html += '</div>';
content = Y.Node.create(html);
content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this);
content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this);
return content;
},
/**
* Insert the picked emote in Atto.
*
* @param {Event} e The event
* @return {Void}
*/
insertEmote: function(e) {
var target = e.target.ancestor(SELECTORS.EMOTE, true),
emote = M.atto_emoticon.emoticons[target.getData('index')],
html = '';
e.preventDefault();
e.stopPropagation();
M.atto_emoticon.dialogue.hide();
html = ' ' + emote.text + ' ';
M.editor_atto.set_selection(M.atto_emoticon.selection);
if (document.selection && document.selection.createRange().pasteHTML) {
document.selection.createRange().pasteHTML(html);
} else {
document.execCommand('insertHTML', false, html);
}
// Clean the YUI ids from the HTML.
M.editor_atto.text_updated(M.atto_emoticon.currentElementId);
}
};
}, '@VERSION@', {"requires": ["node"]});

View file

@ -0,0 +1,10 @@
{
"name": "moodle-atto_emoticon-button",
"builds": {
"moodle-atto_emoticon-button": {
"jsfiles": [
"button.js"
]
}
}
}

View file

@ -0,0 +1,188 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Atto text editor emoticon plugin.
*
* @package atto_emoticon
* @copyright 2014 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* CSS classes and IDs.
*
* @type {Object}
*/
var CSS = {
EMOTE: 'atto_emoticon_emote',
MAP: 'atto_emoticon_map'
},
/**
* Selectors.
*
* @type {Object}
*/
SELECTORS = {
EMOTE: '.atto_emoticon_emote'
};
M.atto_emoticon = M.atto_emoticon || {
/**
* The ID of the current editor.
*
* @type {String}
*/
currentElementId: null,
/**
* The dialogue to select a character.
*
* @type {M.core.dialogue}
*/
dialogue: null,
/**
* List of emoticons.
*
* This must be populated from the result of the PHP function emoticon_manager::get_emoticons().
*
* @type {Array}
*/
emoticons: null,
/**
* Keeps track of the selection made by the user.
*
* @type {Mixed}
*/
selection: null,
/**
* Init.
*
* @param {Object} params
*
* @return {Void}
*/
init: function(params) {
M.atto_emoticon.emoticons = params.emoticons;
var displayChooser = function(e, elementid) {
e.preventDefault();
if (!M.editor_atto.is_active(elementid)) {
M.editor_atto.focus(elementid);
}
// Stores the selection.
M.atto_emoticon.selection = M.editor_atto.get_selection();
if (M.atto_emoticon.selection === false) {
return;
}
// Stores what editor we are working on.
M.atto_emoticon.currentElementId = elementid;
// Initialising the dialogue.
var dialogue;
if (!M.atto_emoticon.dialogue) {
dialogue = new M.core.dialogue({
visible: false,
modal: true,
close: true,
draggable: true
});
// Setting up the content of the dialogue.
dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent());
dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon'));
dialogue.render();
dialogue.centerDialogue();
M.atto_emoticon.dialogue = dialogue;
} else {
dialogue = M.atto_emoticon.dialogue;
}
dialogue.show();
};
var iconurl = M.util.image_url('e/emoticons', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser);
},
/**
* Generates the content of the dialogue.
*
* @return {Node} Node containing the dialogue content
*/
getDialogueContent: function() {
var content,
emote,
emotealt,
html = '',
i;
html += '<div class="' + CSS.MAP + '">';
html += '<ul>';
for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) {
emote = M.atto_emoticon.emoticons[i];
emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent));
html += '<li>';
html += '<div><a href="#" class="' + CSS.EMOTE + '" data-index="' + i + '">';
html += '<img src="' + M.util.image_url(emote.imagename, emote.imagecomponent) + '" alt="' + emotealt + '" />';
html += '</a></div>';
html += '<div>' + Y.Escape.html(emote.text) + '</div>';
html += '<div>' + emotealt + '</div>';
html += '</li>';
}
html += '</ul>';
html += '</div>';
content = Y.Node.create(html);
content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this);
content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this);
return content;
},
/**
* Insert the picked emote in Atto.
*
* @param {Event} e The event
* @return {Void}
*/
insertEmote: function(e) {
var target = e.target.ancestor(SELECTORS.EMOTE, true),
emote = M.atto_emoticon.emoticons[target.getData('index')],
html = '';
e.preventDefault();
e.stopPropagation();
M.atto_emoticon.dialogue.hide();
html = ' ' + emote.text + ' ';
M.editor_atto.set_selection(M.atto_emoticon.selection);
if (document.selection && document.selection.createRange().pasteHTML) {
document.selection.createRange().pasteHTML(html);
} else {
document.execCommand('insertHTML', false, html);
}
// Clean the YUI ids from the HTML.
M.editor_atto.text_updated(M.atto_emoticon.currentElementId);
}
};

View file

@ -0,0 +1,5 @@
{
"moodle-atto_emoticon-button": {
"requires": ["node"]
}
}

View file

@ -33,7 +33,7 @@ if ($ADMIN->fulltree) {
$default = 'style = bold, italic, underline, strike, clear, title' . "\n" .
'paragraph = indent, outdent, orderedlist, unorderedlist' . "\n" .
'links = link, unlink' . "\n" .
'insert = table, image, media, charmap' . "\n" .
'insert = table, image, media, charmap, emoticon' . "\n" .
'other = html';
$setting = new admin_setting_configtextarea('editor_atto/toolbar',
$name,