From c63493c899de714b05b0521bb38aab60d19030ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Fri, 20 Jan 2017 00:55:51 +0100 Subject: Validation initiale --- sources/plugins/indentblock/plugin.js | 312 ++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 sources/plugins/indentblock/plugin.js (limited to 'sources/plugins/indentblock/plugin.js') diff --git a/sources/plugins/indentblock/plugin.js b/sources/plugins/indentblock/plugin.js new file mode 100644 index 0000000..b39fd73 --- /dev/null +++ b/sources/plugins/indentblock/plugin.js @@ -0,0 +1,312 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +/** + * @fileOverview Handles the indentation of block elements. + */ + +( function() { + 'use strict'; + + var $listItem = CKEDITOR.dtd.$listItem, + $list = CKEDITOR.dtd.$list, + TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED, + TRISTATE_OFF = CKEDITOR.TRISTATE_OFF; + + CKEDITOR.plugins.add( 'indentblock', { + requires: 'indent', + init: function( editor ) { + var globalHelpers = CKEDITOR.plugins.indent, + classes = editor.config.indentClasses; + + // Register commands. + globalHelpers.registerCommands( editor, { + indentblock: new commandDefinition( editor, 'indentblock', true ), + outdentblock: new commandDefinition( editor, 'outdentblock' ) + } ); + + function commandDefinition() { + globalHelpers.specificDefinition.apply( this, arguments ); + + this.allowedContent = { + 'div h1 h2 h3 h4 h5 h6 ol p pre ul': { + // Do not add elements, but only text-align style if element is validated by other rule. + propertiesOnly: true, + styles: !classes ? 'margin-left,margin-right' : null, + classes: classes || null + } + }; + + this.contentTransformations = [ + [ 'div: splitMarginShorthand' ], + [ 'h1: splitMarginShorthand' ], + [ 'h2: splitMarginShorthand' ], + [ 'h3: splitMarginShorthand' ], + [ 'h4: splitMarginShorthand' ], + [ 'h5: splitMarginShorthand' ], + [ 'h6: splitMarginShorthand' ], + [ 'ol: splitMarginShorthand' ], + [ 'p: splitMarginShorthand' ], + [ 'pre: splitMarginShorthand' ], + [ 'ul: splitMarginShorthand' ] + ]; + + if ( this.enterBr ) + this.allowedContent.div = true; + + this.requiredContent = ( this.enterBr ? 'div' : 'p' ) + + ( classes ? '(' + classes.join( ',' ) + ')' : '{margin-left}' ); + + this.jobs = { + '20': { + refresh: function( editor, path ) { + var firstBlock = path.block || path.blockLimit; + + // Switch context from somewhere inside list item to list item, + // if not found just assign self (doing nothing). + if ( !firstBlock.is( $listItem ) ) { + var ascendant = firstBlock.getAscendant( $listItem ); + + firstBlock = ( ascendant && path.contains( ascendant ) ) || firstBlock; + } + + // Switch context from list item to list + // because indentblock can indent entire list + // but not a single list element. + + if ( firstBlock.is( $listItem ) ) + firstBlock = firstBlock.getParent(); + + // [-] Context in the path or ENTER_BR + // + // Don't try to indent if the element is out of + // this plugin's scope. This assertion is omitted + // if ENTER_BR is in use since there may be no block + // in the path. + + if ( !this.enterBr && !this.getContext( path ) ) + return TRISTATE_DISABLED; + + else if ( classes ) { + + // [+] Context in the path or ENTER_BR + // [+] IndentClasses + // + // If there are indentation classes, check if reached + // the highest level of indentation. If so, disable + // the command. + + if ( indentClassLeft.call( this, firstBlock, classes ) ) + return TRISTATE_OFF; + else + return TRISTATE_DISABLED; + } else { + + // [+] Context in the path or ENTER_BR + // [-] IndentClasses + // [+] Indenting + // + // No indent-level limitations due to indent classes. + // Indent-like command can always be executed. + + if ( this.isIndent ) + return TRISTATE_OFF; + + // [+] Context in the path or ENTER_BR + // [-] IndentClasses + // [-] Indenting + // [-] Block in the path + // + // No block in path. There's no element to apply indentation + // so disable the command. + + else if ( !firstBlock ) + return TRISTATE_DISABLED; + + // [+] Context in the path or ENTER_BR + // [-] IndentClasses + // [-] Indenting + // [+] Block in path. + // + // Not using indentClasses but there is firstBlock. + // We can calculate current indentation level and + // try to increase/decrease it. + + else { + return CKEDITOR[ + ( getIndent( firstBlock ) || 0 ) <= 0 ? 'TRISTATE_DISABLED' : 'TRISTATE_OFF' + ]; + } + } + }, + + exec: function( editor ) { + var selection = editor.getSelection(), + range = selection && selection.getRanges()[ 0 ], + nearestListBlock; + + // If there's some list in the path, then it will be + // a full-list indent by increasing or decreasing margin property. + if ( ( nearestListBlock = editor.elementPath().contains( $list ) ) ) + indentElement.call( this, nearestListBlock, classes ); + + // If no list in the path, use iterator to indent all the possible + // paragraphs in the range, creating them if necessary. + else { + var iterator = range.createIterator(), + enterMode = editor.config.enterMode, + block; + + iterator.enforceRealBlocks = true; + iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR; + + while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) { + if ( !block.isReadOnly() ) + indentElement.call( this, block, classes ); + } + } + + return true; + } + } + }; + } + + CKEDITOR.tools.extend( commandDefinition.prototype, globalHelpers.specificDefinition.prototype, { + // Elements that, if in an elementpath, will be handled by this + // command. They restrict the scope of the plugin. + context: { div: 1, dl: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, ul: 1, ol: 1, p: 1, pre: 1, table: 1 }, + + // A regex built on config#indentClasses to detect whether an + // element has some indentClass or not. + classNameRegex: classes ? new RegExp( '(?:^|\\s+)(' + classes.join( '|' ) + ')(?=$|\\s)' ) : null + } ); + } + } ); + + // Generic indentation procedure for indentation of any element + // either with margin property or config#indentClass. + function indentElement( element, classes, dir ) { + if ( element.getCustomData( 'indent_processed' ) ) + return; + + var editor = this.editor, + isIndent = this.isIndent; + + if ( classes ) { + // Transform current class f to indent step index. + var indentClass = element.$.className.match( this.classNameRegex ), + indentStep = 0; + + if ( indentClass ) { + indentClass = indentClass[ 1 ]; + indentStep = CKEDITOR.tools.indexOf( classes, indentClass ) + 1; + } + + // Operate on indent step index, transform indent step index + // back to class name. + if ( ( indentStep += isIndent ? 1 : -1 ) < 0 ) + return; + + indentStep = Math.min( indentStep, classes.length ); + indentStep = Math.max( indentStep, 0 ); + element.$.className = CKEDITOR.tools.ltrim( element.$.className.replace( this.classNameRegex, '' ) ); + + if ( indentStep > 0 ) + element.addClass( classes[ indentStep - 1 ] ); + } else { + var indentCssProperty = getIndentCss( element, dir ), + currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 ), + indentOffset = editor.config.indentOffset || 40; + + if ( isNaN( currentOffset ) ) + currentOffset = 0; + + currentOffset += ( isIndent ? 1 : -1 ) * indentOffset; + + if ( currentOffset < 0 ) + return; + + currentOffset = Math.max( currentOffset, 0 ); + currentOffset = Math.ceil( currentOffset / indentOffset ) * indentOffset; + + element.setStyle( + indentCssProperty, + currentOffset ? currentOffset + ( editor.config.indentUnit || 'px' ) : '' + ); + + if ( element.getAttribute( 'style' ) === '' ) + element.removeAttribute( 'style' ); + } + + CKEDITOR.dom.element.setMarker( this.database, element, 'indent_processed', 1 ); + + return; + } + + // Method that checks if current indentation level for an element + // reached the limit determined by config#indentClasses. + function indentClassLeft( node, classes ) { + var indentClass = node.$.className.match( this.classNameRegex ), + isIndent = this.isIndent; + + // If node has one of the indentClasses: + // * If it holds the topmost indentClass, then + // no more classes have left. + // * If it holds any other indentClass, it can use the next one + // or the previous one. + // * Outdent is always possible. We can remove indentClass. + if ( indentClass ) + return isIndent ? indentClass[ 1 ] != classes.slice( -1 ) : true; + + // If node has no class which belongs to indentClasses, + // then it is at 0-level. It can be indented but not outdented. + else + return isIndent; + } + + // Determines indent CSS property for an element according to + // what is the direction of such element. It can be either `margin-left` + // or `margin-right`. + function getIndentCss( element, dir ) { + return ( dir || element.getComputedStyle( 'direction' ) ) == 'ltr' ? 'margin-left' : 'margin-right'; + } + + // Return the numerical indent value of margin-left|right of an element, + // considering element's direction. If element has no margin specified, + // NaN is returned. + function getIndent( element ) { + return parseInt( element.getStyle( getIndentCss( element ) ), 10 ); + } +} )(); + +/** + * A list of classes to use for indenting the contents. If set to `null`, no classes will be used + * and instead the {@link #indentUnit} and {@link #indentOffset} properties will be used. + * + * // Use the 'Indent1', 'Indent2', 'Indent3' classes. + * config.indentClasses = ['Indent1', 'Indent2', 'Indent3']; + * + * @cfg {Array} [indentClasses=null] + * @member CKEDITOR.config + */ + +/** + * The size in {@link CKEDITOR.config#indentUnit indentation units} of each indentation step. + * + * config.indentOffset = 4; + * + * @cfg {Number} [indentOffset=40] + * @member CKEDITOR.config + */ + +/** + * The unit used for {@link CKEDITOR.config#indentOffset indentation offset}. + * + * config.indentUnit = 'em'; + * + * @cfg {String} [indentUnit='px'] + * @member CKEDITOR.config + */ -- cgit v1.2.3