Henning Snater has uploaded a new change for review.
https://gerrit.wikimedia.org/r/62586
Change subject: (bug 48145) Simplified input extender widget
......................................................................
(bug 48145) Simplified input extender widget
Change-Id: I7091801e90f0f665be4de3634847fdf054ea7b86
---
M ValueView/ValueView.resources.mw.php
M ValueView/resources/jquery.ui/jquery.ui.inputextender.css
M ValueView/resources/jquery.ui/jquery.ui.inputextender.js
M ValueView/resources/jquery.ui/jquery.ui.listrotator.js
M ValueView/resources/jquery.valueview/valueview.css
M ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
M ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
7 files changed, 81 insertions(+), 206 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DataValues
refs/changes/86/62586/1
diff --git a/ValueView/ValueView.resources.mw.php
b/ValueView/ValueView.resources.mw.php
index 145f856..d5b9776 100644
--- a/ValueView/ValueView.resources.mw.php
+++ b/ValueView/ValueView.resources.mw.php
@@ -105,6 +105,7 @@
),
'dependencies' => array(
'jquery.eachchange',
+ 'jquery.ui.position',
'jquery.ui.widget',
),
'messages' => array(
diff --git a/ValueView/resources/jquery.ui/jquery.ui.inputextender.css
b/ValueView/resources/jquery.ui/jquery.ui.inputextender.css
index 4554dff..c355404 100644
--- a/ValueView/resources/jquery.ui/jquery.ui.inputextender.css
+++ b/ValueView/resources/jquery.ui/jquery.ui.inputextender.css
@@ -5,25 +5,12 @@
* @author H. Snater < [email protected] >
*/
-.ui-inputextender .ui-inputextender-input {
- display: inline;
-}
-
-.ui-inputextender .ui-inputextender-extender {
- display: inline;
-}
-
-.ui-inputextender .ui-inputextender-contentcontainer {
+.ui-inputextender-extension {
position: absolute;
- z-index: 1;
- left: 2px;
- font-size: 84%;
padding: 2px;
- box-shadow: 2px 2px 6px -1px grey;
+ font-size: 84%
}
-.ui-inputextener .ui-inputextender-extendedcontent {
- margin-top: 5px;
- padding-top: 5px;
- border-top: 1px dashed #CCC;
+.ui-inputextender-extension > * {
+ font-size: 84%;
}
diff --git a/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
b/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
index b925a15..1349c16 100644
--- a/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
+++ b/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
@@ -69,6 +69,13 @@
return ( IS_MODULE_LOADED ) ? mw.msg( msgKey ) : string;
}
+ /**
+ * Caches whether the widget is used in a rtl context. This, however,
depends on using an "rtl"
+ * class on the document body like it is done in MediaWiki.
+ * @type {boolean}
+ */
+ var isRtl = $( 'body' ).hasClass( 'rtl' );
+
$.widget( 'ui.inputextender', {
/**
* Additional options
@@ -79,6 +86,11 @@
extendedContent: [],
initCallback: null,
hideWhenInputEmpty: true,
+ position: {
+ my: ( isRtl ) ? 'right top' : 'left top',
+ at: ( isRtl ) ? 'right bottom' : 'left bottom',
+ collision: 'none'
+ },
messages: {
'show options': mwMsgOrString(
'valueview-inputextender-showoptions', 'show options' ),
'hide options': mwMsgOrString(
'valueview-inputextender-hideoptions', 'hide options' )
@@ -86,46 +98,10 @@
},
/**
- * The widget parent's node.
+ * The input extension's node.
* @type {jQuery}
*/
- $parent: null,
-
- /**
- * Container node wrapping the widget's whole DOM structure.
- * @type {jQuery}
- */
- $container: null,
-
- /**
- * Container node containing the input element and the extender.
- * @type {jQuery}
- */
- $inputContainer: null,
-
- /**
- * Node of the link to extended the extenders additional
content.
- * @type {jQuery}
- */
- $extender: null,
-
- /**
- * Node containing all the extension content.
- * @type {jQuery}
- */
- $contentContainer: null,
-
- /**
- * Node of the default/"fixed" extension content.
- * @type {jQuery}
- */
- $content: null,
-
- /**
- * Node of the additional extension content shown/hidden by the
extender link.
- * @type {jQuery}
- */
- $extendedContent: null,
+ $extension: null,
/**
* Caches the timeout when the actual "blur" action should kick
in.
@@ -139,78 +115,43 @@
_create: function() {
var self = this;
- this.$parent = this.element.parent();
+ this.element
+ .addClass( this.widgetBaseClass + '-input' );
- if( !this.$parent.length ) {
- throw new Error( 'Input extender widget needs
to be in the DOM when initializing.' );
- }
-
- this.$container = $( '<div/>' )
- .addClass( this.widgetBaseClass )
- .appendTo( this.$parent );
-
- this.$inputContainer = $( '<div />' )
- .addClass( this.widgetBaseClass + '-inputcontainer' )
- .append( this.element.addClass( this.widgetBaseClass +
'-input' ).detach() )
- .appendTo( this.$container );
-
- this.$extender = $( '<a/>' )
- .addClass( this.widgetBaseClass + '-extender' )
- .attr( 'href', 'javascript:void(0);' )
- .text( this.options.messages['show options'] )
- .appendTo( this.$inputContainer )
+ this.$extension = $( '<div/>' )
+ .addClass( this.widgetBaseClass + '-extension
ui-widget-content' )
.on( 'click', function( event ) {
clearTimeout( self._blurTimeout );
- self._toggleExtension();
+ event.stopPropagation();
+ self.showExtension();
} )
- .on( 'keydown', function( event ) {
- if( event.keyCode === $.ui.keyCode.ENTER ) {
- clearTimeout( self._blurTimeout );
- self._toggleExtension();
- }
- } )
- .on( 'focus', function( event ) {
- clearTimeout( self._blurTimeout );
- } )
- .hide();
+ .appendTo( $( 'body' ) );
- this.$contentContainer = $( '<div/>' )
- .addClass( this.widgetBaseClass + '-contentcontainer
ui-widget-content' )
- .appendTo( this.$container )
- .on( 'click.' + this.widgetName, function( event ) {
- clearTimeout( self._blurTimeout );
- } );
-
- this.$content = $( '<div/>' )
- .addClass( this.widgetBaseClass + '-content' )
- .appendTo( this.$contentContainer );
-
- this.$extendedContent = $( '<div/>' )
- .addClass( this.widgetBaseClass + '-extendedcontent' )
- .appendTo( this.$contentContainer );
-
- this.element.add( this.$extender )
+ this.element
.on( 'focus.' + this.widgetName, function( event ) {
if( !self.options.hideWhenInputEmpty ||
self.element.val() !== '' ) {
clearTimeout( self._blurTimeout );
- self.showContent();
+ self.showExtension();
}
} )
- // TODO: Do not hide when tabbing into the
inputextender's contents
+ // TODO: Allow direct tabbing into the extension
.on( 'blur.' + this.widgetName, function( event ) {
self._blurTimeout = setTimeout( function() {
- self.hideContent( function() {
- self._toggleExtension( {
forceHide: true } );
- } );
+ self.hideExtension();
}, 150 );
+ } )
+ .on( 'keydown.' + this.widgetName, function( event ) {
+ if( event.keyCode === $.ui.keyCode.ESCAPE ) {
+ self.hideExtension();
+ }
} );
if( this.options.hideWhenInputEmpty ) {
this.element.eachchange( function( event,
oldValue ) {
- if( self.element.val() === '' &&
!self.$extendedContent.is( ':visible' ) ) {
- self.hideContent();
+ if( self.element.val() === '' ) {
+ self.hideExtension();
} else if ( oldValue === '' ) {
- self.showContent();
+ self.showExtension();
}
} );
}
@@ -222,10 +163,8 @@
var $widgetNodes = $( ':' +
self.widgetBaseClass );
$widgetNodes.each( function( i,
widgetNode ) {
var widget = $( widgetNode
).data( self.widgetName );
- if( $( event.target ).closest(
widget.$container ).length === 0 ) {
- widget.hideContent(
function() {
-
widget._toggleExtension( { forceHide: true } );
- } );
+ if( $( event.target ).closest(
widget.$extension.add( widget.element ) ).length === 0 ) {
+ widget.hideExtension();
}
} );
} );
@@ -237,17 +176,14 @@
this.options.initCallback();
}
- this.$contentContainer.hide();
- this.$extendedContent.hide();
+ this.$extension.hide();
},
/**
* @see jQuery.Widget.destroy
*/
destroy: function() {
- var $input = this.element.detach();
- this.$container.remove();
- this.$parent.append( $input );
+ this.$extension.remove();
if( $( ':' + this.widgetBaseClass ).length === 0 ) {
$( 'html' ).off( '.' + this.widgetName );
}
@@ -255,71 +191,34 @@
},
/**
- * Draws the widget according to its current state.
+ * Draws the widget.
*/
_draw: function() {
var self = this;
- this.$content.empty();
-
- // Only show the extender when there are any additional
options to extend:
- this.$extender[ ( this.options.extendedContent.length )
? 'show' : 'hide' ]();
+ this.$extension.empty();
$.each( this.options.content, function( i, $node ) {
- self.$content.append( $node );
- } );
-
- $.each( this.options.extendedContent, function( i,
$node ) {
- self.$extendedContent.append( $node );
+ self.$extension.append( $node );
} );
},
/**
- * Toggles the visibility of the additional options.
- *
- * @param {Object|undefined} customOptions
- */
- _toggleExtension: function( customOptions ) {
- var self = this,
- options = {
- moveFocus: true,
- forceHide: false
- };
-
- $.extend( options, customOptions );
-
- function hideExtendedContent() {
- self.$extendedContent.slideUp( 150, function() {
- self.$extender.text(
self.options.messages['show options'] );
- self._trigger( 'toggle' );
- } );
- }
-
- if( options.forceHide ) {
- hideExtendedContent();
- return;
- }
-
- if( this.$extendedContent.is( ':visible' ) ) {
- this.showContent( hideExtendedContent );
- } else {
- this.showContent( function() {
- self.$extendedContent.slideDown( 150,
function() {
- self.$extender.text(
self.options.messages['hide options'] );
- self._trigger( 'toggle' );
- } );
- } );
- }
-
- },
-
- /**
- * Shows all the extension contents.
+ * Shows the extension.
*
* @param {Function} [callback] Invoked as soon as the contents
are visible.
*/
- showContent: function( callback ) {
- this.$contentContainer.stop( true, true ).fadeIn( 150,
function() {
+ showExtension: function( callback ) {
+ // Element needs to be visible to use
jquery.ui.position.
+ if( !this.$extension.is( ':visible' ) ) {
+ this.$extension.show();
+ this.$extension.position( $.extend( {
+ of: this.element
+ }, this.options.position ) );
+ this.$extension.hide();
+ }
+
+ this.$extension.stop( true, true ).fadeIn( 150,
function() {
if( $.isFunction( callback ) ) {
callback();
}
@@ -327,12 +226,12 @@
},
/**
- * Hides all the extension contents.
+ * Hides the extension.
*
* @param {Function} [callback] Invoked as soon as the contents
are hidden.
*/
- hideContent: function( callback ) {
- this.$contentContainer.stop( true, true ).fadeOut( 150,
function() {
+ hideExtension: function( callback ) {
+ this.$extension.stop( true, true ).fadeOut( 150,
function() {
if( $.isFunction( callback ) ) {
callback();
}
diff --git a/ValueView/resources/jquery.ui/jquery.ui.listrotator.js
b/ValueView/resources/jquery.ui/jquery.ui.listrotator.js
index 86411ab..6c28a34 100644
--- a/ValueView/resources/jquery.ui/jquery.ui.listrotator.js
+++ b/ValueView/resources/jquery.ui/jquery.ui.listrotator.js
@@ -175,7 +175,7 @@
self._trigger( 'auto' );
} )
.addClass( 'ui-state-active' );
- this.$auto.children( 'a' ).text(
this.options.messages['show options'] );
+ this.$auto.children( 'a' ).text(
this.options.messages['auto'] );
// Construct the basic sections:
this.$curr = this._createSection( 'curr', function(
event ) {
diff --git a/ValueView/resources/jquery.valueview/valueview.css
b/ValueView/resources/jquery.valueview/valueview.css
index 6bdf022..faa1393 100644
--- a/ValueView/resources/jquery.valueview/valueview.css
+++ b/ValueView/resources/jquery.valueview/valueview.css
@@ -39,16 +39,16 @@
background-color: white;
}
-.valueview .valueview-preview-value {
- font-size: 119%; /* Reset to default 100% */
-}
-
-.valueview .valueview-preview-novalue {
- font-style: italic;
-}
-
.valueview-ineditmode.linkedsingleinputvalueview a,
.valueview-ineditmode.linkedsingleinputvalueview a {
/* make sure input box which still is inside a doesn't display text as
links */
color: inherit;
}
+
+.valueview-preview-value {
+ font-size: 119%; /* Reset to default 100% */
+}
+
+.valueview-preview-novalue {
+ font-style: italic;
+}
diff --git
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
index 9a63885..b4001ad 100644
---
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
+++
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
@@ -106,8 +106,7 @@
// TODO: Move input extender out of here to a more
generic place since it is not
// TimeInput specific.
.inputextender( {
- content: [ this.$preview ],
- extendedContent: [ this.$precision ],
+ content: [ this.$preview, this.$precision ],
initCallback: function() {
self.$precision.data( 'listrotator'
).initWidths();
}
diff --git a/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
b/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
index fc263d7..c298382 100644
--- a/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
+++ b/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
@@ -18,8 +18,7 @@
var newTestInputextender = function( options ) {
if( !options ) {
options = {
- content: [ $( '<span/>' ).addClass(
'defaultContent' ).text( 'default content' ) ],
- extendedContent: [ $( '<span/>' ).addClass(
'extendedContent' ).text( 'extended content' ) ]
+ content: [ $( '<span/>' ).addClass(
'defaultContent' ).text( 'default content' ) ]
}
}
@@ -45,33 +44,23 @@
expect( 1 );
assert.ok(
- !extender.$contentContainer.is( ':visible' ),
- 'Content is not visible.'
+ !extender.$extension.is( ':visible' ),
+ 'Extension is not visible.'
);
} );
- QUnit.test( 'Show/Hide basic content', function( assert ) {
+ QUnit.test( 'Show/Hide', function( assert ) {
var $input = newTestInputextender(),
extender = $input.data( 'inputextender' );
- expect( 4 );
+ expect( 2 );
stop();
- extender.showContent( function() {
+ extender.showExtension( function() {
assert.ok(
- extender.$contentContainer.is( ':visible' ),
- 'Content visible after focusing input element.'
- );
-
- assert.ok(
- extender.$content.is( ':visible' ),
- 'Default content is visible.'
- );
-
- assert.ok(
- !extender.$extendedContent.is( ':visible' ),
- 'Additional content is hidden.'
+ extender.$extension.is( ':visible' ),
+ 'showExtension()'
);
start();
@@ -79,10 +68,10 @@
stop();
- extender.hideContent( function() {
+ extender.hideExtension( function() {
assert.ok(
- !extender.$contentContainer.is( ':visible' ),
- 'Content is hidden after blurring the input
element.'
+ !extender.$extension.is( ':visible' ),
+ 'hideExtension()'
);
start();
--
To view, visit https://gerrit.wikimedia.org/r/62586
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7091801e90f0f665be4de3634847fdf054ea7b86
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DataValues
Gerrit-Branch: master
Gerrit-Owner: Henning Snater <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits