Fieldsets and default sort keys

Objective:
* Add default sort key field to meta dialog
* Replace PagePanelLayout with a generic panel containing one or more FieldsetLayout elements

Changes:

*.php
* Added/removed file links

ve.dm.MWDefaultSortMetaItem.js
* Added getContent method

ve.dm.MetaItem.js
* Added replaceWith method

ve.dm.MetaList.js
* Allow insertion at the end by omitting offset and index

ve.dm.MWMetaDialog.js
* Added default sort key field
* Put category and default sort fields inside fieldsets
* Added loading/saving default sort key

ve.ui.PagedLayout.js
* Changed class used for pages to generic panel layout

ve.ui.PagePanelLayout
* Moved title/icon stuff to field set

ve.ui.FieldsetLayout.js
* New class, adds fieldset with legend

ve.ui.StackPanelLayout.js
* Moved up to the layouts directory

ve.ui.Dialog.css
* Moved style for paged panel from layout stylesheet

ve.ui.Layout.css
* Added styles for fieldsets

ve.ui.Widget.css
* Adjusted margins of input label widgets

ve.ui.MWCategoryWidget.js, ve.ui.MWCategoryPopupWidget.js
* Added setDefaultSortKey method

Change-Id: I979f5e3f08a688790c9f54086206ed1999af13ea
This commit is contained in:
Trevor Parscal 2013-05-03 15:17:35 -07:00
parent e888d7b985
commit 8409d16f0f
15 changed files with 165 additions and 76 deletions

View file

@ -393,10 +393,10 @@ $wgResourceModules += array(
've/ui/widgets/ve.ui.MWCategoryItemWidget.js', 've/ui/widgets/ve.ui.MWCategoryItemWidget.js',
've/ui/widgets/ve.ui.MWCategoryWidget.js', 've/ui/widgets/ve.ui.MWCategoryWidget.js',
've/ui/layouts/ve.ui.FieldsetLayout.js',
've/ui/layouts/ve.ui.GridLayout.js', 've/ui/layouts/ve.ui.GridLayout.js',
've/ui/layouts/ve.ui.PanelLayout.js', 've/ui/layouts/ve.ui.PanelLayout.js',
've/ui/layouts/panels/ve.ui.StackPanelLayout.js', 've/ui/layouts/ve.ui.StackPanelLayout.js',
've/ui/layouts/panels/ve.ui.PagePanelLayout.js',
've/ui/dialogs/ve.ui.ContentDialog.js', 've/ui/dialogs/ve.ui.ContentDialog.js',
've/ui/dialogs/ve.ui.MediaDialog.js', 've/ui/dialogs/ve.ui.MediaDialog.js',

View file

@ -258,10 +258,10 @@ $html = file_get_contents( $page );
<script src="../../modules/ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script> <script src="../../modules/ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script>
<script src="../../modules/ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> <script src="../../modules/ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script>
<script src="../../modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js"></script> <script src="../../modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js"></script>
<script src="../../modules/ve/ui/layouts/ve.ui.FieldsetLayout.js"></script>
<script src="../../modules/ve/ui/layouts/ve.ui.GridLayout.js"></script> <script src="../../modules/ve/ui/layouts/ve.ui.GridLayout.js"></script>
<script src="../../modules/ve/ui/layouts/ve.ui.PanelLayout.js"></script> <script src="../../modules/ve/ui/layouts/ve.ui.PanelLayout.js"></script>
<script src="../../modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js"></script> <script src="../../modules/ve/ui/layouts/ve.ui.StackPanelLayout.js"></script>
<script src="../../modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script src="../../modules/ve/ui/dialogs/ve.ui.ContentDialog.js"></script> <script src="../../modules/ve/ui/dialogs/ve.ui.ContentDialog.js"></script>
<script src="../../modules/ve/ui/dialogs/ve.ui.MediaDialog.js"></script> <script src="../../modules/ve/ui/dialogs/ve.ui.MediaDialog.js"></script>
<script src="../../modules/ve/ui/dialogs/ve.ui.PagedDialog.js"></script> <script src="../../modules/ve/ui/dialogs/ve.ui.PagedDialog.js"></script>

View file

@ -59,6 +59,20 @@ ve.dm.MetaItem.prototype.remove = function () {
this.list.removeMeta( this ); this.list.removeMeta( this );
}; };
/**
* Replace item with another in-place.
*
* @param {ve.dm.MetaItem} item Item to replace this item with
*/
ve.dm.MetaItem.prototype.replaceWith = function ( item ) {
var offset = this.getOffset(),
index = this.getIndex(),
list = this.list;
list.removeMeta( this );
list.insertMeta( item, offset, index );
};
/** /**
* Get the group this meta item belongs to. * Get the group this meta item belongs to.
* @see ve.dm.MetaItem#static.group * @see ve.dm.MetaItem#static.group

View file

@ -251,7 +251,7 @@ ve.dm.MetaList.prototype.getAllItems = function () {
* Insert new metadata into the document. This builds and processes a transaction that inserts * Insert new metadata into the document. This builds and processes a transaction that inserts
* metadata into the document. * metadata into the document.
* @param {Object|ve.dm.MetaItem} meta Metadata element (or MetaItem) to insert * @param {Object|ve.dm.MetaItem} meta Metadata element (or MetaItem) to insert
* @param {Number} offset Offset at which to insert the new metadata * @param {Number} [offset] Offset at which to insert the new metadata
* @param {Number} [index] Index at which to insert the new metadata, or undefined to add to the end * @param {Number} [index] Index at which to insert the new metadata, or undefined to add to the end
*/ */
ve.dm.MetaList.prototype.insertMeta = function ( meta, offset, index ) { ve.dm.MetaList.prototype.insertMeta = function ( meta, offset, index ) {
@ -259,7 +259,10 @@ ve.dm.MetaList.prototype.insertMeta = function ( meta, offset, index ) {
if ( meta instanceof ve.dm.MetaItem ) { if ( meta instanceof ve.dm.MetaItem ) {
meta = meta.getElement(); meta = meta.getElement();
} }
if ( index === undefined ) { if ( offset === undefined ) {
offset = this.document.getLength();
index = 0;
} else if ( index === undefined ) {
index = ( this.document.metadata.getData( offset ) || [] ).length; index = ( this.document.metadata.getData( offset ) || [] ).length;
} }
tx = ve.dm.Transaction.newFromMetadataInsertion( this.document, offset, index, [ meta ] ); tx = ve.dm.Transaction.newFromMetadataInsertion( this.document, offset, index, [ meta ] );

View file

@ -213,10 +213,10 @@
<script src="../../ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script> <script src="../../ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script>
<script src="../../ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> <script src="../../ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script>
<script src="../../ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js"></script> <script src="../../ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js"></script>
<script src="../../ve/ui/layouts/ve.ui.FieldsetLayout.js"></script>
<script src="../../ve/ui/layouts/ve.ui.GridLayout.js"></script> <script src="../../ve/ui/layouts/ve.ui.GridLayout.js"></script>
<script src="../../ve/ui/layouts/ve.ui.PanelLayout.js"></script> <script src="../../ve/ui/layouts/ve.ui.PanelLayout.js"></script>
<script src="../../ve/ui/layouts/panels/ve.ui.StackPanelLayout.js"></script> <script src="../../ve/ui/layouts/ve.ui.StackPanelLayout.js"></script>
<script src="../../ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script src="../../ve/ui/dialogs/ve.ui.ContentDialog.js"></script> <script src="../../ve/ui/dialogs/ve.ui.ContentDialog.js"></script>
<script src="../../ve/ui/dialogs/ve.ui.MediaDialog.js"></script> <script src="../../ve/ui/dialogs/ve.ui.MediaDialog.js"></script>
<script src="../../ve/ui/dialogs/ve.ui.PagedDialog.js"></script> <script src="../../ve/ui/dialogs/ve.ui.PagedDialog.js"></script>

View file

@ -5,6 +5,8 @@
* @license The MIT License (MIT); see LICENSE.txt * @license The MIT License (MIT); see LICENSE.txt
*/ */
/*global mw*/
/** /**
* Document dialog. * Document dialog.
* *
@ -20,6 +22,9 @@ ve.ui.MWMetaDialog = function VeUiMWMetaDialog( surface ) {
// Properties // Properties
this.metaList = surface.getModel().metaList; this.metaList = surface.getModel().metaList;
this.defaultSortKeyItem = this.getDefaultSortKeyItem();
this.defaultSortKeyChanged = false;
this.fallbackDefaultSortKey = mw.config.get( 'wgTitle' );
// Events // Events
this.metaList.connect( this, { this.metaList.connect( this, {
@ -69,10 +74,11 @@ ve.ui.MWMetaDialog.prototype.onOpen = function () {
* @param {string} action Action that caused the window to be closed * @param {string} action Action that caused the window to be closed
*/ */
ve.ui.MWMetaDialog.prototype.onClose = function ( action ) { ve.ui.MWMetaDialog.prototype.onClose = function ( action ) {
var surfaceModel = this.surface.getModel(); var surfaceModel = this.surface.getModel(),
defaultSortKeyItem;
// Parent method // Parent method
ve.ui.PagedDialog.prototype.onOpen.call( this ); ve.ui.PagedDialog.prototype.onClose.call( this );
// Place transactions made while dialog was open in a common history state // Place transactions made while dialog was open in a common history state
surfaceModel.breakpoint(); surfaceModel.breakpoint();
@ -83,6 +89,18 @@ ve.ui.MWMetaDialog.prototype.onClose = function ( action ) {
surfaceModel.truncateUndoStack(); surfaceModel.truncateUndoStack();
} }
if ( this.defaultSortKeyChanged ) {
defaultSortKeyItem = new ve.dm.MWDefaultSortMetaItem( {
'type': 'MWdefaultSort',
'attributes': { 'content': this.defaultSortInput.getValue() }
} );
if ( this.defaultSortKeyItem ) {
this.defaultSortKeyItem.replaceWith( defaultSortKeyItem );
} else {
this.metaList.insertMeta( defaultSortKeyItem );
}
}
// Return to normal tracking behavior // Return to normal tracking behavior
surfaceModel.startHistoryTracking(); surfaceModel.startHistoryTracking();
}; };
@ -97,25 +115,59 @@ ve.ui.MWMetaDialog.prototype.initialize = function () {
ve.ui.PagedDialog.prototype.initialize.call( this ); ve.ui.PagedDialog.prototype.initialize.call( this );
// Properties // Properties
this.categoriesFieldset = new ve.ui.FieldsetLayout( {
'$$': this.$$, 'label': 'Categories', 'icon': 'tag'
} );
this.categorySettingsFieldset = new ve.ui.FieldsetLayout( {
'$$': this.$$, 'label': 'Category settings', 'icon': 'settings'
} );
this.categoryWidget = new ve.ui.MWCategoryWidget( { this.categoryWidget = new ve.ui.MWCategoryWidget( {
'$$': this.$$, '$overlay': this.$overlay '$$': this.$$, '$overlay': this.$overlay
} ); } );
this.defaultSortInput = new ve.ui.TextInputWidget( {
'$$': this.$$, 'placeholder': this.fallbackDefaultSortKey
} );
this.defaultSortLabel = new ve.ui.InputLabelWidget( {
'$$': this.$$,
'input': this.defaultSortInput,
'label': 'Default page name on category page'
} );
// Events // Events
this.categoryWidget.connect( this, { this.categoryWidget.connect( this, {
'newCategory': 'onNewCategory', 'newCategory': 'onNewCategory',
'updateSortkey': 'onUpdateSortKey' 'updateSortkey': 'onUpdateSortKey'
} ); } );
this.defaultSortInput.connect( this, {
'change': 'onDefaultSortChange'
} );
// Initialization // Initialization
this.defaultSortInput.setValue(
this.defaultSortKeyItem ? this.defaultSortKeyItem.getAttribute( 'content' ) : ''
);
this.categoryWidget.addItems( this.getCategoryItems() ); this.categoryWidget.addItems( this.getCategoryItems() );
this.addPage( 'categories', 'Categories', 'tag' ) this.addPage( 'categories', 'Categories', 'tag' )
.addPage( 'languages', 'Languages', 'language' ); .addPage( 'languages', 'Languages', 'language' );
this.pages.categories.$.append( this.categoryWidget.$ ); this.pages.categories.$.append( this.categoriesFieldset.$, this.categorySettingsFieldset.$ );
this.categoriesFieldset.$.append( this.categoryWidget.$ );
this.categorySettingsFieldset.$.append(
this.defaultSortLabel.$, this.defaultSortInput.$
);
}; };
/** /**
* Gets array of category items from meta list * Get default sort key item.
*
* @returns {string} Default sort key item
*/
ve.ui.MWMetaDialog.prototype.getDefaultSortKeyItem = function () {
var items = this.metaList.getItemsInGroup( 'MWdefaultSort' );
return items.length ? items[0] : null;
};
/**
* Get array of category items from meta list
* *
* @method * @method
* @returns {Object[]} items * @returns {Object[]} items
@ -163,6 +215,16 @@ ve.ui.MWMetaDialog.prototype.getCategoryItemForInsertion = function ( item ) {
}; };
}; };
/**
* Handle category default sort change events.
*
* @param {string} value Default sort value
*/
ve.ui.MWMetaDialog.prototype.onDefaultSortChange = function ( value ) {
this.categoryWidget.setDefaultSortKey( value === '' ? this.fallbackDefaultSortKey : value );
this.defaultSortKeyChanged = true;
};
/** /**
* Inserts new category into meta list * Inserts new category into meta list
* *
@ -181,12 +243,8 @@ ve.ui.MWMetaDialog.prototype.onNewCategory = function ( item ) {
* @param {Object} item * @param {Object} item
*/ */
ve.ui.MWMetaDialog.prototype.onUpdateSortKey = function ( item ) { ve.ui.MWMetaDialog.prototype.onUpdateSortKey = function ( item ) {
var offset = item.metaItem.getOffset(),
index = item.metaItem.getIndex();
// Replace meta item with updated one // Replace meta item with updated one
item.metaItem.remove(); item.metaItem.replaceWith( this.getCategoryItemForInsertion( item ) );
this.metaList.insertMeta( this.getCategoryItemForInsertion( item ), offset, index );
}; };
/** /**

View file

@ -84,7 +84,7 @@ ve.ui.PagedDialog.prototype.addPage = function ( name, label, icon ) {
var config = { '$$': this.$$, 'icon': icon, 'label': label || name }; var config = { '$$': this.$$, 'icon': icon, 'label': label || name };
// Create and add page panel and outline item // Create and add page panel and outline item
this.pages[name] = new ve.ui.PagePanelLayout( config ); this.pages[name] = new ve.ui.PanelLayout( config );
this.pagesPanel.addItems( [this.pages[name]] ); this.pagesPanel.addItems( [this.pages[name]] );
this.outlineWidget.addItems( [ new ve.ui.OutlineItemWidget( name, config ) ] ); this.outlineWidget.addItems( [ new ve.ui.OutlineItemWidget( name, config ) ] );
@ -101,7 +101,7 @@ ve.ui.PagedDialog.prototype.addPage = function ( name, label, icon ) {
* *
* @method * @method
* @param {string} name Symbolic name of page * @param {string} name Symbolic name of page
* @returns {ve.ui.PagePanelLayout|undefined} Page, if found * @returns {ve.ui.PanelLayout|undefined} Page, if found
*/ */
ve.ui.PagedDialog.prototype.getPage = function ( name ) { ve.ui.PagedDialog.prototype.getPage = function ( name ) {
return this.pages[name]; return this.pages[name];

View file

@ -1,47 +0,0 @@
/*!
* VisualEditor UserInterface PagePanelLayout class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Page panel layout.
*
* @class
* @extends ve.ui.PanelLayout
* @mixins ve.ui.LabeledElement
*
* @constructor
* @param {Object} [config] Config options
* @cfg {string} [icon=''] Symbolic icon name
*/
ve.ui.PagePanelLayout = function VeUiPagePanelLayout( config ) {
// Config initialization
config = ve.extendObject( config, { 'scroll': true } );
// Parent constructor
ve.ui.PanelLayout.call( this, config );
// Mixin constructors
ve.ui.LabeledElement.call( this, this.$$( '<div>' ), config );
// Properties
this.icon = config.icon;
// Initialization
this.$label.addClass( 've-ui-icon-' + config.icon + '-big' );
this.$.append( this.$label ).addClass( 've-ui-pagedPanelLayout' );
};
/* Inheritance */
ve.inheritClass( ve.ui.PagePanelLayout, ve.ui.PanelLayout );
ve.mixinClass( ve.ui.PagePanelLayout, ve.ui.LabeledElement );
/* Methods */
ve.ui.PagePanelLayout.prototype.getIcon = function () {
return this.icon;
};

View file

@ -0,0 +1,42 @@
/*!
* VisualEditor UserInterface FieldsetLayout class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Fieldset layout.
*
* @class
* @extends ve.ui.Layout
* @mixins ve.ui.LabeledElement
*
* @constructor
* @param {Object} [config] Config options
* @cfg {string} [icon=''] Symbolic icon name
*/
ve.ui.FieldsetLayout = function VeUiFieldsetLayout( config ) {
// Config initialization
config = ve.extendObject( { 'icon': 'window' }, config );
// Parent constructor
ve.ui.Layout.call( this, config );
// Mixin constructors
ve.ui.LabeledElement.call( this, this.$$( '<legend>' ), config );
// Initialization
this.$label.addClass( 've-ui-icon-' + config.icon );
this.$.append( this.$label ).addClass( 've-ui-fieldsetLayout' );
};
/* Inheritance */
ve.inheritClass( ve.ui.FieldsetLayout, ve.ui.Layout );
ve.mixinClass( ve.ui.FieldsetLayout, ve.ui.LabeledElement );
/* Static Properties */
ve.ui.FieldsetLayout.static.tagName = 'fieldset';

View file

@ -120,3 +120,12 @@
.ve-ui-pagedDialog-outlinePanel { .ve-ui-pagedDialog-outlinePanel {
border-right: solid 1px #ddd; border-right: solid 1px #ddd;
} }
.ve-ui-pagedDialog-pagesPanel .ve-ui-panelLayout {
padding: 1.5em;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
}

View file

@ -21,18 +21,15 @@
position: absolute; position: absolute;
} }
/* ve.ui.EditorPanelLayout */ /* ve.ui.FieldsetLayout */
.ve-ui-pagedPanelLayout { .ve-ui-fieldsetLayout {
padding: 1.5em; border: none;
width: 100%; margin: 0 0 2em 0;
-webkit-box-sizing: border-box; padding: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
} }
.ve-ui-pagedPanelLayout > .ve-ui-labeledElement-label { .ve-ui-fieldsetLayout > legend.ve-ui-labeledElement-label {
font-size: 1.5em; font-size: 1.5em;
padding-left: 1.75em; padding-left: 1.75em;
margin-bottom: 1em; margin-bottom: 1em;

View file

@ -192,6 +192,12 @@
text-shadow: 0 1px 1px rgba(255,255,255,0.5); text-shadow: 0 1px 1px rgba(255,255,255,0.5);
} }
/* ve.ui.InputLabelWidget */
.ve-ui-inputLabelWidget {
margin: 0.5em 0;
}
/* ve.ui.TextInputWidget */ /* ve.ui.TextInputWidget */
.ve-ui-textInputWidget { .ve-ui-textInputWidget {
@ -448,7 +454,6 @@
margin-top: 0; margin-top: 0;
padding-left: 0.75em; padding-left: 0.75em;
padding-right: 0.75em; padding-right: 0.75em;
background-color: #fff;
} }
.ve-ui-mwCategoryPopupMenu { .ve-ui-mwCategoryPopupMenu {

View file

@ -94,6 +94,10 @@ ve.ui.MWCategoryPopupWidget.prototype.closePopup = function () {
this.popupOpen = false; this.popupOpen = false;
}; };
ve.ui.MWCategoryPopupWidget.prototype.setDefaultSortKey = function ( value ) {
this.sortKeyInput.$input.attr( 'placeholder', value );
};
ve.ui.MWCategoryPopupWidget.prototype.setPopup = function ( item ) { ve.ui.MWCategoryPopupWidget.prototype.setPopup = function ( item ) {
var left = item.$.offset().left + ( item.$.width() - 17 ), var left = item.$.offset().left + ( item.$.width() - 17 ),
top = item.$.offset().top + item.$.height(), top = item.$.offset().top + item.$.height(),

View file

@ -150,6 +150,10 @@ ve.ui.MWCategoryWidget.prototype.onTogglePoupupMenu = function ( item ) {
} }
}; };
ve.ui.MWCategoryWidget.prototype.setDefaultSortKey = function ( value ) {
this.popup.setDefaultSortKey( value );
};
/** /**
* Get list of category names. * Get list of category names.
* *