updateEditorProgress

for each discord editor in your region's channel, this script will open the associated editor's profile, capture relevant information, and download that information into

As of 08. 09. 2018. See the latest version.

// //// // ==UserScript==
// @name         updateEditorProgress
// @namespace    http://tampermonkey.net/
// @version      2018.09.08.01
// @description  for each discord editor in your region's channel, this script will open the associated editor's profile, capture relevant information, and download that information into
// @description  comma separated value (CSV) file.  The contents of the file can then be programmaticaly added to a google sheet (using a separate script)
// @description  With the script installed, open any WME editor profile page to execute the script.
// @author       ramblinwreck_81
// @match        https://www.waze.com/user/editor*
// @require      https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js?version=229392
// @grant        none
// ==/UserScript==


// TO DO:
// filter out >R4
// add code that removes editors based on inactivity

// fix bot code to remove duplicates
// fix bot code to avoid editor name errors



(function() {
  'use strict';
  var discordEditors = [];
  var rankLockedEditors = [];
  var tableLockedEditors = [];
  var API_KEY ='AIzaSyDOdMtqjg0CUHMeFt29GeQzrR0__0hr5YQ'
  var CLIENT_ID = '533057355164-2m80uia4u5pedq0dteiia47k3ff6als8.apps.googleusercontent.com'
  var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
  var SCOPES = "https://www.googleapis.com/auth/spreadsheets";
  var spreadsheetId = '15TYXaO7iYRNNDUkkavG-2X75yP6iPobPV-VNBGhVjIU';
  var ssRange = 'discordEditors!A:B';
  var authorizeButton;
  var signoutButton;
  var blnReadyToBuildTable = false;
  var blnWrite = false;
  function bootstrap(tries) {
      if (W && W.Map &&
          W.Model  &&
          $ ) {
         // console.log('passed load check');
          init();
      } else if (tries < 100) {
          setTimeout(function () {
          tries += 1;
          bootstrap(tries);}, 200);
      }
  } // end of bootstrap

  function init()
  {
      console.log("initializing editor progress script");
      createUploadElements();

      function createUploadElements() {
          var y=document.createElement("div");
          y.setAttribute("id", "csv-info");
          document.getElementsByClassName("user-headline")[0].appendChild(y);
             var z=document.createElement("button");
             z.setAttribute("type", "button");
             z.setAttribute("value", "Run");
             z.setAttribute("id","run-editor-update");
             var aa=document.createTextNode("Run");
             z.appendChild(aa);
             document.getElementById("csv-info").appendChild(z);
            document.getElementById("run-editor-update").style.height="20px";
            document.getElementById("run-editor-update").style.width="100px";
          $('#csv-info').append('<button id="authorize_button" style="display: none;">Authorize</button><button id="signout_button" style="display: none;">Sign Out</button>');
   authorizeButton = document.getElementById('authorize_button');
   signoutButton = document.getElementById('signout_button');
      } // end of createUploadElements
      document.getElementById("run-editor-update").addEventListener("click",handleClientLoad,false);
  } // end of init
  function handleClientLoad() {
      gapi.load('client:auth2', initClient);
  }
  function initClient() {
        gapi.client.init({
          //apiKey: API_KEY,
          clientId: CLIENT_ID,
          discoveryDocs: DISCOVERY_DOCS,
          scope: SCOPES
        }).then(function () {
          // Listen for sign-in state changes.
          gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

          // Handle the initial sign-in state.
          updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
          authorizeButton.onclick = handleAuthClick;
          signoutButton.onclick = handleSignoutClick;
        });
  }
  function updateSigninStatus(isSignedIn) {
        if (isSignedIn) {
          authorizeButton.style.display = 'none';
          signoutButton.style.display = 'block';
          if (blnWrite === false) {
              executionSequence();
          } else {
             addLockedEditors();
          }
        } else {
          authorizeButton.style.display = 'block';
          signoutButton.style.display = 'none';
        }
  }
  function handleAuthClick(event) {
        gapi.auth2.getAuthInstance().signIn();
  }

      /**
       *  Sign out the user upon button click.
       */
  function handleSignoutClick(event) {
        gapi.auth2.getAuthInstance().signOut();
  }

  $('body').append('<script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};handleClientLoad()" onreadystatechange="if (this.readyState === complete) this.onload()"></script>');


  // ********************************************************upload function no longer used.
    function upload()
  {
    var blnKeepWaiting = true;
    var fileTimer;
    var fileUpload = document.getElementById("fileUpload");
    var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
    if (regex.test(fileUpload.value.toLowerCase())) {
        if (typeof (FileReader) !== "undefined") {
          var reader = new FileReader();
          reader.onload = function (e) {
            if (fileTimer !==undefined) {
              clearInterval(fileTimer);
              var editorStr = reader.result;
//get rid of duplicate editor names...
              var dups = editorStr.split(',');
              var modDups = dups.forEach(function(element, index, array) {
                array[index] = array[index].toLowerCase().trim();
              });
              discordEditors = dups.reduce(function(a,currentValue) {
                if (a.indexOf(currentValue) <0){
                  a.push(currentValue);
                }
                return a;
              }, []);
              executionSequence();
            }
            blnKeepWaiting=false;
           };
          reader.readAsText(fileUpload.files[0]);
          fileTimer=setInterval(checkAgain,40);
        } else {
            alert("This browser does not support HTML5.");
        }
    } else {
        alert("Please upload a valid CSV file.");
    }
  } // end of upload
// ***************************************************************************************************************

  function checkAgain()
  {
    if (blnKeepWaiting===false) {
    } else {
//        console.log("still waiting for file upload...");
    }
  } //end of checkAgain
//*********************************checkagain was part of upload sequence and is no longer used ****************************
  function executionSequence() {
    let lockedArray = localStorage.getItem('lockedEditors') ? JSON.parse(localStorage.getItem('lockedEditors')) : [];
    var validatedProfileCount = 0;
    var profilePageErrors =0;
    var editors =[];
    var rangeLength = 0;
    var seniorEditor = 0;
    var inactiveEditors = 0;
    var L1Editors = 0;
    var L2Editors = 0;
    var L3Editors = 0;
    var L4Editors = 0;
    var L5Editors = 0;
    var totalEditors = 0;
    var L1Edits = 0;
    var L2Edits = 0;
    var L3Edits =0;
    var L4Edits = 0;
    var L5Edits = 0;
    connectGoogleAPI();
    function connectGoogleAPI() {
      var params = {
        // The ID of the spreadsheet to retrieve data from.
        spreadsheetId: spreadsheetId, //TODO: Update placeholder value.

        // The A1 notation of the values to retrieve.
        ranges: ssRange,

        // How values should be represented in the output.
        // The default render option is ValueRenderOption.FORMATTED_VALUE.
        valueRenderOption: 'UNFORMATTED_VALUE',  // TODO: Update placeholder value.

        // How dates, times, and durations should be represented in the output.
        // This is ignored if value_render_option is
        // FORMATTED_VALUE.
        // The default dateTime render option is [DateTimeRenderOption.SERIAL_NUMBER].
        dateTimeRenderOption: 'FORMATTED_STRING',  // TODO: Update placeholder value.
      };

      var request = gapi.client.sheets.spreadsheets.values.batchGet(params);
      request.then(function(response) {
        var apiEditors = response.result.valueRanges[0].values
        rangeLength = response.result.valueRanges[0].values.length;
        apiEditors.forEach(function(element,index,array){
            discordEditors.push(array[index]);
            if(apiEditors[index][1] === true) {
                discordEditors[index][1] = true;
            }

        });
 console.log(discordEditors);

      var dupes = discordEditors;
      var noDupes = [];
      var a = dupes.reduce(function(accum, value) {
          if(noDupes.indexOf(value)< 0) {
              return value;
          } else {
              console.log('duplicate was ' + value);
          }
      },[]);
      console.log('noDupes is ' + a);
  debugger;
      }, function(reason) {
        console.error('error: ' + reason.result.error.message);
      });
    }
      var timeoutCounter=0;
    c();
    function c() {
        var waitTime=400;

        var g_Wait;
        if(discordEditors.length === rangeLength && rangeLength > 300) {
            clearTimeout(g_Wait);
            connectWazeAPI();
        } else {
            timeoutCounter += 1;
            g_Wait = setTimeout(function d() {
            c();},400);
        }
    }
    timeoutCounter =0;
    a();
    function a() {
      var wait;
      var waitTime=1000;
      if (profilePageErrors + validatedProfileCount + seniorEditor + inactiveEditors === discordEditors.length && discordEditors.length > 0) {
        clearTimeout(wait);
        blnReadyToBuildTable = true;
        buildWebDisplay();
 //       document.getElementById("save-locked").addEventListener("click", function() {addLockedEditors(discordEditors);});
      } else {
          wait = setTimeout(function b() {
          timeoutCounter += 1;
          a();}, 1000);
      }
    }
    function connectWazeAPI() {
      function Editor(name, rank, firstEditDate, totalEdits,editHistory, milestone, rate, lastEditDate, milliFirstEditDate, sevenDayEdits,rankLocked)
        {
          this.name = name;
          this.rank = rank;
          this.firstEditDate = firstEditDate;
          this.totalEdits = totalEdits;
          this.editHistory = editHistory;
          this.sevenDayEdits = sevenDayEdits;
          this.milestone = milestone;
          this.rate = rate;
          this.lastEditDate = lastEditDate;
          this.milliFirstEditDate = milliFirstEditDate;
          this.rankLocked = rankLocked;
        }
      function pullEditorInfo(element, index, array) {

        var wazeURL = 'https://www.waze.com/user/editor/';
        $.ajax({
          url: wazeURL + array[index][0],
          success: function (data, status, xhr) {
            var $result = $.parseHTML(xhr.responseText,true)[9].text;
            var cdata = JSON.parse($result.split(";")[1].replace("gon.data=",""));
            var userdata = "\nUsername: " + cdata.username + "\nRank: " + parseInt(cdata.rank + 1) + "\nEdits: " + cdata.edits + "\nFirst Edit Date: " + cdata.firstEditDate;
            if(cdata.firstEditDate === undefined) {
                profilePageErrors += 1;
                console.log(`${cdata.username} has no valid date.`);
                //debugger;
                return;
            }
            editors[validatedProfileCount] = new Editor(cdata.username, parseInt(cdata.rank + 1), cdata.firstEditDate, cdata.edits, cdata.editingActivity);
            var active = -1;
            editors[validatedProfileCount].lastEditDate = findLastEditDate(editors[validatedProfileCount]);
            editors[validatedProfileCount].milliFirstEditDate = cdata.firstEditDate;
            if (array[index].length > 1) {
                editors[validatedProfileCount].rankLocked = true;
            } else {
                editors[validatedProfileCount].rankLocked = false;
            }
            function findLastEditDate(curEditor){
              var arr = curEditor.editHistory;
              var foundFirst = false;
              var lastDay;
              arr = arr.reverse();
              arr.forEach(function(element, index, array) {
                if((array[index]>0) && (foundFirst === false)) {
                  foundFirst = true;
                  active = index;
                }
              });
              var today = new Date();
              var lastDayMS = 0;
              if (active > -1) {
                  lastDayMS = active * 24 * 60 * 60 * 1000;
              } else {
                  lastDayMS = 92 * 24 * 60 * 60 * 1000;
                  inactiveEditors += 1;
              }
              var lastDate = new Date(today - lastDayMS);
              return lastDate.toLocaleDateString();

            } // end of findLastEditDate
            if (active > -1) {
                validatedProfileCount += 1;
                switch (parseInt(cdata.rank + 1)) {
                    case 1:
                        L1Editors += 1;
                        L1Edits += cdata.editingActivity.reduce(reducer);
                        break;
                    case 2:
                        L2Editors += 1;
                        L2Edits += cdata.editingActivity.reduce(reducer, 0);
                        break;
                    case 3:
                        L3Editors += 1;
                        L3Edits += cdata.editingActivity.reduce(reducer, 0);
                        break;
                    case 4:
                        L4Editors +=1;
                        L4Edits += cdata.editingActivity.reduce(reducer, 0);
                        break;
                    case 5:
                        L5Editors +=1;
                        L5Edits += cdata.editingActivity.reduce(reducer, 0);
                        return;
                        break;
                    case 6:
                    case 7:
                        return;
                        break;
                }
                function reducer(accumulator, value) {
                    return accumulator + value;
                }
                totalEditors = L1Editors + L2Editors + L3Editors + L4Editors + L5Editors;
  //          console.log(L1Edits, L2Edits, L3Edits,L4Edits,L5Edits);
            }
          },
          error: function(XMLHttpRequest, textStatus, errorThrown) {
 //           console.log(element + " Status: " + textStatus + " and Error: " + errorThrown);
            profilePageErrors += 1;
          }
        }); // end of ajax

      } // end of pullEditorInfo
      discordEditors.forEach(pullEditorInfo);
    } // end of connectWazeAPI

    function buildWebDisplay()
    {
      var editorHTML='';
      var regionEditorsHTML = '<div class = "table-area1"><button  type = "button" id = "save-locked">Save Locked Editors</button><div id = "total-editors"></div><div id = regions-edits></div><table id= "region-table">'
      + '<thead id = "the-head"><tr><th id= "name" class = "col1 columz"><button type="button" id="sort-name" '
      + '>Name</button></th><th id="level" class = "col2 columz"><button type = "button" id = "sort-level">Level</button></th><th id= "locked" class = '
      + '"col3 columz"><button type = "button" id = "sort-locked">Locked</button></th><th id="began" class = "col4 columz">'
      + '<button type = "button" id= "sort-began">Editing Since</button>'
      + '</th><th id="total-edits" class = "col5 columz"><button type = "button" id= "sort-edits">Total Edits</button>'
      + '</th><th id="milestone" class = "col6 columz"><button type = "button" id = "sort-milestone">Milestone</button></th><th id="rate" '
      + 'class = "col7 columz"><button type = "button" id = "sort-rate">Edits (L1 is past 7 days, >L1 is past 30 days)</button></th>'
      + '<th id = "milliDate" class = "col8 columz">msDate</tr></thead><tbody id = "theTable-body">';

      editors.forEach(addStatsToTable);
      function addStatsToTable(element, index, array)
      {
        function convertSecondsToDate(sec) {
          var a = new Date(sec).toLocaleDateString();
          if (array[index].firstEditDate !== NaN){
              array[index].firstEditDate = a;
              return a;
          } else {
              console.log( `array[index] first edit date is not a number. array[index].name`);

          }
        }
        var startDate = convertSecondsToDate(editors[index].firstEditDate);
        var rate = editRate(editors[index]);
        function editRate(rateEditor)
        {
          var period;
          if (rateEditor.rank !== NaN) {
              if (rateEditor.rank=== 1) {
                  period = 7;
              } else if (rateEditor.rank >= 2) {
                  period = 30;
              }
          } else {
              console.log(rateEditor.name + ' does not have a valid rank.');
          }
          function sumEdits(accumulator, currentValue) {
            return accumulator + currentValue;
          }
          if (rateEditor.editHistory.length === 0) {
              console.log(rateEditor.name + 'does not have a valid edit history. ' );
          } else {
              var a = rateEditor.editHistory.slice(rateEditor.editHistory.length - period);
              console.log(rateEditor.name, rateEditor.editHistory.length, "period: " + period, rateEditor.editHistory.length-period);
              var b = a.reduce(sumEdits);
              console.log('edit rate is ' + b);
              rateEditor.rate = b;
              return b;
          }
        } // end of editRate function
        var mileStr = milestone(editors[index]);
        function milestone(curEditor)
        {
          switch (curEditor.rank) {
            case 1:
              if(curEditor.totalEdits > 1000) {
                return curEditor.milestone = 'true, total edits';
              } else if ((curEditor.totalEdits + rate)>3000) {
                return curEditor.milestone = 'true, edit rate';
              } else if (rate > 1000) {
                return curEditor.milestone = 'true, edit rate';
              } else if (curEditor.totalEdits > 400) {
                  return curEditor.milestone = 'initial review required';
              } else {
                return curEditor.milestone = 'false';
              }
            break;
            case 2:
              if (curEditor.totalEdits>20000) {
                return curEditor.milestone = 'true, edits';
              } else if ((curEditor.totalEdits + rate)>25000) {
                return curEditor.milestone = 'true, 30 day edit rate'
              } else {
                return curEditor.milestone = 'false';
              }

            break;
            default:
              return curEditor.milestone = 'false';

          }

        }  // end of milestone function

//        console.log(editors[index]);
        var lockStatus = '';
        if(editors[index].rankLocked === true) {
            lockStatus = 'locked';
        } else {
            lockStatus = 'not-locked';
        }
        editorHTML += '<tr class = "table-rows"><td headers= "name" class = "col1 all-cells"><a class= tbl-link href=https://www.waze.com/user/editor/'
        + editors[index].name + '>' + editors[index].name + "</a>" + '</td><td headers = "level" class = "col2">' + editors[index].rank
         + '</td><td headers = "locked" class = "col3" ><input class = ' + lockStatus + ' type = "checkbox" /><td headers="began" class = "col4">' + startDate + '</td><td headers="total-edits" '
         + 'class = "col5">' + editors[index].totalEdits
         + '</td>' + '<td headers="milestone" class = "col6">' + mileStr + '</td><td headers="rate" class = "col7">' + rate + '</td>'
         + '<td headers="msDate" class = "col8">' + editors[index].milliFirstEditDate + '</td></tr>';
//console.log('editor HTML follows:')
//          console.log(`<tr class = "table-rows"><td headers= "name" class = "col1 all-cells"><a class= tbl-link href=https://www.waze.com/user/editor/
//${editors[index].name} >  ${editors[index].name}  "</a>"  </td><td headers = "level" class = "col2"> ${editors[index].rank}
//</td><td headers = "locked" class = "col3"><input type = "checkbox" /><td headers="began" class = "col4"> ${startDate} </td><td headers="total-edits"
//class = "col5"> ${editors[index].totalEdits}
//</td><td headers="milestone" class = "col6"> ${mileStr} </td><td headers="rate" class = "col7"> ${rate}  </td>
//`);
      } // end of addStatsToTable

      var closingHTML ='</tbody></table></div>';
      $('#editing-activity').append(regionEditorsHTML + editorHTML + closingHTML);
 //     $('#header').after(regionEditorsHTML + editorHTML + closingHTML);
      $('.tbl-link').attr('target', '_blank');
      $('.table-area1').css({"display": "inline-block", "max-height": "500px", "overflow": "auto"});
      $('#the-head').css({"max-height": "50px","display":"table-header-group","margin-bottom":"5px"});
      $('#theTable-body').css({"max-height":  "500px","margin-bottom":"50px"});
      $('#region-table').css({"table-layout": "fixed", "width": "100%","white-space": "nowrap", "border": "3","border-style": "solid","border-collapse": "collapse"});
      $('.all-cells').css({"white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis"});
       $('.col1').css({"width":"20px"});
       $('.col2').css({"width":"25px"});
       $('.col3').css({"width":"25px"});
       $('.col4').css({"width":"30px"});
       $('.col5').css({"width":"35px"});
       $('.col6').css({"width":"30px"});
       $('.col7').css({"width":"30px"});
       $('.col8').css({"width":"20px", "display": "none"});
       $('.table-rows').css({"border": "solid thin"});
       $('.columz').attr('title', 'Click to sort.  After the sort is complete, a second click will sort in reverse order.');
       $('#total-editors').html(`Total Editors: ${totalEditors} (L1: ${L1Editors}, L2: ${L2Editors}, L3: ${L3Editors}, L4: ${L4Editors}, L5: ${L5Editors})`);
       $('#regions-edits').html(`Total Edits last 90 days... (L1: ${L1Edits.toLocaleString()}, L2: ${L2Edits.toLocaleString()}, L3: ${L3Edits.toLocaleString()}, L4: ${L4Edits.toLocaleString()}, L5: ${L5Edits.toLocaleString()})`);
       $('.locked').prop('checked', true);
       $('.not-locked').prop('checked', false);
      var nameAscending = false;
      var levelAscending = false;
      var startAscending = false;
      var totalAscending = false;
      var milestoneAscending = false;
      var rateAscending = false;
      var lockedAscending = false;
      document.getElementById("name").addEventListener("click",function() {
        if (nameAscending) {
          nameAscending = false;
        } else {
          nameAscending = true;
        }
        sort(nameAscending,'col1','region-table');
      },false);
      document.getElementById("level").addEventListener("click",function() {
        if (levelAscending) {
          levelAscending = false;
        } else {
          levelAscending = true;
        }
        sort(levelAscending, 'col2', 'region-table');
      },false);
      document.getElementById("began").addEventListener("click",function() {
        if (startAscending) {
          startAscending = false;
        } else {
          startAscending = true;
        }
        sort(startAscending, 'col8','region-table');
      },false);
      document.getElementById("sort-locked").addEventListener("click", function() {
          if (lockedAscending) {
              lockedAscending = false;
          } else {
              lockedAscending = true;
          }
          sort(startAscending, 'col3', 'region-table');
      }, false);
      document.getElementById("total-edits").addEventListener("click",function() {
        if (totalAscending) {
          totalAscending = false;
        } else {
          totalAscending = true;
        }
        sort(totalAscending,'col5','region-table');
      },false);
      document.getElementById("milestone").addEventListener("click",function() {
        if(milestoneAscending) {
          milestoneAscending = false;
        } else {
          milestoneAscending = true;
        }
        sort(milestoneAscending, 'col6', 'region-table');
      },false);
      document.getElementById("rate").addEventListener("click",function(){
        if (rateAscending) {
          rateAscending = false;
        } else {
          rateAscending = true;
        }
        sort(rateAscending, 'col7', 'region-table');
      },false);
      function sort(ascending, columnClassName, tableId)
      {
          var tbody = document.getElementById(tableId).getElementsByTagName(
                  "tbody")[0];
          var rows = tbody.getElementsByTagName("tr");

          var unsorted = true;

          while (unsorted) {
              unsorted = false;

              for (var r = 0; r < rows.length - 1; r++) {
                  var row = rows[r];
                  var nextRow = rows[r + 1];
                  if(columnClassName !== 'col3') {
                      var value = row.getElementsByClassName(columnClassName)[0].innerHTML;
                      var nextValue = nextRow.getElementsByClassName(columnClassName)[0].innerHTML;

                      value = value.replace(',', '.'); // in case a comma is used in float number
                      nextValue = nextValue.replace(',', '.');

                      if (!isNaN(value)) {
                          value = parseFloat(value);
                          nextValue = parseFloat(nextValue);
                      }
                  } else { // element is a checkbox
                      var chk= row.getElementsByClassName(columnClassName)[0];
                      var nextChk = nextRow.getElementsByClassName(columnClassName)[0];
                      if(chk.querySelector("input[type=checkbox]") !== null) { // checkbox case
                          value = chk.querySelector('input[type=checkbox]');
                          nextValue = nextChk.querySelector("input[type=checkbox]").checked;
                      }
                  }

                  if (ascending ? value > nextValue : value < nextValue) {
                      tbody.insertBefore(nextRow, row);
                      unsorted = true;
                  }
              } // end of for
          } // end of while
      } //end of sort function

//        document.getElementById("save-locked").addEventListener("click", function() {addLockedEditors(discordEditors);});

        function storageSave()
        {
            lockedArray = [];
            localStorage.setItem('lockedEditors', JSON.stringify(lockedArray));
            var a = $('.col3 input:checked').map(function() {
                return $(this).closest('tr').find('td:eq(0)').text();
            }).get();
            if (a.length>0) {
                a.forEach(function (element, index, array) {
                    lockedArray.push(array[index]);
                });
            }
            localStorage.setItem('lockedEditors', JSON.stringify(lockedArray));
        } // end of storageSave

    } // end of buildWebDisplay

      // NO LONGER USED:**********************************************************
    function makeCSV(arr)
    {
      var csvContent="";
      arr.forEach(function(element, index, array) {
          if (csvContent !== '') {
            csvContent += '\n';
          }

          csvContent += array[index].name + ',' + new Date(array[index].firstEditDate)+ ',' + array[index].lastEditDate + ','
          + array[index].rank + ',' + array[index].totalEdits + ',' + 'none';
      });
      var linkElement= document.createElement('a');
      linkElement.setAttribute("id", "csv-download");
      var encodedUri=encodeURI(csvContent);
      linkElement.setAttribute('href', "data:text/csv;charset=utf-8," + encodedUri);
      linkElement.innerHTML= "Download SER Editor CSV file";
      document.getElementById("csv-info").appendChild(linkElement);
      document.getElementById("import-csv").disabled = true;
    } // end of make CSV


console.log('end of function executionSequence');
  } // end of executionSequence
  listenMore();
  function listenMore()
  {
      console.log('listenMore');
      if(blnReadyToBuildTable) {
          console.log('save button loaded');
          blnWrite = true;
          document.getElementById("save-locked").addEventListener("click", handleClientLoad);
      } else {
          setTimeout(function() {
              listenMore();
          },10000);
     }
  }
  function addLockedEditors()
    {
       // debugger;
        console.log(discordEditors);
        if(document.getElementById('save-locked') !== null) {
            idLockedEditors();
        } else {
            setTimeout(function() {
                addLockedEditors();
            },500);
        }
        function idLockedEditors() {
            var pleaseConfirm = false;
            $.each($("input[class = 'not-locked']:checked"), //.closest("tr").find("td:eq(1)").text(),
                   function () {
                tableLockedEditors.push($(this).closest('tr').find('td:eq(0)').text());

            });
            if(tableLockedEditors.length > 0) {
                $.each($("input[class= 'locked']:checked"),
                       function() {
                    tableLockedEditors.push($(this).closest('tr').find('td:eq(0)').text());
                });
                pleaseConfirm = window.confirm('You are about to change the lock status of editors.  With your changes, the following editors will be locked: ' + tableLockedEditors.join(", ") + ' Continue with these changes?')

///                alert(tableLockedEditors.join (", "));
            }

            var blnMatch = false;
            if(tableLockedEditors.length > 0 && pleaseConfirm === true) {
                tableLockedEditors.forEach(function (element, index, array) {
                    var test = element.trim();
                    //                console.log('...' + test + '...');
                    discordEditors.map(function(element1, index1, array1) {
                        if(array1[index1][0]) {
                            var test1 = array1[index1][0].trim();
                            //  var test1 = array1[index1].trim();
                            //                    console.log('...' + test1 + '...');
                            if(test === test1) {
                                //                        console.log ('string match with ' + test);
                                var testArr = [test1,'true'];
                                array1.splice(index1, 1, testArr);
                                blnMatch = true;
                                return;
                            }
                        }
                    });
                    if(blnMatch=== false) {
                        console.log('no match found for ...' + array[index] + '...');
                    } else {
                        blnMatch = false;
                    }
                });
            } else {
                $('.locked').prop('checked', true);
                $('.not-locked').prop('checked', false);
                tableLockedEditors = [];
 //      debugger;
//                 discordEditors.forEach(function (element,index,array) {
//                     if(array[index][1]) {
//                         if(array[index][1].length > 0) {
//                             array[index][1] = '';
//                             console.log(array[index]);
//                         }
//                     }
//                 });
            }
            console.log(discordEditors);
//            debugger;


    } // end of idLockedEditors
    var valueRangeBody = {
        values: discordEditors
    };
    var params = {
        spreadsheetId: spreadsheetId, //TODO: Update placeholder value.
        range: ssRange,
        valueInputOption: 'RAW'
    };
            console.log(params);
            console.log(valueRangeBody);
    var request = gapi.client.sheets.spreadsheets.values.update(params, valueRangeBody);
    console.log('here');
    request.then(function(response) {
        // TODO: Change code below to process the `response` object:
        console.log('response is ' + response.result);
    }, function(reason) {
         console.error('google sheets error: ' + reason.result.error.message);
    });
 //       }
        //             if(lockedArray.length > 0) {
        //                 lockedArray.forEach(function (element, index, array) {
        //  //                   console.log(array[index]);
        //                     var $chkbox = $($('#region-table tr').filter(function(){
        //                         return $.trim($('td', this).eq(0).text())== array[index];
        //                     }).find('input[type="checkbox"]'))
        //                     $chkbox[0].checked = true;
        //                 });
        //             }
    } // end of addLockedEditors



bootstrap();
console.log('finished the script');
})();