jenkins-bot has submitted this change and it was merged. Change subject: Added "datetimepicker" input type from Semantic Forms Inputs ......................................................................
Added "datetimepicker" input type from Semantic Forms Inputs Change-Id: Ieb6e8348c64cd0d0cf0c8fe86f776d393fe7d65c --- M PageForms.php M extension.json M includes/PF_FormPrinter.php A includes/forminputs/PF_DateTimePicker.php A includes/forminputs/PF_TimePickerInput.php A libs/PF_datetimepicker.js A libs/PF_timepicker.js A skins/PF_Timepicker.css 8 files changed, 766 insertions(+), 0 deletions(-) Approvals: Yaron Koren: Looks good to me, approved jenkins-bot: Verified diff --git a/PageForms.php b/PageForms.php index 2f59d37..dfffafe 100644 --- a/PageForms.php +++ b/PageForms.php @@ -210,6 +210,8 @@ $GLOBALS['wgAutoloadClasses']['PFComboBoxInput'] = __DIR__ . '/includes/forminputs/PF_ComboBoxInput.php'; $GLOBALS['wgAutoloadClasses']['PFDateInput'] = __DIR__ . '/includes/forminputs/PF_DateInput.php'; $GLOBALS['wgAutoloadClasses']['PFDatePickerInput'] = __DIR__ . '/includes/forminputs/PF_DatePickerInput.php'; +$GLOBALS['wgAutoloadClasses']['PFTimePickerInput'] = __DIR__ . '/includes/forminputs/PF_TimePickerInput.php'; +$GLOBALS['wgAutoloadClasses']['PFDateTimePicker'] = __DIR__ . '/includes/forminputs/PF_DateTimePicker.php'; $GLOBALS['wgAutoloadClasses']['PFDateTimeInput'] = __DIR__ . '/includes/forminputs/PF_DateTimeInput.php'; $GLOBALS['wgAutoloadClasses']['PFYearInput'] = __DIR__ . '/includes/forminputs/PF_YearInput.php'; $GLOBALS['wgAutoloadClasses']['PFTreeInput'] = __DIR__ . '/includes/forminputs/PF_TreeInput.php'; @@ -339,6 +341,23 @@ ), 'position' => 'bottom', // MW 1.26 ), + 'ext.pageforms.timepicker' => $wgPageFormsResourceTemplate + array( + 'scripts' => array( + 'libs/PF_timepicker.js', + ), + 'styles' => 'skins/PF_Timepicker.css', + 'position' => 'bottom', // MW 1.26 + ), + 'ext.pageforms.datetimepicker' => $wgPageFormsResourceTemplate + array( + 'scripts' => array( + 'libs/PF_datetimepicker.js', + ), + 'dependencies' => array( + 'ext.pageforms.datepicker', + 'ext.pageforms.timepicker' + ), + 'position' => 'bottom', // MW 1.26 + ), 'ext.pageforms.regexp' => $wgPageFormsResourceTemplate + array( 'scripts' => 'libs/PF_regexp.js', 'dependencies' => array( diff --git a/extension.json b/extension.json index ad5658f..425ce4f 100644 --- a/extension.json +++ b/extension.json @@ -129,6 +129,8 @@ "PFComboBoxInput": "includes/forminputs/PF_ComboBoxInput.php", "PFDateInput": "includes/forminputs/PF_DateInput.php", "PFDatePickerInput": "includes/forminputs/PF_DatePickerInput.php", + "PFTimePickerInput": "includes/forminputs/PF_TimePickerInput.php", + "PFDateTimePicker": "includes/forminputs/PF_DateTimePicker.php", "PFDateTimeInput": "includes/forminputs/PF_DateTimeInput.php", "PFYearInput": "includes/forminputs/PF_YearInput.php", "PFTreeInput": "includes/forminputs/PF_TreeInput.php", @@ -267,6 +269,19 @@ ], "position": "bottom" }, + "ext.pageforms.timepicker": { + "scripts": "libs/PF_timepicker.js", + "styles": "skins/PF_Timepicker.css", + "position": "bottom" + }, + "ext.pageforms.datetimepicker": { + "scripts": "libs/PF_datetimepicker.js", + "dependencies": [ + "ext.pageforms.datepicker", + "ext.pageforms.timepicker" + ], + "position": "bottom" + }, "ext.pageforms.regexp": { "scripts": "libs/PF_regexp.js", "dependencies": [ diff --git a/includes/PF_FormPrinter.php b/includes/PF_FormPrinter.php index 1b87ae0..22cb60d 100644 --- a/includes/PF_FormPrinter.php +++ b/includes/PF_FormPrinter.php @@ -44,6 +44,7 @@ $this->registerInputType( 'PFTextAreaWithAutocompleteInput' ); $this->registerInputType( 'PFDateInput' ); $this->registerInputType( 'PFDatePickerInput' ); + $this->registerInputType( 'PFDateTimePicker' ); $this->registerInputType( 'PFDateTimeInput' ); $this->registerInputType( 'PFYearInput' ); $this->registerInputType( 'PFCheckboxInput' ); diff --git a/includes/forminputs/PF_DateTimePicker.php b/includes/forminputs/PF_DateTimePicker.php new file mode 100644 index 0000000..7ceab70 --- /dev/null +++ b/includes/forminputs/PF_DateTimePicker.php @@ -0,0 +1,197 @@ +<?php + +/** + * File holding the PFDateTimePicker class + * + * @author Stephan Gambke + * @file + * @ingroup PageForms + */ + +/** + * The PFDateTimePicker class. + * + * @ingroup PageForms + */ +class PFDateTimePicker extends PFFormInput { + + protected $mDatePicker; + protected $mTimePicker; + + /** + * Constructor. + * + * @param String $input_number + * The number of the input in the form. + * @param String $cur_value + * The current value of the input field. + * @param String $input_name + * The name of the input. + * @param String $disabled + * Is this input disabled? + * @param Array $other_args + * An associative array of other parameters that were present in the + * input definition. + */ + public function __construct( $input_number, $cur_value, $input_name, $disabled, $other_args ) { + + parent::__construct( $input_number, $cur_value, $input_name, $disabled, $other_args ); + + // prepare sub-inputs + + $this->mOtherArgs["part of dtp"] = true; + + // find allowed values and keep only the date portion + if ( array_key_exists( 'possible_values', $this->mOtherArgs ) && + count( $this->mOtherArgs[ 'possible_values' ] ) ) { + + $this->mOtherArgs[ 'possible_values' ] = preg_replace( + '/^\s*(\d{4}\/\d{2}\/\d{2}).*/', + '$1', + $this->mOtherArgs[ 'possible_values' ] + ); + } + + $dateTimeString = trim( $this->mCurrentValue ); + $dateString = ''; + $timeString = ''; + + $separatorPos = strpos($dateTimeString, " "); + + // does it have a separating whitespace? assume it's a date & time + if ( $separatorPos ) { + $dateString = substr( $dateTimeString, 0, $separatorPos ); + $timeString = substr( $dateTimeString, $separatorPos + 1 ); + + // does it start with a time of some kind? + } elseif ( preg_match( '/^\d?\d:\d\d/', $dateTimeString ) ) { + $timeString = $dateTimeString; + + // if all else fails assume it's a date + } else { + $dateString = $dateTimeString; + } + + $this->mDatePicker = new PFDatePickerInput( $this->mInputNumber . '_dp', $dateString, $this->mInputName, $this->mIsDisabled, $this->mOtherArgs ); + $this->mTimePicker = new PFTimePickerInput( $this->mInputNumber . '_tp', $timeString, $this->mInputName, $this->mIsDisabled, $this->mOtherArgs ); + + // add JS data + $this->addJsInitFunctionData( 'PF_DTP_init', $this->setupJsInitAttribs() ); + + } + + /** + * Returns the name of the input type this class handles: menuselect. + * + * This is the name to be used in the field definition for the "input + * type" parameter. + * + * @return String The name of the input type this class handles. + */ + public static function getName() { + return 'datetimepicker'; + } + + protected function setupJsInitAttribs() { + $jsattribs = array(); + + $jsattribs['disabled'] = $this->mIsDisabled; + + if ( array_key_exists( 'class', $this->mOtherArgs ) ) { + $jsattribs['userClasses'] = $this->mOtherArgs['class']; + } else { + $jsattribs['userClasses'] = ''; + } + + $jsattribs['subinputs'] = + $this->mDatePicker->getHtmlText() . " " . + $this->mTimePicker->getHtmlText(); + + $jsattribs['subinputsInitData'] = array( + 'input_' . $this->mInputNumber . '_dp' => $this->mDatePicker->getJsInitFunctionData(), + 'input_' . $this->mInputNumber . '_tp' => $this->mTimePicker->getJsInitFunctionData() + ); + + // build JS code from attributes array + return $jsattribs; + } + + /** + * Returns the HTML code to be included in the output page for this input. + * + * Ideally this HTML code should provide a basic functionality even if the + * browser is not JavaScript capable. I.e. even without JavaScript the user + * should be able to input values. + * + */ + public function getHtmlText() { + $html = '<span class="inputSpan' . ( array_key_exists( 'mandatory', $this->mOtherArgs) ? ' mandatoryFieldSpan' : '') . '">' . + PFDatePickerInput::genericTextHTML( $this->mCurrentValue, $this->mInputName, $this->mIsDisabled, $this->mOtherArgs, 'input_' . $this->mInputNumber ) . + '</span>'; + + return $html; + + } + + /** + * Returns the set of SMW property types which this input can + * handle, but for which it isn't the default input. + */ + public static function getOtherPropTypesHandled() { + return array( '_str', '_dat' ); + } + + /** + * Returns the set of parameters for this form input. + */ + public static function getParameters() { + $params = array_merge( + parent::getParameters(), + PFDatePickerInput::getParameters() + ); + + // Copied from PFTimePickerInput, which was not moved + // over to Page Forms. + $params['mintime'] = array( + 'name' => 'mintime', + 'type' => 'string', + 'description' => wfMessage( 'pageforms-timepicker-mintime' )->text(), + ); + $params['maxtime'] = array( + 'name' => 'maxtime', + 'type' => 'string', + 'description' => wfMessage( 'pageforms-timepicker-maxtime' )->text(), + ); + $params['interval'] = array( + 'name' => 'interval', + 'type' => 'int', + 'description' => wfMessage( 'pageforms-timepicker-interval' )->text(), + ); + + return $params; + } + + /** + * Returns the name and parameters for the validation JavaScript + * functions for this input type, if any. + */ + public function getJsValidationFunctionData() { + return array_merge( + $this->mJsValidationFunctionData, + $this->mDatePicker->getJsValidationFunctionData() + ); + } + + /** + * Returns the names of the resource modules this input type uses. + * + * Returns the names of the modules as an array or - if there is only one + * module - as a string. + * + * @return null|string|array + */ + public function getResourceModuleNames() { + return array( 'ext.pageforms.timepicker', 'ext.pageforms.datetimepicker' ); + } + +} \ No newline at end of file diff --git a/includes/forminputs/PF_TimePickerInput.php b/includes/forminputs/PF_TimePickerInput.php new file mode 100644 index 0000000..65de81c --- /dev/null +++ b/includes/forminputs/PF_TimePickerInput.php @@ -0,0 +1,186 @@ +<?php + +/** + * File holding the PFTimePickerInput class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticFormsInputs + */ + +/** + * The PFTimePickerInput class. + * + * @ingroup SemanticFormsInputs + */ +class PFTimePickerInput extends PFFormInput { + + /** + * Constructor. + * + * @param String $input_number + * The number of the input in the form. + * @param String $cur_value + * The current value of the input field. + * @param String $input_name + * The name of the input. + * @param String $disabled + * Is this input disabled? + * @param Array $other_args + * An associative array of other parameters that were present in the + * input definition. + */ + public function __construct( $input_number, $cur_value, $input_name, $disabled, $other_args ) { + + parent::__construct( $input_number, $cur_value, $input_name, $disabled, $other_args ); + + $this->addJsInitFunctionData( 'PF_TP_init', $this->setupJsInitAttribs() ); + + } + + /** + * Returns the name of the input type this class handles: menuselect. + * + * This is the name to be used in the field definition for the "input type" + * parameter. + * + * @return String The name of the input type this class handles. + */ + public static function getName() { + return 'timepicker'; + } + + /** + * Set up JS attributes + * + * @return String + */ + protected function setupJsInitAttribs() { + global $wgExtensionAssetsPath; + + // store user class(es) for use with buttons + $userClasses = array_key_exists( 'class', $this->mOtherArgs ) ? $this->mOtherArgs['class'] : ''; + + // set min time if valid, else use default + if ( array_key_exists( 'mintime', $this->mOtherArgs ) + && ( preg_match( '/^\d+:\d\d$/', trim( $this->mOtherArgs['mintime'] ) ) == 1 ) ) { + $minTime = trim( $this->mOtherArgs['mintime'] ); +// } elseif ( $sfigSettings->timePickerMinTime != null ) { +// $minTime = $sfigSettings->timePickerMinTime; + } else { + $minTime = '00:00'; + } + + // set max time if valid, else use default + if ( array_key_exists( 'maxtime', $this->mOtherArgs ) + && ( preg_match( '/^\d+:\d\d$/', trim( $this->mOtherArgs['maxtime'] ) ) == 1 ) ) { + $maxTime = trim( $this->mOtherArgs['maxtime'] ); +// } elseif ( $sfigSettings->timePickerMaxTime != null ) { +// $maxTime = $sfigSettings->timePickerMaxTime; + } else { + $maxTime = '23:59'; + } + + // set interval if valid, else use default + if ( array_key_exists( 'interval', $this->mOtherArgs ) + && preg_match( '/^\d+$/', trim( $this->mOtherArgs['interval'] ) ) == 1 ) { + $interval = trim( $this->mOtherArgs['interval'] ); + } else { + $interval = '15'; + } + + // build JS code from attributes array + $jsattribs = array( + 'minTime' => $minTime, + 'maxTime' => $maxTime, + 'interval' => $interval, + 'format' => 'hh:mm', + 'currValue' => $this->mCurrentValue, + 'disabled' => $this->mIsDisabled, + 'userClasses' => $userClasses + ); + + if ( array_key_exists( 'part of dtp', $this->mOtherArgs ) ) { + $jsattribs['partOfDTP'] = $this->mOtherArgs['part of dtp']; + } + + // setup attributes required only for either disabled or enabled timepickers + if ( $this->mIsDisabled ) { + $jsattribs['buttonImage'] = $wgExtensionAssetsPath . '/PageForms/images/TimePickerButtonDisabled.gif'; + + } else { + $jsattribs['buttonImage'] = $wgExtensionAssetsPath . '/PageForms/images/TimePickerButton.gif'; + } + + return $jsattribs; + } + + /** + * Returns the HTML code to be included in the output page for this input. + * + * Ideally this HTML code should provide a basic functionality even if the + * browser is not Javascript capable. I.e. even without Javascript the user + * should be able to input values. + * + */ + public function getHtmlText(){ + // create visible input field (for display) and invisible field (for data) + $html = PFDatePickerInput::genericTextHTML( $this->mCurrentValue, $this->mInputName, $this->mIsDisabled, $this->mOtherArgs, 'input_' . $this->mInputNumber ); + + // wrap in span (e.g. used for mandatory inputs) + if ( ! array_key_exists( 'part of dtp', $this->mOtherArgs ) ) { + $html = '<span class="inputSpan' . ( array_key_exists( 'mandatory', $this->mOtherArgs )? ' mandatoryFieldSpan' : '') . '">' .$html . '</span>'; + } + + return $html; + } + + /** + * Returns the set of SMW property types which this input can + * handle, but for which it isn't the default input. + */ + public static function getOtherPropTypesHandled() { + return array( '_str', '_dat' ); + } + + /** + * Returns the set of parameters for this form input. + * + * TODO: Specify parameters specific for menuselect. + */ + public static function getParameters() { + + global $sfigSettings; + + $params = parent::getParameters(); + $params['mintime'] = array( + 'name' => 'mintime', + 'type' => 'string', + 'description' => wfMessage( 'semanticformsinputs-timepicker-mintime' )->text(), + ); + $params['maxtime'] = array( + 'name' => 'maxtime', + 'type' => 'string', + 'description' => wfMessage( 'semanticformsinputs-timepicker-maxtime' )->text(), + ); + $params['interval'] = array( + 'name' => 'interval', + 'type' => 'int', + 'description' => wfMessage( 'semanticformsinputs-timepicker-interval' )->text(), + ); + + return $params; + } + + /** + * Returns the names of the resource modules this input type uses. + * + * Returns the names of the modules as an array or - if there is only one + * module - as a string. + * + * @return null|string|array + */ + public function getResourceModuleNames() { + return 'ext.semanticformsinputs.timepicker'; + } +} \ No newline at end of file diff --git a/libs/PF_datetimepicker.js b/libs/PF_datetimepicker.js new file mode 100644 index 0000000..8185368 --- /dev/null +++ b/libs/PF_datetimepicker.js @@ -0,0 +1,70 @@ +/** + * JavaScript code to be used with input type datetimepicker. + * + * @author Stephan Gambke + * + */ +/*jshint sub:true*/ + +window.PF_DTP_init = function( inputId, params ) { + + var input = jQuery( '#' + inputId ); + + var tabindex = input.attr('tabindex'); + + var hiddenInput = jQuery( '<input type="hidden" >' ); + + hiddenInput.attr( { + id: inputId, + name: input.attr( 'name' ), + value: input.val() + } ); + + input.replaceWith( hiddenInput ); + input = hiddenInput; + + // create and insert subinput elements + var subinputs = jQuery( params.subinputs ); + input.before( subinputs ); + + // call initialisation functions for subinputs + for (var subinputId in params.subinputsInitData) { + if ( params.subinputsInitData[subinputId] ) { + for ( var index in params.subinputsInitData[subinputId] ) { + if( params.subinputsInitData[subinputId][index] ) { + var fn = window[ params.subinputsInitData[subinputId][index]['name'] ]; + var param = params.subinputsInitData[subinputId][index]['param']; + + if ( typeof fn === 'function' ) { + fn( subinputId, param ); + } + } + } + } + } + + var dp = jQuery( '#' + inputId + '_dp_show' ); // datepicker element + var tp = jQuery( '#' + inputId + '_tp_show' ); // timepicker element + + dp.add(tp) + .change (function(){ + + var date; + + // try parsing the date value + try { + + date = jQuery.datepicker.parseDate( dp.datepicker( 'option', 'dateFormat' ), dp.val(), null ); + date = jQuery.datepicker.formatDate( dp.datepicker( 'option', 'altFormat' ), date ); + + } catch ( e ) { + // value does not conform to specified format + // just return the value as is + date = dp.val(); + } + + input.val( jQuery.trim( date + ' ' + tp.val() ) ); + + }); + +}; \ No newline at end of file diff --git a/libs/PF_timepicker.js b/libs/PF_timepicker.js new file mode 100644 index 0000000..50a59df --- /dev/null +++ b/libs/PF_timepicker.js @@ -0,0 +1,243 @@ +/** + * Javascript code to be used with input type timepicker. + * + * @author Stephan Gambke + * + */ + +/** + * Initializes a timepicker input + * + * @param inputID (String) the id of the input to initialize + * @param params (Object) the parameter object for the timepicker, contains + * minTime: (String) the minimum time to be shown (format hh:mm) + * maxTime: (String) the maximum time to be shown (format hh:mm) + * interval: (String) the interval between selectable times in minutes + * format: (String) a format string (unused) (do we even need it?) + * + */ +window.PF_TP_init = function( inputID, params ) { // minTime, maxTime, interval, format + + var inputIDshow = inputID + '_show'; + + var inputShow = jQuery( '#' + inputID ); + inputShow.attr( 'id', inputIDshow ); + + var input; + + // set up hidden input if this timepicker is not part of a datetimepicker + if ( ! params.partOfDTP ) { + + input = jQuery( '<input type="hidden" >'); + input.attr( { + id: inputID, + name: inputShow.attr( 'name' ), + value: inputShow.val() + } ); + input.val(inputShow.val()); + + inputShow.after( input ); + inputShow.removeAttr( 'name' ); + + } else { + input = inputShow; + } + + var tabindex = inputShow.attr('tabindex'); + + // append time picker button + var button = jQuery( '<button type="button" ></button>' ); + button.attr({ + 'class': params.userClasses, + 'id': inputID + '_button', + 'tabindex': tabindex + }); + + + if ( params.disabled ) { + + button.attr( 'disabled', 'disabled' ); + + } else { + + button.click( function(){ + if ( jQuery( '#' + inputID + '_tree>ul' ).is(':visible') ) { + inputShow.blur(); + } else { + inputShow.focus(); + } + + } ); + + } + + var img = jQuery( '<img>' ); + img.attr( 'src', params.buttonImage ); + + button.append( img ); + + input.after( button ); + + // sanitize inputs + var re = /^\d+:\d\d$/; + var minh = 0; + var minm = 0; + + var maxh = 23; + var maxm = 59; + + if ( re.test( params.minTime ) ) { + + var min = params.minTime.split( ':', 2 ); + minh = Number( min[0] ); + minm = Number( min[1] ); + + if ( minm > 59 ) { + minm = 59; + } + } + + if ( re.test( params.maxTime ) ) { + + var max = params.maxTime.split( ':', 2 ); + maxh = Number( max[0] ); + maxm = Number( max[1] ); + + if ( maxm > 59 ) { + maxm = 59; + } + } + + var interv = Number( params.interval ); + + if ( interv < 1 ) { + interv = 1; + } + else if ( interv > 60 ) { + interv = 60; + } + + // build html structure + var sp = jQuery( '<span class="PF_timepicker" id="' + inputID + '_tree" ></span>' ).insertBefore( inputShow ); + + var ulh = jQuery( '<ul class="PF_timepicker_hours" >' ).appendTo( sp ); + + + for ( var h = minh; h <= maxh; ++h ) { + + var lih = jQuery( '<li class="ui-state-default PF_timepicker_hour">' + ( ( h < 10 ) ? '0' : '' ) + h + '</li>' ).appendTo( ulh ); + + //TODO: Replace value for "show" by formatted string + lih + .data( 'value', ( ( h < 10 ) ? '0' : '' ) + h + ':00' ) + .data( 'show', ( ( h < 10 ) ? '0' : '' ) + h + ':00' ); + + var ulm = jQuery( '<ul class="PF_timepicker_minutes" >' ).appendTo( lih ); + + for ( var m = ( (h === minh) ? minm : 0 ) ; m <= ( (h === maxh) ? maxm : 59 ); m += interv ) { + + var lim = jQuery( '<li class="ui-state-default PF_timepicker_minute">' + ( ( m < 10 ) ? '0' : '' ) + m + '</li>' ).appendTo( ulm ); + + //TODO: Replace value for "show" by formatted string + lim + .data( 'value', ( ( h < 10 ) ? '0' : '' ) + h + ':' + ( ( m < 10 ) ? '0' : "" ) + m ) + .data( 'show', ( ( h < 10 ) ? '0' : '' ) + h + ':' + ( ( m < 10 ) ? '0' : "" ) + m ); + + } + + } + + // initially hide everything + jQuery( '#' + inputID + '_tree ul' ) + .hide(); + + // attach event handlers + jQuery( '#' + inputID + '_tree li' ) // hours + .mouseover(function(evt){ + + // clear any timeout that may still run on the last list item + clearTimeout( jQuery( evt.currentTarget ).data( 'timeout' ) ); + + jQuery( evt.currentTarget ) + + // switch classes to change display style + .removeClass( 'ui-state-default' ) + .addClass( 'ui-state-hover' ) + + // set timeout to show minutes for selected hour + .data( 'timeout', setTimeout( + function(){ + jQuery( evt.currentTarget ).children().fadeIn(); + }, 400 ) ); + + }) + + .mouseout(function(evt){ + + // clear any timeout that may still run on this jQuery list item + clearTimeout( jQuery( evt.currentTarget ).data( 'timeout' ) ); + + jQuery( evt.currentTarget ) + + // switch classes to change display style + .removeClass( 'ui-state-hover' ) + .addClass( 'ui-state-default' ) + + // hide minutes after a short pause + .data( 'timeout', setTimeout( + function(){ + jQuery(evt.currentTarget).children().fadeOut(); + }, 400 ) ); + + }); + + jQuery( '#' + inputID + '_tree li' ) // hours, minutes + .mousedown(function(evt){ + + // set values and leave input + inputShow + // Are both these calls necessary? At least the 2nd one is. + .attr( 'value', jQuery( this ).data( 'show' ) ) + .val(jQuery( this ).data( 'show' ) ) + .blur() + .change(); + + // clear any timeout that may still run on this jQuery list item + clearTimeout( jQuery( evt.currentTarget ).data( 'timeout' ) ); + + jQuery( evt.currentTarget ) + + // switch classes to change display style + .removeClass( 'ui-state-hover' ) + .addClass( 'ui-state-default' ); + + // avoid propagation to parent list item (e.g. hours), + // they would overwrite the input value + return false; + }); + + // show timepicker when input gets focus + inputShow + .focus(function() { + jQuery( '#' + inputID + '_tree>ul' ).fadeIn(); + }); + + // hide timepicker when input loses focus + inputShow + .blur(function() { + jQuery( '#' + inputID + '_tree ul' ).fadeOut( 'normal', function() {jQuery(this).hide();}); + }); + + if ( ! params.partOfDTP ) { + inputShow + .change(function() { + jQuery( '#' + inputID ).val( jQuery(this).val() ); + }); + } + + jQuery( '#' + inputID + '_show ~ button[name="button"]' ) + .click( function() { + inputShow.focus(); + }); + +}; \ No newline at end of file diff --git a/skins/PF_Timepicker.css b/skins/PF_Timepicker.css new file mode 100644 index 0000000..2c842f6 --- /dev/null +++ b/skins/PF_Timepicker.css @@ -0,0 +1,35 @@ +/** + * Style sheet for the input type timepicker. + * + * @author Stephan Gambke + */ + +.PF_timepicker { + position: absolute; + cursor: default; + margin-top: 22px; + z-index: 1; +} + +.PF_timepicker ul { /* hours and minutes lists */ + margin: 0px; + padding: 0px; + list-style: none; + position: absolute; +} + +.PF_timepicker ul ul { /* minutes lists only */ + margin-left: 24px; + margin-right: 24px; + margin-top: -22px; + list-style: none; +} + + +.PF_timepicker li { /* hours and minutes entries */ + margin: 1px 0px; + padding: 0px; + text-align: center; + line-height: 22px; + width: 22px; +} \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/325361 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ieb6e8348c64cd0d0cf0c8fe86f776d393fe7d65c Gerrit-PatchSet: 2 Gerrit-Project: mediawiki/extensions/PageForms Gerrit-Branch: master Gerrit-Owner: Yaron Koren <yaro...@gmail.com> Gerrit-Reviewer: Yaron Koren <yaro...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits