enhancements based on feedback from CW/MARS
authorJason Etheridge <jason@esilibrary.com>
Thu, 21 Feb 2013 23:48:39 +0000 (18:48 -0500)
committerJason Etheridge <jason@esilibrary.com>
Mon, 7 Mar 2016 18:56:54 +0000 (13:56 -0500)
Thanks!  Major changes includes different patron summary panes based on context,
removal of the new-tab behavior when selecting different patron interfaces, and
having the patron summary pane for searches replace the search form instead of
the list results (I wonder if catalogers would want similar behavior in the
z39.50 interface...)

For the search interface, the summary pane is mostly used to help identify
patrons, and thus focuses on displaying identifying information like addresses
and phone numbers.

For the patron interface, the summary pane focuses mostly on statuses, alerts,
and notifications.

I've backed away a little bit from the "only show information if it exists"
philosophy.  Another school of thought is that information should always be
in the same place to take advantage of spatial memory.  I was hedging my bets
before by hoping column position would be enough for spatial memory.  It might
still be true, but here's to experimentation. :)

For switching between patron interfaces, the different components are still
disintegrated, and get completely reloaded on context switch, including the
summary pane.  I fear this is going to be very noticeable, but it'll take a
major overhaul to have persistently loaded sub-interfaces that stay in sync.

Still, the load times for retrieving a patron are much faster this way, plus
this wrapper for the sub-interfaces is likely easier to maintain, and likely
less of a source of memory leaks than before.

Signed-off-by: Jason Etheridge <jason@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/PatronSummary.pm
Open-ILS/src/templates/opac/PatronSearchSummary.tt2 [new file with mode: 0644]
Open-ILS/src/templates/opac/PatronSummary.tt2
Open-ILS/src/templates/opac/css/PatronSummary.css.tt2
Open-ILS/xul/staff_client/chrome/content/main/constants.js
Open-ILS/xul/staff_client/server/patron/display.xul
Open-ILS/xul/staff_client/server/patron/patron.js
Open-ILS/xul/staff_client/server/patron/search.js
Open-ILS/xul/staff_client/server/patron/search_result.js

index dd7dc85..1bbf2a3 100644 (file)
@@ -208,6 +208,7 @@ sub load {
     return $self->load_myopac_prefs if $path =~ m|opac/myopac/prefs|;
     return $self->load_sms_cn if $path =~ m|opac/sms_cn|;
     return $self->load_patron_summary if $path =~ m|opac/PatronSummary|;
+    return $self->load_patron_summary if $path =~ m|opac/PatronSearchSummary|;
 
     return Apache2::Const::OK;
 }
index 06c4e2a..a751333 100644 (file)
@@ -46,7 +46,9 @@ sub load_patron_summary {
             'standing_penalties',
             'notes',
             'usr_activity',
-            'ident_type'
+            'home_ou',
+            'ident_type',
+            'ident_type2'
         ]
     );
 
