LP1282277 & LP1282286 MARC edit save warning & TCN search warning
authorLiam Whalen <liam.whalen@bc.libraries.coop>
Mon, 16 Sep 2013 02:26:16 +0000 (19:26 -0700)
committerBen Shum <bshum@biblio.org>
Tue, 11 Nov 2014 01:45:49 +0000 (20:45 -0500)
LP1282286 TCN search shortcut incorrectly prompts for lost data

When cataloguing in the Marc Edit view, users can hit Shift-F3 to bring
up the TCN search dialog box.  After entering a TCN and confirming their
entry, they will be taken to the record specified by the TCN entered.

However, if the user has edited some data on the current marc record,
then another dialog box should appear before the TCN search box that
gives them a warning that they will lose data if they go to a new
record.

Currently, whenver a user presses the Shift-F3 shortcut, they are given
a warning about losing data regardless of the current state of the marc
record being edited.

When a record is edited, a key press event is captured and the function
oils_lock_page is called to record the page as edited.  In the case of
this bug, the Shift key is not being ignored.  So, when the user
presses Shift-F3, the marc record is locked as if it were edited, then
the TCN search function is called.  After the user enters a TCN and
presses OK, the warning about lost data is displayed because the
pressing of Shift marked the record as edited.

This fix adds a check for the ev.shiftKey event in the
set_lock_on_keypress function call in marcedit.js.

Currently, if the user has edited a marc record and
pressed Shift-F3 to retrieve another record via TCN, then the prompt for
the TCN appears and after the user ok's that prompt they are prompted to
make sure they are ok with losing data.

This modification causes the prompt for lost data to appear before the
prompt for the TCN value.  It requires modifying
chrome/content/main/menu.js, which will require a staff client update.
This fix also ensures that if users confirm that it is ok to lose
data but then cancel their TCN searches that they will be prompted that
they might lose data again if they do more TCN retrieving.

LP1282277 Prompt for lost data in  Marc Edit

When using the MARC editor, if you modify a record and then use another
UI element to leave the MARC editor, you will be prompted that you might
lose data if you leave the MARC editor.  Currently, this prompt does not
happen if the user uses an Action for This Record drop down menu item.
As well, if the user then returns to the MARC editor, the changes are
still present, but leaving the MARC editor no longer prompts with  a
lost data warning.

This fix, adds checks to the Actions for This Record menu items, and it
adds some tab variables to keep track of the state of the MARC editor.
That way, if the user leaves then comes back and changes are still
present, the user will still get a lose data warning if they try to
leave again.

As well, when ever a key is pressed in MARC Edit that would result in
modifying a record, a counter is increased on a semamphor stored on
the XUL tab containing the Marc Edit UI.  Currently, when the record is
saved, this counter is decremented by 1.  However, the code checks to
see that the counter is 0 in order to determine if the tab is still
locked and data might be lost.

So, to fix this, we check in the unlock_tab code to see if we are in the
MARC Editor, and if we are, then we set the counter to 0.  The
unlock_tab code is used when saving via the Marc Editor.  It may be
used elsewhere in other parts of the Staff Client, so I have left the
original decrement by 1 logic in for all cases other than being in the
Marc Editor.

Conflicts:

Open-ILS/xul/staff_client/chrome/content/cat/opac.js
Open-ILS/xul/staff_client/server/cat/marcedit.js
Open-ILS/xul/staff_client/server/cat/marcedit.xul

The fix was modified, because the previous fix was storing the flags that
indicated a change to a MARC record at the window level.
This new fix stores them at the tab level.  I am keeping this commit
message to indicate that there were more Conflicts when mergin Sitka's
code into the community code.  In case, I missed something and a record
of what was done needs to be consulted.

Conflicts:

Open-ILS/xul/staff_client/chrome/content/OpenILS/global_util.js
Open-ILS/xul/staff_client/chrome/content/cat/opac.js
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/server/cat/marcedit.js

LP1282277 & LP1282286 MARC edit TCN search lose data prompts

This commit modifies my previous commits.  The code now uses the
previous versions code to mark a tab as locked and to record that data
is saved or not saved.  However, when a user returns to the MARC edit
screen, if there are changes still present, then the code now locks the
tab again and records that there is unsaved data.  This should allow all
previous functionality to remain while providing the proper warnings
when within the MARC editor.

LP1282277 & LP1282286 MARC Edit and TCN lose data prompt

This commit sets the tab.marc_edit_changed value to false when the tab
is set.  This means if an MARC record is edited in a tab then the tab is
set to another view, if the user then goes back to MARC edit, the tab
will not be locked because the flag will now be set to false.  This
results in no warning being shown when a user tries to leave a MARC edit
page when they have not edited the MARC.

Signed-off-by: Liam Whalen <liam.whalen@bc.libraries.coop>
Signed-off-by: Kyle Tomita <tomitakyle@gmail.com>
Signed-off-by: Jennifer Pringle <jpringle@sitka.bclibraries.ca>
Signed-off-by: Ben Shum <bshum@biblio.org>
Open-ILS/xul/staff_client/chrome/content/OpenILS/global_util.js
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/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame.xul
Open-ILS/xul/staff_client/server/cat/marcedit.js
Open-ILS/xul/staff_client/server/cat/marcedit.xul

index d1be186..655008f 100644 (file)
@@ -5,11 +5,17 @@
     function $(id) { return document.getElementById(id); }
 
     function oils_unsaved_data_V() {
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
         data.stash_retrieve();
         if (typeof data.unsaved_data == 'undefined') { data.unsaved_data = 0; }
-        data.unsaved_data++;
-        window.oils_lock++;
+        //We allow unsaved data to be incremented only a single time from marc edit
+        if (tab.marc_edit_allow_multiple_locks || tab.in_marc_edit == false) {
+            data.unsaved_data++;
+            window.oils_lock++;
+        }
         data.stash('unsaved_data');
         dump('\n=-=-=-=-=\n');
         dump('oils_unsaved_data_V for ' + location.href + '\n');
@@ -20,6 +26,9 @@
     }
 
     function oils_unsaved_data_P(count) {
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
         dump('\n=-=-=-=-=\n');
         dump('oils_unsaved_data_P for ' + location.href + '\n');
         if (!count) { count = 1; }
                 return window.oils_lock;
             }
         }
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
         if (typeof xulG != 'undefined') {
             if (typeof xulG.unlock_tab == 'function') {
                 dump('\twith xulG.lock_tab\n');
                 xulG.lock_tab();
+                //make sure we are not in the marc edit window
+                var marceditRe = /\/marcedit.xul$/;
+                if (marceditRe.exec(window.document.location)) {
+                    tab.marc_edit_changed = true;
+                    tab.marc_edit_allow_multiple_locks = false;
+                }
                 window.oils_lock++; // different window scope than the chrome of xulG.lock_tab
             } else {
                 dump('\twithout xulG.lock_tab\n');
     function oils_unlock_page(params) {
         dump('\n=-=-=-=-=\n');
         dump('oils_unlock_page for ' + location.href + '\n');
+        var marceditRe = /\/marcedit.xul$/;
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
         if (typeof xulG != 'undefined') {
             if (typeof xulG.unlock_tab == 'function') {
                 dump('\twith xulG.unlock_tab\n');
index ba54530..a765a69 100644 (file)
@@ -55,13 +55,17 @@ function my_init() {
 }
 
 function default_focus() {
-    opac_wrapper_set_help_context(); 
+    opac_wrapper_set_help_context();
 }
 
 function opac_wrapper_set_help_context() {
     try {
+        var tabs = window.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
+        tab.in_marc_edit = false;
         dump('Entering opac.js, opac_wrapper_set_help_context\n');
-        var cw = bottom_pane.get_contentWindow(); 
+        var cw = bottom_pane.get_contentWindow();
         if (cw && typeof cw['location'] != 'undefined') {
             if (typeof cw.help_context_set_locally == 'undefined') {
                 var help_params = {
@@ -78,6 +82,10 @@ function opac_wrapper_set_help_context() {
                     cw.default_focus();
                 }
             }
+            var marceditRe = /\/marcedit.xul$/;
+            if (marceditRe.exec(cw.location)) {
+                tab.in_marc_edit = true;
+            }
         } else {
             dump('opac.js: problem in opac_wrapper_set_help_context(): bottom_pane = ' + bottom_pane + ' cw = ' + cw + '\n');
             dump('\tcw.location = ' + cw.location + '\n');
@@ -109,7 +117,7 @@ function set_brief_view() {
         "get_barcode", "reload_opac", "get_barcode_and_settings"
     ].forEach(function(k) { content_params[k] = xulG[k]; });
 
-    top_pane.set_iframe( 
+    top_pane.set_iframe(
         url,
         {},
         content_params
@@ -124,7 +132,7 @@ function set_marc_view() {
     } else {
         bottom_pane.set_iframe( xulG.url_prefix( 'XUL_MARC_VIEW?docid=' ) + window.encodeURIComponent(docid),{},xulG);
     }
-    opac_wrapper_set_help_context(); 
+    opac_wrapper_set_help_context();
     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
@@ -149,7 +157,7 @@ function set_marc_edit() {
                             var obj = {};
                             JSAN.use('util.network'); obj.network = new util.network();
                             JSAN.use('util.error'); obj.error = new util.error();
-                        
+
                             var title = '';
                             if (params.copy_ids && params.copy_ids.length > 1 && params.edit == 1)
                                 title = $("offlineStrings").getString('staff.cat.util.copy_editor.batch_edit');
@@ -232,7 +240,7 @@ function set_marc_edit() {
                                         )
                                     },
                                     {
-                                        'doc_id' : doc_id, 
+                                        'doc_id' : doc_id,
                                         'existing_copies' : [ copy_obj ],
                                         'load_opac_when_done' : true,
                                         'labels_in_new_tab' : true
@@ -286,7 +294,7 @@ function set_marc_edit() {
     } else {
         bottom_pane.set_iframe( a,b,c );
     }
-    opac_wrapper_set_help_context(); 
+    opac_wrapper_set_help_context();
     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
@@ -298,7 +306,7 @@ function set_copy_browser() {
     } else {
         bottom_pane.set_iframe( xulG.url_prefix( 'XUL_COPY_VOLUME_BROWSE?docid=' ) + window.encodeURIComponent(docid),{},xulG);
     }
-    opac_wrapper_set_help_context(); 
+    opac_wrapper_set_help_context();
     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
@@ -310,7 +318,7 @@ function set_hold_browser() {
     } else {
         bottom_pane.set_iframe( xulG.url_prefix( 'XUL_HOLDS_BROWSER?docid=' ) + window.encodeURIComponent(docid),{},xulG);
     }
-    opac_wrapper_set_help_context(); 
+    opac_wrapper_set_help_context();
     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
@@ -329,7 +337,7 @@ function open_acq_orders() {
             "set_patron_tab", "volume_item_creator", "get_new_session",
             "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
             "url_prefix", "network_meter", "page_meter", "set_statusbar",
-            "set_help_context", "get_barcode", "reload_opac", 
+            "set_help_context", "get_barcode", "reload_opac",
             "get_barcode_and_settings"
         ].forEach(function(k) { content_params[k] = xulG[k]; });
 
@@ -391,11 +399,11 @@ function open_alt_serial_mgmt() {
 function set_opac() {
     g.view = 'opac';
     try {
-        var content_params = { 
+        var content_params = {
             'show_nav_buttons' : true,
             'show_print_button' : true,
-            'passthru_content_params' : { 
-                'authtoken' : ses(), 
+            'passthru_content_params' : {
+                'authtoken' : ses(),
                 'authtime' : ses('authtime'),
                 'window_open' : function(a,b,c) {
                     try {
@@ -462,7 +470,7 @@ function set_opac() {
                         }
                     }
                 );
-                
+
                 g.f_record_start = null; g.f_record_prev = null;
                 g.f_record_next = null; g.f_record_end = null;
                 g.f_record_back_to_results = null;
@@ -471,22 +479,6 @@ function set_opac() {
                 $('record_back_to_results').disabled = true;
                 $('record_pos').setAttribute('value','');
 
-                function safe_to_proceed() {
-                    if (typeof xulG.is_tab_locked == 'undefined') { return true; }
-                    if (! xulG.is_tab_locked()) { return true; }
-                    var r = window.confirm(
-                        document.getElementById('offlineStrings').getString(
-                           'generic.unsaved_data_warning'
-                        )
-                    );
-                    if (r) {
-                        while ( xulG.unlock_tab() > 0 ) {};
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-
                 win.attachEvt("rdetail", "nextPrevDrawn",
                     function(rIndex,rCount){
                         $('record_pos').setAttribute('value', document.getElementById('offlineStrings').getFormattedString('cat.record.counter', [(1+rIndex), rCount ? rCount : 1]));
@@ -509,7 +501,7 @@ function set_opac() {
                             $('record_prev').disabled = false;
                         }
                         if (win.rdetailStart) {
-                            g.f_record_start = function() { 
+                            g.f_record_start = function() {
                                 if (safe_to_proceed()) {
                                     g.view_override = g.view;
                                     win.rdetailStart();
@@ -518,7 +510,7 @@ function set_opac() {
                             $('record_start').disabled = false;
                         }
                         if (win.rdetailEnd) {
-                            g.f_record_end = function() { 
+                            g.f_record_end = function() {
                                 if (safe_to_proceed()) {
                                     g.view_override = g.view;
                                     win.rdetailEnd();
@@ -962,7 +954,7 @@ function undelete_record() {
 }
 
 function refresh_display(id) {
-    try { 
+    try {
         marc_view_reset = true;
         marc_edit_reset = true;
         copy_browser_reset = true;
@@ -996,7 +988,7 @@ function refresh_display(id) {
             case 'opac' :
             default: set_opac(); break;
         }
-        opac_wrapper_set_help_context(); 
+        opac_wrapper_set_help_context();
     } catch(E) {
         g.error.standard_unexpected_error_alert('in refresh_display',E);
     }
@@ -1019,9 +1011,9 @@ function add_volumes() {
             edit = g.network.request(
                 api.PERM_MULTI_ORG_CHECK.app,
                 api.PERM_MULTI_ORG_CHECK.method,
-                [ 
-                    ses(), 
-                    ses('staff_id'), 
+                [
+                    ses(),
+                    ses('staff_id'),
                     [ ses('ws_ou') ],
                     [ 'CREATE_VOLUME', 'CREATE_COPY' ]
                 ]
@@ -1183,4 +1175,60 @@ function gen_statusbar_click_handler(data_key) {
     }
 }
 
+function record_action(action_function) {
+    if (safe_to_proceed()) {
+        var args = Array.prototype.slice.call(arguments, 1);
+        if (action_function.name == 'set_marc_edit') {
+            var tabs = window.parent.document.getElementById('main_tabs');
+            var idx = tabs.selectedIndex;
+            var tab = tabs.childNodes[idx];
+
+            if (tab.marc_edit_changed) {
+                xulG.lock_tab();
+                tab.marc_edit_allow_multiple_locks = false;
+            }
+        }
+            
+        return action_function.apply(null, args);
+    }
+}
+
+function safe_to_proceed() {
+    //Check to see if we are not in marc edit.  Or if we are, is 
+    //marc_edit_changed not true? We check for != true because it 
+    //migth also be undefined and if it is and we are checking
+    //for false the test will fail
+
+    var in_marc_edit;
+    var marc_edit_changed;
+
+    var tabs = window.parent.document.getElementById('main_tabs');
+    var idx = tabs.selectedIndex;
+    var tab = tabs.childNodes[idx];
+
+    in_marc_edit = tab.in_marc_edit;
+    marc_edit_changed = tab.marc_edit_changed;
 
+    if ((in_marc_edit != true) || (marc_edit_changed != true)) {
+        if (typeof xulG.is_tab_locked == 'undefined') { return true; }
+        if (! xulG.is_tab_locked()) { return true; }
+    }
+    var r = window.confirm(
+        document.getElementById('offlineStrings').getString(
+           'generic.unsaved_data_warning'
+        )
+    );
+
+    //If we are confirming from within MARC edit then
+    //drop the tab locks.  Otherwise the locks get dropped
+    //in cmd_search_tcn
+    if (r) {
+        if (typeof xulG.unlock_tab === 'function') {
+            while ( xulG.unlock_tab() > 0 ) {};
+        }
+
+        return true;
+    } else {
+        return false;
+    }
+}
index ab15bc3..3ed3071 100644 (file)
             <menubar>
                 <menu label="&staff.cat.opac.menu.label;" accesskey="&staff.cat.opac.menu.accesskey;">
                 <menupopup>
-                <menuitem label="&staff.cat.opac.opac_view.label;" accesskey="" id="opac_view" oncommand="set_opac();"/>
-                <menuitem label="&staff.cat.opac.marc_view.label;" accesskey="&staff.cat.opac.marc_view.accesskey;" id="marc_view" oncommand="set_marc_view();"/>
-                <menuitem label="&staff.cat.opac.marc_edit.label;" accesskey="&staff.cat.opac.marc_edit.accesskey;" id="marc_edit" oncommand="set_marc_edit();"/>
-                <menuitem label="&staff.cat.opac.copy_browse.label;" accesskey="&staff.cat.opac.copy_browse.accesskey;" id="copy_browse" oncommand="set_copy_browser();"/>
-                <menuitem label="&staff.cat.opac.manage_multi_home_items.label;" accesskey="&staff.cat.opac.manage_multi_home_items.accesskey;" id="manage_multi_home_items" oncommand="manage_multi_home_items();"/>
-                <menuitem label="&staff.cat.opac.manage_parts.label;" accesskey="&staff.cat.opac.manage_parts.accesskey;" id="manage_parts" oncommand="manage_parts();"/>
-                <menuitem label="&staff.cat.opac.view_holds.label;" accesskey="&staff.cat.opac.view_holds.accesskey;" id="view_holds" oncommand="set_hold_browser();"/>
+                <menuitem label="&staff.cat.opac.opac_view.label;" accesskey="" id="opac_view" oncommand="record_action(set_opac);"/>
+                <menuitem label="&staff.cat.opac.marc_view.label;" accesskey="&staff.cat.opac.marc_view.accesskey;" id="marc_view" oncommand="record_action(set_marc_view);"/>
+                <menuitem label="&staff.cat.opac.marc_edit.label;" accesskey="&staff.cat.opac.marc_edit.accesskey;" id="marc_edit" oncommand="record_action(set_marc_edit);"/>
+                <menuitem label="&staff.cat.opac.copy_browse.label;" accesskey="&staff.cat.opac.copy_browse.accesskey;" id="copy_browse" oncommand="record_action(set_copy_browser);"/>
+                <menuitem label="&staff.cat.opac.manage_multi_home_items.label;" accesskey="&staff.cat.opac.manage_multi_home_items.accesskey;" id="manage_multi_home_items" oncommand="record_action(manage_multi_home_items);"/>
+                <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();"/>
                 <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();"/>
-                <menuitem label="&staff.cat.opac.delete_record.label;" accesskey="&staff.cat.opac.delete_record.accesskey;" id="delete_record" oncommand="delete_record();"/>
-                <menuitem label="&staff.cat.opac.undelete_record.label;" accesskey="&staff.cat.opac.undelete_record.accesskey;" id="undelete_record" oncommand="undelete_record();"/>
+                <menuitem label="&staff.cat.opac.delete_record.label;" accesskey="&staff.cat.opac.delete_record.accesskey;" id="delete_record" oncommand="record_action(delete_record);"/>
+                <menuitem label="&staff.cat.opac.undelete_record.label;" accesskey="&staff.cat.opac.undelete_record.accesskey;" id="undelete_record" oncommand="record_action(undelete_record);"/>
                 <menuseparator/>
                 <menuitem label="&staff.cat.copy_browser.holdings_maintenance.cmd_add_volumes.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_add_volumes.accesskey;" id="add_volumes" oncommand="add_volumes();"/>
                 <menuitem label="&staff.cat.opac.mark_for_hold_transfer.label;" accesskey="&staff.cat.opac.mark_for_hold_transfer.accesskey;" id="mark_for_hold_transfer" oncommand="mark_for_hold_transfer();"/>
                         <menu id="mfhd_delete" label="&staff.serial.mfhd_menu.delete.label;"/>
                     </menupopup>
                 </menu>
-                <menuitem id="serctrl_view" label="&staff.serial.serctrl_view.label;" oncommand="set_serctrl_view();" />
+                <menuitem id="serctrl_view" label="&staff.serial.serctrl_view.label;" oncommand="record_action(set_serctrl_view);" />
                 <menuitem label="&staff.cat.opac.alt_serial.label;" accesskey="&staff.cat.opac.alt_serial.accesskey;" id="alt_serial" oncommand="open_alt_serial_mgmt();" />
                 <menuitem label="&staff.cat.opac.batch_receive.label;" accesskey="&staff.cat.opac.batch_receive.accesskey;" id="batch_receive" oncommand="batch_receive_in_new_tab();"/>
                 <menuseparator/>
                 <menuitem label="&staff.cat.opac.default.label;" id="default" oncommand="set_default();"/>
-                <menuitem label="&staff.cat.opac.refresh_me.label;" id="refresh_me" oncommand="refresh_display(docid);"/>
+                <menuitem label="&staff.cat.opac.refresh_me.label;" id="refresh_me" oncommand="record_action(refresh_display, docid);"/>
                 </menupopup>
                 </menu>
             </menubar>
index f10ba71..e5788c8 100644 (file)
@@ -408,6 +408,36 @@ main.menu.prototype = {
             'cmd_search_tcn' : [
                 ['oncommand'],
                 function(event) {
+                    //obj is defined at the beginning of this block
+                    var idx = obj.controller.view.tabs.selectedIndex;
+                    var tab = obj.controller.view.tabs.childNodes[ idx ];
+                    var id = tab.getAttribute('id');
+                    var lose_saved_data_confirmed = 0;
+
+                    if (id) {
+                        var confirmation;
+                        if (tab.in_marc_edit) {
+                            confirmation = safe_to_proceed();
+                            if (!confirmation) { return; }
+                        }
+
+                        if (typeof obj.tab_semaphores[id] != 'undefined') {
+                            if (obj.tab_semaphores[id] > 0) {
+                                //If confirmation has not been defined yet
+                                //make sure we prompt for possible loss of data
+                                if (typeof confirmation == undefined) {
+                                    confirmation = window.confirm(offlineStrings.getString('menu.replace_tab.unsaved_data_warning'));
+                                }
+
+                                if (!confirmation) { return; }
+                                oils_unsaved_data_P( obj.tab_semaphores[id] );
+                                lose_saved_data_confirmed = 1;
+                            }
+
+                            delete obj.tab_semaphores[id];
+                        }
+                    }
+
                     var tcn = prompt(offlineStrings.getString('menu.cmd_search_tcn.tab'),'',offlineStrings.getString('menu.cmd_search_tcn.prompt'));
 
                     function spawn_tcn(r,event) {
@@ -436,7 +466,7 @@ main.menu.prototype = {
                             }
                         }
                     }
-
+                                       
                     if (tcn) {
                         JSAN.use('util.network');
                         var network = new util.network();
@@ -454,6 +484,16 @@ main.menu.prototype = {
                         } else {
                             spawn_tcn(robj,event);
                         }
+                    } else {
+                        if (lose_saved_data_confirmed) {
+                            //Reinstate the unsaved data count on this tab.
+                            //This is necessary if the user clicks that it is ok
+                            //to lose data, then cancels the TCN search.
+                            //This code ensures that they are prompted that they might lose
+                            //data if they replace the tab again.
+                            obj.tab_semaphores[id] = 1;
+                            oils_unsaved_data_V();
+                        }
                     }
                 }
             ],
@@ -2426,6 +2466,11 @@ commands:
         if (params.focus) tab.focus();
         var panel = this.controller.view.panels.childNodes[ idx ];
         while ( panel.lastChild ) panel.removeChild( panel.lastChild );
+        //We need to set tab.marc_edit_changed to false here, so if the user goes
+        //back to the MARC edit tab from a newly retrieved record when they had
+        //previously edited the record that used to be in the tab then
+        //the tab will not be relocked
+        tab.marc_edit_changed = false;
 
         content_params.is_tab_locked = function() {
             dump('is_tab_locked\n');
@@ -2451,7 +2496,19 @@ commands:
             if (typeof obj.tab_semaphores[id] == 'undefined') {
                 obj.tab_semaphores[id] = 0;
             }
-            obj.tab_semaphores[id]--;
+
+            //If we are in marc edit, then unlock is only calld when saving
+            //the edits.  So, drop all locks in this case.
+            //Otherwise leave the code as is because I am not sure how other parts
+            //of the staff client interact with the tab locking
+            if (tab.in_marc_edit) {
+                obj.tab_semaphores[id] = 0;
+                //allow multiple locks again, so if we
+                //return to marc edit we can put a lock on it again
+                tab.marc_edit_allow_multiple_locks = true;
+            } else {
+                obj.tab_semaphores[id]--;
+            }
             if (obj.tab_semaphores[id] < 0) { obj.tab_semaphores[id] = 0; } 
             oils_unsaved_data_P();
             return obj.tab_semaphores[id]; 
index 664366c..a213ae0 100644 (file)
@@ -43,6 +43,7 @@
     <script type="text/javascript" src="constants.js"/>
     <script type="text/javascript" src="../OpenILS/util/fmall.js"/>
     <script type="text/javascript" src="menu.js"/>
+    <script type="text/javascript" src="../cat/opac.js"/>
     <script type="text/javascript">
     <![CDATA[
         function setup_idle_observer(delay) {
index b404510..13dd771 100644 (file)
@@ -566,11 +566,15 @@ function setFocusToNextTag (row, direction) {
 
 function set_lock_on_keypress(ev) {
     try {
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
         //dump('keypress: isChar = ' + ev.isChar + ' char = ' + ev.char + ' charCode = ' + ev.charCode + ' key = ' + ev.key + ' keyCode = ' + ev.keyCode + '\n');
         if (! /* NOT */(
                 ev.altKey
                 || ev.ctrlKey
                 || ev.metaKey
+                || ev.shiftKey
                 || ev.keyCode == ev.DOM_VK_F1
                 || ev.keyCode == ev.DOM_VK_F2
                 || ev.keyCode == ev.DOM_VK_F3
@@ -596,7 +600,9 @@ function set_lock_on_keypress(ev) {
                 || ev.keyCode == ev.DOM_VK_F23
                 || ev.keyCode == ev.DOM_VK_F24
         )) {
-            oils_lock_page();
+            var params = {};
+            params.allow_multiple_locks = tab.marc_edit_allow_multiple_locks;
+            oils_lock_page(params);
         }
     } catch(E) {
         alert(E);
@@ -604,7 +610,6 @@ function set_lock_on_keypress(ev) {
 }
 
 function createMARCTextbox (element,attrs) {
-
     var box = createComplexXULElement('textbox', attrs, Array.prototype.slice.apply(arguments, [2]) );
     box.addEventListener(
         'keypress',
@@ -1219,11 +1224,16 @@ function fastItemAdd_attempt(doc_id) {
 function save_attempt(xml_string) {
     try {
         var result = window.xulG.save.func( xml_string );
+        var tabs = window.parent.parent.document.getElementById('main_tabs');
+        var idx = tabs.selectedIndex;
+        var tab = tabs.childNodes[idx];
+        var result = window.xulG.save.func( xml_string );
         // I'd prefer to pass on_complete on through to fast_item_add,
         // but with the way these window scopes get destroyed with
         // tab replacement, maybe not a good idea
         var replace_on_complete = false;
         if (result) {
+            tab.marc_edit_changed = false;
             oils_unlock_page();
             if (result.id) {
                 replace_on_complete = fastItemAdd_attempt(result.id);
@@ -1350,6 +1360,12 @@ function marcSubfield (sf) {
 
 function loadRecord() {
     try {
+            var tabs = window.parent.parent.document.getElementById('main_tabs');
+            var idx = tabs.selectedIndex;
+            var tab = tabs.childNodes[idx];
+            tab.marc_edit_changed = false;
+            tab.marc_edit_allow_multiple_locks = true;
+
             var grid_rows = document.getElementById('recGrid').lastChild;
 
             while (grid_rows.firstChild) grid_rows.removeChild(grid_rows.firstChild);