[interchange-cvs] interchange - heins modified 4 files

interchange-cvs at icdevgroup.org interchange-cvs at icdevgroup.org
Thu Jul 24 14:29:00 EDT 2003


User:      heins
Date:      2003-07-24 17:28:59 GMT
Modified:  dist/lib/UI/pages/admin db_metaconfig.html meta_editor.html
Modified:           flex_select.html
Added:     code/UI_Tag flex_select.coretag
Log:
* Add [flex-select] tag, complete replacement for and enhancement to
  the admin/flex_select.html page in the UI.

* Each colunn can have individual sort settings, and can individually
  be specified to use alphabetic more lists when it is the sorting
  column. (ui_more_alpha, ui_sort_option)

* Group "magnifying glass" can be turned off in metadata. (fs_no_group)

* Filters can be specified in metadata instead of just ui_data_fields.
  (fs_display_filter)

* Links to other pages specifying the field value can be done
  easily. For example, to add a per-sku link on the products
  table to the item_options page, put in ui_data_fields

  	sku
	sku-options
	price
	description

  In the metadata for products::sku-options, do:

		'extended.fs_link_page' => 'admin/item_options',
		'extended.fs_link_parm' => 'item_id',
		'extended.fs_link_anchor' => 'Edit Options',

  That will produce:

   <a href="__CGI_URL__/admin/item_options?item_id=SKU">Edit Options</a>

  Can be shorthand-set in ui_data_fields with:

  	sku
	sku-admin/item_options:item_id:Edit Options
	price
	description

* Columns can be calculated values by putting embedded perl code in
  fs_data_calc. The current row hash (with all values in the select colums)
  is put in $Vend::Interpolate::item. You can set tables to be pre-opened
  in fs_data_tables.

  This code in products::prod_group::extended.fs_data_calc:

	if($item->{prod_group} eq $prev) {
		return "''";
	}
	else {
		return $prev = $item->{prod_group};
	}

  will produce ditto marks if a prod_group is duplicated.

* An explicit "edit record" link can be enabled. (explicit_edit)

* The edit link on the key column can be disabled. (no_code_link)

* Checkboxes can be disabled. (no_checkbox)

* Check All/Uncheck All JavaScript links can be automatically inserted.
  (check_uncheck_all)

* The lines can be numbered. (number_list)

* Header cell and data cell CSS is completely settable in metadata on a
  per-column basis.

		'extended.header_link_class' => 'Header row link CSS class',
		'extended.header_cell_class' => 'Header cell CSS class',
		'extended.header_cell_style' => 'Header cell CSS style',
		'extended.data_cell_class' => 'Data cell CSS class',
		'extended.data_cell_style' => 'Data cell CSS style',

  While no metadata edit is provided for data_cell_width, data_cell_height,
  data_cell_align, they would be honored if set.

  The header rows and data rows can be set in the table metadata:

		'extended.header_row_class' => 'Header row CSS class',
		'extended.header_row_style' => 'Header row CSS style',
		'extended.data_row_class_odd' => 'Data row CSS class, odd numbers',
		'extended.data_row_class_even' => 'Data row CSS class, even numbers',

Revision  Changes    Path
2.17      +14 -1     interchange/dist/lib/UI/pages/admin/db_metaconfig.html


rev 2.17, prev_rev 2.16
Index: db_metaconfig.html
===================================================================
RCS file: /var/cvs/interchange/dist/lib/UI/pages/admin/db_metaconfig.html,v
retrieving revision 2.16
retrieving revision 2.17
diff -u -r2.16 -r2.17
--- db_metaconfig.html	21 Jul 2003 17:58:55 -0000	2.16
+++ db_metaconfig.html	24 Jul 2003 17:28:59 -0000	2.17
@@ -74,6 +74,9 @@
 		=Select page display
 
 		height
+		extended.explicit_edit extended.number_list
+		extended.no_code_link extended.no_checkbox
+		extended.check_uncheck_all
 		extended.ui_sort_field
 		extended.ui_sort_option
 		extended.ui_sort_combined
@@ -142,6 +145,11 @@
 		height							=> 'Rows on select page',
 		'extended.bottom_buttons'		=> 'Buttons only on bottom',
 		'extended.restrict_allow'		=> 'Allow these ITL tags',
+		'extended.explicit_edit'		=> 'Show "edit record" link',
+		'extended.no_code_link'		    => "Don't link key column to editor",
+		'extended.no_checkbox'		    => "No checkbox for group ops",
+		'extended.check_uncheck_all'	=> 'Links to check/uncheck all',
+		'extended.number_list'		    => "Number the entries",
 		'extended.file_upload'			=> 'Allow file upload for this table',
 		'extended.filter_field'			=> 'Import field filtering',
 		'extended.left_width'			=> 'Width specification for label column',
@@ -248,6 +256,11 @@
 		height							=> 'text_5',
 		type							=> 'hidden',
 		'extended.restrict_allow'		=> 'text_40',
+		'extended.explicit_edit'		=> 'yesno',
+		'extended.no_code_link'			=> 'yesno',
+		'extended.no_checkbox'			=> 'yesno',
+		'extended.number_list'			=> 'yesno',
+		'extended.check_uncheck_all'	=> 'yesno',
 		'extended.file_upload'			=> 'yesno',
 		'extended.filter_field'			=> 'textarea_2_40',
 		'extended.tab_style'			=> 'textarea_5_40',
@@ -325,7 +338,7 @@
 
 	width=`{
 		'extended.ui_data_fields'		=> 30,
-		'extended.ui_show_fields'		=> 30,
+		'extended.ui_show_fields'		=> 50,
 	}`
 
 	form=`{
@@ -361,4 +374,4 @@
 
 ]
 @_UI_STD_FOOTER_@
-<!-- page: @@MV_PAGE@@ version: $Revision: 2.16 $ -->
+<!-- page: @@MV_PAGE@@ version: $Revision: 2.17 $ -->



2.9       +63 -2     interchange/dist/lib/UI/pages/admin/meta_editor.html


rev 2.9, prev_rev 2.8
Index: meta_editor.html
===================================================================
RCS file: /var/cvs/interchange/dist/lib/UI/pages/admin/meta_editor.html,v
retrieving revision 2.8
retrieving revision 2.9
diff -u -r2.8 -r2.9
--- meta_editor.html	2 Jul 2003 04:09:29 -0000	2.8
+++ meta_editor.html	24 Jul 2003 17:28:59 -0000	2.9
@@ -94,6 +94,7 @@
 	table="[cgi mv_data_table]"
 	no-table-meta=1
 	no-meta=1
+	start-at="[cgi start_at]"
 	default=`$Scratch->{tmp_defaults}`
 	ui_data_fields="
 		=Typical
@@ -123,19 +124,79 @@
 	   extended.lookup_merge
 	   lookup_exclude
 
+	   =Select page behavior
+
+	   extended.ui_more_alpha
+	   extended.ui_sort_option
+	   extended.fs_no_group
+	   extended.fs_display_filter
+	   extended.fs_link_page
+	   extended.fs_link_anchor
+	   extended.fs_link_parm
+	   extended.fs_link_parm_extra
+	   extended.fs_data_calc
+	   extended.fs_data_tables
+	   extended.header_row_class
+	   extended.data_row_class_odd
+	   extended.data_row_class_even
+	   extended.header_cell_class
+	   extended.header_cell_style
+	   extended.header_link_class
+	   extended.data_cell_class
+	   extended.data_cell_style
+
 	   =Advanced
 
 	   outboard
 	   pre_filter
 	   prepend
 	   append
-
+	   __UI_META_ADDITIONAL__
 	"
-	widget.extended="textarea_5_50"
+
+	options=`{
+		'extended.ui_sort_option' => qq{=--default--,f=Case insensitive, fr=Case insensitive/Reverse, n=Numeric, nr=Reverse Numeric},
+	}`
+
+	label=`{
+		'extended.ui_more_alpha' => 'Alphabetic more links',
+		'extended.ui_sort_option' => 'Sort option',
+		'extended.fs_no_group' => 'No group link',
+		'extended.fs_display_filter' => 'Filter(s) for select display',
+		'extended.fs_link_page' => 'Page to link to',
+		'extended.fs_link_anchor' => 'Anchor for link',
+		'extended.fs_link_parm' => 'Parameters to send as',
+		'extended.fs_link_parm_extra' => 'Additional parms to send (from CGI)',
+		'extended.fs_data_calc' => 'Embedded perl code to run on data',
+		'extended.fs_data_tables' => 'Tables to have open for perl code',
+		'extended.fs_display_calc' => 'Embedded perl code to run on header',
+		'extended.header_link_class' => 'Header row link CSS class',
+		'extended.header_cell_class' => 'Header cell CSS class',
+		'extended.header_cell_style' => 'Header cell CSS style',
+		'extended.header_row_class' => 'Header row CSS class',
+		'extended.header_row_style' => 'Header row CSS style',
+		'extended.data_row_class_odd' => 'Data row CSS class, odd numbers',
+		'extended.data_row_class_even' => 'Data row CSS class, even numbers',
+		'extended.data_cell_class' => 'Data cell CSS class',
+		'extended.data_cell_style' => 'Data cell CSS style',
+	}`
+	help=`{
+		'extended.fs_data_calc' => 'Current record passed as $item',
+		'extended.fs_data_tables' => 'To have open for Safe module',
+	}`
+	widget=`{
+		extended => "textarea_5_50",
+		'extended.ui_more_alpha' => 'yesno',
+		'extended.ui_sort_option' => 'select',
+		'extended.fs_no_group' => 'yesno',
+		'extended.fs_display_filter' => 'text_50',
+		'extended.fs_data_calc' => 'textarea_4_70',
+	}`
+
 	ui_style=1
 	output_map=1
 	tabbed=1
 	][/table-editor]
 
 @_UI_STD_FOOTER_@
-<!-- page: @@MV_PAGE@@ version: $Revision: 2.8 $ -->
+<!-- page: @@MV_PAGE@@ version: $Revision: 2.9 $ -->



2.22      +4 -650    interchange/dist/lib/UI/pages/admin/flex_select.html


rev 2.22, prev_rev 2.21
Index: flex_select.html
===================================================================
RCS file: /var/cvs/interchange/dist/lib/UI/pages/admin/flex_select.html,v
retrieving revision 2.21
retrieving revision 2.22
diff -u -r2.21 -r2.22
--- flex_select.html	22 Jun 2003 14:22:35 -0000	2.21
+++ flex_select.html	24 Jul 2003 17:28:59 -0000	2.22
@@ -1,27 +1,6 @@
+[flex-select init=1]
 
-<!-- [if cgi mv_more_ip]
-[calc]
-	for( qw/
-		help_name
-		icon_name
-		mv_data_table
-		page_title
-		ui_break_before
-		ui_show_fields
-		ui_sort_field
-		ui_sort_option
-		ui_description_fields
-		ui_flex_description
-		ui_flex_key
-		page_banner
-		/)
-	{
-		$CGI->{$_} = $Values->{$_};
-		push @out, "$_ = $CGI->{$_}";
-	}
-	return join "\n", @out;
-[/calc]
-[/if] -->
+[set table_perm]1[/set]
 
 [tmp page_title]
 	[either]
@@ -66,129 +45,10 @@
 [tmp help_name][either][cgi help_name][or]flex.select[/either][/tmp]
 [tmp icon_name][either][cgi icon_name][or]icon_config.gif[/either][/tmp]
 
-[if cgi mv_return_table]
-	[calc]
-		$CGI->{mv_data_table} = delete $CGI->{mv_return_table};
-		return;
-	[/calc]
-[/if]
-
-[if-mm function="!tables" table="[cgi mv_data_table]"]
-[tmp errorurl][area href="__UI_BASE__/error" secure="[either]@@UI_SECURE@@[or]__UI_SECURE__[/either]"][/tmp]
-[bounce href="[scratch errorurl]"]
-[/if-mm]
-
-<!-- sequence_edit: [cgi ui_sequence_edit] -->
-<!-- item_id_left: [cgi item_id_left] -->
-[perl tables="[cgi mv_data_table] __UI_META_TABLE__"]
-	delete $Scratch->{ui_location};
-	$Scratch->{ui_class} = $CGI->{ui_class}
-		if $CGI->{ui_class}
-		&&  $CGI->{ui_class} =~ /^\w+$/;
-
-	my $tab = $CGI->{mv_data_table} or return;
-	if($tab =~ s/\.(txt|asc)$/_$1/) {
-		$tab =~ s:.*/::;
-	}
-	my $db = $Db{$tab};
-	if(! $db) {
-		$Scratch->{ui_error} = errmsg('no %s database', $tab);
-		$Scratch->{ui_location} = $Tag->area({href=>"__UI_BASE__/error",
-            secure=>$Scratch->{page_secure}});
-		return;
-	}
-
-	delete $Scratch->{tmp_large};
-	if( $Variable->{UI_LARGE_TABLE} =~ /\b$tab\b/ or $db->config('LARGE') ) {
-		$Scratch->{tmp_large} = 1;
-	}
-
-	return unless $CGI->{item_id};
-	return unless delete $CGI->{deleterecords};
-	return unless $Tag->if_mm('tables', '=d');
-
-	delete $Scratch->{ui_location};
-	$Config->{NoSearch} = '';
-
-	for(grep $_, @{$CGI_array->{item_id}}) {
-		$db->delete_record($_)
-			or push @errors, $@;
-	}
-	if(@errors) {
-		my $plural = @errors > 1 ? 's' : '';
-		return "<span CLASS=error>Error$plural:<UL><LI>" .
-				join ("<LI>", @errors)                    .
-				"</UL></span><BR>";
-	}
-	return;
-[/perl]
-
-[calc]
-	delete $Scratch->{ui_location};
-	my $dest = $CGI->{ui_sequence_destination} || '__UI_BASE__/flex_editor';
-	if($CGI->{ui_sequence_edit}) {
-		my $doit;
-		if($CGI->{item_id_left} =~ s/^(.*?)[\0]//) {
-			$CGI->{ui_sequence_edit} = 1;
-			$CGI->{item_id} = $1;
-			$doit = 1;
-		}
-		elsif ($CGI->{item_id_left}) {
-			$CGI->{item_id} = delete $CGI->{item_id_left};
-			delete $CGI->{ui_sequence_edit};
-			$doit = 1;
-		}
-		else {
-			delete $CGI->{item_id};
-			delete $CGI->{ui_sequence_edit};
-		}
-		return unless $doit;
-		$Scratch->{ui_location}
-				= $Tag->area( {
-						href => $dest,
-						form => qq{
-							mv_data_table=$CGI->{mv_data_table}
-							item_id=$CGI->{item_id}
-							item_id_left=$CGI->{item_id_left}
-							ui_sequence_edit=$CGI->{ui_sequence_edit}
-						},
-					});
-		return;
-	}
-
-[/calc]
-
-<!-- ui_location: [scratch ui_location] -->
-[if scratch ui_location]
-[bounce href=`delete $Scratch->{ui_location}`]
-[elsif !cgi mv_data_table]
-[bounce page="__UI_BASE__/gentable"]
-[/elsif]
-[/if]
-
 @_UI_STD_HEAD_@
 [update values]
 <!-- ----- BEGIN REAL STUFF ----- -->
 
-[tmp extra_title]
-	[loop list="[cgi mv_data_table]"]
-		[if-loop-data __UI_META_TABLE__ name]
-		<B>[loop-data __UI_META_TABLE__ name]</B>
-		[/if-loop-data]
-		[if-loop-data __UI_META_TABLE__ help_url]
-		&nbsp;&nbsp;&nbsp;<small><A HREF="[loop-data __UI_META_TABLE__ help_url]">help</A></small>
-		[/if-loop-data]
-		[if-loop-data __UI_META_TABLE__ help]
-		<i>[loop-data __UI_META_TABLE__ name]</i>
-		[/if-loop-data]
-	[/loop]
-[/tmp]
-[calc]
-	$Scratch->{page_banner} ||= $Scratch->{page_title};
-	$Scratch->{page_banner} .= $Scratch->{extra_title};
-	return;
-[/calc]
-
 [output name=search_box]
 [if compare=`! $Config->{Database}{$CGI->{mv_data_table}}{HUGE}`]
 <FORM ACTION="[area href="[either][cgi ui_searchpage][or]@@MV_PAGE@@[/either]"]" METHOD=GET>
@@ -209,515 +69,9 @@
 [/if]
 [output name=""]
 
-[if scratch ui_failure]
-<blockquote class=cerror>
-	[scratchd ui_failure]
-</blockquote>
-[/if]
-
-[if scratch ui_message]
-	<blockquote class=cmessage>
-		[scratchd ui_message]
-	</blockquote>
-[/if]
-
-[if-mm !super]
-[tmp ui_owner][db-hash
-				table="__UI_ACCESS_TABLE__"
-				column="table_control::[cgi mv_data_table]::owner_field"
-				key="[data session username]"][/tmp]
-[/if-mm]
-
-[set tmp_nomatch_message]<B>[L]No records[/L].</b>[/set]
-[set tmp_like_spec][/set]
-[perl tables="[cgi mv_data_table] __UI_META_TABLE__"]
-	my $tab = $CGI->{mv_data_table};
-	my $ref = $Db{$tab};
-	my $meta = $Tag->meta_record($CGI->{mv_data_table}, $CGI->{ui_meta_view});
-	
-	if (! $ref) {
-		$Scratch->{keypos} = 0;
-		return;
-	}
-	elsif (! $meta) {
-		$Scratch->{keypos} = 0;
-	}
-
-	if( $tab ne $ref->config('name')) {
-		## Probably transient database
-		$CGI->{mv_data_table_real} = $tab = $ref->config('name');
-	}
-
-	$meta ||= {};
-
-	if($CGI->{ui_flex_key}) {
-		$Scratch->{keypos} = $CGI->{ui_flex_key};
-	}
-	else {
-		$Scratch->{keypos} = $ref->config('KEY_INDEX');
-	}
-	$Scratch->{keyname} = $ref->config('KEY');
-
-	if($CGI->{ui_exact_record}) {
-		undef $CGI->{mv_like_field};
-		my $id = $CGI->{mv_like_spec};
-		$id =~ s/\0.*//s;
-		my $url = $Tag->area({
-								href => 'admin/flex_editor',
-								form => qq{
-									mv_data_table=$CGI->{mv_data_table}
-									item_id=$id
-									ui_meta_view=$CGI->{ui_meta_view}
-								},
-							});
-
-		$Tag->deliver({ location => $url });
-		return;
-	}
-
-	$CGI->{ui_show_fields} ||= $meta->{ui_show_fields} || $meta->{field};
-	for(qw/ui_more_alpha ui_more_decade ui_meta_specific/) {
-		$CGI->{$_} ||= $meta->{$_};
-	}
-	$Config->{NoSearch} = '';
-	$ui_text_qualification = $CGI->{ui_text_qualification};
-	if ($ui_text_qualification and $CGI->{ui_text_qualification} =~ /[<!=>\^]/ ) {
-		if($Scratch->{ui_owner}) {
-			$CGI->{ui_text_qualification} = <<EOF;
-co=1
-st=db
-sf=$Scratch->{ui_owner}
-se=$Session->{username}
-op=eq
-nu=0
-os=0
-su=0
-bs=0
-EOF
-		}
-		else {
-			$CGI->{ui_text_qualification} = "co=1\n";
-		}
-
-		my @entries = split /\s+(and|or)\s+/i,  $ui_text_qualification;
-		my $or;
-		for(@entries) {
-			if(/^or$/i) {
-				$or = 1;
-				$CGI->{ui_text_qualification} .= "os=1\n";
-				next;
-			}
-			elsif(/^and$/i) {
-				$or = 0;
-				$CGI->{ui_text_qualification} .= "os=0\n";
-				next;
-			}
-			my ($f, $op, $s) = split /\s*([<=!>\^]+)\s*/, $_, 2;
-			$op = "eq" if $op eq "==";
-			$op = "rm" if $op eq "=";
-			if($op eq '^') {
-				$op = 'rm';
-				$CGI->{ui_text_qualification} .= "bs=1\nsu=1\n";
-			}
-			else {
-				$CGI->{ui_text_qualification} .= "bs=0\nsu=0\n";
-			}
-			if(length($s) > 1) {
-				$CGI->{ui_text_qualification} .= "se=$s\nsf=$f\nop=$op\n";
-			}
-			else {
-				$CGI->{ui_text_qualification} .= "se=.\nsf=$f\nop=rn\n";
-			}
-			if($op =~ /[<>]/ and $s =~ /^[\d.]+$/) {
-				$CGI->{ui_text_qualification} .= "nu=1\n";
-			}
-			else {
-				$CGI->{ui_text_qualification} .= "nu=0\n";
-			}
-		}
-		if(defined $or) {
-			$CGI->{ui_text_qualification} .= $or ? "os=1\n" : "os=0\n";
-		}
-
-		$out_message = errmsg('Entries matching "%s"', $ui_text_qualification);
-	}
-	elsif ($ui_text_qualification) {
-		$CGI->{ui_text_qualification} = "se=$CGI->{ui_text_qualification}";
-		$out_message = errmsg('Entries matching "%s"', $ui_text_qualification);
-		if($Scratch->{ui_owner}) {
-			$CGI->{ui_text_qualification} = <<EOF;
-co=1
-sf=$Scratch->{ui_owner}
-se=$Session->{username}
-op=eq
-sf=:*
-se=$CGI->{ui_text_qualification}
-EOF
-		}
-	}
-	elsif ( $CGI->{mv_like_field} ) {
-		my @f = split /\0/, $CGI->{mv_like_field};
-		my @s = split /\0/, $CGI->{mv_like_spec};
-		my @q = 'ra=yes';
-		my $found;
-		for(my $i = 0; $i < @f; $i++) {
-			next unless length $s[$i];
-			$found++;
-			push @q, "lf=$f[$i]";
-			push @q, "ls=$s[$i]";
-		}
-		if($found) { $CGI->{ui_text_qualification} = join "\n", @q; }
-		else	   { $CGI->{ui_text_qualification} = "" }
-	}
-	elsif($Scratch->{ui_owner}) {
-		$CGI->{ui_text_qualification} = <<EOF;
-co=1
-sf=$Scratch->{ui_owner}
-se=$Session->{username}
-op=eq
-EOF
-	}
-	elsif ($Scratch->{tmp_large}) {
-		my $keylabel = $Tag->display({
-							table => $tab,
-							name => 'item_id',
-							column => $Scratch->{keyname},
-							template => 1,
-						});
-		$Scratch->{tmp_like_spec} = 1;
-		$CGI->{ui_text_qualification} = "";
-	}
-	else {
-		$CGI->{ui_text_qualification} = "ra=yes";
-	}
-
-	if($meta->{ui_sort_combined} =~ /\S/) {
-		$meta->{ui_sort_field} = $meta->{ui_sort_combined};
-		$meta->{ui_sort_option} = '';
-	}
-
-	$CGI->{ui_sort_field}	||= $meta->{ui_sort_field}
-							||  $meta->{lookup}
-							||  $Scratch->{keyname};
-	$CGI->{ui_sort_option}	||= $meta->{ui_sort_option};
-	$CGI->{ui_sort_option}	=~ s/[\0,\s]+//g;
-	$CGI->{ui_list_size} = $meta->{height}
-		if ! $CGI->{ui_list_size};
-
-	if(! $CGI->{ui_show_fields} ) {
-		$CGI->{ui_show_fields} = 
-			$CGI->{ui_description_fields}
-				= join ",", $ref->columns();
-	}
-	else {
-		my $i = 0;
-		my $show = $CGI->{ui_show_fields};
-		$show =~ s/(\w+)(?:\((.*?)\))?/ ($filter_show[$i++] = $2), $1/eg;
-		$show =~ s/[\0,\s]+/,/g;
-		$CGI->{ui_description_fields} = $show;
-	}
-
-	@cols = grep $ref->column_exists($_), 
-				split /,/, $CGI->{ui_description_fields};
-
-	my %limit_field;
-
-	$CGI->{ui_limit_fields} =~ s/[\0,\s]+/ /g;
-	$CGI->{ui_limit_fields} =~ s/^\s+//;
-	$CGI->{ui_limit_fields} =~ s/\s+$//;
-
-	my (@limit_field) = split " ", $CGI->{ui_limit_fields};
-
-	if(@limit_field) {
-		@limit_field{@limit_field} = ();
-		@cols = grep ! exists($limit_field{$_}), @cols;
-	}
-
-	unshift(@cols, $Scratch->{keyname})
-		if $cols[0] ne $Scratch->{keyname};
-
-	for(@cols) {
-		$numeric{$_} = 1 if $ref->numeric($_);
-	}
-
-	$CGI->{ui_description_fields} = join ",", @cols;
-
-	unless ($CGI->{ui_sort_option}) { 
-		 $CGI->{ui_sort_option} = 'n'
-				if $ref->numeric($CGI->{ui_sort_field}); 
-	} 
-
-	my $fi = $CGI->{mv_data_table_real} || $CGI->{mv_data_table};
-	$Scratch->{sparams} = $Scratch->{tmp_like_spec} ? '' : <<EOF;
-
-	fi=$fi
-	st=db
-	$CGI->{ui_text_qualification}
-	su=1
-	ma=$CGI->{ui_more_alpha}
-	md=$CGI->{ui_more_decade}
-	ml=$CGI->{ui_list_size}
-	tf=$CGI->{ui_sort_field}
-	to=$CGI->{ui_sort_option}
-	rf=$CGI->{ui_description_fields}
-
-EOF
-	$Scratch->{page_banner} .= $out_message;
-	$Scratch->{page_title} .= $out_message;
-	return;
-[/perl]
-
-[tmpn tmp_ncols][/tmpn]
-<!-- tq: [scratch sparams] -->
-<table width="100%" border=0 cellpadding=0 cellspacing=1 class=rseparator>
-[output name=top_of_form]
-	<FORM ACTION="[area href="[either][cgi ui_searchpage][or]@@MV_PAGE@@[/either]"]" METHOD=GET>
-	<INPUT TYPE=hidden NAME=mv_data_table    VALUE="[cgi mv_data_table]">
-	<INPUT TYPE=hidden NAME=mv_action        VALUE=back>
-	[if cgi ui_meta_view]
-	[return-to]
-	<!-- got a return-to -->
-	[else]
-	<!-- got no return-to -->
-	<INPUT TYPE=hidden NAME=ui_meta_specific VALUE="[cgi ui_meta_specific]">
-	<INPUT TYPE=hidden NAME=ui_page_title    VALUE="[cgi ui_page_title]">
-	<INPUT TYPE=hidden NAME=ui_page_banner   VALUE="[cgi ui_page_banner]">
-	<INPUT TYPE=hidden NAME=ui_limit_fields VALUE="[cgi ui_limit_fields]">
-	<INPUT TYPE=hidden NAME=ui_show_fields VALUE="[cgi ui_show_fields]">
-	<INPUT TYPE=hidden NAME=ui_return_to     VALUE="@@MV_PAGE@@">
-	<INPUT TYPE=hidden NAME=ui_return_to     VALUE="mv_data_table=[cgi mv_data_table]">
-	[/else]
-	[/if]
-[output name=""]
-	<tr class=rhead>
-	<td class=rhead>&nbsp;</td>
-	[loop list="[cgi ui_description_fields]"]
-	<td class=rhead>
-    <table align="left" class=rhead cellspacing=2 cellpadding=0>
-    <tr>
-      <td align="right" valign="center">
-		<A HREF="[area href='__UI_BASE__/flex_group'
-						form='
-							mv_data_table=[cgi mv_data_table]
-							ui_meta_view=[cgi ui_meta_view]
-							mv_arg=[loop-code]
-						'
-					]"
-			title="[msg arg.0='[loop-code]']Select group by %s[/msg]"
-				><img src="smindex.gif" border=0></a>
-      </td>
-      <td align="left" valign="center" class=rhead>
-	  [calc]
-			my $f = '[loop-code]';
-			my $o = '';
-			my $msg;
-			my $rmsg;
-			if ($CGI->{ui_sort_field} eq $f and $CGI->{ui_sort_option} !~ /r/) {
-				$o .= 'r';
-				$msg = "sort by %s (%s)";
-				$rmsg = errmsg('reverse');
-			}
-			else {
-				$msg = "sort by %s";
-			}
-			$o .= 'n' if $numeric{$f};
-			$Scratch->{tmp_sort_msg} = errmsg($msg, $f, $rmsg);
-			$Scratch->{tmp_ncols}++;
-			$Scratch->{tmp_url} = $Tag->area( {
-											href => '@@MV_PAGE@@',
-											form => qq(
-									ui_text_qualification=$ui_text_qualification
-									mv_data_table=$CGI->{mv_data_table}
-									ui_meta_view=$CGI->{ui_meta_view}
-									ui_sort_field=$f
-									ui_sort_option=$o
-											),
-											});
-			return;
-		[/calc]
-		<a href="[scratch tmp_url]"
-			class=rhead
-			title="[scratch tmp_sort_msg]">[either][data table="__UI_META_TABLE__" column=label key="[cgi mv_data_table]::[loop-code]"][or][loop-code][/either]</A>
-      </td>
-    </tr>
-    </table>	
-	</td>
-	[/loop]
-	</tr>
-	[tmp tmp_url]
-		mv_data_table=[cgi mv_data_table]
-		ui_page_title=[cgi ui_page_title]
-		ui_meta_view=[cgi ui_meta_view]
-		ui_page_banner=[cgi ui_page_banner]
-		ui_meta_specific=[cgi ui_meta_specific]
-		[if cgi ui_return_to]
-		[and !cgi ui_return_stack]
-			[return-to formlink]
-		[else]
-			ui_return_to=@@MV_PAGE@@
-		[/else]
-		[/if][/tmp]
-	[search-region more=1
-		form="
-			ui_meta_specific=[cgi ui_meta_specific]
-			ui_meta_view=[cgi ui_meta_view]
-		" arg="[scratch sparams]"]
-	[search-list]
-	<tr [item-alternate 2]class=rownorm[else]class=rowalt[/else][/item-alternate]>
-
-	<td width="30"><INPUT TYPE=checkbox NAME=item_id VALUE="[item-code]"></td>
-	<td>[page href=__UI_BASE__/flex_editor form=|
-								[scratch tmp_url]
-							item_id=[item-code]
-						|][item-code]</A></TD>
-[item-sub show_line]
-sub {
-	my ($pre, $post) = split /\t/, shift;
-	my $line = shift;
-	return unless $line;
-	shift (@$line);
-	my $out = '';
-	my $i = 1;
-	for(@$line) {
-		my $filter = $filter_show[$i] || '';
-		$filter .= ' encode_entities' unless $filter =~ /\b(?:encode_)?entities\b/;
-
-		my $extra = '';
-		$extra .= " $1" while $filter =~ s/(v?align=\w+)//i;
-
-		$_ = $Tag->filter($filter, $_);
-		s/\[/&#91;/g;
-		$out .= "<TD$extra>$_</TD>";
-		$i++;
-	}
-	return $out . "\n";
-}
-[/item-sub]
-[item-exec show_line][/item-exec]
-</tr>
-[/search-list]
-[no-match]
-<tr>
-<td colspan="[scratch tmp_ncols]" align=left>
-[scratchd tmp_nomatch_message]
-</td>
-</tr>
-[if scratch tmp_like_spec]
-	<tr>
-	<td>&nbsp;</td>
-	<td colspan="[scratch tmp_ncols]" align=left>
-	[L]Check the box for exact record and enter the record id/key.[/L]
-	[L]Or enter a query by example to select a set of records.[/L]
-	[L]Each input will match on the <i>beginning</i> text in the field.[/L]
-	<p>
-	<small><input type=checkbox name=ui_exact_record value=1 class=s3> Edit exact record in key column</small>
-	<br>
-	&nbsp;
-	</td>
-	</tr>
-	<tr>
-	<td>&nbsp;</td>
-	[loop list="[cgi ui_description_fields]"]
-	<TD>
-		<input type=hidden name=mv_like_field value="[loop-code]">
-		<input type=text name=mv_like_spec size=10>
-	</td>
-	[/loop]
-	</tr>
-	<tr>
-	<td>&nbsp;</td>
-	<td colspan="[scratch tmp_ncols]" align=left>
-	&nbsp;
-	<br>
-	&nbsp;
-	<br>
-	<input type=submit value="[L]Find[/L]">
-	</td>
-	</tr>
-[/if]
-[/no-match]
-[more-list]
-<tr>
-<td colspan=6 align=center>
-[L]More rows[/L]: [decade-next][/decade-next] [more] [decade-prev][/decade-prev]
-</td>
-</tr>
-[/more-list]
-</table>
-
-[on-match]
-
-[output name=top_buttons]
-[button text="[L]Edit checked records in sequence[/L]" extra=" class=s2"]
-ui_sequence_edit=[calc]
-	$CGI->{item_id_left} = $CGI->{item_id};
-	$CGI->{item_id_left} =~ s/\0+/,/g;
-	if($CGI->{item_id_left} =~ s/^(.*?),//) {
-		$CGI->{item_id} = $1;
-		return 1;
-	}
-	else {
-		delete $CGI->{item_id_left};
-		return '';
-	}
-[/calc]
-mv_nextpage=admin/flex_editor
-mv_todo=return
-[/button]
-
-[output name=bottom_buttons]
-[button text="[L]Edit checked records in sequence[/L]" extra=" class=s2"]
-ui_sequence_edit=[calc]
-	$CGI->{item_id_left} = $CGI->{item_id};
-	$CGI->{item_id_left} =~ s/\0+/,/g;
-	if($CGI->{item_id_left} =~ s/^(.*?),//) {
-		$CGI->{item_id} = $1;
-		return 1;
-	}
-	else {
-		delete $CGI->{item_id_left};
-		return '';
-	}
-[/calc]
-mv_nextpage=admin/flex_editor
-mv_todo=return
-[/button]
-
-[output]
-
-[if-mm function="tables" table="[cgi mv_data_table]=d"]
-
-[output name=top_buttons]
-&nbsp;&nbsp;&nbsp;&nbsp;
-[button text="[L]Delete checked records[/L]"
-		extra="class=s2"
-		confirm="[L]Are you sure you want to delete the checked records?[/L]"]
-[flag type=write table="[cgi mv_data_table]"]
-deleterecords=1
-mv_click=db_maintenance
-[/button]
-
-[output name=bottom_buttons]
-&nbsp;&nbsp;&nbsp;&nbsp;
-[button text="[L]Delete checked records[/L]"
-		extra="class=s2"
-		confirm="[L]Are you sure you want to delete the checked records?[/L]"]
-[flag type=write table="[cgi mv_data_table]"]
-deleterecords=1
-mv_click=db_maintenance
-[/button]
-[output name=""]
-
-[/if-mm]
-
-[/on-match]
-[/search-region]
-
-[output name=bottom_of_form]
-</FORM>
-[output name=""]
+[flex-select]
 
 <!-- ----- END REAL STUFF ----- -->
 
 @_UI_STD_FOOTER_@
-<!-- page: @@MV_PAGE@@ Revision: $Id: flex_select.html,v 2.21 2003/06/22 14:22:35 mheins Exp $ -->
+<!-- page: @@MV_PAGE@@ Revision: $Id: flex_select.html,v 2.22 2003/07/24 17:28:59 mheins Exp $ -->



1.1                  interchange/code/UI_Tag/flex_select.coretag


rev 1.1, prev_rev 1.0
Index: flex_select.coretag
===================================================================
UserTag flex-select Order table
UserTag flex-select addAttr
UserTag flex-select attrAlias  ml height
UserTag flex-select hasEndTag
UserTag flex-select Routine <<EOR
use vars qw/$CGI $Tmp $Tag/;
my @fs_more = qw/
	help_name
	icon_name
	page_banner
	page_title
	ui_break_before
	ui_description_fields
	ui_flex_description
	ui_flex_key
	ui_show_fields
	ui_sort_field
	ui_sort_option
/;
sub flex_select_init {
	my ($table, $opt) = @_;

	my @warnings;
	my @errors;

#::logDebug("Entering flex_select init");
	if($CGI->{mv_more_ip}) {
		for(@fs_more) {
			$CGI->{$_} = $::Values->{$_};
		}
	}
	if($CGI->{mv_return_table}) {
		$CGI->{mv_data_table} = delete $CGI->{mv_return_table};
	}

	my $bounce_url;
	$::Scratch->{ui_class} = $CGI->{ui_class}
		if $CGI->{ui_class} &&  $CGI->{ui_class} =~ /^\w+$/;

	if($table =~ s/\.(txt|asc)$/_$1/) {
		$table =~ s:.*/::;
	}
	my $db = database_exists_ref($table);

	$Tmp->{flex_select} ||= {};
	my $ts = $Tmp->{flex_select}{$table} = {};

	if(! $db) {
		$Tag->error({
						name => 'flex_select',
						set =>  errmsg('no %s database', $table),
					});
		my $url = $Tag->area( {
							href => $::Variable->{UI_ERROR_PAGE} || 'admin/error',
							secure => $::Variable->{UI_SECURE},
						});
		$Tag->deliver( { location => $url });
		return;
	}

	if( $::Variable->{UI_LARGE_TABLE} =~ /\b$table\b/ or $db->config('LARGE') ) {
		$ts->{large} = 1;
	}

	DELETE: {
		last DELETE unless $CGI->{item_id};
		last DELETE unless delete $CGI->{deleterecords};
		unless ($Tag->if_mm('tables', '=d')) {
			$Tag->error({
							name => 'flex_select',
							set => errmsg("no permission to delete records"),
						});
			last DELETE;
		};

		$Vend::Cfg->{NoSearch} = '';

		my @ids = split /\0/, $CGI->{item_id};
		for(grep $_, @ids) {
			if($db->delete_record($_)) {
				push @warnings, errmsg("Deleted record %s", $_);
			}
			else {
				push @errors, $db->errstr();
			}
		}
	}

	SEQUENCE: {
		my $dest = $CGI->{ui_sequence_destination} || '__UI_BASE__/flex_editor';
#::logDebug("Entering flex_select sequence edit stuff");
		last SEQUENCE unless $CGI->{ui_sequence_edit};
		my $doit;
		if($CGI->{item_id_left} =~ s/^(.*?)[\0]//) {
			$CGI->{ui_sequence_edit} = 1;
			$CGI->{item_id} = $1;
			$doit = 1;
		}
		elsif ($CGI->{item_id_left}) {
			$CGI->{item_id} = delete $CGI->{item_id_left};
			delete $CGI->{ui_sequence_edit};
			$doit = 1;
		}
		else {
			delete $CGI->{item_id};
			delete $CGI->{ui_sequence_edit};
		}
		last SEQUENCE unless $doit;
		my $url = $Tag->area( {
									href => $dest,
									form => qq{
										mv_data_table=$CGI->{mv_data_table}
										item_id=$CGI->{item_id}
										item_id_left=$CGI->{item_id_left}
										ui_sequence_edit=$CGI->{ui_sequence_edit}
									},
								});
#::logDebug("flex_select sequence developed URL=$url");
		$Tag->deliver( { location => $url } );
		return;
	}

	$ts->{table_meta} = $Tag->meta_record($table, $CGI->{ui_meta_view}) || {};
	my $tm = $ts->{table_meta};
	
	my $extra;
	if($tm->{name}) {
		$extra .= "<b>$tm->{name}</br>";
	}
	if($ts->{help_url}) {
		$extra .= qq{&nbsp;&nbsp;&nbsp;<small><A HREF="$ts->{help_url}">};
		$extra .= errmsg('help');
		$extra .= "</A></small>";
	}
	if($ts->{help}) {
		$extra .= "<blockquote>$ts->{help}</blockquote>";
	}
	$::Scratch->{page_banner} ||= $::Scratch->{page_title};
	$::Scratch->{page_banner} .= $extra;

	for(@errors) {
		$Tag->error({ name => 'flex_select', set => $_ });
	}
	for(@warnings) {
		$Tag->warnings($_);
	}
	return;
}

sub {
	my ($table, $opt, $body) = @_;

	my $CGI = \%CGI::values;

	$table ||= $CGI->{mv_data_table};

	## Do the initialization
	if($opt->{init}) {
		return flex_select_init($table, $opt);
	}

	my $ref = dbref($table)
		or do {
			my $msg = errmsg("%s: table '%s' does not exist", 'flex_select', $table);
			logError($msg);
			$Tag->error({ name => 'flex_select', set => $msg });
			return undef;
		};
	my $ts = $Tmp->{flex_select}{$table} ||= {};
	my $meta = $ts->{table_meta} ||= $Tag->meta_record($table, $CGI->{ui_meta_view});
	
	if( $table ne $ref->config('name')) {
		## Probably transient database
		$CGI->{mv_data_table_real} = $table = $ref->config('name');
	}

	$meta ||= {};

	if($CGI->{ui_flex_key}) {
		$ts->{keypos} = $CGI->{ui_flex_key};
	}
	else {
		$ts->{keypos} = $ref->config('KEY_INDEX');
	}

	$ts->{keyname} = $ref->config('KEY');
	$ts->{owner_field} = $ref->config('OWNER_FIELD') || $::Scratch->{ui_owner};

	if($CGI->{ui_exact_record}) {
		undef $CGI->{mv_like_field};
		my $id = $CGI->{mv_like_spec};
		$id =~ s/\0.*//s;
		my $url = $Tag->area({
								href => 'admin/flex_editor',
								form => qq{
									mv_data_table=$CGI->{mv_data_table}
									item_id=$id
									ui_meta_view=$CGI->{ui_meta_view}
								},
							});

		$Tag->deliver({ location => $url });
		return;
	}

	$CGI->{ui_show_fields} ||= $meta->{ui_show_fields} || $meta->{field};

	my $sf;
	if($sf = $CGI->{ui_sort_field} and $sf =~ s/^(\w+)([,\s\0]+.*)?$/$1/) {
		my $fmeta;
		$fmeta = $Tag->meta_record("${table}::$sf", $CGI->{ui_meta_view})
			and do {
				$CGI->{ui_more_alpha} = $fmeta->{ui_more_alpha}
					if length($fmeta->{ui_more_alpha});
				if (! $CGI->{ui_sort_option} and length($fmeta->{ui_sort_option}) ) {
					my $o = $fmeta->{ui_sort_option};
					if($CGI->{ui_sort_option} =~ /r/) {
						$o =~ s/^([^r]+)$/$1r/
							or $o =~ s/r//;
					}
					$CGI->{ui_sort_option} = $o;
				}
			};
	}

	for(qw/ui_more_alpha ui_more_decade ui_meta_specific/) {
		$CGI->{$_} = $meta->{$_} unless defined $CGI->{$_};
	}
	$Vend::Cfg->{NoSearch} = '';
	my $out_message = '';
	my $ui_text_qualification = $CGI->{ui_text_qualification};

	if ($ui_text_qualification and $CGI->{ui_text_qualification} =~ /[<!=>\^]/ ) {
		if($ts->{owner_field}) {
			$CGI->{ui_text_qualification} = <<EOF;
co=1
st=db
sf=$ts->{owner_field}
se=$Vend::username
op=eq
nu=0
os=0
su=0
bs=0
EOF
		}
		else {
			$CGI->{ui_text_qualification} = "co=1\n";
		}

		my @entries = split /\s+(and|or)\s+/i,  $ui_text_qualification;
		my $or;
		for(@entries) {
			if(/^or$/i) {
				$or = 1;
				$CGI->{ui_text_qualification} .= "os=1\n";
				next;
			}
			elsif(/^and$/i) {
				$or = 0;
				$CGI->{ui_text_qualification} .= "os=0\n";
				next;
			}
			my ($f, $op, $s) = split /\s*([<=!>\^]+)\s*/, $_, 2;
			$op = "eq" if $op eq "==";
			$op = "rm" if $op eq "=";
			if($op eq '^') {
				$op = 'rm';
				$CGI->{ui_text_qualification} .= "bs=1\nsu=1\n";
			}
			else {
				$CGI->{ui_text_qualification} .= "bs=0\nsu=0\n";
			}
			if(length($s) > 1) {
				$CGI->{ui_text_qualification} .= "se=$s\nsf=$f\nop=$op\n";
			}
			else {
				$CGI->{ui_text_qualification} .= "se=.\nsf=$f\nop=rn\n";
			}
			if($op =~ /[<>]/ and $s =~ /^[\d.]+$/) {
				$CGI->{ui_text_qualification} .= "nu=1\n";
			}
			else {
				$CGI->{ui_text_qualification} .= "nu=0\n";
			}
		}
		if(defined $or) {
			$CGI->{ui_text_qualification} .= $or ? "os=1\n" : "os=0\n";
		}

		$out_message = errmsg('Entries matching "%s"', $ui_text_qualification);
	}
	elsif ($ui_text_qualification) {
		$CGI->{ui_text_qualification} = "se=$CGI->{ui_text_qualification}";
		$out_message = errmsg('Entries matching "%s"', $ui_text_qualification);
		if($ts->{owner_field}) {
			$CGI->{ui_text_qualification} = <<EOF;
co=1
sf=$ts->{owner_field}
se=$Vend::username
op=eq
sf=:*
se=$CGI->{ui_text_qualification}
EOF
		}
	}
	elsif ( $CGI->{mv_like_field} ) {
		my @f = split /\0/, $CGI->{mv_like_field};
		my @s = split /\0/, $CGI->{mv_like_spec};
		my @q = 'ra=yes';
		my $found;
		for(my $i = 0; $i < @f; $i++) {
			next unless length $s[$i];
			$found++;
			push @q, "lf=$f[$i]";
			push @q, "ls=$s[$i]";
		}
		if($found) { $CGI->{ui_text_qualification} = join "\n", @q; }
		else	   { $CGI->{ui_text_qualification} = "" }
	}
	elsif($ts->{owner_field}) {
		$CGI->{ui_text_qualification} = <<EOF;
co=1
sf=$ts->{owner_field}
se=$Vend::username
op=eq
EOF
	}
	elsif ($ts->{large}) {
		my $keylabel = $Tag->display({
							table => $table,
							name => 'item_id',
							column => $ts->{keyname},
							template => 1,
						});
		$ts->{like_spec} = 1;
		$CGI->{ui_text_qualification} = "";
	}
	else {
		$CGI->{ui_text_qualification} = "ra=yes";
	}

	if($meta->{ui_sort_combined} =~ /\S/) {
		$meta->{ui_sort_field} = $meta->{ui_sort_combined};
		$meta->{ui_sort_option} = '';
	}

	$CGI->{ui_sort_field}	||= $meta->{ui_sort_field}
							||  $meta->{lookup}
							||  $ts->{keyname};
	$CGI->{ui_sort_option}	||= $meta->{ui_sort_option};
	$CGI->{ui_sort_option}	=~ s/[\0,\s]+//g;
	$CGI->{ui_list_size} = $opt->{height} || $meta->{height}
		if ! $CGI->{ui_list_size};


	my @labels;          ## Locally set labels in ui_show_fields
	my @views;           ## Locally set view data in ui_show_fields
	my @filter_show;     ## Locally set filters in ui_show_fields
	my @calcs;           ## Data calculation code (if any) from fs_data_calc
	my @redirect;        ## A column with a different metadata from standard
	my @extras;          ## A column with a different metadata from standard
	my @style;           ## Style for data cell, only have to read once
	my @link_page;       ## Locally set filters in ui_show_fields
	my @link_parm;       ## Locally set filters in ui_show_fields
	my @link_parm_extra; ## Locally set filters in ui_show_fields
	my @link_anchor;     ## Locally set filters in ui_show_fields

	if(! $CGI->{ui_show_fields} ) {
		$CGI->{ui_show_fields} = 
			$CGI->{ui_description_fields}
				= join ",", $ref->columns();
	}
	else {
		my $i = 0;
		my $show = $CGI->{ui_show_fields};
		if($show =~ s/[\r\n]+/\n/g) {
			$show =~ s/^\s+//;
			$show =~ s/\s+$//;
			my @f = split /\n/, $show;
			my @c;
			for(@f) {
				s/^\s+//;
				s/\s+$//;
				if(s/\s*\((.+)\)\s*$//)  {
					$filter_show[$i] = $1;
				}
				
				if(/^(\w+)-(\w+)$/) {
					push @c, $1;
					$redirect[$i] = $2;
				}
				elsif(/^(\w+)(?:-([^=]+))?(?:=(.*))?/) {
					push @c, $1;
					$views[$i] = $2 if $2;
					$labels[$i] = $3;
				}
				else {
					push @c, $_;
				}
				$i++;
			}
			$show = join ",", @c;
		}
		else {
			$show =~ s/(\w+)(?:\((.*?)\))?/ ($filter_show[$i++] = $2), $1/eg;
			$show =~ s/[\0,\s]+/,/g;
		}
		$CGI->{ui_description_fields} = $show;
	}

	my @cols = grep $ref->column_exists($_), 
				split /,/, $CGI->{ui_description_fields};

	my %limit_field;

	$CGI->{ui_limit_fields} =~ s/[\0,\s]+/ /g;
	$CGI->{ui_limit_fields} =~ s/^\s+//;
	$CGI->{ui_limit_fields} =~ s/\s+$//;

	my (@limit_field) = split " ", $CGI->{ui_limit_fields};

	if(@limit_field) {
		@limit_field{@limit_field} = ();
		@cols = grep ! exists($limit_field{$_}), @cols;
	}

	unshift(@cols, $ts->{keyname})
		if $cols[0] ne $ts->{keyname};

	$CGI->{ui_description_fields} = join ",", @cols;

	unless ($CGI->{ui_sort_option}) { 
		 $CGI->{ui_sort_option} = 'n'
				if $ref->numeric($CGI->{ui_sort_field}); 
	} 

	my $fi = $CGI->{mv_data_table_real} || $CGI->{mv_data_table};
	$ts->{sparams} = $ts->{like_spec} ? '' : <<EOF;

	fi=$fi
	st=db
	$CGI->{ui_text_qualification}
	su=1
	ma=$CGI->{ui_more_alpha}
	md=$CGI->{ui_more_decade}
	ml=$CGI->{ui_list_size}
	tf=$CGI->{ui_sort_field}
	to=$CGI->{ui_sort_option}
	rf=$CGI->{ui_description_fields}

EOF
	$::Scratch->{page_banner} .= $out_message;
	$::Scratch->{page_title} .= $out_message;

	my %output;
### Header determination

	my @refkeys = grep ref($opt->{$_}) eq 'HASH', keys %$opt;

	my %default = (
		data_cell_class   => '',
		data_cell_style   => '',
		data_row_class_even   => 'rownorm',
		data_row_class_odd   => 'rowalt',
		data_row_style_even   => '',
		data_row_style_odd   => '',
		form_method => 'GET',
		explicit_edit => '',
		no_code_link => '',
		group_image   => 'smindex.gif',
		group_class   => 'rhead',
		group_spacing   => 2,
		group_padding   => 0,
		group_width   => '100%',
		header_link_class   => 'rhead',
		header_cell_class   => 'rhead',
		header_cell_style   => '',
		header_row_class   => 'rhead',
		header_row_style   => '',
		mv_action => 'back',
		meta_image => errmsg('meta.png'),
		label => "flex_select_$table",
		no_checkbox => 0,
		check_uncheck_all => 0,
		number_list => 0,
		table_border  => 0,
		table_class   => 'rseparator',
		table_padding => 0,
		table_spacing => 1,
		table_style   => '',
		table_width   => '100%',
	);

	for(keys %default) {
		next if defined $opt->{$_};
		if(length $meta->{$_}) {
			$opt->{$_} = $meta->{$_};
		}
		else {
			$opt->{$_} = $default{$_};
		}
	}

	$opt->{ui_style} = 1 unless defined $opt->{ui_style};

	my $show_meta;
	my $meta_anchor;
	if($Tag->if_mm('super') and ! $opt->{no_meta}) {
		$show_meta = defined $::Values->{ui_meta_force}
					? $::Values->{ui_meta_force}
					: $::Variable->{UI_META_SELECT};
		if($opt->{meta_image}) {
			$meta_anchor = qq{<img src="$opt->{meta_image}" border=0>};
		}
		else {
			$meta_anchor = 'M';
		}
	}

	$opt->{form_name} ||= "fs_$table";

	$output{TOP_OF_TABLE} = <<EOF;
<table width="$opt->{table_width}" border="$opt->{table_border}" cellpadding="$opt->{table_padding}" cellspacing="$opt->{table_spacing}" class="$opt->{table_class}">
EOF

	my $cwp = $Global::Variable->{MV_PAGE};
	$opt->{form_href} ||= $CGI->{ui_searchpage} || $cwp;
	$opt->{form_extra} ||= '';
	$opt->{form_extra} .= qq{ name="$opt->{form_name}"} if $opt->{form_name};
	$opt->{form_extra} =~ s/^\s*/ /;
	my $action = $Tag->process({href => $opt->{form_href}});

	$output{TOP_OF_FORM} = <<EOF;
<form action="$action" method="$opt->{form_method}"$opt->{form_extra}>
<INPUT TYPE=hidden NAME=mv_data_table    VALUE="$table">
<INPUT TYPE=hidden NAME=mv_action        VALUE="$opt->{mv_action}">
EOF

	### What the heck is going on here?
	if($CGI->{ui_meta_view}) {
		$output{TOP_OF_FORM} .= $Tag->return_to();
	}
	else {
		$output{TOP_OF_FORM} .= <<EOF;
	<!-- got no return-to -->
<input type=hidden name=ui_meta_specific value="$CGI->{ui_meta_specific}">
<input type=hidden name=ui_page_title    value="$CGI->{ui_page_title}">
<input type=hidden name=ui_page_banner   value="$CGI->{ui_page_banner}">
<input type=hidden name=ui_limit_fields  value="$CGI->{ui_limit_fields}">
<input type=hidden name=ui_show_fields   value="$CGI->{ui_show_fields}">
<input type=hidden name=ui_return_to     value="$cwp">
<input type=hidden name=ui_return_to     value="mv_data_table=$table">
EOF
	}

	my $cc = $ts->{column_meta} ||= {};
	my $mview = $CGI->{ui_meta_view};

	my $cmeta = sub {
		my $col = shift;
		return $cc->{$col} if $cc->{$col};
		my $m = $Tag->meta_record("${table}::$col", $mview);
		for(@refkeys) {
			$m->{$_} = $opt->{$_}{$col} if exists $opt->{$_}{$col};
		}
		$cc->{$col} = $m;
		return $m;
	};

	my $header_cell_style = sub {
				my $col = shift;
				my $m = $cmeta->($col);
#::logDebug("meta for header=" . ::uneval($m));
				my $stuff = '';
				for(qw/ class style align valign /) {
					my $tag = "header_cell_$_";
					my $thing = $m->{$tag} || $opt->{$tag}
						or next;
					encode_entities($thing);
					$stuff .= qq{ $_="$thing"};
				}
				return $stuff;
			};

	my $data_cell_style = sub {
				my $col = shift;
				my $m = $cmeta->($col);
				my $stuff = '';
				for(qw/ class style align valign /) {
					my $tag = "data_cell_$_";
					my $thing = $m->{$tag} || $opt->{$tag}
						or next;
					encode_entities($thing);
					$stuff .= qq{ $_="$thing"};
				}
				return $stuff;
			};

	my @head;
	my $rc = $opt->{header_row_class};
	push @head, "<tr ";
	push @head, qq( class=$opt->{header_row_class}) if $opt->{header_row_class};
	push @head, qq( style=$opt->{header_row_style}) if $opt->{header_row_style};
	push @head, ">\n";
	if(! $opt->{no_checkbox}) {
		push @head, "	<td class=rhead>&nbsp;</td>" 
	}
	if($opt->{number_list}) {
		push @head, "	<td class=rhead align=right>#&nbsp;</td>" ;
	}
	if($opt->{explicit_edit}) {
		push @head, "	<td class=rhead>&nbsp;</td>" 
	}

	my $return = <<EOF;
ui_return_to=$cwp
ui_return_to=ui_meta_view=$opt->{ui_meta_view}
ui_return_to=mv_return_table=$table
mv_return_table=$table
ui_return_stack=$CGI->{ui_return_stack}
start_at=extended.ui_more_alpha
EOF

	my $idx = 0;
	foreach my $col (@cols) {
		my $mcol = $col;
		if($redirect[$idx]) {
			$mcol .= "-$redirect[$idx]";
		}
		my $td_extra = $header_cell_style->($mcol);

		## $cc is set in header_cell_class 
		my $m = $cc->{$mcol};

		push @head, <<EOF;
<td$td_extra>
<table align="left" class="$opt->{group_class}" cellspacing=$opt->{group_spacing} cellpadding=$opt->{group_padding} width="$opt->{group_width}">
    <tr>
EOF
		unless($opt->{no_group} || $m->{fs_no_group}) {
			my $u = $Tag->area({
								href => 'admin/flex_group',
								form => qq(
											mv_data_table=$table
											ui_meta_view=$mview
											mv_arg=$col
										),
							});
			my $msg = errmsg('Select group by %s', $col);

			push @head, <<EOF;
      <td align="right" valign="center" width=1>
		<A HREF="$u" title="$msg"><img src="$opt->{group_image}" border=0></a>
      </td>
EOF

		}

		my $o = '';
		my $msg;
		my $rmsg;
		if($o = $m->{ui_sort_option}) {
			my @m;
			$msg = "sort by %s (%s)";
#::logDebug("sort field=$col, meta sort_option=$o, ui_sort_option=$CGI->{ui_sort_option}");
			if($CGI->{ui_sort_field} eq $col) {
				if($CGI->{ui_sort_option} =~ /r/) {
					$o =~ s/r//;
				}
				else {
					$o .= "r";
				}
#::logDebug("sort field=$col, sort_option now=$o, sort_option=$CGI->{ui_sort_option}");
			}
			push @m, errmsg('reverse') if $o =~ /r/;
			push @m, errmsg('case insensitive') if $o =~ /f/;
			push @m, errmsg('numeric') if $o =~ /n/;
			$rmsg = join ", ", @m;
		}
		else {
			if ($CGI->{ui_sort_field} eq $col and $CGI->{ui_sort_option} !~ /r/) {
				$o .= 'r';
				$msg = "sort by %s (%s)";
				$rmsg = errmsg('reverse');
			}
			else {
				$msg = "sort by %s";
			}
			$o .= 'n' if $ref->numeric($col);
		}
		my $sort_msg = errmsg($msg, $col, $rmsg);
		my $url = $Tag->area( {
								href => $cwp,
								form => qq(
									ui_text_qualification=$ui_text_qualification
									mv_data_table=$table
									ui_meta_view=$mview
									ui_sort_field=$col
									ui_sort_option=$o
									ui_more_alpha=$m->{ui_more_alpha}
								),
							});

		my $lab = $labels[$idx] || $m->{label} || $col;

		# Set up some stuff for the data cells;
		$style[$idx] = $data_cell_style->($mcol);
		$filter_show[$idx] ||= $m->{fs_display_filter} || 'encode_entities';
		$filter_show[$idx] .= ' encode_entities'
			 unless $filter_show[$idx] =~ /\b(?:encode_)?entities\b/;
		$style[$idx] .= " $1" while $filter_show[$idx] =~ s/(v?align=\w+)//i;

		if($views[$idx]) {
			my ($page, $parm, $l) = split /:/, $views[$idx];
			$m->{fs_link_page} = $page;

			$parm ||= 'item_id';
			my @p = split /[\s,\0]+/, $parm;
			my $arg = shift @p;
			$m->{fs_link_parm} = $arg;
			$m->{fs_link_parm_extra} = join ",", @p;
			$m->{fs_link_anchor} = $l;
		}

		if($m->{fs_link_page}) {
			$link_page[$idx]		= $m->{fs_link_page};
			$link_parm[$idx]		= $m->{fs_link_parm};
			if($m->{fs_link_parm_extra}) {
				my @p = grep /\S/, split /[\s,\0]+/, $m->{fs_link_parm_extra};
				$link_parm_extra[$idx]	= \@p;
			}
			$link_anchor[$idx]	= $m->{fs_link_anchor};
		}

		if(my $prog = $m->{fs_data_calc}) {
#::logDebug("looking at calcs=$prog");
			$prog =~ s/^\s+//;
			$prog =~ s/\s+$//;
			if($prog =~ /^\w+$/) {
				$calcs[$idx] = $Vend::Cfg->{Sub}{$prog} || $Global::GlobalSub->{$prog};
			}
			else {
				$prog =~ s/^\[(calc|perl)(.*?)\]//;
				$prog =~ s{\[/(calc|perl)\]$}{};
				$calcs[$idx] = $prog;
			}
			if($m->{fs_data_tables}) {
				tag_perl($m->{fs_data_tables}, {});
			}
		}

		push @head, <<EOF;
	  <td$td_extra>
		<a href="$url" class=$opt->{header_link_class} title="$sort_msg">$lab</A>
      </td>
EOF

		if($show_meta) {
			my $u = $Tag->area({ href=>'admin/meta_editor',
								 form => qq(
								 item_id=${table}::$mcol
								 ui_meta_view=$mview
								 $return),
								});
			my $tit = errmsg(
							"Edit header meta information for %s::%s",
							$table,
							$col,
						);
			push @head, <<EOF;
<td width=1>
<a href="$u" title="$tit">$meta_anchor</a>
</td>
EOF

		}

		push @head, <<EOF;
    </tr>
    </table>	
	</td>
EOF

		$idx++;
	}
	push @head, "</tr>";

	my $ncols = $idx;
	$ncols++ if $opt->{explicit_edit};
	$ncols++ if $opt->{number_list};
	$ncols++ unless $opt->{no_checkbox};

	$output{HEADER_AREA} = join "", @head;
### Row output

	my $cb_width = $opt->{checkbox_width} || '30';
	my $cb_name = $opt->{checkbox_name} || 'item_id';
	my $edit_page = $opt->{edit_page} || 'admin/flex_editor';
	my $edit_parm = $opt->{edit_parm} || 'item_id';
	my $edit_extra = <<EOF;
mv_data_table=$table
ui_page_title=$CGI->{ui_page_title}
ui_meta_view=$mview
ui_page_banner=$CGI->{ui_page_banner}
ui_meta_specific=$CGI->{ui_meta_specific}
EOF

	
	my @rows;

	if($body =~ /\S/) {
		my $o = { 
					label		=> $opt->{label},
					list_prefix	=> 'flex',
					prefix		=> 'flex',
					more		=> 1,
					search		=> $ts->{sparams},
				};
		push @rows, tag_loop_list($o);
	}
	else {
		my $ary;
		my $search;
		my $params;
		my $c;
#::logDebug("MM=$CGI->{MM}($CGI::values{MM}) mv_more_matches=$CGI->{mv_more_matches}($CGI::values{mv_more_matches})");
		if($CGI->{mv_more_ip}) {
			$search = $::Instance->{SearchObject}{$opt->{label}};
			$search ||= $::Instance->{SearchObject}{''};
			$search ||= perform_search();
			$ary = [ splice(
						@{$search->{mv_results}},
						$search->{mv_first_match},
						$search->{mv_matchlimit},
						)] ;
#::logDebug("search first_match=$search->{mv_first_match} length=$search->{mv_matchlimit}");
#::logDebug("Found search=" . ::uneval($search));
		}
		else {
#::logDebug("In new search");
			$params = escape_scan($ts->{sparams});
			$c = { mv_search_immediate => 1, mv_search_label => $opt->{label} };
			Vend::Scan::find_search_params($c, $params);
			$search = Vend::Scan::perform_search($c);
			$ary = $search->{mv_results};
		}

		finish_search($search);
		
		if($CGI->{ui_return_to} and ! $CGI->{ui_return_stack}) {
			$edit_extra .= $Tag->return_to('formlink');	
		}
		else {
			$edit_extra .= "ui_return_to=$cwp";
		}

		my $edit_anchor;
		my $ee_extra;
		if($opt->{explicit_edit}) {
			$edit_anchor = errmsg('edit record');
			$edit_anchor =~ s/ /&nbsp;/g;
			$ee_extra = '';
			for(qw/ class style width align valign /) {
				my $v = $opt->{"explicit_edit_$_"}
					or next;
				$ee_extra .= qq{ $_="$v"};
			}
			$ee_extra ||= ' width=30';
		}
#::logDebug("explicit_edit=$opt->{explicit_edit} no_code_link=$opt->{no_code_link}");
		my $j = $search->{mv_first_match} || 0;
		foreach my $line (@$ary) {
			my $code = shift (@$line);
			my $ecode = encode_entities($code);
			my $rc = $j++ % 2
					? $opt->{data_row_class_even}
					: $opt->{data_row_class_odd};
			my $out = qq{<tr class="$rc">\n};

			my $code_pre; my $code_post;
			if($opt->{no_code_link} and ! $opt->{explicit_edit}) {
				$code_pre = $code_post = '';
			}
			else {
				my $edit_url = $Tag->area({
									href => $edit_page,
									form => qq{
												$edit_parm=$code
												$edit_extra
									}
								});
				my $msg = errmsg('edit %s', $ecode);
				$code_pre = qq{<a href="$edit_url" title="$msg">};
				$code_post = qq{</a>};
			}

			unless($opt->{no_checkbox}) {
				$out .= <<EOF;
<td width="$cb_width"><INPUT TYPE=checkbox NAME=$cb_name VALUE="$ecode"></td>
EOF
			}

			if($opt->{number_list}) {
				$out .= qq{<td align=right>&nbsp;$j&nbsp;</td>};
			}

			if($opt->{explicit_edit}) {
				$out .= qq{<td$ee_extra>&nbsp;$code_pre$edit_anchor$code_post&nbsp;</td>};
				$opt->{no_code_link} and $code_pre = $code_post = '';
			}

#::logDebug("keyname=$ts->{keyname}");
			$out .= "<td" . $data_cell_style->($ts->{keyname}) . ">";
			$out .= "$code_pre$ecode$code_post</td>";
			my $i = 1;
			for my $v (@$line) {
				my $extra = $style[$i];
				my $pre = '';
				my $post = '';
				my $lab;

				if($link_page[$i]) {
					my $opt = { $link_parm[$i] => $v, form => 'auto' };
					if(my $p = $link_parm_extra[$i]) {
						for(@$p) {
							$opt->{$_} = $CGI->{$_};
						}
					}
					$opt->{href} = $link_page[$i];

					$lab = $link_anchor[$i];
					$lab =~ s/^\s+//;
					my $url = $Tag->area($opt);
					my $ev = encode_entities($v);
					$pre = qq{<a href="$url" title="$ev">};
					$post = '</a>';
				}

				if($calcs[$i]) {
#::logDebug("found a calc");
					my %item;
					@item{@cols} = ($code, @$line);
					if(ref($calcs[$i]) eq 'CODE') {
						$lab = $calcs[$i]->(\%item);
					}
					else {
						$Vend::Interpolate::item = \%item;
						$lab = tag_calc($calcs[$i]);
					}
				}

				$lab ||= $v;

				$lab = $Tag->filter($filter_show[$i], $lab, $cols[$i]);

				$lab =~ s/\[/&#91;/g;
				$out .= "<TD$extra>$pre$lab$post</TD>";

				$i++;
			}
			$out .= "</tr>\n";
			push @rows, $out;
		}

		unless(@rows) {
			my $nomsg = errmsg('No records.');
			push @rows, qq{<tr><td colspan=$ncols><blockquote>$nomsg</blockquote></td></tr>};
		}
		else {
			my $mmsg = errmsg($opt->{more_message} ||= 'More rows');
			$opt->{more_list} ||= <<EOF;
<tr>
<td colspan={NCOLS} align=center>
$mmsg: [decade-next][/decade-next] [more] [decade-prev][/decade-prev]
</td>
</tr>
EOF
			$opt->{more_list} =~ s/\{NCOLS\}/$ncols/g;
			my $override = { mv_data_table => $table, ui_meta_view => $mview };
			my @forms;
			my @formparms = qw/ mv_data_table ui_meta_view ui_meta_specific /;
			for(@formparms) {
				my $thing = $override->{$_} || $CGI->{$_};
				next unless length $thing;
				push @forms, "$_=$thing";
			}
			my $o = {
				object => $search,
				label => $opt->{label},
				form => join("\n", @forms),
			};
			$output{MORE_LIST} = tag_more_list(
										$opt->{next_anchor},
										$opt->{prev_anchor},
										$opt->{page_anchor},
										$opt->{more_border},
										$opt->{more_border_selected},
										$o,
										$opt->{more_list},
									);
		}
	}

	$output{BOTTOM_OF_TABLE} = '</table>';
	$output{BOTTOM_OF_FORM} = '</form>';
	my $calc_sequence = <<'EOF';
ui_sequence_edit=[calc]
	$CGI->{item_id_left} = $CGI->{item_id};
	$CGI->{item_id_left} =~ s/\0+/,/g;
	if($CGI->{item_id_left} =~ s/^(.*?),//) {
		$CGI->{item_id} = $1;
		return 1;
	}
	else {
		delete $CGI->{item_id_left};
		return '';
	}
[/calc]
EOF
	$calc_sequence .= "mv_nextpage=$edit_page\nmv_todo=return";
	my $ebutton = $Tag->button(	
							{
								text => errmsg('Edit checked records in sequence'),
								extra => $opt->{edit_button_extra} || ' class=s2',
							},
							$calc_sequence,
						);
	my $dbutton = '';
	if($Tag->if_mm({ function => 'tables', table => "$table=d"}) ) {
		$opt->{confirm} ||= "Are you sure you want to delete the checked records?";
		my $dtext = qq{
[flag type=write table=$table]
deleterecords=1
mv_click=db_maintenance};
		$dbutton = '&nbsp;';
		$dbutton .= $Tag->button(	
							{
								text => errmsg('Delete checked records'),
								extra => $opt->{edit_button_extra} || ' class=s2',
								confirm => errmsg($opt->{confirm}),
							},
							$dtext,
						);
	}
	my $cboxes = '';

	if($meta->{check_uncheck_all}) {
		my $uc_msg = errmsg('Uncheck all');
		my $ch_msg = errmsg('Check all');
		$ch_msg =~ s/\s/&nbsp;/g;
		$uc_msg =~ s/\s/&nbsp;/g;
		$cboxes = <<EOF;
<A HREF="javascript:checkAll(document.$opt->{form_name}, '$cb_name')">
$ch_msg
</A>&nbsp;&nbsp;
<A HREF="javascript:checkAll(document.$opt->{form_name}, '$cb_name', 1)">
$uc_msg
</A>&nbsp;&nbsp;
EOF
		$cboxes =~ s/\n//g;
	}

	if(! $opt->{no_checkbox}) {
		unless($opt->{no_top} || $opt->{bottom_buttons}) {
			$output{TOP_BUTTONS} = $cboxes;
			$output{TOP_BUTTONS} .= $ebutton;
			if($dbutton) {
				$output{TOP_BUTTONS} .= '&nbsp;' x 4;
				$output{TOP_BUTTONS} .= $dbutton;
			}
		}

		unless($opt->{no_bottom} || $opt->{top_buttons}) {
			$output{BOTTOM_BUTTONS} = $cboxes;
			$output{BOTTOM_BUTTONS} .= $ebutton;
			if($dbutton) {
				$output{BOTTOM_BUTTONS} .= '&nbsp;' x 4;
				$output{BOTTOM_BUTTONS} .= $dbutton;
			}
		}
	}

	my %map = qw/
			TOP_OF_FORM			top_of_form
			BOTTOM_OF_FORM		bottom_of_form
			HIDDEN_FIELDS  	    hidden_fields
			TOP_BUTTONS    	    top_buttons
			BOTTOM_BUTTONS    	bottom_buttons
			EXTRA_BUTTONS    	extra_buttons
		/;

	my @areas = qw/
					TOP_OF_TABLE
					TOP_OF_FORM
					HIDDEN_FIELDS
					TOP_BUTTONS 
					HEADER_AREA
					MAIN_BODY
					MORE_LIST
					BOTTOM_BUTTONS
					EXTRA_BUTTONS
					BOTTOM_OF_FORM
					BOTTOM_OF_TABLE
				/;
	
	$output{MAIN_BODY} = join "", @rows;

	my @out;
	for(@areas) {
		next unless $output{$_};
		if($opt->{ui_style} and $map{$_}) {
			my $op = $map{$_};
			$Tag->output_to($op, { name => $op }, $output{$_} );
		}
		else {
			push @out, $output{$_};
		}
	}
	return join "", @out;
}
EOR







More information about the interchange-cvs mailing list