diff --git a/Open-ILS/src/templates/opac/PatronSearchSummary.tt2 b/Open-ILS/src/templates/opac/PatronSearchSummary.tt2
new file mode 100644 (file)
index 0000000..0ca1d64
--- /dev/null
@@ -0,0 +1,123 @@
+[%  PROCESS "opac/parts/header.tt2";
+    WRAPPER "base_nodojo.tt2"
+        extracss="/eg/opac/css/PatronSummary.css";
+    ctx.page_title = l("Patron Summary") %]
+    <div id="content-wrapper">
+        <div id="main-content" class="[% ctx.css_classnames %]">
+            <div class="common-full-pad" style="float:none"></div>
+            [% IF NOT ctx.error %]
+            <div class="table patronSummaryDiv">
+                <div class="row"><div class="cell">
+                    <div class="textBackground">
+                        <span class="patronNameLarge">
+                            [% l(
+                                HUMAN_NAME_FORMAT,
+                                ctx.user.prefix, ctx.user.first_given_name,
+                                ctx.user.second_given_name, ctx.user.family_name,
+                                ctx.user.suffix
+                            ) | html %]
+                        </span><br/>
+                        [% IF ctx.user.mailing_address %]
+                        <span>
+                            [% ctx.user.mailing_address.street1 | html %]<br/>
+                            [% ctx.user.mailing_address.street2 | html %]<br/>
+                            [% ctx.user.mailing_address.city | html %],
+                            [% ctx.user.mailing_address.state | html %]
+                            [% ctx.user.mailing_address.post_code | html %]
+                        </span><br/>
+                        [% END %]
+                    </div>
+                </div><div class="cell">
+                    <div class="textBackground">
+                        <span>
+                            [% ctx.user.email OR ' ' | html %]
+                        </span></br>
+                        [% IF ctx.user.billing_address %]
+                        <span>
+                            [% ctx.user.billing_address.street1 | html %]<br/>
+                            [% ctx.user.billing_address.street2 | html %]<br/>
+                            [% ctx.user.billing_address.city | html %],
+                            [% ctx.user.billing_address.state | html %]
+                            [% ctx.user.billing_address.post_code | html %]
+                        </span><br/>
+                        [% END %]
+                    </div>
+                </div><div class="cell">
+                    <div class="textBackground">
+                        <span>
+                            [% l('D: [_1] ', ctx.user.day_phone) | html %]<br/>
+                            [% l('E: [_1] ', ctx.user.evening_phone) | html %]<br/>
+                            [% l('O: [_1] ', ctx.user.other_phone) | html %]<br/>
+                        </span>
+                        [% IF ctx.user.ident_value %]
+                        <span>
+                            [% l(
+                                '[_1]: [_2]',
+                                ctx.user.ident_type.name,
+                                ctx.user.ident_value
+                            ) | html %]
+                        </span><br/>
+                        [% END %]
+                        [% IF ctx.user.ident_value2 %]
+                        <span>
+                            [% l(
+                                '[_1]: [_2]',
+                                ctx.user.ident_type2.name,
+                                ctx.user.ident_value2
+                            ) | html %]
+                        </span><br/>
+                        [% END %]
+                    </div>
+                </div><div class="cell">
+                    <div class="textBackground">
+                        <span>[% ctx.user.profile.name | html %]</span><br/>
+                        <span>[% ctx.user.home_ou.shortname | html %]</span><br/>
+                        <span>
+                            [% l(
+                                'Items Overdue: [_1] Total: [_2]',
+                                ctx.checked_out_count.overdue + ctx.checked_out_count.long_overdue,
+                                ctx.checked_out_count.out
+                            ) | html %]
+                        <span><br/>
+                        <span>
+                            [% l(
+                                'Holds Ready: [_1] Total: [_2]',
+                                ctx.holds_count.ready,
+                                ctx.holds_count.total
+                            ) | html %]
+                        </span><br/>
+                        <span>
+                        [% IF ctx.money_open_user_summary %]
+                            [% l(
+                                'Bills: [_1]',
+                                ctx.money_open_user_summary.balance_owed
+                            ) | html %]
+                        [% ELSE %]
+                            [% l(
+                                'Bills: [_1]',
+                                '0.00'
+                            ) | html %]
+                        [% END %]
+                        </span><br/>
+                    </div>
+                </div></div>
+            </div>
+            [% ELSE %]
+            <div>
+                <span style="font-weight: bold; font-size: xx-large">
+                    Error loading user with database id = [% ctx.au_id | html %]
+                </span><br/>
+                <span style="font-weight: bold;">
+                    Description: [% ctx.error.desc | html %]
+                </span><br/>
+                <span>Server Time: [% ctx.error.servertime | html %]</span><br/>
+                <span>Text Code: [% ctx.error.textcode | html %]</span><br/>
+                <span>ILS Event: [% ctx.error.ilsevent | html %]</span><br/>
+                <span>PID: [% ctx.error.pid | html %]</span><br/>
+                <span>Stack Trace: [% ctx.error.stacktrace | html %]</span><br/>
+            </div>
+            [% END %]
+            <div class="common-full-pad" style="float:none"></div>
+        </div>
+    </div>
+[% END %]
index a831ff7..9832bdd 100644 (file)
                                 ctx.user.suffix
                             ) | html %]
                         </span><br/>
