public/app.js
// Define function that fires when the submit query button is clicked.
Define function that fires when the submit query button is clicked.
Define function that fires when the submit query button is clicked .
async function onClickEventBehaviorOfSubmitQueryButton(event)  
  {
    event.preventDefault();
    let arrayOfFieldsToDisplay = [];     
    tableCaption = document.createElement('caption');
    tableCaption.innerHTML = 'List of Users';
    tableCaption.className = "tableCaption";
    if(!document.querySelector(".tableCaption"))
    {
      table.appendChild(tableCaption);
    }
    document.querySelectorAll('.fieldToDisplay').forEach(function(node, nodeIndex, nodeList)
    {
      if(nodeIndex < nodeList.length - 1)
      {
        arrayOfFieldsToDisplay.push(node.value);
      }
      else if(nodeIndex = nodeList.length - 1 && node.value != "")
      {
        arrayOfFieldsToDisplay.push(node.value);
      }
    });
    let tableRow = document.createElement('tr'); 
    table.appendChild(tableRow);   
    if(arrayOfFieldsToDisplay.length == 0) 
    {
      arrayOfFieldsToDisplay = [];
      document.querySelector('.fieldToDisplay').querySelectorAll("option").forEach(function(node, nodeIndex)
      {
        if (nodeIndex != 0)
        {
            arrayOfFieldsToDisplay.push(node.value);
        }
      });
    } 
    arrayOfFieldsToDisplay.forEach(function(arrayElement)
    {
      let tableHeader = document.createElement('th');  
      tableHeader.innerHTML = arrayElement  
      tableRow.appendChild(tableHeader);
    });    
    tableHeader = document.createElement('th');  
    tableHeader.innerHTML = 'Details'  
    tableRow.appendChild(tableHeader);     
    let nameOfPrimaryKey = document.querySelector('.fieldToDisplay').querySelectorAll("option")[1].value;
    let queryExpression = document.querySelector(".queryExpressionTextArea").value;
    let indexOfOrderByClause = queryExpression.indexOf("ORDERBY:;");
    if(indexOfOrderByClause === -1)
    {
      runQueryThenStreamToDisplay(queryExpression, arrayOfFieldsToDisplay, nameOfPrimaryKey);
    }
    else 
    {
      let orderByString = queryExpression.substring(indexOfOrderByClause);  
      let orderByArray = orderByString.split(":;"); 
      orderByArray.splice(orderByArray.length -1, 1);
      let amountOfOrderByClauses = orderByArray.length/3; 
      let fieldsToOrderByArray = [];
      let typeOfSortArray = []
      for (let i = 0; i < amountOfOrderByClauses; i++) 
      {
        orderByArray.splice(0, 1);
        fieldsToOrderByArray.push(orderByArray.splice(0, 1)[0]);
        typeOfSortArray.push(orderByArray.splice(0, 1)[0]);
      }         
      let recordsArray = await runQueryWaitForAllData(queryExpression);
      recordsArray.sort(function(a, b)
      {
        let loopCounter = 0;
        let sortResult = 0;
        while (loopCounter <= amountOfOrderByClauses - 1) 
        {
          if(typeOfSortArray[loopCounter] === 'ascendingAlphaSort')
          {
            sortResult = a[fieldsToOrderByArray[loopCounter]].toString().toLowerCase().localeCompare(b[fieldsToOrderByArray[loopCounter]].toString().toLowerCase());
            if(sortResult === 1){return 1;} 
            if(sortResult === -1){return -1;} 
          }
          if(typeOfSortArray[loopCounter] === 'descendingAlphaSort')
          {
            sortResult = a[fieldsToOrderByArray[loopCounter]].toString().toLowerCase().localeCompare(b[fieldsToOrderByArray[loopCounter]].toString().toLowerCase());
            if(sortResult === 1){return -1;} 
            if(sortResult === -1){return 1;} 
          }          
          else if (typeOfSortArray[loopCounter] === 'ascendingNumericSort')
          {
            if (a[fieldsToOrderByArray[loopCounter]] < b[fieldsToOrderByArray[loopCounter]]) return -1;
            if (a[fieldsToOrderByArray[loopCounter]] > b[fieldsToOrderByArray[loopCounter]]) return 1;
          }
          else if (typeOfSortArray[loopCounter] === 'descendingNumericSort')
          {
            if (a[fieldsToOrderByArray[loopCounter]] > b[fieldsToOrderByArray[loopCounter]]) return -1;
            if (a[fieldsToOrderByArray[loopCounter]] < b[fieldsToOrderByArray[loopCounter]]) return 1;
          }          
          loopCounter = loopCounter + 1;      
          if (loopCounter === amountOfOrderByClauses)
          {
            return 0
          }         
        } 
      }) 
      recordsArray.forEach(function(value)
      {
        let tr = table.insertRow(-1);            
        arrayOfFieldsToDisplay.forEach(function(arrayElement, elementIndex)
        {
          let newCell = tr.insertCell(elementIndex);
          newCell.innerHTML = value[arrayElement];               
        });   
        let lastCell = tr.insertCell(arrayOfFieldsToDisplay.length);             
        lastCell.innerHTML = '<a href="/user/edit?userId=' + value[nameOfPrimaryKey] + '">View / Edit / Delete</a>';
      }) 
    }
    let tableParent = document.querySelector('.content');
    tableParent.appendChild(table);    
    document.querySelector("#submitQueryButton").scrollIntoView();
  }
