r79522 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r79521‎ | r79522 | r79523 >
Date:20:18, 3 January 2011
Author:foxtrott
Status:deferred
Tags:
Comment:
new input type datetimepicker
Modified paths:
  • /trunk/extensions/SemanticFormsInputs/SFI_Inputs.php (modified) (history)
  • /trunk/extensions/SemanticFormsInputs/SFI_Settings.php (modified) (history)
  • /trunk/extensions/SemanticFormsInputs/SemanticFormsInputs.php (modified) (history)
  • /trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButton.gif (added) (history)
  • /trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButtonDisabled.gif (added) (history)
  • /trunk/extensions/SemanticFormsInputs/libs/datepicker.js (modified) (history)
  • /trunk/extensions/SemanticFormsInputs/libs/datetimepicker.js (added) (history)
  • /trunk/extensions/SemanticFormsInputs/libs/timepicker.js (modified) (history)
  • /trunk/extensions/SemanticFormsInputs/skins/SFI_Timepicker.css (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticFormsInputs/SemanticFormsInputs.php
@@ -45,7 +45,7 @@
4646 class SFISettings {
4747 // general settings
4848 public $scriptPath;
49 - public $yuiBase;
 49+ //public $yuiBase;
5050
5151 // settings for input type datepicker
5252 public $datePickerFirstDate;
@@ -73,6 +73,7 @@
7474 $sfgFormPrinter->setInputTypeHook( 'datepicker', array( 'SFIInputs', 'jqDatePickerHTML' ), array() );
7575 $sfgFormPrinter->setInputTypeHook( 'simpledatepicker', array( 'SFIInputs', 'jqDatePickerHTML' ), array() );
7676 $sfgFormPrinter->setInputTypeHook( 'timepicker', array( 'SFIInputs', 'timepickerHTML' ), array() );
 77+ $sfgFormPrinter->setInputTypeHook( 'datetimepicker', array( 'SFIInputs', 'datetimepickerHTML' ), array() );
7778 // $sfgFormPrinter->setInputTypeHook( 'wysiwyg', array( 'SFIInputs', 'wysiwygHTML' ), array() );
7879 $sfgFormPrinter->setInputTypeHook( 'menuselect', array( 'SFIInputs', 'menuselectHTML' ), array() );
7980
Index: trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButtonDisabled.gif
Cannot display: file marked as a binary type.
svn:mime-type = image/gif
Property changes on: trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButtonDisabled.gif
___________________________________________________________________
Added: svn:mime-type
8081 + image/gif
Index: trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButton.gif
Cannot display: file marked as a binary type.
svn:mime-type = image/gif
Property changes on: trunk/extensions/SemanticFormsInputs/images/DateTimePickerResetButton.gif
___________________________________________________________________
Added: svn:mime-type
8182 + image/gif
Index: trunk/extensions/SemanticFormsInputs/SFI_Settings.php
@@ -159,3 +159,10 @@
160160 #
161161 $sfigSettings->timePickerShowResetButton = false;
162162
 163+
 164+##
 165+# This determines if a reset button shall be shown. This is the only
 166+# way to erase the input field if it is disabled for direct input.
 167+#
 168+$sfigSettings->datetimePickerShowResetButton = false;
 169+
Index: trunk/extensions/SemanticFormsInputs/skins/SFI_Timepicker.css
@@ -6,9 +6,9 @@
77 */
88
99 .SFI_timepicker {
10 - display: block;
1110 position: absolute;
1211 cursor: default;
 12+ margin-top: 22px;
1313 }
1414
1515 .SFI_timepicker ul { /* hours and minutes lists */
Index: trunk/extensions/SemanticFormsInputs/SFI_Inputs.php
@@ -9,8 +9,8 @@
1010 *
1111 */
1212
13 -if ( !defined( 'MEDIAWIKI' ) ) {
14 - die( 'This file is a MediaWiki extension, it is not a valid entry point.' );
 13+if ( !defined( 'SFI_VERSION' ) ) {
 14+ die( 'This file is part of a MediaWiki extension, it is not a valid entry point.' );
1515 }
1616
1717 class SFIInputs {
@@ -111,19 +111,15 @@
112112 /**
113113 * Definition of input type "regexp"
114114 *
115 - * Returns an array containing three elements: the html code and the JS code
116 - * to be included in the page and the name of a JS function to be called to
117 - * initialize the input.
 115+ * Returns the html code to be included in the page and registers the
 116+ * input's JS initialisation method
118117 *
119 - * These values are all taken from the base input type, the JS for the
120 - * regexp is written to the code directly.
121 - *
122118 * @param string $cur_value current value of this field (which is sometimes null)
123119 * @param string $input_name HTML name that this input should have
124120 * @param boolean $is_mandatory indicates whether this field is mandatory for the user
125121 * @param boolean $is_disabled indicates whether this field is disabled (meaning, the user can't edit)
126122 * @param array $other_args hash representing all the other properties defined for this input in the form definition
127 - * @return array of two strings
 123+ * @return string html code of input
128124 */
129125 static function regexpHTML ( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) {
130126
@@ -458,17 +454,15 @@
459455 /**
460456 * Definition of input type "datepicker".
461457 *
462 - * Returns an array containing three elements: the html code to be included
463 - * in the page, an empty string (instead of JS initialization code, which is
464 - * inserted into the page directly) and the name of a JS function to be
465 - * called to initialize the input.
 458+ * Returns the html code to be included in the page and registers the
 459+ * input's JS initialisation method
466460 *
467461 * @param string $cur_value current value of this field (which is sometimes null)
468462 * @param string $input_name HTML name that this input should have
469463 * @param boolean $is_mandatory indicates whether this field is mandatory for the user
470464 * @param boolean $is_disabled indicates whether this field is disabled (meaning, the user can't edit)
471465 * @param array $other_args hash representing all the other properties defined for this input in the form definition
472 - * @return array of three strings
 466+ * @return string html code of input
473467 */
474468 static function jqDatePickerHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) {
475469
@@ -499,9 +493,96 @@
500494 || ( !array_key_exists( 'enable input field', $other_args ) && $sfigSettings->datePickerDisableInputField )
501495 || $is_disabled ;
502496
503 - // second: set up JS attributes, but only if we need them
504 - if ( !$is_disabled ) {
 497+ // second: set up JS attributes
505498
 499+ // set up attributes required for both enabled and disabled datepickers
 500+ $jsattribs = array(
 501+ 'currValue' => $cur_value,
 502+ 'disabled' => $is_disabled,
 503+ 'userClasses' => $userClasses
 504+ );
 505+
 506+ if ( array_key_exists( 'part of dtp', $other_args ) ) {
 507+ $jsattribs['partOfDTP'] = $other_args['part of dtp'];
 508+ }
 509+
 510+ // set date format
 511+ // SHORT and LONG are SFI specific acronyms and are translated here
 512+ // into format strings, anything else is passed to the jQuery date picker
 513+ // Americans need special treatment
 514+ if ( $wgAmericanDates && $wgLang->getCode() == "en" ) {
 515+
 516+ if ( array_key_exists( 'date format', $other_args ) ) {
 517+
 518+ if ( $other_args['date format'] == 'SHORT' ) {
 519+ $jsattribs['dateFormat'] = 'mm/dd/yy';
 520+ } elseif ( $other_args['date format'] == 'LONG' ) {
 521+ $jsattribs['dateFormat'] = 'MM d, yy';
 522+ } else {
 523+ $jsattribs['dateFormat'] = $other_args['date format'];
 524+ }
 525+
 526+ } elseif ( $sfigSettings->datePickerDateFormat ) {
 527+
 528+ if ( $sfigSettings->datePickerDateFormat == 'SHORT' ) {
 529+ $jsattribs['dateFormat'] = 'mm/dd/yy';
 530+ } elseif ( $sfigSettings->datePickerDateFormat == 'LONG' ) {
 531+ $jsattribs['dateFormat'] = 'MM d, yy';
 532+ } else {
 533+ $jsattribs['dateFormat'] = $sfigSettings->datePickerDateFormat;
 534+ }
 535+
 536+ } else $jsattribs['dateFormat'] = 'yy/mm/dd';
 537+
 538+ } else {
 539+
 540+ if ( array_key_exists( 'date format', $other_args ) ) {
 541+
 542+ if ( $other_args['date format'] == 'SHORT' ) {
 543+ $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatshort' );
 544+ } elseif ( $other_args['date format'] == 'LONG' ) {
 545+ $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatlong' );
 546+ } else {
 547+ $jsattribs['dateFormat'] = $other_args['date format'];
 548+ }
 549+
 550+ } elseif ( $sfigSettings->datePickerDateFormat ) {
 551+
 552+ if ( $sfigSettings->datePickerDateFormat == 'SHORT' ) {
 553+ $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatshort' );
 554+ } elseif ( $sfigSettings->datePickerDateFormat == 'LONG' ) {
 555+ $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatlong' );
 556+ } else {
 557+ $jsattribs['dateFormat'] = $sfigSettings->datePickerDateFormat;
 558+ }
 559+
 560+ } else $jsattribs['dateFormat'] = 'yy/mm/dd';
 561+
 562+ }
 563+
 564+ // setup attributes required only for either disabled or enabled datepickers
 565+ if ( $is_disabled ) {
 566+
 567+ $jsattribs['buttonImage'] = $sfigSettings->scriptPath . '/images/DatePickerButtonDisabled.gif';
 568+
 569+ if ( array_key_exists( 'show reset button', $other_args ) ||
 570+ ( !array_key_exists( 'hide reset button', $other_args ) && $sfigSettings->datePickerShowResetButton ) ) {
 571+
 572+ $jsattribs['resetButtonImage'] = $sfigSettings->scriptPath . '/images/DatePickerResetButtonDisabled.gif';
 573+
 574+ }
 575+
 576+ } else {
 577+
 578+ $jsattribs['buttonImage'] = $sfigSettings->scriptPath . '/images/DatePickerButton.gif';
 579+
 580+ if ( array_key_exists( 'show reset button', $other_args ) ||
 581+ ( !array_key_exists( 'hide reset button', $other_args ) && $sfigSettings->datePickerShowResetButton ) ) {
 582+
 583+ $jsattribs['resetButtonImage'] = $sfigSettings->scriptPath . '/images/DatePickerResetButton.gif';
 584+
 585+ }
 586+
506587 // find min date, max date and disabled dates
507588
508589 // set first date
@@ -640,12 +721,6 @@
641722 $highlightedDays = null;
642723 }
643724
644 - // set datepicker widget attributes
645 - $jsattribs = array(
646 - 'currValue' => $cur_value,
647 - 'buttonImage' => $sfigSettings->scriptPath . '/images/DatePickerButton.gif',
648 - );
649 -
650725 // set first day of the week
651726 if ( array_key_exists( 'week start', $other_args ) ) {
652727 $jsattribs['firstDay'] = $other_args['week start'];
@@ -664,243 +739,190 @@
665740 $jsattribs['showWeek'] = false;
666741 }
667742
668 - // set date format
669 - // SHORT and LONG are SFI specific acronyms and are translated here
670 - // into format strings, anything else is passed to the jQuery date picker
671 - // Americans need special treatment
672 - if ( $wgAmericanDates && $wgLang->getCode() == "en" ) {
 743+ // store min date as JS attrib
 744+ if ( $minDate ) {
 745+ $jsattribs['minDate'] = $minDate->format( 'Y/m/d' );
 746+ }
673747
674 - if ( array_key_exists( 'date format', $other_args ) ) {
 748+ // store max date as JS attrib
 749+ if ( $maxDate ) {
 750+ $jsattribs['maxDate'] = $maxDate->format( 'Y/m/d' );
 751+ }
675752
676 - if ( $other_args['date format'] == 'SHORT' ) {
677 - $jsattribs['dateFormat'] = 'mm/dd/yy';
678 - } elseif ( $other_args['date format'] == 'LONG' ) {
679 - $jsattribs['dateFormat'] = 'MM d, yy';
680 - } else {
681 - $jsattribs['dateFormat'] = $other_args['date format'];
682 - }
 753+ // register disabled dates with datepicker
 754+ if ( count( $disabledDates ) > 0 ) {
683755
684 - } elseif ( $sfigSettings->datePickerDateFormat ) {
 756+ // convert the PHP array of date ranges into an array of numbers
 757+ $jsattribs["disabledDates"] = array_map( create_function ( '$range', '
685758
686 - if ( $sfigSettings->datePickerDateFormat == 'SHORT' ) {
687 - $jsattribs['dateFormat'] = 'mm/dd/yy';
688 - } elseif ( $sfigSettings->datePickerDateFormat == 'LONG' ) {
689 - $jsattribs['dateFormat'] = 'MM d, yy';
690 - } else {
691 - $jsattribs['dateFormat'] = $sfigSettings->datePickerDateFormat;
692 - }
 759+ $y0 = $range[0]->format( "Y" );
 760+ $m0 = $range[0]->format( "m" ) - 1;
 761+ $d0 = $range[0]->format( "d" );
693762
694 - } else $jsattribs['dateFormat'] = 'yy/mm/dd';
 763+ $y1 = $range[1]->format( "Y" );
 764+ $m1 = $range[1]->format( "m" ) - 1;
 765+ $d1 = $range[1]->format( "d" );
695766
696 - } else {
 767+ return array($y0, $m0, $d0, $y1, $m1, $d1);
 768+ ' ) , $disabledDates );
 769+ }
697770
698 - if ( array_key_exists( 'date format', $other_args ) ) {
 771+ // register highlighted dates with datepicker
 772+ if ( count( $highlightedDates ) > 0 ) {
699773
700 - if ( $other_args['date format'] == 'SHORT' ) {
701 - $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatshort' );
702 - } elseif ( $other_args['date format'] == 'LONG' ) {
703 - $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatlong' );
704 - } else {
705 - $jsattribs['dateFormat'] = $other_args['date format'];
706 - }
 774+ // convert the PHP array of date ranges into an array of numbers
 775+ $jsattribs["highlightedDates"] = array_map( create_function ( '$range', '
707776
708 - } elseif ( $sfigSettings->datePickerDateFormat ) {
 777+ $y0 = $range[0]->format( "Y" );
 778+ $m0 = $range[0]->format( "m" ) - 1;
 779+ $d0 = $range[0]->format( "d" );
709780
710 - if ( $sfigSettings->datePickerDateFormat == 'SHORT' ) {
711 - $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatshort' );
712 - } elseif ( $sfigSettings->datePickerDateFormat == 'LONG' ) {
713 - $jsattribs['dateFormat'] = wfMsg( 'semanticformsinputs-dateformatlong' );
714 - } else {
715 - $jsattribs['dateFormat'] = $sfigSettings->datePickerDateFormat;
716 - }
 781+ $y1 = $range[1]->format( "Y" );
 782+ $m1 = $range[1]->format( "m" ) - 1;
 783+ $d1 = $range[1]->format( "d" );
717784
718 - } else $jsattribs['dateFormat'] = 'yy/mm/dd';
 785+ return array($y0, $m0, $d0, $y1, $m1, $d1);
 786+ ' ) , $highlightedDates );
 787+ }
719788
 789+ // register disabled days of week with datepicker
 790+ if ( count( $disabledDays ) > 0 ) {
 791+ $jsattribs["disabledDays"] = $disabledDays;
720792 }
721793
 794+ // register highlighted days of week with datepicker
 795+ if ( count( $highlightedDays ) > 0 ) {
 796+ $jsattribs["highlightedDays"] = $highlightedDays;
 797+ }
722798 }
723799
724800
725801 // third: assemble HTML and JS code
726802
727 - if ( $is_disabled ) {
 803+ // start with the displayed input and append the real, but hidden
 804+ // input that gets sent to SF; it will be filled by the datepicker
 805+ $html = self::textHTML( $cur_value, "", $is_mandatory, $inputFieldDisabled,
 806+ $other_args, "input_{$sfgFieldNum}_dp_show", null, "createboxInput" );
728807
729 - // if the input field is disabled, create a mockup without functionality
 808+ if ( ! array_key_exists( 'part of dtp', $other_args ) ) {
730809
731 - // first create a simple text input and an inert button
732 - $html = self::textHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args, null, null, "createboxInput" )
733 -
734 - . Xml::element( "button",
 810+ $html .= Xml::element( "input",
735811 array(
736 - 'type' => 'button',
737 - 'class' => $userClasses,
738 - 'disabled' => '1',
739 - 'id' => "input_{$sfgFieldNum}_button"
740 - ) )
 812+ "id" => "input_{$sfgFieldNum}",
 813+ "name" => $input_name,
 814+ "type" => "hidden",
 815+ "value" => $cur_value
 816+ ) );
741817
742 - . Xml::element( "image",
743 - array(
744 - 'src' => $sfigSettings->scriptPath . '/images/DatePickerButtonDisabled.gif'
745 - ) )
 818+ // wrap in span (e.g. used for mandatory inputs)
 819+ $html = '<span class="inputSpan' . ($is_mandatory ? ' mandatoryFieldSpan' : '') . '">' .$html . '</span>';
 820+ }
746821
747 - . Xml::closeElement( "button" );
 822+ // build JS code from attributes array
 823+ $jsattribsString = Xml::encodeJsVar( $jsattribs );
748824
749 - // append reset button if required
750 - if ( array_key_exists( 'show reset button', $other_args ) ||
751 - $sfigSettings->datePickerShowResetButton && !array_key_exists( 'hide reset button', $other_args ) ) {
 825+ // wrap the JS code fragment in a function for deferred init
 826+ $jstext = <<<JAVASCRIPT
 827+jQuery(function(){ jQuery('#input_{$sfgFieldNum}_dp_show').registerInitialisation(SFI_DP_init, $jsattribsString ); });
 828+JAVASCRIPT;
752829
753 - $html .= Xml::openElement( "button",
754 - array(
755 - 'type' => 'button',
756 - 'class' => $userClasses,
757 - 'disabled' => '1',
758 - 'id' => "input_{$sfgFieldNum}_resetbutton"
759 - ) )
 830+ // insert the code of the JS init function into the pages code
 831+ $wgOut->addScript( '<script type="text/javascript">' . $jstext . '</script>' );
760832
761 - . Xml::element( "image",
762 - array(
763 - 'src' => $sfigSettings->scriptPath . '/images/DatePickerResetButtonDisabled.gif'
764 - ) )
 833+ //return array( $html, "", "initInput$sfgFieldNum" );
 834+ return $html;
765835
766 - . Xml::closeElement( "button" );
 836+ }
767837
768 - }
 838+ /**
 839+ * Setup for input type jqdatepicker.
 840+ *
 841+ * Adds the Javascript code used by all datetimepickers.
 842+ */
 843+ static private function datetimePickerSetup () {
769844
770 - // no JS needed on a disabled datepicker
771 - $jstext = '';
 845+ global $wgOut, $sfigSettings;
772846
773 - } else {
 847+ static $hasRun = false;
774848
775 - // start with the displayed input and append the real, but hidden
776 - // input that gets sent to SF; it will be filled by the datepicker
777 - $html = self::textHTML( $cur_value, "", $is_mandatory, $inputFieldDisabled,
778 - $other_args, "input_{$sfgFieldNum}_show", null, "createboxInput" )
 849+ if ( !$hasRun ) {
 850+ $hasRun = true;
779851
780 - . Xml::element( "input",
781 - array(
782 - "id" => "input_{$sfgFieldNum}",
783 - "name" => $input_name,
784 - "type" => "hidden"
785 - ) );
 852+ $wgOut->addScript( '<script type="text/javascript" src="' . $sfigSettings->scriptPath . '/libs/datetimepicker.js"></script> ' );
786853
787 - // append reset button if required
788 - if ( array_key_exists( 'show reset button', $other_args ) ||
789 - ( !array_key_exists( 'hide reset button', $other_args ) && $sfigSettings->datePickerShowResetButton ) ) {
 854+ }
 855+ }
790856
791 - // can not use Xml::element, it would sanitize the onclick attribute
792 - $html .= "<button "
793 - . Xml::expandAttributes ( array(
794 - 'type' => 'button',
795 - 'class' => $userClasses,
796 - 'id' => "input_{$sfgFieldNum}_resetbutton",
797 - ) )
798 - . "onclick= \"\n"
799 - . "document.getElementById(this.id.replace('_resetbutton','')).value='';"
800 - . "document.getElementById(this.id.replace('_resetbutton','_show')).value='';"
801 - . "\""
802 - . ">"
 857+ /**
 858+ * Definition of input type "datetimepicker".
 859+ *
 860+ * Returns the html code to be included in the page and registers the
 861+ * input's JS initialisation method
 862+ *
 863+ * @param string $cur_value current value of this field (which is sometimes null)
 864+ * @param string $input_name HTML name that this input should have
 865+ * @param boolean $is_mandatory indicates whether this field is mandatory for the user
 866+ * @param boolean $is_disabled indicates whether this field is disabled (meaning, the user can't edit)
 867+ * @param array $other_args hash representing all the other properties defined for this input in the form definition
 868+ * @return string html code of input
 869+ */
 870+ static function datetimepickerHTML($cur_value, $input_name, $is_mandatory, $is_disabled, $other_args) {
803871
804 - . Xml::element( "image",
805 - array(
806 - 'src' => $sfigSettings->scriptPath . '/images/DatePickerResetButton.gif'
807 - ) )
 872+ global $wgOut, $sfgFieldNum, $sfigSettings;
808873
809 - . Xml::closeElement( "button" );
 874+ self::datetimePickerSetup();
810875
811 - }
 876+ $other_args["part of dtp"] = true;
812877
813 - // sanitize current value before putting it into the JS code
814 - $cur_value = Xml::escapeJsString( $cur_value );
 878+ $jsAttribs = array();
815879
816 - // build JS code from attributes array
817 - $jsattribsString = Xml::encodeJsVar( $jsattribs );
 880+ // if we have to show a reset button
 881+ if ( array_key_exists( 'show reset button', $other_args ) ||
 882+ ( !array_key_exists( 'hide reset button', $other_args ) && $sfigSettings->datetimePickerShowResetButton ) ) {
818883
819 - // store min date as JS attrib
820 - if ( $minDate ) {
821 - $jsattribs['minDate'] = $minDate->format( 'Y/m/d' );
822 - }
 884+ // some values must be available to the init function
823885
824 - // store max date as JS attrib
825 - if ( $maxDate ) {
826 - $jsattribs['maxDate'] = $maxDate->format( 'Y/m/d' );
827 - }
 886+ // is the button disabled?
 887+ $jsattribs['disabled'] = $is_disabled;
828888
829 -
830 - // add user-defined class(es) to all datepicker components
831 - if ( array_key_exists( 'class', $other_args ) ) {
832 - $jsattribs['userClass'] = $userClasses;
 889+ // set the button image
 890+ if ( $is_disabled ) {
 891+ $jsattribs['resetButtonImage'] = $sfigSettings->scriptPath . '/images/DateTimePickerResetButtonDisabled.gif';
 892+ } else {
 893+ $jsattribs['resetButtonImage'] = $sfigSettings->scriptPath . '/images/DateTimePickerResetButton.gif';
833894 }
834895
835 - // attach event handler to handle disabled and highlighted dates
836 - if ( count( $disabledDates ) || count( $highlightedDates ) || count( $disabledDays ) || count( $highlightedDays ) ) {
 896+ // set user classes
 897+ if ( array_key_exists( 'class', $other_args ) ) $jsattribs[ "userClasses" ] = $other_args['class'];
 898+ else $jsattribs[ "userClasses" ] = "";
837899
838 - // first register disabled dates with datepicker
839 - if ( count( $disabledDates ) ) {
 900+ }
840901
841 - // convert the PHP array of date ranges into a JS array definition
842 - $jsattribs["disabledDates"] = array_map( create_function ( '$range', '
 902+ // build JS code from attributes array
 903+ $jsattribsString = Xml::encodeJsVar( $jsattribs );
843904
844 - $y0 = $range[0]->format( "Y" );
845 - $m0 = $range[0]->format( "m" ) - 1;
846 - $d0 = $range[0]->format( "d" );
847 -
848 - $y1 = $range[1]->format( "Y" );
849 - $m1 = $range[1]->format( "m" ) - 1;
850 - $d1 = $range[1]->format( "d" );
851 -
852 - return array($y0, $m0, $d0, $y1, $m1, $d1);
853 - ' ) , $disabledDates );
854 - }
855 -
856 - // then register highlighted dates with datepicker
857 - if ( count( $highlightedDates ) > 0 ) {
858 -
859 - // convert the PHP array of date ranges into a JS array definition
860 - $jsattribs["highlightedDates"] = array_map( create_function ( '$range', '
861 -
862 - $y0 = $range[0]->format( "Y" );
863 - $m0 = $range[0]->format( "m" ) - 1;
864 - $d0 = $range[0]->format( "d" );
865 -
866 - $y1 = $range[1]->format( "Y" );
867 - $m1 = $range[1]->format( "m" ) - 1;
868 - $d1 = $range[1]->format( "d" );
869 -
870 - return array($y0, $m0, $d0, $y1, $m1, $d1);
871 - ' ) , $highlightedDates );
872 - }
873 -
874 - // register disabled days of week with datepicker
875 - if ( count( $disabledDays ) ) {
876 - $jsattribs["disabledDays"] = $disabledDays;
877 - }
878 -
879 - // register highlighted days of week with datepicker
880 - if ( count( $highlightedDays ) ) {
881 - $jsattribs["highlightedDays"] = $highlightedDays;
882 - }
883 - }
884 -
885 - // build JS code from attributes array
886 - $jsattribsString = Xml::encodeJsVar( $jsattribs );
887 -
888 - // wrap the JS code fragment in a function for deferred init
889 - $jstext = <<<JAVASCRIPT
890 -jQuery(function(){ jQuery('#input_$sfgFieldNum').registerInitialisation(SFI_DP_init, $jsattribsString ); });
 905+ $jstext = <<<JAVASCRIPT
 906+jQuery(function(){ jQuery('#input_$sfgFieldNum').registerInitialisation(SFI_DTP_init, $jsattribsString ); });
891907 JAVASCRIPT;
892908
893 -
894 - }
895 -
896 - // wrap in span (e.g. used for mandatory inputs)
897 - $html = '<span class="inputSpan' . ($is_mandatory ? ' mandatoryFieldSpan' : '') . '">' .$html . '</span>';
898 -
899909 // insert the code of the JS init function into the pages code
900 - $wgOut->addScript( '<script type="text/javascript">' . $jstext . '</script>' );
 910+ $wgOut->addScript('<script type="text/javascript">' . $jstext . '</script>');
901911
902 - return array( $html, "", "initInput$sfgFieldNum" );
 912+ $html = '<span class="inputSpan' . ($is_mandatory ? ' mandatoryFieldSpan' : '') . '">' .
 913+ self::jqDatePickerHTML($cur_value, $input_name, $is_mandatory, $is_disabled, $other_args) . " " .
 914+ self::timepickerHTML($cur_value, $input_name, $is_mandatory, $is_disabled, $other_args) .
 915+ Xml::element("input",
 916+ array(
 917+ "id" => "input_{$sfgFieldNum}",
 918+ "name" => $input_name,
 919+ "type" => "hidden",
 920+ "value" => $cur_value
 921+ ))
 922+ . '</span>';
903923
 924+ return $html;
904925 }
 926+
905927 //
906928 // static function wysiwygSetup() {
907929 //
@@ -963,17 +985,15 @@
964986 /**
965987 * Definition of input type "timepicker"
966988 *
967 - * Returns an array containing three elements: the html code to be included
968 - * in the page, an empty string (instead of JS initialization code, which is
969 - * inserted into the page directly) and the name of a JS function to be
970 - * called to initialize the input.
 989+ * Returns the html code to be included in the page and registers the
 990+ * input's JS initialisation method
971991 *
972992 * @param string $cur_value current value of this field (which is sometimes null)
973993 * @param string $input_name HTML name that this input should have
974994 * @param boolean $is_mandatory indicates whether this field is mandatory for the user
975995 * @param boolean $is_disabled indicates whether this field is disabled (meaning, the user can't edit)
976996 * @param array $other_args hash representing all the other properties defined for this input in the form definition
977 - * @return array of three strings
 997+ * @return string html code of input
978998 */
979999 static function timepickerHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) {
9801000
@@ -999,13 +1019,16 @@
10001020
10011021 // second: assemble HTML
10021022 // create visible input field (for display) and invisible field (for data)
1003 - $html = self::textHTML( $cur_value, '', $is_mandatory, $inputFieldDisabled, $other_args, "input_{$sfgFieldNum}_show", null, "createboxInput" )
1004 - . Xml::element( "input", array(
 1023+ $html = self::textHTML( $cur_value, '', $is_mandatory, $inputFieldDisabled, $other_args, "input_{$sfgFieldNum}_tp_show", null, "createboxInput" );
 1024+
 1025+ if ( ! array_key_exists( 'part of dtp', $other_args ) ) {
 1026+ $html .= Xml::element( "input", array(
10051027 'id' => "input_{$sfgFieldNum}",
10061028 'type' => 'hidden',
10071029 'name' => $input_name,
10081030 'value' => $cur_value
10091031 ) );
 1032+ }
10101033
10111034 // append time picker button
10121035 if ( $is_disabled ) {
@@ -1034,7 +1057,7 @@
10351058 'class' => 'createboxInput ' . $userClasses,
10361059 'name' => "button",
10371060 ) )
1038 - . "onclick=\"document.getElementById(this.id.replace('_button','_show')).focus();\""
 1061+ . "onclick=\"document.getElementById(this.id.replace('_button','_tp_show')).focus();\""
10391062 . ">"
10401063
10411064 . Xml::element(
@@ -1047,8 +1070,11 @@
10481071 }
10491072
10501073 // append reset button (if selected)
1051 - if ( array_key_exists( 'show reset button', $other_args ) ||
1052 - $sfigSettings->timePickerShowResetButton && !array_key_exists( 'hide reset button', $other_args ) ) {
 1074+ if ( ! array_key_exists( 'part of dtp', $other_args ) &&
 1075+ ( array_key_exists( 'show reset button', $other_args ) ||
 1076+ $sfigSettings->timePickerShowResetButton && !array_key_exists( 'hide reset button', $other_args )
 1077+ )
 1078+ ) {
10531079
10541080 if ( $is_disabled ) {
10551081
@@ -1077,7 +1103,7 @@
10781104 'name' => "resetbutton",
10791105 ) )
10801106 . "onclick=\"document.getElementById(this.id.replace('_resetbutton','')).value='';"
1081 - . "document.getElementById(this.id.replace('_resetbutton','_show')).value='';\""
 1107+ . "document.getElementById(this.id.replace('_resetbutton','_tp_show')).value='';\""
10821108 . ">"
10831109
10841110 . Xml::element(
@@ -1091,7 +1117,9 @@
10921118 }
10931119
10941120 // wrap in span (e.g. used for mandatory inputs)
1095 - $html = '<span class="inputSpan' . ($is_mandatory ? ' mandatoryFieldSpan' : '') . '">' .$html . '</span>';
 1121+ if ( ! array_key_exists( 'part of dtp', $other_args ) ) {
 1122+ $html = '<span class="inputSpan' . ($is_mandatory ? ' mandatoryFieldSpan' : '') . '">' .$html . '</span>';
 1123+ }
10961124
10971125 // third: if the timepicker is not disabled set up JS attributes ans assemble JS call
10981126 if ( !$is_disabled ) {
@@ -1123,29 +1151,32 @@
11241152 }
11251153
11261154 // build JS code from attributes array
1127 - $jstext = Xml::encodeJsVar( array(
 1155+ $jsattribs = array(
11281156 "minTime" => $minTime,
11291157 "maxTime" => $maxTime,
11301158 "interval" => $interval,
11311159 "format" => "hh:mm"
1132 - ) );
 1160+ );
11331161
 1162+ if ( array_key_exists( 'part of dtp', $other_args ) ) {
 1163+ $jsattribs['partOfDTP'] = $other_args['part of dtp'];
 1164+ }
 1165+
 1166+ $jstext = Xml::encodeJsVar( $jsattribs );
 1167+
11341168 $jstext = <<<JAVASCRIPT
1135 -jQuery(function(){ jQuery('#input_$sfgFieldNum').registerInitialisation(SFI_TP_init, $jstext ); });
 1169+jQuery(function(){ jQuery('#input_{$sfgFieldNum}_tp_show').registerInitialisation(SFI_TP_init, $jstext ); });
11361170 JAVASCRIPT;
11371171
11381172 // write JS code directly to the page's code
11391173 $wgOut->addScript( '<script type="text/javascript">' . $jstext . '</script>' );
11401174
11411175 // return HTML and name of JS init function
1142 - return $html;
11431176
1144 - } else {
 1177+ }
11451178
1146 - return $html;
 1179+ return $html;
11471180
1148 - }
1149 -
11501181 }
11511182
11521183 /**
@@ -1172,10 +1203,15 @@
11731204 /**
11741205 * Definition of input type "menuselect"
11751206 *
1176 - * Returns an array containing two elements: the html text to be included
1177 - * and an empty string (no JS code necessary)
 1207+ * Returns the html code to be included in the page and registers the
 1208+ * input's JS initialisation method
11781209 *
1179 - * @return array of two strings
 1210+ * @param string $cur_value current value of this field (which is sometimes null)
 1211+ * @param string $input_name HTML name that this input should have
 1212+ * @param boolean $is_mandatory indicates whether this field is mandatory for the user
 1213+ * @param boolean $is_disabled indicates whether this field is disabled (meaning, the user can't edit)
 1214+ * @param array $other_args hash representing all the other properties defined for this input in the form definition
 1215+ * @return string html code of input
11801216 */
11811217 static function menuselectHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) {
11821218 global $wgParser, $wgUser, $wgTitle, $wgOut;
Index: trunk/extensions/SemanticFormsInputs/libs/datetimepicker.js
@@ -0,0 +1,37 @@
 2+/**
 3+ * Javascript code to be used with input type datepicker.
 4+ *
 5+ * @author Stephan Gambke
 6+ * @version 0.4 alpha
 7+ *
 8+ */
 9+
 10+
 11+function SFI_DTP_init ( input_id, params ) {
 12+
 13+ var dp = jQuery( "#" + input_id + "_dp_show"); // datepicker element
 14+ var tp = jQuery( "#" + input_id + "_tp_show"); // timepicker element
 15+
 16+ jQuery( "#" + input_id + "_dp_show, #" + input_id + "_tp_show" ).change (function(){
 17+ jQuery( "#" + input_id ).attr("value",
 18+ jQuery.datepicker.formatDate( dp.datepicker("option", "altFormat"), dp.datepicker("getDate"), null ) +
 19+ " " + tp.attr( "value" )
 20+ );
 21+ })
 22+
 23+ if ( params.resetButtonImage ) {
 24+
 25+ if ( params.disabled ) {
 26+ // append inert reset button if image is set
 27+ tp.parent().append('<button type="button" class="ui-datetimepicker-trigger' + params.userClasses + '" disabled><img src="' + params.resetButtonImage + '" alt="..." title="..."></button>');
 28+ } else {
 29+ var resetbutton = jQuery('<button type="button" class="ui-datetimepicker-trigger ' + params.userClasses + '" ><img src="' + params.resetButtonImage + '" alt="..." title="..."></button>');
 30+ tp.parent().append(resetbutton);
 31+ resetbutton.click(function(){
 32+ dp.datepicker( "setDate", null);
 33+ tp.attr( "value", "" );
 34+ jQuery( "#" + input_id ).attr( "value", "" );
 35+ })
 36+ }
 37+ }
 38+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticFormsInputs/libs/datetimepicker.js
___________________________________________________________________
Added: svn:eol-style
139 + native
Index: trunk/extensions/SemanticFormsInputs/libs/datepicker.js
@@ -8,82 +8,113 @@
99
1010 function SFI_DP_init ( input_id, params ) {
1111
12 - var input = jQuery("#" + input_id + "_show");
 12+ var input = jQuery("#" + input_id);
 13+ var re = /\d{4}\/\d{2}\/\d{2}/
1314
14 - input.datepicker( {
15 - "showOn": "both",
16 - "buttonImage": params.buttonImage,
17 - "buttonImageOnly": false,
18 - "changeMonth": true,
19 - "changeYear": true,
20 - "altFormat": "yy/mm/dd",
21 - // Today button does not work (http://dev.jqueryui.com/ticket/4045)
22 - // do not show button panel for now
23 - // TODO: show date picker button panel when bug is fixed
24 - "showButtonPanel": false,
25 - "firstDay": params.firstDay,
26 - "showWeek": params.showWeek,
27 - "dateFormat": params.dateFormat,
28 - "altField": "#" + input_id,
29 - "beforeShowDay": function (date) {return SFI_DP_checkDate("#" + input_id + "_show", date);}
30 - } );
 15+ if ( params.disabled ) {
3116
32 - if ( params.minDate ) {
33 - input.datepicker( "option", "minDate",
34 - jQuery.datepicker.parseDate("yy/mm/dd", params.minDate, null) );
35 - }
 17+ // append inert reset button if image is set
 18+ if ( params.resetButtonImage && ! params.partOfDTP ) {
 19+ input.after('<button type="button" class="ui-datepicker-trigger' + params.userClasses + '" disabled><img src="' + params.resetButtonImage + '" alt="..." title="..."></button>');
 20+ }
3621
37 - if ( params.maxDate ) {
38 - input.datepicker( "option", "maxDate",
39 - jQuery.datepicker.parseDate("yy/mm/dd", params.maxDate, null) );
40 - }
 22+ // append inert datepicker button
 23+ input.after('<button type="button" class="ui-datepicker-trigger' + params.userClasses + '" disabled><img src="' + params.buttonImage + '" alt="..." title="..."></button>');
4124
42 - if ( params.userClass ) {
43 - input.datepicker("widget").addClass( params.userClass );
44 - jQuery("#" + input_id + "_show + button").addClass( params.userClass );
45 - }
 25+ // set value for input fields
 26+ try {
 27+ if ( ! re.test( params.currValue ) ) {
 28+ throw "Wrong date format!";
 29+ }
 30+ input.attr( "value", jQuery.datepicker.formatDate(params.dateFormat, jQuery.datepicker.parseDate( "yy/mm/dd", params.currValue, null ), null ) );
4631
47 - if ( params.disabledDates ) {
 32+ } catch (e) {
 33+ input.attr( "value", params.currValue );
 34+ }
 35+ } else {
4836
49 - var disabledDates = params.disabledDates.map(function(range) {
50 - return [new Date(range[0], range[1], range[2]), new Date(range[3], range[4], range[5])]
51 - });
 37+ // append reset button if image is set
 38+ if ( params.resetButtonImage && ! params.partOfDTP ) {
 39+ var resetbutton = jQuery('<button type="button" class="ui-datepicker-trigger ' + params.userClasses + '" ><img src="' + params.resetButtonImage + '" alt="..." title="..."></button>');
 40+ input.after(resetbutton);
 41+ resetbutton.click(function(){
 42+ input.datepicker( "setDate", null);
 43+ })
 44+ }
5245
53 - input.datepicker("option", "disabledDates", disabledDates);
54 - }
 46+ input.datepicker( {
 47+ "showOn": "both",
 48+ "buttonImage": params.buttonImage,
 49+ "buttonImageOnly": false,
 50+ "changeMonth": true,
 51+ "changeYear": true,
 52+ "altFormat": "yy/mm/dd",
 53+ // Today button does not work (http://dev.jqueryui.com/ticket/4045)
 54+ // do not show button panel for now
 55+ // TODO: show date picker button panel when bug is fixed
 56+ "showButtonPanel": false,
 57+ "firstDay": params.firstDay,
 58+ "showWeek": params.showWeek,
 59+ "dateFormat": params.dateFormat,
 60+ "beforeShowDay": function (date) {return SFI_DP_checkDate("#" + input_id, date);}
 61+ } );
5562
56 - if ( params.highlightedDates ) {
 63+ if ( ! params.partOfDTP ) {
 64+ input.datepicker( "option", "altField", "#" + input_id.replace( "_dp_show", "" ) );
 65+ }
5766
58 - var highlightedDates = params.highlightedDates.map(function(range) {
59 - return [new Date(range[0], range[1], range[2]), new Date(range[3], range[4], range[5])]
60 - });
 67+ if ( params.minDate ) {
 68+ input.datepicker( "option", "minDate",
 69+ jQuery.datepicker.parseDate("yy/mm/dd", params.minDate, null) );
 70+ }
6171
62 - input.datepicker("option", "highlightedDates", highlightedDates);
63 - }
 72+ if ( params.maxDate ) {
 73+ input.datepicker( "option", "maxDate",
 74+ jQuery.datepicker.parseDate("yy/mm/dd", params.maxDate, null) );
 75+ }
6476
65 - if (params.disabledDays) {
66 - input.datepicker("option", "disabledDays", params.disabledDays);
67 - }
 77+ if ( params.userClasses ) {
 78+ input.datepicker("widget").addClass( params.userClasses );
 79+ jQuery("#" + input_id + " + button").addClass( params.userClasses );
 80+ }
6881
69 - if (params.highlightedDays) {
70 - input.datepicker("option", "highlightedDays", params.highlightedDays);
71 - }
 82+ if ( params.disabledDates ) {
7283
73 - //input.datepicker("option", "beforeShowDay", function (date) {return SFI_DP_checkDate("#" + input_id + "_show", date);});
 84+ var disabledDates = params.disabledDates.map(function(range) {
 85+ return [new Date(range[0], range[1], range[2]), new Date(range[3], range[4], range[5])]
 86+ });
7487
75 - try {
 88+ input.datepicker("option", "disabledDates", disabledDates);
 89+ }
7690
77 - var re = /\d{4}\/\d{2}\/\d{2}/
78 - if ( ! re.test( params.currValue ) ) {
79 - throw "Wrong date format!";
 91+ if ( params.highlightedDates ) {
 92+
 93+ var highlightedDates = params.highlightedDates.map(function(range) {
 94+ return [new Date(range[0], range[1], range[2]), new Date(range[3], range[4], range[5])]
 95+ });
 96+
 97+ input.datepicker("option", "highlightedDates", highlightedDates);
8098 }
81 - input.datepicker( "setDate", jQuery.datepicker.parseDate( "yy/mm/dd", params.currValue, null ) );
82 -
83 - } catch (e) {
84 - input.attr( "value", params.currValue );
85 - jQuery( "#" + input_id).attr( "value", params.currValue );
 99+
 100+ if (params.disabledDays) {
 101+ input.datepicker("option", "disabledDays", params.disabledDays);
 102+ }
 103+
 104+ if (params.highlightedDays) {
 105+ input.datepicker("option", "highlightedDays", params.highlightedDays);
 106+ }
 107+
 108+ try {
 109+ if ( ! re.test( params.currValue ) ) {
 110+ throw "Wrong date format!";
 111+ }
 112+ input.datepicker( "setDate", jQuery.datepicker.parseDate( "yy/mm/dd", params.currValue, null ) );
 113+
 114+ } catch (e) {
 115+ input.attr( "value", params.currValue );
 116+ jQuery( "#" + input_id.replace( "_dp_show", "" )).attr( "value", params.currValue );
 117+ }
86118 }
87 -
88119 }
89120
90121 /**
@@ -139,4 +170,3 @@
140171
141172 return [ enable, highlight, "" ];
142173 }
143 -
Index: trunk/extensions/SemanticFormsInputs/libs/timepicker.js
@@ -17,8 +17,10 @@
1818 * format: (String) a format string (unused) (do we even need it?)
1919 *
2020 */
21 -function SFI_TP_init( inputID, params ) { // minTime, maxTime, interval, format
 21+function SFI_TP_init( inputIDshow, params ) { // minTime, maxTime, interval, format
2222
 23+ var inputID = inputIDshow.replace( "_tp_show", "" );
 24+
2325 // sanitize inputs
2426 var re = /^\d+:\d\d$/;
2527 var minh = 0;
@@ -27,7 +29,7 @@
2830 var maxh = 23;
2931 var maxm = 59;
3032
31 -if ( re.test( params.minTime ) ) {
 33+ if ( re.test( params.minTime ) ) {
3234
3335 var min = params.minTime.split( ':', 2 );
3436 minh = Number( min[0] );
@@ -46,12 +48,12 @@
4749 }
4850
4951 var interv = Number( params.interval );
50 -
 52+
5153 if ( interv < 1 ) interv = 1;
5254 else if ( interv > 60 ) interv = 60;
5355
5456 // build html structure
55 - var sp = jQuery( "<span class='SFI_timepicker' id='" + inputID + "_tree' ></span>" ).insertAfter( "#" + inputID );
 57+ var sp = jQuery( "<span class='SFI_timepicker' id='" + inputID + "_tree' ></span>" ).insertBefore( "#" + inputIDshow );
5658
5759 var ulh = jQuery( "<ul>" ).appendTo( sp );
5860
@@ -128,36 +130,50 @@
129131 });
130132
131133 jQuery("#" + inputID + "_tree li") // hours, minutes
132 - .mousedown(function(){
 134+ .mousedown(function(evt){
133135 // set values and leave input
134 - jQuery("#" + inputID + "_show").attr("value", jQuery(this).data("show")).blur();
135 - jQuery("#" + inputID ).attr("value", jQuery(this).data("value"));
 136+ jQuery("#" + inputIDshow ).attr("value", jQuery(this).data("show")).blur().change();
 137+ //jQuery("#" + inputID ).attr("value", jQuery(this).data("value"));
 138+
 139+ // clear any timeout that may still run on this jQuery list item
 140+ clearTimeout(jQuery(evt.currentTarget).data("timeout"));
 141+
 142+ jQuery(evt.currentTarget)
 143+
 144+ // switch classes to change display style
 145+ .removeClass("ui-state-hover")
 146+ .addClass("ui-state-default")
 147+
 148+ // avoid propagation to parent list item (e.g. hours),
 149+ // they would overwrite the input value
136150 return false;
137151 });
138152
139153 // show timepicker when input gets focus
140 - jQuery("#" + inputID + "_show").focus(function() {
 154+ jQuery("#" + inputIDshow ).focus(function() {
141155 jQuery("#" + inputID + "_tree>ul").fadeIn();
142 - });
 156+ });
143157
144158 // hide timepicker when input loses focus
145 - jQuery("#" + inputID + "_show").blur(function() {
146 - jQuery("#" + inputID + "_tree ul").fadeOut();
 159+ jQuery("#" + inputIDshow ).blur(function() {
 160+ jQuery("#" + inputID + "_tree ul").fadeOut("normal", function() {jQuery(this).hide()});
147161 });
148162
149 - jQuery("#" + inputID + "_show").change(function() {
150 - jQuery("#" + inputID ).attr("value", jQuery(this).attr("value"));
151 - });
 163+ if ( ! params.partOfDTP ) {
 164+ jQuery("#" + inputIDshow).change(function() {
 165+ jQuery("#" + inputID ).attr("value", jQuery(this).attr("value"));
 166+ });
 167+ }
152168
153 - jQuery("#" + inputID + '~ button[name="button"]' )
 169+ jQuery("#" + inputID + '_tp_show ~ button[name="button"]' )
154170 .attr("id", inputID + "_button")
155171 .click(function() {
156 - jQuery("#" + inputID + "_show" ).focus();
 172+ jQuery("#" + inputIDshow ).focus();
157173 });
158174
159 - jQuery("#" + inputID + '~ button[name="resetbutton"]' )
 175+ jQuery("#" + inputID + '_tp_show ~ button[name="resetbutton"]' )
160176 .attr("id", inputID + "_resetbutton")
161177 .click(function() {
162 - jQuery("#" + inputID + "_show" ).attr("value", "");
 178+ jQuery("#" + inputIDshow ).attr("value", "");
163179 });
164180 }
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r79525Followup r79522: bugfix for datetimepickerfoxtrott20:39, 3 January 2011
r79587Followup r79522: bugfix, improved datetimepickerfoxtrott18:06, 4 January 2011

Status & tagging log