Dirk Harriman Banner Image

 

Notes Node JS

Projects:

 

Project 7 - App7

Music Tab application. Connects to MySql database.


 
 

Parts To Application:

Like most web applications, there is an interaction between the frontend and the backend. In a database application there is also the interaction between the backend and the database.

Initial Rendering From Database

The page sets up a number of form fields:

Hidden Fields

These fields are to be used by the frontend js application.

hidSongList Used to hold a comma delimited list of TabIDs
hidSongName Used to hold a comma delimited list of SongTitles
hidFilterArg Used to send filter arguments for the data query
Drop Down Lists
ddlAlpha Alphabetic drop down list used to search alphabetically. Uses the radio buttons as search modifiers.
ddlSongArtist A list of song artists.
ddlSetList Predefined set lists of songs.
Radio Buttons

These are used to modify the alphabetic search.

rbSongTitle The default. Searches aplphabetically by song title.
rbArtist Searches aplphabetically by song artist.
rbAuthor Searches aplphabetically by song author.
Buttons
btnSetList The render set list button. If there are songs in the set list, this will render the song tabs in the order of the set list.

Frontend Processing

Frontend processing happens in the main.js file located in the public/js/ folder. All of the interaction between the frontend and backend, after the initial rendering, occurs in the Music Tab Javascript Object.

Within the Music Tab Javascript Object, the following functions call the server:

loadSetList()

The key parts of this function to note are the url and data fields in the jQuery ajax() call.
The value in the url field is the route data. The importance of this field ('/setlist/render') will be obvious within the server-side code.
The value in the data field is a comma delimited list of tab ids.

