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.MWCategoryWidget.js',
've/ui/layouts/ve.ui.FieldsetLayout.js',
've/ui/layouts/ve.ui.GridLayout.js',
've/ui/layouts/ve.ui.PanelLayout.js',
've/ui/layouts/panels/ve.ui.StackPanelLayout.js',
've/ui/layouts/panels/ve.ui.PagePanelLayout.js',
've/ui/layouts/ve.ui.StackPanelLayout.js',
've/ui/dialogs/ve.ui.ContentDialog.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.LinkTargetInputWidget.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.PanelLayout.js"></script>
<script src="../../modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js"></script>
<script src="../../modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script src="../../modules/ve/ui/layouts/ve.ui.StackPanelLayout.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.PagedDialog.js"></script>

View file

@ -59,6 +59,20 @@ ve.dm.MetaItem.prototype.remove = function () {
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.
* @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
* metadata into the document.
* @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
*/
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 ) {
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;
}
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.LinkTargetInputWidget.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.PanelLayout.js"></script>
<script src="../../ve/ui/layouts/panels/ve.ui.StackPanelLayout.js"></script>
<script src="../../ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script src="../../ve/ui/layouts/ve.ui.StackPanelLayout.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.PagedDialog.js"></script>

View file

@ -5,6 +5,8 @@
* @license The MIT License (MIT); see LICENSE.txt
*/
/*global mw*/
/**
* Document dialog.
*
@ -20,6 +22,9 @@ ve.ui.MWMetaDialog = function VeUiMWMetaDialog( surface ) {
// Properties
this.metaList = surface.getModel().metaList;
this.defaultSortKeyItem = this.getDefaultSortKeyItem();
this.defaultSortKeyChanged = false;
this.fallbackDefaultSortKey = mw.config.get( 'wgTitle' );
// Events
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
*/
ve.ui.MWMetaDialog.prototype.onClose = function ( action ) {
var surfaceModel = this.surface.getModel();
var surfaceModel = this.surface.getModel(),
defaultSortKeyItem;
// 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
surfaceModel.breakpoint();
@ -83,6 +89,18 @@ ve.ui.MWMetaDialog.prototype.onClose = function ( action ) {
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
surfaceModel.startHistoryTracking();
};
@ -97,25 +115,59 @@ ve.ui.MWMetaDialog.prototype.initialize = function () {
ve.ui.PagedDialog.prototype.initialize.call( this );
// 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.$$, '$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
this.categoryWidget.connect( this, {
'newCategory': 'onNewCategory',
'updateSortkey': 'onUpdateSortKey'
} );
this.defaultSortInput.connect( this, {
'change': 'onDefaultSortChange'
} );
// Initialization
this.defaultSortInput.setValue(
this.defaultSortKeyItem ? this.defaultSortKeyItem.getAttribute( 'content' ) : ''
);
this.categoryWidget.addItems( this.getCategoryItems() );
this.addPage( 'categories', 'Categories', 'tag' )
.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
* @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
*
@ -181,12 +243,8 @@ ve.ui.MWMetaDialog.prototype.onNewCategory = function ( item ) {
* @param {Object} item
*/
ve.ui.MWMetaDialog.prototype.onUpdateSortKey = function ( item ) {
var offset = item.metaItem.getOffset(),
index = item.metaItem.getIndex();
// Replace meta item with updated one
item.metaItem.remove();
this.metaList.insertMeta( this.getCategoryItemForInsertion( item ), offset, index );
item.metaItem.replaceWith( this.getCategoryItemForInsertion( item ) );
};
/**

View file

@ -84,7 +84,7 @@ ve.ui.PagedDialog.prototype.addPage = function ( name, label, icon ) {
var config = { '$$': this.$$, 'icon': icon, 'label': label || name };
// 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.outlineWidget.addItems( [ new ve.ui.OutlineItemWidget( name, config ) ] );
@ -101,7 +101,7 @@ ve.ui.PagedDialog.prototype.addPage = function ( name, label, icon ) {
*
* @method
* @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 ) {
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 {
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;
}
/* ve.ui.EditorPanelLayout */
/* ve.ui.FieldsetLayout */
.ve-ui-pagedPanelLayout {
padding: 1.5em;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
.ve-ui-fieldsetLayout {
border: none;
margin: 0 0 2em 0;
padding: 0;
}
.ve-ui-pagedPanelLayout > .ve-ui-labeledElement-label {
.ve-ui-fieldsetLayout > legend.ve-ui-labeledElement-label {
font-size: 1.5em;
padding-left: 1.75em;
margin-bottom: 1em;

View file

@ -192,6 +192,12 @@
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 {
@ -448,7 +454,6 @@
margin-top: 0;
padding-left: 0.75em;
padding-right: 0.75em;
background-color: #fff;
}
.ve-ui-mwCategoryPopupMenu {

View file

@ -94,6 +94,10 @@ ve.ui.MWCategoryPopupWidget.prototype.closePopup = function () {
this.popupOpen = false;
};
ve.ui.MWCategoryPopupWidget.prototype.setDefaultSortKey = function ( value ) {
this.sortKeyInput.$input.attr( 'placeholder', value );
};
ve.ui.MWCategoryPopupWidget.prototype.setPopup = function ( item ) {
var left = item.$.offset().left + ( item.$.width() - 17 ),
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.
*