[Rt-commit] r7461 - in rt/branches/3.7-EXPERIMENTAL: . docs html/Widgets/Form

ruz at bestpractical.com ruz at bestpractical.com
Wed Apr 4 17:53:37 EDT 2007


Author: ruz
Date: Wed Apr  4 17:53:35 2007
New Revision: 7461

Added:
   rt/branches/3.7-EXPERIMENTAL/docs/using_forms_widgets.pod
Modified:
   rt/branches/3.7-EXPERIMENTAL/   (props changed)
   rt/branches/3.7-EXPERIMENTAL/html/Prefs/Other.html
   rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Boolean
   rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Integer
   rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Select

Log:
 r4894 at cubic-pc:  cubic | 2007-04-05 01:38:20 +0400
 * add docs for html/Widgets/Form/*
 * use Default instead of Empty


Added: rt/branches/3.7-EXPERIMENTAL/docs/using_forms_widgets.pod
==============================================================================
--- (empty file)
+++ rt/branches/3.7-EXPERIMENTAL/docs/using_forms_widgets.pod	Wed Apr  4 17:53:35 2007
@@ -0,0 +1,113 @@
+=head1 Using widgets F<html/Widgets/Form*>
+
+This widgets was implemented to address several common issues in handling
+request arguments and allow developers to avoid reinventing the wheel.
+
+=head2 General info
+
+Each component shows widget by default and has two methods: Process and 
+InputOnly. The first one method process arguments and return new value
+of a parametr. The second one is helper that shows only form elements
+with minimum of required text labels.
+
+So you show a widget with:
+    <& /Widgets/Form/Integer,
+        Name => 'NameOfInputElement',
+        Description => 'Input integer',
+    &>
+
+You can show only C<input> box using:
+    <& /Widgets/Form/Integer:InputOnly,
+        Name => 'NameOfInputElement',
+    &>
+
+In such a simple case you even can avoid processing. Yeah, most probably
+you want to check if value is really integer, but these widgets don't
+do validation for you, but they are more about fetching values from
+hash of arguments, showing these values to user and preserving state
+of value between form reloads (see below).
+
+=head2 Processing
+
+Processing is required when you use L<extended features|/Extendent features>,
+such as Default, Multiple or Alternative.
+
+To process arguments of a request you have to do the following:
+    $ARGS{'NameOfInputElement'} = $m->comp(
+        '/Widgets/Form/Integer:Process',
+        Arguments => \%ARGS,
+        Name      => 'NameOfInputElement',
+    );
+
+The method returns processed value in canonical form. For different widgets
+a canonical form is different and depends on activated features, so you must
+always activate the same features during showing a widget and processing
+results.
+
+=head2 Extendent features
+
+=head3 Default value
+
+If C<Default> argument is true then widgets expect that there is some
+default value for argument if user fills nothing. 'Nothing' in each
+widget is different, for example in select box it's special option
+which is always the first one, in integer box string '' means empty
+value, but boolean box uses radio buttons in this case with three
+options: Yes, No and Default.
+
+Each widget that supports C<Default> feature as well has C<DefaultLabel> and
+C<DefaultValue> arguments.
+
+=head4 Processing and showing with activated Default feature
+
+When this option is activated then C<Process> method returns undef
+value if user selected default value. So for integer box it's empty
+string and so on.
+
+As well when you show a widget you should pass undef as C<CurrentValue>
+to inform widget that the current value is default one.
+
+As all methods of a widget are consistent in this behaviour so you
+shouldn't care much about that, but this allows you to implement
+custom actions if processing returned undef, for example delete user's
+preference record instead of updating it (default value may change later to).
+
+=head4 C<DefaultValue> when C<Default> is not active
+
+DefaultValue argument is still actual in the Process method even if
+C<Default> is not true. This argument defines intial value. If value
+of a key in Arguments is not defined then it's treated as intial state
+and the method returns default value.
+
+=head3 Multiple and Alternative
+
+These options are only supported by the select widget.
+
+TODO: Add more info
+
+=head2 Implementation details
+
+=head3 Boolean widget
+
+This widget a little bit tricky. When you use Default option then
+things are simple and you see three radio buttons, but in other
+case we use a checkbox. But as you know browsers don't pass unchecked
+boxes to server, so arguments of a request has no entry for them.
+
+In the latter case it's hard to figure out case when user unselected
+value. Imagine form with a checkbox, you want show it checked by
+default and as well form is reloadable (like Reply forms that have
+"Add Another File" buttons). User uncheck the box and then upload
+file, in this case you want to show user's choice instead of default,
+but browser doesn't send any value and you can not figure out if
+it's initial state or page reload. To solve this problem we use magic
+hidden input field with the same name as the box and value equal to
+zero (0). Mason folds arguments with the same name into array refs, so
+we get 0 if box is unchecked and [0, 1] if box is checked. An array
+reference is true value and 0 is defined value so we know that it's
+not initial state and avoid switching back to default. As well this
+trick works good in a case when you want show a link to a page and
+define default choice for some boolean argument, you don't need
+to set argument twice, you just set it to true value (for ex. 1) and
+things just work.
+

Modified: rt/branches/3.7-EXPERIMENTAL/html/Prefs/Other.html
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Prefs/Other.html	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Prefs/Other.html	Wed Apr  4 17:53:35 2007
@@ -11,10 +11,10 @@
 % foreach my $option( RT->Config->Options( Section => $section ) ) {
 % my $meta = RT->Config->Meta( $option );
 <& $meta->{'Widget'},
-    Empty        => 1,
+    Default      => 1,
     %{ $localize_meta->( $meta->{'WidgetArguments'} ) },
     Name         => $option,
-    EmptyValue   => scalar RT->Config->Get( $option ),
+    DefaultValue => scalar RT->Config->Get( $option ),
     CurrentValue => $preferences->{ $option },
 &>
 % }
@@ -35,7 +35,7 @@
         my $meta = RT->Config->Meta( $option );
         my $value = $m->comp($meta->{'Widget'} .":Process",
             Arguments    => \%ARGS,
-            Empty        => 1,
+            Default      => 1,
             %{ $meta->{'WidgetArguments'} },
             Name         => $option,
             DefaultValue => scalar RT->Config->Get( $option ),

Modified: rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Boolean
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Boolean	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Boolean	Wed Apr  4 17:53:35 2007
@@ -1,3 +1,6 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
 <div id="form-box-<% lc $Name %>">
 <span class="description"><% $Description %></span>:\
 <& SELF:InputOnly, %ARGS &>
@@ -11,13 +14,13 @@
 <%ARGS>
 $Name         => undef,
 
-$Empty        => 0,
-$EmptyValue   => 0,
-$EmptyLabel   => loc( 'System default ([_1])', $EmptyValue? loc('Yes'): loc('No') ),
+$Default        => 0,
+$DefaultValue   => 0,
+$DefaultLabel   => loc( 'Use system default ([_1])', $DefaultValue? loc('Yes'): loc('No') ),
 
 $CurrentValue => undef,
 </%ARGS>
-% unless ( $Empty ) {
+% unless ( $Default ) {
 <input type="hidden" name="<% $Name %>" value="0" />\
 <input type="checkbox" name="<% $Name %>" <% $CurrentValue? 'checked="checked"': '' %> />\
 % } else {
@@ -26,21 +29,21 @@
 <input type="radio" name="<% $Name %>" value="0" <% defined $CurrentValue && !$CurrentValue? 'checked="checked"': '' %> />\
 <% loc('No') %>
 <input type="radio" name="<% $Name %>" value="__empty_value__" <% !defined $CurrentValue? 'checked="checked"': '' %> />\
-<% $EmptyLabel %>
+<% $DefaultLabel %>
 % }
 </%METHOD>
 
 <%METHOD Process>
 <%ARGS>
+$Name
 $Arguments    => {},
 
-$Name         => undef,
-$Empty        => 0,
+$Default      => 0,
 $DefaultValue => 0,
 </%ARGS>
 <%INIT>
 my $value = $Arguments->{ $Name };
-if ( $Empty ) {
+if ( $Default ) {
     return undef if !defined $value || $value eq '__empty_value__';
     return $value? 1: 0;
 } else {

Modified: rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Integer
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Integer	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Integer	Wed Apr  4 17:53:35 2007
@@ -1,8 +1,11 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
 <div id="form-box-<% lc $Name %>">
 <span class="description"><% $Description %></span>:\
 <& SELF:InputOnly, %ARGS &>
-% if ( $Empty ) {
-<span class="comment"><% $EmptyLabel %></span>
+% if ( $Default ) {
+<span class="comment"><% $DefaultLabel %></span>
 % }
 </div>
 <%INIT>
@@ -14,9 +17,9 @@
 
 $CurrentValue => '',
 
-$Empty        => 0,
-$EmptyValue   => 0,
-$EmptyLabel   => loc( 'Leaving this empty will default to the system default of [_1]', $EmptyValue ),
+$Default        => 0,
+$DefaultValue   => 0,
+$DefaultLabel   => loc( 'Leaving this empty will default to the system default of [_1]', $DefaultValue ),
 </%ARGS>
 
 <%METHOD InputOnly>
@@ -33,13 +36,13 @@
 
 $Arguments    => {},
 
+$Default      => 0,
 $DefaultValue => '',
-$Empty        => 0,
 </%ARGS>
 <%INIT>
 my $value = $Arguments->{ $Name };
 if ( !defined $value || $value eq '' ) {
-    return $DefaultValue unless $Empty;
+    return $DefaultValue unless $Default;
     return undef;
 }
 return $value;

Modified: rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Select
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Select	(original)
+++ rt/branches/3.7-EXPERIMENTAL/html/Widgets/Form/Select	Wed Apr  4 17:53:35 2007
@@ -1,3 +1,6 @@
+<%DOC>
+see docs/using_forms_widgets.pod
+</%DOC>
 <div id="form-box-<% lc $Name %>">
 % if ( $Description ) {
 <% $Description %>:\
@@ -19,9 +22,9 @@
 %ValuesLabel      => (),
 @CurrentValue     => (),
 
-$Empty            => 1,
- at EmptyValue       => (),
-$EmptyLabel       => loc('Use system default ([_1])', join ', ', @EmptyValue),
+$Default            => 1,
+ at DefaultValue       => (),
+$DefaultLabel       => loc('Use system default ([_1])', join ', ', @DefaultValue),
 
 $Alternative      => 0,
 $AlternativeLabel => loc('other...'),
@@ -30,10 +33,10 @@
 </%ARGS>
 <select name="<% $Name %>">
 
-% if ( $Empty ) {
+% if ( $Default ) {
 % my $selected = '';
 % $selected = 'selected="selected"' unless @CurrentValue;
-<option value="__empty_value__" <% $selected |n %>><% $EmptyLabel %></option>
+<option value="__empty_value__" <% $selected |n %>><% $DefaultLabel %></option>
 % }
 
 % foreach my $v( @Values ) {
@@ -78,16 +81,17 @@
 
 @Values           => (),
 %ValuesLabel      => (),
+
+$Default          => 0,
 @DefaultValue     => (),
 
-$Empty            => 1,
 $Alternative      => 0,
 $Multiple         => 0,
 </%ARGS>
 <%INIT>
 my $value = $Arguments->{ $Name };
 if( !defined $value || $value eq '__empty_value__' ) {
-    return undef if $Empty;
+    return undef if $Default;
     return [ @DefaultValue ] if $Multiple;
     return $DefaultValue[0];
 }


More information about the Rt-commit mailing list