mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-25 19:26:46 +00:00
Merge "JSHint: Added dotfiles and fixed tons of linting warnings."
This commit is contained in:
commit
ab47265c34
6
.jshintignore
Normal file
6
.jshintignore
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
api
|
||||||
|
modules/jquery
|
||||||
|
modules/qunit
|
||||||
|
modules/rangy
|
||||||
|
modules/parser
|
||||||
|
tests/parser
|
43
.jshintrc
Normal file
43
.jshintrc
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"predef": [
|
||||||
|
"ve",
|
||||||
|
|
||||||
|
"Node",
|
||||||
|
|
||||||
|
"QUnit",
|
||||||
|
"test",
|
||||||
|
"raises",
|
||||||
|
"expect",
|
||||||
|
"ok",
|
||||||
|
"equal",
|
||||||
|
"notEqual",
|
||||||
|
"strictEqual",
|
||||||
|
"strictNotEqual",
|
||||||
|
"deepEqual",
|
||||||
|
"deepNotEqual"
|
||||||
|
],
|
||||||
|
|
||||||
|
"bitwise": true,
|
||||||
|
"curly": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"immed": true,
|
||||||
|
"latedef": true,
|
||||||
|
"newcap": true,
|
||||||
|
"noarg": true,
|
||||||
|
"noempty": true,
|
||||||
|
"nonew": true,
|
||||||
|
"regexp": true,
|
||||||
|
"undef": true,
|
||||||
|
"strict": false,
|
||||||
|
"trailing": true,
|
||||||
|
|
||||||
|
"smarttabs": true,
|
||||||
|
"multistr": true,
|
||||||
|
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
"jquery": true,
|
||||||
|
|
||||||
|
"nomen": true,
|
||||||
|
"onevar": true
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ ve.ce.ImageNode = function( model ) {
|
||||||
this.model.addListenerMethod( this, 'update', 'onUpdate' );
|
this.model.addListenerMethod( this, 'update', 'onUpdate' );
|
||||||
/*
|
/*
|
||||||
this.$.on('mousedown', function() {
|
this.$.on('mousedown', function() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ ve.ce.TextNode.prototype.onUpdate = function( force ) {
|
||||||
throw 'Can not update a text node that is not attached to a document';
|
throw 'Can not update a text node that is not attached to a document';
|
||||||
}
|
}
|
||||||
if ( force === true || this.root.getSurface().render === true ) {
|
if ( force === true || this.root.getSurface().render === true ) {
|
||||||
|
// XXX: Why is this being passed to $(), creating a new jQuery object? –krinkle 20120719
|
||||||
var $new = $( $( '<span>' + this.getHtml() + '</span>' ).contents() );
|
var $new = $( $( '<span>' + this.getHtml() + '</span>' ).contents() );
|
||||||
if ( $new.length === 0 ) {
|
if ( $new.length === 0 ) {
|
||||||
$new = $new.add( document.createTextNode( '' ) );
|
$new = $new.add( document.createTextNode( '' ) );
|
||||||
|
@ -144,9 +145,9 @@ ve.ce.TextNode.prototype.onUpdate = function( force ) {
|
||||||
if ( this.parent ) {
|
if ( this.parent ) {
|
||||||
this.parent.clean();
|
this.parent.clean();
|
||||||
if ( ve.debug ) {
|
if ( ve.debug ) {
|
||||||
this.parent.$.css('background-color', '#F6F6F6');
|
this.parent.$.css('backgroundColor', '#F6F6F6');
|
||||||
setTimeout( ve.proxy( function() {
|
setTimeout( ve.proxy( function () {
|
||||||
this.parent.$.css('background-color', 'transparent');
|
this.parent.$.css('backgroundColor', 'transparent');
|
||||||
}, this ), 350 );
|
}, this ), 350 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,15 +178,17 @@ ve.ce.TextNode.prototype.getHtml = function() {
|
||||||
leftPlain,
|
leftPlain,
|
||||||
rightPlain,
|
rightPlain,
|
||||||
hashStack = [],
|
hashStack = [],
|
||||||
annotationStack = {};
|
annotationStack = {},
|
||||||
|
chr;
|
||||||
|
|
||||||
var replaceWithNonBreakingSpace = function( index, data ) {
|
function replaceWithNonBreakingSpace( index, data ) {
|
||||||
if ( ve.isArray( data[index] ) ) {
|
if ( ve.isArray( data[index] ) ) {
|
||||||
data[index][0] = ' ';
|
data[index][0] = ' ';
|
||||||
} else {
|
} else {
|
||||||
data[index] = ' ';
|
data[index] = ' ';
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if ( data.length > 0 ) {
|
if ( data.length > 0 ) {
|
||||||
character = data[0];
|
character = data[0];
|
||||||
if ( ve.isArray( character ) ? character[0] === ' ' : character === ' ' ) {
|
if ( ve.isArray( character ) ? character[0] === ' ' : character === ' ' ) {
|
||||||
|
@ -212,10 +215,10 @@ ve.ce.TextNode.prototype.getHtml = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var openAnnotations = function( annotations ) {
|
function openAnnotations( annotations ) {
|
||||||
var out = '',
|
var out = '',
|
||||||
annotation;
|
annotation, hash;
|
||||||
for ( var hash in annotations ) {
|
for ( hash in annotations ) {
|
||||||
annotation = annotations[hash];
|
annotation = annotations[hash];
|
||||||
out += typeof renderers[annotation.type].open === 'function' ?
|
out += typeof renderers[annotation.type].open === 'function' ?
|
||||||
renderers[annotation.type].open( annotation.data ) :
|
renderers[annotation.type].open( annotation.data ) :
|
||||||
|
@ -224,12 +227,12 @@ ve.ce.TextNode.prototype.getHtml = function() {
|
||||||
annotationStack[hash] = annotation;
|
annotationStack[hash] = annotation;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
};
|
}
|
||||||
|
|
||||||
var closeAnnotations = function( annotations ) {
|
function closeAnnotations( annotations ) {
|
||||||
var out = '',
|
var out = '',
|
||||||
annotation;
|
annotation, hash;
|
||||||
for ( var hash in annotations ) {
|
for ( hash in annotations ) {
|
||||||
annotation = annotations[hash];
|
annotation = annotations[hash];
|
||||||
out += typeof renderers[annotation.type].close === 'function' ?
|
out += typeof renderers[annotation.type].close === 'function' ?
|
||||||
renderers[annotation.type].close( annotation.data ) :
|
renderers[annotation.type].close( annotation.data ) :
|
||||||
|
@ -238,7 +241,7 @@ ve.ce.TextNode.prototype.getHtml = function() {
|
||||||
delete annotationStack[hash];
|
delete annotationStack[hash];
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
};
|
}
|
||||||
|
|
||||||
for ( i = 0; i < data.length; i++ ) {
|
for ( i = 0; i < data.length; i++ ) {
|
||||||
right = data[i];
|
right = data[i];
|
||||||
|
@ -294,7 +297,7 @@ ve.ce.TextNode.prototype.getHtml = function() {
|
||||||
out += openAnnotations( open );
|
out += openAnnotations( open );
|
||||||
}
|
}
|
||||||
|
|
||||||
var chr = rightPlain ? right : right[0];
|
chr = rightPlain ? right : right[0];
|
||||||
out += chr in htmlChars ? htmlChars[chr] : chr;
|
out += chr in htmlChars ? htmlChars[chr] : chr;
|
||||||
left = right;
|
left = right;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,12 @@ if ( $.browser.msie ) {
|
||||||
* @throws 'Invalid attribute value' if attribute value is not a key in {domWrapperElementTypes}
|
* @throws 'Invalid attribute value' if attribute value is not a key in {domWrapperElementTypes}
|
||||||
*/
|
*/
|
||||||
ve.ce.BranchNode.getDomWrapperType = function( model, key ) {
|
ve.ce.BranchNode.getDomWrapperType = function( model, key ) {
|
||||||
var value = model.getAttribute( key );
|
var types,
|
||||||
|
value = model.getAttribute( key );
|
||||||
if ( value === undefined ) {
|
if ( value === undefined ) {
|
||||||
throw 'Undefined attribute: ' + key;
|
throw 'Undefined attribute: ' + key;
|
||||||
}
|
}
|
||||||
var types = ve.ce.nodeFactory.lookup( model.getType() ).domWrapperElementTypes;
|
types = ve.ce.nodeFactory.lookup( model.getType() ).domWrapperElementTypes;
|
||||||
if ( types[value] === undefined ) {
|
if ( types[value] === undefined ) {
|
||||||
throw 'Invalid attribute value: ' + value;
|
throw 'Invalid attribute value: ' + value;
|
||||||
}
|
}
|
||||||
|
@ -85,10 +86,12 @@ ve.ce.BranchNode.getDomWrapper = function( model, key ) {
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
ve.ce.BranchNode.prototype.addSlugs = function() {
|
ve.ce.BranchNode.prototype.addSlugs = function() {
|
||||||
|
var i, $slug;
|
||||||
|
|
||||||
// Remove all slugs in this branch
|
// Remove all slugs in this branch
|
||||||
this.$slugs.remove();
|
this.$slugs.remove();
|
||||||
|
|
||||||
var $slug = ve.ce.BranchNode.$slugTemplate.clone();
|
$slug = ve.ce.BranchNode.$slugTemplate.clone();
|
||||||
|
|
||||||
if ( this.canHaveGrandchildren() ) {
|
if ( this.canHaveGrandchildren() ) {
|
||||||
$slug.css( 'display', 'block');
|
$slug.css( 'display', 'block');
|
||||||
|
@ -101,7 +104,7 @@ ve.ce.BranchNode.prototype.addSlugs = function() {
|
||||||
$slug.clone().appendTo( this.$ )
|
$slug.clone().appendTo( this.$ )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for ( var i = 0; i < this.children.length; i++ ) {
|
for ( i = 0; i < this.children.length; i++ ) {
|
||||||
if ( this.children[i].canHaveSlug() ) {
|
if ( this.children[i].canHaveSlug() ) {
|
||||||
if ( i === 0 ) {
|
if ( i === 0 ) {
|
||||||
// First sluggable child (left side)
|
// First sluggable child (left side)
|
||||||
|
@ -138,9 +141,11 @@ ve.ce.BranchNode.prototype.addSlugs = function() {
|
||||||
* @emits rewrap ($old, $new)
|
* @emits rewrap ($old, $new)
|
||||||
*/
|
*/
|
||||||
ve.ce.BranchNode.prototype.updateDomWrapper = function( key ) {
|
ve.ce.BranchNode.prototype.updateDomWrapper = function( key ) {
|
||||||
var type = ve.ce.BranchNode.getDomWrapperType( this.model, key );
|
var $element,
|
||||||
|
type = ve.ce.BranchNode.getDomWrapperType( this.model, key );
|
||||||
|
|
||||||
if ( type !== this.domWrapperElementType ) {
|
if ( type !== this.domWrapperElementType ) {
|
||||||
var $element = $( '<' + type + '></' + type + '>' );
|
$element = $( '<' + type + '></' + type + '>' );
|
||||||
// Copy classes
|
// Copy classes
|
||||||
$element.attr( 'class', this.$.attr( 'class' ) );
|
$element.attr( 'class', this.$.attr( 'class' ) );
|
||||||
// Copy .data( 'node' )
|
// Copy .data( 'node' )
|
||||||
|
@ -172,21 +177,23 @@ ve.ce.BranchNode.prototype.updateDomWrapper = function( key ) {
|
||||||
ve.ce.BranchNode.prototype.onSplice = function( index, howmany ) {
|
ve.ce.BranchNode.prototype.onSplice = function( index, howmany ) {
|
||||||
var i,
|
var i,
|
||||||
length,
|
length,
|
||||||
args = Array.prototype.slice.call( arguments, 0 );
|
args = Array.prototype.slice.call( arguments, 0 ),
|
||||||
|
$anchor,
|
||||||
|
removals,
|
||||||
|
$target;
|
||||||
// Convert models to views and attach them to this node
|
// Convert models to views and attach them to this node
|
||||||
if ( args.length >= 3 ) {
|
if ( args.length >= 3 ) {
|
||||||
for ( i = 2, length = args.length; i < length; i++ ) {
|
for ( i = 2, length = args.length; i < length; i++ ) {
|
||||||
args[i] = ve.ce.nodeFactory.create( args[i].getType(), args[i] );
|
args[i] = ve.ce.nodeFactory.create( args[i].getType(), args[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var removals = this.children.splice.apply( this.children, args );
|
removals = this.children.splice.apply( this.children, args );
|
||||||
for ( i = 0, length = removals.length; i < length; i++ ) {
|
for ( i = 0, length = removals.length; i < length; i++ ) {
|
||||||
removals[i].detach();
|
removals[i].detach();
|
||||||
// Update DOM
|
// Update DOM
|
||||||
removals[i].$.detach();
|
removals[i].$.detach();
|
||||||
}
|
}
|
||||||
if ( args.length >= 3 ) {
|
if ( args.length >= 3 ) {
|
||||||
var $target;
|
|
||||||
if ( index ) {
|
if ( index ) {
|
||||||
// Get the element before the insertion point
|
// Get the element before the insertion point
|
||||||
$anchor = this.$.children(':not(.ve-ce-slug)').eq( index - 1 );
|
$anchor = this.$.children(':not(.ve-ce-slug)').eq( index - 1 );
|
||||||
|
@ -205,13 +212,14 @@ ve.ce.BranchNode.prototype.onSplice = function( index, howmany ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.BranchNode.prototype.hasSlugAtOffset = function( offset ) {
|
ve.ce.BranchNode.prototype.hasSlugAtOffset = function( offset ) {
|
||||||
|
var i, nodeOffset, nodeLength;
|
||||||
if ( this.getLength() === 0 ) {
|
if ( this.getLength() === 0 ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for ( var i = 0; i < this.children.length; i++ ) {
|
for ( i = 0; i < this.children.length; i++ ) {
|
||||||
if ( this.children[i].canHaveSlug() ) {
|
if ( this.children[i].canHaveSlug() ) {
|
||||||
var nodeOffset = this.children[i].model.getRoot().getOffsetFromNode( this.children[i].model );
|
nodeOffset = this.children[i].model.getRoot().getOffsetFromNode( this.children[i].model );
|
||||||
var nodeLength = this.children[i].model.getOuterLength();
|
nodeLength = this.children[i].model.getOuterLength();
|
||||||
if ( i === 0 ) {
|
if ( i === 0 ) {
|
||||||
if ( nodeOffset === offset ) {
|
if ( nodeOffset === offset ) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*global rangy */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ContentEditable surface.
|
* ContentEditable surface.
|
||||||
*
|
*
|
||||||
|
@ -115,6 +117,14 @@ ve.ce.Surface.prototype.onMouseDown = function( e ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
|
var offset,
|
||||||
|
relativeContentOffset,
|
||||||
|
relativeStructuralOffset,
|
||||||
|
relativeStructuralOffsetNode,
|
||||||
|
hasSlug,
|
||||||
|
newOffset,
|
||||||
|
annotations,
|
||||||
|
annotation;
|
||||||
switch ( e.keyCode ) {
|
switch ( e.keyCode ) {
|
||||||
// Indenting list items doesn't work yet, so disable tab handling for now
|
// Indenting list items doesn't work yet, so disable tab handling for now
|
||||||
/*
|
/*
|
||||||
|
@ -134,12 +144,11 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
// Left arrow
|
// Left arrow
|
||||||
case 37:
|
case 37:
|
||||||
if ( !e.metaKey && !e.altKey && !e.shiftKey && this.model.getSelection().getLength() === 0 ) {
|
if ( !e.metaKey && !e.altKey && !e.shiftKey && this.model.getSelection().getLength() === 0 ) {
|
||||||
var offset = this.model.getSelection().start;
|
offset = this.model.getSelection().start;
|
||||||
var relativeContentOffset = this.documentView.model.getRelativeContentOffset( offset, -1 );
|
relativeContentOffset = this.documentView.model.getRelativeContentOffset( offset, -1 );
|
||||||
var relativeStructuralOffset = this.documentView.model.getRelativeStructuralOffset( offset - 1, -1, true );
|
relativeStructuralOffset = this.documentView.model.getRelativeStructuralOffset( offset - 1, -1, true );
|
||||||
var relativeStructuralOffsetNode = this.documentView.documentNode.getNodeFromOffset( relativeStructuralOffset );
|
relativeStructuralOffsetNode = this.documentView.documentNode.getNodeFromOffset( relativeStructuralOffset );
|
||||||
var hasSlug = relativeStructuralOffsetNode.hasSlugAtOffset( relativeStructuralOffset );
|
hasSlug = relativeStructuralOffsetNode.hasSlugAtOffset( relativeStructuralOffset );
|
||||||
var newOffset;
|
|
||||||
if ( hasSlug ) {
|
if ( hasSlug ) {
|
||||||
if ( relativeContentOffset > offset ) {
|
if ( relativeContentOffset > offset ) {
|
||||||
newOffset = relativeStructuralOffset;
|
newOffset = relativeStructuralOffset;
|
||||||
|
@ -158,13 +167,17 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
break;
|
break;
|
||||||
// Right arrow
|
// Right arrow
|
||||||
case 39:
|
case 39:
|
||||||
if ( !e.metaKey && !e.altKey && !e.shiftKey && this.model.getSelection().getLength() === 0 ) {
|
if (
|
||||||
var offset = this.model.getSelection().start;
|
!e.metaKey &&
|
||||||
var relativeContentOffset = this.documentView.model.getRelativeContentOffset( offset, 1 );
|
!e.altKey &&
|
||||||
var relativeStructuralOffset = this.documentView.model.getRelativeStructuralOffset( offset + 1, 1, true );
|
!e.shiftKey &&
|
||||||
var relativeStructuralOffsetNode = this.documentView.documentNode.getNodeFromOffset( relativeStructuralOffset );
|
this.model.getSelection().getLength() === 0
|
||||||
var hasSlug = relativeStructuralOffsetNode.hasSlugAtOffset( relativeStructuralOffset );
|
) {
|
||||||
var newOffset;
|
offset = this.model.getSelection().start;
|
||||||
|
relativeContentOffset = this.documentView.model.getRelativeContentOffset( offset, 1 );
|
||||||
|
relativeStructuralOffset = this.documentView.model.getRelativeStructuralOffset( offset + 1, 1, true );
|
||||||
|
relativeStructuralOffsetNode = this.documentView.documentNode.getNodeFromOffset( relativeStructuralOffset );
|
||||||
|
hasSlug = relativeStructuralOffsetNode.hasSlugAtOffset( relativeStructuralOffset );
|
||||||
if ( hasSlug ) {
|
if ( hasSlug ) {
|
||||||
if ( relativeContentOffset < offset ) {
|
if ( relativeContentOffset < offset ) {
|
||||||
newOffset = relativeStructuralOffset;
|
newOffset = relativeStructuralOffset;
|
||||||
|
@ -201,8 +214,8 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
if ( ve.ce.Surface.isShortcutKey( e ) ) {
|
if ( ve.ce.Surface.isShortcutKey( e ) ) {
|
||||||
// Ctrl+B / Cmd+B, annotate with bold
|
// Ctrl+B / Cmd+B, annotate with bold
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var annotations = this.documentView.model.getAnnotationsFromRange( this.model.getSelection() ),
|
annotations = this.documentView.model.getAnnotationsFromRange( this.model.getSelection() );
|
||||||
annotation = {"type":"textStyle/bold"};
|
annotation = { 'type': 'textStyle/bold' };
|
||||||
|
|
||||||
this.model.annotate( annotations[ve.getHash(annotation)] ? 'clear' : 'set', annotation );
|
this.model.annotate( annotations[ve.getHash(annotation)] ? 'clear' : 'set', annotation );
|
||||||
}
|
}
|
||||||
|
@ -212,8 +225,8 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
if ( ve.ce.Surface.isShortcutKey( e ) ) {
|
if ( ve.ce.Surface.isShortcutKey( e ) ) {
|
||||||
// Ctrl+I / Cmd+I, annotate with italic
|
// Ctrl+I / Cmd+I, annotate with italic
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var annotations = this.documentView.model.getAnnotationsFromRange( this.model.getSelection() ),
|
annotations = this.documentView.model.getAnnotationsFromRange( this.model.getSelection() );
|
||||||
annotation = {"type":"textStyle/italic"};
|
annotation = { 'type': 'textStyle/italic' };
|
||||||
|
|
||||||
this.model.annotate( annotations[ve.getHash(annotation)] ? 'clear' : 'set', annotation );
|
this.model.annotate( annotations[ve.getHash(annotation)] ? 'clear' : 'set', annotation );
|
||||||
}
|
}
|
||||||
|
@ -256,7 +269,7 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onCutCopy = function( e ) {
|
ve.ce.Surface.prototype.onCutCopy = function( e ) {
|
||||||
var _this = this,
|
var view = this,
|
||||||
sel = rangy.getSelection(),
|
sel = rangy.getSelection(),
|
||||||
$frag = null,
|
$frag = null,
|
||||||
key = '';
|
key = '';
|
||||||
|
@ -264,10 +277,10 @@ ve.ce.Surface.prototype.onCutCopy = function( e ) {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
|
|
||||||
// Create key from text and element names
|
// Create key from text and element names
|
||||||
$frag = $(sel.getRangeAt(0).cloneContents());
|
$frag = $( sel.getRangeAt(0).cloneContents() );
|
||||||
$frag.contents().each(function() {
|
$frag.contents().each( function () {
|
||||||
key += this.textContent || this.nodeName;
|
key += this.textContent || this.nodeName;
|
||||||
});
|
} );
|
||||||
key = key.replace( /\s/gm, '' );
|
key = key.replace( /\s/gm, '' );
|
||||||
|
|
||||||
// Set surface clipboard
|
// Set surface clipboard
|
||||||
|
@ -275,32 +288,32 @@ ve.ce.Surface.prototype.onCutCopy = function( e ) {
|
||||||
this.documentView.model.getData( this.model.getSelection() )
|
this.documentView.model.getData( this.model.getSelection() )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( e.type == 'cut' ) {
|
if ( e.type === 'cut' ) {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
|
|
||||||
setTimeout( function() {
|
setTimeout( function() {
|
||||||
var selection = null,
|
var selection = null,
|
||||||
tx = null;
|
tx = null;
|
||||||
|
|
||||||
// We don't like how browsers cut, so let's undo it and do it ourselves.
|
// We don't like how browsers cut, so let's undo it and do it ourselves.
|
||||||
document.execCommand('undo', false, false);
|
document.execCommand( 'undo', false, false );
|
||||||
|
|
||||||
selection = _this.model.getSelection();
|
selection = view.model.getSelection();
|
||||||
|
|
||||||
// Transact
|
// Transact
|
||||||
_this.autoRender = true;
|
view.autoRender = true;
|
||||||
tx = ve.dm.Transaction.newFromRemoval( _this.documentView.model, selection );
|
tx = ve.dm.Transaction.newFromRemoval( view.documentView.model, selection );
|
||||||
_this.model.change( tx, new ve.Range( selection.start ) );
|
view.model.change( tx, new ve.Range( selection.start ) );
|
||||||
_this.autoRender = false;
|
view.autoRender = false;
|
||||||
|
|
||||||
_this.clearPollData();
|
view.clearPollData();
|
||||||
_this.startPolling();
|
view.startPolling();
|
||||||
}, 1 );
|
}, 1 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onPaste = function( e ) {
|
ve.ce.Surface.prototype.onPaste = function( e ) {
|
||||||
var _this = this,
|
var view = this,
|
||||||
selection = this.model.getSelection(),
|
selection = this.model.getSelection(),
|
||||||
tx = null;
|
tx = null;
|
||||||
|
|
||||||
|
@ -308,14 +321,14 @@ ve.ce.Surface.prototype.onPaste = function( e ) {
|
||||||
|
|
||||||
// Pasting into a range? Remove first.
|
// Pasting into a range? Remove first.
|
||||||
if (!rangy.getSelection().isCollapsed) {
|
if (!rangy.getSelection().isCollapsed) {
|
||||||
tx = ve.dm.Transaction.newFromRemoval( _this.documentView.model, selection );
|
tx = ve.dm.Transaction.newFromRemoval( view.documentView.model, selection );
|
||||||
_this.model.change( tx );
|
view.model.change( tx );
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#paste').html('').show().focus();
|
$('#paste').html('').show().focus();
|
||||||
|
|
||||||
setTimeout( function() {
|
setTimeout( function() {
|
||||||
var key = '',
|
var key = '',
|
||||||
pasteData = null,
|
pasteData = null,
|
||||||
tx = null;
|
tx = null;
|
||||||
|
|
||||||
|
@ -326,39 +339,40 @@ ve.ce.Surface.prototype.onPaste = function( e ) {
|
||||||
key = key.replace( /\s/gm, '' );
|
key = key.replace( /\s/gm, '' );
|
||||||
|
|
||||||
// Get linear model from surface clipboard or create array from unknown pasted content
|
// Get linear model from surface clipboard or create array from unknown pasted content
|
||||||
pasteData = ( _this.clipboard[key] ) ? _this.clipboard[key] : $('#paste').text().split('');
|
pasteData = ( view.clipboard[key] ) ? view.clipboard[key] : $('#paste').text().split('');
|
||||||
|
|
||||||
// Transact
|
// Transact
|
||||||
tx = ve.dm.Transaction.newFromInsertion(
|
tx = ve.dm.Transaction.newFromInsertion(
|
||||||
_this.documentView.model, selection.start, pasteData
|
view.documentView.model, selection.start, pasteData
|
||||||
);
|
);
|
||||||
_this.model.change( tx, new ve.Range( selection.start + pasteData.length ) );
|
view.model.change( tx, new ve.Range( selection.start + pasteData.length ) );
|
||||||
_this.documentView.documentNode.$.focus();
|
view.documentView.documentNode.$.focus();
|
||||||
|
|
||||||
_this.clearPollData();
|
view.clearPollData();
|
||||||
_this.startPolling();
|
view.startPolling();
|
||||||
}, 1 );
|
}, 1 );
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
||||||
|
var node, selection, data;
|
||||||
|
|
||||||
ve.log('onKeyPress');
|
ve.log('onKeyPress');
|
||||||
|
|
||||||
if ( ve.ce.Surface.isShortcutKey( e ) || e.which === 13 ) {
|
if ( ve.ce.Surface.isShortcutKey( e ) || e.which === 13 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selection = this.model.getSelection();
|
selection = this.model.getSelection();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
selection.getLength() === 0 &&
|
selection.getLength() === 0 &&
|
||||||
this.sluggable === true &&
|
this.sluggable === true &&
|
||||||
this.hasSlugAtOffset( selection.start )
|
this.hasSlugAtOffset( selection.start )
|
||||||
) {
|
) {
|
||||||
var node;
|
|
||||||
this.sluggable = false;
|
this.sluggable = false;
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
if ( this.documentView.getNodeFromOffset( selection.start ).getLength() !== 0 ) {
|
if ( this.documentView.getNodeFromOffset( selection.start ).getLength() !== 0 ) {
|
||||||
var data = [ { 'type' : 'paragraph' }, { 'type' : '/paragraph' } ];
|
data = [ { 'type' : 'paragraph' }, { 'type' : '/paragraph' } ];
|
||||||
this.model.change(
|
this.model.change(
|
||||||
ve.dm.Transaction.newFromInsertion(
|
ve.dm.Transaction.newFromInsertion(
|
||||||
this.documentView.model,
|
this.documentView.model,
|
||||||
|
@ -419,7 +433,11 @@ ve.ce.Surface.prototype.clearPollData = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.pollChanges = function( async ) {
|
ve.ce.Surface.prototype.pollChanges = function( async ) {
|
||||||
var delay = ve.proxy( function( async ) {
|
var delay, node, range, rangySelection,
|
||||||
|
$anchorNode, $focusNode,
|
||||||
|
text, hash;
|
||||||
|
|
||||||
|
delay = ve.proxy( function( async ) {
|
||||||
if ( this.poll.polling ) {
|
if ( this.poll.polling ) {
|
||||||
if ( this.poll.timeout !== null ) {
|
if ( this.poll.timeout !== null ) {
|
||||||
clearTimeout( this.poll.timeout );
|
clearTimeout( this.poll.timeout );
|
||||||
|
@ -435,9 +453,9 @@ ve.ce.Surface.prototype.pollChanges = function( async ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var node = this.poll.node,
|
node = this.poll.node;
|
||||||
range = this.poll.range,
|
range = this.poll.range;
|
||||||
rangySelection = rangy.getSelection();
|
rangySelection = rangy.getSelection();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
rangySelection.anchorNode !== this.poll.rangySelection.anchorNode ||
|
rangySelection.anchorNode !== this.poll.rangySelection.anchorNode ||
|
||||||
|
@ -452,8 +470,8 @@ ve.ce.Surface.prototype.pollChanges = function( async ) {
|
||||||
|
|
||||||
// TODO: Optimize for the case of collapsed (rangySelection.isCollapsed) range
|
// TODO: Optimize for the case of collapsed (rangySelection.isCollapsed) range
|
||||||
|
|
||||||
var $anchorNode = $( rangySelection.anchorNode ).closest( '.ve-ce-branchNode' ),
|
$anchorNode = $( rangySelection.anchorNode ).closest( '.ve-ce-branchNode' );
|
||||||
$focusNode = $( rangySelection.focusNode ).closest( '.ve-ce-branchNode' );
|
$focusNode = $( rangySelection.focusNode ).closest( '.ve-ce-branchNode' );
|
||||||
|
|
||||||
if ( $anchorNode[0] === $focusNode[0] ) {
|
if ( $anchorNode[0] === $focusNode[0] ) {
|
||||||
node = $anchorNode[0];
|
node = $anchorNode[0];
|
||||||
|
@ -481,8 +499,8 @@ ve.ce.Surface.prototype.pollChanges = function( async ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( node !== null ) {
|
if ( node !== null ) {
|
||||||
var text = ve.ce.getDomText( node ),
|
text = ve.ce.getDomText( node );
|
||||||
hash = ve.ce.getDomHash( node );
|
hash = ve.ce.getDomHash( node );
|
||||||
if ( this.poll.text !== text || this.poll.hash !== hash ) {
|
if ( this.poll.text !== text || this.poll.hash !== hash ) {
|
||||||
this.emit( 'contentChange', {
|
this.emit( 'contentChange', {
|
||||||
'node': node,
|
'node': node,
|
||||||
|
@ -518,25 +536,27 @@ ve.ce.Surface.prototype.pollChanges = function( async ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onContentChange = function( e ) {
|
ve.ce.Surface.prototype.onContentChange = function( e ) {
|
||||||
var nodeOffset = $( e.node ).data( 'node' ).model.getOffset(),
|
var nodeOffset = $( e.node ).data( 'node' ).model.getOffset(),
|
||||||
offsetDiff = (
|
offsetDiff = (
|
||||||
e.old.range !== null &&
|
e.old.range !== null &&
|
||||||
e.new.range !== null &&
|
e['new'].range !== null &&
|
||||||
e.old.range.getLength() === 0 &&
|
e.old.range.getLength() === 0 &&
|
||||||
e.new.range.getLength() === 0
|
e['new'].range.getLength() === 0
|
||||||
) ? e.new.range.start - e.old.range.start : null,
|
) ? e['new'].range.start - e.old.range.start : null,
|
||||||
lengthDiff = e.new.text.length - e.old.text.length;
|
lengthDiff = e['new'].text.length - e.old.text.length,
|
||||||
|
data,
|
||||||
|
annotations;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
offsetDiff === lengthDiff &&
|
offsetDiff === lengthDiff &&
|
||||||
e.old.text.substring( 0, e.old.range.start - nodeOffset - 1 ) ===
|
e.old.text.substring( 0, e.old.range.start - nodeOffset - 1 ) ===
|
||||||
e.new.text.substring( 0, e.old.range.start - nodeOffset - 1 )
|
e['new'].text.substring( 0, e.old.range.start - nodeOffset - 1 )
|
||||||
) {
|
) {
|
||||||
var data = e.new.text.substring(
|
data = e['new'].text.substring(
|
||||||
e.old.range.start - nodeOffset - 1,
|
e.old.range.start - nodeOffset - 1,
|
||||||
e.new.range.start - nodeOffset - 1
|
e['new'].range.start - nodeOffset - 1
|
||||||
).split( '' ),
|
).split( '' );
|
||||||
annotations = this.model.getDocument().getAnnotationsFromOffset( e.old.range.start - 1 );
|
annotations = this.model.getDocument().getAnnotationsFromOffset( e.old.range.start - 1 );
|
||||||
|
|
||||||
if ( !ve.isEmptyObject( annotations ) ) {
|
if ( !ve.isEmptyObject( annotations ) ) {
|
||||||
ve.dm.Document.addAnnotationsToData( data, annotations );
|
ve.dm.Document.addAnnotationsToData( data, annotations );
|
||||||
|
@ -545,28 +565,28 @@ ve.ce.Surface.prototype.onContentChange = function( e ) {
|
||||||
this.render = false;
|
this.render = false;
|
||||||
this.model.change(
|
this.model.change(
|
||||||
ve.dm.Transaction.newFromInsertion( this.documentView.model, e.old.range.start, data ),
|
ve.dm.Transaction.newFromInsertion( this.documentView.model, e.old.range.start, data ),
|
||||||
e.new.range
|
e['new'].range
|
||||||
);
|
);
|
||||||
this.render = true;
|
this.render = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var fromLeft = 0,
|
var fromLeft = 0,
|
||||||
fromRight = 0,
|
fromRight = 0,
|
||||||
len = Math.min( e.old.text.length, e.new.text.length );
|
len = Math.min( e.old.text.length, e['new'].text.length );
|
||||||
|
|
||||||
while ( fromLeft < len && e.old.text[fromLeft] === e.new.text[fromLeft] ) {
|
while ( fromLeft < len && e.old.text[fromLeft] === e['new'].text[fromLeft] ) {
|
||||||
++fromLeft;
|
++fromLeft;
|
||||||
}
|
}
|
||||||
while (
|
while (
|
||||||
fromRight < len - fromLeft &&
|
fromRight < len - fromLeft &&
|
||||||
e.old.text[e.old.text.length - 1 - fromRight] ===
|
e.old.text[e.old.text.length - 1 - fromRight] ===
|
||||||
e.new.text[e.new.text.length - 1 - fromRight]
|
e['new'].text[e['new'].text.length - 1 - fromRight]
|
||||||
) {
|
) {
|
||||||
++fromRight;
|
++fromRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
var annotations = this.model.getDocument().getAnnotationsFromOffset( nodeOffset + 1 + fromLeft ),
|
annotations = this.model.getDocument().getAnnotationsFromOffset( nodeOffset + 1 + fromLeft );
|
||||||
data = e.new.text.substring( fromLeft, e.new.text.length - fromRight ).split( '' );
|
data = e['new'].text.substring( fromLeft, e['new'].text.length - fromRight ).split( '' );
|
||||||
|
|
||||||
if ( !ve.isEmptyObject( annotations ) ) {
|
if ( !ve.isEmptyObject( annotations ) ) {
|
||||||
ve.dm.Document.addAnnotationsToData( data, annotations );
|
ve.dm.Document.addAnnotationsToData( data, annotations );
|
||||||
|
@ -581,12 +601,12 @@ ve.ce.Surface.prototype.onContentChange = function( e ) {
|
||||||
this.documentView.model,
|
this.documentView.model,
|
||||||
new ve.Range( nodeOffset + 1 + fromLeft, nodeOffset + 1 + e.old.text.length - fromRight )
|
new ve.Range( nodeOffset + 1 + fromLeft, nodeOffset + 1 + e.old.text.length - fromRight )
|
||||||
),
|
),
|
||||||
e.new.range
|
e['new'].range
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.model.change(
|
this.model.change(
|
||||||
ve.dm.Transaction.newFromInsertion( this.documentView.model, nodeOffset + 1 + fromLeft, data ),
|
ve.dm.Transaction.newFromInsertion( this.documentView.model, nodeOffset + 1 + fromLeft, data ),
|
||||||
e.new.range
|
e['new'].range
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.sluggable = true;
|
this.sluggable = true;
|
||||||
|
@ -621,7 +641,9 @@ ve.ce.Surface.prototype.handleEnter = function( e ) {
|
||||||
documentModel = this.model.getDocument(),
|
documentModel = this.model.getDocument(),
|
||||||
emptyParagraph = [{ 'type': 'paragraph' }, { 'type': '/paragraph' }],
|
emptyParagraph = [{ 'type': 'paragraph' }, { 'type': '/paragraph' }],
|
||||||
tx,
|
tx,
|
||||||
advanceCursor = true;
|
advanceCursor = true,
|
||||||
|
outerParent,
|
||||||
|
outerChildrenCount;
|
||||||
|
|
||||||
// Stop polling while we work
|
// Stop polling while we work
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
|
@ -633,7 +655,7 @@ ve.ce.Surface.prototype.handleEnter = function( e ) {
|
||||||
this.model.change( tx, selection );
|
this.model.change( tx, selection );
|
||||||
}
|
}
|
||||||
// Handle insertion
|
// Handle insertion
|
||||||
var node = this.documentView.getNodeFromOffset( selection.from ),
|
var node = this.documentView.getNodeFromOffset( selection.from ),
|
||||||
nodeModel = node.getModel(),
|
nodeModel = node.getModel(),
|
||||||
cursor = selection.from,
|
cursor = selection.from,
|
||||||
nodeOffset = nodeModel.getOffset(),
|
nodeOffset = nodeModel.getOffset(),
|
||||||
|
@ -660,7 +682,7 @@ ve.ce.Surface.prototype.handleEnter = function( e ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Split
|
// Split
|
||||||
var stack = [],
|
var stack = [],
|
||||||
outermostNode = null;
|
outermostNode = null;
|
||||||
|
|
||||||
ve.Node.traverseUpstream( node, function( node ) {
|
ve.Node.traverseUpstream( node, function( node ) {
|
||||||
|
@ -681,14 +703,14 @@ ve.ce.Surface.prototype.handleEnter = function( e ) {
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
var outerParent = outermostNode.getModel().getParent(),
|
outerParent = outermostNode.getModel().getParent();
|
||||||
outerChildrenCount = outerParent.getChildren().length
|
outerChildrenCount = outerParent.getChildren().length;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
outermostNode.type == 'listItem' && // this is a list item
|
outermostNode.type === 'listItem' && // this is a list item
|
||||||
outerParent.getChildren()[outerChildrenCount - 1] == outermostNode.getModel() && // this is the last list item
|
outerParent.getChildren()[outerChildrenCount - 1] === outermostNode.getModel() && // this is the last list item
|
||||||
outermostNode.children.length == 1 && // there is one child
|
outermostNode.children.length === 1 && // there is one child
|
||||||
node.model.length == 0 // the child is empty
|
node.model.length === 0 // the child is empty
|
||||||
) {
|
) {
|
||||||
// Enter was pressed in an empty list item.
|
// Enter was pressed in an empty list item.
|
||||||
var list = outermostNode.getModel().getParent();
|
var list = outermostNode.getModel().getParent();
|
||||||
|
@ -730,7 +752,11 @@ ve.ce.Surface.prototype.handleDelete = function( backspace ) {
|
||||||
sourceSplitableNode,
|
sourceSplitableNode,
|
||||||
targetSplitableNode,
|
targetSplitableNode,
|
||||||
tx,
|
tx,
|
||||||
cursorAt;
|
cursorAt,
|
||||||
|
sourceNode,
|
||||||
|
targetNode,
|
||||||
|
sourceData,
|
||||||
|
nodeToDelete;
|
||||||
|
|
||||||
if ( selection.from === selection.to ) {
|
if ( selection.from === selection.to ) {
|
||||||
if ( backspace || selection.to === this.model.getDocument().data.length - 1) {
|
if ( backspace || selection.to === this.model.getDocument().data.length - 1) {
|
||||||
|
@ -741,8 +767,8 @@ ve.ce.Surface.prototype.handleDelete = function( backspace ) {
|
||||||
targetOffset = selection.to;
|
targetOffset = selection.to;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceNode = this.documentView.getNodeFromOffset( sourceOffset, false ),
|
sourceNode = this.documentView.getNodeFromOffset( sourceOffset, false );
|
||||||
targetNode = this.documentView.getNodeFromOffset( targetOffset, false );
|
targetNode = this.documentView.getNodeFromOffset( targetOffset, false );
|
||||||
|
|
||||||
if ( sourceNode.type === targetNode.type ) {
|
if ( sourceNode.type === targetNode.type ) {
|
||||||
sourceSplitableNode = ve.ce.Node.getSplitableNode( sourceNode );
|
sourceSplitableNode = ve.ce.Node.getSplitableNode( sourceNode );
|
||||||
|
@ -771,9 +797,9 @@ ve.ce.Surface.prototype.handleDelete = function( backspace ) {
|
||||||
} else {
|
} else {
|
||||||
// Source and target are different nodes and do not share a parent, perform tricky merge
|
// Source and target are different nodes and do not share a parent, perform tricky merge
|
||||||
// Get the data for the source node
|
// Get the data for the source node
|
||||||
var sourceData = this.documentView.model.getData( sourceNode.model.getRange() );
|
sourceData = this.documentView.model.getData( sourceNode.model.getRange() );
|
||||||
// Find the node that should be completely removed
|
// Find the node that should be completely removed
|
||||||
var nodeToDelete = sourceNode;
|
nodeToDelete = sourceNode;
|
||||||
ve.Node.traverseUpstream( nodeToDelete, function( node ) {
|
ve.Node.traverseUpstream( nodeToDelete, function( node ) {
|
||||||
if ( node.getParent().children.length === 1 ) {
|
if ( node.getParent().children.length === 1 ) {
|
||||||
nodeToDelete = node.getParent();
|
nodeToDelete = node.getParent();
|
||||||
|
@ -874,7 +900,7 @@ ve.ce.Surface.prototype.getNearestCorrectOffset = function( offset, direction )
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentOffset = this.documentView.model.getNearestContentOffset( offset, direction ),
|
var contentOffset = this.documentView.model.getNearestContentOffset( offset, direction ),
|
||||||
structuralOffset =
|
structuralOffset =
|
||||||
this.documentView.model.getNearestStructuralOffset( offset, direction, true );
|
this.documentView.model.getNearestStructuralOffset( offset, direction, true );
|
||||||
|
|
||||||
|
@ -918,7 +944,7 @@ ve.ce.Surface.prototype.hasSlugAtOffset = function( offset ) {
|
||||||
* offset is the position within the element
|
* offset is the position within the element
|
||||||
*/
|
*/
|
||||||
ve.ce.Surface.prototype.getNodeAndOffset = function( offset ) {
|
ve.ce.Surface.prototype.getNodeAndOffset = function( offset ) {
|
||||||
var node = this.documentView.getNodeFromOffset( offset ),
|
var node = this.documentView.getNodeFromOffset( offset ),
|
||||||
startOffset = this.documentView.getDocumentNode().getOffsetFromNode( node ) +
|
startOffset = this.documentView.getDocumentNode().getOffsetFromNode( node ) +
|
||||||
( ( node.isWrapped() ) ? 1 : 0 ),
|
( ( node.isWrapped() ) ? 1 : 0 ),
|
||||||
current = [node.$.contents(), 0],
|
current = [node.$.contents(), 0],
|
||||||
|
@ -992,18 +1018,21 @@ ve.ce.Surface.prototype.getOffset = function( domNode, domOffset ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.getOffsetFromTextNode = function( domNode, domOffset ) {
|
ve.ce.Surface.prototype.getOffsetFromTextNode = function( domNode, domOffset ) {
|
||||||
var $node = $( domNode ).closest(
|
var $node, nodeModel, current, stack, item, offset, $item;
|
||||||
'.ve-ce-branchNode, .ve-ce-alienBlockNode, .ve-ce-alienInlineNode'
|
|
||||||
),
|
$node = $( domNode ).closest(
|
||||||
nodeModel = $node.data( 'node' ).getModel();
|
'.ve-ce-branchNode, .ve-ce-alienBlockNode, .ve-ce-alienInlineNode'
|
||||||
|
);
|
||||||
|
nodeModel = $node.data( 'node' ).getModel();
|
||||||
|
|
||||||
if ( ! $node.hasClass( 've-ce-branchNode' ) ) {
|
if ( ! $node.hasClass( 've-ce-branchNode' ) ) {
|
||||||
return nodeModel.getOffset();
|
return nodeModel.getOffset();
|
||||||
}
|
}
|
||||||
var current = [$node.contents(), 0],
|
|
||||||
stack = [current],
|
current = [$node.contents(), 0];
|
||||||
offset = 0,
|
stack = [current];
|
||||||
item,
|
offset = 0;
|
||||||
$item;
|
|
||||||
while ( stack.length > 0 ) {
|
while ( stack.length > 0 ) {
|
||||||
if ( current[1] >= current[0].length ) {
|
if ( current[1] >= current[0].length ) {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
@ -1041,7 +1070,7 @@ ve.ce.Surface.prototype.getOffsetFromTextNode = function( domNode, domOffset ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.getOffsetFromElementNode = function( domNode, domOffset, addOuterLength ) {
|
ve.ce.Surface.prototype.getOffsetFromElementNode = function( domNode, domOffset, addOuterLength ) {
|
||||||
var $domNode = $( domNode ),
|
var $domNode = $( domNode ),
|
||||||
nodeModel,
|
nodeModel,
|
||||||
node;
|
node;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ ve.dm.DefinitionListItemNode.converters = {
|
||||||
return element.attributes && ( {
|
return element.attributes && ( {
|
||||||
'term': document.createElement( 'dt' ),
|
'term': document.createElement( 'dt' ),
|
||||||
'definition': document.createElement( 'dd' )
|
'definition': document.createElement( 'dd' )
|
||||||
} )[element.attributes['style']];
|
} )[element.attributes.style];
|
||||||
},
|
},
|
||||||
'toDataElement': function( tag, element ) {
|
'toDataElement': function( tag, element ) {
|
||||||
return ( {
|
return ( {
|
||||||
|
|
|
@ -46,7 +46,7 @@ ve.dm.HeadingNode.converters = {
|
||||||
4: document.createElement( 'h4' ),
|
4: document.createElement( 'h4' ),
|
||||||
5: document.createElement( 'h5' ),
|
5: document.createElement( 'h5' ),
|
||||||
6: document.createElement( 'h6' )
|
6: document.createElement( 'h6' )
|
||||||
} )[element.attributes['level']];
|
} )[element.attributes.level];
|
||||||
},
|
},
|
||||||
'toDataElement': function( tag, element ) {
|
'toDataElement': function( tag, element ) {
|
||||||
return ( {
|
return ( {
|
||||||
|
|
|
@ -42,7 +42,7 @@ ve.dm.ListNode.converters = {
|
||||||
return element.attributes && ( {
|
return element.attributes && ( {
|
||||||
'bullet': document.createElement( 'ul' ),
|
'bullet': document.createElement( 'ul' ),
|
||||||
'number': document.createElement( 'ol' )
|
'number': document.createElement( 'ol' )
|
||||||
} )[element.attributes['style']];
|
} )[element.attributes.style];
|
||||||
},
|
},
|
||||||
'toDataElement': function( tag, element ) {
|
'toDataElement': function( tag, element ) {
|
||||||
return ( {
|
return ( {
|
||||||
|
|
|
@ -42,7 +42,7 @@ ve.dm.TableCellNode.converters = {
|
||||||
return element.attributes && ( {
|
return element.attributes && ( {
|
||||||
'data': document.createElement( 'td' ),
|
'data': document.createElement( 'td' ),
|
||||||
'header': document.createElement( 'th' )
|
'header': document.createElement( 'th' )
|
||||||
} )[element.attributes['style']];
|
} )[element.attributes.style];
|
||||||
},
|
},
|
||||||
'toDataElement': function( tag, element ) {
|
'toDataElement': function( tag, element ) {
|
||||||
return ( {
|
return ( {
|
||||||
|
|
|
@ -43,7 +43,7 @@ ve.dm.TableSectionNode.converters = {
|
||||||
'header': document.createElement( 'thead' ),
|
'header': document.createElement( 'thead' ),
|
||||||
'body': document.createElement( 'tbody' ),
|
'body': document.createElement( 'tbody' ),
|
||||||
'footer': document.createElement( 'tfoot' )
|
'footer': document.createElement( 'tfoot' )
|
||||||
} )[element.attributes['style']];
|
} )[element.attributes.style];
|
||||||
},
|
},
|
||||||
'toDataElement': function( tag, element ) {
|
'toDataElement': function( tag, element ) {
|
||||||
return ( {
|
return ( {
|
||||||
|
|
|
@ -373,7 +373,7 @@ ve.dm.Converter.prototype.getDataFromDom = function( domElement, annotations, da
|
||||||
// If we're closing a node that doesn't have any children, but could contain a paragraph,
|
// If we're closing a node that doesn't have any children, but could contain a paragraph,
|
||||||
// add a paragraph. This prevents things like empty list items
|
// add a paragraph. This prevents things like empty list items
|
||||||
var childTypes = ve.dm.nodeFactory.getChildNodeTypes( branchType );
|
var childTypes = ve.dm.nodeFactory.getChildNodeTypes( branchType );
|
||||||
if ( branchType !== 'paragraph' && dataElement && data[data.length - 1] == dataElement &&
|
if ( branchType !== 'paragraph' && dataElement && data[data.length - 1] === dataElement &&
|
||||||
!wrapping && !ve.dm.nodeFactory.canNodeContainContent( branchType ) &&
|
!wrapping && !ve.dm.nodeFactory.canNodeContainContent( branchType ) &&
|
||||||
!ve.dm.nodeFactory.isNodeContent( branchType ) &&
|
!ve.dm.nodeFactory.isNodeContent( branchType ) &&
|
||||||
( childTypes === null || $.inArray( 'paragraph', childTypes ) !== -1 )
|
( childTypes === null || $.inArray( 'paragraph', childTypes ) !== -1 )
|
||||||
|
@ -606,7 +606,7 @@ ve.dm.Converter.prototype.getDomFromData = function( data ) {
|
||||||
.contents()
|
.contents()
|
||||||
.filter( function() {
|
.filter( function() {
|
||||||
// Text nodes only
|
// Text nodes only
|
||||||
return this.nodeType == 3 &&
|
return this.nodeType === 3 &&
|
||||||
// Exclude text nodes within lists
|
// Exclude text nodes within lists
|
||||||
$( this.parentNode ).closest( 'li, dd, dt' ).length === 0;
|
$( this.parentNode ).closest( 'li, dd, dt' ).length === 0;
|
||||||
} )
|
} )
|
||||||
|
|
|
@ -64,7 +64,7 @@ ve.dm.Document = function( data, parentDocument ) {
|
||||||
textLength = 0;
|
textLength = 0;
|
||||||
}
|
}
|
||||||
// Element open/close
|
// Element open/close
|
||||||
if ( this.data[i].type.charAt( 0 ) != '/' ) {
|
if ( this.data[i].type.charAt( 0 ) !== '/' ) {
|
||||||
// Branch or leaf node opening
|
// Branch or leaf node opening
|
||||||
// Create a childless node
|
// Create a childless node
|
||||||
node = ve.dm.nodeFactory.create( this.data[i].type, [], this.data[i].attributes );
|
node = ve.dm.nodeFactory.create( this.data[i].type, [], this.data[i].attributes );
|
||||||
|
@ -131,7 +131,7 @@ ve.dm.Document = function( data, parentDocument ) {
|
||||||
*/
|
*/
|
||||||
ve.dm.Document.addAnnotationsToData = function( data, annotations ) {
|
ve.dm.Document.addAnnotationsToData = function( data, annotations ) {
|
||||||
// Apply annotations to data
|
// Apply annotations to data
|
||||||
for ( i = 0; i < data.length; i++ ) {
|
for ( var i = 0; i < data.length; i++ ) {
|
||||||
if ( !ve.isArray( data[i] ) ) {
|
if ( !ve.isArray( data[i] ) ) {
|
||||||
data[i] = [data[i]];
|
data[i] = [data[i]];
|
||||||
}
|
}
|
||||||
|
@ -946,55 +946,55 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
* This function updates parentNode, parentType, openingStack and closingStack.
|
* This function updates parentNode, parentType, openingStack and closingStack.
|
||||||
*
|
*
|
||||||
* @param {Object|Array|String} element Linear model element
|
* @param {Object|Array|String} element Linear model element
|
||||||
* @param {Number} index Index in data that this element came from. Used for error reporting only
|
* @param {Number} index Index in data that this element came from (for error reporting only)
|
||||||
*/
|
*/
|
||||||
function writeElement( element, index ) {
|
function writeElement( element, index ) {
|
||||||
var expectedType;
|
var expectedType;
|
||||||
if ( element.type === undefined ) {
|
if ( element.type !== undefined ) {
|
||||||
// Content, do nothing
|
if ( element.type.charAt( 0 ) !== '/' ) {
|
||||||
} else if ( element.type.charAt( 0 ) !== '/' ) {
|
// Opening
|
||||||
// Opening
|
// Check if this opening balances an earlier closing of a node
|
||||||
// Check if this opening balances an earlier closing of a node
|
// that was already in the document. This is only the case if
|
||||||
// that was already in the document. This is only the case if
|
// openingStack is empty (otherwise we still have unclosed nodes from
|
||||||
// openingStack is empty (otherwise we still have unclosed nodes from
|
// within data) and if this opening matches the top of closingStack
|
||||||
// within data) and if this opening matches the top of closingStack
|
if ( openingStack.length === 0 && closingStack.length > 0 &&
|
||||||
if ( openingStack.length === 0 && closingStack.length > 0 &&
|
closingStack[closingStack.length - 1] === element.type
|
||||||
closingStack[closingStack.length - 1] === element.type
|
) {
|
||||||
) {
|
// The top of closingStack is now balanced out, so remove it
|
||||||
// The top of closingStack is now balanced out, so remove it
|
closingStack.pop();
|
||||||
closingStack.pop();
|
} else {
|
||||||
} else {
|
// This opens something new, put it on openingStack
|
||||||
// This opens something new, put it on openingStack
|
openingStack.push( element );
|
||||||
openingStack.push( element );
|
|
||||||
}
|
|
||||||
parentType = element.type;
|
|
||||||
} else {
|
|
||||||
// Closing
|
|
||||||
// Make sure that this closing matches the currently opened node
|
|
||||||
if ( openingStack.length > 0 ) {
|
|
||||||
// The opening was on openingStack, so we're closing
|
|
||||||
// a node that was opened within data. Don't track
|
|
||||||
// that on closingStack
|
|
||||||
expectedType = openingStack.pop().type;
|
|
||||||
} else {
|
|
||||||
// openingStack is empty, so we're closing a node that
|
|
||||||
// was already in the document. This means we have to
|
|
||||||
// reopen it later, so track this on closingStack
|
|
||||||
expectedType = parentNode.getType();
|
|
||||||
closingStack.push( expectedType );
|
|
||||||
parentNode = parentNode.getParent();
|
|
||||||
if ( !parentNode ) {
|
|
||||||
throw 'Inserted data is trying to close the root node ' +
|
|
||||||
'(at index ' + index + ')';
|
|
||||||
}
|
}
|
||||||
}
|
parentType = element.type;
|
||||||
parentType = expectedType;
|
} else {
|
||||||
|
// Closing
|
||||||
|
// Make sure that this closing matches the currently opened node
|
||||||
|
if ( openingStack.length > 0 ) {
|
||||||
|
// The opening was on openingStack, so we're closing
|
||||||
|
// a node that was opened within data. Don't track
|
||||||
|
// that on closingStack
|
||||||
|
expectedType = openingStack.pop().type;
|
||||||
|
} else {
|
||||||
|
// openingStack is empty, so we're closing a node that
|
||||||
|
// was already in the document. This means we have to
|
||||||
|
// reopen it later, so track this on closingStack
|
||||||
|
expectedType = parentNode.getType();
|
||||||
|
closingStack.push( expectedType );
|
||||||
|
parentNode = parentNode.getParent();
|
||||||
|
if ( !parentNode ) {
|
||||||
|
throw 'Inserted data is trying to close the root node ' +
|
||||||
|
'(at index ' + index + ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parentType = expectedType;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
// FIXME this breaks certain input, should fix it up, not scream and die
|
// FIXME this breaks certain input, should fix it up, not scream and die
|
||||||
if ( element.type !== '/' + expectedType ) {
|
if ( element.type !== '/' + expectedType ) {
|
||||||
throw 'Type mismatch, expected /' + expectedType +
|
throw 'Type mismatch, expected /' + expectedType +
|
||||||
' but got ' + element.type + ' (at index ' + index + ')';
|
' but got ' + element.type + ' (at index ' + index + ')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newData.push( element );
|
newData.push( element );
|
||||||
|
@ -1007,7 +1007,10 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
if ( inTextNode && data[i].type !== undefined ) {
|
if ( inTextNode && data[i].type !== undefined ) {
|
||||||
// We're leaving a text node, process fixupStack if needed
|
// We're leaving a text node, process fixupStack if needed
|
||||||
// TODO duplicated code
|
// TODO duplicated code
|
||||||
if ( fixupStack.length > 0 && fixupStack[fixupStack.length - 1].expectedType == '/text' ) {
|
if (
|
||||||
|
fixupStack.length > 0 &&
|
||||||
|
fixupStack[fixupStack.length - 1].expectedType === '/text'
|
||||||
|
) {
|
||||||
popped = fixupStack.pop();
|
popped = fixupStack.pop();
|
||||||
// Go through these in reverse!
|
// Go through these in reverse!
|
||||||
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
||||||
|
@ -1017,7 +1020,8 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
writeElement( popped.reopenElements[j], i );
|
writeElement( popped.reopenElements[j], i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentType = openingStack.length > 0 ? openingStack[openingStack.length - 1] : parentNode.getType();
|
parentType = openingStack.length > 0 ?
|
||||||
|
openingStack[openingStack.length - 1] : parentNode.getType();
|
||||||
}
|
}
|
||||||
if ( data[i].type === undefined || data[i].type.charAt( 0 ) !== '/' ) {
|
if ( data[i].type === undefined || data[i].type.charAt( 0 ) !== '/' ) {
|
||||||
childType = data[i].type || 'text';
|
childType = data[i].type || 'text';
|
||||||
|
@ -1111,20 +1115,31 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
if ( openings.length > 0 ) {
|
if ( openings.length > 0 ) {
|
||||||
// We wrapped the text node, update parentType
|
// We wrapped the text node, update parentType
|
||||||
parentType = childType;
|
parentType = childType;
|
||||||
fixupStack.push( { 'expectedType': '/text', 'openings': openings, 'reopenElements': reopenElements } );
|
fixupStack.push( {
|
||||||
|
'expectedType': '/text',
|
||||||
|
'openings': openings,
|
||||||
|
'reopenElements': reopenElements
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
// If we didn't wrap the text node, then the node we're inserting
|
// If we didn't wrap the text node, then the node we're inserting
|
||||||
// into can have content, so we couldn't have closed anything
|
// into can have content, so we couldn't have closed anything
|
||||||
} else {
|
} else {
|
||||||
fixupStack.push( { 'expectedType': '/' + data[i].type, 'openings': openings, 'reopenElements': reopenElements } );
|
fixupStack.push( {
|
||||||
|
'expectedType': '/' + data[i].type,
|
||||||
|
'openings': openings,
|
||||||
|
'reopenElements': reopenElements
|
||||||
|
} );
|
||||||
parentType = data[i].type;
|
parentType = data[i].type;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Closing
|
// Closing
|
||||||
writeElement( data[i], i );
|
writeElement( data[i], i );
|
||||||
// TODO don't close fixup stuff if the next thing immediately needs to be fixed up as well;
|
// TODO don't close fixup stuff if the next thing immediately needs to be fixed up as
|
||||||
// instead, merge the two wrappers
|
// well; instead, merge the two wrappers
|
||||||
if ( fixupStack.length > 0 && fixupStack[fixupStack.length - 1].expectedType == data[i].type ) {
|
if (
|
||||||
|
fixupStack.length > 0 &&
|
||||||
|
fixupStack[fixupStack.length - 1].expectedType === data[i].type
|
||||||
|
) {
|
||||||
popped = fixupStack.pop();
|
popped = fixupStack.pop();
|
||||||
// Go through these in reverse!
|
// Go through these in reverse!
|
||||||
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
||||||
|
@ -1134,14 +1149,18 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
writeElement( popped.reopenElements[j], i );
|
writeElement( popped.reopenElements[j], i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentType = openingStack.length > 0 ? openingStack[openingStack.length - 1] : parentNode.getType();
|
parentType = openingStack.length > 0 ?
|
||||||
|
openingStack[openingStack.length - 1] : parentNode.getType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( inTextNode ) {
|
if ( inTextNode ) {
|
||||||
// We're leaving a text node, process fixupStack if needed
|
// We're leaving a text node, process fixupStack if needed
|
||||||
// TODO duplicated code
|
// TODO duplicated code
|
||||||
if ( fixupStack.length > 0 && fixupStack[fixupStack.length - 1].expectedType == '/text' ) {
|
if (
|
||||||
|
fixupStack.length > 0 &&
|
||||||
|
fixupStack[fixupStack.length - 1].expectedType === '/text'
|
||||||
|
) {
|
||||||
popped = fixupStack.pop();
|
popped = fixupStack.pop();
|
||||||
// Go through these in reverse!
|
// Go through these in reverse!
|
||||||
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
for ( j = popped.openings.length - 1; j >= 0; j-- ) {
|
||||||
|
@ -1151,7 +1170,8 @@ ve.dm.Document.prototype.fixupInsertion = function( data, offset ) {
|
||||||
writeElement( popped.reopenElements[j], i );
|
writeElement( popped.reopenElements[j], i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentType = openingStack.length > 0 ? openingStack[openingStack.length - 1] : parentNode.getType();
|
parentType = openingStack.length > 0 ?
|
||||||
|
openingStack[openingStack.length - 1] : parentNode.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close unclosed openings
|
// Close unclosed openings
|
||||||
|
|
|
@ -218,7 +218,7 @@ ve.dm.Node.prototype.getClonedElement = function() {
|
||||||
retval.attributes = ve.copyObject( this.attributes );
|
retval.attributes = ve.copyObject( this.attributes );
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this node can be merged with another.
|
* Checks if this node can be merged with another.
|
||||||
|
|
|
@ -80,7 +80,7 @@ ve.dm.Surface.prototype.change = function( transaction, selection ) {
|
||||||
if ( selection && ( !this.selection || !this.selection.equals ( selection ) ) ) {
|
if ( selection && ( !this.selection || !this.selection.equals ( selection ) ) ) {
|
||||||
selection.normalize();
|
selection.normalize();
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
this.emit ('select', this.selection.clone() );
|
this.emit('select', this.selection.clone() );
|
||||||
}
|
}
|
||||||
if ( transaction ) {
|
if ( transaction ) {
|
||||||
this.emit( 'transact', transaction );
|
this.emit( 'transact', transaction );
|
||||||
|
@ -112,7 +112,7 @@ ve.dm.Surface.prototype.breakpoint = function( selection ) {
|
||||||
selection: selection || this.selection.clone()
|
selection: selection || this.selection.clone()
|
||||||
} );
|
} );
|
||||||
this.smallStack = [];
|
this.smallStack = [];
|
||||||
this.emit ( 'history' );
|
this.emit( 'history' );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ ve.dm.Surface.prototype.undo = function() {
|
||||||
}
|
}
|
||||||
var selection = item.selection;
|
var selection = item.selection;
|
||||||
selection.end -= diff;
|
selection.end -= diff;
|
||||||
this.emit ( 'history' );
|
this.emit( 'history' );
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -136,6 +136,7 @@ ve.dm.Surface.prototype.undo = function() {
|
||||||
|
|
||||||
ve.dm.Surface.prototype.redo = function() {
|
ve.dm.Surface.prototype.redo = function() {
|
||||||
this.breakpoint();
|
this.breakpoint();
|
||||||
|
var selection;
|
||||||
if ( this.undoIndex > 0 ) {
|
if ( this.undoIndex > 0 ) {
|
||||||
if ( this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
if ( this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
||||||
var diff = 0;
|
var diff = 0;
|
||||||
|
@ -144,11 +145,11 @@ ve.dm.Surface.prototype.redo = function() {
|
||||||
this.documentModel.commit( item.stack[i] );
|
this.documentModel.commit( item.stack[i] );
|
||||||
diff += item.stack[i].lengthDifference;
|
diff += item.stack[i].lengthDifference;
|
||||||
}
|
}
|
||||||
var selection = item.selection;
|
selection = item.selection;
|
||||||
selection.end += diff;
|
selection.end += diff;
|
||||||
}
|
}
|
||||||
this.undoIndex--;
|
this.undoIndex--;
|
||||||
this.emit ( 'history' );
|
this.emit( 'history' );
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -59,7 +59,8 @@ ve.dm.Transaction.newFromInsertion = function( doc, offset, insertion ) {
|
||||||
*/
|
*/
|
||||||
ve.dm.Transaction.newFromRemoval = function( doc, range ) {
|
ve.dm.Transaction.newFromRemoval = function( doc, range ) {
|
||||||
var tx = new ve.dm.Transaction(),
|
var tx = new ve.dm.Transaction(),
|
||||||
data = doc.getData();
|
data = doc.getData(),
|
||||||
|
i;
|
||||||
// Normalize and validate range
|
// Normalize and validate range
|
||||||
range.normalize();
|
range.normalize();
|
||||||
if ( range.start === range.end ) {
|
if ( range.start === range.end ) {
|
||||||
|
@ -375,11 +376,9 @@ ve.dm.Transaction.newFromWrap = function( doc, range, unwrapOuter, wrapOuter, un
|
||||||
// TODO figure out if we should use the tree/node functions here
|
// TODO figure out if we should use the tree/node functions here
|
||||||
// rather than iterating over offsets, it may or may not be faster
|
// rather than iterating over offsets, it may or may not be faster
|
||||||
for ( i = range.start; i < range.end; i++ ) {
|
for ( i = range.start; i < range.end; i++ ) {
|
||||||
if ( doc.data[i].type === undefined ) {
|
if ( doc.data[i].type !== undefined ) {
|
||||||
// This is a content offset, skip
|
|
||||||
} else {
|
|
||||||
// This is a structural offset
|
// This is a structural offset
|
||||||
if ( doc.data[i].type.charAt( 0 ) != '/' ) {
|
if ( doc.data[i].type.charAt( 0 ) !== '/' ) {
|
||||||
// This is an opening element
|
// This is an opening element
|
||||||
if ( depth === 0 ) {
|
if ( depth === 0 ) {
|
||||||
// We are at the start of a top-level element
|
// We are at the start of a top-level element
|
||||||
|
|
|
@ -245,7 +245,7 @@ ve.dm.TransactionProcessor.processors.replace = function( op ) {
|
||||||
scopeEnd,
|
scopeEnd,
|
||||||
opAdjustment = 0;
|
opAdjustment = 0;
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
if ( operation.type == 'replace' ) {
|
if ( operation.type === 'replace' ) {
|
||||||
var opRemove = this.reversed ? operation.insert : operation.remove,
|
var opRemove = this.reversed ? operation.insert : operation.remove,
|
||||||
opInsert = this.reversed ? operation.remove : operation.insert;
|
opInsert = this.reversed ? operation.remove : operation.insert;
|
||||||
// Update the linear model for this insert
|
// Update the linear model for this insert
|
||||||
|
@ -282,14 +282,14 @@ ve.dm.TransactionProcessor.processors.replace = function( op ) {
|
||||||
// only consistent if both levels are zero.
|
// only consistent if both levels are zero.
|
||||||
for ( i = 0; i < opRemove.length; i++ ) {
|
for ( i = 0; i < opRemove.length; i++ ) {
|
||||||
type = opRemove[i].type;
|
type = opRemove[i].type;
|
||||||
if ( type === undefined ) {
|
if ( type !== undefined ) {
|
||||||
// This is content, ignore
|
if ( type.charAt( 0 ) === '/' ) {
|
||||||
} else if ( type.charAt( 0 ) === '/' ) {
|
// Closing element
|
||||||
// Closing element
|
removeLevel--;
|
||||||
removeLevel--;
|
} else {
|
||||||
} else {
|
// Opening element
|
||||||
// Opening element
|
removeLevel++;
|
||||||
removeLevel++;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Keep track of the scope of the insertion
|
// Keep track of the scope of the insertion
|
||||||
|
@ -298,27 +298,27 @@ ve.dm.TransactionProcessor.processors.replace = function( op ) {
|
||||||
// in which case it's the affected ancestor
|
// in which case it's the affected ancestor
|
||||||
for ( i = 0; i < opInsert.length; i++ ) {
|
for ( i = 0; i < opInsert.length; i++ ) {
|
||||||
type = opInsert[i].type;
|
type = opInsert[i].type;
|
||||||
if ( type === undefined ) {
|
if ( type !== undefined ) {
|
||||||
// This is content, ignore
|
if ( type.charAt( 0 ) === '/' ) {
|
||||||
} else if ( type.charAt( 0 ) === '/' ) {
|
// Closing element
|
||||||
// Closing element
|
insertLevel--;
|
||||||
insertLevel--;
|
if ( insertLevel < minInsertLevel ) {
|
||||||
if ( insertLevel < minInsertLevel ) {
|
// Closing an unopened element at a higher
|
||||||
// Closing an unopened element at a higher
|
// (more negative) level than before
|
||||||
// (more negative) level than before
|
// Lazy-initialize scope
|
||||||
// Lazy-initialize scope
|
scope = scope || this.document.getNodeFromOffset( prevCursor );
|
||||||
scope = scope || this.document.getNodeFromOffset( prevCursor );
|
// Push the full range of the old scope as an affected range
|
||||||
// Push the full range of the old scope as an affected range
|
scopeStart = this.document.getDocumentNode().getOffsetFromNode( scope );
|
||||||
scopeStart = this.document.getDocumentNode().getOffsetFromNode( scope );
|
scopeEnd = scopeStart + scope.getOuterLength();
|
||||||
scopeEnd = scopeStart + scope.getOuterLength();
|
affectedRanges.push( new ve.Range( scopeStart, scopeEnd ) );
|
||||||
affectedRanges.push( new ve.Range( scopeStart, scopeEnd ) );
|
// Update scope
|
||||||
// Update scope
|
scope = scope.getParent() || scope;
|
||||||
scope = scope.getParent() || scope;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Opening element
|
// Opening element
|
||||||
insertLevel++;
|
insertLevel++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update adjustment
|
// Update adjustment
|
||||||
|
@ -374,7 +374,7 @@ ve.dm.TransactionProcessor.prototype.executeOperation = function( op ) {
|
||||||
if ( op.type in ve.dm.TransactionProcessor.processors ) {
|
if ( op.type in ve.dm.TransactionProcessor.processors ) {
|
||||||
ve.dm.TransactionProcessor.processors[op.type].call( this, op );
|
ve.dm.TransactionProcessor.processors[op.type].call( this, op );
|
||||||
} else {
|
} else {
|
||||||
throw 'Invalid operation error. Operation type is not supported: ' + operation.type;
|
throw 'Invalid operation error. Operation type is not supported: ' + op.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*global mw,confirm,alert */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit page target.
|
* Edit page target.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*global mw */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic target.
|
* Generic target.
|
||||||
*
|
*
|
||||||
|
@ -19,7 +21,7 @@ ve.init.Target = function( pageName ) {
|
||||||
this.dom = null;
|
this.dom = null;
|
||||||
this.isMobileDevice = (
|
this.isMobileDevice = (
|
||||||
'ontouchstart' in window ||
|
'ontouchstart' in window ||
|
||||||
( window.DocumentTouch && document instanceof DocumentTouch )
|
( window.DocumentTouch && document instanceof window.DocumentTouch )
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,11 @@ ve.ui.LinkInspector = function( toolbar, context ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var surfaceModel = _this.context.getSurfaceView().getModel(),
|
var hash,
|
||||||
|
surfaceModel = _this.context.getSurfaceView().getModel(),
|
||||||
annotations = _this.getSelectedLinkAnnotations();
|
annotations = _this.getSelectedLinkAnnotations();
|
||||||
// If link annotation exists, clear it.
|
// If link annotation exists, clear it.
|
||||||
for ( var hash in annotations ) {
|
for ( hash in annotations ) {
|
||||||
surfaceModel.annotate( 'clear', annotations[hash] );
|
surfaceModel.annotate( 'clear', annotations[hash] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +67,9 @@ ve.ui.LinkInspector.prototype.getSelectedLinkAnnotations = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ui.LinkInspector.prototype.getAnnotationFromSelection = function() {
|
ve.ui.LinkInspector.prototype.getAnnotationFromSelection = function() {
|
||||||
var annotations = this.getSelectedLinkAnnotations();
|
var hash,
|
||||||
for ( var hash in annotations ) {
|
annotations = this.getSelectedLinkAnnotations();
|
||||||
|
for ( hash in annotations ) {
|
||||||
// Use the first one with a recognized type (there should only be one, but this is just in case)
|
// Use the first one with a recognized type (there should only be one, but this is just in case)
|
||||||
if ( annotations[hash].type === 'link/wikiLink' || annotations[hash].type === 'link/extLink' ) {
|
if ( annotations[hash].type === 'link/wikiLink' || annotations[hash].type === 'link/extLink' ) {
|
||||||
return annotations[hash];
|
return annotations[hash];
|
||||||
|
@ -78,13 +80,14 @@ ve.ui.LinkInspector.prototype.getAnnotationFromSelection = function() {
|
||||||
|
|
||||||
// TODO: This should probably be somewhere else but I needed this here for now.
|
// TODO: This should probably be somewhere else but I needed this here for now.
|
||||||
ve.ui.LinkInspector.prototype.getSelectionText = function() {
|
ve.ui.LinkInspector.prototype.getSelectionText = function() {
|
||||||
var surfaceView = this.context.getSurfaceView(),
|
var i,
|
||||||
|
surfaceView = this.context.getSurfaceView(),
|
||||||
surfaceModel = surfaceView.getModel(),
|
surfaceModel = surfaceView.getModel(),
|
||||||
documentModel = surfaceModel.getDocument(),
|
documentModel = surfaceModel.getDocument(),
|
||||||
data = documentModel.getData( surfaceModel.getSelection() ),
|
data = documentModel.getData( surfaceModel.getSelection() ),
|
||||||
str = '',
|
str = '',
|
||||||
max = Math.min( data.length, 255 );
|
max = Math.min( data.length, 255 );
|
||||||
for ( var i = 0; i < max; i++ ) {
|
for ( i = 0; i < max; i++ ) {
|
||||||
if ( ve.isArray( data[i] ) ) {
|
if ( ve.isArray( data[i] ) ) {
|
||||||
str += data[i][0];
|
str += data[i][0];
|
||||||
} else if( typeof data[i] === 'string' ) {
|
} else if( typeof data[i] === 'string' ) {
|
||||||
|
|
|
@ -158,7 +158,7 @@ ve.FormatDropdownTool.prototype.getMatchingMenuItems = function( nodes ) {
|
||||||
itemLoop:
|
itemLoop:
|
||||||
for ( var j = 0; j < items.length; j++ ) {
|
for ( var j = 0; j < items.length; j++ ) {
|
||||||
var item = items[j];
|
var item = items[j];
|
||||||
if ( item.type == nodeType ) {
|
if ( item.type === nodeType ) {
|
||||||
if ( item.attributes && nodeAttributes ) {
|
if ( item.attributes && nodeAttributes ) {
|
||||||
// Compare attributes
|
// Compare attributes
|
||||||
for ( var key in item.attributes ) {
|
for ( var key in item.attributes ) {
|
||||||
|
@ -166,7 +166,7 @@ ve.FormatDropdownTool.prototype.getMatchingMenuItems = function( nodes ) {
|
||||||
// Node must have all the required attributes
|
// Node must have all the required attributes
|
||||||
!( key in nodeAttributes ) ||
|
!( key in nodeAttributes ) ||
|
||||||
// Use weak comparison because numbers sometimes come through as strings
|
// Use weak comparison because numbers sometimes come through as strings
|
||||||
item.attributes[key] != nodeAttributes[key]
|
item.attributes[key] !== nodeAttributes[key]
|
||||||
) {
|
) {
|
||||||
// Skip to the next menu item
|
// Skip to the next menu item
|
||||||
continue itemLoop;
|
continue itemLoop;
|
||||||
|
|
|
@ -23,7 +23,7 @@ ve.ui.IndentationButtonTool.prototype.onClick = function() {
|
||||||
for ( i = 0; i < this.nodes.length; i++ ) {
|
for ( i = 0; i < this.nodes.length; i++ ) {
|
||||||
listItem = this.nodes[i].getParent();
|
listItem = this.nodes[i].getParent();
|
||||||
if ( listItems.length > 0 ) {
|
if ( listItems.length > 0 ) {
|
||||||
if (listItem != listItems[listItems.length - 1]) {
|
if (listItem !== listItems[listItems.length - 1]) {
|
||||||
listItems.push( listItem );
|
listItems.push( listItem );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,7 +42,8 @@ ve.ui.IndentationButtonTool.prototype.indent = function( listItems ) {
|
||||||
// FIXME old code, doesn't work
|
// FIXME old code, doesn't work
|
||||||
var surface = this.toolbar.surfaceView,
|
var surface = this.toolbar.surfaceView,
|
||||||
styles,
|
styles,
|
||||||
i;
|
i,
|
||||||
|
tx;
|
||||||
|
|
||||||
for ( i = 0; i < listItems.length; i++ ) {
|
for ( i = 0; i < listItems.length; i++ ) {
|
||||||
styles = listItems[i].getElementAttribute( 'styles' );
|
styles = listItems[i].getElementAttribute( 'styles' );
|
||||||
|
@ -62,7 +63,8 @@ ve.ui.IndentationButtonTool.prototype.outdent = function( listItems ) {
|
||||||
// FIXME old code, doesn't work
|
// FIXME old code, doesn't work
|
||||||
var surface = this.toolbar.surfaceView,
|
var surface = this.toolbar.surfaceView,
|
||||||
styles,
|
styles,
|
||||||
i;
|
i,
|
||||||
|
tx;
|
||||||
|
|
||||||
for ( i = 0; i < listItems.length; i++ ) {
|
for ( i = 0; i < listItems.length; i++ ) {
|
||||||
styles = listItems[i].getElementAttribute( 'styles' );
|
styles = listItems[i].getElementAttribute( 'styles' );
|
||||||
|
|
|
@ -202,7 +202,6 @@ ve.ui.Context.prototype.getInspector = function( name ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ui.Context.prototype.addInspector = function( name, inspector ) {
|
ve.ui.Context.prototype.addInspector = function( name, inspector ) {
|
||||||
var _this = this;
|
|
||||||
if ( name in this.inspectors ) {
|
if ( name in this.inspectors ) {
|
||||||
throw 'Duplicate inspector error. Previous registration with the same name: ' + name;
|
throw 'Duplicate inspector error. Previous registration with the same name: ' + name;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +209,7 @@ ve.ui.Context.prototype.addInspector = function( name, inspector ) {
|
||||||
this.inspectors[name] = inspector;
|
this.inspectors[name] = inspector;
|
||||||
// Iframe build code below.
|
// Iframe build code below.
|
||||||
// TODO: Rework this to allow multiple inspectors
|
// TODO: Rework this to allow multiple inspectors
|
||||||
$styleLink =
|
var $styleLink =
|
||||||
$('<link />')
|
$('<link />')
|
||||||
.attr({
|
.attr({
|
||||||
'rel': 'stylesheet',
|
'rel': 'stylesheet',
|
||||||
|
|
|
@ -26,7 +26,6 @@ ve.ui.Toolbar = function( $container, surfaceView, config ) {
|
||||||
{ 'name': 'list', 'items' : ['number', 'bullet', 'outdent', 'indent'] }
|
{ 'name': 'list', 'items' : ['number', 'bullet', 'outdent', 'indent'] }
|
||||||
];
|
];
|
||||||
this.setup();
|
this.setup();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
@ -44,7 +43,8 @@ ve.ui.Toolbar.prototype.updateTools = function() {
|
||||||
range = model.getSelection(),
|
range = model.getSelection(),
|
||||||
startNode,
|
startNode,
|
||||||
endNode,
|
endNode,
|
||||||
_this = this;
|
_this = this,
|
||||||
|
i;
|
||||||
|
|
||||||
if ( range !== null ) {
|
if ( range !== null ) {
|
||||||
if ( range.from === range.to ){
|
if ( range.from === range.to ){
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*global mw */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VisualEditor User Interface namespace.
|
* VisualEditor User Interface namespace.
|
||||||
*
|
*
|
||||||
|
|
|
@ -54,7 +54,7 @@ ve.BranchNode.prototype.indexOf = function( node ) {
|
||||||
* @param {ve.Node} root Node to use as root
|
* @param {ve.Node} root Node to use as root
|
||||||
*/
|
*/
|
||||||
ve.BranchNode.prototype.setRoot = function( root ) {
|
ve.BranchNode.prototype.setRoot = function( root ) {
|
||||||
if ( root == this.root ) {
|
if ( root === this.root ) {
|
||||||
// Nothing to do, don't recurse into all descendants
|
// Nothing to do, don't recurse into all descendants
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ ve.BranchNode.prototype.setRoot = function( root ) {
|
||||||
* @param {ve.Document} root Node to use as root
|
* @param {ve.Document} root Node to use as root
|
||||||
*/
|
*/
|
||||||
ve.BranchNode.prototype.setDocument = function( doc ) {
|
ve.BranchNode.prototype.setDocument = function( doc ) {
|
||||||
if ( doc == this.doc ) {
|
if ( doc === this.doc ) {
|
||||||
// Nothing to do, don't recurse into all descendants
|
// Nothing to do, don't recurse into all descendants
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ ve.BranchNode.prototype.getNodeFromOffset = function( offset, shallow ) {
|
||||||
childNode;
|
childNode;
|
||||||
for ( var i = 0, length = this.children.length; i < length; i++ ) {
|
for ( var i = 0, length = this.children.length; i < length; i++ ) {
|
||||||
childNode = this.children[i];
|
childNode = this.children[i];
|
||||||
if ( offset == nodeOffset ) {
|
if ( offset === nodeOffset ) {
|
||||||
// The requested offset is right before childNode,
|
// The requested offset is right before childNode,
|
||||||
// so it's not inside any of this's children, but inside this
|
// so it's not inside any of this's children, but inside this
|
||||||
return this;
|
return this;
|
||||||
|
@ -121,7 +121,7 @@ ve.BranchNode.prototype.getNodeFromOffset = function( offset, shallow ) {
|
||||||
}
|
}
|
||||||
nodeOffset += nodeLength;
|
nodeOffset += nodeLength;
|
||||||
}
|
}
|
||||||
if ( offset == nodeOffset ) {
|
if ( offset === nodeOffset ) {
|
||||||
// The requested offset is right before this.children[i],
|
// The requested offset is right before this.children[i],
|
||||||
// so it's not inside any of this's children, but inside this
|
// so it's not inside any of this's children, but inside this
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -113,11 +113,11 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
||||||
// Does the node have wrapping elements around it
|
// Does the node have wrapping elements around it
|
||||||
isWrapped = node.isWrapped();
|
isWrapped = node.isWrapped();
|
||||||
// Is the start between prevNode and node or between the parent's opening and node?
|
// Is the start between prevNode and node or between the parent's opening and node?
|
||||||
startBetween = isWrapped ? start == left - 1 : start == left;
|
startBetween = isWrapped ? start === left - 1 : start === left;
|
||||||
// Is the end between node and nextNode or between node and the parent's closing?
|
// Is the end between node and nextNode or between node and the parent's closing?
|
||||||
endBetween = isWrapped ? end == right + 1 : end == right;
|
endBetween = isWrapped ? end === right + 1 : end === right;
|
||||||
|
|
||||||
if ( start == end && ( startBetween || endBetween ) && node.isWrapped() ) {
|
if ( start === end && ( startBetween || endBetween ) && node.isWrapped() ) {
|
||||||
// Empty range in the parent, outside of any child
|
// Empty range in the parent, outside of any child
|
||||||
nodeRange = new ve.Range( currentFrame.startOffset,
|
nodeRange = new ve.Range( currentFrame.startOffset,
|
||||||
currentFrame.startOffset + currentFrame.node.getLength()
|
currentFrame.startOffset + currentFrame.node.getLength()
|
||||||
|
@ -204,8 +204,10 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
||||||
} ];
|
} ];
|
||||||
}
|
}
|
||||||
} else if ( startInside ) {
|
} else if ( startInside ) {
|
||||||
if ( ( mode === 'leaves' || mode === 'covered' )
|
if (
|
||||||
&& node.children && node.children.length
|
( mode === 'leaves' || mode === 'covered' ) &&
|
||||||
|
node.children &&
|
||||||
|
node.children.length
|
||||||
) {
|
) {
|
||||||
// node is a branch node and the start is inside it
|
// node is a branch node and the start is inside it
|
||||||
// Descend into it
|
// Descend into it
|
||||||
|
@ -262,8 +264,10 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
} else if ( endInside ) {
|
} else if ( endInside ) {
|
||||||
if ( ( mode === 'leaves' || mode === 'covered' )
|
if (
|
||||||
&& node.children && node.children.length
|
( mode === 'leaves' || mode === 'covered' ) &&
|
||||||
|
node.children &&
|
||||||
|
node.children.length
|
||||||
) {
|
) {
|
||||||
// node is a branch node and the end is inside it
|
// node is a branch node and the end is inside it
|
||||||
// Descend into it
|
// Descend into it
|
||||||
|
|
|
@ -159,7 +159,7 @@ ve.Surface.prototype.makeMainEditorToolbarFloat = function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var $toolbarWrapper = this.toolbarWrapper.top,
|
var $toolbarWrapper = this.toolbarWrapper.top,
|
||||||
$toolbar = $toolbarWrapper.find( '.es-toolbar' );
|
$toolbar = $toolbarWrapper.find( '.es-toolbar' ),
|
||||||
$window = $( window );
|
$window = $( window );
|
||||||
|
|
||||||
$window.scroll( function() {
|
$window.scroll( function() {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*global mw */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VisualEditor namespace.
|
* VisualEditor namespace.
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,7 +120,7 @@ test( 'getHtml', 22, function() {
|
||||||
}],
|
}],
|
||||||
'g',
|
'g',
|
||||||
'h',
|
'h',
|
||||||
'i',
|
'i',
|
||||||
{ 'type': '/paragraph' }
|
{ 'type': '/paragraph' }
|
||||||
],
|
],
|
||||||
'html': 'abc<b><i><u>def</u></i></b>ghi'
|
'html': 'abc<b><i><u>def</u></i></b>ghi'
|
||||||
|
@ -147,7 +147,7 @@ test( 'getHtml', 22, function() {
|
||||||
}],
|
}],
|
||||||
'g',
|
'g',
|
||||||
'h',
|
'h',
|
||||||
'i',
|
'i',
|
||||||
{ 'type': '/paragraph' }
|
{ 'type': '/paragraph' }
|
||||||
],
|
],
|
||||||
'html': 'abc<b><i><u>d</u></i></b><i><u>e<b>f</b></u></i>ghi'
|
'html': 'abc<b><i><u>d</u></i></b><i><u>e<b>f</b></u></i>ghi'
|
||||||
|
@ -174,7 +174,7 @@ test( 'getHtml', 22, function() {
|
||||||
}],
|
}],
|
||||||
'g',
|
'g',
|
||||||
'h',
|
'h',
|
||||||
'i',
|
'i',
|
||||||
{ 'type': '/paragraph' }
|
{ 'type': '/paragraph' }
|
||||||
],
|
],
|
||||||
'html': 'abc<i><u><b>d</b>e<b>f</b></u></i>ghi'
|
'html': 'abc<i><u><b>d</b>e<b>f</b></u></i>ghi'
|
||||||
|
@ -200,7 +200,7 @@ test( 'getHtml', 22, function() {
|
||||||
}],
|
}],
|
||||||
'g',
|
'g',
|
||||||
'h',
|
'h',
|
||||||
'i',
|
'i',
|
||||||
{ 'type': '/paragraph' }
|
{ 'type': '/paragraph' }
|
||||||
],
|
],
|
||||||
'html': 'abc<i><u><b>d</b></u></i><u><b>ef</b></u>ghi'
|
'html': 'abc<i><u><b>d</b></u></i><u><b>ef</b></u>ghi'
|
||||||
|
|
|
@ -102,7 +102,7 @@ test( 'annotate', 1, function() {
|
||||||
for ( var i = 0; i < cases.length; i++ ) {
|
for ( var i = 0; i < cases.length; i++ ) {
|
||||||
surface = new ve.dm.SurfaceStub( cases[i].data );
|
surface = new ve.dm.SurfaceStub( cases[i].data );
|
||||||
surface.change( null, new ve.Range( 0, surface.getDocument().getData().length ) );
|
surface.change( null, new ve.Range( 0, surface.getDocument().getData().length ) );
|
||||||
surface.annotate( cases[i].annotate['method'], cases[i].annotate['annotation'] );
|
surface.annotate( cases[i].annotate.method, cases[i].annotate.annotation );
|
||||||
deepEqual( surface.getDocument().getData(), cases[i].expected, cases[i].msg );
|
deepEqual( surface.getDocument().getData(), cases[i].expected, cases[i].msg );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,35 +148,7 @@ test( 'traverseLeafNodes', 1, function() {
|
||||||
'desc': 'Passing a sibling for from results in an exception'
|
'desc': 'Passing a sibling for from results in an exception'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
var count=0;
|
|
||||||
for(var t=0;t<tests.length;t++) {
|
|
||||||
if(tests[t].hasOwnProperty('reverse')) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
expect (count);
|
|
||||||
for ( var i = 0; i < tests.length; i++ ) {
|
|
||||||
executeTest( tests[i] );
|
|
||||||
if ( tests[i].reverse !== undefined ) {
|
|
||||||
var reversed = {
|
|
||||||
'node': tests[i].node,
|
|
||||||
'from': tests[i].from,
|
|
||||||
'callback': tests[i].callback,
|
|
||||||
'exception': tests[i].exception,
|
|
||||||
'isReversed': true,
|
|
||||||
'desc': tests[i].reverseDesc || tests[i].desc + ' (in reverse)'
|
|
||||||
};
|
|
||||||
if ( tests[i].output !== undefined && tests[i].reverse === true ) {
|
|
||||||
reversed.output = tests[i].output.reverse();
|
|
||||||
} else {
|
|
||||||
reversed.output = tests[i].reverse;
|
|
||||||
}
|
|
||||||
executeTest( reversed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function executeTest( test ) {
|
function executeTest( test ) {
|
||||||
var realLeaves = [],
|
var realLeaves = [],
|
||||||
callback = function( node ) {
|
callback = function( node ) {
|
||||||
|
@ -199,4 +171,33 @@ test( 'traverseLeafNodes', 1, function() {
|
||||||
ok( ve.compareArrays( realLeaves, test.output ), test.desc );
|
ok( ve.compareArrays( realLeaves, test.output ), test.desc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} );
|
|
||||||
|
var count = 0;
|
||||||
|
for ( var t = 0; t < tests.length; t++ ) {
|
||||||
|
if ( tests[t].hasOwnProperty( 'reverse' ) ) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect( count );
|
||||||
|
for ( var i = 0; i < tests.length; i++ ) {
|
||||||
|
executeTest( tests[i] );
|
||||||
|
if ( tests[i].reverse !== undefined ) {
|
||||||
|
var reversed = {
|
||||||
|
'node': tests[i].node,
|
||||||
|
'from': tests[i].from,
|
||||||
|
'callback': tests[i].callback,
|
||||||
|
'exception': tests[i].exception,
|
||||||
|
'isReversed': true,
|
||||||
|
'desc': tests[i].reverseDesc || tests[i].desc + ' (in reverse)'
|
||||||
|
};
|
||||||
|
if ( tests[i].output !== undefined && tests[i].reverse === true ) {
|
||||||
|
reversed.output = tests[i].output.reverse();
|
||||||
|
} else {
|
||||||
|
reversed.output = tests[i].reverse;
|
||||||
|
}
|
||||||
|
executeTest( reversed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
|
@ -296,7 +296,8 @@ ve.example.getSelectNodesCases = function( doc ) {
|
||||||
* @returns {Object} Summary of node tree
|
* @returns {Object} Summary of node tree
|
||||||
*/
|
*/
|
||||||
ve.example.getNodeTreeSummary = function( node, shallow ) {
|
ve.example.getNodeTreeSummary = function( node, shallow ) {
|
||||||
var summary = {
|
var i,
|
||||||
|
summary = {
|
||||||
'getType': node.getType(),
|
'getType': node.getType(),
|
||||||
'getLength': node.getLength(),
|
'getLength': node.getLength(),
|
||||||
'getOuterLength': node.getOuterLength(),
|
'getOuterLength': node.getOuterLength(),
|
||||||
|
@ -306,7 +307,7 @@ ve.example.getNodeTreeSummary = function( node, shallow ) {
|
||||||
summary['children.length'] = node.children.length;
|
summary['children.length'] = node.children.length;
|
||||||
if ( !shallow ) {
|
if ( !shallow ) {
|
||||||
summary.children = [];
|
summary.children = [];
|
||||||
for ( var i = 0; i < node.children.length; i++ ) {
|
for ( i = 0; i < node.children.length; i++ ) {
|
||||||
summary.children.push( ve.example.getNodeTreeSummary( node.children[i] ) );
|
summary.children.push( ve.example.getNodeTreeSummary( node.children[i] ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,12 +326,13 @@ ve.example.getNodeTreeSummary = function( node, shallow ) {
|
||||||
* @returns {Object} Summary of selection
|
* @returns {Object} Summary of selection
|
||||||
*/
|
*/
|
||||||
ve.example.getNodeSelectionSummary = function( selection ) {
|
ve.example.getNodeSelectionSummary = function( selection ) {
|
||||||
var summary = {
|
var i,
|
||||||
|
summary = {
|
||||||
'length': selection.length
|
'length': selection.length
|
||||||
};
|
};
|
||||||
if ( selection.length ) {
|
if ( selection.length ) {
|
||||||
summary.results = [];
|
summary.results = [];
|
||||||
for ( var i = 0; i < selection.length; i++ ) {
|
for ( i = 0; i < selection.length; i++ ) {
|
||||||
summary.results.push( {
|
summary.results.push( {
|
||||||
'node': ve.example.getNodeTreeSummary( selection[i].node, true ),
|
'node': ve.example.getNodeTreeSummary( selection[i].node, true ),
|
||||||
'range': selection[i].range,
|
'range': selection[i].range,
|
||||||
|
@ -382,16 +384,18 @@ ve.example.getDomElementSummary = function( element ) {
|
||||||
* @param {ve.Node} Node at given path
|
* @param {ve.Node} Node at given path
|
||||||
*/
|
*/
|
||||||
ve.example.lookupNode = function( root ) {
|
ve.example.lookupNode = function( root ) {
|
||||||
var node = root;
|
var i,
|
||||||
for ( var i = 1; i < arguments.length; i++ ) {
|
node = root;
|
||||||
|
for ( i = 1; i < arguments.length; i++ ) {
|
||||||
node = node.children[arguments[i]];
|
node = node.children[arguments[i]];
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.example.createDomElement = function( type, attributes ) {
|
ve.example.createDomElement = function( type, attributes ) {
|
||||||
var element = document.createElement( type );
|
var key,
|
||||||
for ( var key in attributes ) {
|
element = document.createElement( type );
|
||||||
|
for ( key in attributes ) {
|
||||||
element.setAttribute( key, attributes[key] );
|
element.setAttribute( key, attributes[key] );
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
|
|
Loading…
Reference in a new issue