All Update Items Commits In One
authorBill Erickson <berickxx@gmail.com>
Wed, 29 Oct 2014 21:09:50 +0000 (17:09 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 21 Mar 2019 19:46:23 +0000 (15:46 -0400)
    Cross-port: 738e031

Conflicts:
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/asset.pm

12 files changed:
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/asset.pm
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/cat/opac.js
Open-ILS/xul/staff_client/chrome/content/cat/opac.xul
Open-ILS/xul/staff_client/chrome/content/main/constants.js
Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
Open-ILS/xul/staff_client/server/cat/update_items.js [new file with mode: 0644]
Open-ILS/xul/staff_client/server/cat/update_items.xul [new file with mode: 0644]
Open-ILS/xul/staff_client/server/cat/util.js
Open-ILS/xul/staff_client/server/locale/en-US/cat.properties

index 389a3e3..bcc60d8 100644 (file)
@@ -1735,16 +1735,14 @@ sub asset_by_call_number {
        else{
 
                my $meth = $self->method_lookup("open-ils.storage.asset.map_asset_by_call_number");
-       
+
                my ($key_pair_ref) = $meth->run($user_session, $docid);
-       
-               $logger->debug("cat key_pair: ".Dumper($key_pair_ref));
-       
+
                my $key_string = ${$key_pair_ref}[0];#'maintenance_data';
                my $index = ${$key_pair_ref}[1];
-       
+
                $logger->debug("cat key: ".$key_string.$index);
-       
+
                # start at 0
                $returned = $cache->get_cache($key_string.'0');
 
@@ -1754,9 +1752,6 @@ sub asset_by_call_number {
 
                $cache->delete_cache($key_string.'0'); # remove the cache
 
-               $logger->debug("cat response: ".Dumper($returned));
-               $logger->debug("cat response: ".${$returned}[(scalar @{$returned} - 1)]);
-
                $client->respond($returned);
        }
 
index bad3be3..6f415eb 100644 (file)
@@ -32,6 +32,8 @@ use OpenILS::Const qw/:const/;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::Cat::AssetCommon;
 
+use Data::Dumper;
+
 my $apputils = "OpenILS::Application::AppUtils";
 my $U = $apputils;
 
@@ -1008,11 +1010,97 @@ sub create_copy_note {
     return $note->id;
 }
 
+__PACKAGE__->register_method(
+    api_name        => 'open-ils.circ.create_batch_copy_note',
+    method          => 'create_batch_copy_note',
+    api_level       => 1,
+);
+
+sub create_batch_copy_note {
+    
+    my( $self, $connection, $authtoken, $notes ) = @_;
+    
+    my( $reqr, $evt ) = $U->checkses($authtoken);
+    return $evt if $evt;
+    my $e = new_editor(requestor => $reqr, xact => 1);
+    
+    $logger->debug("create_batch_copy_note creator?: ".Dumper($reqr));
+    $logger->debug("create_batch_copy_note creator?: ".Dumper($reqr->id()));
+    
+    #my $meth = $self->method_lookup("open-ils.storage.asset.create_batch_copy_note");
+
+    #$meth->run($authtoken, $notes);
+    
+        # [{'creator' => 1,'ou_id' => '1493','value' => 'sfh','create_date' => 'now',
+    # 'acp_id' => '7130592','barcode' => 'NEW13415850','pub' => 'f'},{'creator' => 1,'ou_id' => '1495','value' => 'zxcv','create_date' => 'now','acp_id' => '7130591','barcode' => 'MALOLO13415843','pub' => 'f'},{'creator' => 1,'ou_id' => '1497','value' => 'fyj,','create_date' => 'now','acp_id' => '7130590','barcode' => 'MALOLO13415835','pub' => 'f'},{'creator' => 1,'ou_id' => '119','value' => 'xvb','create_date' => 'now','acp_id' => '7130584','barcode' => 'MALOLO3415777','pub' => 'f'}];
+    $logger->debug("create_batch_copy_note notes: ".Dumper($notes));
+    
+    #my $e = new_editor(authtoken => $authtoken);
+    #return $e->event unless $e->checkauth;
+    
+    #my @note_list;
+    my %response;
+    
+    foreach my $note (@{ $notes }) {
+
+        # pub is incorrect and creator isn't there...
+        if ($note->{'barcode'} && $note->{'ou_id'} && $note->{'acn_id'} &&
+            $note->{'pub'} && $note->{'value'}){
+                
+            #my @note_object;
+
+            #push (@note_object, $reqr->id()); # Creator is the current user
+            #push (@note_object, $note->{'pub'});
+            #push (@note_object, $note->{'value'});
+            
+            my $copy_id_ref = $e->json_query({
+              'from' => 'acp',
+              'select' => {
+                'acp' => [
+                  'id'
+                ]
+              },
+              'where' => {
+                '-and' => [
+                  {
+                     'barcode' => $note->{'barcode'}
+                  },
+                  {
+                     'circ_lib' => $note->{'ou_id'}
+                  },
+                  {
+                     'call_number' => $note->{'acn_id'}
+                  }
+                ]
+              }
+            });
+
+            #push (@note_object, ${$copy_id_ref->[0]}{'id'});
+            #push (@note_list, \@note_object);
+
+            my $cn = Fieldmapper::asset::copy_note->new;
+            $cn->owning_copy(${$copy_id_ref->[0]}{'id'});
+            $cn->creator($e->requestor->id);
+            $cn->pub($note->{'pub'});
+            $cn->value($note->{'value'});
+            $cn->title('');
+            
+            $cn->id(create_copy_note($self, $connection, $authtoken, $cn));
+
+            # key:copy_id, value:note_text
+            $response{ $cn->owning_copy() } = $note->{'value'};  
+        }
+
+    }
+    
+    return \%response;
+}
+
 
 __PACKAGE__->register_method(
-    method      => 'delete_copy_note',
-    api_name        =>  'open-ils.circ.copy_note.delete',
-    signature   => q/
+    method    => 'delete_copy_note',
+    api_name  =>  'open-ils.circ.copy_note.delete',
+    signature => q/
         Deletes an existing copy note
         @param authtoken The login session key
         @param noteid The id of the note to delete
@@ -2075,8 +2163,75 @@ sub get_copy_due_date {
     return $circ->{due_date};
 }
 
+__PACKAGE__->register_method(
+    method    => "get_lineitem",
+    api_name  => "open-ils.circ.lineitem.latest_by_tcn",
+    signature => {
+        desc => "Grabs the latest lineitem by tcn value.  "
+    }
+);
 
+__PACKAGE__->register_method(
+    method    => "get_lineitem",
+    api_name  => "open-ils.circ.lineitem.lineitem_by_id",
+    signature => {
+        desc => "Grabs the latest lineitem by tcn value.  "
+    }
+);
 
+sub get_lineitem {
+    
+    my( $self, $client, $user_session, $id ) = @_;
+    
+    my $e = new_editor(authtoken => $user_session, xact => 1);
+    return $e->die_event unless $e->checkauth;
+    
+    my $meth = $self->method_lookup("open-ils.storage.asset.lineitem_by_id");
+    
+    if($self->api_name =~ /latest_by_tcn/) {
+        
+        $meth = $self->method_lookup("open-ils.storage.asset.latest_by_tcn");
+        $logger->debug("update_items latest_by_tcn");
+    }
+    
+    my ($arrayOfArrays) = $meth->run($user_session, $id);
+    
+    $logger->debug("update_items arrayOfArrays: ".Dumper($arrayOfArrays));
+    
+    # returnArray is [values, objectTemplate]
+    my @returnArray;
+    push(@returnArray, $arrayOfArrays);
+    
+    my %links;
+    $links{ 'acp' } = 1;
+    $links{ 'acn' } = 1;
+    
+    # Get the object template
+    my $returned = objectify(\%links);
+    
+    push(@returnArray, $returned);
+    
+    return \@returnArray;
+}
+
+# This will return a fieldmapped object template
+# type is the fieldmapper class you want to map to
+# links_to_follow is an optional list of links that will need to be fieldmapped in 
+sub objectify {
+    
+    my $links_to_follow = shift;
+    my %base_object;
+
+    for my $type ( keys %{ $links_to_follow } ){
+
+        my $class = Fieldmapper::class_for_hint($type);
+        my @fields = $class->all_fields();
+        
+        $base_object{ $type } = \@fields;
+    }
+
+    return \%base_object;
+}
 
 
 # {"select":{"acp":["id"],"circ":[{"aggregate":true,"transform":"count","alias":"count","column":"id"}]},"from":{"acp":{"circ":{"field":"target_copy","fkey":"id","type":"left"},"acn"{"field":"id","fkey":"call_number"}}},"where":{"+acn":{"record":200057}}
index 34128b2..15f628d 100644 (file)
@@ -878,9 +878,9 @@ __PACKAGE__->register_method(
 
 
 __PACKAGE__->register_method(
-       api_name        => 'open-ils.storage.asset.map_asset_by_call_number',
-       method          => 'map_asset_by_call_number'
-       
+    api_name        => 'open-ils.storage.asset.map_asset_by_call_number',
+    method          => 'map_asset_by_call_number'
+    
 );
 
 sub map_asset_by_call_number {
@@ -990,6 +990,109 @@ sub format_asset_map{
        return \@key_pair;
 }
 
+sub retrieve_latest_lineitem_by_tcn {
+
+    # Grab self, client
+    my $self = shift;
+    my $client = shift;
+    my $auth = shift;
+    my $tcn = shift;
+    
+    $log->debug("update_items client: ".Dumper($client));
+    $log->debug("update_items tcn: ".$tcn);
+    
+    # This guards against SQL injection
+    return [] unless $tcn =~ m/^[\d]+$/;
+    
+    my $select = <<"    SQL";
+        SELECT jub.id, apo.id, bre.marc
+        FROM biblio.record_entry bre
+        JOIN acq.lineitem jub ON (bre.id = jub.eg_bib_id)
+        JOIN acq.purchase_order apo ON (jub.purchase_order = apo.id)
+        WHERE jub.eg_bib_id = $tcn
+        AND (jub.state = 'received' 
+            OR jub.state = 'on-order')
+        ORDER BY apo.order_date DESC
+    SQL
+
+    # Load and execute statement
+    my $sth = asset::stat_cat->db_Main->prepare_cached($select);
+
+    $sth->execute();
+    
+    my @returnArray;
+    my @lineitems;
+    
+    my $arrayref = $sth->fetchall_arrayref;
+    
+    my $n = 0;
+    
+    while ($arrayref->[$n] != undef){
+        
+        push(@lineitems, $arrayref->[$n]);
+        $n ++;
+    }
+    
+    push(@returnArray, \@lineitems);
+        
+    my $li_id = $returnArray[0]->[0]->[0];
+    
+    my $array_ref = fill_lineitem($self,$client,$auth,$li_id);
+    
+    # returnArray = [\@lineitem, \@copies]
+    #copies = [\@copy, \@copy, etc.]
+    push(@returnArray, $array_ref );
+    $log->debug("update_items copies: ".Dumper($returnArray[1]));
+    
+    return \@returnArray;
+}
+
+__PACKAGE__->register_method(
+    api_name        => 'open-ils.storage.asset.latest_by_tcn',
+    method          => 'retrieve_latest_lineitem_by_tcn',
+    api_level       => 1,
+    stream          => 1,
+);
+
+sub fill_lineitem{
 
+    # Grab self, client
+    my $self = shift;
+    my $client = shift;
+    my $auth = shift;
+    my $li_id = shift;
+
+    $log->debug("update_items fill_lineitem: $li_id");
+
+    return [] unless $li_id =~ m/^[\d]+$/;
+
+    my $SQL = <<"    SQL";
+        SELECT acp.age_protect, acp.alert_message, acp.barcode, acp.call_number, acp.circ_as_type,
+        acp.circ_lib, acp.circ_modifier, acp.circulate, acp.copy_number, acp.create_date, acp.active_date, 
+        acp.creator, acp.deleted, acp.dummy_isbn, acp.deposit, acp.deposit_amount, acp.dummy_author, 
+        acp.dummy_title, acp.edit_date, acp.editor, acp.fine_level, acp.holdable, acp.id, acp.loan_duration,
+        acp.location, acp.opac_visible, acp.price, acp.ref, acp.status, acn.create_date, acn.creator,
+        acn.deleted, acn.edit_date, acn.editor, acn.id, acn.label, acn.owning_lib, acn.record, 
+        acn.label_sortkey, acn.label_class, acn.prefix, acn.suffix, ccs.name
+        FROM asset.copy acp
+        JOIN acq.lineitem_detail alid ON (acp.id = alid.eg_copy_id)
+        JOIN asset.call_number acn ON (acp.call_number = acn.id)
+        JOIN config.copy_status ccs ON (acp.status = ccs.id)
+        WHERE alid.lineitem = $li_id AND acp.deleted = 'f'
+    SQL
+
+    # Load and execute statement
+    my $dbcall = asset::stat_cat->db_Main->prepare_cached($SQL);
+
+    $dbcall->execute();
+    return $dbcall->fetchall_arrayref;
+}
+
+__PACKAGE__->register_method(
+    api_name        => 'open-ils.storage.asset.lineitem_by_id',
+    method          => 'fill_lineitem',
+    api_level       => 1,
+    stream          => 1,
+);
 
 1;
index c1ff1a1..d1c3f2b 100644 (file)
 <!ENTITY staff.cat.opac.view_holds.label "View Holds">
 <!ENTITY staff.cat.opac.view_orders.accesskey "r">
 <!ENTITY staff.cat.opac.view_orders.label "View/Place Orders">
+<!ENTITY staff.cat.opac.update_items.accesskey "u">
+<!ENTITY staff.cat.opac.update_items.label "Update Items">
 <!ENTITY staff.cat.opac.alt_serial.accesskey "a">
 <!ENTITY staff.cat.opac.alt_serial.label "Alternate Serial Control">
 <!ENTITY staff.cat.opac.batch_receive.accesskey "i">
index 33bb5da..6be3ba8 100644 (file)
@@ -329,6 +329,7 @@ function set_hold_browser() {
 
 
 function open_acq_orders() {
+
     try {
         var content_params = {
             "session": ses(),
@@ -363,6 +364,69 @@ function open_acq_orders() {
     }
 }
 
+function update_items(){
+    try {
+        var edit = 0;
+        try {
+            edit = g.network.request(
+                api.PERM_MULTI_ORG_CHECK.app,
+                api.PERM_MULTI_ORG_CHECK.method,
+                [ 
+                    ses(), 
+                    ses('staff_id'), 
+                    [ ses('ws_ou') ],
+                    [ 'CREATE_VOLUME', 'CREATE_COPY' ]
+                ]
+            ).length == 0 ? 1 : 0;
+        } catch(E) {
+            g.error.sdump('D_ERROR','batch permission check: ' + E);
+        }
+
+        if (edit==0) {
+            alert(document.getElementById('offlineStrings').getString('staff.circ.copy_status.add_volumes.perm_failure'));
+            return; // no read-only view for this interface
+        }
+
+        // Check if the source is allowed to have copies.
+        try {
+            var bibObj = g.network.request(
+                api.FM_BRE_RETRIEVE_VIA_ID.app,
+                api.FM_BRE_RETRIEVE_VIA_ID.method,
+                               [ ses(), [docid] ]
+            );
+
+                       bibObj = bibObj[0];
+
+            var cbsObj = g.network.request(
+                api.FM_CBS_RETRIEVE_VIA_PCRUD.app,
+                api.FM_CBS_RETRIEVE_VIA_PCRUD.method,
+                [ ses(), bibObj.source() ]
+            );
+
+            if (cbsObj && cbsObj.can_have_copies() != get_db_true()) {
+                alert(document.getElementById('offlineStrings').getFormattedString('staff.cat.bib_source.can_have_copies.false', [cbsObj.source()]));
+                return;
+            }
+        } catch(E) {
+            g.error.sdump('D_ERROR','can have copies check: ' + E);
+            alert('Error in chrome/content/cat/opac.js, update_items(): ' + E);
+            return;
+        }
+
+        var title = document.getElementById('offlineStrings').getFormattedString('staff.cat.update_items.title', [docid]);
+
+        var url = window.xulG.url_prefix( 'XUL_UPDATE_ITEMS' );
+               
+        var w = xulG.new_tab(
+            url,
+            { 'tab_name' : title },
+            { 'doc_id' : docid, 'ou_ids' : [ ses('ws_ou') ], 'reload_opac' : xulG.reload_opac }
+        );
+    } catch(E) {
+        alert('Error in chrome/content/cat/opac.js, update_items(): ' + E);
+    }
+}
+
 function open_alt_serial_mgmt() {
     try {
         var content_params = {
index 3ed3071..60fe278 100644 (file)
@@ -52,6 +52,7 @@
                 <menuitem label="&staff.cat.opac.manage_parts.label;" accesskey="&staff.cat.opac.manage_parts.accesskey;" id="manage_parts" oncommand="record_action(manage_parts);"/>
                 <menuitem label="&staff.cat.opac.view_holds.label;" accesskey="&staff.cat.opac.view_holds.accesskey;" id="view_holds" oncommand="record_action(set_hold_browser);"/>
                 <menuitem label="&staff.cat.opac.view_orders.label;" accesskey="&staff.cat.opac.view_orders.accesskey;" id="view_orders" oncommand="open_acq_orders();"/>
+                <menuitem label="&staff.cat.opac.update_items.label;" accesskey="&staff.cat.opac.update_items.accesskey;" id="update_items" oncommand="update_items();"/>
                 <menuseparator/>
                 <menuitem label="&staff.cat.opac.add_bucket.label;" accesskey="&staff.cat.opac.add_bucket.accesskey;" id="add_bucket" oncommand="add_to_bucket();"/>
                 <menuitem label="&staff.cat.opac.mark_for_overlay.label;" accesskey="&staff.cat.opac.mark_for_overlay.accesskey;" id="mark_for_overlay" oncommand="mark_for_overlay();"/>
index f1c5ada..96100b4 100644 (file)
@@ -86,6 +86,9 @@ var api = {
     'CLEAR_HOLD_SHELF' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold.clear_shelf.process', 'secure' : false },
     'FM_ACN_RETRIEVE' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.callnumber.fleshed.retrieve', 'secure' : false },
     'FM_ACN_RETRIEVE.authoritative' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.callnumber.fleshed.retrieve.authoritative', 'secure' : false },
+    'FM_OPEN_LI_RETRIEVE_BY_TCN' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.lineitem.latest_by_tcn', 'secure' : false },
+    'FM_OPEN_LI_RETRIEVE_BY_ID' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.lineitem.lineitem_by_id', 'secure' : false },
+    'FM_CUD_LI_NOTE' : { 'app' : 'open-ils.acq', 'method' : 'open-ils.acq.lineitem_note.cud.batch', 'secure' : false },
     'FM_ACN_TREE_UPDATE' : { 'app' : 'open-ils.cat', 'method' : 'open-ils.cat.asset.volume.fleshed.batch.update' },
     'FM_ACN_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS' : { 'app' : 'open-ils.cat', 'method' : 'open-ils.cat.asset.copy_tree.retrieve', 'secure' : false },
     'FM_ACN_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS.authoritative' : { 'app' : 'open-ils.cat', 'method' : 'open-ils.cat.asset.copy_tree.retrieve.authoritative', 'secure' : false },
@@ -116,6 +119,7 @@ var api = {
     'FM_ACPL_RETRIEVE_VIA_ID.authoritative' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.copy_location.retrieve.authoritative', 'secure' : false },
     'FM_ACPN_RETRIEVE_ALL' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.copy_note.retrieve.all.authoritative', 'secure' : false },
     'FM_ACPN_CREATE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.copy_note.create' },
+    'FM_ACPN_BATCH_CREATE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.create_batch_copy_note' },
     'FM_ACPN_DELETE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.copy_note.delete', 'secure' : false },
     'FM_ACTSC_RETRIEVE_BATCH' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.stat_cat.actor.retrieve.batch', 'secure' : false },
     'FM_ACTSC_RETRIEVE_VIA_AOU' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.stat_cat.actor.retrieve.all', 'secure' : false },
@@ -420,6 +424,7 @@ var urls = {
     'XUL_COPY_EDITOR' : 'oils://remote/xul/server/cat/copy_editor.xul',
     'XUL_COPY_LOCATION_EDIT' : 'oils://remote/xul/server/admin/copy_locations.xhtml',
     'XUL_COPY_NOTES' : 'oils://remote/xul/server/cat/copy_notes.xul',
+    'XUL_UPDATE_ITEMS' : 'oils://remote/xul/server/cat/update_items.xul',
     'XUL_COPY_STATUS' : 'oils://remote/xul/server/circ/copy_status.xul',
     'XUL_COPY_SUMMARY' : 'oils://remote/xul/server/cat/copy_summary.xul',
     'XUL_COPY_VOLUME_BROWSE' : 'oils://remote/xul/server/cat/copy_browser.xul',
@@ -520,6 +525,7 @@ var urls = {
     'EG_MARCEDIT_PHYS_CHAR_WIZARD' : 'oils://remote/eg/cat/marcedit/phys_char_wizard',
     'CUSTOM_JS' : '/xul/server/skin/custom.js',
     'ACQ_LINEITEM' : 'oils://remote/eg/acq/lineitem/related/',
+    'PRINT_LINEITEM_WORKSHEET' : 'oils://remote/eg/acq/lineitem/worksheet/',
     'SERIAL_LIST_SUBSCRIPTION' : 'oils://remote/eg/serial/list_subscription',
     'BOOKING_RESOURCE' : 'oils://remote/eg/conify/global/booking/resource',
     'BOOKING_RESERVATION' : 'oils://remote/eg/booking/reservation',
index ae58e5d..292ef43 100644 (file)
@@ -277,6 +277,7 @@ staff.cat.util.copy_editor.edit=Edit
 staff.cat.util.copy_editor.view=View
 staff.circ.copy_status.add_volumes.perm_failure=You do not have permission to add volumes to the workstation library.
 staff.circ.copy_status.add_volumes.title=Add Volume/Item for Record # %1$s
+staff.cat.update_items.title=Update Items for Record # %1$s
 staff.cat.copy_browser.marked_record_for_multi_home_indicator.tcn.label=Record with TCN %1$s targeted for Multi-Bib items.
 staff.cat.copy_browser.marked_record_for_multi_home_indicator.record_id.label=Record with ID %1$s targeted for Multi-Bib items.
 staff.cat.z3950.marked_record_for_overlay_indicator.tcn.label=Record with TCN %1$s marked for overlay.
diff --git a/Open-ILS/xul/staff_client/server/cat/update_items.js b/Open-ILS/xul/staff_client/server/cat/update_items.js
new file mode 100644 (file)
index 0000000..c1bf398
--- /dev/null
@@ -0,0 +1,2245 @@
+const g_max_copies_that_can_be_added_at_a_time_per_volume = 999;
+const rel_vert_pos_volume_count = 1;
+const rel_vert_pos_call_number = 2;
+const rel_vert_pos_copy_count = 3;
+const rel_vert_pos_barcode = 4;
+const rel_vert_pos_copy_note = 5;
+const update_timer = 1000;
+const call_number_width = 100;
+const barcode_width = 100;
+const status_width = 90;
+var g = {};
+g.use_defaults = true;
+g.map_acn = {};
+g.volumes_by_ou = {};
+g.acpl_list = [];
+
+// This file was modeled off of volume_copy_creator.js, so if you need
+// functionality back, take it from there
+function my_init() {
+
+    try {
+
+        /* Initial setup */
+
+        if (typeof JSAN == 'undefined') {
+
+            throw( $("commonStrings").getString('common.jsan.missing') );
+        }
+
+        JSAN.use('cat.util');
+        JSAN.use('OpenILS.data');
+        JSAN.use('util.barcode');
+        JSAN.use('util.date');
+        JSAN.use('util.error');
+        JSAN.use('util.file');
+        JSAN.use('util.fm_utils');
+        JSAN.use('util.functional');
+        JSAN.use('util.money');
+        JSAN.use('util.network');
+        JSAN.use('util.widgets');
+
+        g.data = new OpenILS.data();
+        g.data.init({'via':'stash'});
+
+        JSAN.errorLevel = "die"; // none, warn, or die
+        JSAN.addRepository('/xul/server/');
+
+        g.error = new util.error();
+        g.error.sdump('D_TRACE','my_init() for cat/volume_copy_creator.xul');
+
+        g.network = new util.network();
+
+        g.refresh = xul_param('onrefresh');
+
+        /////////////////////////// INITIALIZE DATA ///////////////////////////////////////
+        var raw_lineitem_data = g.network.simple_request(
+            'FM_OPEN_LI_RETRIEVE_BY_TCN',
+            [ ses(), xul_param('doc_id') ]
+        );
+
+        // Create the list of lineitems
+        g.lineitem_list = raw_lineitem_data[0][0];
+
+        if (g.lineitem_list[0].length == 0){
+
+            alert('TCN '+xul_param('doc_id')+" doesn't appear to have any open lineitems...");
+        }
+
+        else{
+
+            //copyTemplatecopyTemplate.push("owning_lib");
+            g.current_lineitem_index = 0; // This keeps track of which lineitem we're on
+
+            g.load_lineitem(raw_lineitem_data);
+
+            g.render_batch_button();
+
+            g.render_lineitem_dropdown();
+
+            /***********************************************************************************************************/
+            /* What record am I dealing with?  */
+            g.doc_id = g.doc_id || xul_param('doc_id');
+
+            if (! g.doc_id) {
+
+                alert('Error in update_items.js, g.doc_id not valid'+": 187");
+                window.close(); return;
+            }
+
+            var sb = document.getElementById('summary_box');
+
+            if (xul_param('no_bib_summary')) {
+
+                sb.hidden = true;
+                sb.nextSibling.hidden = true; /* splitter */
+            }
+
+            else {
+
+                while(sb.firstChild){
+
+                    sb.removeChild(sb.lastChild);
+                }
+
+                var summary = document.createElement('iframe');
+                sb.appendChild(summary);
+                summary.setAttribute('src',urls.XUL_BIB_BRIEF);
+                summary.setAttribute('flex','1');
+                get_contentWindow(summary).xulG = { 'docid' : g.doc_id };
+            }
+
+            /***********************************************************************************************************/
+            /* Setup pcrud and fetch the monographic parts for this bib */
+
+            dojo.require('openils.PermaCrud');
+            g.pcrud = new openils.PermaCrud({'authtoken':ses()});
+
+            /***********************************************************************************************************/
+            /* For the batch drop downs */
+
+            // OPENSRF call made
+            cat.util.render_callnumbers_for_bib_menu('marc_cn',g.doc_id, g.label_class, call_number_width);
+
+            var control_bar = document.getElementById('misc_control_bar');
+
+            // Sets the font
+            control_bar.setAttribute('class','ALL_FONTS_8PT');
+
+            // Setup checkboxes
+
+            // Worksheet checkbox
+            var worksheetCheckbox = document.createElement('checkbox');
+            worksheetCheckbox.setAttribute('id','print_worksheet');
+            worksheetCheckbox.setAttribute('label',$('catStrings').getString('staff.cat.update_items.print_worksheet'));
+            control_bar.appendChild( worksheetCheckbox );
+
+            // Add Notes checkbox
+            var noteCheckbox = document.createElement('checkbox');
+            noteCheckbox.setAttribute('id','li_note_checkbox');
+            noteCheckbox.setAttribute('label',$('catStrings').getString('staff.cat.update_items.lineitem_note.default'));
+            control_bar.appendChild( noteCheckbox );
+
+            // Make the textbox for the default note
+            var default_liNote = document.createElement('textbox');
+            default_liNote.setAttribute('id','default_li_note');
+            control_bar.appendChild( default_liNote );
+
+            // Now we add the default note text using the logged in staff's 'middle name'
+            // If my initials are 'DJC' and the date is '3/6/14', the note should read: 'REC:DJC 3/6/14'
+            var d = new Date();
+            var date = (d.getMonth() + 1) + "/" + d.getDate() + "/" + d.getFullYear().toString().slice(-2);
+            var staff_initials = ses('staff').second_given_name();
+            var default_note = 'REC:'+staff_initials+" "+date;
+            default_liNote.setAttribute('value',default_note);
+
+            // Create label for the custom note
+            var liNoteLabel = document.createElement('label');
+            liNoteLabel.setAttribute('id','custom_li_note_label');
+            liNoteLabel.appendChild(document.createTextNode($('catStrings').getString('staff.cat.update_items.lineitem_note.custom')));
+            control_bar.appendChild( liNoteLabel );
+
+            // Align the label so it looks nice
+            liNoteLabel.setAttribute('style', 'line-height:12px;padding-top:6px;');
+
+            // Make the textbox
+            var liNote = document.createElement('textbox');
+            liNote.setAttribute('id','custom_li_note');
+            control_bar.appendChild( liNote );
+
+            // Create fields from Edit Items
+            g.retrieve_templates();
+            g.setGridId();
+
+            // To populate g.data with current data
+            g.data.stash_retrieve();
+
+            // g.data.list.au[0].ws_ou() is the current workstations lib id
+            g.init_edit_item_panes(g.data.list.au[0].ws_ou());
+            g.summarize( g.existing_copies );
+            g.render_edit_items_panes();
+
+            // Set the default call number label for dropdown
+            document.getElementById('marc_cn_menulist').selectedIndex = 1;
+        }
+    } catch(E) {
+
+        var err_msg = $("commonStrings").getFormattedString('common.exception', ['cat/volume_copy_creator.js', E]);
+
+        try {
+
+            g.error.sdump('D_ERROR',err_msg);
+        }
+
+        catch(E) {
+
+            dump(err_msg);
+            dump(js2JSON(E));
+        }
+
+        alert(err_msg+": 111");
+    }
+}
+
+g.load_lineitem = function(raw_lineitem_data){
+
+    var raw_data = raw_lineitem_data[0][1];
+    var copyTemplate = raw_lineitem_data[1].acp;
+    var volumeTemplate = raw_lineitem_data[1].acn;
+
+    var volTemplate = [];
+
+    for (var i in volumeTemplate){
+
+        if (volumeTemplate[i] != "copies" &&
+            volumeTemplate[i] != "notes" &&
+            volumeTemplate[i] != "uri_maps" &&
+            volumeTemplate[i] != "uris"){
+
+            volTemplate.push(volumeTemplate[i]);
+        }
+    }
+
+    var copies = [];
+
+    // Load all relevant data structures via raw DB data
+    for (var i in raw_data){
+
+        var status_string = raw_data[i].pop();
+        var copy_data = raw_data[i].slice(0,29);
+        var volume_data = raw_data[i].slice(29,42);
+        var new_volume = new acn();
+
+        for (var m in volTemplate){
+
+            var val = volume_data[m];
+
+            // booleans get a db type assignment
+            val = g.makeDBFriendly(val, new_volume.Structure.fields[m].datatype);
+
+            if (typeof new_volume[volTemplate[m]] == 'function'){
+
+                new_volume[volTemplate[m]](val);
+            }
+
+            else {
+
+                new_volume.a[m] = val;
+            }
+        }
+
+        if (!g.map_acn[new_volume.id()] && new_volume){
+
+            g.map_acn[new_volume.id()] = new_volume;
+
+            if (!g.volumes_by_ou[new_volume.owning_lib()]){
+
+                g.volumes_by_ou[new_volume.owning_lib()] = [];
+            }
+
+            g.volumes_by_ou[new_volume.owning_lib()].push(new_volume.id());
+        }
+
+        else if(new_volume){
+
+            new_volume = g.map_acn[new_volume.id()];
+        }
+
+        var new_copy = new acp();
+
+        for (var m in copyTemplate){
+
+            var val = copy_data[m];
+
+            // booleans get a db type assignment
+            val = g.makeDBFriendly(val, new_copy.Structure.fields[m].datatype);
+
+            if (typeof new_copy[copyTemplate[m]] == 'function'){
+
+                if (copyTemplate[m] == "call_number"){
+
+                    if (new_volume.id() && val == new_volume.id()){
+
+                        new_copy.call_number(new_volume);
+                    }
+
+                    else{
+
+                        new_copy.call_number(val);
+                    }
+                }
+
+                else {
+
+                    new_copy[copyTemplate[m]](val);
+                }
+            }
+
+            else {
+
+                new_copy.a[m] = val;
+            }
+        }
+
+        new_copy.status_string = status_string;
+        copies.push(new_copy);
+    }
+
+    // set the current callnumber label
+    var marc = g.lineitem_list[g.current_lineitem_index][2];
+    g.callnumber_label = marc.replace(/.*<datafield tag="092"/,'');
+    g.callnumber_label = g.callnumber_label.replace(/<\/subfield>.*/,'');
+    g.callnumber_label = g.callnumber_label.replace(/.*<subfield code="a">/,'');
+
+    // Set global copies
+    g.existing_copies = copies || [];
+
+    if (xulG.unified_interface) {
+
+        $('non_unified_buttons').hidden = true;
+
+        xulG.apply_template_to_batch = function(id,value) {
+
+            if (!isNaN(Number(value))) {
+
+                $(id).value = value;
+                util.widgets.dispatch('command',$(id));
+            }
+
+            util.widgets.dispatch('command',$('batch_button'));
+        }
+
+    }
+
+    else {
+
+        $('Create').hidden = true;
+    }
+
+    /***********************************************************************************************************/
+
+    if (g.existing_copies.length > 0) {
+
+        g.set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.label');
+        g.set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.accesskey');
+        g.set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.rebarcode.btn.label');
+        g.set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.rebarcode.btn.accesskey');
+        g.set_attr('Create','label','staff.cat.volume_copy_creator.rebarcode.btn.label');
+        g.set_attr('Create','accesskey','staff.cat.volume_copy_creator.rebarcode.btn.accesskey');
+    }
+
+    else {
+
+        g.set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_create.btn.label');
+        g.set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_create.btn.accesskey');
+        g.set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.create_with_defaults.btn.label');
+        g.set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.create_with_defaults.btn.accesskey');
+        g.set_attr('Create','label','staff.cat.volume_copy_creator.create.btn.label');
+        g.set_attr('Create','accesskey','staff.cat.volume_copy_creator.create.btn.accesskey');
+    }
+
+    var ou_ids = [];
+
+    // Get the default callnumber classification scheme from OU settings
+    // or a reasonable fall-back
+    g.label_class = g.data.hash.aous['cat.default_classification_scheme'];
+
+    // Assign a default value if none was returned
+    // Begin by looking for the "Generic" label class by name
+    if (!g.label_class) {
+
+        for (var i = 0; i < g.data.list.acnc.length; i++) {
+
+            if (g.data.list.acnc[i].name() == 'Generic') {
+
+                g.label_class = g.data.list.acnc[i].id();
+                break;
+            }
+        }
+    }
+    // Maybe this database has renamed or removed their Generic
+    // entry; in that case, just return the first one that we
+    // know exists
+    if (!g.label_class) {
+
+        g.label_class = g.data.list.acnc[0].id();
+    }
+
+
+    /***********************************************************************************************************/
+
+    // Make a lookup object for existing copies keyed on org id and callnumber id, and another keyed on copy id. */
+
+    // g.org_label_existing_copy_map = { ou_id : { vol_id : [ copy1, copy2, ... ] }, ... }
+    g.org_label_existing_copy_map = {};
+
+    // g.id_copy_map = { acp_id : acp, ... }
+    g.id_copy_map = {};
+
+    for (var i = 0; i < g.existing_copies.length; i++) {
+
+        var copy = g.existing_copies[i];
+        g.id_copy_map[ copy.id() ] = copy;
+        var owning_lib;
+
+        if (typeof copy.call_number() == "object" && copy.call_number().owning_lib()){
+
+            owning_lib = copy.call_number().owning_lib();
+        }
+
+        if (!g.org_label_existing_copy_map[ owning_lib ]) {
+
+            ou_ids.push( owning_lib );
+            g.org_label_existing_copy_map[ owning_lib ] = {};
+        }
+
+        if (! g.org_label_existing_copy_map[ owning_lib ][ copy.call_number().id() ]) {
+
+            g.org_label_existing_copy_map[ owning_lib ][ copy.call_number().id() ] = [];
+        }
+
+        g.org_label_existing_copy_map[ owning_lib ][ copy.call_number().id() ].push( copy );
+    }
+
+    g.ou_ids = g.sort_ou_ids(ou_ids);
+
+    /***********************************************************************************************************/
+    /* render the orgs and volumes/input */
+
+    g.render_loaded_lineitem();
+}
+
+/*
+ * This renders all the lineitem data to the screen
+ */
+
+g.render_loaded_lineitem = function(){
+
+    var rows = document.getElementById('rows');
+
+    // For every library
+    for (var i = 0; i < g.ou_ids.length; i++) {
+
+        try {
+
+            var org = g.data.hash.aou[ g.ou_ids[i] ];
+
+            if ( get_bool( g.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) {
+
+                var r = document.createElement('row'); rows.appendChild( r );
+
+                var x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.library_label.value'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.num_of_volumes_label.value'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.call_nums'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value',$("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.num_of_copies'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value',$("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.barcodes'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value',$("catStrings").getString('staff.cat.copy_editor.status'));
+                    x.setAttribute('style','font-weight: bold');
+                x = document.createElement('label'); r.appendChild(x);
+                    x.setAttribute('value',$("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.notes'));
+                    x.setAttribute('style','font-weight: bold');
+
+
+                var row = document.createElement('row');
+                rows.appendChild(row);
+                row.setAttribute('ou_id',g.ou_ids[i]);
+
+                // First render the library label
+                g.render_library_label(row,g.ou_ids[i]);
+
+                // Then enter the number of volumes
+                var num_volumes = g.render_volume_count_entry( rows, row, g.ou_ids[i] );
+
+                var isFirst = true;
+
+                // Draw each volume
+                for (var volume_id in g.org_label_existing_copy_map[g.ou_ids[i]]) {
+
+                    // this draws a volume
+                    g.render_callnumber_copy_count_entry(rows,row,g.ou_ids[i],isFirst, volume_id);
+
+                    isFirst = false;
+                }
+            }
+        }
+
+        catch(E) {
+
+            g.error.sdump('D_ERROR',E);
+        }
+    }
+
+    g.common_ancestor_ou_ids = util.fm_utils.find_common_aou_ancestors( g.ou_ids ).reverse();
+
+    g.load_prefs();
+
+    try {
+
+        $('main').parentNode.scrollLeft = 9999;
+    }
+
+    catch(E) {
+
+        dump('Error in update_items.js, my_init(), trying to auto-scroll to the far right: ' + E + '\n');
+    }
+
+    if (typeof xulG.volume_ui_callback_for_unified_interface == 'function') {
+
+        xulG.volume_ui_callback_for_unified_interface();
+    }
+}
+
+g.render_barcode = function(
+        vol_id,
+        number_of_copies_textbox,
+        barcode_column_box,
+        ou_id,
+        row
+    ) {
+
+    if ( Number( number_of_copies_textbox.value ) > g_max_copies_that_can_be_added_at_a_time_per_volume ) {
+        g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_volume_count_entry.message', [g_max_copies_that_can_be_added_at_a_time_per_volume]),
+            $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.title'),
+            $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.ok_label'),null,null,'');
+        return;
+    }
+
+    var status_column_box = barcode_column_box.nextSibling;
+
+    // if this exists, it's worth killing if the copy no longer exists
+    // otherwise, don't bother
+    if (status_column_box){
+
+        // This will throw an error if status_column_box doesn't exist
+        var note_column_box = status_column_box.nextSibling;
+
+        while (barcode_column_box.childNodes.length > Number(number_of_copies_textbox.value)) {
+
+            barcode_column_box.removeChild( barcode_column_box.lastChild );
+            status_column_box.removeChild( status_column_box.lastChild );
+            note_column_box.removeChild( note_column_box.lastChild );
+        }
+    }
+
+    // Only place this is called
+    g.render_volume_copies(
+        barcode_column_box,
+        vol_id,
+        Number(number_of_copies_textbox.value),
+        ou_id,
+        row
+    );
+}
+
+g.render_library_label = function(row,ou_id) {
+
+    var label = document.createElement('label');
+    row.appendChild(label);
+    label.setAttribute('ou_id',ou_id);
+    label.setAttribute('value',g.data.hash.aou[ ou_id ].shortname());
+}
+
+g.render_volume_count_entry = function(rows,row,ou_id) {
+
+    var hb = document.createElement('vbox');
+    row.appendChild(hb);
+    var tb = document.createElement('textbox');
+    hb.appendChild(tb);
+
+    tb.value = Object.size(g.org_label_existing_copy_map[ou_id]);
+    tb.setAttribute('ou_id',ou_id);
+    tb.setAttribute('size','3');
+    tb.setAttribute('cols','3');
+    tb.setAttribute('rel_vert_pos',rel_vert_pos_volume_count);
+
+    tb.disabled = true;
+    tb.style.color = "#000000";
+
+    return tb.value;
+}
+
+g.render_callnumber_copy_count_entry = function(rows,row,ou_id,isFirst,vol_id){
+
+    var r = row;
+
+    if (!isFirst){
+
+        r = document.createElement('row');
+        r.setAttribute('ou_id',ou_id);
+        rows.appendChild(r);
+
+        for (var i = 0; i < 2; i++){
+
+            var spacer = document.createElement('vbox');
+            r.appendChild(spacer);
+        }
+    }
+
+    /**** CALLNUMBER COLUMN ****/
+    var call_number_node = document.createElement('vbox');
+    r.appendChild(call_number_node);
+
+    call_number_node.width = $('marc_cn').parentNode.boxObject.width;
+    var call_number_textbox = document.createElement('textbox');
+    call_number_node.appendChild(call_number_textbox);
+
+    call_number_textbox.setAttribute('rel_vert_pos',rel_vert_pos_call_number);
+    call_number_textbox.setAttribute('ou_id',ou_id);
+    call_number_textbox.setAttribute('acn_id',vol_id);
+
+    call_number_textbox.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
+
+    // First set the label
+    call_number_textbox.value = g.callnumber_label;
+
+    /**** NUMBER OF COPIES COLUMN ****/
+    var number_of_copies_node = document.createElement('vbox');
+    r.appendChild(number_of_copies_node);
+    var number_of_copies_textbox = document.createElement('textbox');
+    number_of_copies_node.appendChild(number_of_copies_textbox);
+
+    number_of_copies_textbox.setAttribute('size','3'); number_of_copies_textbox.setAttribute('cols','3');
+    number_of_copies_textbox.setAttribute('rel_vert_pos',rel_vert_pos_copy_count);
+    number_of_copies_textbox.setAttribute('ou_id',ou_id);
+
+    number_of_copies_textbox.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
+
+    number_of_copies_textbox.disabled = true;
+    number_of_copies_textbox.style.color = "#000000";
+
+
+    /**** BARCODE COLUMN ****/
+    var barcode_column_box = document.createElement('vbox');
+    r.appendChild(barcode_column_box);
+
+    /**** STATUS COLUMN ****/
+    var status_column_box = document.createElement('vbox');
+    r.appendChild(status_column_box);
+
+    /**** NOTE COLUMN ****/
+    var note_column_box = document.createElement('vbox');
+    r.appendChild(note_column_box);
+
+    try {
+
+        if (g.org_label_existing_copy_map[ou_id]) {
+
+            var num_of_copies = 0;
+
+            if (g.org_label_existing_copy_map[ou_id][vol_id]){
+
+                num_of_copies = g.org_label_existing_copy_map[ou_id][vol_id].length;
+            }
+
+            if (num_of_copies>0) {
+
+                number_of_copies_textbox.value = num_of_copies;
+            }
+        }
+
+        // Grab the node within the row
+        var call_number_node = call_number_textbox.parentNode;
+
+        // Shift to the node to the right to find the number of copies node
+        var number_of_copies_node = call_number_node.nextSibling; /* one over to the right */
+        var number_of_copies_textbox = number_of_copies_node.firstChild;
+
+        // Grab the barcode node
+        var barcode_node = number_of_copies_node.nextSibling;
+
+        var acn_label = call_number_textbox.value;
+
+        call_number_textbox.setAttribute('callkey',acn_label);
+
+        // Only place this is called
+        g.render_barcode(
+            vol_id,
+            number_of_copies_textbox,
+            barcode_node,
+            ou_id,
+            row
+        );
+
+    } catch(E) {
+        alert(E+": 762 - "+JSON.stringify(number_of_copies_textbox));
+    }
+}
+
+g.render_volume_copies = function(barcode_column,acn_id,count,ou_id,row) {
+
+    try {
+
+        // Add the status and note boxes
+        var status_column = barcode_column.nextSibling;
+
+        var note_column = status_column.nextSibling;
+
+        // For each copy
+        for (var i = 0; i < count; i++) {
+
+            var status_string = g.org_label_existing_copy_map[ ou_id ][ acn_id ][i].status_string;
+
+            var barcode_node;
+            var barcode_textbox;
+            var status_node;
+            var status_textbox;
+            var note_node;
+            var note_textbox;
+            var set_handlers = false;
+
+            if (typeof barcode_column.childNodes[i] == 'undefined') {
+
+                barcode_node = document.createElement('hbox');
+                barcode_column.appendChild(barcode_node);
+
+                barcode_textbox = document.createElement('textbox');
+                barcode_node.appendChild(barcode_textbox);
+                barcode_textbox.width = barcode_width;
+                set_handlers = true;
+
+                // Make status
+                status_node = document.createElement('hbox');
+                status_column.appendChild(status_node);
+
+                status_textbox = document.createElement('textbox');
+                status_node.appendChild(status_textbox);
+                status_textbox.value = status_string;
+                status_textbox.disabled = true;
+                status_textbox.style.color = "#000000";
+                status_textbox.width = status_width;
+
+                // Make notes
+                note_node = document.createElement('hbox');
+                note_column.appendChild(note_node);
+
+                note_textbox = document.createElement('textbox');
+
+                if (g.org_label_existing_copy_map[ ou_id ] &&
+                    g.org_label_existing_copy_map[ ou_id ][ acn_id ] &&
+                    g.org_label_existing_copy_map[ ou_id ][ acn_id ].length > n){
+
+                    note_textbox.setAttribute('acp_id',g.org_label_existing_copy_map[ ou_id ][ acn_id ][i].id());
+                }
+
+                else{
+
+                    note_textbox.setAttribute('acp_id',ou_id);
+                }
+
+                note_textbox.setAttribute('ou_id',ou_id);
+                note_textbox.setAttribute('rel_vert_pos',rel_vert_pos_copy_note);
+                note_node.appendChild(note_textbox);
+            }
+
+            barcode_textbox.setAttribute('acn_id',acn_id);
+            barcode_textbox.setAttribute('ou_id',ou_id);
+            barcode_textbox.setAttribute('callkey',acn_id);
+            barcode_textbox.setAttribute('rel_vert_pos',rel_vert_pos_barcode);
+
+            if (!barcode_textbox.value && g.org_label_existing_copy_map[ ou_id ] &&
+                g.org_label_existing_copy_map[ ou_id ][ acn_id ] &&
+                g.org_label_existing_copy_map[ ou_id ][ acn_id ].length > i) {
+
+                barcode_textbox.value = g.org_label_existing_copy_map[ ou_id ][ acn_id ][i].barcode();
+                barcode_textbox.setAttribute('acp_id', g.org_label_existing_copy_map[ ou_id ][ acn_id ][i].id());
+
+                barcode_textbox.select();
+
+                // If this is the first barcode on the page
+                // Set it accordingly to direct focus after load
+                if (! g.first_focus) {
+
+                    g.first_focus = barcode_textbox;
+                }
+            }
+
+            if (g.use_defaults && ! g.first_focus) {
+
+                g.first_focus = barcode_textbox;
+                barcode_textbox.focus();
+            }
+
+            if (set_handlers) {
+
+                util.widgets.apply_vertical_tab_on_enter_handler(
+                    barcode_textbox,
+                    function() { setTimeout(function(){util.widgets.vertical_tab(barcode_textbox);},0); },
+                    function() { }
+                );
+
+                barcode_textbox.addEventListener('change', function(ev) {
+
+                    var barcode = String( ev.target.value ).replace(/\s/g,'');
+
+                    if (barcode != ev.target.value){
+
+                        ev.target.value = barcode;
+                    }
+
+                    if ($('check_barcodes').checked && ! util.barcode.check(barcode) ) {
+
+                        g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_barcode_entry.alert_message', [barcode]),
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_title'),
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_ok_button'),null,null,
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_confirm'));
+                        setTimeout( function() { ev.target.select(); ev.target.focus(); }, 0);
+                    }
+                }, false);
+
+                barcode_textbox.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
+            }
+        }
+
+        if (g.first_focus) {
+
+            g.first_focus.focus();
+        }
+
+    } catch(E) {
+        alert('784 : ' + E);
+        g.error.sdump('D_ERROR','g.render_barcode_entry: ' + E);
+    }
+}
+
+g.generate_barcodes = function() {
+
+    try {
+
+        var nodes = document.getElementsByAttribute('rel_vert_pos',rel_vert_pos_barcode);
+
+        if (nodes.length < 1) { return; }
+
+        var first_barcode = nodes[0].value;
+
+        if (! first_barcode) { return; }
+
+        var barcodes = g.network.simple_request(
+            'AUTOGENERATE_BARCODES',
+            [
+                ses(),
+                first_barcode,
+                nodes.length - 1,
+                $('check_barcodes').checked ? {} : { "checkdigit" : false }
+            ]
+        );
+
+        if (typeof barcodes.ilsevent != 'undefined') {
+
+            throw(barcodes);
+        }
+
+        for (var i = 0; i < barcodes.length; i++) {
+
+            nodes[i+1].value = barcodes[i];
+            nodes[i+1].select();
+            util.widgets.dispatch('change',nodes[i+1]);
+        }
+
+    } catch(E) {
+        g.error.sdump('D_ERROR','g.generate_barcodes: ' + E);
+    }
+}
+
+g.new_acp_id = -1;
+g.new_acn_id = -1;
+
+g.gather_copies = function() {
+
+    try {
+        var nl = document.getElementsByTagName('textbox');
+
+        var copies = g.existing_copies;
+
+        var barcodes = [];
+        var notes = [];
+        var v_count = 0;
+        g.notes = [];
+        var copy_map = {};
+
+        // grab any copy_notes
+        for (var i = 0; i < nl.length; i++) {
+
+            if ( nl[i].getAttribute('rel_vert_pos') == rel_vert_pos_copy_note ){
+
+                notes.push( nl[i] );
+            }
+
+            if ( nl[i].getAttribute('rel_vert_pos') == rel_vert_pos_barcode ) barcodes.push( nl[i] );
+
+            if ( nl[i].getAttribute('rel_vert_pos') == rel_vert_pos_call_number )  {
+
+                v_count++;
+                var ou_id = nl[i].getAttribute('ou_id');
+                var acn_id = nl[i].getAttribute('acn_id');
+
+                if (!acn_id) {
+
+                    acn_id = g.new_acn_id--;
+                    nl[i].setAttribute('acn_id',acn_id);
+                }
+
+                var callnumber = nl[i].value;
+
+                if (!(acn_id in g.map_acn)){
+
+                    // FIXME This needs to create a valid and helpful acn
+                    //var new_volume = new acn();
+                    //new_volume.id(acn_id);
+                    //new_volume.id(acn_id);
+                    //new_volume.id(acn_id);
+                }
+
+                else{
+
+                    // If there's a new label, update it and mark volume as 'changed'
+                    if (g.map_acn[acn_id].label() != callnumber){
+
+                        g.map_acn[acn_id].label(callnumber);
+                        g.map_acn[acn_id].ischanged(get_db_true());
+                    }
+                }
+            }
+        };
+
+        // gather barcode info
+        for (var i = 0; i < barcodes.length; i++) {
+
+            var acp_id = barcodes[i].getAttribute('acp_id') || g.new_acp_id--;
+            var acn_id = barcodes[i].getAttribute('acn_id') || g.new_acn_id--;
+
+            if (acp_id < 0) {
+
+                barcodes[i].setAttribute('acp_id',acp_id);
+            }
+
+            var ou_id = barcodes[i].getAttribute('ou_id');
+            //var callnumber_callkey = barcodes[i].getAttribute('callkey');
+            var barcode = barcodes[i].value;
+
+            copy_map[acp_id] = {"ou_id" : ou_id, "barcode" : barcode, "acn_id" : acn_id }
+
+            var note = notes[i].value;
+
+            if (note !== null && note.length > 0 && barcode !== null && barcode.length > 0){
+
+                //{"value":noteText, "barcode":barcode, "ou_id":ou_id, "acp_id":acp_id, "pub":public}
+                // Need creator
+                var note_data = {};
+                note_data.value = note;
+                note_data.barcode = barcode;
+                note_data.ou_id = ou_id;
+                note_data.acn_id = acn_id;
+                note_data.pub = 'f';
+
+                g.notes.push(note_data);
+            }
+        }
+
+        // Update old copies
+        for (var i in copies){
+
+            if (copies[i].id() in copy_map){
+
+                if (copies[i].barcode() != copy_map[copies[i].id()].barcode){
+
+                    copies[i].barcode(copy_map[copies[i].id()].barcode);
+                    copies[i].a[45] = get_db_true(); // setting ischanged to true
+                }
+
+                if (copies[i].call_number() != copy_map[copies[i].id()].acn_id){
+
+                    copies[i].call_number(copy_map[copies[i].id()].acn_id);
+                    copies[i].a[45] = get_db_true(); // setting ischanged to true
+                }
+
+                delete copy_map[copies[i].id()];
+            }
+
+            else{
+
+                copies[i].isdeleted(get_db_true());
+            }
+        }
+
+        // Get the default copy status; default to "In Process" if unset, per 1.6
+        var normal_ccs = g.data.hash.aous['cat.default_copy_status_normal'] || 5;
+
+        function new_copy(acp_id,ou_id,acn_id,barcode) {
+
+            var copy = new acp();
+            copy.id( acp_id );
+            copy.isnew('1');
+            copy.barcode( barcode );
+            copy.call_number( acn_id );
+            copy.circ_lib(ou_id);
+            /* FIXME -- use constants */
+            copy.deposit(0);
+            copy.price(0);
+            copy.deposit_amount(0);
+            copy.fine_level(2); // Normal
+            copy.loan_duration(2); // Normal
+            copy.location(1); // Stacks
+            copy.status(normal_ccs);
+            copy.circulate(get_db_true());
+            copy.holdable(get_db_true());
+            copy.opac_visible(get_db_true());
+            copy.ref(get_db_false());
+            copy.mint_condition(get_db_true());
+            return copy;
+        }
+
+        // Add new copies
+        for (var i in copy_map){
+
+            var copy = new_copy(i,copy_map[i].ou_id,copy_map[i].acn_id,copy_map[i].barcode);
+            copies.push( copy );
+        }
+
+        xulG.copies = copies;
+        return copies;
+
+    } catch(E) {
+        alert('Error in update_items.js, g.gather_copies():' + E+": 1100");
+    }
+}
+
+g.stash_and_close = function(param) {
+
+    oils_unlock_page();
+
+    try {
+
+        if (g.update_copy_editor_timeoutID) {
+
+            clearTimeout(g.update_copy_editor_timeoutID);
+        }
+
+        var copies;
+
+        if (xulG.unified_interface) {
+
+            g.gather_copies();
+            xulG.refresh_copy_editor();
+            copies = xulG.copies;
+        }
+
+        else {
+
+            copies = g.gather_copies();
+        }
+
+        // Collects and persists lineitem notes
+        g.handle_li_notes();
+        var volume_list = [];
+
+        // fill volume list
+        for (var i in g.map_acn){
+
+            volume_list.push(g.map_acn[i]);
+        }
+
+        // Update volumes
+        var r = g.network.simple_request(
+            'FM_ACN_TREE_UPDATE',
+            [ ses(),volume_list, false, { 'auto_merge_vols' : true } ]
+        );
+
+        if (typeof r.ilsevent != 'undefined') {
+            alert('error with volume update: ' + js2JSON(r));
+        }
+
+               // Check for merged volumes
+        var copy_ids = [];
+
+               for (var c in copies){
+
+            copy_ids.push(copies[c].id());
+        }
+
+        var copies_to_check = g.network.simple_request(
+            'FM_ACP_UNFLESHED_BATCH_RETRIEVE',
+            [ copy_ids ]
+        );
+
+        if (typeof r.ilsevent != 'undefined') {
+            alert('error with volume update: ' + js2JSON(r));
+        }
+
+        var dont_close = false;
+
+        var label_editor_func;
+
+        if (copies.length > 0) {
+
+            var altered_copies = [];
+            var remaining_copies = [];
+
+            for (var c in copies){
+
+                for (var i in copies_to_check){
+
+                    if (copies_to_check[i].id() == copies[c].id()){
+
+                        copies[c].call_number( copies_to_check[i].call_number() );
+
+                        break;
+                    }
+                }
+
+                if(copies[c].ischanged() == get_db_true()
+                || copies[c].isdeleted() == get_db_true()){
+
+                    altered_copies.push(copies[c]);
+                }
+
+                if(copies[c].isdeleted() != get_db_true()){
+
+                    remaining_copies.push(copies[c]);
+                }
+            }
+
+            // User clicked 'Edit then Re-barcode'
+            if (param === 'edit') {
+
+                copies = cat.util.spawn_copy_editor({
+                      'edit' : true
+                    , 'docid' : g.doc_id
+                    , 'copies' : copies
+                    , 'caller_handles_update' : false
+                });
+            }
+
+            // User clicked 'Save'
+            else {
+
+                // Update copies
+                var r = g.network.simple_request(
+                    'FM_ACP_FLESHED_BATCH_UPDATE',
+                    [ ses(),altered_copies, true ]
+                );
+
+                if (r.textcode === 'ITEM_BARCODE_EXISTS') {
+
+                    alert('error with item update: ' + r.desc+": 1184");
+                    dont_close = true;
+                }
+
+                else if (typeof r.ilsevent != 'undefined') {
+
+                    alert('error with copy update:' + js2JSON(r)+": 1188");
+                }
+            }
+
+            try {
+
+                // If there are copy specific notes, persist them
+                if (g.notes.length > 0){
+
+                    r = g.network.simple_request(
+                        'FM_ACPN_BATCH_CREATE',
+                        [ ses(),g.notes ]
+                    );
+
+                                       if (typeof r.ilsevent != 'undefined') {
+
+                                               alert('error with copy note creation: ' + js2JSON(r));
+                                       }
+                }
+
+                //case 1706 /* ITEM_BARCODE_EXISTS */ :
+                if (remaining_copies && remaining_copies.length > 0){
+
+                    if ($('print_labels').checked) {
+
+                        dont_close = true;
+                        var tab_name = $("catStrings").getString('staff.cat.util.spine_editor.tab_name');
+                        var worksheet_tab_name = $("catStrings").getString('staff.cat.util.print_worksheet.tab_name') + g.lineitem_list[g.current_lineitem_index][0];
+
+                        label_editor_func = function() {
+
+                            xulG.set_tab(
+                                urls.XUL_SPINE_LABEL,
+                                { 'tab_name' : tab_name },
+                                {
+                                    'barcodes' : util.functional.map_list( remaining_copies, function(o){return o.barcode();})
+                                }
+                            );
+                        };
+
+                        // If they're both checked, open this in a new tab
+                        if ($('print_worksheet').checked){
+
+                            label_editor_func = function() {
+
+                                xulG.set_tab(
+                                    urls.PRINT_LINEITEM_WORKSHEET
+                                        + g.lineitem_list[g.current_lineitem_index][0],
+                                    { 'tab_name' : worksheet_tab_name }
+                                );
+
+                                xulG.new_tab(
+                                    urls.XUL_SPINE_LABEL,
+                                    { 'tab_name' : tab_name },
+                                    {
+                                        'barcodes' : util.functional.map_list( remaining_copies, function(o){return o.barcode();})
+                                    }
+                                );
+                            };
+                        }
+                    }
+
+                    else if ($('print_worksheet').checked){
+
+                        dont_close = true;
+
+                        xulG.set_tab(
+                            urls.PRINT_LINEITEM_WORKSHEET + g.lineitem_list[g.current_lineitem_index][0]
+                        );
+
+                    }
+                }
+            } catch(E) {
+                alert('2: Error in update_items.js with g.stash_and_close(): ' + E+": 1210");
+            }
+        }
+
+        try { if (typeof window.refresh == 'function') { window.refresh(); } } catch(E) { dump(E+'\n'); }
+        try { if (typeof g.refresh == 'function') { g.refresh(); } } catch(E) { dump(E+'\n'); }
+
+        if (typeof xulG.unlock_copy_editor == 'function') {
+
+            xulG.unlock_copy_editor();
+        }
+
+        if (typeof xulG.reload_opac == 'function') {
+
+            xulG.reload_opac();
+        }
+
+        if (xul_param('load_opac_when_done')) {
+
+            var opac_url = xulG.url_prefix('opac_rdetail') + g.doc_id;
+            var content_params = {
+                'session' : ses(),
+                'authtime' : ses('authtime'),
+                'opac_url' : opac_url
+            };
+
+            xulG.set_tab(
+                xulG.url_prefix('XUL_OPAC_WRAPPER'),
+                {
+                    'tab_name':'Retrieving title...',
+                    'on_tab_load' : function(cw) {
+                        if (typeof label_editor_func == 'function') {
+                            label_editor_func();
+                        }
+                    }
+                },
+                content_params
+            );
+        }
+
+        else {
+
+            if (typeof label_editor_func == 'function') {
+
+                label_editor_func();
+            }
+
+            if (! dont_close) { xulG.close_tab(); }
+        }
+
+    } catch(E) {
+        alert('3: Error in update_items.js with g.stash_and_close(): ' + E+": 1251");
+    }
+}
+
+// This decides whether lineitem notes should be persisted
+// and persists accordingly
+g.handle_li_notes = function() {
+
+    var notes_to_add = [];
+
+    // get default note
+    var df_el = document.getElementById('default_li_note');
+    var df_li_note = df_el.value;
+
+    // Only add the default note if the checkbox is checked and there's a note there...
+    if ($('li_note_checkbox').checked && df_li_note && df_li_note.length > 0){
+
+        var note = new fieldmapper.acqlin();
+        note.isnew(true);
+
+        // Assume the note is not vendor public for now
+        note.vendor_public(false);
+        note.value(df_li_note);
+
+        // Set the current lineitem id
+        note.lineitem(g.lineitem_list[g.current_lineitem_index][0]);
+
+        notes_to_add.push(note);
+    }
+
+    // get custom note
+    var el = document.getElementById('custom_li_note');
+    var cu_li_note = el.value;
+
+    // Only add the custom note if the checkbox is checked and there's a note there...
+    if (cu_li_note && cu_li_note.length > 0){
+
+        var note = new fieldmapper.acqlin();
+        note.isnew(true);
+
+        // Assume the note is not vendor public for now
+        note.vendor_public(false);
+        note.value(cu_li_note);
+
+        // Set the current lineitem id
+        note.lineitem(g.lineitem_list[g.current_lineitem_index][0]);
+
+        notes_to_add.push(note);
+    }
+
+    // If we end up with notes to persist, persist them!
+    if (notes_to_add.length > 0){
+
+        var r = g.network.simple_request(
+        'FM_CUD_LI_NOTE',
+        [ ses(), notes_to_add]);
+
+        if (typeof r.ilsevent != 'undefined') {
+
+                       alert('error with lineitem note creation: ' + js2JSON(r));
+               }
+    }
+}
+
+g.load_prefs = function() {
+    try {
+
+        var file = new util.file('volume_copy_creator.prefs');
+
+        if (file._file.exists()) {
+
+            var prefs = file.get_object();
+            file.close();
+
+            if (prefs.check_barcodes) {
+
+                if ( prefs.check_barcodes == 'false' ) {
+
+                    $('check_barcodes').checked = false;
+                }
+
+                else {
+
+                    $('check_barcodes').checked = prefs.check_barcodes;
+                }
+            }
+
+            else {
+
+                $('check_barcodes').checked = false;
+            }
+
+            if (prefs.print_labels) {
+
+                if ( prefs.print_labels == 'false' ) {
+
+                    $('print_labels').checked = false;
+                }
+
+                else {
+
+                    $('print_labels').checked = prefs.print_labels;
+                }
+            }
+
+            else {
+
+                $('print_labels').checked = false;
+            }
+
+        }
+    } catch(E) {
+        alert('Error in update_items.js with g.load_prefs(): ' + E+": 1281");
+    }
+}
+
+g.save_prefs = function () {
+
+    try {
+
+        var file = new util.file('volume_copy_creator.prefs');
+
+        file.set_object(
+            {
+                'check_barcodes' : $('check_barcodes').checked,
+                'print_labels' : $('print_labels').checked,
+            }
+        );
+
+        file.close();
+    } catch(E) {
+        alert('Error in update_items.js with g.save_prefs(): ' + E+": 1296");
+    }
+}
+
+g.render_batch_button = function() {
+
+    var hbox = $('batch_button_box');
+    var btn = document.createElement('button');
+    btn.setAttribute('id','batch_button');
+    btn.setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.label'));
+    btn.setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.accesskey'));
+    btn.setAttribute('image','/xul/server/skin/media/images/down_arrow.gif');
+    hbox.appendChild(btn);
+    btn.addEventListener(
+        'command',
+        function() {
+
+            var nl = document.getElementsByTagName('textbox');
+            var label =  $('marc_cn').firstChild.value;
+
+            if (label != '') {
+
+                for (var i = 0; i < nl.length; i++) {
+
+                    /* label */
+                    if (nl[i].getAttribute('rel_vert_pos')==rel_vert_pos_call_number && !nl[i].disabled) {
+
+                        nl[i].value = label;
+                    }
+                }
+
+                for (var i in g.map_acn){
+
+                    if (g.map_acn[i].label() != label){
+
+                        g.map_acn[i].label(label);
+                        g.map_acn[acn_id].ischanged(get_db_true());
+                    }
+                }
+            }
+
+            if (g.last_focus){
+
+                g.last_focus.focus();
+            }
+        },
+        false
+    );
+}
+
+g.setGridId = function() {
+
+    $('rows').parentNode.setAttribute('id','mainGrid');
+
+    //alert(new XMLSerializer().serializeToString($('mainGrid')));
+    //alert($('mainGrid').getAttribute('width') + " out of " + $('cat_volume_copy_creator_win').getAttribute('width'));
+}
+
+g.render_lineitem_dropdown = function() {
+
+    var PO_lineitem_list = [];
+    var menulist = document.createElement('menulist');
+    var hbox = $('lineitem_menulist');
+
+    hbox.appendChild(menulist);
+    menulist.width = barcode_width;
+
+    for (var i in g.lineitem_list){
+
+        var po = g.lineitem_list[i][1];
+        var li = g.lineitem_list[i][0];
+        var li_string = "Li:"+li+" PO:"+po;
+
+        var item = menulist.appendItem( li_string, i );
+    }
+
+    menulist.selectedIndex = 0;
+
+    menulist.addEventListener(
+        'command',
+        function(ev) {
+
+            g.current_lineitem_index = menulist.getIndexOfItem( menulist.selectedItem );
+            g.reset_lineitem();
+            g.summarize( g.existing_copies );
+            g.render_edit_items_panes();
+        },
+        false
+    );
+}
+
+g.remove_lineitem_data = function(){
+
+    var rows = document.getElementById('rows');
+    var row_list = rows.childNodes;
+
+    while(row_list.length > 1){
+
+        if (row_list[0].id != "batch_bar"){
+
+            rows.removeChild(row_list[0]);
+        }
+
+        else{
+
+            rows.removeChild(row_list[1]);
+        }
+    }
+
+    for (var i = 0; i < row_list.length; i++){
+
+        if (!(row_list[i].id && row_list[i].id == "batch_bar")){
+
+            rows.removeChild(row_list[i]);
+        }
+    }
+}
+
+g.reset_lineitem = function(){
+
+    g.remove_lineitem_data();
+
+    g.load_lineitem_by_id();
+}
+
+g.load_lineitem_by_id = function(){
+
+    var raw_lineitem_data = g.network.simple_request(
+        'FM_OPEN_LI_RETRIEVE_BY_ID',
+        [ ses(), g.lineitem_list[g.current_lineitem_index][0] ]
+    );
+
+       if (typeof raw_lineitem_data.ilsevent != 'undefined') {
+
+               alert('error with load: ' + js2JSON(r));
+       }
+
+    var raw_data = raw_lineitem_data[0];
+    raw_lineitem_data[0] = [null];
+    raw_lineitem_data[0].push(raw_data);
+
+    g.load_lineitem(raw_lineitem_data);
+}
+
+g.sort_ou_ids = function(ou_ids){
+
+    if (typeof g.data.hash.aou == 'undefined'){
+
+        return ou_ids;
+    }
+
+    var id = ou_ids.pop();
+
+    var smaller = [];
+    var bigger = [];
+
+    for (var i in ou_ids){
+
+        if (g.data.hash.aou[ ou_ids[i] ].shortname() < g.data.hash.aou[ id ].shortname()){
+
+            smaller.push(ou_ids[i]);
+        }
+
+        else{
+
+            bigger.push(ou_ids[i]);
+        }
+    }
+
+    if (smaller.length > 1){
+
+        smaller = g.sort_ou_ids(smaller);
+    }
+
+    smaller.push(id);
+
+    if (bigger.length > 1){
+
+        bigger = g.sort_ou_ids(bigger);
+    }
+
+    return smaller.concat(bigger);
+}
+
+g.makeDBFriendly = function(data, datatype){
+
+    // booleans get a db type assignment
+    if (datatype == "bool"){
+
+        if (data){
+
+            data = "t";
+        }
+
+        else{
+
+            data = "f";
+        }
+    }
+
+    return data;
+}
+
+g.set_attr = function(id,attr,msgcat_key) {
+
+    var x = $(id);
+
+    if (x) {
+
+        x.setAttribute(
+            attr,
+            $('catStrings').getString(msgcat_key)
+        );
+    }
+}
+
+/* The following functions were ported wholesale from copy_editor.js in 
+ * order to port the fields and functionality for Price, Circulate, 
+ * Location/Collection, Circulation Modifier, and Templates
+ */
+
+/******************************************************************************************************/
+/* This keeps track of which fields have been edited for styling purposes */
+
+g.changed = {};
+
+/******************************************************************************************************/
+/* This keeps track of which fields are required, and which fields have been populated */
+
+g.required = {};
+g.populated = {};
+
+// I'm assuming this will simply apply whatever change was made to any 
+// given field when the 'Apply' button is clicked for that field
+g.apply = function(field,value) {
+    g.error.sdump('D_TRACE','applying field = <' + field + '>  value = <' + value + '>\n');
+    if (value == '<HACK:KLUDGE:NULL>') {
+        value = null;
+    }
+    if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
+    if (field == 'price' || field == 'deposit_amount') {
+        if (value == '') {
+            value = null;
+        } else {
+            value = util.money.sanitize( value );
+        }
+    }
+    for (var i = 0; i < g.existing_copies.length; i++) {
+        var copy = g.existing_copies[i];
+        try {
+            copy[field]( value ); copy.ischanged('1');
+        } catch(E) {
+            alert(E);
+        }
+    }
+
+    oils_lock_page();
+}
+
+// This appears to be required by g.apply_template
+g.applied_templates = [];
+
+// This applies the template selected to all the copies on the page
+g.apply_template = function() {
+
+    try {
+
+        var name = g.template_menu.value;
+
+        if (g.templates[ name ] != 'undefined') {
+
+            var template = g.templates[ name ];
+
+            for (var i in template) {
+
+                if (template[i].field == 'status') {
+
+                    if (!g.safe_to_edit_copy_status()) {
+
+                        alert($('catStrings').getFormattedString('staff.cat.copy_editor.apply_unsafe_field',[i]));
+                        continue;
+                    }
+                }
+
+                g.changed[ i ] = template[ i ];
+
+                switch( template[i].type ) {
+
+                    case 'attribute' :
+
+                        g.apply(template[i].field,template[i].value);
+                    break;
+                    case 'stat_cat' :
+
+                        if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
+                    break;
+                    case 'owning_lib' :
+
+                        g.apply_owning_lib(template[i].value);
+                    break;
+                    case 'volume_copy_creator' :
+
+                        if (xulG.unified_interface) {
+                            xulG.apply_template_to_batch(template[i].field,template[i].value);
+                        }
+                    break;
+                }
+            }
+
+            g.summarize( g.existing_copies );
+            g.render_edit_items_panes();
+        }
+    } 
+
+    catch(E) {
+
+        alert('Error in copy_editor.js, g.apply_template('+name+'): ' + E);
+    }
+}
+
+// This appears to load all the templates specific to the user to the
+// templates dropdown.  Includes button functionality that will probably
+// need to be stripped out
+
+/* Retrieve Templates */
+
+g.retrieve_templates = function() {
+
+    try {
+
+        g.templates = {};
+        var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
+
+        if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
+
+            g.templates = robj['staff_client.copy_editor.templates'];
+        }
+
+        var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } ).sort();
+
+        g.template_menu = util.widgets.make_menulist( list );
+        g.template_menu.setAttribute('id','template_menu');
+        $('template_placeholder').appendChild(g.template_menu);
+        g.template_menu.addEventListener(
+            'command',
+            function() { g.apply_template(); },
+            false
+        );
+    } 
+
+    catch(E) {
+
+        g.error.standard_unexpected_error_alert($('catStrings').getString('staff.cat.copy_editor.retrieve_templates.error'), E);
+    }
+}
+
+/******************************************************************************************************/
+/* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
+
+g.safe_to_edit_copy_status = function() {
+    try {
+        var safe = true;
+        for (var i = 0; i < g.existing_copies.length; i++) {
+            var status = g.existing_copies[i].status(); if (typeof status == 'object') status = status.id();
+            if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
+        }
+        return safe;
+    } catch(E) {
+        g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
+        return false;
+    }
+}
+
+
+/******************************************************************************************************/
+/* This actually draws the change button and input widget for a given field */
+g.render_input = function(node,blob) {
+    try {
+        // node = hbox ;    groupbox ->  hbox, hbox
+
+        var groupbox = node.parentNode;
+        var caption = groupbox.firstChild;
+        var vbox = node.previousSibling;
+        var hbox = node;
+        var hbox2 = node.nextSibling;
+
+        var input_cmd = blob.input;
+        var render_cmd = blob.render;
+        var attr = blob.attr;
+
+        var block = false;
+        var first = true;
+
+        function on_mouseover(ev) {
+
+            groupbox.setAttribute('style','background: white');
+        }
+
+        function on_mouseout(ev) {
+
+            groupbox.setAttribute('style','');
+        }
+
+        groupbox.addEventListener('mouseover',on_mouseover,false);
+        groupbox.addEventListener('mouseout',on_mouseout,false);
+
+        function on_click(ev){
+
+            try {
+
+                if (block || g.disabled || ev.currentTarget.classList.contains('disabled')) {
+
+                    return;
+                }
+
+                block = true;
+
+                oils_lock_page();
+
+                function post_c(v) {
+
+                    try {
+
+                        var f = input_cmd.match(/apply\("(.+?)",/)[1];
+
+                        g.changed[ hbox.id ] = { 'type' : 'attribute', 'field' : f, 'value' : v };
+                        block = false;
+
+                        g.summarize( g.existing_copies );
+                        g.render_edit_items_panes();
+                        document.getElementById(caption.id).focus();
+
+                    } catch(E) {
+
+                        g.error.standard_unexpected_error_alert('post_c',E);
+                    }
+                }
+
+                var x;
+                var c;
+                eval( input_cmd );
+
+                if (x) {
+
+                    util.widgets.remove_children(vbox);
+                    util.widgets.remove_children(hbox);
+                    util.widgets.remove_children(hbox2);
+                    hbox.appendChild(x);
+                    var apply = document.createElement('button');
+                    apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
+                    apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
+                    hbox2.appendChild(apply);
+                    apply.addEventListener('command',function() { c(x.value); },false);
+                    var cancel = document.createElement('button');
+                    cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
+                    cancel.addEventListener('command',function() {
+                            setTimeout( function() {
+                                    g.summarize( g.existing_copies );
+                                    g.render_edit_items_panes();
+                                    g.check_for_unmet_required_fields();
+                                    document.getElementById(caption.id).focus(); 
+                                }, 0
+                            );
+                        }, false
+                    );
+                    hbox2.appendChild(cancel);
+                    setTimeout( function() { x.focus(); }, 0 );
+                }
+            } catch(E) {
+                g.error.standard_unexpected_error_alert('render_input',E);
+            }
+        }
+        groupbox.addEventListener('click',on_click, false);
+        groupbox.addEventListener('keypress',function(ev) {
+            if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
+        }, false);
+        caption.setAttribute('style','-moz-user-focus: normal');
+        caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
+        caption.setAttribute('onblur','this.setAttribute("class","")');
+
+    } catch(E) {
+        g.error.sdump('D_ERROR',E + '\n');
+    }
+}
+
+// This is a really ... interesting way to define the attributes for each Edit Items field
+g.init_edit_item_panes = function(lib_for_location_list) {
+
+    g.panes_and_field_names = {
+
+        'left_pane' :
+        [
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.circulation_modifier.label'),
+                {    
+                    render: 'fm.circ_modifier() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : $("commonStrings").getFormattedString("staff.circ_modifier.display",[fm.circ_modifier(),g.data.hash.ccm[fm.circ_modifier()].name(),g.data.hash.ccm[fm.circ_modifier()].description()])',
+                    input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null"), "<HACK:KLUDGE:NULL>" ] ].concat( util.functional.map_list( g.data.list.ccm, function(obj) { return [ $("commonStrings").getFormattedString("staff.circ_modifier.display",[obj.code(),obj.name(),obj.description()]), obj.code() ]; } ).sort() ) ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.location.label'),
+                { 
+                    render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()', 
+                    input: 'c = function(v){ g.apply("location",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.get_acpl_list(' + lib_for_location_list + '), function(obj) { return [ ' + (g.cl_first ? 'obj.name() + " : " + g.data.hash.aou[ obj.owning_lib() ].shortname()' : 'g.data.hash.aou[ obj.owning_lib() ].shortname() + " : " + obj.name()') + ', obj.id() ]; }).sort()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+                }
+            ]
+        ],
+
+        'right_pane' :
+        [
+
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.circulate.label'),
+                {     
+                    render: 'fm.circulate() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : ( get_bool( fm.circulate() ) ? $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true") : $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false") )',
+                    input: 'c = function(v){ g.apply("circulate",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true"), get_db_true() ], [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false"), get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.price.label'),
+                { 
+                    render: 'if (fm.price() == null) { $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null"); } else { util.money.sanitize( fm.price() ); }', 
+                    input: 'c = function(v){ g.apply("price",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                }
+            ]
+        ]
+    };
+}
+
+/******************************************************************************************************/
+/* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+g.summarize = function( copies ) {
+
+    /******************************************************************************************************/
+    /* Setup */
+
+    g.summary = {};
+    g.field_names = [];
+
+    for (var i in g.panes_and_field_names) {
+
+        g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
+    }
+
+    /******************************************************************************************************/
+    /* Loop through the field names */
+
+    for (var i = 0; i < g.field_names.length; i++) {
+
+        var field_name = g.field_names[i][0];
+        var render = g.field_names[i][1].render;
+        var attr = g.field_names[i][1].attr;
+        g.summary[ field_name ] = {};
+        g.populated[ field_name ] = 1; // delete later if we encounter a copy with the field unset
+
+        /******************************************************************************************************/
+        /* Loop through the copies */
+
+        for (var j = 0; j < copies.length; j++) {
+
+            var fm = copies[j];
+            var value = $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null");
+
+            /**********************************************************************************************/
+            /* Try to retrieve the value for this field for this copy */
+
+            try { 
+
+                value = eval( render ); 
+            } 
+
+            catch(E) { 
+
+                g.error.sdump('D_ERROR','Attempted ' + render + '\n' +  E + '\n'); 
+            }
+
+            if (typeof value == 'object' && value != null) {
+
+                alert('FIXME: field_name = <' + field_name + '>  value = <' + js2JSON(value) + '>\n');
+            }
+
+            if (value == $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null")) {
+
+                delete g.populated[field_name];
+            }
+
+            /**********************************************************************************************/
+            /* Tally the count */
+
+            if (g.summary[ field_name ][ value ]) {
+
+                g.summary[ field_name ][ value ]++;
+            } 
+
+            else {
+
+                g.summary[ field_name ][ value ] = 1;
+            }
+        }
+    }
+
+    g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
+}
+
+/******************************************************************************************************/
+/* Display the summarized data and inputs for editing */
+
+g.render_edit_items_panes = function() {
+
+    /******************************************************************************************************/
+    /* Library setup and clear any existing interface */
+
+    for (var i in g.panes_and_field_names) {
+
+        var p = document.getElementById(i);
+        if (p) util.widgets.remove_children(p);
+    }
+
+    /******************************************************************************************************/
+    /* Prepare the panes */
+
+    var groupbox;
+    var caption;
+    var vbox;
+    var grid;
+    var rows;
+    
+    /******************************************************************************************************/
+    /* Loop through the field names */
+
+    for (h in g.panes_and_field_names) {
+
+        if (document.getElementById(h)){
+
+            for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
+
+                try {
+
+                    var f = g.panes_and_field_names[h][i];
+                    var fn = f[0];
+                    var attr = f[1].attr;
+                    groupbox = document.createElement('groupbox');
+                    document.getElementById(h).appendChild(groupbox);
+                    groupbox.setAttribute('hideable',fn);
+
+                    if (attr) {
+
+                        for (var a in attr) {
+
+                            groupbox.setAttribute(a,attr[a]);
+                        }
+                    }
+
+                    caption = document.createElement('caption');
+                    groupbox.appendChild(caption);
+                    caption.setAttribute('label',fn);
+                    caption.setAttribute('id','caption_'+fn); // used for focus/keyboard navigation
+                    caption.setAttribute('hideable',fn);
+                    vbox = document.createElement('vbox');
+                    groupbox.appendChild(vbox); // main display widget goes here
+
+                    if (typeof g.changed[fn] != 'undefined') {
+
+                        addCSSClass(vbox,'copy_editor_field_changed');
+                    }
+
+                    if (typeof g.required[fn] != 'undefined') {
+
+                        addCSSClass(vbox,'copy_editor_field_required');
+                    }
+
+                    grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] );
+                    vbox.appendChild(grid);
+                    grid.setAttribute('flex','1');
+                    rows = grid.lastChild;
+                    var row;
+                    
+                    /**************************************************************************************/
+                    /* Loop through each value for the field */
+
+                    for (var j in g.summary[fn]) {
+
+                        var value = j;
+                        var count = g.summary[fn][j];
+                        row = document.createElement('row');
+                        rows.appendChild(row);
+                        var label1 = document.createElement('description');
+                        row.appendChild(label1);
+
+                        label1.appendChild( document.createTextNode(value) );
+
+                        var label2 = document.createElement('description');
+                        row.appendChild(label2);
+                        var copy_count;
+
+                        if (count == 1) {
+
+                            copy_count = $('catStrings').getString('staff.cat.copy_editor.copy_count');
+                        }
+
+                        else {
+
+                            copy_count = $('catStrings').getFormattedString('staff.cat.copy_editor.copy_count.plural', [count]);
+                        }
+
+                        label2.appendChild( document.createTextNode(copy_count) );
+                    }
+
+                    groupbox.setAttribute('id','groupbox_'+fn); // this id is meant to be referenced by cat_custom.css for hiding fields
+                    var hbox = document.createElement('hbox'); // main input controls go here
+                    hbox.setAttribute('id',fn); // this id gets used to color areas green, etc.
+                    groupbox.appendChild(hbox);
+                    var hbox2 = document.createElement('hbox'); // cancel/apply buttons go here
+                    groupbox.appendChild(hbox2);
+
+                    /**************************************************************************************/
+                    /* Render the input widget */
+
+                    if (f[1].input) {
+
+                        g.render_input(hbox,f[1]);
+                    }
+
+                } catch(E) {
+                    g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
+                }
+            }
+        }
+    }
+    
+    
+    /******************************************************************************************************/
+    /* Synchronize stat cat visibility with library filter menu, and default template selection */
+    JSAN.use('util.file'); 
+    var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
+    g.copy_editor_prefs = util.widgets.load_attributes(file);
+    for (var i in g.copy_editor_prefs) {
+        if (i.match(/filter_/) && g.copy_editor_prefs[i].checked == '') {
+            try { 
+                g.toggle_stat_cat_display( document.getElementById(i) ); 
+            } catch(E) { alert(E); }
+        }
+    }
+    if (g.template_menu) {
+        g.template_menu.value = g.template_menu.getAttribute('value');
+        if (xulG.unified_interface) {
+            if (typeof xulG.update_unified_template_selection == 'function') {
+                xulG.update_unified_template_selection(g.template_menu.value);
+            }
+        }
+    }
+
+    util.hide.generate_css('ui.hide_copy_editor_fields');
+}
+
+/******************************************************************************************************/
+/* This returns a list of acpl's appropriate for the copies being edited */
+
+g.get_acpl_list = function(lib_id) {
+
+    try {
+
+        var acpl_list = g.get_acpl_list_for_lib(lib_id);
+
+        var returnList = acpl_list.sort(
+
+            function(a,b) {
+
+                var label_a = g.data.hash.aou[ a.owning_lib() ].shortname() + ' : ' + a.name();
+                var label_b = g.data.hash.aou[ b.owning_lib() ].shortname() + ' : ' + b.name();
+
+                if (label_a < label_b) return -1;
+                if (label_a > label_b) return 1;
+
+                return 0;
+            }
+        );
+
+        return returnList;
+    
+    } catch(E) {
+
+        g.error.standard_unexpected_error_alert('get_acpl_list',E);
+        return [];
+    }
+}
+
+/***************************************************************************************************************/
+/* This returns a list of acpl's appropriate for the copies being edited (and caches them in the global stash) */
+
+g.get_acpl_list_for_lib = function(lib_id) {
+
+    var label = 'acpl_list_for_lib_'+lib_id;
+
+    if (typeof g.data[label] == 'undefined') {
+
+        var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]); // This returns acpl's for all ancestors and descendants as well as the lib
+
+        if (typeof robj.ilsevent != 'undefined') throw(robj);
+
+        var temp_list = [];
+
+        for (var j = 0; j < robj.length; j++) {
+
+            var my_acpl = robj[j];
+
+            if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
+
+                g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
+                g.data.list.acpl.push( my_acpl );
+            }
+
+            temp_list.push( my_acpl );
+        }
+
+        g.data[label] = temp_list;
+        g.data.stash(label,'hash','list');
+    }
+
+    return g.data[label];
+}
+
+Object.size = function(obj) {
+    var size = 0, key;
+    for (key in obj) {
+        if (obj.hasOwnProperty(key)) size++;
+    }
+    return size;
+};
diff --git a/Open-ILS/xul/staff_client/server/cat/update_items.xul b/Open-ILS/xul/staff_client/server/cat/update_items.xul
new file mode 100644 (file)
index 0000000..9b83d17
--- /dev/null
@@ -0,0 +1,147 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="cat_volume_copy_creator_win" 
+    onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }"
+    title="&staff.cat.volume_copy_creator.title;"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+    <!-- BEHAVIOR -->
+    <script type="text/javascript">
+    var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; 
+    </script>
+    <scripts id="openils_util_scripts"/>
+
+    <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+    <script type="text/javascript" src="update_items.js"/>
+    
+    <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+    <messagecatalog id="circStrings" src="/xul/server/locale/<!--#echo var='locale'-->/circ.properties" />
+
+<vbox flex="1" class="my_overflow">
+    <vbox id="summary_box" oils_persist="height"/>
+    <splitter
+        collapse="before"
+        resize_before="flex"
+        resize_after="flex"
+        oils_persist="state hidden"
+        oils_persist_peers="summary_box main">
+        <grippy/>
+    </splitter>
+    <vbox id="main" oils_persist="height" flex="1">
+        <groupbox flex="1" class="my_overflow" orient="horizontal">
+            <caption id="caption" label="Update Items"/>
+            <grid flex="1">
+                <columns> <column/> <column/> <column/> <column/> <column/> <column/> <column/> </columns>
+                <rows id="rows">
+                    <row id="batch_bar">
+                        <spacer />
+                        <spacer />
+                                               <vbox>
+                                                       <label
+                                                               value="&staff.cat.volume_copy_creator.batch_bar.call_number.label.label;"
+                                                               accesskey="&staff.cat.volume_copy_creator.batch_bar.call_number.label.accesskey;"
+                                                               control="marc_cn_menulist" class="header"/>
+                                                       <hbox id="marc_cn"/>
+                                               </vbox>
+                                               <vbox>
+                                                       <label class="header" value="&staff.cat.volume_copy_creator.batch_bar;"/>
+                                                       <hbox id="batch_button_box"/>
+                                               </vbox>
+                                               <vbox>
+                                                       <label class="header" value="Lineitem"/>
+                                                       <hbox id="lineitem_menulist"/>
+                                               </vbox>
+                    </row>
+                </rows>
+            </grid>
+
+
+<!--
+            <grid flex="1">
+
+                               <columns> <column/> <column/> <column/> </columns>
+                               <rows id="edit_items">
+                                       <row id="empty_row"></row>
+                                               <vbox>
+                                                       <spacer />
+                                                       <spacer />
+                                               </vbox>
+                                       <row id="templates">
+                                               <vbox>
+                                                       <label class="header" value="Templates"/>
+                                                       <hbox id="template_placeholder"/>
+                                               </vbox>
+                                       </row>
+                                       <row id="modifier"></row>
+                                       <row id="the_rest"></row>
+                               </rows>
+
+            </grid>
+-->
+
+                       <groupbox flex="1" class="my_overflow" id="edit_items">
+                               <caption id="caption" label="&staff.cat.copy_browser.actions.cmd_edit_items.label;"/>
+
+                               <hbox id="top_nav">
+                                       <hbox id="template_bar" style="background: grey" flex="1">
+                                               <vbox><spacer flex="1"/><label value="&staff.cat.copy_editor.templates.label;" style="font-weight: bold"/><spacer flex="1"/></vbox>
+                                               <hbox id="template_placeholder"/>
+                                       </hbox>
+                               </hbox>
+
+                               <hbox flex="1" style="overflow: scroll">
+                                       <vbox flex="1" id="before_splitter1" oils_persist="width">
+                                               <vbox id="left_pane" flex="1"/>
+                                       </vbox>
+                                       <splitter id="splitter1" oils_persist="state hidden" oils_persist_peers="before_splitter1 after_splitter1"><grippy /></splitter>
+                                       <vbox flex="1" id="after_splitter1" oils_persist="width">
+                                               <vbox id="right_pane" flex="1"/>
+                                       </vbox>
+                               </hbox>
+                       </groupbox>
+        </groupbox>
+        <hbox style="border-bottom: solid black thin">
+            <hbox id="misc_control_bar">
+                <button id="generate_barcodes"
+                    label="&staff.cat.volume_copy_creator.generate_barcodes.label;"
+                    oncommand="g.generate_barcodes();"
+                    accesskey="&staff.cat.volume_copy_creator.generate_barcodes.accesskey;"/>
+                <checkbox id="check_barcodes"
+                    label="&staff.cat.volume_copy_creator.check_barcodes.label;"
+                    oncommand="g.save_prefs();"
+                    accesskey="&staff.cat.volume_copy_creator.check_barcodes.accesskey;"/>
+                <checkbox id="print_labels"
+                    label="&staff.cat.volume_copy_creator.print_labels.label;"
+                    oncommand="g.save_prefs();"
+                    accesskey="&staff.cat.volume_copy_creator.print_labels.accesskey;"/>
+            </hbox>
+            <spacer flex="1"/>
+            <hbox id="non_unified_buttons">
+                <button id="CreateWithDefaults" oncommand="g.stash_and_close('noedit');"/>
+                <button id="EditThenCreate" oncommand="g.stash_and_close('edit');"/>
+            </hbox>
+            <button id="Create" disabled="true" oncommand="g.stash_and_close('unified_interface');"/>
+        </hbox>
+    </vbox>
+</vbox>
+
+</window>
+
index eeda8a5..9cf3260 100644 (file)
@@ -966,7 +966,7 @@ cat.util.mark_item_as_missing_pieces = function(copy_ids) {
     }
 }
 
-cat.util.render_callnumbers_for_bib_menu = function(node, doc_id, label_class) {
+cat.util.render_callnumbers_for_bib_menu = function(node, doc_id, label_class, width) {
     try {
         var cn_blob;
         try {
@@ -992,7 +992,17 @@ cat.util.render_callnumbers_for_bib_menu = function(node, doc_id, label_class) {
             )
         ); hbox.appendChild(ml);
         ml.setAttribute('editable','true');
-        ml.setAttribute('width', '200');
+
+        if (width){
+
+            ml.setAttribute('width', width);
+        }
+
+        else{
+
+            ml.setAttribute('width', '200');
+        }
+
         ml.setAttribute('id', hbox.id + '_menulist');
     } catch(E) {
         alert('Error in cat.util.render_callnumbers_for_bib_menu: ' + E);
index 9279234..43399fc 100644 (file)
@@ -355,6 +355,7 @@ staff.cat.util.transfer_copies.aborted_transfer=Transfer Aborted
 staff.cat.util.transfer_copies.override_transfer_failure=Override Transfer Failure?
 staff.cat.util.transfer_copies.successful_transfer=Items transferred.
 staff.cat.util.transfer_copies.transfer_error=All items not likely transferred.
+staff.cat.util.print_worksheet.tab_name=Worksheet for Lineitem #
 staff.cat.util.spine_editor.tab_name=Spine Labels
 staff.cat.util.spine_editor.spine_editor_error=Spine Labels
 staff.cat.util.show_in_opac.unknown_barcode=%1$s is not cataloged
@@ -428,17 +429,21 @@ staff.cat.volume_copy_creator.create.btn.label=Create Volumes/Items
 staff.cat.volume_copy_creator.create.btn.accesskey=C
 staff.cat.volume_copy_creator.edit_then_rebarcode.btn.label=Edit then Re-barcode
 staff.cat.volume_copy_creator.edit_then_rebarcode.btn.accesskey=E
-staff.cat.volume_copy_creator.rebarcode.btn.label=Re-barcode / Update Items
-staff.cat.volume_copy_creator.rebarcode.btn.accesskey=R
+staff.cat.volume_copy_creator.rebarcode.btn.label=Save
+staff.cat.volume_copy_creator.rebarcode.btn.accesskey=S
 staff.cat.volume_copy_creator.render_volume_count_entry.message=You may not add more than %1$s items at a time for a given volume in this interface.
 staff.cat.volume_copy_creator.render_volume_count_entry.title=Maximum items exceeded.
 staff.cat.volume_copy_creator.render_volume_count_entry.ok_label=Ok
+staff.cat.volume_copy_creator.library_label.value=Library
+staff.cat.volume_copy_creator.num_of_volumes_label.value=# of volumes
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.classification=Classification
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.prefix=Prefix
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.call_nums=Call Number
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.suffix=Suffix
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.num_of_copies=# of Copies
 staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.barcodes_and_parts=Barcode / Part Designation
+staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.barcodes=Barcode
+staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.notes=Copy Note
 staff.cat.volume_copy_creator.render_barcode_entry.alert_message="%1$s" is an invalid barcode.
 staff.cat.volume_copy_creator.render_barcode_entry.alert_title=Invalid Barcode
 staff.cat.volume_copy_creator.render_barcode_entry.alert_ok_button=OK
@@ -452,6 +457,10 @@ staff.cat.volume_copy_creator.save_prefs.err_storing_prefs=Error storing prefere
 staff.cat.volume_copy_creator.call_number_prefix.menuitem_label=%2$s : %1$s
 # %1$s = Call Number Suffix Label, %2$s = Call Number Suffix Owning Lib Shortname
 staff.cat.volume_copy_creator.call_number_suffix.menuitem_label=%2$s : %1$s
+staff.cat.update_items.lineitem_note.custom=Additional Note:
+staff.cat.update_items.lineitem_note.default=Add Notes?
+staff.cat.update_items.print_worksheet=Print Worksheet?
+staff.cat.update_items.print_worksheet.accesskey=W
 staff.cat.z3950.native_catalog=Native Catalog
 staff.cat.z3950.obj_list_init.list_construction_error=Failure during list construction.
 staff.cat.z3950.results_view.label=Results View