mirror of
https://github.com/UnickSoft/graphonline.git
synced 2025-07-01 23:36:00 +00:00
308 lines
9.4 KiB
JavaScript
Executable File
308 lines
9.4 KiB
JavaScript
Executable File
/**
|
|
* @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
|
|
* For licensing, see LICENSE.html 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( editor, name ) {
|
|
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
|
|
}
|
|
};
|
|
|
|
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 list item to list
|
|
// because indentblock can indent entire list
|
|
// but not a single list element.
|
|
|
|
if ( firstBlock.is( $listItem ) )
|
|
firstBlock = firstBlock.getParent();
|
|
|
|
// If firstBlock isn't list item, but still there's
|
|
// some ascendant (i.e. <ul>), then this is not
|
|
// a job for indentblock, e.g.:
|
|
//
|
|
// <ul>
|
|
// <li><p>foo</p></li>
|
|
// </ul>
|
|
|
|
else if ( firstBlock.getAscendant( $listItem ) )
|
|
return TRISTATE_DISABLED;
|
|
|
|
// [-] 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( 1 )[ 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' ) ) )
|
|
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
|
|
*/
|