[interchange-cvs] interchange - heins modified lib/Vend/Table/Editor.pm

interchange-core@icdevgroup.org interchange-core@icdevgroup.org
Mon Sep 23 13:58:01 2002


User:      heins
Date:      2002-09-23 17:57:18 GMT
Modified:  lib/Vend/Table Editor.pm
Log:
* Last preps for complete templatabililty.

	-- Now can set all styles for rows and cells in metadata.
	-- Titles are handled transparently for tabbed and non-tabbed displays.
	-- Can template the different types of rows:

		row_template   --> The normal data row
		combo_template --> The row that is used for user inputted widgets
		break_template --> The row for titles

    -- Fixed quite a few bugs in row formatting
	-- Old row_template styles should be transparently converted to the
	   new tag_attr_list style

  Next stop -- overall_template.

  	{FORM_INTRO}
	<table>
	<tr>
		<td colspan=3D2>
		{TOP_BUTTONS}
		</td>
	</tr>
	<tr>
		{COLUMN_SKU}
		{COLUMN_PRICE}
	</tr>
	{REST}
	<tr>
		<td colspan=3D2>
		{BOTTOM_BUTTONS}
		</td>
	</tr>
	</table>
	{FORM_END}

Revision  Changes    Path
1.4       +307 -166  interchange/lib/Vend/Table/Editor.pm


rev 1.4, prev_rev 1.3
Index: Editor.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/interchange/lib/Vend/Table/Editor.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Editor.pm	20 Sep 2002 16:57:15 -0000	1.3
+++ Editor.pm	23 Sep 2002 17:57:18 -0000	1.4
@@ -1,6 +1,6 @@
 # Vend::Table::Editor - Swiss-army-knife table editor for Interchange
 #
-# $Id: Editor.pm,v 1.3 2002/09/20 16:57:15 mheins Exp $
+# $Id: Editor.pm,v 1.4 2002/09/23 17:57:18 mheins Exp $
 #
 # Copyright (C) 2002 ICDEVGROUP <interchange@icdevgroup.org>
 # Copyright (C) 2002 Mike Heins <mike@perusion.net>
@@ -26,7 +26,7 @@
 package Vend::Table::Editor;
=20
 use vars qw($VERSION);
-$VERSION =3D substr(q$Revision: 1.3 $, 10);
+$VERSION =3D substr(q$Revision: 1.4 $, 10);
=20
 use Vend::Util;
 use Vend::Interpolate;
@@ -429,10 +429,6 @@
 		}
 	}
=20
-#::logDebug("widget=3D$w");
-	# don't output label if widget is hidden form variable only
-	return $w if $w =3D~ /^\s*<input\s[^>]*type\s*=3D\W*hidden\b[^>]*>\s*$/i;
-
 	if(! defined $w) {
 		my $text =3D $opt->{value};
 		my $iname =3D $opt->{name} || $column;
@@ -464,7 +460,13 @@
=20
 	my $array_return =3D wantarray;
=20
-	return $w unless $template || $array_return;
+#::logDebug("widget=3D$w");
+
+	# don't output label if widget is hidden form variable only
+	# and not an array type
+	undef $template if $w =3D~ /^\s*<input\s[^>]*type\s*=3D\W*hidden\b[^>]*>\=
s*$/i;
+
+	return $w unless $template || $opt->{return_hash} || $array_return;
=20
 	if($template and $template !~ /\s/) {
 		$template =3D <<'EOF';
@@ -495,7 +497,12 @@
 #::logDebug("passed meta_url=3D$opt->{meta_url}");
       $sub{HELP_EITHER} =3D $sub{HELP} || $sub{HELP_URL};
=20
-	if($array_return) {
+	if($opt->{return_hash}) {
+		$sub{OPT} =3D $opt;
+		$sub{RECORD} =3D $record;
+		return \%sub;
+	}
+	elsif($array_return) {
 		return ($w, $sub{LABEL}, $sub{HELP}, $record->{help_url});
 	}
 	else {
@@ -877,6 +884,7 @@
 	%outhash =3D ();
 	%alias =3D ();
 	$tcount_all =3D 0;
+	$ctl_index =3D 0;
 }
=20
 my %o_default_length =3D (
@@ -891,6 +899,15 @@
 my %o_default_defined =3D (
 	mv_update_empty		=3D> 1,
 	restrict_allow		=3D> 'page area',
+	widget_cell_class	=3D> 'cwidget',
+	label_cell_class	=3D> 'clabel',
+	data_cell_class	=3D> 'cdata',
+	help_cell_class	=3D> 'chelp',
+	break_cell_class	=3D> 'cbreak',
+	spacer_row_class =3D> 'rspacer',
+	break_row_class =3D> 'rbreak',
+	title_row_class =3D> 'rmarq',
+	data_row_class =3D> 'rnorm',
 );
=20
 my %o_default =3D (
@@ -906,9 +923,29 @@
=20
 # Build maps for ui_te_* option pass
 my @cgi_opts =3D qw/
-        append check database default extra field filter height help
-        help_url lookup options outboard override passed pre_filter
-        prepend widget width
+
+	append
+	check
+	database
+	default
+	extra
+	field
+	filter
+	height
+	help
+	help_url
+	label
+	lookup
+	options
+	outboard
+	override
+	passed
+	pre_filter
+	prepend
+	template
+	widget
+	width
+
 /;
=20
 my @hmap;
@@ -959,27 +996,28 @@
 		no strict 'refs';
 		my $ref;
 		for(qw/
-					default=20=20=20=20=20
-					error=20=20=20=20=20=20=20
-					extra=20=20=20=20=20=20=20
-					filter=20=20=20=20=20=20
-					height=20=20=20=20=20=20
-					help=20=20=20=20=20=20=20=20
-					label=20=20=20=20=20=20=20
-					override=20=20=20=20
-					passed=20=20=20=20=20=20
-					options=20=20=20=20=20=20
-					outboard
-					append
-					prepend
-					lookup
-					lookup_query
-					field
-					pre_filter=20=20
-					left_width
-					widget=20=20=20=20=20=20
-					width=20=20=20=20=20=20=20
-					meta=20=20=20=20=20=20=20
+                    append
+                    default
+					database
+                    error
+                    extra
+                    field
+                    filter
+                    height
+                    help
+                    label
+                    lookup
+                    lookup_query
+                    meta
+                    options
+                    outboard
+                    override
+                    passed
+                    pre_filter
+                    prepend
+                    template
+                    widget
+                    width
 				/ )
 		{
 			next if ref $opt->{$_};
@@ -1003,6 +1041,24 @@
 		mv_blob_pointer
 		mv_blob_label
 		mv_blob_title
+		widget_cell_class
+		label_cell_class
+		data_cell_class
+		help_cell_class
+		break_cell_class
+		spacer_row_class
+		break_row_class
+		title_row_class
+		data_row_class
+		widget_cell_style
+		label_cell_style
+		data_cell_style
+		help_cell_style
+		break_cell_style
+		spacer_row_style
+		break_row_style
+		title_row_style
+		data_row_style
 		left_width
 		table_width
 		tabbed
@@ -1120,6 +1176,44 @@
 		$opt->{$k} ||=3D $v;
 	}
=20
+	# init the row styles
+	foreach my $rtype (qw/data break combo spacer/) {
+		my $mainp =3D $rtype . '_row_extra';
+		my $thing =3D '';
+		for my $ptype (qw/class style align valign width/) {
+			my $parm =3D $rtype . '_row_' . $ptype;
+			$opt->{$parm} ||=3D $tmeta->{$parm};
+			if(defined $opt->{$parm}) {
+				$thing .=3D qq{ $ptype=3D"$opt->{$parm}"};
+			}
+		}
+		$opt->{$mainp} ||=3D $tmeta->{$mainp};
+		if($opt->{$mainp}) {
+			$thing .=3D " " . $opt->{$mainp};
+		}
+		$opt->{$mainp} =3D $thing;
+	}
+
+	# Init the cell styles
+
+	for my $ctype (qw/label data widget help break/) {
+		my $mainp =3D $ctype . '_cell_extra';
+		my $thing =3D '';
+		for my $ptype (qw/class style align valign width/) {
+			my $parm =3D $ctype . '_cell_' . $ptype;
+			$opt->{$parm} ||=3D $tmeta->{$parm};
+			if(defined $opt->{$parm}) {
+				$thing .=3D qq{ $ptype=3D"$opt->{$parm}"};
+			}
+		}
+		$opt->{$mainp} ||=3D $tmeta->{$mainp};
+		if($opt->{$mainp}) {
+			$thing .=3D " " . $opt->{$mainp};
+		}
+		$opt->{$mainp} =3D $thing;
+	}
+
+
 	###############################################################
 	# Get the field display information including breaks and labels
 	###############################################################
@@ -1178,7 +1272,7 @@
 # UserTag table-editor MapRoutine Vend::Table::Editor::editor
 sub editor {
=20
-	my ($table, $key, $opt, $template) =3D @_;
+	my ($table, $key, $opt, $overall_template) =3D @_;
 show_times("begin table editor call item_id=3D$key") if $Global::ShowTimes;
=20
 	use vars qw/$Tag/;
@@ -1199,13 +1293,13 @@
 	$key =3D $opt->{item_id};
 #::logDebug("key after resolve_options: $key");
=20
-	my $rowdiv =3D $opt->{across} || 1;
+	my $rowdiv         =3D $opt->{across}    || 1;
+	my $cells_per_span =3D $opt->{cell_span} || 2;
 	my $rowcount =3D 0;
-	my $span =3D $rowdiv * 2;
+	my $span =3D $rowdiv * $cells_per_span;
 	my $oddspan =3D $span - 1;
 	my $def =3D $opt->{default_ref} || $::Values;
=20
-
 	my $append       =3D $opt->{append};
 	my $check        =3D $opt->{check};
 	my $database     =3D $opt->{database};
@@ -1227,13 +1321,14 @@
 	my $passed       =3D $opt->{passed};
 	my $pre_filter   =3D $opt->{pre_filter};
 	my $prepend      =3D $opt->{prepend};
+	my $template     =3D $opt->{template};
 	my $widget       =3D $opt->{widget};
 	my $width        =3D $opt->{width};
=20
 	#my $blabel      =3D $opt->{begin_label} || '<b>';
 	#my $elabel      =3D $opt->{end_label} || '</b>';
-	my $blabel      ;
-	my $elabel      ;
+	my $blabel =3D $opt->{blabel};
+	my $elabel =3D $opt->{elabel};
 	my $mlabel =3D '';
=20
 	my $ntext;
@@ -1384,8 +1479,8 @@
 EOP
 [/perl]
 EOF
-		$blabel =3D '<span style=3D"font-weight: normal">';
-		$elabel =3D '</span>';
+		$opt->{blabel} =3D '<span style=3D"font-weight: normal">';
+		$opt->{elabel} =3D '</span>';
 		$mlabel =3D ($opt->{message_label} || '&nbsp;&nbsp;&nbsp;<B>Bold</B> fie=
lds are required');
 		$have_errors =3D $Tag->error( {
 									all =3D> 1,
@@ -1709,7 +1804,7 @@
=20
 	no strict 'subs';
=20
-	chunk 'FORM_BEGIN', 'WO', 'TOP_PORTION', <<EOF; # unless $wo;
+	chunk 'FORM_BEGIN', 'WO', 'TOP_OF_FORM', <<EOF; # unless $wo;
 $restrict_begin<FORM METHOD=3D$opt->{method} ACTION=3D"$opt->{href}"$opt->=
{form_name}$opt->{enctype}$opt->{form_extra}>
 $sidstr<INPUT TYPE=3Dhidden NAME=3Dmv_todo VALUE=3D"$opt->{action}">
 <INPUT TYPE=3Dhidden NAME=3Dmv_click VALUE=3D"process_filter">
@@ -1747,7 +1842,7 @@
 		$val =3D~ s/"/&quot;/g;
 		push @o, qq{<INPUT TYPE=3Dhidden NAME=3D$_ VALUE=3D"$val">\n}; # unless =
$wo;
 	}
-	chunk 'HIDDEN_OPT', '', 'TOP_PORTION', join("", @o);
+	chunk 'HIDDEN_OPT', '', 'TOP_OF_FORM', join("", @o);
   }
=20
   CGISET: {
@@ -1758,7 +1853,7 @@
 		$val =3D~ s/"/&quot;/g;
 		push @o, qq{<INPUT TYPE=3Dhidden NAME=3D$_ VALUE=3D"$val">\n}; # unless =
$wo;
 	}
-	chunk 'HIDDEN_CGI', join("", @o);
+	chunk 'HIDDEN_CGI', '', 'TOP_OF_FORM', join("", @o);
   }
=20
 	if($opt->{mailto}) {
@@ -1780,7 +1875,7 @@
 		elsif ($CGI::values{ui_return_to}) {
 			@$r_ary =3D ( $CGI::values{ui_return_to} );=20
 		}
-		chunk 'RETURN_TO', 'WO', $Tag->return_to(); # unless $wo;
+		chunk 'RETURN_TO', '', 'TOP_OF_FORM', $Tag->return_to(); # unless $wo;
 #::logDebug("return-to stack =3D " . ::uneval($r_ary));
 	}
=20
@@ -1817,17 +1912,16 @@
 						|| $mlabel;
 	if ($extra_ok and ! $opt->{no_top} and ! $opt->{nosave}) {
 	  	if($opt->{back_text}) {
-		  chunk ttag(), 'WO', <<EOF; # unless $wo;
+		  chunk ttag(), '', <<EOF; # unless $wo;
 <TR class=3Drnorm>
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
-			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS', <<EOF; # if ! $opt->{bott=
om_buttons};
+			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS', 'TOP_BUTTONS', <<EOF; # i=
f ! $opt->{bottom_buttons};
 <INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{back_text}">&nbsp;<IN=
PUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{cancel_text}">&nbsp;<B><I=
NPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{next_text}"></B>
 <BR>
 EOF
-			chunk 'MLABEL', 'WO', $mlabel;
-			chunk_alias 'MLABEL', 'FORM_TOP';
+			chunk 'MLABEL', '', 'MESSAGES', $mlabel;
 			chunk ttag(), <<EOF;
 </TD>
 </TR>
@@ -1843,11 +1937,11 @@
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
-			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS', <<EOF; # if ! $opt->{bott=
om_buttons};
+			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS NO_TOP', 'TOP_BUTTONS', <<E=
OF; # if ! $opt->{bottom_buttons};
 <INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{cancel_text}">&nbsp;<=
B><INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{next_text}"></B>
 <BR>
 EOF
-			chunk 'MLABEL', 'BOTTOM_BUTTONS', $mlabel;
+			chunk 'MLABEL', 'BOTTOM_BUTTONS', 'MESSAGES', $mlabel;
 			chunk ttag(), <<EOF;
 </TD>
 </TR>
@@ -1858,7 +1952,7 @@
 EOF
 		}
 		else {
-		  chunk ttag(), 'BOTTOM_BUTTONS', <<EOF;
+		  chunk ttag(), 'BOTTOM_BUTTONS NO_TOP', <<EOF;
 <TR class=3Drnorm>
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
@@ -1867,21 +1961,25 @@
 		  $opt->{ok_button_style} =3D 'font-weight: bold; width: 40px; text-alig=
n: center'
 		  	unless defined $opt->{ok_button_style};
=20=09=09=20=20=09
-		  chunk 'OK_TOP', 'BOTTOM_BUTTONS', <<EOF;
+		  chunk 'OK_TOP', 'NO_TOP', 'TOP_BUTTONS', <<EOF;
 <INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{next_text}" style=3D"=
$opt->{ok_button_style}">
 EOF
-		  chunk ttag(), 'NOCANCEL BOTTOM_BUTTONS', <<EOF; # unless $opt->{nocanc=
el};
+		  chunk ttag(), 'NOCANCEL BOTTOM_BUTTONS NO_TOP', 'TOP_BUTTONS', <<EOF;
 &nbsp;
 <INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{cancel_text}" style=
=3D"$opt->{cancel_button_style}">
 EOF
=20
-		  chunk 'RESET_TOP', '_SHOW_RESET BOTTOM_BUTTONS', <<EOF;
+		  chunk
+		  	'RESET_TOP',
+			'_SHOW_RESET BOTTOM_BUTTONS NO_TOP',
+			'TOP_BUTTONS',
+			<<EOF;
 &nbsp;
 <INPUT TYPE=3Dreset>
 EOF
=20
-			chunk 'MLABEL', 'BOTTOM_BUTTONS', $mlabel;
-			chunk ttag(), 'BOTTOM_BUTTONS', , <<EOF;
+			chunk 'MLABEL', 'BOTTOM_BUTTONS', 'MESSAGES', $mlabel;
+			chunk ttag(), 'BOTTOM_BUTTONS NO_TOP', <<EOF;
 </TD>
 </TR>
=20
@@ -2107,33 +2205,8 @@
 	my @data_enable =3D ($opt->{mv_blob_pointer}, $opt->{mv_blob_field});
 	my @ext_enable;
=20
-	# Init the cell stuff
-	my %td_extra;
-	my %td_default =3D (
-			widget_cell_class	=3D> 'cwidget',
-			label_cell_class	=3D> 'clabel',
-			data_cell_class	=3D> 'cdata',
-			help_cell_class	=3D> 'chelp',
-	);
-
-	for my $ctype (qw/label data widget help/) {
-		$td_extra{$ctype} =3D '';
-		for my $ptype (qw/class style align valign width/) {
-			my $parm =3D $ctype . '_cell_' . $ptype;
-			if(defined $opt->{$parm}) {
-				$td_extra{$ctype} .=3D qq{ $ptype=3D"$opt->{$parm}"};
-			}
-			elsif ($td_default{$parm}) {
-				$td_extra{$ctype} .=3D qq{ $ptype=3D"$td_default{$parm}"};
-			}
-		}
-		if(my $thing =3D $opt->{$ctype . "_cell_extra"}) {
-			$td_extra{$ctype} .=3D " $thing";
-		}
-	}
-
 	if($opt->{left_width} and ! $opt->{label_cell_width}) {
-		$td_extra{label} .=3D qq{ width=3D"$opt->{left_width}"};
+		$opt->{label_cell_extra} .=3D qq{ width=3D"$opt->{left_width}"};
 	}
=20
 	my $show_meta;
@@ -2166,31 +2239,31 @@
 			if $opt->{meta_style};
 	}
=20
- 	my $row_template =3D $opt->{row_template};
+ 	my $row_template =3D convert_old_template($opt->{row_template});
=20=09
 	if(! $row_template) {
 		if($opt->{simple_row}) {
 			$opt->{help_anchor} ||=3D 'help';
 			$row_template =3D <<EOF;
-   <td$td_extra{label}>=20
-     $blabel\$LABEL\$$elabel
+   <td$opt->{label_cell_extra}>=20
+     {BLABEL}{LABEL}{ELABEL}
    </td>
-   <td$td_extra{widget}>\$WIDGET\${HELP_EITHER}&nbsp;<a href=3D"\$HELP_URL=
\$" title=3D"\$HELP\$">$opt->{help_anchor}</a>{/HELP_EITHER}&nbsp;{META_URL=
}<A HREF=3D"\$META_URL\$">$opt->{meta_anchor}</A>{/META_URL}
+   <td$opt->{data_cell_extra}>{WIDGET}{HELP_EITHER}&nbsp;<a href=3D"{HELP_=
URL}" title=3D"{HELP\$">$opt->{help_anchor}</a>{/HELP_EITHER?}&nbsp;{META_U=
RL?}<A HREF=3D"{META_URL}">$opt->{meta_anchor}</A>{/META_URL?}
    </td>
 EOF
 		}
 		else {
 			$row_template =3D <<EOF;
-   <td$td_extra{label}>=20
-     $blabel\$LABEL\$$elabel~META~
+   <td$opt->{label_cell_extra}>=20
+     {BLABEL}{LABEL}{ELABEL}{META_STRING}
    </td>
-   <td$td_extra{data}>
+   <td$opt->{data_cell_extra}>
      <table cellspacing=3D0 cellmargin=3D0 width=3D"100%">
        <tr>=20
-         <td$td_extra{widget}>
-           \$WIDGET\$
+         <td$opt->{widget_cell_extra}>
+           {WIDGET}
          </td>
-         <td$td_extra{help}>~TKEY~<i>\$HELP\$</i>{HELP_URL}<BR><A HREF=3D"=
\$HELP_URL\$">help</A>{/HELP_URL}</FONT></td>
+         <td$opt->{help_cell_extra}>{TKEY}{HELP?}<i>{HELP}</i>{/HELP?}{HEL=
P_URL?}<BR><A HREF=3D"{HELP_URL}">help</A>{/HELP_URL?}</FONT></td>
        </tr>
      </table>
    </td>
@@ -2199,9 +2272,15 @@
 	}
=20
 	$row_template =3D~ s/~OPT:(\w+)~/$opt->{$1}/g;
-	$row_template =3D~ s/~BLABEL~/$blabel/g;
-	$row_template =3D~ s/~ELABEL~/$elabel/g;
-	$row_template =3D~ s/~([A-Z]+)_EXTRA~/$td_extra{lc $1}/g;
+	$row_template =3D~ s/~([A-Z]+)_EXTRA~/$opt->{"\L$1\E_extra"} || $opt->{"\=
L$1\E_cell_extra"}/g;
+
+	$opt->{combo_template} ||=3D <<EOF;
+<tr$opt->{combo_row_extra}><td colspan=3D$span>{ROW}</td></tr>
+EOF
+
+	$opt->{break_template} ||=3D <<EOF;
+<tr$opt->{break_row_extra}><td colspan=3D$span $opt->{break_cell_extra}>{R=
OW}</td></tr>
+EOF
=20
 	my %serialize;
 	my %serial_data;
@@ -2270,7 +2349,8 @@
=20
 			$ll ||=3D errmsg("Settings in table %s linked by %s", $lt, $lk);
=20
-			my $tpl =3D $row_template;
+			my $whash =3D {};
+
 			my $ldb =3D database_exists_ref($lt)
 				or do {
 					logError("Bad table editor link table: %s", $lt);
@@ -2287,16 +2367,14 @@
 			$lf =3D join " ", @cf;
 			my $lextra =3D $opt->{link_extra} || '';
 			$lextra =3D " $lextra" if $lextra;
-			my $labside =3D <<EOF;
+
+			my @lout =3D q{<table cellspacing=3D0 cellpadding=3D1>};
+			push @lout, qq{<tr><td$lextra>
 <input type=3Dhidden name=3D"mv_data_table__$tcount" value=3D"$lt">
 <input type=3Dhidden name=3D"mv_data_fields__$tcount" value=3D"$lf">
 <input type=3Dhidden name=3D"mv_data_multiple__$tcount" value=3D"1">
 <input type=3Dhidden name=3D"mv_data_key__$tcount" value=3D"$l_pkey">
-$ll
-EOF
-
-			my @lout =3D q{<table cellspacing=3D0 cellpadding=3D1>};
-			push @lout, qq{<tr><td$lextra>$l_pkey</td>};
+$l_pkey</td>};
 			push @lout, $Tag->row_edit({ table =3D> $lt, columns =3D> $lf });
 			push @lout, '</tr>';
=20
@@ -2341,25 +2419,24 @@
 			push @lout, $Tag->row_edit(\%o);
 			push @lout, '</tr>';
 			push @lout, "</table>";
-			$tpl =3D~ s{\$LABEL\$}{$labside}g;
-			$tpl =3D~ s{\$WIDGET\$}{join "", @lout}ge;
+			$whash->{LABEL}  =3D $ll;
+			$whash->{WIDGET} =3D join "", @lout;
 			my $murl =3D '';
 			if($show_meta) {
-				$murl =3D $Tag->page({
+				my $murl;
+				$murl =3D $Tag->area({
 							href =3D> 'admin/db_metaconfig_spread',
 							form =3D> qq(
 									ui_table=3D$lt
 									ui_view=3D$lv
 								),
 							});
-				$murl .=3D errmsg('meta');
-				$murl .=3D '</a>';
+				$whash->{META_URL} =3D $murl;
+				$whash->{META_STRING} =3D qq{<a href=3D"$murl"$opt->{meta_extra}>};
+				$whash->{META_STRING} .=3D errmsg('meta') . '</a>';
+
 			}
-			$tpl =3D~ s{\~META\~}{$murl}g;
-			$tpl =3D~ s{\$HELP\$}{}g;
-			$tpl =3D~ s{\~TKEY\~}{}g;
-			$tpl =3D~ s!{HELP_URL}.*?{/HELP_URL}!!gs;
-			$link_row{$lt} =3D $tpl;
+			$link_row{$lt} =3D $whash;
 			if($lb) {
 				$link_before{$lb} =3D $lt;
 			}
@@ -2380,9 +2457,16 @@
         chunk ttag(), qq{<tr><td colspan=3D$span$extra>\n};
     }
=20
+	my @extra_hidden;
+	my $icount =3D 0;
 	foreach my $col (@cols) {
 		if($link_before{$col}) {
-			col_chunk "SPREAD_$link_before{$col}", delete $link_row{$link_before{$c=
ol}};
+			my $h =3D { ROW =3D> delete $link_row{$link_before{$col}} };
+			col_chunk "_SPREAD_$link_before{$col}", $h;
+		}
+		if($opt->{include_before} and $opt->{include_before}{$col}) {
+			my $h =3D { ROW =3D> $opt->{include_before}{$col} };
+			col_chunk "_INCLUDE_$link_before{$col}", $h;
 		}
 		my $t;
 		my $c;
@@ -2391,9 +2475,8 @@
 		if($col eq $keycol) {
 			if($opt->{ui_hide_key}) {
 				my $kval =3D $key || $override->{$col} || $default->{$col};
-				col_chunk $col, <<EOF;
-	<INPUT TYPE=3Dhidden NAME=3D"$col" VALUE=3D"$kval">
-EOF
+				push @extra_hidden,
+					qq{<INPUT TYPE=3Dhidden NAME=3D"$col" VALUE=3D"$kval">};
 				next;
 			}
 			elsif ($opt->{ui_new_item}) {
@@ -2504,7 +2587,9 @@
 			$currval =3D $default->{$c};
 		}
=20
-		my $template =3D $row_template;
+		$template->{$c} ||=3D $row_template;
+
+		my $err_string;
 		if($error->{$c}) {
 			my $parm =3D {
 					name =3D> $c,
@@ -2518,7 +2603,12 @@
 [else]{REQUIRED <B>}{LABEL}{REQUIRED </B>}[/else]
 EOF
 			}
-			$template =3D~ s/\$LABEL\$/$Tag->error($parm)/eg;
+			$err_string =3D $Tag->error($parm);
+			if($template->{$c} !~ /{ERROR\??}/) {
+				$template->{$c} =3D~ s/{LABEL}/$err_string/g
+					and
+				$template->{$c} =3D~ s/\$LABEL\$/{LABEL}/g;
+			}
 		}
=20
 		my $meta_string =3D '';
@@ -2571,7 +2661,6 @@
 EOF
 		}
=20
-		$template =3D~ s/~TKEY~/$tkey_message || ''/eg;
 #::logDebug("col=3D$c currval=3D$currval widget=3D$widget->{$c} label=3D$l=
abel->{$c} (type=3D$type)");
 		my $display =3D display($t, $c, $key, {
 										applylocale =3D> 1,
@@ -2604,53 +2693,44 @@
 										table =3D> $t,
 										type =3D> $widget->{$c} || $type,
 										width =3D> $width->{$c},
-										template =3D> $template,
+										return_hash =3D> 1,
 									});
 #::logDebug("finished display of col=3D$c");
+		my $update_ctl;
=20
-		# don't use template if we have only a hidden HTML form variable
-		if ($display =3D~ /^\s*<input\s[^>]*type\s*=3D\W*hidden\b[^>]*>\s*$/i) {
-			col_chunk $c, $display . "\n";
+		if ($display->{WIDGET} =3D~ /^\s*<input\s[^>]*type\s*=3D\W*hidden\b[^>]*=
>\s*$/is) {
+			push @extra_hidden, $display->{WIDGET};
 			next;
 		}
-
-		$display =3D~ s/\~META\~/$meta_string/g;
-
-		$display =3D~ s/\~ERROR\~/$Tag->error({ name =3D> $c, keep =3D> 1 })/eg;
-=20=20=20=20=20=20=20=20
-		my $update_ctl;
-		if (! $wo and $break{$namecol}) {
-			push @titles, $break_label{$namecol};
-			if(@controls =3D=3D 0 and @titles =3D=3D 1) {
-				# do nothing
+		$display->{TEMPLATE} =3D $template->{$c};
+		$display->{META_STRING} =3D $meta_string;
+		$display->{TKEY}   =3D $tkey_message;
+		$display->{BLABEL} =3D $blabel;
+		$display->{ELABEL} =3D $elabel;
+		$display->{ERROR}  =3D $err_string;
+
+		$update_ctl =3D 0;
+		if ($break{$namecol}) {
+#::logDebug("breaking on $namecol, control index=3D$ctl_index");
+			if(@controls =3D=3D 0 and @titles =3D=3D 0) {
+				$titles[0] =3D $break_label{$namecol};
 			}
-			else {
+			elsif(@titles =3D=3D 0) {
+				$titles[1] =3D $break_label{$namecol};
 				$update_ctl =3D 1;
 			}
-
-			while($rowcount % $rowdiv) {
-				$w .=3D '<TD>&nbsp;</td><TD>&nbsp;</td>';
-				$rowcount++;
-			}
-			$w .=3D "</TR>\n";
-			unless ($opt->{tabbed}) {
-				$w .=3D <<EOF if $break{$namecol};
-	<TR class=3Drbreak>
-		<TD COLSPAN=3D$span class=3Dcbreak>$break_label{$namecol}<IMG SRC=3D"$op=
t->{clear_image}" WIDTH=3D1 HEIGHT=3D1 alt=3Dx></TD>
-	</TR>
-EOF
+			else {
+				push @titles, $break_label{$namecol};
+				$update_ctl =3D 1;
 			}
-			$rowcount =3D 0;
 		}
-		$w .=3D "<tr class=3Drnorm>\n" unless $rowcount++ % $rowdiv;
-		$w .=3D $display;
-		$w .=3D "</TR>\n" unless $rowcount % $rowdiv;
-		col_chunk $c, $w;
 		$ctl_index++ if $update_ctl;
+#::logDebug("control index now=3D$ctl_index");
+		col_chunk $c, $display;
 	}
=20
 	for(sort keys %link_row) {
-		col_chunk "SPREAD_$_", delete $link_row{$_};
+		col_chunk "_SPREAD_$_", { ROW =3D> delete $link_row{$_} };
 	}
=20
 	my $firstout =3D scalar(@out);
@@ -2660,7 +2740,7 @@
 	}
=20
 	while($rowcount % $rowdiv) {
-		chunk ttag(), '<TD>&nbsp;</td><TD>&nbsp;</td>'; # unless $wo;
+		chunk ttag(), '<td colspan=3D$cells_per_span>&nbsp;</td>'; # unless $wo;
 		$rowcount++;
 	}
=20
@@ -2697,11 +2777,7 @@
 	### Here the user can include some extra stuff in the form....
 	###
 	if($opt->{include_form}) {
-		chunk 'INCLUDE_FORM', <<EOF; # if ! $wo;
-<tr class=3Drnorm>
-<td colspan=3D$span>$opt->{include_form}</td>
-</tr>
-EOF
+		col_chunk '_INCLUDE_FORM', { ROW =3D> $opt->{include_form} };
 	}
 	### END USER INCLUDE
=20
@@ -2710,9 +2786,6 @@
 	}
 	$passed_fields =3D join " ", @cols;
=20
-	chunk 'MV_DATA_FIELDS', <<EOF; # unless $wo;
-<INPUT TYPE=3Dhidden NAME=3Dmv_data_fields VALUE=3D"$passed_fields">
-EOF
=20
 	chunk ttag(), <<EOF;
 <tr class=3Drspacer>
@@ -2727,6 +2800,11 @@
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
+
+		chunk 'EXTRA_HIDDEN', <<EOF; # unless $wo;
+<INPUT TYPE=3Dhidden NAME=3Dmv_data_fields VALUE=3D"$passed_fields">@extra=
_hidden
+EOF
+
 	  	if($opt->{back_text}) {
=20
 			chunk 'BOTTOM_BUTTONS', <<EOF;
@@ -2887,17 +2965,18 @@
 #::logDebug("In tabbed display...controls=3D" . scalar(@controls) . ", tit=
les=3D" . scalar(@titles));
 		my @tabcont;
 		for(@controls) {
-			push @tabcont, join "", map { $outhash{$_} } @$_;
+			push @tabcont, create_rows($opt, $_);
 		}
 		$opt->{panel_prepend} ||=3D '<table>';
 		$opt->{panel_append} ||=3D '</table>';
 		push @put, tabbed_display(\@titles,\@tabcont,$opt);
 	}
 	else {
-		for my $c (@controls) {
-			for (@$c) {
-				push @put, $outhash{$_};
-			}
+#::logDebug("titles=3D" . uneval(\@titles) . "\ncontrols=3D" . uneval(\@co=
ntrols));
+		for(my $i =3D 0; $i < @controls; $i++) {
+			push @put, tag_attr_list($opt->{break_template}, { ROW =3D> $titles[$i]=
 })
+				if $titles[$i];
+			push @put, create_rows($opt, $controls[$i]);
 		}
 	}
=20
@@ -2907,5 +2986,67 @@
 	}
 	return join "", @put;
 }
+
+sub convert_old_template {
+	my $string =3D shift;
+	$string =3D~ s/\$WIDGET\$/{WIDGET}/g
+		or return $string;
+	$string =3D~ s!\{HELP_URL\}(.*)\{/HELP_URL\}!{HELP_URL?}$1\{/HELP_URL?}!g=
s;
+	$string =3D~ s/\$HELP\$/{HELP}/g;
+	$string =3D~ s/\$HELP_URL\$/{HELP_URL}/g;
+	$string =3D~ s/\~META\~/{META_STRING}/g;
+	$string =3D~ s/\$LABEL\$/{LABEL}/g;
+	$string =3D~ s/\~ERROR\~/{LABEL}/g;
+	$string =3D~ s/\~TKEY\~/{TKEY}/g;
+	$string =3D~ s/\~BLABEL\~/{BLABEL}/g;
+	$string =3D~ s/\~ELABEL\~/{ELABEL}/g;
+	return $string;
+}
+
+sub create_rows {
+	my ($opt, $columns) =3D @_;
+	$columns ||=3D [];
+
+	my $rowdiv			=3D $opt->{across}    || 1;
+	my $cells_per_span	=3D $opt->{cell_span} || 2;
+	my $rowcount		=3D 0;
+	my $span			=3D $rowdiv * $cells_per_span;
+	my $oddspan			=3D $span - 1;
+
+	my @out;
+
+	for(@$columns) {
+		# If doesn't exist, was brought in before.
+		my $ref =3D delete $outhash{$_}
+			or next;
+		if($opt->{ROW}) {
+			push @out, tag_attr_list($opt->{combo_template}, $ref, 1);
+			$rowcount =3D 0;
+			next;
+		}
+		my $w =3D '';
+		$w .=3D "<tr$opt->{data_row_extra}>\n" unless $rowcount++ % $rowdiv;
+		$w .=3D tag_attr_list($ref->{TEMPLATE}, $ref);
+		$w .=3D "</tr>" unless $rowcount % $rowdiv;
+		push @out, $w;
+	}=09
+
+	if($rowcount % $rowdiv) {
+		my $w =3D '';
+		while($rowcount % $rowdiv) {
+			$w .=3D '<TD colspan=3D$cells_per_span>&nbsp;</td>';
+			$rowcount++;
+		}
+		$w .=3D "</tr>";
+		push @out, $w;
+	}
+	return join "\n", @out;
+}
+
+#			push @out, <<EOF if $break;
+#<tr$opt->{break_row_extra}>
+#	<td COLSPAN=3D$span$opt->{td_extra}{break}>$break_label{$namecol}</td>
+#</tr>
+#EOF
=20
 1;