Ignore:
Timestamp:
2019-03-04T21:13:35+13:00 (5 years ago)
Author:
ak19
Message:

Dr Bainbridge solved the weird bug whereby when you're in doc editing mode and quickly try to leave/reload the page before it's finished changing, you're asked to save changes. But no changes were made. The cause was complex: it checks for changes on page unload by comparing the initial states of editable elements against their final state on unload. When the page is unloaded prematurely (before the doc has finished loading) not all the editable elements have finished initialising, so the array keep track of initial states of editable elements, editableInitStates, does not match the final state. Dr Bainbridge added a counter variable to keep track of the number of editable elements that still need to finish initialising. It's incremented for every metadataTable row, since each is editable, and for every sectionText as this gets turned into a CKEditor. The count then gets decremented when each such individual element has finished initialising, which happens in the CKEditor.instanceReady handler for CKEditor items and in the setTimeout() which initialises metadataTable row elements. Previously the call to CKEditor's instanceReady() took place too late, in function documentedit_scripts::readyPageForEditing(), which got called much after CKEditor instances were all ready, and that's why adding the CKEDITOR's instanceReady handler in there didn't work. That problem is now overcome in adding the CKEDITOR instanceReady handler on documentReady. Another notable change is that the beforeunload() handler is now moved into the end of documentedit_scripts::readyPageForEditing(), since we don't want check for changes that need to be saved until the page has fully loaded. Further, it won't find any changes until editableInitStates and editableLastStates (current states) are both ready/all initialised, so that any popup about unsaved changes is now also accurate if the doc-editing page gets prematurely unloaded.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/web/interfaces/default/js/documentedit_scripts_util.js

    r32850 r32852  
    2121
    2222
    23 // If the user is attempting to leave the page, check if there are unsaved changes
    24 // and if so, display an "Are you sure you want to leave" message.
    25 // https://stackoverflow.com/questions/7080269/javascript-before-leaving-the-page
    26 // Newer versions of Firefox/Chrome don't display custom message (security feature):
    27 // https://stackoverflow.com/questions/22776544/why-is-jquery-onbeforeunload-not-working-in-chrome-and-firefox
    28 // and http://jsfiddle.net/XZAWS/
    29 // jquery bind() is deprecated: https://stackoverflow.com/questions/33654716/is-jquery-bind-deprecated
    30 $(window).on("beforeunload", function(event) {
    31    
    32     if(gs.cgiParams.docEdit == "1") { // like document.xsl, which checks the same var upon onload
    33     // shouldn't check for whether changes are saved unless on Doc Editing page (DocEdit=1)
    34     // else the following pop up always ends up appearing when attempting
    35     // to leave a doc view page in Doc Editing Mode (when not yet actually Doc Editing)
    36    
    37    
    38     var changes = changesToUpdate();
    39    
    40     //console.log("#### CHANGES before page reload: ", changes);
    41    
    42     if(changes.length > 0) {
    43         console.log("The collection hasn't yet been saved after editing. Are you sure you want to leave?");
    44         return "The collection hasn't yet been saved after editing. Are you sure you want to leave?";   
    45     }
    46     }
    47 
    48 });
    49 
     23// We need to wait for all editable elements (metadataTable and sectionText) to be finished with initialising
     24// before we try to store their current states in the editableInitStates array
     25// To do this, we need to keep track of how many elements still require initialising.
     26var editableElementsInitialisationProgress = 0;
     27
     28   
    5029
    5130function encodeDelimiters(meta_value) {
     
    305284{
    306285    var resultArray = new Array();
    307     getLastEditableStates();
    308     for (var j in editableLastStates)
    309     {   
    310         if (isNodeChanged(editableLastStates[j]))
    311         {
    312             resultArray.push(editableLastStates[j].editableNode);
     286   
     287    console.log("**** changesToUpdate::editableElementsInitialisationProgress = " + editableElementsInitialisationProgress);
     288   
     289    // Only want to check for valid edited states if the editableInitStates has been fully set up:
     290    // We don't bother if editableInitStates is not ready:
     291    // if editableInitStates array has nothing in it (which means CKEditor is not ready)
     292    // OR if some of the editable elements (metadataTable OR ckeditor editable values) still need to be initialised/initialising is only partway through
     293    if ((editableInitStates.length > 0) && (editableElementsInitialisationProgress == 0)) {
     294        getLastEditableStates();
     295        for (var j in editableLastStates)
     296        {   
     297            if (isNodeChanged(editableLastStates[j]))
     298            {
     299                resultArray.push(editableLastStates[j].editableNode);
     300            }
    313301        }
    314302    }
     
    337325    }
    338326
     327    console.log("**** isNodeChanged() editableInitStates = ", editableInitStates);
    339328    return true;
    340329   
     
    909898    //This registering can cause a sizeable delay so we'll thread it (effectively) so the browser is not paused
    910899    cell.originalValue = cell.value;
    911     setTimeout(function(){addEditableState(cell, editableInitStates)}, 0);
     900    setTimeout(function(){
     901        addEditableState(cell, editableInitStates);
     902        // finished initialising one more editable element,
     903        // so decrement the counter keeping track of how many elements still need initialising
     904        editableElementsInitialisationProgress--;
     905    },0);
    912906}
    913907
     
    958952function addFunctionalityToTable(table)
    959953{
    960     table.find("tr").each(function()
     954    var $tr_array = table.find("tr");   
     955
     956   
     957    // We need to keep track of editableElementsInitialisationProgress: the number of editable elements that still need to be initialised/need to finish initialising
     958    // Each table's rows means *that* many more editable elements still need initialising.
     959    // So each time addFunctionalityToTable() is called on a table, we must increment our counter editableElementsInitialisationProgress
     960    // with how many editable cells it has/how many rows it has.
     961    editableElementsInitialisationProgress += $tr_array.length;
     962    console.log("**** addFunctionalityToTable::editableElementsInitialisationProgress = " + editableElementsInitialisationProgress);
     963   
     964    $tr_array.each(function()
    961965    {
    962966        var cells = $(this).find("td");
     
    14561460}
    14571461*/
     1462
     1463
     1464$( document ).ready(function() {
     1465    console.log( "**** Dom ready!" );
     1466   
     1467    // monitor whether ckeditor instances are all ready
     1468    // See https://stackoverflow.com/questions/18461206/how-to-retrieve-the-ckeditor-status-ready
     1469    // (and https://stackoverflow.com/questions/3447803/how-to-determine-if-ckeditor-is-loaded )
     1470    if(gs.cgiParams.docEdit == "1") { // CKEDITOR only exists in docEdit mode
     1471        //CKEDITOR.on( 'loaded', function( evt ) { // not triggered
     1472            //console.log("*** CKEDITOR loaded");
     1473            CKEDITOR.on( 'instanceReady', function( evt ) {
     1474                console.log("*** CKEDITOR instanceReady", evt);
     1475                addCKEEditableState(evt,editableInitStates);
     1476                // finished initialising one more editable element,
     1477                // so decrement the counter keeping track of how many elements still need initialising
     1478                editableElementsInitialisationProgress--;
     1479            } );
     1480        //} );
     1481    }
     1482   
     1483});
     1484
     1485
     1486
Note: See TracChangeset for help on using the changeset viewer.