-                        [% IF ctx.addr %]
-                        <span>
-                            [% ctx.addr.street1 | html %]<br/>
-                            [% ctx.addr.street2 | html %]<br/>
-                            [% ctx.addr.city | html %],
-                            [% ctx.addr.state | html %]
-                            [% ctx.post_code | html %]
-                        </span><br/>
-                        [% END %]
-                        <span>
-                        [% IF ctx.user.day_phone %]
-                            [% l('D: [_1] ', ctx.user.day_phone) | html %]
-                        [% ELSIF ctx.user.evening_phone %]
-                            [% l('E: [_1] ', ctx.user.evening_phone) | html %]
-                        [% ELSIF ctx.user.other_phone %]
-                            [% l('O: [_1] ', ctx.user.other_phone) | html %]
-                        [% END %]
-                        </span><br/>
-                        [% IF ctx.user.email %]
-                        <span>
-                            [% ctx.user.email | html %]
-                        </span>
-                        [% END %]
-                    </div>
-                </div><div class="cell">
-                    <div class="textBackground alerts">
                         [% IF ctx.barred %]
                         <span>
-                            [% l('Patron is BARRED') %]
+                            [% l('Patron is BARRED') | html %]
                         </span><br/>
                         [% END %]
                         [% IF ctx.holds_count.ready > 0 %]
                         <span>
-                            [% l('[_1] holds Ready for Pickup', ctx.holds_count.ready) %]
+                            [% IF ctx.holds_count.ready == 1 %]
+                                [% l('1 hold Ready for Pickup') | html %]
+                            [% ELSE %]
+                                [% l('[_1] holds Ready for Pickup', ctx.holds_count.ready) | html %]
+                            [% END %]
                         </span><br/>
                         [% END %]
                         [% IF ctx.user.alert_message %]
                             [% ctx.user.alert_message | html %]
                         </span><br/>
                         [% END %]
+                        [% IF ctx.user.notes.size == 1 %]
+                            [% l('1 note') | html %]
+                        [% ELSIF ctx.user.notes.size > 1 %]
+                            [% l('[_1] notes', ctx.user.notes.size) | html %]
+                        [% END %]
+                    </div>
+                </div><div class="cell">
+                    <div class="textBackground alerts">
                         [% FOREACH p IN ctx.user.standing_penalties %]
                         <span>
                             [% p.standing_penalty.label | html %]
                     </div>
                 </div><div class="cell">
                     <div class="textBackground">
-                        <span>[% ctx.user.profile.name | html %]</span><br/>
-                        [% IF ctx.user.card AND ctx.user.card.active %]
+                        <span>
+                            [% l('D: [_1] ', ctx.user.day_phone) | html %]<br/>
+                            [% l('E: [_1] ', ctx.user.evening_phone) | html %]<br/>
+                            [% l('O: [_1] ', ctx.user.other_phone) | html %]<br/>
+                        </span>
                         <span>
                             [% l(
                                 'Card: [_1]',
                                 ctx.user.card.barcode
                             ) | html %]
                         </span><br/>
-                        [% END %]
                         <span>
                             [% l(
                                 'OPAC: [_1]',
                                 ctx.user.usrname
                             ) | html %]
                         </span><br/>
