2011-12-05 21:10:19 +00:00
|
|
|
/**
|
2012-02-06 23:50:56 +00:00
|
|
|
* Creates an ve.ui.ListButtonTool object.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-12-05 21:10:19 +00:00
|
|
|
* @class
|
|
|
|
* @constructor
|
2012-02-06 23:50:56 +00:00
|
|
|
* @extends {ve.ui.ButtonTool}
|
|
|
|
* @param {ve.ui.Toolbar} toolbar
|
2011-12-05 21:10:19 +00:00
|
|
|
* @param {String} name
|
|
|
|
*/
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.ListButtonTool = function( toolbar, name, title, data ) {
|
2011-12-05 21:10:19 +00:00
|
|
|
// Inheritance
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.ButtonTool.call( this, toolbar, name, title );
|
2011-12-05 21:10:19 +00:00
|
|
|
|
|
|
|
// Properties
|
2011-12-04 02:59:53 +00:00
|
|
|
this.data = data;
|
|
|
|
this.nodes = [];
|
|
|
|
};
|
|
|
|
|
2011-12-05 21:10:19 +00:00
|
|
|
/* Methods */
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.ListButtonTool.prototype.list = function( nodes, style ) {
|
2012-06-20 19:27:46 +00:00
|
|
|
var surfaceView = this.toolbar.getSurfaceView(),
|
|
|
|
surfaceModel = surfaceView.getModel(),
|
|
|
|
selection = surfaceModel.getSelection(),
|
|
|
|
doc = surfaceModel.getDocument(),
|
|
|
|
leaves = doc.selectNodes( selection, 'leaves' ),
|
|
|
|
wrapGap = null,
|
|
|
|
prevList,
|
|
|
|
firstCoveredSibling,
|
|
|
|
lastCoveredSibling,
|
|
|
|
node,
|
|
|
|
parentNode,
|
|
|
|
grandparentNode,
|
|
|
|
thisNode,
|
|
|
|
convertRange,
|
|
|
|
lastOffset = selection.to;
|
|
|
|
// Iterate through covered leaf nodes and process either a conversion or wrapping for groups of
|
|
|
|
// consecutive covered siblings - for conversion, the entire list will be changed
|
|
|
|
for ( var i = 0; i < leaves.length; i++ ) {
|
|
|
|
node = leaves[i].node;
|
|
|
|
if ( node.isContent() ) {
|
|
|
|
node = node.getParent();
|
|
|
|
}
|
|
|
|
parentNode = node.getParent();
|
|
|
|
if ( parentNode.getType() === 'listItem' ) {
|
|
|
|
// Convert it
|
|
|
|
grandparentNode = parentNode.getParent();
|
|
|
|
if ( grandparentNode !== prevList && grandparentNode.getType() === 'list' ) {
|
|
|
|
// Change the list style
|
|
|
|
surfaceModel.change(
|
|
|
|
ve.dm.Transaction.newFromAttributeChange(
|
|
|
|
doc, grandparentNode.getOffset(), 'style', style
|
|
|
|
),
|
|
|
|
selection
|
|
|
|
);
|
|
|
|
// Skip this one next time
|
|
|
|
prevList = grandparentNode;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Wrap it and it's covered siblings
|
|
|
|
firstCoveredSibling = node;
|
|
|
|
// Seek forward to the last covered sibling
|
|
|
|
thisNode = firstCoveredSibling;
|
|
|
|
do {
|
|
|
|
lastCoveredSibling = thisNode;
|
|
|
|
i++;
|
|
|
|
if ( leaves[i] === undefined ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
thisNode = leaves[i].node;
|
|
|
|
if ( thisNode.isContent() ) {
|
|
|
|
thisNode = thisNode.getParent();
|
|
|
|
}
|
|
|
|
} while ( thisNode.getParent() === parentNode );
|
|
|
|
convertRange = new ve.Range(
|
|
|
|
firstCoveredSibling.getOuterRange().start, lastCoveredSibling.getOuterRange().end
|
|
|
|
);
|
|
|
|
// Convert everything to paragraphs first
|
|
|
|
surfaceModel.change(
|
|
|
|
ve.dm.Transaction.newFromContentBranchConversion( doc, convertRange, 'paragraph' ),
|
|
|
|
selection
|
|
|
|
);
|
|
|
|
// Wrap everything in a list and each content branch in a listItem
|
|
|
|
surfaceModel.change(
|
|
|
|
ve.dm.Transaction.newFromWrap(
|
|
|
|
doc,
|
|
|
|
convertRange,
|
|
|
|
[],
|
|
|
|
[{ 'type': 'list', 'attributes': { 'style': style } }],
|
|
|
|
[],
|
|
|
|
[{ 'type': 'listItem' }]
|
|
|
|
)
|
|
|
|
// TODO: Come up with a proper range object and use it here
|
|
|
|
);
|
|
|
|
}
|
2011-12-07 22:57:17 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
ve.ui.ListButtonTool.prototype.unlist = function( node ){
|
|
|
|
var surface = this.toolbar.surfaceView,
|
|
|
|
model = surface.getModel(),
|
|
|
|
doc = model.getDocument(),
|
|
|
|
selection = model.getSelection(),
|
|
|
|
siblings = doc.selectNodes( selection, 'siblings'),
|
|
|
|
listNode,
|
|
|
|
tx;
|
|
|
|
|
|
|
|
if ( siblings.length === 0 ) {
|
|
|
|
return ;
|
2011-12-08 04:18:15 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
|
|
|
|
listNode = siblings[0].node;
|
|
|
|
// Get the parent list node
|
|
|
|
while( listNode && listNode.getType() !== 'list' ) {
|
|
|
|
listNode = listNode.getParent();
|
2011-12-08 04:18:15 +00:00
|
|
|
}
|
2011-12-06 00:49:00 +00:00
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
tx = ve.dm.Transaction.newFromWrap(
|
|
|
|
doc,
|
|
|
|
listNode.getRange(),
|
|
|
|
[ { 'type': 'list' } ],
|
|
|
|
[],
|
|
|
|
[ { 'type': 'listItem' } ],
|
|
|
|
[]
|
|
|
|
);
|
2011-12-08 04:18:15 +00:00
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
model.change( tx );
|
2011-12-07 22:57:17 +00:00
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.ListButtonTool.prototype.onClick = function() {
|
2011-12-10 00:06:37 +00:00
|
|
|
this.toolbar.surfaceView.model.breakpoint();
|
2011-12-07 22:57:17 +00:00
|
|
|
if ( !this.$.hasClass( 'es-toolbarButtonTool-down' ) ) {
|
|
|
|
this.list( this.nodes, this.name );
|
|
|
|
} else {
|
|
|
|
this.unlist( this.nodes );
|
2011-12-04 02:59:53 +00:00
|
|
|
}
|
2011-12-10 00:06:37 +00:00
|
|
|
this.toolbar.surfaceView.model.breakpoint();
|
2011-12-04 02:59:53 +00:00
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.ListButtonTool.prototype.updateState = function( annotations, nodes ) {
|
2012-06-20 22:01:18 +00:00
|
|
|
var surfaceView = this.toolbar.getSurfaceView(),
|
|
|
|
surfaceModel = surfaceView.getModel(),
|
|
|
|
doc = surfaceView.getDocument(),
|
|
|
|
selection = surfaceModel.getSelection(),
|
|
|
|
leaves = doc.selectNodes( selection, 'leaves' );
|
2012-06-20 01:20:28 +00:00
|
|
|
|
2012-06-20 22:01:18 +00:00
|
|
|
function areListItemsOfStyle( leaves, style ){
|
2012-06-20 01:20:28 +00:00
|
|
|
var listNode = null;
|
2012-06-20 22:01:18 +00:00
|
|
|
|
|
|
|
for ( var i=0; i < leaves.length; i++ ) {
|
|
|
|
listNode = leaves[i].node;
|
2012-06-20 01:20:28 +00:00
|
|
|
// Get the list node
|
|
|
|
while( listNode && listNode.getType() !== 'list' ) {
|
|
|
|
listNode = listNode.getParent();
|
2012-06-20 22:01:18 +00:00
|
|
|
if ( listNode === null ) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-04 02:59:53 +00:00
|
|
|
}
|
2012-06-20 22:01:18 +00:00
|
|
|
if( listNode.getModel().getAttribute('style') !== style ) {
|
|
|
|
return false;
|
2011-12-04 02:59:53 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-20 22:01:18 +00:00
|
|
|
return true;
|
2011-12-04 02:59:53 +00:00
|
|
|
}
|
2011-12-07 22:57:17 +00:00
|
|
|
|
2012-06-20 22:01:18 +00:00
|
|
|
if ( areListItemsOfStyle( leaves, this.name ) ) {
|
2011-12-04 02:59:53 +00:00
|
|
|
this.$.addClass( 'es-toolbarButtonTool-down' );
|
|
|
|
} else {
|
2011-12-07 22:57:17 +00:00
|
|
|
this.$.removeClass( 'es-toolbarButtonTool-down' );
|
2011-12-04 02:59:53 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-05 21:10:19 +00:00
|
|
|
/* Registration */
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.Tool.tools.number = {
|
|
|
|
'constructor': ve.ui.ListButtonTool,
|
2011-12-09 21:16:42 +00:00
|
|
|
'name': 'number',
|
2012-06-20 22:01:18 +00:00
|
|
|
'title': ve.msg( 'visualeditor-listbutton-number-tooltip' )
|
2011-12-04 02:59:53 +00:00
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.ui.Tool.tools.bullet = {
|
|
|
|
'constructor': ve.ui.ListButtonTool,
|
2011-12-09 21:16:42 +00:00
|
|
|
'name': 'bullet',
|
2012-06-20 22:01:18 +00:00
|
|
|
'title': ve.msg( 'visualeditor-listbutton-bullet-tooltip' )
|
2011-12-04 02:59:53 +00:00
|
|
|
};
|
|
|
|
|
2011-12-05 21:10:19 +00:00
|
|
|
/* Inheritance */
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.extendClass( ve.ui.ListButtonTool, ve.ui.ButtonTool );
|