/** MUSIC TAB JAVASCRIPT OBJECT **/ (function (w, $) { ... var loadSetList = function() { ... $.ajax({ url: '/setlist/render', data: { tlist: $("#hidSongList").val() } }).done(function(response){ if (response.length > 0) { for (var i=0;i< response.length; i++) { ... // response[i].SongTitle // response[i].SongArtist // response[i].SongCapo // response[i].SongData } }); }; ... w.AddListItem = AddListItem; w.SaveSetList = SaveSetList; w.ClearList = ClearList; w.MakeListSortable = MakeListSortable; w.ddlAlphaChange = ddlAlphaChange; w.ddlArtistChange = ddlArtistChange; w.loadSetList = loadSetList; })(window, jQuery);

ddlAlphaChange(ddlObj)

In this function, the route data is stored in a local variable called route_u.
The initial value of route_u is '/tabs/alpha/'
Depending on the radio button selected, route_u will be appended with either 'SongTitle', 'SongArtist', or 'SongAuthor'.
Next route_u is appended with the selected alpha character in ddlAlpha
 
Examples:
/tabs/alpha/SongTitle/B
/tabs/alpha/SongTitle/F
/tabs/alpha/SongArtist/T
/tabs/alpha/SongArtist/S
/tabs/alpha/SongAuthor/R
/tabs/alpha/SongAuthor/A

/** MUSIC TAB JAVASCRIPT OBJECT **/ (function (w, $) { ... var ddlAlphaChange = function(ddlObj) { ... let route_u = '/tabs/alpha/'; ... if ($("#rbSongTitle").prop("checked")) { route_u += 'SongTitle'; } else if ($("#rbArtist").prop("checked")) { route_u += 'SongArtist'; } else if ($("#rbAuthor").prop("checked")) { route_u += 'SongAuthor'; } else { route_u += 'SongTitle'; } route_u += '/'+ $(ddlObj).val(); $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ ... BUILDS AN UNORDERED LIST }); }; ... w.AddListItem = AddListItem; w.SaveSetList = SaveSetList; w.ClearList = ClearList; w.MakeListSortable = MakeListSortable; w.ddlAlphaChange = ddlAlphaChange; w.ddlArtistChange = ddlArtistChange; w.loadSetList = loadSetList; })(window, jQuery);

ddlArtistChange(ddlObj)

In this function, the route data is stored in a local variable called route_u.
The initial value of route_u is '/tabs/artist'
Next route_u is appended with the selected artist name in ddlSongArtist
 
Examples:
/tabs/artist/Beatles
/tabs/artist/Al Green
/tabs/artist/Clash
/tabs/artist/Jam

/** MUSIC TAB JAVASCRIPT OBJECT **/ (function (w, $) { ... var ddlArtistChange = function(ddlObj) { let resp = ''; let route_u = '/tabs/artist'; route_u += '/'+ $(ddlObj).val(); $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ ... BUILDS AN UNORDERED LIST }); }; ... w.AddListItem = AddListItem; w.SaveSetList = SaveSetList; w.ClearList = ClearList; w.MakeListSortable = MakeListSortable; w.ddlAlphaChange = ddlAlphaChange; w.ddlArtistChange = ddlArtistChange; w.loadSetList = loadSetList; })(window, jQuery);

Backend Processing

Upon selection or submission, the backend code is called.
 
Examples:
/tabs/alpha/SongTitle/B
/tabs/alpha/SongTitle/F
/tabs/alpha/SongArtist/T
/tabs/alpha/SongArtist/S
/tabs/alpha/SongAuthor/R
/tabs/alpha/SongAuthor/A

Alphabetic Listing

/** ROUTING - Alphabetic Search Parameters: byparam By Song Name, By Artist, By Author selchar A, B, C, ... Z **/ app.get('/tabs/alpha/:byparam/:selchar', (req, res) => { let sql = "SELECT TabID, SongTitle, SongArtist, SongAuthor, DataMask, SongYear, SongKey, SongCapo "; sql += "FROM musictabs "; sql += "WHERE "+ req.params.byparam +" LIKE '"+ req.params.selchar +"%' ORDER BY "; sql += (req.params.byparam == "SongTitle") ? "SongTitle" : req.params.byparam +", SongTitle"; let query = db.query(sql, (err, result) => { if(err) throw err; res.json(result); // SENDS JSON DATA BACK TO CLIENT }); });

Artist Listing

/** ROUTING - Artist Search Parameters: artistname Artist Name **/ app.get('/tabs/artist/:artistname', (req, res) => { let sql = "SELECT TabID, SongTitle, SongArtist, SongAuthor, DataMask, SongYear, SongKey, SongCapo "; sql += "FROM musictabs "; sql += "WHERE SongArtist LIKE '"+ req.params.artistname +"%' ORDER BY SongTitle"; let query = db.query(sql, (err, result) => { if(err) throw err; res.json(result); // SENDS JSON DATA BACK TO CLIENT }); });

Response Rendering

The response in both the Alphabetic and Artist listing is the same, which is the result of the database query converted to JSON.

res.json(result);

// ALPHABETICAL $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ if (response.length > 0) { // CLEAR SELECT SONG LIST LIST let liSelSong = document.getElementById("ulSelectSong").getElementsByTagName("li"); for (var i = liSelSong.length-1; i >= 0; i--) { liSelSong[i].parentNode.removeChild(liSelSong[i]); } } for (var i=0;i< response.length; i++) { $("#ulSelectSong").append("<li value="+ response[i].TabID +" onclick='AddListItem(this)'>"+ response[i].SongTitle +"</li>"); } $("#divMsg").html(resp); }); // ARTISTS $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ if (response.length > 0) { // CLEAR SELECT SONG LIST LIST let liSelSong = document.getElementById("ulSelectSong").getElementsByTagName("li"); for (var i = liSelSong.length-1; i >= 0; i--) { liSelSong[i].parentNode.removeChild(liSelSong[i]); } } for (var i=0;i< response.length; i++) { $("#ulSelectSong").append("<li value="+ response[i].TabID +" onclick='AddListItem(this)'>"+ response[i].SongTitle +"</li>"); } $("#divMsg").html(resp); });

Project Files

node_modules/ .bin/ accepts/ array-flatten/ bignumber.js/ body-parser/ bytes/ content-disposition/ content-type/ cookie/ cookie-signature/ core-util-is/ debug/ depd/ destroy/ ee-first/ ejs/ encodeurl/ escape-html/ etag/ express/ finalhandler/ forwarded/ fresh/ http-errors/ iconv-lite/ inherits/ ipaddr.js/ isarray/ media-typer/ merge-descriptors/ methods/ mime/ mime-db/ mime-types/ ms/ mysql/ negotiator/ on-finished/ parseurl/ path-to-regexp/ process-nextick-args/ proxy-addr/ qs/ range-parser/ raw-body/ readable-stream/ safe-buffer/ safer-buffer/ send/ serve-static/ setprototypeof/ sqlstring/ statuses/ string_decoder/ type-is/ unpipe/ util-deprecate/ utils-merge/ vary/ public/ css/ bootstrap-grid.css bootstrap-grid.css.map bootstrap-grid.min.css bootstrap-grid.min.css.map bootstrap-reboot.css bootstrap-reboot.css.map bootstrap-reboot.min.css bootstrap-reboot.min.css.map bootstrap.css bootstrap.css.map bootstrap.min.css bootstrap.min.css.map ie10-viewport-bug-workaround.css jquery-ui.min.css jquery-ui.structure.css jquery-ui.structure.min.css jquery-ui.theme.css jquery-ui.theme.min.css jquery-ui3.css site.css js/ easing/ EasePack.min.js plugins/ AttrPlugin.min.js BezierPlugin.min.js ColorPropsPlugin.min.js CSSPlugin.min.js CSSRulePlugin.min.js DirectionalRotationPlugin.min.js EaselPlugin.min.js EndArrayPlugin.min.js KineticPlugin.min.js RaphaelPlugin.min.js RoundPropsPlugin.min.js ScrollToPlugin.min.js TextPlugin.min.js vendor/ anchor.min.js clipboard.min.js holder.min.js jquery-slim.min.js jquery.js jquery.min.js popper.min.js qunit.css qunit.js bootstrap.bundle.js bootstrap.bundle.js.map bootstrap.bundle.min.js bootstrap.bundle.min.js.map bootstrap.js bootstrap.js.map bootstrap.min.js bootstrap.min.js.map ie-emulation-modes-warning.js ie10-viewport-bug-workaround.js jquery-ui.js jquery-ui.min.js jquery.js jquery.min.js main.js popper.min.js views/ partials/ footer.ejs header.ejs index.ejs app7.js package-lock.json package.json

Backend Processing - Application File

/* APP7 - Node.js MySQL DEVELOPMENT TESTING */ const express = require('express'); // WEB APPLICATION FRAMEWORK const bodyParser = require('body-parser'); // BODY PARSER const path = require('path'); // APPLICATION PATH const mysql = require('mysql'); // MySQL DATABASE const app = express(); // WEB APP FRAMEWORK const db = mysql.createConnection({ // DATABASE CONNECTION PARAMETERS host: 'localhost', user: 'NodeAcct', password: 'Banyans26', database: 'DirkSiteDB', multipleStatements: true }); db.connect((err) => { // CONNECT TO DATABASE if (err) { // CHECK FOR DB CONNECTION ERROR console.error('Error connecting: ' + err.stack); return; } console.log('Connected as id ' + db.threadId); // LOG CONNECTION }); app.set('view engine', 'ejs'); // SET WEB VIEW ENGINE TO EJS app.set('views', path.join(__dirname, 'views')); // SET views PATH /* BODY PARSER MIDDLEWARE */ app.use(bodyParser.json()); // PARSE application/json app.use(bodyParser.urlencoded({extended: false})); // PARSE application/x-www-form-urlencoded /* SET STATIC PATH - USED TO HOLD LIBRARY FILES LIKE jQuery etc... */ app.use(express.static(path.join(__dirname, 'public'))); /** ROUTING **/ app.get('/', (req, res) => { let sql = 'SELECT DISTINCT SongArtist FROM musictabs ORDER BY SongArtist;'; sql += 'SELECT SetListID, SetListName FROM setlist;'; let query = db.query(sql, (err, result) => { if(err) throw err; res.render('index', { title : 'Dirks Node JS Tab App', artists : result[0], setlists : result[1] }); }); }); /** ROUTING - Artist Search Parameters: artistname Artist Name **/ app.get('/tabs/artist/:artistname', (req, res) => { let sql = "SELECT TabID, SongTitle, SongArtist, SongAuthor, DataMask, SongYear, SongKey, SongCapo "; sql += "FROM musictabs "; sql += "WHERE SongArtist LIKE '"+ req.params.artistname +"%' ORDER BY SongTitle"; let query = db.query(sql, (err, result) => { if(err) throw err; res.json(result); // SENDS JSON DATA BACK TO CLIENT }); }); /** ROUTING - Alphabetic Search Parameters: byparam By Song Name, By Artist, By Author selchar A, B, C, ... Z **/ app.get('/tabs/alpha/:byparam/:selchar', (req, res) => { let sql = "SELECT TabID, SongTitle, SongArtist, SongAuthor, DataMask, SongYear, SongKey, SongCapo "; sql += "FROM musictabs "; sql += "WHERE "+ req.params.byparam +" LIKE '"+ req.params.selchar +"%' ORDER BY "; sql += (req.params.byparam == "SongTitle") ? "SongTitle" : req.params.byparam +", SongTitle"; let query = db.query(sql, (err, result) => { if(err) throw err; res.json(result); // SENDS JSON DATA BACK TO CLIENT }); }); /** ROUTING - Set List Rendering Parameters: setlist Delimited list of tab ids **/ app.get('/setlist/render', (req, res) => { console.log('Set List Render'+ req.query.tlist); let sql = 'SELECT TabID, SongTitle, SongArtist, SongAuthor, DataMask, SongYear, SongKey, SongCapo, SongData '; sql += 'FROM musictabs '; sql += 'WHERE TabID IN ('+ req.query.tlist +') '; sql += 'ORDER BY FIELD (TabID,'+ req.query.tlist +') '; let query = db.query(sql, (err, result) => { if(err) throw err; res.json(result); // SENDS JSON DATA BACK TO CLIENT }); }); /** PORT LISTENER **/ app.listen(3000, function() { console.log('Server started on port 3000'); });

Frontend Processing

$(document).ready(function(){ $('.deleteUser').on('click', deleteUser); }); function deleteUser(){ var confirmation = confirm('Are You Sure?'); if(confirmation){ $.ajax({ type:'DELETE', url: '/users/delete/' + $(this).data('id') }).done(function(response){ window.location.replace('/'); }); window.location.replace('/'); } else { return false; } } function htmlEncode(value){ // Create a in-memory div, set its inner text (which jQuery automatically encodes) // Then grab the encoded contents back out. The div never exists on the page. return $('<div/>').text(value).html(); } function htmlDecode(value){ return $('<div/>').html(value).text(); } /** MUSIC TAB JAVASCRIPT OBJECT **/ (function (w, $) { /* LOAD SET LIST - RENDER SET LIST ***********************************************************************************************/ var loadSetList = function() { let strHtm = ''; SaveSetList(); // SAVES SET LIST IDS AND NAMES TO HIDDEN FIELDS // NEED TO PACKAGE UP DATA TO SEND TO SERVER - LIST OF SET LIST IDS $.ajax({ url: '/setlist/render', data: { tlist: $("#hidSongList").val() } }).done(function(response){ if (response.length > 0) { for (var i=0;i< response.length; i++) { //TabsSetList strHtm += '<div class="col-md-6 song-title">'+ response[i].SongTitle +'</div>'; if ( parseInt(response[i].SongCapo) > 0 ) { strHtm += '<div class="col-md-6 song-artist">'+ response[i].SongArtist +' (Capo: '+ response[i].SongCapo +')</div>'; } else { strHtm += '<div class="col-md-6 song-artist">'+ response[i].SongArtist +'</div>'; } strHtm += '<div class="col-md-12"><div class="song-text">'+ response[i].SongData +'</div></div>'; } $("#TabsSetList").html(strHtm); } }); }; /* DROP DOWN LIST CHANGE - ALPHABETICAL LIST ***********************************************************************************************/ var ddlAlphaChange = function(ddlObj) { let resp = ''; let route_u = '/tabs/alpha/'; // GET THE ORDER BY PARAMETER if ($("#rbSongTitle").prop("checked")) { route_u += 'SongTitle'; } else if ($("#rbArtist").prop("checked")) { route_u += 'SongArtist'; } else if ($("#rbAuthor").prop("checked")) { route_u += 'SongAuthor'; } else { route_u += 'SongTitle'; } route_u += '/'+ $(ddlObj).val(); $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ if (response.length > 0) { // CLEAR SELECT SONG LIST LIST let liSelSong = document.getElementById("ulSelectSong").getElementsByTagName("li"); for (var i = liSelSong.length-1; i >= 0; i--) { liSelSong[i].parentNode.removeChild(liSelSong[i]); } } for (var i=0;i< response.length; i++) { $("#ulSelectSong").append("<li value="+ response[i].TabID +" onclick='AddListItem(this)'>"+ response[i].SongTitle +"</li>"); } $("#divMsg").html(resp); }); }; /* DROP DOWN LIST CHANGE - ARTIST LIST ***********************************************************************************************/ var ddlArtistChange = function(ddlObj) { let resp = ''; let route_u = '/tabs/artist'; route_u += '/'+ $(ddlObj).val(); $.ajax({ url: route_u, data: { fname: 'Dirk', lname: 'Harriman', position: 'Lead Developer' } }).done(function(response){ if (response.length > 0) { //alert('Response Length: ' + response.length + ', Clearing List'); // CLEAR SELECT SONG LIST LIST let liSelSong = document.getElementById("ulSelectSong").getElementsByTagName("li"); for (var i = liSelSong.length-1; i >= 0; i--) { liSelSong[i].parentNode.removeChild(liSelSong[i]); } } for (var i=0;i< response.length; i++) { $("#ulSelectSong").append("<li value="+ response[i].TabID +" onclick='AddListItem(this)'>"+ response[i].SongTitle +"</li>"); } $("#divMsg").html(resp); }); }; /* ADD SONG TAB FROM SELECT LIST TO SET LIST ***********************************************************************************************/ var AddListItem = function (ListItem) { var ulSetList = document.getElementById("ulSetList"); /* SET LIST */ var listElem, textElem, anchor; //alert('Inside Function AddListItem'); if (IsInList(ListItem.value)) { //ShowMessage('Set List', 'Selection is already in the Set List'); alert('Selection is already in the Set List'); } else { listElem = document.createElement("li"); //textElem = document.createTextNode(ListItem.innerHTML); textElem = document.createTextNode(ListItem.innerText); //textElem = unescape(textElem); anchor = document.createElement("a"); anchor.href = "javascript:DelListItem(" + ListItem.value + ")"; anchor.innerText = "DEL"; anchor.setAttribute("class", "anchorBtnSm"); listElem.value = ListItem.value; listElem.appendChild(anchor); listElem.appendChild(textElem); ulSetList.appendChild(listElem); MakeListSortable(); } } /* IS IN LIST - BOOLEAN FUNCTION TO TEST IF SELECTED SONG TAB IS ALREADY IN THE LIST ***********************************************************************************************/ var IsInList = function (TabID) { var liSetList = document.getElementById("ulSetList").getElementsByTagName("li"); var ReturnVal = false; var lTabID = 0; for (var j = 0; j < liSetList.length; ++j) { lTabID = liSetList[j].value; if (TabID == lTabID) { ReturnVal = true; break; } } return ReturnVal; } /* MAKE LIST SORTABLE - ENABLE JQUERY UI DRAG SORTING ***********************************************************************************************/ var MakeListSortable = function () { $("#ulSetList").sortable({ revert: true }); $("ul, li").disableSelection(); ReBuildList(); } /* SAVE SET LIST - SAVE THE LIST TO HIDDEN FIELDS FOR AJAX POSTBACK ***********************************************************************************************/ var SaveSetList = function () { var liSetList = document.getElementById("ulSetList").getElementsByTagName("li"); var hidSongList = document.getElementById("hidSongList"); var hidSongName = document.getElementById("hidSongName"); var SongTitle = ""; for (var j = 0; j < liSetList.length; ++j) { if (j == 0) { hidSongList.value = liSetList[j].value; hidSongName.value = htmlEncode(liSetList[j].innerText.replace("DEL", "")); //SongTitle = htmlEncode(liSetList[j].innerText.replace("DEL", "")); //alert(SongTitle); //hidSongName.value = SongTitle.replace("DEL", ""); // REMOVE THE TEXT FROM THE DELETE BUTTON //hidSongName.value = SongTitle.replace("DEL", ""); // REMOVE THE TEXT FROM THE DELETE BUTTON } else { hidSongList.value += "," + liSetList[j].value; hidSongName.value += "," + htmlEncode(liSetList[j].innerText.replace("DEL", "")); //SongTitle = htmlEncode(liSetList[j].innerText.replace("DEL", "")); //alert(SongTitle); //hidSongName.value += "," + SongTitle.replace("DEL", ""); // REMOVE THE TEXT FROM THE DELETE BUTTON } } return true; } /* ReBuildList - Rebuild set list from hidden fields delimited list */ /********************************************************************/ var ReBuildList = function () { var ulSetList = document.getElementById("ulSetList"); var hidSongList = document.getElementById("hidSongList"); var hidSongName = document.getElementById("hidSongName"); var listElem, textElem, anchor; var arSongList = []; var arSongName = []; if (hidSongList.value != "") { arSongList = hidSongList.value.split(","); arSongName = hidSongName.value.split(","); for (var i = 0; i < arSongList.length; i++) { listElem = document.createElement("li"); textElem = document.createTextNode(arSongName[i]); anchor = document.createElement("a"); anchor.href = "javascript:DelListItem(" + arSongList[i] + ")"; anchor.innerText = "DEL"; anchor.setAttribute("class", "anchorBtnSm"); listElem.value = arSongList[i]; listElem.appendChild(anchor); listElem.appendChild(textElem); ulSetList.appendChild(listElem); } } } /* ClearList - Clear the ulSetList unordered list */ /********************************************************************/ var ClearList = function () { var liSetList = document.getElementById("ulSetList").getElementsByTagName("li"); var HidSongList = document.getElementById("hidSongList"); var HidSongName = document.getElementById("hidSongName"); var TabsSetList = document.getElementById("TabsSetList"); for (var i = liSetList.length-1; i >= 0; i--) { liSetList[i].parentNode.removeChild(liSetList[i]); } HidSongList.value = ""; HidSongName.value = ""; TabsSetList.innerHTML = ""; } w.AddListItem = AddListItem; w.SaveSetList = SaveSetList; w.ClearList = ClearList; w.MakeListSortable = MakeListSortable; w.ddlAlphaChange = ddlAlphaChange; w.ddlArtistChange = ddlArtistChange; w.loadSetList = loadSetList; })(window, jQuery);

Rendering

<% include partials/header %> <form> <input type="hidden" name="hidSongList" id="hidSongList" /> <input type="hidden" name="hidSongName" id="hidSongName" /> <input type="hidden" name="hidFilterArg" id="hidFilterArg" /> <div class="row"> <div class="col-md-6"> <h1><%= title %></h1> <select id="ddlAlpha" name="ddlAlpha" class="FormInput1" onchange="ddlAlphaChange(this)"> <option value="A">Alphabetical</option> <option value="A">A</option><option value="B">B</option><option value="C">C</option> <option value="D">D</option><option value="E">E</option><option value="F">F</option> <option value="G">G</option><option value="H">H</option><option value="I">I</option> <option value="J">J</option><option value="K">K</option><option value="L">L</option> <option value="M">M</option><option value="N">N</option><option value="O">O</option> <option value="P">P</option><option value="Q">Q</option><option value="R">R</option> <option value="S">S</option><option value="T">T</option><option value="U">U</option> <option value="V">V</option><option value="W">W</option><option value="X">X</option> <option value="Y">Y</option><option value="Z">Z</option> </select> By <span class="rbSelect"> <input id="rbSongTitle" name="rbByParam" type="radio" value="SongTitle" checked="checked" /> <label for="rbSongTitle">Song</label> </span> <span class="rbSelect"> <input id="rbArtist" name="rbByParam" type="radio" value="SongArtist" /> <label for="rbArtist">Artist</label> </span> <span class="rbSelect"> <input id="rbAuthor" name="rbByParam" type="radio" value="SongAuthor" /> <label for="rbAuthor">Author</label> </span><br /> <select id="ddlSongArtist" name="ddlSongArtist" onchange="ddlArtistChange(this)"> <option value="">Select Artist</option> <% artists.forEach(function(artist){ %> <option value="<%= artist.SongArtist %>"><%= artist.SongArtist %></option> <% }) %> </select> <select id="ddlSetList" name="ddlSetList"> <option value="">Select Set List</option> <% setlists.forEach(function(setlist){ %> <option value="<%= setlist.SetListID %>"><%= setlist.SetListName %></option> <% }) %> </select> </div> <div class="col-md-6"> <h1>Controls</h1> <input type="button" id="btnSetList" class="btnCtrl1" value="Render Set List" onclick="loadSetList()" /> </div> </div> <div id="TabsList" name="TabsList" class="row NoPrint"> <div class="col-md-6"> <h3>Select List</h3> <div id="divMsg"></div> <ul id="ulSelectSong"></ul> </div> <div class="col-md-6"> <h3>Set List</h3> <ul id="ulSetList"></ul> </div> </div> <div id="TabsSetList" class="row"> </div> </form> <% include partials/footer %>

<!DOCTYPE html> <html> <head> <title>Node JS - Express Test Page</title> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="description" content=""/> <meta name="author" content=""/> <link type="text/css" rel="stylesheet" href="css/site.css"> <link type="text/css" rel="stylesheet" href="css/bootstrap.min.css"> <link type="text/css" rel="stylesheet" href="css/ie10-viewport-bug-workaround.css"> <link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans" /> <script src="js/ie-emulation-modes-warning.js"></script> <script src="js/jquery.min.js" ></script> <script src="js/jquery-ui.min.js" ></script> <script src="js/main.js" ></script> </head> <body> <div class="container"> <h4>Header here</h4> <hr/>

<hr/> <h4>Footer Here</h4> </div> <!-- Bootstrap core JavaScript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> <script src="js/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')</script> <script src="js/bootstrap.min.js"></script> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <script src="js/ie10-viewport-bug-workaround.js"></script> </body> </html>

Styling

body { font:normal 16px 'Open Sans',Helvetica,Arial,sans-serif; margin:0px;border:0px;padding:0px;width:100%; background-color:#FFFFFF;color:#555; } html {overflow-y: scroll;} span.rbSelect label {margin:1% 2%;} .musicTab { width:100%; margin:0px;border:0px none #333;padding:0px; white-space:pre; font:normal 16px 'Courier New',Courier,Arial,sans-serif; } .btnCtrl1 { width:20rem; margin:0px; border:1px solid #0A0; border-radius:4px; padding:0.2rem 1rem; background-color:#333; color:#fff; text-align:left; } .btnCtrl1:hover, .btnCtrl1:active { background-color:#999; border-color:#00f; color:#333; } /** T A B A P P S E T T I N G S **/ a.anchorBtnSm { width:25px; height:15px; display:inline-block; margin:0px 4px 0px 0px; border:1px solid #000; border-radius:3px; padding:2px 2px 4px 2px; text-align:center; vertical-align:middle; font-weight:700; font-size:0.65em; } a.anchorBtnSm:link { color:#fff; background-color:#4F7E9E; text-decoration:none; } a.anchorBtnSm:visited { color:#fff; background-color:#4F7E9E; text-decoration:none; } a.anchorBtnSm:hover { color:#555; background-color:#CFDCE6; text-decoration:underline; } a.anchorBtnSm:active { color:#555; background-color:#CFDCE6; text-decoration:none; } /* S E T L I S T */ ul#ulSetList { list-style-type:none; margin:10px 0px; border:0px none #fff; padding:0px; } ul#ulSetList li { width:460px; background-color:#DDD; margin:5px 20px; border:1px solid #555; border-radius:3px; padding:5px; cursor:pointer; font-size:0.75em; vertical-align:bottom; } ul#ulSetList li:hover { background-color:#CFDCE6; color:#555; } /* S E L E C T S O N G F O R S E T L I S T */ ul#ulSelectSong { list-style-type:none; margin:10px 0px; border:0px none #fff; padding:0px; } ul#ulSelectSong li { width:460px; background-color:#fff; margin:5px 20px; border:1px solid #555; border-radius:3px; padding:5px; cursor:pointer; font-size:0.75em; } ul#ulSelectSong li:hover { background-color:#CFDCE6; color:#555; } /* R E N D E R E D S O N G T I T L E */ div.song-title { font-size:1.2rem; font-weight:700; padding:2rem 0rem 0.5rem 0rem; color:#369; } /* R E N D E R E D S O N G A R T I S T */ div.song-artist { font-size:1.2rem; font-weight:700; padding:2rem 0rem 0.5rem 0rem; color:#369; } /* R E N D E R E D S O N G T E X T */ div.song-text { width:100%; margin:5px; border:0px none #000; padding:0px; page-break-after:always; white-space:pre; font-family:'Courier New'; font-size:1.0rem; color:#000; } /* C O N T R O L P A N E L F O R M U S I C T A B S */ div#CtrlPnlWrap { position:relative; width:980px; height:50px; margin:0px auto; border:0px none #000; padding:0px; } /* S E L E C T A L P H A B E T L E T T E R */ div#CtrlPnlWrap > div:first-child { position:absolute; top:0px; left:0px; width:80px; height:30px; margin:0px; border:0px none #000; padding:0px; background-color:transparent; } /* R A D I O A L P H A B E T C H O I C E S */ div#CtrlPnlWrap > div:nth-child(2) { position:absolute; top:0px; left:80px; font-size:0.8em; width:210px; height:30px; margin:0px; border:0px none #000; padding:0px; background-color:transparent; } .rbSelect { margin:0px; border:0px none #000; padding:0px; } /* S E L E C T A R T I S T */ div#CtrlPnlWrap > div:nth-child(3) { position:absolute; top:0px; left:300px; width:390px; height:30px; margin:0px; border:0px none #000; padding:0px; background-color:transparent; } /* B U T T O N S */ div#CtrlPnlWrap > div:nth-child(4) { position:absolute; top:0px; right:0px; width:270px; height:30px; margin:0px; border:0px none #000; padding:0px; background-color:transparent; } div#TabsTitle {display:normal;} div#TabsControl {display:normal;} div#TabsList {display:normal;} div#TabsSetList {display:normal;} div#TabsScreenRes {display:none;}

The JSON Files

{ "name": "app7", "version": "1.0.0", "description": "MySQL Tab Application Development", "main": "app7.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Dirk Harriman", "license": "ISC", "dependencies": { "body-parser": "^1.18.3", "ejs": "^2.6.1", "express": "^4.16.3", "mysql": "^2.16.0" } }

{ "name": "app7", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "bignumber.js": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" }, "body-parser": { "version": "1.18.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "requires": { "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "~1.6.3", "iconv-lite": "0.4.23", "on-finished": "~2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", "type-is": "~1.6.16" } }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "express": { "version": "4.16.3", "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "requires": { "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.3", "qs": "6.5.1", "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", "statuses": "~1.4.0", "type-is": "~1.6.16", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", "requires": { "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.1", "http-errors": "~1.6.2", "iconv-lite": "0.4.19", "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", "type-is": "~1.6.15" } }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", "iconv-lite": "0.4.19", "unpipe": "1.0.0" }, "dependencies": { "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", "requires": { "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", "statuses": ">= 1.3.1 < 2" } }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" } } }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, "finalhandler": { "version": "1.1.1", "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "statuses": "~1.4.0", "unpipe": "~1.0.0" }, "dependencies": { "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "http-errors": { "version": "1.6.3", "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ipaddr.js": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { "version": "1.36.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" }, "mime-types": { "version": "2.1.20", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "requires": { "mime-db": "~1.36.0" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mysql": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.16.0.tgz", "integrity": "sha512-dPbN2LHonQp7D5ja5DJXNbCLe/HRdu+f3v61aguzNRQIrmZLOeRoymBYyeThrR6ug+FqzDL95Gc9maqZUJS+Gw==", "requires": { "bignumber.js": "4.1.0", "readable-stream": "2.3.6", "safe-buffer": "5.1.2", "sqlstring": "2.3.1" }, "dependencies": { "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "requires": { "ee-first": "1.1.1" } }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "proxy-addr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "requires": { "forwarded": "~0.1.2", "ipaddr.js": "1.8.0" } }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "requires": { "bytes": "3.0.0", "http-errors": "1.6.3", "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, "readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", "on-finished": "~2.3.0", "range-parser": "~1.2.0", "statuses": "~1.4.0" }, "dependencies": { "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, "serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.2", "send": "0.16.2" } }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.18" } }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" } } }