[interchange-cvs] interchange - heins modified 4 files

interchange-core@icdevgroup.org interchange-core@icdevgroup.org
Tue Sep 24 11:42:01 2002


User:      heins
Date:      2002-09-24 15:40:58 GMT
Modified:  dist/foundation/products mv_metadata.asc
Modified:  dist/lib/UI/pages/admin db_metaconfig.html
Modified:  dist/lib/UI/pages/include page_editor
Modified:  lib/Vend/Table Editor.pm
Log:
* Templateable editor. Example:

[table-editor table=3Dproducts item_id=3Dos28004]
{TOP_OF_FORM}
{HIDDEN_FIELDS}
<table>
	<tr>
		<td>
			Whoa, boy!
		</td>
		<td>
		{COLUMN_description__WIDGET}
		</td>
	</tr>
	<tr>
		{COLUMN_comment}
	</tr>
	<tr>
	<td colspan=3D2>
	{:REST}
	</td>
	<tr>
		<td colspan=3D2>
		{BOTTOM_BUTTONS}
		</td>
	</td>
</table>
{BOTTOM_OF_FORM}
[/table-editor]

   The key feature that makes this usable for me is the {:REST},
   which plops the rest of the fields in a tabbed display inside
   that table cell.

* Allow configuring of link_table with db_metaconfig, example provided
  in foundation with transactions table. Only allows one link table --
  multiple link tables would need to be configured in via the
  extended field or with tag options.

* More bug fixes in table-editor stuff. This thing is really coming along!

* Supply end tags to the table-editor in the page editor. While it works
  without it, performance should be better and a stray [/table-editor]
  won't cause problems.

Revision  Changes    Path
2.14      +1 -1      interchange/dist/foundation/products/mv_metadata.asc


rev 2.14, prev_rev 2.13
Index: mv_metadata.asc
=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/dist/foundation/products/mv_metadata.asc,v
retrieving revision 2.13
retrieving revision 2.14
diff -u -r2.13 -r2.14
--- mv_metadata.asc	24 Sep 2002 01:37:28 -0000	2.13
+++ mv_metadata.asc	24 Sep 2002 15:40:56 -0000	2.14
@@ -195,7 +195,7 @@
 shipping	text			description=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09=
=09=09
 state				code=0Dcountry=0Dstate=0Dname=0Dtax=0Dtax_name		State/Province Se=
ttings (tax, etc)=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09
 state::state	text	4											word=09=09=09=09=09=09=09=09
-transactions	text																		1=09=09
+transactions	text		100																1		{'bottom_buttons' =3D> "",'spread=
_textarea' =3D> "",'tab_vert_offset' =3D> "",'widget_cell_class' =3D> "",'u=
i_sort_field' =3D> "order_number",'link_table' =3D> "orderline",'ui_show_fi=
elds' =3D> "code=0Dusername=0Dnitems=0Dtotal_cost",'link_extra' =3D> "",'br=
eak_row_class' =3D> "",'label_cell_class' =3D> "",'tab_horiz_offset' =3D> "=
",'link_before' =3D> "session",'ui_special_add' =3D> "",'left_width' =3D> "=
120",'top_buttons' =3D> "",'combo_row_class' =3D> "",'spread_fields' =3D> "=
",'tab_height' =3D> "",'link_view' =3D> "",'link_fields' =3D> "code order_n=
umber sku quantity description price subtotal",'spread_meta' =3D> "",'tab_w=
idth' =3D> "",'data_row_class' =3D> "",'panel_height' =3D> "",'help_cell_cl=
ass' =3D> "",'spacer_row_class' =3D> "",'ui_data_fields' =3D> "=3DGeneral=
=0D=0Dcode=0Dstore_id=0Dorder_number =0Dsession=0Dusername=0Dcomments=0D=0D=
=3DTransaction info=0D=0Dstatus=0Dnitems=0Dsubtotal=0Dshipping=0Dhandling=
=0Dtotal_cost=0Dorder_date=0Dorder_ymd=0Dorder_wday=0Darchived=0Ddeleted=0D=
complete=0D=0D=3DMisc=0D=0Dshipmode=0Dpayment_method=0Davs=0Dpo_number=0Dor=
der_id=0Dsalestax=0D=0D=3DShipping=0D=0Dfname=0Dlname=0Dcompany=0Daddress1=
=0Daddress2=0Dcity=0Dstate=0Dzip=0Dcountry=0Dphone_day=0Dphone_night=0Dfax=
=0Demail=0D=0D=3DBilling=0D=0Db_fname=0Db_lname=0Db_company=0Db_address1=0D=
b_address2=0Db_city=0Db_state=0Db_zip=0Db_country=0Db_phone=0D=0D=3DTrackin=
g info=0D=0Daffiliate=0Dcampaign=0Dcurrency_locale=0Dparent=0Dupdate_date=
=0D",'file_upload' =3D> "",'spread_width' =3D> "",'tabbed' =3D> "1",'spread=
_height' =3D> "",'spread_textarea_rows' =3D> "",'table_width' =3D> "800",'l=
ink_sort' =3D> "code",'panel_width' =3D> "",'link_key' =3D> "order_number",=
'data_cell_class' =3D> "",'link_label' =3D> "Ordered Items",}
 transactions::status	combo							pending=3DPending, shipped=3DShipped, par=
tial=3DPartially shipped, backorder=3DBack ordered, credit=3DWaiting for cr=
edit check, canceled=3DCanceled					nullselect=09=09=09=09=09=09=09=09
 ui_component::mv_metadata																					{'ui_data_fields' =3D> "=3DM=
ain=0D=0Dcode=0Dlabel=0Ddefault=0Dtype=0Dwidth=0Dheight=0Doptions=0Dfilter=
=0D=0D=3DDatabase lookup=0D=0Dlookup=0Dfield=0Ddb=0D=0D=3DHelp and misc=0D=
=0Dhelp=0Dhelp_url=0Dprepend=0Dappend=0Dpre_filter",'table_width' =3D> "80%=
",'left_width' =3D> "30%",}
 ui_component::mv_metadata::append	textarea	60	5							Append HTML	<SMALL>H=
TML to be appended to the widget.=0DWill substitute in the macros _UI_TABLE=
_, _UI_COLUMN_,=0D_UI_KEY, and _UI_VALUE_, and will resolve relative links=
=0Dwith absolute links.</SMALL>=09=09=09=09=09=09=09=09=09=09



2.5       +23 -0     interchange/dist/lib/UI/pages/admin/db_metaconfig.html


rev 2.5, prev_rev 2.4
Index: db_metaconfig.html
=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/dist/lib/UI/pages/admin/db_metaconfig.html,v
retrieving revision 2.4
retrieving revision 2.5
diff -u -r2.4 -r2.5
--- db_metaconfig.html	24 Sep 2002 01:37:29 -0000	2.4
+++ db_metaconfig.html	24 Sep 2002 15:40:57 -0000	2.5
@@ -70,6 +70,14 @@
 		extended.ui_data_fields
 		extended.bottom_buttons
 		extended.top_buttons
+		extended.link_table
+		extended.link_before
+		extended.link_key
+		extended.link_label
+		extended.link_sort
+		extended.link_fields
+		extended.link_view
+		extended.link_extra
=20
 		=3DTabbed display
=20
@@ -130,6 +138,14 @@
 		'extended.ui_show_fields'		=3D> 'Show on select page',
 		'extended.ui_sort_field'		=3D> 'Sort by on select page',
 		'extended.ui_special_add'		=3D> 'Special Additions',
+		'extended.link_table'			=3D> 'Table to link in cell',
+		'extended.link_before'			=3D> 'Column to appear before',
+		'extended.link_key'				=3D> 'Foreign Key',
+		'extended.link_label'			=3D> 'Label for linked table',
+		'extended.link_sort'			=3D> 'Sort linked records by',
+		'extended.link_fields'			=3D> 'Fields in table to link',
+		'extended.link_view'			=3D> 'View to derive link display',
+		'extended.link_extra'			=3D> 'HTML style info for linked cells',
 		'extended.data_row_class'		=3D> 'Data row class',
 		'extended.break_row_class'		=3D> 'Break row class',
 		'extended.spacer_row_class'		=3D> 'Spacer row class',
@@ -182,6 +198,11 @@
 		'extended.ui_show_fields'		=3D> 'move_combo_8',
 		'extended.ui_sort_field'		=3D> 'select',
 		'extended.bottom_buttons'		=3D> 'yesno',
+		'extended.link_table'			=3D> 'select',
+		'extended.link_before'			=3D> 'text_12',
+		'extended.link_label'			=3D> 'text_50',
+		'extended.link_fields'			=3D> 'text_70',
+		'extended.link_key'			=3D> 'text_20',
 		'extended.top_buttons'		=3D> 'yesno',
 	}`
=20
@@ -219,6 +240,8 @@
 		'extended.spread_fields'		=3D> 'columns',
 		'extended.spread_meta'			=3D> 'columns',
 		'extended.spread_textarea'		=3D> 'columns',
+		'extended.link_table'			=3D> 'tables',
+		'extended.link_before'			=3D> '',
 		'extended.ui_special_add'		=3D> q{NONE,
 Qty price;pricing:q5:rn=3DQty price,
 Options;options:o_enable:r=3DOptions,



1.5       +10 -4     interchange/dist/lib/UI/pages/include/page_editor


rev 1.5, prev_rev 1.4
Index: page_editor
=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/dist/lib/UI/pages/include/page_editor,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- page_editor	13 Sep 2002 20:46:21 -0000	1.4
+++ page_editor	24 Sep 2002 15:40:57 -0000	1.5
@@ -463,6 +463,7 @@
 			action=3Dreturn
 			height.ui_body_text=3D"38"
 			width.ui_body_text=3D"100%"
+			no-table-meta=3D1
 			hidden.ui_content_op=3Dmodify_body
 			hidden.ui_name=3D"[page-param ui_name]"
 			hidden.ui_type=3Dpage
@@ -475,6 +476,7 @@
 			nocancel=3D1
 			notable=3D1
 			no_meta=3D1
+			no-table-meta=3D1
 			override.ui_body_text=3D`$page_content`
 			show_reset=3D1
 			table=3Djunk
@@ -493,7 +495,7 @@
 			  [/else]
 			  [/if-comp-param]
 			|
-		]
+		][/table-editor]
=20=09=09
 	[/else]
 	[/if-comp-param]
@@ -546,6 +548,7 @@
 			nocancel=3D1
 			notable=3D1
 			no_meta=3D1
+			no-table-meta=3D1
 			override.ui_body_text=3D`$page_content`
 			show_reset=3D1
 			table=3Djunk
@@ -558,9 +561,10 @@
 				onSubmit=3D"submitted('CONTENT'); return check_change()"
 				onReset=3D"submitted('CONTENT')"
 			|
-		]
+		][/table-editor]
=20
 	</div>
+
 [/if]
=20
 	<div
@@ -589,6 +593,7 @@
 			nocancel=3D1
 			notable=3D1
 			no_meta=3D1
+			no-table-meta=3D1
 			override.ui_body_text=3D`$page_preamble`
 			show_reset=3D1
 			table=3Djunk
@@ -601,7 +606,7 @@
 				onSubmit=3D"submitted('PREAMBLE'); return check_change()"
 				onReset=3D"submitted('PREAMBLE')"
 			|
-		]
+		][/table-editor]
 		<div
 			align=3Dleft
 			valign=3Dbottom
@@ -676,6 +681,7 @@
 			nocancel=3D1
 			notable=3D1
 			no_meta=3D1
+			no-table-meta=3D1
 			override.ui_body_text=3D`$page_postamble`
 			show_reset=3D1
 			table=3Djunk
@@ -688,7 +694,7 @@
 				onSubmit=3D"submitted('POSTAMBLE'); return check_change()"
 				onReset=3D"submitted('POSTAMBLE')"
 			|
-		]
+		][/table-editor]
 		<div
 			align=3Dleft
 			valign=3Dbottom



1.7       +158 -55   interchange/lib/Vend/Table/Editor.pm


rev 1.7, prev_rev 1.6
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.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Editor.pm	24 Sep 2002 01:37:31 -0000	1.6
+++ Editor.pm	24 Sep 2002 15:40:58 -0000	1.7
@@ -1,6 +1,6 @@
 # Vend::Table::Editor - Swiss-army-knife table editor for Interchange
 #
-# $Id: Editor.pm,v 1.6 2002/09/24 01:37:31 mheins Exp $
+# $Id: Editor.pm,v 1.7 2002/09/24 15:40:58 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.6 $, 10);
+$VERSION =3D substr(q$Revision: 1.7 $, 10);
=20
 use Vend::Util;
 use Vend::Interpolate;
@@ -800,6 +800,8 @@
=20
 sub add_exclude {
 	my ($tag, $string) =3D @_;
+#::logDebug("calling add_exclude tag=3D'$tag' string=3D'$string'");
+	return unless $string =3D~ /\S/;
 	$exclude{$tag} ||=3D ' ';
 	$exclude{$tag} .=3D "$string ";
 }
@@ -847,14 +849,14 @@
 	die "duplicate tag settor $tag" if exists $outhash{$tag};
 	$outhash{$tag} =3D $value;
=20
-#::logDebug("$tag content length=3D" . length($value));
+#::logDebug("$tag exclude=3D$exclude, content length=3D" . length($value));
=20
 	if(@others) {
 		$alias{$tag} ||=3D [];
 		push @{$alias{$tag}}, @others;
 	}
=20
-	add_exclude($tag, $exclude) if $exclude;
+	add_exclude($tag, $exclude) if $exclude =3D~ /\S/;
=20
 	return unless length($value);
 	push @out, $tag;
@@ -863,13 +865,16 @@
 sub resolve_exclude {
 	my $exc =3D shift;
 	while(my ($k, $v) =3D each %exclude) {
+		my %seen;
+		my @things =3D grep /\S/ && ! $seen{$_}++, split /\s+/, $v;
 #::logDebug("examining $k for $v");
-		while ($v =3D~ m{(\S+)}g) {
-			my $thing =3D $1;
+		for my $thing (@things) {
 			if($thing =3D~ s/^[^A-Z]//) {
+#::logDebug("examining $v for $thing!=3D$exc->{$thing}");
 				$outhash{$k} =3D '' unless $exc->{$thing};
 			}
 			else {
+#::logDebug("examining $v for $thing=3D$exc->{$thing}");
 				$outhash{$k} =3D '' if $exc->{$thing};
 			}
 		}
@@ -885,6 +890,7 @@
 	@controls =3D ();
 	@titles =3D ();
 	%outhash =3D ();
+	%exclude =3D ();
 	%alias =3D ();
 	$tcount_all =3D 0;
 	$ctl_index =3D 0;
@@ -1071,6 +1077,15 @@
 		label_cell_class
 		label_cell_style
 		left_width
+		link_before
+		link_table
+		link_fields
+		link_label
+		link_sort
+		link_key
+		link_view
+		link_template
+		link_extra
 		mv_blob_field
 		mv_blob_label
 		mv_blob_nick
@@ -1830,8 +1845,10 @@
=20
 	no strict 'subs';
=20
-	chunk 'FORM_BEGIN', 'WO', 'TOP_OF_FORM', <<EOF; # unless $wo;
+	chunk 'FORM_BEGIN', <<EOF; # unless $wo;
 $restrict_begin<FORM METHOD=3D$opt->{method} ACTION=3D"$opt->{href}"$opt->=
{form_name}$opt->{enctype}$opt->{form_extra}>
+EOF
+	chunk 'HIDDEN_ALWAYS', <<EOF;
 $sidstr<INPUT TYPE=3Dhidden NAME=3Dmv_todo VALUE=3D"$opt->{action}">
 <INPUT TYPE=3Dhidden NAME=3Dmv_click VALUE=3D"process_filter">
 <INPUT TYPE=3Dhidden NAME=3Dmv_nextpage VALUE=3D"$opt->{mv_nextpage}">
@@ -1868,7 +1885,7 @@
 		$val =3D~ s/"/&quot;/g;
 		push @o, qq{<INPUT TYPE=3Dhidden NAME=3D$_ VALUE=3D"$val">\n}; # unless =
$wo;
 	}
-	chunk 'HIDDEN_OPT', '', 'TOP_OF_FORM', join("", @o);
+	chunk 'HIDDEN_OPT', '', join("", @o);
   }
=20
   CGISET: {
@@ -1879,7 +1896,7 @@
 		$val =3D~ s/"/&quot;/g;
 		push @o, qq{<INPUT TYPE=3Dhidden NAME=3D$_ VALUE=3D"$val">\n}; # unless =
$wo;
 	}
-	chunk 'HIDDEN_CGI', '', 'TOP_OF_FORM', join("", @o);
+	chunk 'HIDDEN_CGI', '', join("", @o);
   }
=20
 	if($opt->{mailto}) {
@@ -1901,7 +1918,7 @@
 		elsif ($CGI::values{ui_return_to}) {
 			@$r_ary =3D ( $CGI::values{ui_return_to} );=20
 		}
-		chunk 'RETURN_TO', '', 'TOP_OF_FORM', $Tag->return_to(); # unless $wo;
+		chunk 'RETURN_TO', '', $Tag->return_to(); # unless $wo;
 #::logDebug("return-to stack =3D " . ::uneval($r_ary));
 	}
=20
@@ -1911,14 +1928,10 @@
 		while ( ($hk, $hv) =3D each %{$opt->{hidden}} ) {
 			push @o, qq{<INPUT TYPE=3Dhidden NAME=3D"$hk" VALUE=3D"$hv">\n};
 		}
-		chunk 'HIDDEN', 'WO', join("", @o); # unless $wo;
+		chunk 'HIDDEN_USER', join("", @o); # unless $wo;
 	}
=20
-	my $tcount_all =3D 0;
-=09
-	my $tcount_top =3D 0;
-	my $tcount_bot =3D 0;
-	chunk ttag(), 'WO', <<EOF; # unless $wo;
+	chunk ttag(), <<EOF; # unless $wo;
 <table class=3Dtouter border=3D"0" cellspacing=3D"0" cellpadding=3D"0" wid=
th=3D"$opt->{table_width}">
 <tr>
   <td>
@@ -1943,7 +1956,7 @@
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
-			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS', 'TOP_BUTTONS', <<EOF; # i=
f ! $opt->{bottom_buttons};
+			chunk 'COMBINED_BUTTONS_TOP', 'BOTTOM_BUTTONS', <<EOF; # if ! $opt->{bo=
ttom_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
@@ -1963,7 +1976,7 @@
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
-			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS NO_TOP', 'TOP_BUTTONS', <<E=
OF; # if ! $opt->{bottom_buttons};
+			chunk 'WIZARD_BUTTONS_TOP', 'BOTTOM_BUTTONS NO_TOP', <<EOF; # 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
@@ -1987,24 +2000,20 @@
 		  $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', 'NO_TOP', 'TOP_BUTTONS', <<EOF;
+		  chunk 'OK_TOP', 'NO_TOP', <<EOF;
 <INPUT TYPE=3Dsubmit NAME=3Dmv_click VALUE=3D"$opt->{next_text}" style=3D"=
$opt->{ok_button_style}">
 EOF
-		  chunk ttag(), 'NOCANCEL BOTTOM_BUTTONS NO_TOP', 'TOP_BUTTONS', <<EOF;
+		  chunk 'CANCEL_TOP', 'NOCANCEL BOTTOM_BUTTONS NO_TOP', <<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 NO_TOP',
-			'TOP_BUTTONS',
-			<<EOF;
+		  chunk 'RESET_TOP', '_SHOW_RESET BOTTOM_BUTTONS NO_TOP', <<EOF;
 &nbsp;
 <INPUT TYPE=3Dreset>
 EOF
=20
-			chunk 'MLABEL', 'BOTTOM_BUTTONS', 'MESSAGES', $mlabel;
+			chunk 'MLABEL', 'BOTTOM_BUTTONS', $mlabel;
 			chunk ttag(), 'BOTTOM_BUTTONS NO_TOP', <<EOF;
 </TD>
 </TR>
@@ -2133,6 +2142,17 @@
 EOF
 	}
=20
+	chunk_alias 'TOP_OF_FORM', qw/ FORM_BEGIN /;
+	chunk_alias 'TOP_BUTTONS', qw/
+								COMBINED_BUTTONS_TOP
+								WIZARD_BUTTONS_TOP
+								OK_TOP
+								CANCEL_TOP
+								RESET_TOP
+								BLOB_WIDGET
+								CLONE_TABLES
+								/;
+
 	my %break;
 	my %break_label;
 	if($opt->{ui_break_before}) {
@@ -2290,7 +2310,7 @@
          <td$opt->{widget_cell_extra}>
            {WIDGET}
          </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>
+         <td$opt->{help_cell_extra}>{TKEY}{HELP?}<i>{HELP}</i>{/HELP?}{HEL=
P_URL?}<BR><A HREF=3D"{HELP_URL}">help</A>{/HELP_URL?}</td>
        </tr>
      </table>
    </td>
@@ -2301,8 +2321,10 @@
 	$row_template =3D~ s/~OPT:(\w+)~/$opt->{$1}/g;
 	$row_template =3D~ s/~([A-Z]+)_EXTRA~/$opt->{"\L$1\E_extra"} || $opt->{"\=
L$1\E_cell_extra"}/g;
=20
+	$opt->{row_template} =3D $row_template;
+
 	$opt->{combo_template} ||=3D <<EOF;
-<tr$opt->{combo_row_extra}><td colspan=3D$span>{ROW}</td></tr>
+<tr$opt->{combo_row_extra}><td> {LABEL} </td><td>{WIDGET}</td></tr>
 EOF
=20
 	$opt->{break_template} ||=3D <<EOF;
@@ -2335,6 +2357,7 @@
 	my %link_row;
 	my %link_before;
 	if($opt->{link_table} and $key) {
+#::logDebug("In link table routines...");
 		my @ltable;
 		my @lfields;
 		my @lkey;
@@ -2368,7 +2391,7 @@
 			my $lf =3D shift @lfields;
 			my $lv =3D shift @lview;
 			my $lk =3D shift @lkey;
-			my $ll =3D shift @lkey;
+			my $ll =3D shift @llab;
 			my $lb =3D shift @lbefore;
 			my $ls =3D shift @lsort;
=20
@@ -2463,6 +2486,7 @@
 				$whash->{META_STRING} .=3D errmsg('meta') . '</a>';
=20
 			}
+			$whash->{ROW} =3D 1;
 			$link_row{$lt} =3D $whash;
 			if($lb) {
 				$link_before{$lb} =3D $lt;
@@ -2470,6 +2494,7 @@
 			my $mde_key =3D "mv_data_enable__$tcount";
 			$::Scratch->{$mde_key} =3D "$lt:" . join(",", $l_pkey, @cf) . ':';
 			$tcount++;
+#::logDebug("Made link_table...whash=3D$whash");
 		}
 	}
=20
@@ -2748,8 +2773,8 @@
 			}
 		}
 		if($link_before{$col}) {
-			my $h =3D { ROW =3D> delete $link_row{$link_before{$col}} };
-			col_chunk "_SPREAD_$link_before{$col}", $h;
+			col_chunk "_SPREAD_$link_before{$col}",
+						delete $link_row{$link_before{$col}};
 		}
 		if($opt->{include_before} and $opt->{include_before}{$col}) {
 			my $h =3D { ROW =3D> $opt->{include_before}{$col} };
@@ -2762,11 +2787,11 @@
 		}
 #::logDebug("control index now=3D$ctl_index");
 		col_chunk $c, $display;
-		$titles[0] =3D $t if ! $titles[0];
 	}
=20
 	for(sort keys %link_row) {
-		col_chunk "_SPREAD_$_", { ROW =3D> delete $link_row{$_} };
+#::logDebug("chunking link_table to _SPREAD_$_");
+		col_chunk "_SPREAD_$_", delete $link_row{$_};
 	}
=20
 	my $firstout =3D scalar(@out);
@@ -2825,30 +2850,34 @@
=20
 	chunk ttag(), <<EOF;
 <tr class=3Drspacer>
-<td colspan=3D$span ><img src=3D"$opt->{clear_image}" height=3D3 alt=3Dx><=
/td>
+<td colspan=3D$span>
+EOF
+	chunk 'HIDDEN_EXTRA', <<EOF; # unless $wo;
+<INPUT TYPE=3Dhidden NAME=3Dmv_data_fields VALUE=3D"$passed_fields">@extra=
_hidden
+EOF
+	chunk ttag(), <<EOF;
+<img src=3D"$opt->{clear_image}" height=3D3 alt=3Dx></td>
 </tr>
 EOF
=20
   SAVEWIDGETS: {
   	last SAVEWIDGETS if $wo || $opt->{nosave};=20
+#::logDebug("in SAVEWIDGETS");
 		chunk ttag(), <<EOF;
 <TR class=3Drnorm>
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
 EOF
=20
-		chunk 'EXTRA_HIDDEN', <<EOF; # unless $wo;
-<INPUT TYPE=3Dhidden NAME=3Dmv_data_fields VALUE=3D"$passed_fields">@extra=
_hidden
-EOF
=20
 	  	if($opt->{back_text}) {
=20
-			chunk 'BOTTOM_BUTTONS', <<EOF;
+			chunk 'COMBINED_BUTTONS_BOTTOM', <<EOF;
 <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>
 EOF
 		}
 		elsif($opt->{wizard}) {
-			chunk 'BOTTOM_BUTTONS', <<EOF;
+			chunk 'WIZARD_BUTTONS_BOTTOM', <<EOF;
 <TR class=3Drnorm>
 <td>&nbsp;</td>
 <td align=3Dleft colspan=3D$oddspan class=3Dcdata>
@@ -2866,7 +2895,6 @@
=20
 			chunk 'RESET_BOTTOM', qq{&nbsp;<INPUT TYPE=3Dreset>}
 				if $opt->{show_reset};
-			chunk_alias 'BOTTOM_BUTTONS', qw/OK_BOTTOM CANCEL_BOTTOM RESET_BOTTOM/;
 		}
=20
 	if(! $opt->{notable} and $Tag->if_mm('tables', "$table=3Dx") and ! $db->c=
onfig('LARGE') ) {
@@ -2910,6 +2938,21 @@
 EOF
=20
 	}
+	chunk_alias 'HIDDEN_FIELDS', qw/
+										HIDDEN_ALWAYS
+										HIDDEN_OPT
+										HIDDEN_CGI
+										HIDDEN_USER
+										HIDDEN_EXTRA
+										/;
+	chunk_alias 'BOTTOM_BUTTONS', qw/
+										WIZARD_BUTTONS_BOTTOM
+										COMBINED_BUTTONS_BOTTOM
+										OK_BOTTOM
+										CANCEL_BOTTOM
+										RESET_BOTTOM
+										AUTO_EXPORT
+										DELETE_BUTTON/;
 	chunk ttag(), <<EOF;
 </small>
 </td>
@@ -2919,16 +2962,6 @@
=20
 	my $message =3D '';
=20
-#	if($opt->{bottom_errors}) {
-#		my $err =3D $Tag->error( {
-#									show_var =3D> $error_show_var,
-#									show_error =3D> 1,
-#									joiner =3D> '<BR>',
-#								}
-#								);
-#		push @errors, $err if $err;
-#	}
-
 	if(@errors) {
 		$message .=3D '<P>Errors:';
 		$message .=3D qq{<FONT COLOR=3D"$opt->{color_fail}">};
@@ -2956,12 +2989,14 @@
 	</td>
 </tr>
 EOF
+
+#::logDebug("tcount=3D$tcount_all, prior to closing table");
 	chunk ttag(), <<EOF; # unless $wo;
 </table>
 </td></tr></table>
 EOF
=20
-	chunk 'FORM_BOTTOM', <<EOF;
+	chunk 'FORM_END', '', 'BOTTOM_OF_FORM', <<EOF;
 </form>$restrict_end
 EOF
=20
@@ -2974,7 +3009,6 @@
 		NOSAVE
 		NO_BOTTOM
 		NO_TOP
-		WO
 		SHOW_RESET
 		/)
 	{
@@ -2983,6 +3017,7 @@
=20
 	$ehash{MESSAGE} =3D length($message) ? 1 : 0;
=20
+#::logDebug("exclude is " . uneval(\%exclude));
 	resolve_exclude(\%ehash);
=20
 	if($wo) {
@@ -2992,6 +3027,72 @@
 show_times("end table editor call item_id=3D$key") if $Global::ShowTimes;
=20
 	my @put;
+	if($overall_template) {
+		my $death =3D sub {
+			my $item =3D shift;
+			logDebug("must have chunk {$item} defined in overall template.");
+			logError("must have chunk {%s} defined in overall template.", $item);
+			return undef;
+		};
+		$overall_template =3D~ /{TOP_OF_FORM}/
+			or return $death->('TOP_OF_FORM');
+		$overall_template =3D~ /{HIDDEN_FIELDS}/
+			or return $death->('HIDDEN_FIELDS');
+		$overall_template =3D~ /{BOTTOM_OF_FORM}/
+			or return $death->('BOTTOM_OF_FORM');
+		while($overall_template =3D~ m/\{((?:_INCLUDE_|COLUMN_|_SPREAD_).*?)\}/g=
) {
+			my $name =3D $1;
+			my $orig =3D $name;
+			my $thing =3D delete $outhash{$name};
+#::logDebug("Got to column replace $name, thing=3D$thing");
+			if($name =3D~ /^_/) {
+				$overall_template =3D~ s/\{$name\}/$thing->{ROW}/;
+			}
+			elsif($name =3D~ s/__WIDGET$//) {
+				$thing =3D delete $outhash{$name};
+#::logDebug("Got to widget replace $name, thing=3D$thing");
+				$overall_template =3D~ s/\{$orig\}/$thing->{WIDGET}/;
+			}
+			elsif($thing) {
+				$overall_template =3D~ s!\{$name\}!
+										tag_attr_list($thing->{TEMPLATE}, $thing)
+										!e;
+			}
+		}
+		while($overall_template =3D~ m/\{([A-Z_]+)\}/g) {
+			my $name =3D $1;
+			my $thing =3D delete $outhash{$name};
+#::logDebug("Got to random replace $name, thing=3D$thing");
+			next if ! $thing and $alias{$name};
+			$overall_template =3D~ s/\{$name\}/$thing/;
+		}
+		while($overall_template =3D~ m/\{([A-Z_]+)\}/g) {
+			my $name =3D $1;
+			my $thing =3D delete $alias{$name};
+#::logDebug("Got to alias replace $name, thing=3D$thing");
+			$overall_template =3D~ s/\{$name\}/join "", @outhash{@$thing}/e;
+		}
+		my @put;
+		if($opt->{tabbed}) {
+			my @tabcont;
+			for(@controls) {
+				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 $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]);
+			}
+		}
+		$overall_template =3D~ s/{:REST}/join "\n", @put/e;
+		return $overall_template;
+	}
+
 	for(my $i =3D 0; $i < $firstout; $i++) {
 #::logDebug("$out[$i] content length=3D" . length($outhash{$out[$i]} ));
 		push @put, $outhash{$out[$i]};
@@ -3018,7 +3119,7 @@
=20
 	for(my $i =3D $firstout; $i < @out; $i++) {
 #::logDebug("$out[$i] content length=3D" . length($outhash{$out[$i]} ));
-		push @put, $outhash{$out[$i]};
+		push @put, @outhash{$out[$i]};
 	}
 	return join "", @put;
 }
@@ -3055,8 +3156,10 @@
 		# 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);
+		if($ref->{ROW}) {
+#::logDebug("outputting ROW $_=3D$ref->{ROW}");
+			my $tpl =3D $ref->{TEMPLATE} || $opt->{row_template};
+			push @out, tag_attr_list($opt->{combo_template}, $ref);
 			$rowcount =3D 0;
 			next;
 		}