async function onClickEventBehaviorOfSubmitQueryButton ( event ) { event . preventDefault ( ) ; let arrayOfFieldsToDisplay = [ ] ; tableCaption = document . createElement ( 'caption' ) ; tableCaption . innerHTML = 'List of Users' ; tableCaption . className = "tableCaption" ; if ( ! document . querySelector ( ".tableCaption" ) ) { table . appendChild ( tableCaption ) ; } document . querySelectorAll ( '.fieldToDisplay' ) . forEach ( function ( node , nodeIndex , nodeList ) { if ( nodeIndex < nodeList . length - 1 ) { arrayOfFieldsToDisplay . push ( node . value ) ; } else if ( nodeIndex = nodeList . length - 1 && node . value != "" ) { arrayOfFieldsToDisplay . push ( node . value ) ; } } ) ; let tableRow = document . createElement ( 'tr' ) ; table . appendChild ( tableRow ) ; if ( arrayOfFieldsToDisplay . length == 0 ) { arrayOfFieldsToDisplay = [ ] ; document . querySelector ( '.fieldToDisplay' ) . querySelectorAll ( "option" ) . forEach ( function ( node , nodeIndex ) { if ( nodeIndex != 0 ) { arrayOfFieldsToDisplay . push ( node . value ) ; } } ) ; } arrayOfFieldsToDisplay . forEach ( function ( arrayElement ) { let tableHeader = document . createElement ( 'th' ) ; tableHeader . innerHTML = arrayElement tableRow . appendChild ( tableHeader ) ; } ) ; tableHeader = document . createElement ( 'th' ) ; tableHeader . innerHTML = 'Details' tableRow . appendChild ( tableHeader ) ; let nameOfPrimaryKey = document . querySelector ( '.fieldToDisplay' ) . querySelectorAll ( "option" ) [ 1 ] . value ; let queryExpression = document . querySelector ( ".queryExpressionTextArea" ) . value ; let indexOfOrderByClause = queryExpression . indexOf ( "ORDERBY:;" ) ; if ( indexOfOrderByClause === - 1 ) { runQueryThenStreamToDisplay ( queryExpression , arrayOfFieldsToDisplay , nameOfPrimaryKey ) ; } else { let orderByString = queryExpression . substring ( indexOfOrderByClause ) ; let orderByArray = orderByString . split ( ":;" ) ; orderByArray . splice ( orderByArray . length - 1 , 1 ) ; let amountOfOrderByClauses = orderByArray . length / 3 ; let fieldsToOrderByArray = [ ] ; let typeOfSortArray = [ ] for ( let i = 0 ; i < amountOfOrderByClauses ; i ++ ) { orderByArray . splice ( 0 , 1 ) ; fieldsToOrderByArray . push ( orderByArray . splice ( 0 , 1 ) [ 0 ] ) ; typeOfSortArray . push ( orderByArray . splice ( 0 , 1 ) [ 0 ] ) ; } let recordsArray = await runQueryWaitForAllData ( queryExpression ) ; recordsArray . sort ( function ( a , b ) { let loopCounter = 0 ; let sortResult = 0 ; while ( loopCounter <= amountOfOrderByClauses - 1 ) { if ( typeOfSortArray [ loopCounter ] === 'ascendingAlphaSort' ) { sortResult = a [ fieldsToOrderByArray [ loopCounter ] ] . toString ( ) . toLowerCase ( ) . localeCompare ( b [ fieldsToOrderByArray [ loopCounter ] ] . toString ( ) . toLowerCase ( ) ) ; if ( sortResult === 1 ) { return 1 ; } if ( sortResult === - 1 ) { return - 1 ; } } if ( typeOfSortArray [ loopCounter ] === 'descendingAlphaSort' ) { sortResult = a [ fieldsToOrderByArray [ loopCounter ] ] . toString ( ) . toLowerCase ( ) . localeCompare ( b [ fieldsToOrderByArray [ loopCounter ] ] . toString ( ) . toLowerCase ( ) ) ; if ( sortResult === 1 ) { return - 1 ; } if ( sortResult === - 1 ) { return 1 ; } } else if ( typeOfSortArray [ loopCounter ] === 'ascendingNumericSort' ) { if ( a [ fieldsToOrderByArray [ loopCounter ] ] < b [ fieldsToOrderByArray [ loopCounter ] ] ) return - 1 ; if ( a [ fieldsToOrderByArray [ loopCounter ] ] > b [ fieldsToOrderByArray [ loopCounter ] ] ) return 1 ; } else if ( typeOfSortArray [ loopCounter ] === 'descendingNumericSort' ) { if ( a [ fieldsToOrderByArray [ loopCounter ] ] > b [ fieldsToOrderByArray [ loopCounter ] ] ) return - 1 ; if ( a [ fieldsToOrderByArray [ loopCounter ] ] < b [ fieldsToOrderByArray [ loopCounter ] ] ) return 1 ; } loopCounter = loopCounter + 1 ; if ( loopCounter === amountOfOrderByClauses ) { return 0 } } } ) recordsArray . forEach ( function ( value ) { let tr = table . insertRow ( - 1 ) ; arrayOfFieldsToDisplay . forEach ( function ( arrayElement , elementIndex ) { let newCell = tr . insertCell ( elementIndex ) ; newCell . innerHTML = value [ arrayElement ] ; } ) ; let lastCell = tr . insertCell ( arrayOfFieldsToDisplay . length ) ; lastCell . innerHTML = '<a href="/user/edit?userId=' + value [ nameOfPrimaryKey ] + '">View / Edit / Delete</a>' ; } ) } let tableParent = document . querySelector ( '.content' ) ; tableParent . appendChild ( table ) ; document . querySelector ( "#submitQueryButton" ) . scrollIntoView ( ) ; }
Define function that fires when the submit query button is clicked.
Define function that fires when the submit query button is clicked .
// Stop it from redirecting anywhere // Create an empty array to hold the values contained in each fieldToDisplay selector control. // Create a title for the table.     // Only apply the title if one does not already exist. // This will populate arrayOfFieldsToDisplay with the values of every fieldToDisplay  // selector control (except the last empty one) shown on the webpage. // In other words: Populate the array with all the selections made by the user. // Make the first empty row for the headers and put it in the table // Check if the user did not select any fields to display. // Nothing selected means all fields should be displayed. // Nothing selected so display all fields as they are positioned in the table. // Clear out the array // Repopulate arrayOfFieldsToDisplay with all possible options except the first empty option. // In other words: populate the array with every field name it is possble to display. // End of: if(arrayOfFieldsToDisplay[0] == "") // Nothing selected // Populate the first row with headers containing the names of each field. // Make a header for row 1 and put it in the row. // Make an extra header for row 1 so that the user can drill into the record and edit the detail or delete it. // The first record in any table will be the primary key. This a global sequ // Used here to populate the last cell of each row in a table with a control to drill in on that record. // Check if there is an order-by clause in the queryExpression. // If no order-by clause exists in the query expression fetch the data and stream the results directly to the page. // Run the query defined in the textarea on the form. // This call to the server is used when NO sort order is specified by the user. // The user specified an order so await for all the results and then sort before presenting to the user. // Get the part of the queryExpression string starting at "ORDERBY:;" // Fill an array with data from the orderby clause // Make an array out of the queryString where each phrase of the query is an element. // Get rid of the last element in the array. This is just an empty string. // Determine the amount of orderby clauses. // There are three elements in the array for each clause. // Make an array for the names of the fields to sort // Make an array for the type of sort to make on the respective field. // Populate the two new arrays from the orderByArray // Get rid of the first element in the array. It's just the conjunction. // Copy the next element into the fieldsToOrderByArray and then remove the element. // Copy the next element into the typeOfSortArray and then remove the element. // Run the query defined in the textarea on the form. // This call to the server is used when a sort order IS specified by the user.     // Sort the recordsArray which was populated after running the query. // return a.email.toString().toLowerCase().localeCompare(b.email.toString().toLowerCase()); // If we are ranking alphabetically: // Alphabetic Sort // Don't change the order. // b ranks higher so swap a and b // Alphabetic Sort // Don't change the order. // b ranks higher so swap a and b // Numeric Sort // Numeric Sort // If we got this far then records a and b are the same for the field currently being examined.  // Check to see if there are more orderby clauses to test on these two records. // If there are then we will go through the loop again using the next clause as a tie breaker.        // If there are no more orderby clauses to  // End of: while (loopCounter <= amountOfOrderByClauses - 1){...} // end of: recordsArray.sort(function(a, b){...} // Sort the recordsArray which was populated after running the query.       // Insert a new row in the table. // Insert a new cell for each field to display and populate with data for that field. // Add an extra cell to the end of the row that contains a link which sends the user // to a new screen where the record can be edited or deleted. // Put the table on the webpage. // This scrolls the results into view.