AutorÃa | Ultima modificación | Ver Log |
// 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/>./*** @module moodle-editor_atto-editor* @submodule styling*//*** Editor styling functions for the Atto editor.** See {{#crossLink "M.editor_atto.Editor"}}{{/crossLink}} for details.** @namespace M.editor_atto* @class EditorStyling*/function EditorStyling() {}EditorStyling.ATTRS = {};EditorStyling.prototype = {/*** Disable CSS styling.** @method disableCssStyling*/disableCssStyling: function() {try {document.execCommand("styleWithCSS", 0, false);} catch (e1) {try {document.execCommand("useCSS", 0, true);} catch (e2) {try {document.execCommand('styleWithCSS', false, false);} catch (e3) {// We did our best.}}}},/*** Enable CSS styling.** @method enableCssStyling*/enableCssStyling: function() {try {document.execCommand("styleWithCSS", 0, true);} catch (e1) {try {document.execCommand("useCSS", 0, false);} catch (e2) {try {document.execCommand('styleWithCSS', false, true);} catch (e3) {// We did our best.}}}},/*** Change the formatting for the current selection.** This will wrap the selection in span tags, adding the provided classes.** If the selection covers multiple block elements, multiple spans will be inserted to preserve the original structure.** @method toggleInlineSelectionClass* @param {Array} toggleclasses - Class names to be toggled on or off.*/toggleInlineSelectionClass: function(toggleclasses) {var classname = toggleclasses.join(" ");var cssApplier = rangy.createClassApplier(classname, {normalize: true});cssApplier.toggleSelection();},/*** Change the formatting for the current selection.** This will set inline styles on the current selection.** @method formatSelectionInlineStyle* @param {Array} styles - Style attributes to set on the nodes.*/formatSelectionInlineStyle: function(styles) {var classname = this.PLACEHOLDER_CLASS;var cssApplier = rangy.createClassApplier(classname, {normalize: true});cssApplier.applyToSelection();this.editor.all('.' + classname).each(function(node) {node.removeClass(classname).setStyles(styles);}, this);},/*** Change the formatting for the current selection.** Also changes the selection to the newly formatted block (allows applying multiple styles to a block).** @method formatSelectionBlock* @param {String} [blocktag] Change the block level tag to this. Empty string, means do not change the tag.* @param {Object} [attributes] The keys and values for attributes to be added/changed in the block tag.* @return {Node|boolean} The Node that was formatted if a change was made, otherwise false.*/formatSelectionBlock: function(blocktag, attributes) {// First find the nearest ancestor of the selection that is a block level element.var selectionparentnode = this.getSelectionParentNode(),boundary,cell,nearestblock,newcontent,match,replacement;if (!selectionparentnode) {// No selection, nothing to format.return false;}boundary = this.editor;selectionparentnode = Y.one(selectionparentnode);// If there is a table cell in between the selectionparentnode and the boundary,// move the boundary to the table cell.// This is because we might have a table in a div, and we select some text in a cell,// want to limit the change in style to the table cell, not the entire table (via the outer div).cell = selectionparentnode.ancestor(function(node) {var tagname = node.get('tagName');if (tagname) {tagname = tagname.toLowerCase();}return (node === boundary) ||(tagname === 'td') ||(tagname === 'th');}, true);if (cell) {// Limit the scope to the table cell.boundary = cell;}nearestblock = selectionparentnode.ancestor(this.BLOCK_TAGS.join(', '), true);if (nearestblock) {// Check that the block is contained by the boundary.match = nearestblock.ancestor(function(node) {return node === boundary;}, false);if (!match) {nearestblock = false;}}// No valid block element - make one.if (!nearestblock) {var alignment;if (this.coreDirection === 'rtl') {alignment = 'style="text-align: right;"';} else {alignment = 'style="text-align: left;"';}// There is no block node in the content, wrap the content in a p and use that.newcontent = Y.Node.create('<p dir="' + this.coreDirection + '" ' + alignment + '></p>');boundary.get('childNodes').each(function(child) {newcontent.append(child.remove());});boundary.append(newcontent);nearestblock = newcontent;}// Guaranteed to have a valid block level element contained in the contenteditable region.// Change the tag to the new block level tag.if (blocktag && blocktag !== '') {// Change the block level node for a new one.replacement = Y.Node.create('<' + blocktag + '></' + blocktag + '>');// Copy all attributes.replacement.setAttrs(nearestblock.getAttrs());// Copy all children.nearestblock.get('childNodes').each(function(child) {child.remove();replacement.append(child);});nearestblock.replace(replacement);nearestblock = replacement;}// Set the attributes on the block level tag.if (attributes) {nearestblock.setAttrs(attributes);}// Change the selection to the modified block. This makes sense when we might apply multiple styles// to the block.var selection = this.getSelectionFromNode(nearestblock);this.setSelection(selection);return nearestblock;}};Y.Base.mix(Y.M.editor_atto.Editor, [EditorStyling]);