-                        [% IF ctx.user.ident_value %]
-                        <span>
-                            [% l(
-                                '[_1]: [_2]',
-                                ctx.user.ident_type.name,
-                                ctx.user.ident_value
-                            ) | html %]
-                        </span><br/>
-                        [% END %]
-                        <span>
-                            [% l(
-                                'Last Updated: [_1]',
-                                date.format(ctx.user.last_update_time, DATE_FORMAT)
-                            ) | html %]
-                        </span><br/>
                     </div>
                 </div><div class="cell">
                     <div class="textBackground">
-                        [% IF ctx.user.dob %]
+                        <span>[% ctx.user.profile.name | html %]</span><br/>
+                        <span>[% ctx.user.home_ou.shortname | html %]</span><br/>
                         <span>
                             [% l(
-                                'DOB: [_1]',
-                                date.format(ctx.user.dob, DATE_FORMAT)
+                                'Items Overdue: [_1] Total: [_2]',
+                                ctx.checked_out_count.overdue + ctx.checked_out_count.long_overdue,
+                                ctx.checked_out_count.out
                             ) | html %]
-                        </span><br/>
-                        [% END %]
+                        <span><br/>
                         <span>
                             [% l(
-                                'Exp: [_1]',
-                                date.format(ctx.user.expire_date, DATE_FORMAT)
+                                'Holds Ready: [_1] Total: [_2]',
+                                ctx.holds_count.ready,
+                                ctx.holds_count.total
                             ) | html %]
                         </span><br/>
-                        [% IF ctx.user.usr_activity AND ctx.user.usr_activity.0 %]
                         <span>
+                        [% IF ctx.money_open_user_summary %]
                             [% l(
-                                'Last Activity: [_1]',
-                                date.format(
-                                    ctx.user.usr_activity.0.event_time,
-                                    DATE_FORMAT
-                                )
+                                'Bills: [_1]',
+                                ctx.money_open_user_summary.balance_owed
                             ) | html %]
-                        </span><br/>
-                        [% END %]
-                        [% IF ctx.user.credit_forward_balance %]
-                        <span>
+                        [% ELSE %]
                             [% l(
-                                'Credit: [_1]',
-                                ctx.user.credit_forward_balance
+                                'Bills: [_1]',
+                                '0.00'
                             ) | html %]
-                        </span><br/>
                         [% END %]
-                        [% IF ctx.money_open_user_summary %]
-                        <span>
-                            [% l(
-                                'Balance: [_1]',
-                                ctx.money_open_user_summary.balance_owed
-                            ) | html %]
                         </span><br/>
-                        [% END %]
                     </div>
                 </div></div>
             </div>
             [% ELSE %]
             <div>
                 <span style="font-weight: bold; font-size: xx-large">
-                    Error loading user with database id = [% ctx.au_id %]
+                    Error loading user with database id = [% ctx.au_id | html %]
                 </span><br/>
                 <span style="font-weight: bold;">
-                    Description: [% ctx.error.desc %]
+                    Description: [% ctx.error.desc | html %]
                 </span><br/>
-                <span>Server Time: [% ctx.error.servertime %]</span><br/>
-                <span>Text Code: [% ctx.error.textcode %]</span><br/>
-                <span>ILS Event: [% ctx.error.ilsevent %]</span><br/>
-                <span>PID: [% ctx.error.pid %]</span><br/>
-                <span>Stack Trace: [% ctx.error.stacktrace %]</span><br/>
+                <span>Server Time: [% ctx.error.servertime | html %]</span><br/>
+                <span>Text Code: [% ctx.error.textcode | html %]</span><br/>
+                <span>ILS Event: [% ctx.error.ilsevent | html %]</span><br/>
+                <span>PID: [% ctx.error.pid | html %]</span><br/>
+                <span>Stack Trace: [% ctx.error.stacktrace | html %]</span><br/>
             </div>
             [% END %]
             <div class="common-full-pad" style="float:none"></div>
index 7d4f98a..0ccccdd 100644 (file)
@@ -29,7 +29,10 @@ body {
     padding-left: 10px;
     padding-right: 10px;
 }
-.alerts { font-weight: bold; }
+.alerts {
+    font-weight: bold;
+    overflow: auto;
+}
 .patronNameLarge { font-weight: bold; }
 .patronSummaryDiv { border: solid thick transparent; padding: 10px; }
 .NO_PENALTIES .patronSummaryDiv { border-color: lime; }
index 5aba197..a4c1fdf 100644 (file)
@@ -525,4 +525,5 @@ var urls = {
     'XUL_SEARCH_PREFS' : 'chrome://open_ils_staff_client/content/main/search_prefs.xul',
     'XUL_SERVER_ADDONS' : 'oils://remote/xul/server/addon/addons.xul',
     'EG_PATRON_SUMMARY' : 'oils://remote/eg/opac/PatronSummary',
+    'EG_PATRON_SEARCH_SUMMARY' : 'oils://remote/eg/opac/PatronSearchSummary'
 }
index 915e0b8..95d5e5b 100644 (file)
@@ -30,6 +30,7 @@
         <command id="cmd_sel_clip" />
         <command id="cmd_save_columns" />
         <command id="cmd_search_print" />
+        <command id="cmd_clear" />
 
         <command id="cmd_reload" />
         <command id="cmd_bills" />
@@ -62,6 +63,7 @@
 
     <vbox flex="1">
 
+    <deck id="deck" flex="1">
     <groupbox id="psgf_gb">
         <caption id="psgf_gbc" label='&staff.patron_search_form.caption;' />
         <hbox>
             </vbox>
         </hbox>
     </groupbox>
-    <groupbox flex="1">
+    <iframe id="iframe" flex="1"/>
+    </deck>
+    <splitter collapse="before" resizebefore="flex" resizeafter="flex" oils_persist="state hidden" oils_persist_peers="deck search_bottom_pane"><grippy/></splitter>
+    <groupbox id="search_bottom_pane" oils_persist="height" flex="1">
         <caption label="Patrons"/>
-        <deck id="deck" flex="1">
-            <tree id="patron_list" flex="1" enableColumnDrag="true" seltype="multiple"/>
-            <iframe id="iframe" flex="1"/>
-        </deck>
+        <tree id="patron_list" flex="1" enableColumnDrag="true" seltype="multiple"/>
         <hbox>
             <hbox id="patron_list_actions"/>
             <hbox id="retrieve_settings">
                             oils_persist="checked"
                             accesskey="M"
                             label="Auto-Retrieve Single Match"/>
+                        <menuitem type="checkbox" id="auto_via_barcode"
+                            oils_persist="checked"
+                            accesskey="B"
+                            checked="true"
+                            label="Auto-Retrieve Single Match via Barcode"/>
                         <menuitem type="checkbox" id="replace_tab"
                             oils_persist="checked"
                             accesskey="T"
                             label="Replace Tab on Retrieve"/>
+                        <menuitem type="checkbox" id="replace_tab_via_barcode"
+                            oils_persist="checked"
+                            accesskey="B"
+                            checked="true"
+                            label="Replace Tab on Retrieve via Barcode"/>
                         <menuitem type="checkbox" id="retrieve_library_card"
                             oils_persist="checked"
                             accesskey="C"
 
     <vbox flex="1">
         <hbox id="top_pane" flex="1" oils_persist="height">
-            <iframe id="iframe1" flex="1" src="data:,Loading..." oils_persist="height"/>
+            <iframe id="iframe1" flex="1" oils_persist="height"/>
         </hbox>
         <splitter collapse="before" resizebefore="flex" resizeafter="flex" oils_persist="state hidden" oils_persist_peers="top_pane bottom_pane"><grippy/></splitter>
         <hbox id="bottom_pane" flex="1" oils_persist="height">
                     label="Reload"
                     accesskey="R"
                     command="cmd_reload"/>
