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

Reply via email to