@@ -, +, @@ fields/subfields the only ones we use, and the only ones we actually need. Events removed: change, mouseover, mouseout, mousedown, mouseup, mousemove, keydown, keypress, keyup. If you ever need one of those, you can still add event listeners in the 'focus' event handler, and remove them in the 'blur' event handler It just makes the code a lot less complicated. All framework plugins have been updated - Go to every page that has a MARC editor and verify that plugins still work. This includes addbiblio.pl, additem.pl, authorities.pl, neworderempty.pl, orderreceive.pl - Test plugins that use 'focus' event (for instance barcode.pl), 'blur' event (callnumber.pl) and 'click' event (almost all the others) - Test that plugins work on cloned fields/subfields --- C4/Items.pm | 2 +- Koha/FrameworkPlugin.pm | 84 ++-------------- Koha/UI/Form/Builder/Item.pm | 1 + authorities/authorities.pl | 1 + cataloguing/value_builder/EXAMPLE.pl | 26 +---- cataloguing/value_builder/barcode.pl | 12 ++- cataloguing/value_builder/barcode_manual.pl | 3 +- cataloguing/value_builder/callnumber-KU.pl | 4 +- cataloguing/value_builder/callnumber.pl | 4 +- cataloguing/value_builder/cn_browser.pl | 4 +- cataloguing/value_builder/dateaccessioned.pl | 1 - cataloguing/value_builder/marc21_field_005.pl | 1 - cataloguing/value_builder/stocknumber.pl | 9 +- cataloguing/value_builder/stocknumberAV.pl | 6 +- cataloguing/value_builder/stocknumberam123.pl | 4 +- .../value_builder/unimarc_field_010.pl | 4 +- .../value_builder/unimarc_field_100.pl | 3 +- .../unimarc_field_100_authorities.pl | 3 +- .../value_builder/unimarc_field_105.pl | 6 +- .../value_builder/unimarc_field_106.pl | 6 +- .../value_builder/unimarc_field_110.pl | 6 +- .../value_builder/unimarc_field_115a.pl | 5 +- .../value_builder/unimarc_field_115b.pl | 6 +- .../value_builder/unimarc_field_116.pl | 6 +- .../value_builder/unimarc_field_117.pl | 6 +- .../value_builder/unimarc_field_120.pl | 6 +- .../value_builder/unimarc_field_121a.pl | 6 +- .../value_builder/unimarc_field_121b.pl | 6 +- .../value_builder/unimarc_field_122.pl | 6 +- .../value_builder/unimarc_field_123a.pl | 6 +- .../value_builder/unimarc_field_123d.pl | 6 +- .../value_builder/unimarc_field_123e.pl | 6 +- .../value_builder/unimarc_field_123f.pl | 6 +- .../value_builder/unimarc_field_123g.pl | 6 +- .../value_builder/unimarc_field_123i.pl | 6 +- .../value_builder/unimarc_field_123j.pl | 6 +- .../value_builder/unimarc_field_124.pl | 6 +- .../value_builder/unimarc_field_124a.pl | 6 +- .../value_builder/unimarc_field_124b.pl | 6 +- .../value_builder/unimarc_field_124c.pl | 6 +- .../value_builder/unimarc_field_124d.pl | 6 +- .../value_builder/unimarc_field_124e.pl | 6 +- .../value_builder/unimarc_field_124f.pl | 6 +- .../value_builder/unimarc_field_124g.pl | 6 +- .../value_builder/unimarc_field_125.pl | 6 +- .../value_builder/unimarc_field_125a.pl | 6 +- .../value_builder/unimarc_field_125b.pl | 6 +- .../value_builder/unimarc_field_126.pl | 6 +- .../value_builder/unimarc_field_126a.pl | 6 +- .../value_builder/unimarc_field_126b.pl | 6 +- .../value_builder/unimarc_field_127.pl | 6 +- .../value_builder/unimarc_field_128a.pl | 6 +- .../value_builder/unimarc_field_128b.pl | 7 +- .../value_builder/unimarc_field_128c.pl | 6 +- .../value_builder/unimarc_field_130.pl | 6 +- .../value_builder/unimarc_field_135a.pl | 6 +- .../value_builder/unimarc_field_140.pl | 6 +- .../value_builder/unimarc_field_141.pl | 6 +- .../value_builder/unimarc_field_146a.pl | 1 - .../value_builder/unimarc_field_146h.pl | 1 - .../value_builder/unimarc_field_146i.pl | 1 - .../value_builder/unimarc_field_210c.pl | 6 +- .../value_builder/unimarc_field_210c_bis.pl | 4 +- .../value_builder/unimarc_field_225a.pl | 6 +- .../value_builder/unimarc_field_225a_bis.pl | 4 +- .../value_builder/unimarc_field_4XX.pl | 6 +- .../value_builder/unimarc_field_686a.pl | 6 +- .../value_builder/unimarc_field_700-4.pl | 6 +- cataloguing/value_builder/unimarc_leader.pl | 11 +-- .../unimarc_leader_authorities.pl | 8 +- cataloguing/value_builder/upload.pl | 1 - .../prog/en/includes/html_helpers.inc | 6 +- .../prog/en/modules/acqui/neworderempty.tt | 2 +- .../prog/en/modules/acqui/orderreceive.tt | 2 +- .../en/modules/authorities/authorities.tt | 4 +- .../prog/en/modules/cataloguing/addbiblio.tt | 8 +- .../prog/en/modules/cataloguing/additem.tt | 2 +- koha-tmpl/intranet-tmpl/prog/js/additem.js | 14 --- koha-tmpl/intranet-tmpl/prog/js/cataloging.js | 97 ++++++++----------- 79 files changed, 249 insertions(+), 359 deletions(-) --- a/C4/Items.pm +++ a/C4/Items.pm @@ -1753,7 +1753,7 @@ sub PrepareItemrecordDisplay { my $tab= $plugin->noclick? '-1': ''; my $class= $plugin->noclick? ' disabled': ''; my $title= $plugin->noclick? 'No popup': 'Tag editor'; - $subfield_data{marc_value} = qq[...\n].$plugin->javascript; + $subfield_data{marc_value} = qq[...\n].$plugin->javascript; } else { warn $plugin->errstr; $subfield_data{marc_value} = qq(); # supply default input form --- a/Koha/FrameworkPlugin.pm +++ a/Koha/FrameworkPlugin.pm @@ -297,94 +297,24 @@ sub _process_javascript { $script =~ s/\]*\>\s*(\/\/\\s*)?\<\/script\>//s; - my $id = $params->{id}//''; - my $bind = ''; my $clickfound = 0; - my @events = qw|click focus blur change mouseover mouseout mousedown - mouseup mousemove keydown keypress keyup|; + my @events = qw|click focus blur|; foreach my $ev ( @events ) { my $scan = $ev eq 'click' && $self->{oldschool}? 'clic': $ev; - if( $script =~ /function\s+($scan\w+)\s*\(([^\)]*)\)/is ) { - my ( $bl, $sl ) = $self->_add_binding( $1, $2, $ev, $id ); - $script .= $sl; - $bind .= $bl; + if( $script =~ /function\s+($scan\w+)\s*\(/is ) { + my $function_name = $1; + $script .= sprintf('registerFrameworkPluginHandler("%s", "%s", %s);', $self->name, $ev, $function_name); $clickfound = 1 if $ev eq 'click'; } } - if( !$clickfound ) { # make buttonDot do nothing - my ( $bl ) = $self->_add_binding( 'noclick', '', 'click', $id ); - $bind .= $bl; - } $self->{noclick} = !$clickfound; - $self->{javascript}= _merge_script( $id, $script, $bind ); -} - -sub _add_binding { -# adds some jQuery code for event binding: -# $bind contains lines for the actual event binding: .click, .focus, etc. -# $script contains function definitions (if needed) - my ( $self, $fname, $pars, $ev, $id ) = @_; - my ( $bind, $script ); - my $ctl= $ev eq 'click'? 'buttonDot_'.$id: $id; - #click event applies to buttonDot - - if( $pars =~ /^(e|ev|event)$/i ) { # new style event handler assumed - $bind= qq| \$("#$ctl").$ev(\{id: '$id'\}, $fname);\n|; - $script=''; - } elsif( $fname eq 'noclick' ) { # no click: return false, no scroll - $bind= qq| \$("#$ctl").$ev(function () { return false; });\n|; - $script=''; - } else { # add real event handler calling the function found - $bind=qq| \$("#$ctl").$ev(\{id: '$id'\}, ${fname}_handler);\n|; - $script = $self->_add_handler( $ev, $fname ); - } - return ( $bind, $script ); -} - -sub _add_handler { -# adds a handler with event parameter -# event.data.id is passed to the plugin function in parameters -# for the click event we always return false to prevent scrolling - my ( $self, $ev, $fname ) = @_; - my $first= $self->_first_item_par( $ev ); - my $prefix= $ev eq 'click'? '': 'return '; - my $suffix= $ev eq 'click'? "\n return false;": ''; - return <{item_style} && $self->{oldschool} && - $event=~/focus|blur|change/ ) { - return qq/'0',/; - } - return ''; -} - -sub _merge_script { -# Combine script and event bindings, enclosed in script tags. -# The BindEvents function is added to easily repeat event binding; -# this is used in additem.js for dynamically created item blocks. - my ( $id, $script, $bind ) = @_; - chomp ($script, $bind); - return <{javascript} = < +\$(document).ready(function () { $script -function BindEvents$id() { -$bind -} -\$(document).ready(function() { - BindEvents$id(); }); -HERE +JS } =head1 AUTHOR --- a/Koha/UI/Form/Builder/Item.pm +++ a/Koha/UI/Form/Builder/Item.pm @@ -329,6 +329,7 @@ sub generate_subfield_form { class => $class, nopopup => $plugin->noclick, javascript => $plugin->javascript, + plugin => $plugin->name, }; } else { --- a/authorities/authorities.pl +++ a/authorities/authorities.pl @@ -191,6 +191,7 @@ sub create_input { maxlength => $max_length, javascript => $plugin->javascript, noclick => $plugin->noclick, + plugin => $plugin->name, }; } else { # warn and supply default field warn $plugin->errstr; --- a/cataloguing/value_builder/EXAMPLE.pl +++ a/cataloguing/value_builder/EXAMPLE.pl @@ -65,37 +65,19 @@ my $builder= sub { |; }; --- a/cataloguing/value_builder/barcode.pl +++ a/cataloguing/value_builder/barcode.pl @@ -86,14 +86,16 @@ END_OF_JS my $js = < - -function Focus$function_name(id, force) { +function set_barcode(id, force) { $scr } -function Click$function_name(id) { - Focus$function_name(id, 1); - return false; +function Focus$function_name(event) { + set_barcode(event.data.id, false); +} + +function Click$function_name(event) { + set_barcode(event.data.id, true); } END_OF_JS --- a/cataloguing/value_builder/barcode_manual.pl +++ a/cataloguing/value_builder/barcode_manual.pl @@ -66,7 +66,8 @@ END_OF_JS my $js = < - function Click$function_name(id) { + function Click$function_name(event) { + const id = event.data.id; $scr return false; } --- a/cataloguing/value_builder/callnumber-KU.pl +++ a/cataloguing/value_builder/callnumber-KU.pl @@ -46,8 +46,8 @@ my $builder = sub { my ( $params ) = @_; my $res=" --- a/cataloguing/value_builder/stocknumber.pl +++ a/cataloguing/value_builder/stocknumber.pl @@ -39,15 +39,18 @@ my $builder = sub { my $js = < -function Focus$function_name(id, force) { +function set_stocknumber(id, force) { if (\$('#' + id).val() == '' || force) { \$('#' + id).val('$nextnum'); } } +function Focus$function_name(event) { + set_stocknumber(event.data.id, false); +} + function Click$function_name(event) { - Focus$function_name(event.data.id, 1); - return false; + set_stocknumber(event.data.id, true); } END_OF_JS --- a/cataloguing/value_builder/stocknumberAV.pl +++ a/cataloguing/value_builder/stocknumberAV.pl @@ -47,8 +47,8 @@ my $builder = sub { my ( $params ) = @_; my $res = qq{ --- a/cataloguing/value_builder/unimarc_field_106.pl +++ a/cataloguing/value_builder/unimarc_field_106.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= "106".(int(rand(100000))+1); my $res=" --- a/cataloguing/value_builder/unimarc_field_110.pl +++ a/cataloguing/value_builder/unimarc_field_110.pl @@ -33,9 +33,9 @@ sub plugin_javascript { my ($dbh,$record,$tagslib,$field_number) = @_; my $res=" --- a/cataloguing/value_builder/unimarc_field_115a.pl +++ a/cataloguing/value_builder/unimarc_field_115a.pl @@ -32,7 +32,8 @@ sub plugin_javascript { my ( $dbh, $record, $tagslib, $field_number ) = @_; my $res = " --- a/cataloguing/value_builder/unimarc_field_115b.pl +++ a/cataloguing/value_builder/unimarc_field_115b.pl @@ -32,9 +32,9 @@ sub plugin_javascript { my ( $dbh, $record, $tagslib, $field_number ) = @_; my $res = " --- a/cataloguing/value_builder/unimarc_field_116.pl +++ a/cataloguing/value_builder/unimarc_field_116.pl @@ -32,9 +32,9 @@ sub plugin_javascript { my ( $dbh, $record, $tagslib, $field_number ) = @_; my $res = " --- a/cataloguing/value_builder/unimarc_field_117.pl +++ a/cataloguing/value_builder/unimarc_field_117.pl @@ -32,9 +32,9 @@ sub plugin_javascript { my ($dbh,$record,$tagslib,$field_number) = @_; my $res=" --- a/cataloguing/value_builder/unimarc_field_120.pl +++ a/cataloguing/value_builder/unimarc_field_120.pl @@ -34,9 +34,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name=$field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_121a.pl +++ a/cataloguing/value_builder/unimarc_field_121a.pl @@ -33,9 +33,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_121b.pl +++ a/cataloguing/value_builder/unimarc_field_121b.pl @@ -31,9 +31,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_122.pl +++ a/cataloguing/value_builder/unimarc_field_122.pl @@ -31,9 +31,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123a.pl +++ a/cataloguing/value_builder/unimarc_field_123a.pl @@ -31,9 +31,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123d.pl +++ a/cataloguing/value_builder/unimarc_field_123d.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123e.pl +++ a/cataloguing/value_builder/unimarc_field_123e.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123f.pl +++ a/cataloguing/value_builder/unimarc_field_123f.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123g.pl +++ a/cataloguing/value_builder/unimarc_field_123g.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123i.pl +++ a/cataloguing/value_builder/unimarc_field_123i.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_123j.pl +++ a/cataloguing/value_builder/unimarc_field_123j.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124.pl +++ a/cataloguing/value_builder/unimarc_field_124.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124a.pl +++ a/cataloguing/value_builder/unimarc_field_124a.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124b.pl +++ a/cataloguing/value_builder/unimarc_field_124b.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124c.pl +++ a/cataloguing/value_builder/unimarc_field_124c.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124d.pl +++ a/cataloguing/value_builder/unimarc_field_124d.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124e.pl +++ a/cataloguing/value_builder/unimarc_field_124e.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124f.pl +++ a/cataloguing/value_builder/unimarc_field_124f.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_124g.pl +++ a/cataloguing/value_builder/unimarc_field_124g.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_125.pl +++ a/cataloguing/value_builder/unimarc_field_125.pl @@ -38,9 +38,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_125a.pl +++ a/cataloguing/value_builder/unimarc_field_125a.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_125b.pl +++ a/cataloguing/value_builder/unimarc_field_125b.pl @@ -33,9 +33,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_126.pl +++ a/cataloguing/value_builder/unimarc_field_126.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_126a.pl +++ a/cataloguing/value_builder/unimarc_field_126a.pl @@ -33,9 +33,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_126b.pl +++ a/cataloguing/value_builder/unimarc_field_126b.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_127.pl +++ a/cataloguing/value_builder/unimarc_field_127.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_128a.pl +++ a/cataloguing/value_builder/unimarc_field_128a.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_128b.pl +++ a/cataloguing/value_builder/unimarc_field_128b.pl @@ -33,9 +33,10 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_128c.pl +++ a/cataloguing/value_builder/unimarc_field_128c.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_130.pl +++ a/cataloguing/value_builder/unimarc_field_130.pl @@ -34,9 +34,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_135a.pl +++ a/cataloguing/value_builder/unimarc_field_135a.pl @@ -33,9 +33,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_140.pl +++ a/cataloguing/value_builder/unimarc_field_140.pl @@ -34,9 +34,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_141.pl +++ a/cataloguing/value_builder/unimarc_field_141.pl @@ -32,9 +32,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res=" --- a/cataloguing/value_builder/unimarc_field_146a.pl +++ a/cataloguing/value_builder/unimarc_field_146a.pl @@ -29,7 +29,6 @@ my $builder = sub { return qq| "; --- a/cataloguing/value_builder/unimarc_field_210c_bis.pl +++ a/cataloguing/value_builder/unimarc_field_210c_bis.pl @@ -54,8 +54,8 @@ sub plugin_javascript { "; --- a/cataloguing/value_builder/unimarc_field_225a.pl +++ a/cataloguing/value_builder/unimarc_field_225a.pl @@ -62,7 +62,7 @@ sub plugin_javascript { --- a/cataloguing/value_builder/unimarc_field_225a_bis.pl +++ a/cataloguing/value_builder/unimarc_field_225a_bis.pl @@ -35,8 +35,8 @@ sub plugin_javascript { my $function_name = $field_number; my $res = " "; --- a/cataloguing/value_builder/unimarc_field_4XX.pl +++ a/cataloguing/value_builder/unimarc_field_4XX.pl @@ -46,9 +46,9 @@ sub plugin_javascript { my $function_name = $field_number; my $res = " --- a/cataloguing/value_builder/unimarc_field_686a.pl +++ a/cataloguing/value_builder/unimarc_field_686a.pl @@ -31,9 +31,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res = " --- a/cataloguing/value_builder/unimarc_field_700-4.pl +++ a/cataloguing/value_builder/unimarc_field_700-4.pl @@ -33,9 +33,9 @@ my ($dbh,$record,$tagslib,$field_number) = @_; my $function_name= $field_number; my $res = " --- a/cataloguing/value_builder/unimarc_leader.pl +++ a/cataloguing/value_builder/unimarc_leader.pl @@ -33,17 +33,16 @@ sub plugin_javascript { my $function_name = $field_number; my $res = " --- a/cataloguing/value_builder/unimarc_leader_authorities.pl +++ a/cataloguing/value_builder/unimarc_leader_authorities.pl @@ -30,15 +30,15 @@ sub plugin_javascript { my ( $dbh, $record, $tagslib, $field_number ) = @_; my $res = " "; --- a/cataloguing/value_builder/upload.pl +++ a/cataloguing/value_builder/upload.pl @@ -35,7 +35,6 @@ my $builder = sub { return <<"SCRIPT";