mediawiki-extensions-Visual.../modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js
Alex Monk 871a0a288f Unbreak meta dialog cancel button
Don't try to apply page settings changes to meta list unless we're actually
applying. "Cancel" shouldn't apply changes, we have another button for that.

Bug: T97682
Change-Id: I9eae20c3946b315413340268e44537cdbec2e455
2015-08-03 22:36:53 +00:00

306 lines
8.4 KiB
JavaScript

/*!
* VisualEditor user interface MWCategoriesPage class.
*
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* MediaWiki meta dialog categories page.
*
* @class
* @extends OO.ui.PageLayout
*
* @constructor
* @param {string} name Unique symbolic name of page
* @param {Object} [config] Configuration options
* @cfg {jQuery} [$overlay] Overlay to render dropdowns in
*/
ve.ui.MWCategoriesPage = function VeUiMWCategoriesPage( name, config ) {
// Configuration initialization
config = config || {};
// Parent constructor
OO.ui.PageLayout.call( this, name, config );
// Properties
this.metaList = null;
this.defaultSortKeyTouched = false;
this.fallbackDefaultSortKey = mw.config.get( 'wgTitle' );
this.categoriesFieldset = new OO.ui.FieldsetLayout( {
label: ve.msg( 'visualeditor-dialog-meta-categories-data-label' ),
icon: 'tag'
} );
this.categoryOptionsFieldset = new OO.ui.FieldsetLayout( {
label: ve.msg( 'visualeditor-dialog-meta-categories-options' ),
icon: 'settings'
} );
this.categoryWidget = new ve.ui.MWCategoryWidget( {
$overlay: config.$overlay
} );
this.defaultSortInput = new OO.ui.TextInputWidget( {
placeholder: this.fallbackDefaultSortKey
} );
this.defaultSortInput.$element.addClass( 've-ui-mwCategoriesPage-defaultsort' );
this.defaultSort = new OO.ui.FieldLayout(
this.defaultSortInput,
{
align: 'top',
label: ve.msg( 'visualeditor-dialog-meta-categories-defaultsort-label' ),
help: ve.msg( 'visualeditor-dialog-meta-categories-defaultsort-help' )
}
);
// Events
this.categoryWidget.connect( this, {
newCategory: 'onNewCategory',
updateSortkey: 'onUpdateSortKey'
} );
this.defaultSortInput.connect( this, {
change: 'onDefaultSortChange'
} );
// Initialization
this.categoriesFieldset.$element.append( this.categoryWidget.$element );
this.categoryOptionsFieldset.addItems( [ this.defaultSort ] );
this.$element.append( this.categoriesFieldset.$element, this.categoryOptionsFieldset.$element );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWCategoriesPage, OO.ui.PageLayout );
/* Methods */
/**
* @inheritdoc
*/
ve.ui.MWCategoriesPage.prototype.setOutlineItem = function ( outlineItem ) {
// Parent method
OO.ui.PageLayout.prototype.setOutlineItem.call( this, outlineItem );
if ( this.outlineItem ) {
this.outlineItem
.setIcon( 'tag' )
.setLabel( ve.msg( 'visualeditor-dialog-meta-categories-section' ) );
}
};
/**
* Handle category default sort change events.
*
* @param {string} value Default sort value
*/
ve.ui.MWCategoriesPage.prototype.onDefaultSortChange = function ( value ) {
this.categoryWidget.setDefaultSortKey( value === '' ? this.fallbackDefaultSortKey : value );
this.defaultSortKeyTouched = true;
};
/**
* Inserts new category into meta list
*
* @param {Object} item
* @param {ve.dm.MWCategoryMetaItem} [beforeMetaItem] Meta item to insert before,
* or undefined to go at the end
*/
ve.ui.MWCategoriesPage.prototype.onNewCategory = function ( item, beforeMetaItem ) {
// Insert new metaList item
if ( beforeMetaItem ) {
this.insertMetaListItem(
this.getCategoryItemForInsertion( item ),
beforeMetaItem.getOffset(),
beforeMetaItem.getIndex()
);
} else {
this.insertMetaListItem( this.getCategoryItemForInsertion( item ) );
}
};
/**
* Removes and re-inserts updated category widget item
*
* @param {Object} item
*/
ve.ui.MWCategoriesPage.prototype.onUpdateSortKey = function ( item ) {
// Replace meta item with updated one
item.metaItem.replaceWith( this.getCategoryItemForInsertion( item, item.metaItem.getElement() ) );
};
/**
* Bound to MetaList insert event for adding meta dialog components.
*
* @param {ve.dm.MetaItem} metaItem
*/
ve.ui.MWCategoriesPage.prototype.onMetaListInsert = function ( metaItem ) {
// Responsible for adding UI components
if ( metaItem.element.type === 'mwCategory' ) {
this.categoryWidget.addItems(
[ this.getCategoryItemFromMetaListItem( metaItem ) ],
this.metaList.findItem( metaItem.getOffset(), metaItem.getIndex(), 'mwCategory' )
);
}
};
/**
* Bound to MetaList insert event for removing meta dialog components.
*
* @param {ve.dm.MetaItem} metaItem
*/
ve.ui.MWCategoriesPage.prototype.onMetaListRemove = function ( metaItem ) {
var item;
if ( metaItem.element.type === 'mwCategory' ) {
item = this.categoryWidget.categories[this.getCategoryItemFromMetaListItem( metaItem ).value];
this.categoryWidget.removeItems( [ item ] );
}
};
/**
* Get default sort key item.
*
* @returns {string} Default sort key item
*/
ve.ui.MWCategoriesPage.prototype.getDefaultSortKeyItem = function () {
return this.metaList.getItemsInGroup( 'mwDefaultSort' )[0] || null;
};
/**
* Get array of category items from meta list
*
* @returns {Object[]} items
*/
ve.ui.MWCategoriesPage.prototype.getCategoryItems = function () {
var i,
items = [],
categories = this.metaList.getItemsInGroup( 'mwCategory' );
// Loop through MwCategories and build out items
for ( i = 0; i < categories.length; i++ ) {
items.push( this.getCategoryItemFromMetaListItem( categories[i] ) );
}
return items;
};
/**
* Gets category item from meta list item
*
* @param {ve.dm.MWCategoryMetaItem} metaItem
* @returns {Object} item
*/
ve.ui.MWCategoriesPage.prototype.getCategoryItemFromMetaListItem = function ( metaItem ) {
var title = mw.Title.newFromText( metaItem.element.attributes.category ),
value = title ? title.getMainText() : '';
return {
name: metaItem.element.attributes.category,
value: value,
// TODO: sortkey is lcase, make consistent throughout CategoryWidget
sortKey: metaItem.element.attributes.sortkey,
metaItem: metaItem
};
};
/**
* Get metaList like object to insert from item
*
* @param {Object} item category widget item
* @param {Object} [oldData] Metadata object that was previously associated with this item, if any
* @returns {Object} metaBase
*/
ve.ui.MWCategoriesPage.prototype.getCategoryItemForInsertion = function ( item, oldData ) {
var newData = {
attributes: { category: item.name, sortkey: item.sortKey || '' },
type: 'mwCategory'
};
if ( oldData ) {
return ve.extendObject( {}, oldData, newData );
}
return newData;
};
/**
* Inserts a meta list item
*
* @param {Object} metaBase meta list insert object
* @param {number} [offset] Offset of the meta items within the document
* @param {number} [index] Index of the meta item within the group of meta items at this offset
*/
ve.ui.MWCategoriesPage.prototype.insertMetaListItem = function ( metaBase, offset, index ) {
this.metaList.insertMeta( metaBase, offset, index );
};
/**
* Setup categories page.
*
* @param {ve.dm.MetaList} metaList Meta list
* @param {Object} [data] Dialog setup data
*/
ve.ui.MWCategoriesPage.prototype.setup = function ( metaList ) {
var defaultSortKeyItem,
page = this;
this.metaList = metaList;
this.metaList.connect( this, {
insert: 'onMetaListInsert',
remove: 'onMetaListRemove'
} );
defaultSortKeyItem = this.getDefaultSortKeyItem();
this.categoryWidget.addItems( this.getCategoryItems() );
this.defaultSortInput.setValue(
defaultSortKeyItem ? defaultSortKeyItem.getAttribute( 'content' ) : ''
);
this.defaultSortKeyTouched = false;
// Update input position once visible
setTimeout( function () {
page.categoryWidget.fitInput();
} );
};
/**
* Tear down the page. This is called when the MWMetaDialog is torn down.
*
* @param {Object} [data] Dialog tear down data
*/
ve.ui.MWCategoriesPage.prototype.teardown = function ( data ) {
var currentDefaultSortKeyItem = this.getDefaultSortKeyItem(),
newDefaultSortKey = this.defaultSortInput.getValue(),
newDefaultSortKeyData = {
type: 'mwDefaultSort',
attributes: { content: newDefaultSortKey }
};
data = data || {};
if ( data.action !== 'apply' ) {
return;
}
// Alter the default sort key iff it's been touched & is actually different
if ( this.defaultSortKeyTouched ) {
if ( newDefaultSortKey === '' ) {
if ( currentDefaultSortKeyItem ) {
currentDefaultSortKeyItem.remove();
}
} else {
if ( !currentDefaultSortKeyItem ) {
this.metaList.insertMeta( newDefaultSortKeyData );
} else if ( currentDefaultSortKeyItem.getAttribute( 'content' ) !== newDefaultSortKey ) {
currentDefaultSortKeyItem.replaceWith(
ve.extendObject( true, {},
currentDefaultSortKeyItem.getElement(),
newDefaultSortKeyData
) );
}
}
}
this.categoryWidget.clearItems();
this.metaList.disconnect( this );
this.metaList = null;
};