-                <description>New tab for...</description>
+                <label value=" "/>
                 <vbox id="main_button_group">
                     <button id="bills"
                         label="Bills"
index b1bfa35..c273cc8 100644 (file)
@@ -41,6 +41,7 @@ function patron_init() {
         } catch(E) {}
 
         patron_ui_setup();
+        patron_ui_populate();
         patron_default_focus();
 
     } catch(E) {
@@ -85,7 +86,7 @@ function spawn_editor(p) {
                 'on_save' : function(p_obj) {
                     JSAN.use('patron.util');
                     patron.util.work_log_patron_edit(p_obj);
-                    new_patron_tab('edit',true);
+                    patron_tab('edit','merely_reset');
                 }
             },
             'lock_tab' : xulG.lock_tab,
@@ -147,22 +148,31 @@ function get_tab_name(p_interface) {
     }
 }
 
-function new_patron_tab(p_interface,replace_tab) {
+function patron_tab(p_interface,replace_tab) {
     try {
-        xulG[
-            replace_tab
-            ? 'set_tab'
-            : 'new_tab'
-        ](
-            urls.XUL_PATRON_DISPLAY,{
-                'tab_name' : get_tab_name(p_interface)
-            },{
-                'id':patron_id,
-                'interface' : p_interface
-            }
-        );
+        if (replace_tab == 'merely_reset') {
+            $(main_interface).disabled = false;
+            main_interface = p_interface;
+            try {
+                xulG.set_tab_name(get_tab_name(main_interface));
+            } catch(E) {}
+            patron_ui_populate();
+        } else {
+            xulG[
+                replace_tab
+                ? 'set_tab'
+                : 'new_tab'
+            ](
+                urls.XUL_PATRON_DISPLAY,{
+                    'tab_name' : get_tab_name(p_interface)
+                },{
+                    'id':patron_id,
+                    'interface' : p_interface
+                }
+            );
+        }
     } catch(E) {
-        dump('Error in patron.xul, new_patron_tab('+p_interface+'): ' + E + '\n');
+        dump('Error in patron.xul, patron_tab('+p_interface+'): ' + E + '\n');
     }
 }
 
@@ -418,7 +428,7 @@ function patron_ui_setup() {
 
         $('cmd_reload').addEventListener(
             'command',
-            function(ev){ new_patron_tab(main_interface,true); },
+            function(ev){ patron_tab(main_interface,'merely_reset'); },
             false
         );
 
@@ -467,7 +477,7 @@ function patron_ui_setup() {
                     'command',
                     function(c_interface) {
                         return function(ev) {
-                            new_patron_tab(c_interface);
+                            patron_tab(c_interface,'merely_reset');
                         }
                     }(cmd),
                     false
@@ -475,9 +485,24 @@ function patron_ui_setup() {
             }
         );
 
+    } catch(E) {
+        alert('Error in patron.xul, ui_setup(): ' + E + '\n');
+    }
+}
+
+function patron_ui_populate() {
+    try {
         $('iframe1').setAttribute(
             'src',
-            urls.EG_PATRON_SUMMARY + '?au_id=' + patron_id
+            'data:,Loading...'
+        );
+        setTimeout(
+            function() {
+                $('iframe1').setAttribute(
+                    'src',
+                    urls.EG_PATRON_SUMMARY + '?au_id=' + patron_id
+                );
+            }, 0
         );
 
         $(main_interface).disabled = true;
@@ -605,7 +630,7 @@ function patron_ui_setup() {
                     'on_save' : function(p) {
                         JSAN.use('patron.util');
                         patron.util.work_log_patron_edit(p);
-                        new_patron_tab('edit',true);
+                        patron_tab('edit','merely_reset');
                     },
                     'spawn_search' : spawn_search,
                     'spawn_editor' : spawn_editor,
@@ -637,7 +662,7 @@ function patron_ui_setup() {
         }
 
     } catch(E) {
-        alert('Error in patron.xul, ui_setup(): ' + E + '\n');
+        alert('Error in patron.xul, ui_setup_populate(): ' + E + '\n');
     }
 }
 
index 7fd6af5..716b4b4 100644 (file)
@@ -79,22 +79,35 @@ function handle_enter(ev) {
     }
 }
 
+function update_search_summary_view() {
+    try {
+        var patrons = g.search.list.retrieve_selection_retrieval_data();
+        if (patrons.length > 0) {
+            $('iframe').setAttribute('src','data:,Loading...');
+            setTimeout(
+                function() {
+                    $('iframe').setAttribute(
+                        'src',
+                        urls.EG_PATRON_SEARCH_SUMMARY+'?au_id='+patrons[0]
+                    );
+                }, 0
+            );
+        }
+    } catch(E) {
+        dump('Error in patron/search.xul, update_search_summary_view(): ' + E + '\n');
+    }
+}
+
 function swap_view(ev) {
     try {
         var idx = $('deck').selectedIndex;
         if (idx == 0) {
             $('deck').selectedIndex = 1;
-            var patrons = g.search.list.retrieve_selection_retrieval_data();
-            if (patrons.length > 0) {
-                $('iframe').setAttribute(
-                    'src',
-                    urls.EG_PATRON_SUMMARY+'?au_id='+patrons[0]
-                );
-            }
+            $('patron_list').focus();
+            update_search_summary_view();
         } else {
             $('deck').selectedIndex = 0;
-            $('patron_list').focus();
-            $('iframe').setAttribute('src','data:,Loading...');
+            search_default_focus();
         }
     } catch(E) {
         dump('Error in patron/search.xul, swap_view(): ' + E + '\n');
@@ -120,12 +133,21 @@ function search_ui_setup() {
     try {
         dump('entering patron/search.xul, ui_setup()\n');
 
+        $('cmd_swap_view').setAttribute('disabled','true');
+        $('cmd_retrieve').setAttribute('disabled','true');
+        $('cmd_merge').setAttribute('disabled','true');
+
         $('cmd_swap_view').addEventListener(
             'command',
             swap_view,
             false
         );
-        $('iframe').setAttribute('src','data:,Loading...');
+
+        $('cmd_clear').addEventListener(
+            'command',
+            clear_form,
+            false
+        );
 
         $('cmd_submit').addEventListener(
             'command',
@@ -246,6 +268,27 @@ function search_default_focus() {
     );
 }
 
+function clear_form() {
+    try {
+        var render_list = document.getElementsByAttribute('group','*');
+        for (var i = 0; i < render_list.length; i++) {
+            var node = render_list[i];
+            var id = node.id;
+            if (id == 'inactive') {
+                // no-op, sticky
+            } else if (id == 'profile'
+            || id == 'search_ou') {
+                // no-op, sticky
+            } else {
+                render_list[i].value = '';
+            }
+        }
+        search_default_focus();
+    } catch(E) {
+        dump('Error in patron/search.xul, clear_form(): ' + E + '\n');
+    }
+}
+
 var _submitting = false;
 function submit(ev) {
     if (_submitting) {
@@ -283,15 +326,59 @@ function submit(ev) {
     } catch(E) {
         dump('Error in patron/search.xul, submit(): ' + E + '\n');
     }
-    _submitting = false;
+}
+
+function handle_search_select(ev){
+    var select_count = g.search.list.retrieve_selection_retrieval_data().length;
+    $('cmd_swap_view').setAttribute('disabled','true');
+    $('cmd_retrieve').setAttribute('disabled','true');
+    $('cmd_merge').setAttribute('disabled','true');
+    if (select_count > 0) {
+        $('cmd_swap_view').setAttribute('disabled','false');
+        $('cmd_retrieve').setAttribute('disabled','false');
+    }
+    if (select_count > 1) {
+        $('cmd_merge').setAttribute('disabled','false');
+    }
+    if (_submitting) { return; }
+    if ($('deck').selectedIndex == 1) {
+        update_search_summary_view();
+    } else {
+        swap_view();
+    }
+}
+
+function want_auto_retrieve() {
+    if ($('auto').getAttribute('checked') == 'true') {
+        return true;
+    }
+    if ($('auto_via_barcode').getAttribute('checked') == 'true'
+        && $('card').value != ''
+    ) {
+        return true;
+    }
+    return false;
+}
+
+function want_tab_replace() {
+    if ($('replace_tab').getAttribute('checked') == 'true') {
+        return true;
+    }
+    if ($('replace_tab_via_barcode').getAttribute('checked') == 'true'
+        && $('card').value != ''
+    ) {
+        return true;
+    }
+    return false;
 }
 
 function search(query,limit,sort) {
     try {
         g.search.search_limit = limit;
         g.search.search_sort = sort;
-        g.search.on_select = function(ev){dump('on_select\n');};
+        g.search.on_select =  handle_search_select;
         g.search.on_dblclick = function(ev) { retrieve_patrons() };
+        g.search.on_finished = function(results) { _submitting = false; }
         var patron_parts = [];
         if ($('retrieve_library_card').getAttribute('checked') == 'true') {
             patron_parts.push('card');
@@ -303,16 +390,14 @@ function search(query,limit,sort) {
             patron_parts.push('billing_address');
         }
         g.search.patron_parts = patron_parts;
-        g.search.skip_render_of_single_result =
-            $('replace_tab').getAttribute('checked') == 'true';
-        if ($('auto').getAttribute('checked') == 'true') {
+        g.search.skip_render_of_single_result = want_tab_replace();
+        if (want_auto_retrieve()) {
             g.search.single_result_callback =
                 function(id) { retrieve_patrons([id]); }
         } else {
             g.search.single_result_callback = null;
         }
-        $('deck').selectedIndex = 0;
-        $('iframe').setAttribute('src','data:,Loading...');
+        g.search.list.clear();
         $('patron_list').focus();
         g.search.search(query);
     } catch(E) {
@@ -327,9 +412,10 @@ function retrieve_patrons(patrons) {
     var current_tab_index = typeof xulG.get_idx == 'function'
         ? xulG.get_idx()
         : -1; // Just want to test this code without requiring a
-              // local staff client upgrade
+              // local staff client upgrade. get_idx is needed if
+              // we want to replace a tab that does not have focus
     for (
-        var i = $('replace_tab').getAttribute('checked') == 'true'
+        var i = want_tab_replace()
         ? 1 // open new tabs before replacing current tab
         : 0;
         i < patrons.length;
@@ -338,6 +424,7 @@ function retrieve_patrons(patrons) {
         xulG.new_tab(
             urls.XUL_PATRON_DISPLAY,{
                 'nofocus' : current_tab_index == -1
+                && want_tab_replace()
             },{
                 'id':patrons[i],
                 'interface' : xul_param('perm_editor')
@@ -346,7 +433,7 @@ function retrieve_patrons(patrons) {
             }
         );
     }
-    if ($('replace_tab').getAttribute('checked') == 'true') {
+    if (want_tab_replace()) {
         var tab_params = {};
         if (current_tab_index != -1) {
             tab_params.index = current_tab_index;
index d85aa29..42fd63d 100644 (file)
@@ -271,6 +271,9 @@ patron.search_result.prototype = {
             if (obj.search_term_count > 0) {
                 //alert('search params = ' + obj.error.pretty_print( js2JSON( params ) ) );
                 results = this.network.simple_request( 'FM_AU_IDS_RETRIEVE_VIA_HASH', params );
+                if (typeof obj.on_select == 'function') {
+                    obj.on_finished(results);
+                }
                 if ( results == null ) results = [];
                 if (typeof results.ilsevent != 'undefined') throw(results);
                 if (results.length == 0) {