diff --git a/README.md b/README.md new file mode 100644 index 0000000..a4b35e4 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +edu-sharing atto plugin +========================= + +The edu-sharing atto plugin adds the option to embed all kinds of edu-sharing content to all WYSIWYG fields. The new button will open the edu-sharing search engine and let you pick an item embed. Audio and video-files will be embedded with a player. Documents will be represented by a link. You may pick which version of the content you would like to provide in the course (always the latest vs. the version you just picked). + +Dependencies +------------ + +Depends on the edu-sharing activity module. To show the embedded content the edu-sharing filter must be activated. + +Installation +------------ + +For a full documentation with screenshots of the installation steps for the edu-sharing plugin pakage visit the [documentation pages](http://docs.edu-sharing.com/confluence/edp/en). + +Documentation +------------- + +More information can be found on the [homepage](http://www.edu-sharing.com). + +Where can I get the latest release? +----------------------------------- +You find our latest releases on our [github repository](https://github.com/edu-sharing). + +Contributing +------------ + +If you plan to contribute on a regular basis, please visit our [community site](http://edu-sharing-network.org/?lang=en). + +License +------- +Code is under the [GNU GENERAL PUBLIC LICENSE v3](./LICENSE). diff --git a/db/access.php b/db/access.php new file mode 100644 index 0000000..e2c8367 --- /dev/null +++ b/db/access.php @@ -0,0 +1,41 @@ +. + +/** + * Plugin capabilities + * + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$capabilities = array( + + 'atto/edusharing:visible' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_COURSE, + 'archetypes' => array( + 'coursecreator' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ) +); + diff --git a/db/install.php b/db/install.php new file mode 100644 index 0000000..c6b2885 --- /dev/null +++ b/db/install.php @@ -0,0 +1,57 @@ +. + +/** + * Add the edusharing button to Atto + * + * @package atto_edusharing + * @copyright metaVentis GmbH — http://metaventis.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Enable edusharing for Atto buttons on installation. + */ +function xmldb_atto_edusharing_install() { + $toolbar = get_config('editor_atto', 'toolbar'); + if (strpos($toolbar, 'edusharing') === false && $toolbar && $toolbar != '') { + $groups = explode("\n", $toolbar); + // Try to put edusharing in files group. + $found = false; + foreach ($groups as $i => $group) { + $parts = explode('=', $group); + if (trim($parts[0]) == 'files') { + $groups[$i] = 'files = ' . trim($parts[1]) . ', edusharing'; + $found = true; + } + } + // Otherwise create a edusharing group in the second position starting from + // the end. + if (!$found) { + do { + $last = array_pop($groups); + } while (empty($last) && !empty($groups)); + + $groups[] = 'edusharing = edusharing'; + $groups[] = $last; + } + // Update config variable. + $toolbar = implode("\n", $groups); + set_config('toolbar', $toolbar, 'editor_atto'); + } +} diff --git a/db/uninstall.php b/db/uninstall.php new file mode 100644 index 0000000..420808a --- /dev/null +++ b/db/uninstall.php @@ -0,0 +1,54 @@ +. + +/** + * Atto uninstall script. Removes edusharing button from Atto toolbar. + * + * @package atto_edusharing + * @copyright metaVentis GmbH — http://metaventis.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +function xmldb_atto_edusharing_uninstall() { + // Remove 'edusharing' from the toolbar editor_atto config variable. + $toolbar = get_config('editor_atto', 'toolbar'); + if (strpos($toolbar, 'edusharing') !== false) { + $groups = explode("\n", $toolbar); + $newgroups = array(); + foreach ($groups as $group) { + if (strpos($group, 'edusharing') !== false) { + $parts = explode('=', $group); + $items = explode(',', $parts[1]); + $newitems = array(); + foreach ($items as $item) { + if (trim($item) != 'edusharing') { + $newitems[] = $item; + } + } + if (!empty($newitems)) { + $parts[1] = implode(',', $newitems); + $newgroups[] = implode('=', $parts); + } + } else { + $newgroups[] = $group; + } + } + $toolbar = implode("\n", $newgroups); + set_config('toolbar', $toolbar, 'editor_atto'); + } +} diff --git a/delete.php b/delete.php new file mode 100644 index 0000000..27eb92f --- /dev/null +++ b/delete.php @@ -0,0 +1,58 @@ +. + +/** + * Called on object deletion + * + * @package editor_edusharing + * @copyright metaVentis GmbH — http://metaventis.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../../../config.php'); +require_once($CFG->dirroot . '/lib/setup.php'); + +require_login(); +require_sesskey(); + +require_once($CFG->dirroot . '/mod/edusharing/lib.php'); + +$input = file_get_contents('php://input'); +if (!$input) { + throw new Exception(get_string('error_json', 'editor_edusharing')); +} + +$delete = json_decode($input); +if (!$delete) { + throw new Exception(get_string('error_json', 'editor_edusharing')); +} + +$where = array( + 'id' => $delete->id, + 'course' => $delete->course, +); +$edusharing = $DB->get_record(EDUSHARING_TABLE, $where); +if (!$edusharing) { + trigger_error(get_string('error_resource_not_found', 'editor_edusharing'), E_USER_WARNING); + header('HTTP/1.1 404 Not found', true, 404); + exit(); +} + +if (!edusharing_delete_instance($edusharing->id)) { + trigger_error(get_string('error_deleting_instance', 'editor_edusharing'), E_USER_WARNING); + + header('', true, 500); +} diff --git a/insert.php b/insert.php new file mode 100644 index 0000000..2a3877d --- /dev/null +++ b/insert.php @@ -0,0 +1,61 @@ +. + +/** + * Called on object insertion + * + * @package editor_edusharing + * @copyright metaVentis GmbH — http://metaventis.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once( __DIR__ . '/../../../../../config.php'); +require_once($CFG->dirroot . '/lib/setup.php'); + +require_login(); +require_sesskey(); + +require_once($CFG->dirroot . '/mod/edusharing/lib.php'); + +try { + + $input = file_get_contents('php://input'); + if (!$input) { + throw new Exception(get_string('error_json', 'editor_edusharing')); + } + + $edusharing = json_decode($input); + if (!$edusharing) { + throw new Exception(get_string('error_json', 'editor_edusharing')); + } + + $edusharing->editor_atto = true; + + $id = edusharing_add_instance($edusharing); + if (!$id) { + throw new Exception(get_string('error_adding_instance', 'editor_edusharing')); + } + + $edusharing->id = $id; + + $edusharing->src = $CFG->wwwroot . '/lib/editor/edusharing/images/edusharing.png'; + + header('Content-type: application/json', true, 200); + echo json_encode($edusharing); +} catch (Exception $exception) { + trigger_error($exception->getMessage(), E_USER_WARNING); + header('HTTP/1.1 500 Internal Server Error', true, 500); +} diff --git a/lang/de/atto_edusharing.php b/lang/de/atto_edusharing.php new file mode 100644 index 0000000..a9ceb9c --- /dev/null +++ b/lang/de/atto_edusharing.php @@ -0,0 +1,45 @@ +. + +/** + * Strings for component 'atto_edusharing', language 'de'. + * + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['pluginname'] = 'edu-sharing'; +$string['dialogtitle'] = 'edu-sharing Material'; +$string['settings'] = 'edu-sharing (Atto)'; +$string['insert'] = 'EINFÜGEN'; +$string['update'] = 'AKTUALISIEREN'; +$string['cancel'] = 'ABBRECHEN'; +$string['title'] = 'Title'; +$string['subtitle'] = 'Untertitel'; +$string['alwaysShowLatestVersion'] = 'Immer die neuste Version anzeigen'; +$string['alignment'] = 'Ausrichtung'; +$string['alignmentLeft'] = 'Links umfließend'; +$string['alignmentRight'] = 'Rechts umfließend'; +$string['alignmentNone'] = 'Keine'; +$string['dimensions'] = 'Dimensionen'; +$string['dimensionsWidth'] = 'Breite'; +$string['dimensionsheight'] = 'Höhe'; +$string['openRepo'] = 'REPOSITORIUM ÖFFNEN'; +$string['hint1'] = 'Wählen Sie ein edu-sharing Objekt aus dem Repositorium, um es in Moodle einzubinden. Klicken Sie dazu auf "' . $string['openRepo'] . '".'; +$string['hint2'] = 'Suchen Sie nun das gewünschte Objekt und betätigen Sie die "ÜBERNEHMEN" Schaltfläche.'; +$string['skipHint'] = 'Beim nächsten Mal direkt zur Suche springen.'; +$string['directoryHint'] = 'Der Ordner wird eingebunden. Elemente des Ordners werden angezeigt, nicht aber weitere Unterordner.'; diff --git a/lang/en/atto_edusharing.php b/lang/en/atto_edusharing.php new file mode 100644 index 0000000..5839623 --- /dev/null +++ b/lang/en/atto_edusharing.php @@ -0,0 +1,45 @@ +. + +/** + * Strings for component 'atto_edusharing', language 'en'. + * + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['pluginname'] = 'edu-sharing'; +$string['dialogtitle'] = 'edu-sharing material'; +$string['settings'] = 'edu-sharing (Atto)'; +$string['insert'] = 'EMBED'; +$string['update'] = 'UPDATE'; +$string['cancel'] = 'CANCEL'; +$string['title'] = 'Title'; +$string['subtitle'] = 'Caption'; +$string['alwaysShowLatestVersion'] = 'Always use the latest version.'; +$string['alignment'] = 'Alignment'; +$string['alignmentLeft'] = 'float left'; +$string['alignmentRight'] = 'float right'; +$string['alignmentNone'] = 'none'; +$string['dimensions'] = 'Dimensions'; +$string['dimensionsWidth'] = 'Width'; +$string['dimensionsheight'] = 'Height'; +$string['openRepo'] = 'OPEN REPOSITORY'; +$string['hint1'] = 'Select an edu-sharing object from the repository to embed it in Moodle. Click on "' . $string['openRepo'] . '".'; +$string['hint2'] = 'Search for the desired object and click the "APPLY" button.'; +$string['skipHint'] = 'Open the search engine right away next time.'; +$string['directoryHint'] = 'The folder was embedded. Elements of the folder will be displayed, but not its subfolders.'; diff --git a/lib.php b/lib.php new file mode 100644 index 0000000..3a8289d --- /dev/null +++ b/lib.php @@ -0,0 +1,91 @@ +. + +/** + * Atto text editor integration version file. + * + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Initialise this plugin + * @param string $elementid + */ +function atto_edusharing_strings_for_js() { + global $PAGE; + + $PAGE->requires->strings_for_js(array( + 'pluginname', + 'dialogtitle', + 'settings', + 'insert', + 'update', + 'cancel', + 'title', + 'subtitle', + 'alwaysShowLatestVersion', + 'alignment', + 'alignmentLeft', + 'alignmentRight', + 'alignmentNone', + 'dimensions', + 'dimensionsWidth', + 'dimensionsheight', + 'hint1', + 'hint2', + 'skipHint', + 'openRepo', + 'directoryHint', + ), + 'atto_edusharing'); +} + +/** + * Return the js params required for this module. + * @return array of additional params to pass to javascript init function for this module. + */ +function atto_edusharing_params_for_js($elementid, $options, $fpoptions) { + global $PAGE, $COURSE; + $disabled = false; + + $params = array(); + $coursecontext = context_course::instance($COURSE->id); + + //disable edusharing button for content that is viewable on the front-page + $pagetype = $PAGE->pagetype; + if($pagetype == 'course-edit' || $pagetype == 'admin-setting-frontpagesettings'){ + $disabled = true; + } + + if (!has_capability('atto/edusharing:visible', $coursecontext)) { + $disabled = true; + } + $params['disabled'] = $disabled; + $params['repourl'] = trim(get_config('edusharing', 'application_cc_gui_url'), '/'); + $params['courseid'] = $COURSE->id; + + $ccauth = new mod_edusharing_web_service_factory(); + $ticket = $ccauth->edusharing_authentication_get_ticket(); + $params['ticket'] = $ticket; + + return $params; +} + diff --git a/pix/help_en.gif b/pix/help_en.gif new file mode 100644 index 0000000..adb13c9 Binary files /dev/null and b/pix/help_en.gif differ diff --git a/pix/icon.svg b/pix/icon.svg new file mode 100644 index 0000000..af0f985 --- /dev/null +++ b/pix/icon.svg @@ -0,0 +1,9 @@ + + + + + edu-sharing Logo Wabe + + + + diff --git a/preview.php b/preview.php new file mode 100644 index 0000000..f7c5938 --- /dev/null +++ b/preview.php @@ -0,0 +1,70 @@ +. + +/** + * Fetches object preview from repository + * + * @package editor_edusharing + * @copyright metaVentis GmbH — http://metaventis.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Create preview link with signature. +require_once(__DIR__ . '/../../../../../config.php'); +require_once($CFG->dirroot . '/lib/setup.php'); +require_once($CFG->dirroot . '/mod/edusharing/lib.php'); + +require_login(); + +global $DB, $USER; + +$resourceid = optional_param('resourceId', 0, PARAM_INT); + +if (!$edusharing = $DB->get_record('edusharing', array('id' => $resourceid))) { + trigger_error(get_string('error_loading_instance', 'editor_edusharing'), E_USER_WARNING); +} + +$previewservice = get_config('edusharing', 'application_cc_gui_url') . '/' . 'preview'; + +$time = round(microtime(true) * 1000); + +$url = $previewservice; +$url .= '?appId=' . get_config('edusharing', 'application_appid'); +$url .= '&courseId=' . $edusharing->course; +$url .= '&repoId=' . edusharing_get_repository_id_from_url($edusharing->object_url); +$url .= '&proxyRepId=' . get_config('edusharing', 'application_homerepid'); +$url .= '&nodeId=' . edusharing_get_object_id_from_url($edusharing->object_url); +$url .= '&resourceId=' . $resourceid; +$url .= '&version=' . $edusharing->object_version; +$sigdata = get_config('edusharing', 'application_appid') . $time . edusharing_get_object_id_from_url($edusharing->object_url); +$sig = urlencode(edusharing_get_signature($sigdata)); +$url .= '&sig=' . $sig; +$url .= '&signed=' . $sigdata; +$url .= '&ts=' . $time; + +$curlhandle = curl_init($url); +curl_setopt($curlhandle, CURLOPT_SSL_VERIFYPEER, false); +curl_setopt($curlhandle, CURLOPT_SSL_VERIFYHOST, false); +curl_setopt($curlhandle, CURLOPT_FOLLOWLOCATION, 1); +curl_setopt($curlhandle, CURLOPT_HEADER, 0); +curl_setopt($curlhandle, CURLOPT_RETURNTRANSFER, 1); +curl_setopt($curlhandle, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); +$output = curl_exec($curlhandle); +$mimetype = curl_getinfo($curlhandle, CURLINFO_CONTENT_TYPE); +curl_close($curlhandle); +header('Content-type: ' . $mimetype); +echo $output; +exit(); diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..540ce98 --- /dev/null +++ b/styles.css @@ -0,0 +1,133 @@ +.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-bd { + padding: 1rem !important; +} + +#edusharing_form { + padding: 0; +} + +#edusharing_form input { + border-radius: 3px; + border: 1px solid #bbb; + padding: 5px 10px; +} + +#edusharing_form input[type=number] { + padding-right: 0; +} + +#edusharing_form h2 { + font-size: 1.4em; +} + +#edusharing_preview { + float: right; + max-width: 300px; + max-height: 300px; +} + +.edusharing_form_wrapper { + margin-top: 30px; +} + +#edusharing_wrapper_buttons { + text-align: right; + position: absolute; + right: 15px; + bottom: 15px; +} + +.atto_form label.edusharing_label_inline { + display: inline-block; + margin-left: 10px; +} + +.atto_form label.edusharing_label_block { + display: block; +} + +#edusharing_height, +#edusharing_width { + width: 70px; + text-align: center; +} + +#edusharing_wrapper_buttons { + clear: both; +} + +#edusharing_hint { + text-align: left; +} + +#edusharing_hint_help { + float: left; + width: 340px; + margin-right: 40px; +} + +#edusharing_hint_skip { + text-align: center; + margin-top: 60px; +} + +#edusharing_hint_check { + margin-right: 10px; +} + +.edusharing_center { + display: block; + text-align: center; +} + +.edusharing_hint_buttons { + margin: 30px 0 10px 0; +} + +#edusharing_hint_logo { + display: block; + margin: 0 auto; + margin-bottom: 30px; + max-height: 120px; +} + +input#edusharing_title { + border: none; + font-family: inherit; + font-size: 2em; + padding: 0; + width: auto; +} + +#edusharing_title_pencil { + display: none; + margin-left: 15px; + font-size: 1.5em; + vertical-align: baseline; +} + +input#edusharing_title:hover + #edusharing_title_pencil { + display: inline-block; +} + +#edusharing_caption { + width: 300px; +} + + +.editor_atto .edusharing_atto { + background-color: #efefef; + background-repeat: no-repeat; + background-size: 16px; + background-image: url('[[pix:atto_edusharing|/icon]]'); +} + +.editor_atto img.edusharing_atto { + object-position: 0 -30px; + background-position: bottom 5px left 5px; +} + +.editor_atto a.edusharing_atto { + background-position: center left 5px; + padding: 6px 10px 6px 30px; +} diff --git a/version.php b/version.php new file mode 100644 index 0000000..de028cc --- /dev/null +++ b/version.php @@ -0,0 +1,37 @@ +. + +/** + * Atto edusharing version file. + * + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2020020701; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2013110500; // Requires this Moodle version. +$plugin->component = 'atto_edusharing'; // Full name of the plugin (used for diagnostics). +$plugin->maturity = MATURITY_STABLE; +$plugin->dependencies = array( + 'mod_edusharing' => 2018110801 +); +// Human readable version information. +$plugin->release = '5.0'; + + diff --git a/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-debug.js b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-debug.js new file mode 100644 index 0000000..e86f18c --- /dev/null +++ b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-debug.js @@ -0,0 +1,838 @@ +YUI.add('moodle-atto_edusharing-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 . + +/* + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// build yui with the command: shifter + +/** + * @module moodle-atto_edusharing-button + */ + +/** + * Atto text editor edusharing plugin. + * + * @namespace M.atto_edusharing + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_edusharing'; + +var TEMPLATE = '
' + + '' + + '' + + '{{get_string "hint1" component}}

{{get_string "hint2" component}}' + + '
' + + '
' + + '{{get_string "skipHint" component}}
' + + '
' + + '{{get_string "cancel" component}} ' + + '
' + + '
' + + ''; + +Y.namespace('M.atto_edusharing').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * Initialize the button + * + * @method Initializer + */ + initializer: function () { + // If we don't have the capability to view then give up. + if (this.get('disabled')) { + return; + } + this.addButton({ + icon: 'icon', + iconComponent: 'atto_edusharing', + buttonName: 'icon', + callback: this._displayDialogue, + callbackArgs: 'icon', + tags: '.edusharing_atto', + tagMatchRequiresAll: false + }); + + // Attach a submit listener to the form. + var form = this.get('host').textarea.ancestor('form'); + if (form) { + form.on('submit', this.eduSubmit, this); + } + + this.getExistingObjects(); + + var that = this; + window.addEventListener("message", function (event) { + if (event.data.event == "APPLY_NODE") { + var node = event.data.data; + window.win.close(); + that.updateDialog(node); + } + }, false); + }, + + getUrlVars: function (query) { + var vars = {}; + if (!query.startsWith('?')) { + query = '?' + query; + } + var parts = query.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { + vars[key] = value; + }); + return vars; + }, + + getExistingObjects: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + var nodes = [container]; + while (0 < nodes.length) { + var node = nodes.shift(); + // Is ELEMENT_NODE? + if (1 == node.nodeType) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var object = new edusharingObject(this.get('courseid')); + if (object.importNode(searchParams)) { + this.get('existingObjects')[object.id] = object; + } else { + alert('error_importing_node - 1'); + node.parentNode.removeChild(node); + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + }, + + updateDialog: function (node, update) { + Y.one('#edusharing_form').set('style', 'display:block'); + Y.one('#edusharing_hint').set('style', 'display:none'); + + if (node.isDirectory) { + Y.one('#edusharing_wrapper_dimensions').set('style', 'display:none'); + Y.one('#edusharing_version_latest').set('style', 'visibility:hidden'); + Y.one('#edusharing_version_latest_label').set('style', 'visibility:hidden'); + Y.one('#edusharing_wrapper_alignment').set('style', 'visibility:hidden'); + Y.one('#edusharing_hint_directory').set('style', 'display:block'); + } else if (this.getType(node.mediatype) == "ref") { + Y.one('#edusharing_wrapper_dimensions').set('style', 'visibility:hidden'); + } else { + var width = Math.round(node.properties['ccm:width']) || 600; + var height = Math.round(node.properties['ccm:height']) || 400; + Y.one('#edusharing_width').set('value', width); + Y.one('#edusharing_height').set('value', height); + Y.one('#edusharing_ratio').set('value', width / height); + } + + Y.one('#edusharing_title').set('value', node.title || node.name); + Y.one('#edusharing_caption').set('value', node.caption || ''); + Y.one('#edusharing_object_url').set('value', node.objectUrl); + Y.one('#edusharing_mimetype').set('value', node.mimetype); + Y.one('#edusharing_mediatype').set('value', node.mediatype); + Y.one('#edusharing_preview_url').set('value', node.preview.url); + Y.one('#edusharing_preview').set('src', node.preview.url); + Y.one('#edusharing_version').set('value', node.properties['cclom:version']); + + if (update) { + Y.one('#edusharing_resid').set('value', node.resid); + Y.one('#edusharing_version_latest').set('style', 'display:none'); + Y.one('#edusharing_version_latest_label').set('style', 'display:none'); + Y.one('#edusharing_submit').setContent(M.util.get_string('update', COMPONENTNAME)); + if (node.alignment) { + Y.one('#edusharing_alignment_none').set('checked', false); + Y.one('#edusharing_alignment_' + node.alignment).set('checked', true); + } else { + Y.one('#edusharing_alignment_none').set('checked', true); + Y.one('#edusharing_alignment_right').set('checked', false); + Y.one('#edusharing_alignment_left').set('checked', false); + } + } + }, + + eduSubmit: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + + var nodes = [container]; + + while (0 < nodes.length) { + var node = nodes.shift(); + if (node.nodeType == 1) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var resource_id = searchParams.get('resourceId'); + if (resource_id && this.get('existingObjects')[resource_id]) { + delete this.get('existingObjects')[resource_id]; + } else { + var object = new edusharingObject(this.get('courseid')); + if (!object.importNode(searchParams)) { + alert('error_importing_node - 2'); + } + if (!object.link(node)) { + alert('error_setting_usage'); + node.parentNode.removeChild(node); + } + + if (node.nodeName.toLowerCase() == 'img') { + node.setAttribute('src', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } else { + node.setAttribute('href', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + + // The remaining known objects can be deleted. + for (var resource_id in this.get('existingObjects')) { + var remainder = this.get('existingObjects')[resource_id]; + if (!remainder.unlink(node)) { + alert('error_deleting_usage'); + } + } + + this.get('host').textarea.set('value', container.innerHTML); + }, + + getQueryStringFromParams: function (params) { + var out = []; + for (var key in params) { + out.push(key + '=' + params[key]); + } + return out.join('&'); + }, + + getPreviewUrl: function (resourceId) { + var previewUrl = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/preview.php'; + previewUrl += '?resourceId=' + resourceId; + return previewUrl; + }, + + getSelectedElement: function () { + var element = this.get('host').getSelectedNodes()._nodes[0]; + if (element && element.nodeType && element.nodeType == 3) { + element = element.parentElement; + } + + if (typeof element === 'undefined') { + return ''; + } + + if (Y.one(element).hasClass('edusharing_atto')) { + return element; + } + + return ''; + }, + + handleUpdate: function () { + var selectedElement; + var node = []; + + selectedElement = this.getSelectedElement(); + + if (selectedElement) { + + if (selectedElement.nodeName.toLowerCase() == 'img') { + var query = selectedElement.getAttribute('src'); + } else { + var query = selectedElement.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + if (searchParams.get('mediatype') == 'folder') { + node.isDirectory = true; + } + if (searchParams.get('resourceId')) { + node.resid = searchParams.get('resourceId'); + } + node.title = searchParams.get('title'); + node.caption = searchParams.get('caption'); + node.properties = []; + if (searchParams.get('width')) { + node.properties['ccm:width'] = selectedElement.attributes.width.value; + } + if (selectedElement.attributes.height) { + node.properties['ccm:height'] = selectedElement.attributes.height.value; + } + node.objectUrl = searchParams.get('object_url'); + node.mimetype = searchParams.get('mimetype'); + node.mediatype = searchParams.get('mediatype'); + node.preview = []; + + if (this.getType(node.mediatype) == 'content') { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + + if (selectedElement.attributes.src) { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + node.properties['cclom:version'] = searchParams.get('window_version'); + node.alignment = selectedElement.style.float; + + this.updateDialog(node, true); + + return true; + } + return false; + }, + + /** + * Display the edusharing Dialogue + * + * @method _displayDialogue + */ + _displayDialogue: function (e, clickedicon) { + e.preventDefault(); + + var width = 800; + var height = 600; + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('dialogtitle', COMPONENTNAME), + width: width + 'px', + height: height + 'px', + focusAfterHide: clickedicon + }); + // Dialog doesn't detect changes in width without this. + // If you reuse the dialog, this seems necessary. + if (dialogue.width !== width + 'px') { + dialogue.set('width', width + 'px'); + } + + // Append buttons to iframe. + var buttonform = this._getFormContent(clickedicon); + var bodycontent = Y.Node.create('
'); + bodycontent.append(buttonform); + + // Set to bodycontent. + dialogue.set('bodyContent', bodycontent); + + var update = this.handleUpdate(); + + if (!update) { + Y.one('#edusharing_hint_logo').setAttribute('src', this.get('repourl') + '/assets/images/logo.svg'); + var that = this; + YUI().use('cookie', function (Y) { + if (Y.Cookie.get("edusharing_hint_hide")) { + // Open repository if user checked up. + that.open_repo(); + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + }); + } else { + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').removeAttribute('checked'); + }); + } + }); + } + + dialogue.show(); + this.markUpdated(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getFormContent: function (clickedicon) { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + component: COMPONENTNAME, + clickedicon: clickedicon, + })); + + this._form = content; + this._form.one('#edusharing_submit').on('click', this._doInsert, this); + this._form.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + this._form.one('#edusharing_hint_check').on('change', this.edusharing_hint_check_change, this); + this._form.one('#edusharing_open_repo').on('click', this.open_repo, this); + this._form.one('#edusharing_hint_close').on('click', this.closeDialog, this); + this._form.one('#edusharing_dialog_cancel').on('click', this.closeDialog, this); + this._form.one('#edusharing_width').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_width').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_title').on('keyup', this.recalculateTitleWidth, this); + + return content; + }, + + recalculateTitleWidth: function () { + Y.one('#edusharing_title_helper').setContent(Y.one('#edusharing_title').get('value')); + Y.one('#edusharing_title').setStyle('width', (Y.one('#edusharing_title_helper').get('offsetWidth') + 10) + 'px'); + }, + + closeDialog: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + }, + + open_repo: function () { + var url = this.get('repourl') + '/components/search?reurl=WINDOW&applyDirectories=true&ticket=' + this.get('ticket'); + window.win = window.open(url); + }, + + recalculateDimensions: function (e) { + if (e._currentTarget.id == 'edusharing_height') { + Y.one('#edusharing_width').set('value', Math.round(Y.one('#edusharing_height') + .get('value') * Y.one('#edusharing_ratio').get('value'))); + } else { + Y.one('#edusharing_height').set('value', Math.round(Y.one('#edusharing_width') + .get('value') / Y.one('#edusharing_ratio').get('value'))); + } + }, + + edusharing_hint_check_change: function (e) { + YUI().use('cookie', function (Y) { + if (e.target._stateProxy.checked) { + Y.Cookie.set("edusharing_hint_hide", true, {expires: new Date("January 12, 2025")}); + } else { + Y.Cookie.remove("edusharing_hint_hide"); + } + }); + }, + + /** + * Inserts the users input onto the page. + * @private + */ + + _doInsert: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + this.editor.focus(); + + var node = this.getNode(); + + // Update. + if (node.resid) { + var selectedElement = this.getSelectedElement(); + selectedElement.setAttribute('title', node.title); + + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + selectedElement.setAttribute('style', style); + if (this.getType(node.mediatype) == 'ref') { + const url = new URL(selectedElement.attributes.href.value); + selectedElement.innerHTML = node.title; + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + selectedElement.setAttribute('href', url.toString()); + } else { + const url = new URL(selectedElement.attributes.src.value); + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + url.searchParams.set('width', node.width); + url.searchParams.set('height', node.height); + selectedElement.setAttribute('alt', node.title); + selectedElement.setAttribute('width', node.width); + selectedElement.setAttribute('height', node.height); + selectedElement.setAttribute('src', url.toString()); + } + + } else { + // Insert. + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment + ';'; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + var version = '0'; + if (false == node.showlatest && node.version != 'undefined') { + version = node.version; + } + var insert = 'class="edusharing_atto" ' + + 'style="' + style + '" ' + + 'title="' + node.title + '" ' + + 'contenteditable="false" '; + + var url = node.previewurl + + '&caption=' + node.caption + + '&object_url=' + node.objecturl + + '&mediatype=' + node.mediatype + + '&mimetype=' + node.mimetype + + '&window_version=' + version + + '&title=' + node.title; + + var url = new URL(node.previewurl); + url.searchParams.set('caption', node.caption); + url.searchParams.set('object_url', node.objecturl); + url.searchParams.set('mediatype', node.mediatype); + url.searchParams.set('mimetype', node.mimetype); + url.searchParams.set('window_version', version); + url.searchParams.set('title', node.title); + + if (node.type == 'ref') { + insert = ' ' + node.title + ' '; + } else { + insert += 'src="' + url.toString() + + '&width=' + node.width + + '&height=' + node.height + '"'; + insert = '' + node.title + ''; + } + this.get('host').insertContentAtFocusPoint(insert); + } + this.markUpdated(); + }, + + getType: function (mediatype) { + var type = "ref"; + switch (true) { + case (mediatype.indexOf('image') > -1): + case (mediatype.indexOf('video') > -1): + case (mediatype.indexOf('h5p') > -1): + case (mediatype.indexOf('learningapps') > -1): + case (mediatype.indexOf('youtube') > -1): + case (mediatype.indexOf('vimeo') > -1): + case (mediatype.indexOf('folder') > -1): + + type = "content"; + break; + } + return type; + }, + + getNode: function () { + var n = {}; + n.resid = Y.one('#edusharing_resid').get('value'); + n.title = Y.one('#edusharing_title').get('value'); + n.caption = Y.one('#edusharing_caption').get('value'); + n.width = Y.one('#edusharing_width').get('value'); + n.height = Y.one('#edusharing_height').get('value'); + n.previewurl = Y.one('#edusharing_preview_url').get('value'); + n.objecturl = Y.one('#edusharing_object_url').get('value'); + n.mimetype = Y.one('#edusharing_mimetype').get('value'); + n.mediatype = Y.one('#edusharing_mediatype').get('value'); + n.showlatest = Y.one('#edusharing_version_latest').get('checked'); + n.version = Y.one('#edusharing_version').get('value'); + if (n.version == 'undefined') { + n.version = '0'; + } + n.alignment = Y.one('input[name=edusharing_alignment]:checked').get('value'); + n.type = this.getType(n.mediatype); + if (n.mediatype == 'folder') { + n.showlatest = true; + n.width = 500; + } + return n; + + } +}, { + ATTRS: { + disabled: { + value: false + }, + repourl: { + value: '' + }, + courseid: { + value: '' + }, + ticket: { + value: '' + }, + existingObjects: { + value: [] + } + } +}); + + +/** + * Define object-structure + * + * @param int course_id + */ +function edusharingObject(course_id) { + this.name = ''; + this.object_url = ''; + this.course = course_id; + this.id = ''; + this.object_version = '0'; +} + +/** + * Read object-data from node when editor loads content. + * + * @param DOMElement node + * + * @return bool + */ + +edusharingObject.prototype.importNode = function importNode(searchParams) { + + var name = searchParams.get('title'); + if (!name) { + return false; + } + this.name = name; + + var object_url = searchParams.get('object_url'); + if (!object_url) { + return false; + } + this.object_url = object_url; + + var resource_id = searchParams.get('resourceId'); + if (resource_id) { + this.id = resource_id; + } + + var object_version = searchParams.get('window_version'); + if (object_version) { + this.object_version = object_version; + } + return true; +}; + + +/** + * Link this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.link = function link(node) { + // Helper-url. + + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/insert.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + // Post data to ensure usage gets set. + var Y = YUI().use('io', 'json'); + + // Request-configuration. + var config = { + // POST data. + method: 'POST', + // Synchronous (blocking) request. + sync: true, + // Transmit data from form. + data: Y.JSON.stringify(object), + // Default arguments for callbacks. + arguments: {}, + + // Setup event-handling. + on: { + /* + * Request returned successfully + * + * Parse response. Create new element. Append it. + */ + success: function (transId, o, args) { + try { + var data = Y.JSON.parse(o.responseText); + } catch (exception) { + alert('invalid data'); + return false; + } + + // Import received data. + if (!data.id) { + alert('no resource id'); + return false; + } + + object.id = data.id; + + return true; + }, + + // Request failed. + failure: function (transId, o, args) { + alert('error setting usage'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; + +/** + * Unlink/delete this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.unlink = function unlink(node) { + // Tell moodle about deleted object. + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/delete.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + var Y = YUI().use('io', 'json', 'json-stringify'); + + var config = { + method: 'POST', + // Synchronous (blocking) request. + sync: true, + headers: {'Content-Type': 'application/json'}, + data: Y.JSON.stringify(object), + + arguments: { + object: object, + node: node + }, + + on: { + success: function (transId, o, args) { + return true; + }, + + failure: function (transId, o, args) { + alert('error deleting object' + ' ' + object.id + '.'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; + + +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-min.js b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-min.js new file mode 100644 index 0000000..5e13542 --- /dev/null +++ b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button-min.js @@ -0,0 +1,3 @@ +YUI.add("moodle-atto_edusharing-button",function(e,t){function i(e){this.name="",this.object_url="",this.course=e,this.id="",this.object_version="0"}var n="atto_edusharing",r='
'+'{{get_string "hint1" component}}

{{get_string "hint2" component}}'+'
'+'
'+'{{get_string "skipHint" component}}
'+'
'+'{{get_string "cancel" component}} '+'
'+"
"+'";e.namespace("M.atto_edusharing").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){if(this.get("disabled"))return;this.addButton({icon:"icon",iconComponent:"atto_edusharing",buttonName:"icon",callback:this._displayDialogue,callbackArgs:"icon",tags:".edusharing_atto",tagMatchRequiresAll:!1});var e=this.get("host").textarea.ancestor("form");e&&e.on("submit",this.eduSubmit,this),this.getExistingObjects();var t=this;window.addEventListener("message",function(e){if(e.data.event=="APPLY_NODE"){var n=e.data.data;window.win.close(),t.updateDialog(n)}},!1)},getUrlVars:function(e){var t={};e.startsWith("?")||(e="?"+e);var n=e.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(e,n,r){t[n]=r});return t},getExistingObjects:function(){var t=this.get("host").textarea.get("value"),n=document.createElement("div");n.innerHTML=t;var r=[n];while(0");a.append(u),o.set("bodyContent",a);var f=this.handleUpdate();if(!f){e.one("#edusharing_hint_logo").setAttribute("src",this.get("repourl")+"/assets/images/logo.svg");var l=this;YUI().use("cookie",function(e){e.Cookie.get("edusharing_hint_hide")?(l.open_repo(),YUI().use("node",function(e){e.one("#edusharing_hint_check").setAttribute("checked","checked")})):YUI().use("node",function(e){e.one("#edusharing_hint_check").removeAttribute("checked")})})}o.show(),this.markUpdated()},_getFormContent:function(t){var i=e.Handlebars.compile(r),s=e.Node.create(i({component:n,clickedicon:t}));return this._form=s,this._form.one("#edusharing_submit").on("click",this._doInsert,this),this._form.one("#edusharing_hint_check").setAttribute("checked","checked"),this._form.one("#edusharing_hint_check").on("change",this.edusharing_hint_check_change,this),this._form.one("#edusharing_open_repo").on("click",this.open_repo,this),this._form.one("#edusharing_hint_close").on("click",this.closeDialog,this),this._form.one("#edusharing_dialog_cancel").on("click",this.closeDialog,this),this._form.one("#edusharing_width").on("change",this.recalculateDimensions,this),this._form.one("#edusharing_width").on("keyup",this.recalculateDimensions,this),this._form.one("#edusharing_height").on("change",this.recalculateDimensions,this),this._form.one("#edusharing_height").on("keyup",this.recalculateDimensions,this),this._form.one("#edusharing_title").on("keyup",this.recalculateTitleWidth,this),s},recalculateTitleWidth:function( +){e.one("#edusharing_title_helper").setContent(e.one("#edusharing_title").get("value")),e.one("#edusharing_title").setStyle("width",e.one("#edusharing_title_helper").get("offsetWidth")+10+"px")},closeDialog:function(e){e.preventDefault(),this.getDialogue({focusAfterHide:null}).hide()},open_repo:function(){var e=this.get("repourl")+"/components/search?reurl=WINDOW&applyDirectories=true&ticket="+this.get("ticket");window.win=window.open(e)},recalculateDimensions:function(t){t._currentTarget.id=="edusharing_height"?e.one("#edusharing_width").set("value",Math.round(e.one("#edusharing_height").get("value")*e.one("#edusharing_ratio").get("value"))):e.one("#edusharing_height").set("value",Math.round(e.one("#edusharing_width").get("value")/e.one("#edusharing_ratio").get("value")))},edusharing_hint_check_change:function(e){YUI().use("cookie",function(t){e.target._stateProxy.checked?t.Cookie.set("edusharing_hint_hide",!0,{expires:new Date("January 12, 2025")}):t.Cookie.remove("edusharing_hint_hide")})},_doInsert:function(e){e.preventDefault(),this.getDialogue({focusAfterHide:null}).hide(),this.editor.focus();var t=this.getNode();if(t.resid){var n=this.getSelectedElement();n.setAttribute("title",t.title);var r="";t.alignment!="none"&&(r="float:"+t.alignment),t.mediatype=="folder"&&(r="display:block;"),n.setAttribute("style",r);if(this.getType(t.mediatype)=="ref"){const i=new URL(n.attributes.href.value);n.innerHTML=t.title,i.searchParams.set("title",t.title),i.searchParams.set("caption",t.caption),n.setAttribute("href",i.toString())}else{const i=new URL(n.attributes.src.value);i.searchParams.set("title",t.title),i.searchParams.set("caption",t.caption),i.searchParams.set("width",t.width),i.searchParams.set("height",t.height),n.setAttribute("alt",t.title),n.setAttribute("width",t.width),n.setAttribute("height",t.height),n.setAttribute("src",i.toString())}}else{var r="";t.alignment!="none"&&(r="float:"+t.alignment+";"),t.mediatype=="folder"&&(r="display:block;");var s="0";0==t.showlatest&&t.version!="undefined"&&(s=t.version);var o='class="edusharing_atto" style="'+r+'" '+'title="'+t.title+'" '+'contenteditable="false" ',i=t.previewurl+"&caption="+t.caption+"&object_url="+t.objecturl+"&mediatype="+t.mediatype+"&mimetype="+t.mimetype+"&window_version="+s+"&title="+t.title,i=new URL(t.previewurl);i.searchParams.set("caption",t.caption),i.searchParams.set("object_url",t.objecturl),i.searchParams.set("mediatype",t.mediatype),i.searchParams.set("mimetype",t.mimetype),i.searchParams.set("window_version",s),i.searchParams.set("title",t.title),t.type=="ref"?o=" '+t.title+" ":(o+='src="'+i.toString()+"&width="+t.width+"&height="+t.height+'"',o=''+t.title+'"),this.get("host").insertContentAtFocusPoint(o)}this.markUpdated()},getType:function(e){var t="ref";switch(!0){case e.indexOf("image")>-1:case e.indexOf("video")>-1:case e.indexOf("h5p")>-1:case e.indexOf("learningapps")>-1:case e.indexOf("youtube")>-1:case e.indexOf("vimeo")>-1:case e.indexOf("folder")>-1:t="content"}return t},getNode:function(){var t={};return t.resid=e.one("#edusharing_resid").get("value"),t.title=e.one("#edusharing_title").get("value"),t.caption=e.one("#edusharing_caption").get("value"),t.width=e.one("#edusharing_width").get("value"),t.height=e.one("#edusharing_height").get("value"),t.previewurl=e.one("#edusharing_preview_url").get("value"),t.objecturl=e.one("#edusharing_object_url").get("value"),t.mimetype=e.one("#edusharing_mimetype").get("value"),t.mediatype=e.one("#edusharing_mediatype").get("value"),t.showlatest=e.one("#edusharing_version_latest").get("checked"),t.version=e.one("#edusharing_version").get("value"),t.version=="undefined"&&(t.version="0"),t.alignment=e.one("input[name=edusharing_alignment]:checked").get("value"),t.type=this.getType(t.mediatype),t.mediatype=="folder"&&(t.showlatest=!0,t.width=500),t}},{ATTRS:{disabled:{value:!1},repourl:{value:""},courseid:{value:""},ticket:{value:""},existingObjects:{value:[]}}}),i.prototype.importNode=function(t){var n=t.get("title");if(!n)return!1;this.name=n;var r=t.get("object_url");if(!r)return!1;this.object_url=r;var i=t.get("resourceId");i&&(this.id=i);var s=t.get("window_version");return s&&(this.object_version=s),!0},i.prototype.link=function(t){var n=M.cfg.wwwroot+"/lib/editor/atto/plugins/edusharing/insert.php?sesskey="+M.cfg.sesskey,r=this,i=YUI().use("io","json"),s={method:"POST",sync:!0,data:i.JSON.stringify(r),arguments:{},on:{success:function(e,t,n){try{var s=i.JSON.parse(t.responseText)}catch(o){return alert("invalid data"),!1}return s.id?(r.id=s.id,!0):(alert("no resource id"),!1)},failure:function(e,t,n){return alert("error setting usage"),!1}}};return i.io(n,s)},i.prototype.unlink=function(t){var n=M.cfg.wwwroot+"/lib/editor/atto/plugins/edusharing/delete.php?sesskey="+M.cfg.sesskey,r=this,i=YUI().use("io","json","json-stringify"),s={method:"POST",sync:!0,headers:{"Content-Type":"application/json"},data:i.JSON.stringify(r),arguments:{object:r,node:t},on:{success:function(e,t,n){return!0},failure:function(e,t,n){return alert("error deleting object "+r.id+"."),!1}}};return i.io(n,s)}},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button.js b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button.js new file mode 100644 index 0000000..e86f18c --- /dev/null +++ b/yui/build/moodle-atto_edusharing-button/moodle-atto_edusharing-button.js @@ -0,0 +1,838 @@ +YUI.add('moodle-atto_edusharing-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 . + +/* + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// build yui with the command: shifter + +/** + * @module moodle-atto_edusharing-button + */ + +/** + * Atto text editor edusharing plugin. + * + * @namespace M.atto_edusharing + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_edusharing'; + +var TEMPLATE = '
' + + '' + + '' + + '{{get_string "hint1" component}}

{{get_string "hint2" component}}' + + '
' + + '
' + + '{{get_string "skipHint" component}}
' + + '
' + + '{{get_string "cancel" component}} ' + + '
' + + '
' + + ''; + +Y.namespace('M.atto_edusharing').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * Initialize the button + * + * @method Initializer + */ + initializer: function () { + // If we don't have the capability to view then give up. + if (this.get('disabled')) { + return; + } + this.addButton({ + icon: 'icon', + iconComponent: 'atto_edusharing', + buttonName: 'icon', + callback: this._displayDialogue, + callbackArgs: 'icon', + tags: '.edusharing_atto', + tagMatchRequiresAll: false + }); + + // Attach a submit listener to the form. + var form = this.get('host').textarea.ancestor('form'); + if (form) { + form.on('submit', this.eduSubmit, this); + } + + this.getExistingObjects(); + + var that = this; + window.addEventListener("message", function (event) { + if (event.data.event == "APPLY_NODE") { + var node = event.data.data; + window.win.close(); + that.updateDialog(node); + } + }, false); + }, + + getUrlVars: function (query) { + var vars = {}; + if (!query.startsWith('?')) { + query = '?' + query; + } + var parts = query.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { + vars[key] = value; + }); + return vars; + }, + + getExistingObjects: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + var nodes = [container]; + while (0 < nodes.length) { + var node = nodes.shift(); + // Is ELEMENT_NODE? + if (1 == node.nodeType) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var object = new edusharingObject(this.get('courseid')); + if (object.importNode(searchParams)) { + this.get('existingObjects')[object.id] = object; + } else { + alert('error_importing_node - 1'); + node.parentNode.removeChild(node); + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + }, + + updateDialog: function (node, update) { + Y.one('#edusharing_form').set('style', 'display:block'); + Y.one('#edusharing_hint').set('style', 'display:none'); + + if (node.isDirectory) { + Y.one('#edusharing_wrapper_dimensions').set('style', 'display:none'); + Y.one('#edusharing_version_latest').set('style', 'visibility:hidden'); + Y.one('#edusharing_version_latest_label').set('style', 'visibility:hidden'); + Y.one('#edusharing_wrapper_alignment').set('style', 'visibility:hidden'); + Y.one('#edusharing_hint_directory').set('style', 'display:block'); + } else if (this.getType(node.mediatype) == "ref") { + Y.one('#edusharing_wrapper_dimensions').set('style', 'visibility:hidden'); + } else { + var width = Math.round(node.properties['ccm:width']) || 600; + var height = Math.round(node.properties['ccm:height']) || 400; + Y.one('#edusharing_width').set('value', width); + Y.one('#edusharing_height').set('value', height); + Y.one('#edusharing_ratio').set('value', width / height); + } + + Y.one('#edusharing_title').set('value', node.title || node.name); + Y.one('#edusharing_caption').set('value', node.caption || ''); + Y.one('#edusharing_object_url').set('value', node.objectUrl); + Y.one('#edusharing_mimetype').set('value', node.mimetype); + Y.one('#edusharing_mediatype').set('value', node.mediatype); + Y.one('#edusharing_preview_url').set('value', node.preview.url); + Y.one('#edusharing_preview').set('src', node.preview.url); + Y.one('#edusharing_version').set('value', node.properties['cclom:version']); + + if (update) { + Y.one('#edusharing_resid').set('value', node.resid); + Y.one('#edusharing_version_latest').set('style', 'display:none'); + Y.one('#edusharing_version_latest_label').set('style', 'display:none'); + Y.one('#edusharing_submit').setContent(M.util.get_string('update', COMPONENTNAME)); + if (node.alignment) { + Y.one('#edusharing_alignment_none').set('checked', false); + Y.one('#edusharing_alignment_' + node.alignment).set('checked', true); + } else { + Y.one('#edusharing_alignment_none').set('checked', true); + Y.one('#edusharing_alignment_right').set('checked', false); + Y.one('#edusharing_alignment_left').set('checked', false); + } + } + }, + + eduSubmit: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + + var nodes = [container]; + + while (0 < nodes.length) { + var node = nodes.shift(); + if (node.nodeType == 1) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var resource_id = searchParams.get('resourceId'); + if (resource_id && this.get('existingObjects')[resource_id]) { + delete this.get('existingObjects')[resource_id]; + } else { + var object = new edusharingObject(this.get('courseid')); + if (!object.importNode(searchParams)) { + alert('error_importing_node - 2'); + } + if (!object.link(node)) { + alert('error_setting_usage'); + node.parentNode.removeChild(node); + } + + if (node.nodeName.toLowerCase() == 'img') { + node.setAttribute('src', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } else { + node.setAttribute('href', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + + // The remaining known objects can be deleted. + for (var resource_id in this.get('existingObjects')) { + var remainder = this.get('existingObjects')[resource_id]; + if (!remainder.unlink(node)) { + alert('error_deleting_usage'); + } + } + + this.get('host').textarea.set('value', container.innerHTML); + }, + + getQueryStringFromParams: function (params) { + var out = []; + for (var key in params) { + out.push(key + '=' + params[key]); + } + return out.join('&'); + }, + + getPreviewUrl: function (resourceId) { + var previewUrl = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/preview.php'; + previewUrl += '?resourceId=' + resourceId; + return previewUrl; + }, + + getSelectedElement: function () { + var element = this.get('host').getSelectedNodes()._nodes[0]; + if (element && element.nodeType && element.nodeType == 3) { + element = element.parentElement; + } + + if (typeof element === 'undefined') { + return ''; + } + + if (Y.one(element).hasClass('edusharing_atto')) { + return element; + } + + return ''; + }, + + handleUpdate: function () { + var selectedElement; + var node = []; + + selectedElement = this.getSelectedElement(); + + if (selectedElement) { + + if (selectedElement.nodeName.toLowerCase() == 'img') { + var query = selectedElement.getAttribute('src'); + } else { + var query = selectedElement.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + if (searchParams.get('mediatype') == 'folder') { + node.isDirectory = true; + } + if (searchParams.get('resourceId')) { + node.resid = searchParams.get('resourceId'); + } + node.title = searchParams.get('title'); + node.caption = searchParams.get('caption'); + node.properties = []; + if (searchParams.get('width')) { + node.properties['ccm:width'] = selectedElement.attributes.width.value; + } + if (selectedElement.attributes.height) { + node.properties['ccm:height'] = selectedElement.attributes.height.value; + } + node.objectUrl = searchParams.get('object_url'); + node.mimetype = searchParams.get('mimetype'); + node.mediatype = searchParams.get('mediatype'); + node.preview = []; + + if (this.getType(node.mediatype) == 'content') { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + + if (selectedElement.attributes.src) { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + node.properties['cclom:version'] = searchParams.get('window_version'); + node.alignment = selectedElement.style.float; + + this.updateDialog(node, true); + + return true; + } + return false; + }, + + /** + * Display the edusharing Dialogue + * + * @method _displayDialogue + */ + _displayDialogue: function (e, clickedicon) { + e.preventDefault(); + + var width = 800; + var height = 600; + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('dialogtitle', COMPONENTNAME), + width: width + 'px', + height: height + 'px', + focusAfterHide: clickedicon + }); + // Dialog doesn't detect changes in width without this. + // If you reuse the dialog, this seems necessary. + if (dialogue.width !== width + 'px') { + dialogue.set('width', width + 'px'); + } + + // Append buttons to iframe. + var buttonform = this._getFormContent(clickedicon); + var bodycontent = Y.Node.create('
'); + bodycontent.append(buttonform); + + // Set to bodycontent. + dialogue.set('bodyContent', bodycontent); + + var update = this.handleUpdate(); + + if (!update) { + Y.one('#edusharing_hint_logo').setAttribute('src', this.get('repourl') + '/assets/images/logo.svg'); + var that = this; + YUI().use('cookie', function (Y) { + if (Y.Cookie.get("edusharing_hint_hide")) { + // Open repository if user checked up. + that.open_repo(); + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + }); + } else { + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').removeAttribute('checked'); + }); + } + }); + } + + dialogue.show(); + this.markUpdated(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getFormContent: function (clickedicon) { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + component: COMPONENTNAME, + clickedicon: clickedicon, + })); + + this._form = content; + this._form.one('#edusharing_submit').on('click', this._doInsert, this); + this._form.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + this._form.one('#edusharing_hint_check').on('change', this.edusharing_hint_check_change, this); + this._form.one('#edusharing_open_repo').on('click', this.open_repo, this); + this._form.one('#edusharing_hint_close').on('click', this.closeDialog, this); + this._form.one('#edusharing_dialog_cancel').on('click', this.closeDialog, this); + this._form.one('#edusharing_width').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_width').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_title').on('keyup', this.recalculateTitleWidth, this); + + return content; + }, + + recalculateTitleWidth: function () { + Y.one('#edusharing_title_helper').setContent(Y.one('#edusharing_title').get('value')); + Y.one('#edusharing_title').setStyle('width', (Y.one('#edusharing_title_helper').get('offsetWidth') + 10) + 'px'); + }, + + closeDialog: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + }, + + open_repo: function () { + var url = this.get('repourl') + '/components/search?reurl=WINDOW&applyDirectories=true&ticket=' + this.get('ticket'); + window.win = window.open(url); + }, + + recalculateDimensions: function (e) { + if (e._currentTarget.id == 'edusharing_height') { + Y.one('#edusharing_width').set('value', Math.round(Y.one('#edusharing_height') + .get('value') * Y.one('#edusharing_ratio').get('value'))); + } else { + Y.one('#edusharing_height').set('value', Math.round(Y.one('#edusharing_width') + .get('value') / Y.one('#edusharing_ratio').get('value'))); + } + }, + + edusharing_hint_check_change: function (e) { + YUI().use('cookie', function (Y) { + if (e.target._stateProxy.checked) { + Y.Cookie.set("edusharing_hint_hide", true, {expires: new Date("January 12, 2025")}); + } else { + Y.Cookie.remove("edusharing_hint_hide"); + } + }); + }, + + /** + * Inserts the users input onto the page. + * @private + */ + + _doInsert: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + this.editor.focus(); + + var node = this.getNode(); + + // Update. + if (node.resid) { + var selectedElement = this.getSelectedElement(); + selectedElement.setAttribute('title', node.title); + + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + selectedElement.setAttribute('style', style); + if (this.getType(node.mediatype) == 'ref') { + const url = new URL(selectedElement.attributes.href.value); + selectedElement.innerHTML = node.title; + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + selectedElement.setAttribute('href', url.toString()); + } else { + const url = new URL(selectedElement.attributes.src.value); + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + url.searchParams.set('width', node.width); + url.searchParams.set('height', node.height); + selectedElement.setAttribute('alt', node.title); + selectedElement.setAttribute('width', node.width); + selectedElement.setAttribute('height', node.height); + selectedElement.setAttribute('src', url.toString()); + } + + } else { + // Insert. + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment + ';'; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + var version = '0'; + if (false == node.showlatest && node.version != 'undefined') { + version = node.version; + } + var insert = 'class="edusharing_atto" ' + + 'style="' + style + '" ' + + 'title="' + node.title + '" ' + + 'contenteditable="false" '; + + var url = node.previewurl + + '&caption=' + node.caption + + '&object_url=' + node.objecturl + + '&mediatype=' + node.mediatype + + '&mimetype=' + node.mimetype + + '&window_version=' + version + + '&title=' + node.title; + + var url = new URL(node.previewurl); + url.searchParams.set('caption', node.caption); + url.searchParams.set('object_url', node.objecturl); + url.searchParams.set('mediatype', node.mediatype); + url.searchParams.set('mimetype', node.mimetype); + url.searchParams.set('window_version', version); + url.searchParams.set('title', node.title); + + if (node.type == 'ref') { + insert = ' ' + node.title + ' '; + } else { + insert += 'src="' + url.toString() + + '&width=' + node.width + + '&height=' + node.height + '"'; + insert = '' + node.title + ''; + } + this.get('host').insertContentAtFocusPoint(insert); + } + this.markUpdated(); + }, + + getType: function (mediatype) { + var type = "ref"; + switch (true) { + case (mediatype.indexOf('image') > -1): + case (mediatype.indexOf('video') > -1): + case (mediatype.indexOf('h5p') > -1): + case (mediatype.indexOf('learningapps') > -1): + case (mediatype.indexOf('youtube') > -1): + case (mediatype.indexOf('vimeo') > -1): + case (mediatype.indexOf('folder') > -1): + + type = "content"; + break; + } + return type; + }, + + getNode: function () { + var n = {}; + n.resid = Y.one('#edusharing_resid').get('value'); + n.title = Y.one('#edusharing_title').get('value'); + n.caption = Y.one('#edusharing_caption').get('value'); + n.width = Y.one('#edusharing_width').get('value'); + n.height = Y.one('#edusharing_height').get('value'); + n.previewurl = Y.one('#edusharing_preview_url').get('value'); + n.objecturl = Y.one('#edusharing_object_url').get('value'); + n.mimetype = Y.one('#edusharing_mimetype').get('value'); + n.mediatype = Y.one('#edusharing_mediatype').get('value'); + n.showlatest = Y.one('#edusharing_version_latest').get('checked'); + n.version = Y.one('#edusharing_version').get('value'); + if (n.version == 'undefined') { + n.version = '0'; + } + n.alignment = Y.one('input[name=edusharing_alignment]:checked').get('value'); + n.type = this.getType(n.mediatype); + if (n.mediatype == 'folder') { + n.showlatest = true; + n.width = 500; + } + return n; + + } +}, { + ATTRS: { + disabled: { + value: false + }, + repourl: { + value: '' + }, + courseid: { + value: '' + }, + ticket: { + value: '' + }, + existingObjects: { + value: [] + } + } +}); + + +/** + * Define object-structure + * + * @param int course_id + */ +function edusharingObject(course_id) { + this.name = ''; + this.object_url = ''; + this.course = course_id; + this.id = ''; + this.object_version = '0'; +} + +/** + * Read object-data from node when editor loads content. + * + * @param DOMElement node + * + * @return bool + */ + +edusharingObject.prototype.importNode = function importNode(searchParams) { + + var name = searchParams.get('title'); + if (!name) { + return false; + } + this.name = name; + + var object_url = searchParams.get('object_url'); + if (!object_url) { + return false; + } + this.object_url = object_url; + + var resource_id = searchParams.get('resourceId'); + if (resource_id) { + this.id = resource_id; + } + + var object_version = searchParams.get('window_version'); + if (object_version) { + this.object_version = object_version; + } + return true; +}; + + +/** + * Link this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.link = function link(node) { + // Helper-url. + + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/insert.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + // Post data to ensure usage gets set. + var Y = YUI().use('io', 'json'); + + // Request-configuration. + var config = { + // POST data. + method: 'POST', + // Synchronous (blocking) request. + sync: true, + // Transmit data from form. + data: Y.JSON.stringify(object), + // Default arguments for callbacks. + arguments: {}, + + // Setup event-handling. + on: { + /* + * Request returned successfully + * + * Parse response. Create new element. Append it. + */ + success: function (transId, o, args) { + try { + var data = Y.JSON.parse(o.responseText); + } catch (exception) { + alert('invalid data'); + return false; + } + + // Import received data. + if (!data.id) { + alert('no resource id'); + return false; + } + + object.id = data.id; + + return true; + }, + + // Request failed. + failure: function (transId, o, args) { + alert('error setting usage'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; + +/** + * Unlink/delete this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.unlink = function unlink(node) { + // Tell moodle about deleted object. + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/delete.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + var Y = YUI().use('io', 'json', 'json-stringify'); + + var config = { + method: 'POST', + // Synchronous (blocking) request. + sync: true, + headers: {'Content-Type': 'application/json'}, + data: Y.JSON.stringify(object), + + arguments: { + object: object, + node: node + }, + + on: { + success: function (transId, o, args) { + return true; + }, + + failure: function (transId, o, args) { + alert('error deleting object' + ' ' + object.id + '.'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; + + +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/yui/src/button/build.json b/yui/src/button/build.json new file mode 100644 index 0000000..c487ced --- /dev/null +++ b/yui/src/button/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-atto_edusharing-button", + "builds": { + "moodle-atto_edusharing-button": { + "jsfiles": [ + "button.js" + ] + } + } +} diff --git a/yui/src/button/js/button.js b/yui/src/button/js/button.js new file mode 100644 index 0000000..9879e0a --- /dev/null +++ b/yui/src/button/js/button.js @@ -0,0 +1,833 @@ +// 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 . + +/* + * @package atto_edusharing + * @copyright COPYRIGHTINFO + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// build yui with the command: shifter + +/** + * @module moodle-atto_edusharing-button + */ + +/** + * Atto text editor edusharing plugin. + * + * @namespace M.atto_edusharing + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_edusharing'; + +var TEMPLATE = '
' + + '' + + '' + + '{{get_string "hint1" component}}

{{get_string "hint2" component}}' + + '
' + + '
' + + '{{get_string "skipHint" component}}
' + + '
' + + '{{get_string "cancel" component}} ' + + '
' + + '
' + + ''; + +Y.namespace('M.atto_edusharing').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * Initialize the button + * + * @method Initializer + */ + initializer: function () { + // If we don't have the capability to view then give up. + if (this.get('disabled')) { + return; + } + this.addButton({ + icon: 'icon', + iconComponent: 'atto_edusharing', + buttonName: 'icon', + callback: this._displayDialogue, + callbackArgs: 'icon', + tags: '.edusharing_atto', + tagMatchRequiresAll: false + }); + + // Attach a submit listener to the form. + var form = this.get('host').textarea.ancestor('form'); + if (form) { + form.on('submit', this.eduSubmit, this); + } + + this.getExistingObjects(); + + var that = this; + window.addEventListener("message", function (event) { + if (event.data.event == "APPLY_NODE") { + var node = event.data.data; + window.win.close(); + that.updateDialog(node); + } + }, false); + }, + + getUrlVars: function (query) { + var vars = {}; + if (!query.startsWith('?')) { + query = '?' + query; + } + var parts = query.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { + vars[key] = value; + }); + return vars; + }, + + getExistingObjects: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + var nodes = [container]; + while (0 < nodes.length) { + var node = nodes.shift(); + // Is ELEMENT_NODE? + if (1 == node.nodeType) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var object = new edusharingObject(this.get('courseid')); + if (object.importNode(searchParams)) { + this.get('existingObjects')[object.id] = object; + } else { + alert('error_importing_node - 1'); + node.parentNode.removeChild(node); + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + }, + + updateDialog: function (node, update) { + Y.one('#edusharing_form').set('style', 'display:block'); + Y.one('#edusharing_hint').set('style', 'display:none'); + + if (node.isDirectory) { + Y.one('#edusharing_wrapper_dimensions').set('style', 'display:none'); + Y.one('#edusharing_version_latest').set('style', 'visibility:hidden'); + Y.one('#edusharing_version_latest_label').set('style', 'visibility:hidden'); + Y.one('#edusharing_wrapper_alignment').set('style', 'visibility:hidden'); + Y.one('#edusharing_hint_directory').set('style', 'display:block'); + } else if (this.getType(node.mediatype) == "ref") { + Y.one('#edusharing_wrapper_dimensions').set('style', 'visibility:hidden'); + } else { + var width = Math.round(node.properties['ccm:width']) || 600; + var height = Math.round(node.properties['ccm:height']) || 400; + Y.one('#edusharing_width').set('value', width); + Y.one('#edusharing_height').set('value', height); + Y.one('#edusharing_ratio').set('value', width / height); + } + + Y.one('#edusharing_title').set('value', node.title || node.name); + Y.one('#edusharing_caption').set('value', node.caption || ''); + Y.one('#edusharing_object_url').set('value', node.objectUrl); + Y.one('#edusharing_mimetype').set('value', node.mimetype); + Y.one('#edusharing_mediatype').set('value', node.mediatype); + Y.one('#edusharing_preview_url').set('value', node.preview.url); + Y.one('#edusharing_preview').set('src', node.preview.url); + Y.one('#edusharing_version').set('value', node.properties['cclom:version']); + + if (update) { + Y.one('#edusharing_resid').set('value', node.resid); + Y.one('#edusharing_version_latest').set('style', 'display:none'); + Y.one('#edusharing_version_latest_label').set('style', 'display:none'); + Y.one('#edusharing_submit').setContent(M.util.get_string('update', COMPONENTNAME)); + if (node.alignment) { + Y.one('#edusharing_alignment_none').set('checked', false); + Y.one('#edusharing_alignment_' + node.alignment).set('checked', true); + } else { + Y.one('#edusharing_alignment_none').set('checked', true); + Y.one('#edusharing_alignment_right').set('checked', false); + Y.one('#edusharing_alignment_left').set('checked', false); + } + } + }, + + eduSubmit: function () { + var content = this.get('host').textarea.get('value'); + var container = document.createElement('div'); + container.innerHTML = content; + + var nodes = [container]; + + while (0 < nodes.length) { + var node = nodes.shift(); + if (node.nodeType == 1) { + + if (Y.one(node).hasClass('edusharing_atto')) { + + if (node.nodeName.toLowerCase() == 'img') { + var query = node.getAttribute('src'); + } else { + var query = node.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + var resource_id = searchParams.get('resourceId'); + if (resource_id && this.get('existingObjects')[resource_id]) { + delete this.get('existingObjects')[resource_id]; + } else { + var object = new edusharingObject(this.get('courseid')); + if (!object.importNode(searchParams)) { + alert('error_importing_node - 2'); + } + if (!object.link(node)) { + alert('error_setting_usage'); + node.parentNode.removeChild(node); + } + + if (node.nodeName.toLowerCase() == 'img') { + node.setAttribute('src', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } else { + node.setAttribute('href', this.getPreviewUrl(object.id) + '&' + searchParams.toString()); + } + } + } + } + + // Stack child-nodes for further examination. + if (node.hasChildNodes()) { + child = 0; + while (child < node.childNodes.length) { + nodes.push(node.childNodes.item(child)); + child++; + } + } + } + + // The remaining known objects can be deleted. + for (var resource_id in this.get('existingObjects')) { + var remainder = this.get('existingObjects')[resource_id]; + if (!remainder.unlink(node)) { + alert('error_deleting_usage'); + } + } + + this.get('host').textarea.set('value', container.innerHTML); + }, + + getQueryStringFromParams: function (params) { + var out = []; + for (var key in params) { + out.push(key + '=' + params[key]); + } + return out.join('&'); + }, + + getPreviewUrl: function (resourceId) { + var previewUrl = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/preview.php'; + previewUrl += '?resourceId=' + resourceId; + return previewUrl; + }, + + getSelectedElement: function () { + var element = this.get('host').getSelectedNodes()._nodes[0]; + if (element && element.nodeType && element.nodeType == 3) { + element = element.parentElement; + } + + if (typeof element === 'undefined') { + return ''; + } + + if (Y.one(element).hasClass('edusharing_atto')) { + return element; + } + + return ''; + }, + + handleUpdate: function () { + var selectedElement; + var node = []; + + selectedElement = this.getSelectedElement(); + + if (selectedElement) { + + if (selectedElement.nodeName.toLowerCase() == 'img') { + var query = selectedElement.getAttribute('src'); + } else { + var query = selectedElement.getAttribute('href'); + } + + var href = new URL(query); + const searchParams = href.searchParams; + + if (searchParams.get('mediatype') == 'folder') { + node.isDirectory = true; + } + if (searchParams.get('resourceId')) { + node.resid = searchParams.get('resourceId'); + } + node.title = searchParams.get('title'); + node.caption = searchParams.get('caption'); + node.properties = []; + if (searchParams.get('width')) { + node.properties['ccm:width'] = selectedElement.attributes.width.value; + } + if (selectedElement.attributes.height) { + node.properties['ccm:height'] = selectedElement.attributes.height.value; + } + node.objectUrl = searchParams.get('object_url'); + node.mimetype = searchParams.get('mimetype'); + node.mediatype = searchParams.get('mediatype'); + node.preview = []; + + if (this.getType(node.mediatype) == 'content') { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + + if (selectedElement.attributes.src) { + node.preview.url = selectedElement.attributes.src.value; + } else { + node.preview.url = selectedElement.attributes.href.value; + } + node.properties['cclom:version'] = searchParams.get('window_version'); + node.alignment = selectedElement.style.float; + + this.updateDialog(node, true); + + return true; + } + return false; + }, + + /** + * Display the edusharing Dialogue + * + * @method _displayDialogue + */ + _displayDialogue: function (e, clickedicon) { + e.preventDefault(); + + var width = 800; + var height = 600; + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('dialogtitle', COMPONENTNAME), + width: width + 'px', + height: height + 'px', + focusAfterHide: clickedicon + }); + // Dialog doesn't detect changes in width without this. + // If you reuse the dialog, this seems necessary. + if (dialogue.width !== width + 'px') { + dialogue.set('width', width + 'px'); + } + + // Append buttons to iframe. + var buttonform = this._getFormContent(clickedicon); + var bodycontent = Y.Node.create('
'); + bodycontent.append(buttonform); + + // Set to bodycontent. + dialogue.set('bodyContent', bodycontent); + + var update = this.handleUpdate(); + + if (!update) { + Y.one('#edusharing_hint_logo').setAttribute('src', this.get('repourl') + '/assets/images/logo.svg'); + var that = this; + YUI().use('cookie', function (Y) { + if (Y.Cookie.get("edusharing_hint_hide")) { + // Open repository if user checked up. + that.open_repo(); + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + }); + } else { + YUI().use('node', function (Y) { + Y.one('#edusharing_hint_check').removeAttribute('checked'); + }); + } + }); + } + + dialogue.show(); + this.markUpdated(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getFormContent: function (clickedicon) { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + component: COMPONENTNAME, + clickedicon: clickedicon, + })); + + this._form = content; + this._form.one('#edusharing_submit').on('click', this._doInsert, this); + this._form.one('#edusharing_hint_check').setAttribute('checked', 'checked'); + this._form.one('#edusharing_hint_check').on('change', this.edusharing_hint_check_change, this); + this._form.one('#edusharing_open_repo').on('click', this.open_repo, this); + this._form.one('#edusharing_hint_close').on('click', this.closeDialog, this); + this._form.one('#edusharing_dialog_cancel').on('click', this.closeDialog, this); + this._form.one('#edusharing_width').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_width').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('change', this.recalculateDimensions, this); + this._form.one('#edusharing_height').on('keyup', this.recalculateDimensions, this); + this._form.one('#edusharing_title').on('keyup', this.recalculateTitleWidth, this); + + return content; + }, + + recalculateTitleWidth: function () { + Y.one('#edusharing_title_helper').setContent(Y.one('#edusharing_title').get('value')); + Y.one('#edusharing_title').setStyle('width', (Y.one('#edusharing_title_helper').get('offsetWidth') + 10) + 'px'); + }, + + closeDialog: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + }, + + open_repo: function () { + var url = this.get('repourl') + '/components/search?reurl=WINDOW&applyDirectories=true&ticket=' + this.get('ticket'); + window.win = window.open(url); + }, + + recalculateDimensions: function (e) { + if (e._currentTarget.id == 'edusharing_height') { + Y.one('#edusharing_width').set('value', Math.round(Y.one('#edusharing_height') + .get('value') * Y.one('#edusharing_ratio').get('value'))); + } else { + Y.one('#edusharing_height').set('value', Math.round(Y.one('#edusharing_width') + .get('value') / Y.one('#edusharing_ratio').get('value'))); + } + }, + + edusharing_hint_check_change: function (e) { + YUI().use('cookie', function (Y) { + if (e.target._stateProxy.checked) { + Y.Cookie.set("edusharing_hint_hide", true, {expires: new Date("January 12, 2025")}); + } else { + Y.Cookie.remove("edusharing_hint_hide"); + } + }); + }, + + /** + * Inserts the users input onto the page. + * @private + */ + + _doInsert: function (e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + this.editor.focus(); + + var node = this.getNode(); + + // Update. + if (node.resid) { + var selectedElement = this.getSelectedElement(); + selectedElement.setAttribute('title', node.title); + + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + selectedElement.setAttribute('style', style); + if (this.getType(node.mediatype) == 'ref') { + const url = new URL(selectedElement.attributes.href.value); + selectedElement.innerHTML = node.title; + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + selectedElement.setAttribute('href', url.toString()); + } else { + const url = new URL(selectedElement.attributes.src.value); + url.searchParams.set('title', node.title); + url.searchParams.set('caption', node.caption); + url.searchParams.set('width', node.width); + url.searchParams.set('height', node.height); + selectedElement.setAttribute('alt', node.title); + selectedElement.setAttribute('width', node.width); + selectedElement.setAttribute('height', node.height); + selectedElement.setAttribute('src', url.toString()); + } + + } else { + // Insert. + var style = ''; + if (node.alignment != 'none') { + style = 'float:' + node.alignment + ';'; + } + if (node.mediatype == 'folder') { + style = 'display:block;'; + } + var version = '0'; + if (false == node.showlatest && node.version != 'undefined') { + version = node.version; + } + var insert = 'class="edusharing_atto" ' + + 'style="' + style + '" ' + + 'title="' + node.title + '" ' + + 'contenteditable="false" '; + + var url = node.previewurl + + '&caption=' + node.caption + + '&object_url=' + node.objecturl + + '&mediatype=' + node.mediatype + + '&mimetype=' + node.mimetype + + '&window_version=' + version + + '&title=' + node.title; + + var url = new URL(node.previewurl); + url.searchParams.set('caption', node.caption); + url.searchParams.set('object_url', node.objecturl); + url.searchParams.set('mediatype', node.mediatype); + url.searchParams.set('mimetype', node.mimetype); + url.searchParams.set('window_version', version); + url.searchParams.set('title', node.title); + + if (node.type == 'ref') { + insert = ' ' + node.title + ' '; + } else { + insert += 'src="' + url.toString() + + '&width=' + node.width + + '&height=' + node.height + '"'; + insert = '' + node.title + ''; + } + this.get('host').insertContentAtFocusPoint(insert); + } + this.markUpdated(); + }, + + getType: function (mediatype) { + var type = "ref"; + switch (true) { + case (mediatype.indexOf('image') > -1): + case (mediatype.indexOf('video') > -1): + case (mediatype.indexOf('h5p') > -1): + case (mediatype.indexOf('learningapps') > -1): + case (mediatype.indexOf('youtube') > -1): + case (mediatype.indexOf('vimeo') > -1): + case (mediatype.indexOf('folder') > -1): + + type = "content"; + break; + } + return type; + }, + + getNode: function () { + var n = {}; + n.resid = Y.one('#edusharing_resid').get('value'); + n.title = Y.one('#edusharing_title').get('value'); + n.caption = Y.one('#edusharing_caption').get('value'); + n.width = Y.one('#edusharing_width').get('value'); + n.height = Y.one('#edusharing_height').get('value'); + n.previewurl = Y.one('#edusharing_preview_url').get('value'); + n.objecturl = Y.one('#edusharing_object_url').get('value'); + n.mimetype = Y.one('#edusharing_mimetype').get('value'); + n.mediatype = Y.one('#edusharing_mediatype').get('value'); + n.showlatest = Y.one('#edusharing_version_latest').get('checked'); + n.version = Y.one('#edusharing_version').get('value'); + if (n.version == 'undefined') { + n.version = '0'; + } + n.alignment = Y.one('input[name=edusharing_alignment]:checked').get('value'); + n.type = this.getType(n.mediatype); + if (n.mediatype == 'folder') { + n.showlatest = true; + n.width = 500; + } + return n; + + } +}, { + ATTRS: { + disabled: { + value: false + }, + repourl: { + value: '' + }, + courseid: { + value: '' + }, + ticket: { + value: '' + }, + existingObjects: { + value: [] + } + } +}); + + +/** + * Define object-structure + * + * @param int course_id + */ +function edusharingObject(course_id) { + this.name = ''; + this.object_url = ''; + this.course = course_id; + this.id = ''; + this.object_version = '0'; +} + +/** + * Read object-data from node when editor loads content. + * + * @param DOMElement node + * + * @return bool + */ + +edusharingObject.prototype.importNode = function importNode(searchParams) { + + var name = searchParams.get('title'); + if (!name) { + return false; + } + this.name = name; + + var object_url = searchParams.get('object_url'); + if (!object_url) { + return false; + } + this.object_url = object_url; + + var resource_id = searchParams.get('resourceId'); + if (resource_id) { + this.id = resource_id; + } + + var object_version = searchParams.get('window_version'); + if (object_version) { + this.object_version = object_version; + } + return true; +}; + + +/** + * Link this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.link = function link(node) { + // Helper-url. + + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/insert.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + // Post data to ensure usage gets set. + var Y = YUI().use('io', 'json'); + + // Request-configuration. + var config = { + // POST data. + method: 'POST', + // Synchronous (blocking) request. + sync: true, + // Transmit data from form. + data: Y.JSON.stringify(object), + // Default arguments for callbacks. + arguments: {}, + + // Setup event-handling. + on: { + /* + * Request returned successfully + * + * Parse response. Create new element. Append it. + */ + success: function (transId, o, args) { + try { + var data = Y.JSON.parse(o.responseText); + } catch (exception) { + alert('invalid data'); + return false; + } + + // Import received data. + if (!data.id) { + alert('no resource id'); + return false; + } + + object.id = data.id; + + return true; + }, + + // Request failed. + failure: function (transId, o, args) { + alert('error setting usage'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; + +/** + * Unlink/delete this object. + * + * @param node + * + * @return bool + */ +edusharingObject.prototype.unlink = function unlink(node) { + // Tell moodle about deleted object. + var helper_url = M.cfg.wwwroot + '/lib/editor/atto/plugins/edusharing/delete.php?sesskey=' + M.cfg.sesskey; + + // Bind object for context. + var object = this; + + var Y = YUI().use('io', 'json', 'json-stringify'); + + var config = { + method: 'POST', + // Synchronous (blocking) request. + sync: true, + headers: {'Content-Type': 'application/json'}, + data: Y.JSON.stringify(object), + + arguments: { + object: object, + node: node + }, + + on: { + success: function (transId, o, args) { + return true; + }, + + failure: function (transId, o, args) { + alert('error deleting object' + ' ' + object.id + '.'); + return false; + } + } + }; + + return Y.io(helper_url, config); +}; diff --git a/yui/src/button/meta/button.json b/yui/src/button/meta/button.json new file mode 100644 index 0000000..6277953 --- /dev/null +++ b/yui/src/button/meta/button.json @@ -0,0 +1,7 @@ +{ + "moodle-atto_edusharing-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } +}