Every night a dump of configuration data is made containing information about staff such as name, phone, email, and various other data points. I pull this data via ajax into an indexedDB used by the web application as it would use a database.

The application uses the department field to sort users into departments. It contains a feature where you can take names and drop them onto a surface or dump an entire department to create a mailing list .

The really cool thing about this approach is virtually all the processing is on the client computer so little CPU overhead. From a security perspective there isn’t much here to compromise. The server can be in a DMZ or even totally exposed but only information already available via the application is stored on the server. Finally no application server is needed, just a plain old HTTP server.

indexdb.js indexedDB Code

As mentioned earlier this data is dumped and is dirty. Most of the code below is involved in sorting through inconsistencies in the data to arrive at valid information. With proper formatting, this code could probably be cut down by about 80%.

/**
 * Created by jmm on 7/22/2016.
 */

var db = '';
var searchresults = '';
var employeesOS = '';

function loadFileContents(version, browserparameters) {

  $.ajax({
    //location of the directory flat file and load
    url: "http://cosinfo.springfield-ma.gov/directory/adusersou.csv", success: function (filecontents) {

      var temp;

      //version information is absolute value of hash (since no negatives allowed for db version) plus a number in case we need to manually fo
      // rce an updated of the database.
      var combinedversion = Math.round(version); //(Math.abs(filecontents.hashCode()) +
      $("#versionid").html("Database Version: " + combinedversion);
      console.log(combinedversion);
      var openRequest = indexedDB.open("employeesDB", combinedversion);

      openRequest.onupgradeneeded = function (e) {
        console.log("running onupgradeneeded");

        db = e.target.result;

        db.onerror = function (event) {
          console.log("Error loading database");
        };

        if (!db.objectStoreNames.contains("employees")) {
          try {
            console.log("making a new object store");
            window.employeesOS = db.createObjectStore("employees", {autoIncrement: true});
            window.employeesOS.createIndex("department", "department", {unique: false});
            window.employeesOS.createIndex("lastname", "lastname", {unique: false});
            window.employeesOS.createIndex("firstname", "firstname", {unique: false});
            window.employeesOS.createIndex("title", "title", {unique: false});
            window.employeesOS.createIndex('allindex', ['department', 'lastname', 'firstname', 'telephone', 'title', 'email'], {unique: false});
            window.employeesOS.createIndex("fullemployee", "fullemployee", {unique: false});

            temp = processDirectoryString(filecontents, window.employeesOS);
          } catch (e) {
            console.log(e);
          }
        } else {
          try {
            db.deleteObjectStore("employees");
            console.log("Database deleted successfully");
            console.log("makng a new object store");
            window.employeesOS = db.createObjectStore("employees", {autoIncrement: true});
            window.employeesOS.createIndex("department", "department", {unique: false});
            window.employeesOS.createIndex("lastname", "lastname", {unique: false});
            window.employeesOS.createIndex("firstname", "firstname", {unique: false});
            window.employeesOS.createIndex("title", "title", {unique: false});
            window.employeesOS.createIndex("telephone", "telephone", {unique: false});
            window.employeesOS.createIndex('allindex', ['department', 'lastname', 'firstname', 'title', 'telephone', 'email'], {unique: false});
            window.employeesOS.createIndex("fullemployee", "fullemployee", {unique: false});

            temp = processDirectoryString(filecontents, window.employeesOS);
          } catch (e) {
            console.log(e);
          }
        }
      }

      openRequest.onsuccess = function (e) {
        console.log("running onsuccess");
        db = e.target.result;
        getDepartments(db);
      }

      openRequest.onerror = function (e) {
        console.log(e.target.error.name + ": " + e.target.error.message);
      }
    }
  });
}

function getDepartments(db) {
  var transaction = db.transaction(["employees"], "readwrite");
  var store = transaction.objectStore('employees');
  var temp = "";
  var index = store.index('department');
  var thisindex = store.index('department');

  thisindex.openKeyCursor(null, "nextunique").onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
      if (cursor.key.indexOf("{") <= 0) {
        temp = temp + '<li class="ajaxSideMenu" id="sidemenuelement"><a href="javascript:void(0)" onclick="getDepartmentsbyClick(\'' + cursor.key.replace(/\"/g, '').replace(/\'/g, '') + '\',\'#resultsdiv\')">' + cursor.key.replace(/\"/g, '').replace(/\'/g, '') + '</a></li>'
      }
      cursor.continue();
    }
  };

  transaction.oncomplete = function (event) {
    $("#menuitems").html(temp);
  };

  transaction.onerror = function (event) {
    console.log(event);
  };

}

function getDepartmentsbyClick(searchterm, element) {
  window.searchresults = "";
  var transaction = window.db.transaction(["employees"], "readonly");
  var store = transaction.objectStore('employees');
  var thisindex = store.index('fullemployee');

  var request = thisindex.openKeyCursor(null, "nextunique");
  request.onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
      //console.log(cursor);
      var s;
      if (cursor.key.toString().indexOf("{") <= 0 && cursor.key.toString().indexOf("NORMAL_ACCOUNT") <= 0) {
        var cursorsplit = cursor.key.toString().split(",");
        if (cursorsplit[2].toLowerCase() == searchterm.toLowerCase()) {
          var cursorarray = cursor.key.toString().split(',');
          window.searchresults = window.searchresults +
            '<div  nameid="' + cursorarray[0] + cursorarray[1] + '" id="draggable_name_id" class="draggable-name" style=" background: #d6e7f9; border-radius: 10px; border: 1px solid #ebebeb; margin: 5px;  padding: 5px;"><div id="clickerhideparent" class="clicker_hide_parent"><span ><a href="javascript:void(0)">' + cursorarray[0] + ', ' + cursorarray[1] + '</a></span><span style="float:right"><div style="width:350px; text-align:right">' + cursorarray[2] + '</div></span></div>' +
            '<div id="personparent" nameid="' + cursorarray[1] + cursorarray[2] + '" style="display: none;">' +
            '<div id="' + cursorarray[1] + cursorarray[2] + '_one"  style=" background: #FFFFFF; border-radius: 5px; border: 1px solid #ebebeb; margin: 7px;  padding: 5px; height: auto;">' +
            '<table width="500" ><tr><td>Email: ' + cursorarray[5] + '</td><td align="right">' + cursorarray[3]
            + '<tr><td width="64%">Phone : <a id="phone" href=tel:"' + cursorarray[4].replace(/\(/g, '').replace(/\)/g, '').replace(/-/g, '').replace(/ /g, '') + '>' + formatPhoneNumber(cursorarray[4].replace(/\(/g, '').replace(/\)/g, '').replace(/-/g, '').replace(/ /g, '')) + '</a></td><td></td></tr>'
            + '</td></tr></table>'
            + '</div></div></div>';
        }
      }
      //console.log("sr: " + window.searchresults);
      cursor.continue();
    }
    else {
      //console.log('Entries all displayed.');
    }
  };
  request.onerror = function (event) {
    console.log(event);
  }

  transaction.oncomplete = function (event) {
    //console.log(window.searchresults);
    $(element).html(window.searchresults); //searchterm + " = " +
    var cols = document.querySelectorAll('#resultsdiv .draggable-name');
    [].forEach.call(cols, function(col) {
      col.addEventListener('dragstart', handleDragStart, false);
    });
    window.location.href = "#";
  };

  transaction.onerror = function (event) {

  };

  return window.searchresults;
}

function getSearchResults(searchterm, element) {
  window.searchresults = "";
  var transaction = window.db.transaction(["employees"], "readonly");
  var store = transaction.objectStore('employees');
  var thisindex = store.index('fullemployee');

  thisindex.openKeyCursor(null, "nextunique").onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
      var s;
      if (cursor.key.toString().indexOf("{") <= 0 && cursor.key.toString().indexOf("NORMAL_ACCOUNT") <= 0) {
        if (cursor.key.toString().toLowerCase().indexOf(searchterm.toLowerCase()) >= 0) {
          var cursorarray = cursor.key.toString().split(',');
          window.searchresults = window.searchresults +
            '<div draggable="true" nameid="' + cursorarray[0] + cursorarray[1] + '" class="draggable-name"  style=" background: #d6e7f9; border-radius: 10px; border: 1px solid #ebebeb; margin: 5px;  padding: 5px;"><div id="clickerhideparent"><span ><a href="javascript:void(0)">' + cursorarray[0] + ', ' + cursorarray[1] + '</a></span><span style="float:right"><div style="width:350px; text-align:right">' + cursorarray[2] + '</div></span></div>' +
            '<div id="personparent" nameid="' + cursorarray[1] + cursorarray[2] + '" style="display: none;">' +
            '<div id="' + cursorarray[1] + cursorarray[2] + '_one"  style=" background: #FFFFFF; border-radius: 5px; border: 1px solid #ebebeb; margin: 7px;  padding: 5px; height: auto;">' +
            '<table width="500" ><tr><td>Email: ' + cursorarray[5] + '</td><td align="right">' + cursorarray[3]
            + '<tr><td width="64%">Phone : <a id="phone" href=tel:"' + cursorarray[4].replace(/\(/g, '').replace(/\)/g, '').replace(/-/g, '').replace(/ /g, '') + '>' + formatPhoneNumber(cursorarray[4].replace(/\(/g, '').replace(/\)/g, '').replace(/-/g, '').replace(/ /g, '')) + '</a></td><td></td></tr>'
            + '</td></tr></table>'
            + '</div></div></div>';
        }
      }
      cursor.continue();
    }
    else {
      //console.log('Entries all displayed.');
    }
  };

  transaction.oncomplete = function (event) {
    $(element).html(window.searchresults);
    var cols = document.querySelectorAll('#resultsdiv .draggable-name');
    [].forEach.call(cols, function(col) {
      col.addEventListener('dragstart', handleDragStart, false);
      });
  };

  transaction.onerror = function (event) {

  };

  return window.searchresults;
}

function processDirectoryString(s, db) {

  //split it up by line breaks, each entry is on a single line
  var splitbylines = s.split("\n");
  var results;

  for (x = 1, lenx = splitbylines.length; x < lenx; x++) {
    if (splitbylines[x].indexOf("ACCOUNTDISABLE") < 0) { //&& ((splitbylines[x].indexOf("employeeID") > 0 && splitbylines[x].indexOf('\\', splitbylines[x].indexOf("CN=") + 3) > 0) || (splitbylines[x].split(',')[0].indexOf('NORMAL_ACCOUNT')>=0)) ){
      //if(splitbylines[x].indexOf("employeeID") > 0 && splitbylines[x].indexOf('\\', splitbylines[x].indexOf("CN=") + 3) > 0) {
      // if (splitbylines[x].indexOf("employeeID") > 0) {
      //console.log(splitbylines[x].indexOf("department") + " | " + splitbylines[x].indexOf('\\', splitbylines[x].indexOf("CN=") + 3));
      // }
      results = parseline(splitbylines[x]);

      if (!(results[1].trim() == "") && results[2].trim().toLowerCase() != 'conference') {
        var employee = {
          'department': results[0]
          ,
          'lastname': results[1]
          ,
          'firstname': results[2]
          ,
          'title': results[3]
          ,
          'telephone': results[4]
          ,
          'email': results[5]
          ,
          'location': results[6]
          ,
          'fullemployee': results[2] + ',' + results[1] + ',' + results[0] + ',' + results[3] + ',' + results[4] + ',' + results[5] + ',' + results[6]
        };
        var request = db.put(employee);
      } else {
        var request = "";
      }
      request.onerror = function (e) {
        console.log("Error: ", e.target.error.name, e.target.error.message, results[0] + " " + results[1]);
      };
      request.onsuccess = function (e) {
        //console.log(x);
      };
    } else {
      // if(splitbylines[x].indexOf("employeeID") > 0) {
      //   console.log(splitbylines[x].indexOf("department") + " | " + splitbylines[x].indexOf('\\', splitbylines[x].indexOf("CN=") + 3));
      // }

    }
    // if(x == 20) {
    //   break;
    // }
  }
}

function parseline(linetext) {
  var returnarray = ['', '', '', '', '', '', ''];
  var linetextsplit = linetext.split(',');
  if (linetextsplit.length > 1) {
    if (!(linetextsplit[0].replace(/\"/g, "").trim() == "NORMAL_ACCOUNT" || linetextsplit[0].replace(/\"/g, "").trim() == "TRUSTED_FOR_DELEGATION" || linetextsplit[0].replace(/\"/g, "").trim() == "PASSWD_NOTREQD" )) {
      returnarray[0] = findDepartment(linetext);
      returnarray[1] = findFirstName(linetext);
      returnarray[2] = findLastName(linetext);
      returnarray[3] = findTitle(linetext);
      returnarray[4] = findPhone(linetext);
      returnarray[5] = createEmail(linetext);
      returnarray[6] = '';
      //console.log(returnarray);
    }
  }
  return returnarray;
}

function findDepartment(linetext) {
  var department = "";
  if (linetext.indexOf("department") > 0) {
    department = "" + (linetext.substring(linetext.indexOf("department") + 15, linetext.indexOf('"', linetext.indexOf("department") + 15)));
  } else if (linetext.split(',')[1].trim() != "") {
    department = "" + (linetext.split(',')[1].trim().replace("\"", ""));
  } else {
    department = findOU(linetext);
  }
  if (department) {
    if (department.trim() == '311') {
      department = "311 Call Center";
    } else if (department.trim() == 'Capital Assets' || department.trim() == 'Capital Asset') {
      department = "Capital Asset Construction";
    } else if (department.trim().toLowerCase().indexOf("city clerk") >= 0) {
      department = "City Clerk";
    } else if (department.trim().toLowerCase() == "housing") {
      department = "Code Enforcement";
    } else if (department.trim().toLowerCase().indexOf("treas") >= 0 || department.trim().toLowerCase().indexOf("collect") >= 0) {
      department = "Collector/Treasurer";
    } else if (department.trim() == 'Comm Dev Plan Management') {
      department = "Community Developement";
    } else if (department.trim() == 'Office of Consumer Information') {
      department = "Consumer Information";
    } else if (findTitle(linetext).toLowerCase().indexOf("dpw") >= 0 || department.trim().toLowerCase() == 'dpw engineering' || department.trim().toLowerCase() == 'dpw' || department.trim().toLowerCase() == 'department public works' || department.trim().toLowerCase().indexOf("fleet") >= 0 || department.trim().toLowerCase().indexOf("engineer") >= 0 || department.trim().toLowerCase().indexOf("traffic") >= 0 || department.trim().toLowerCase().indexOf("streets") >= 0 || department.trim().toLowerCase().indexOf("waste") >= 0 || department.trim().toLowerCase().indexOf("repair") >= 0) {
      department = 'Department of Public Works';
    } else if (department.trim().toLowerCase().indexOf("election") >= 0) {
      department = "Election Commission";
    } else if (department.trim().toLowerCase().indexOf("elder") >= 0) {
      department = "Elder Affairs";
    } else if (department.trim().toLowerCase().indexOf("facilit") >= 0 || department.trim().toLowerCase().indexOf("collect") >= 0) {
      department = "Facilities Management";
    } else if (department.trim().toLowerCase() == 'alarm' || department.trim().toLowerCase() == 'fire dept' || department.trim().toLowerCase() == 'fire dept.'  || department.trim().toLowerCase().indexOf("fire") == 0 || department.trim().toLowerCase() == 'prevention') {
      department = "Fire Department";
    } else if (department.trim().toLowerCase().indexOf("health") >= 0 || department.trim().toLowerCase() == "hhs") {
      department = "Health and Human Services";
    } else if (department.trim().toLowerCase() == "housing - 1600 columbus") {
      department = "Housing Department";
    } else if (department.trim().toLowerCase() == 'it' || department.trim().toLowerCase().indexOf("information technology") == 0) {
      department = "Information Technology";
    } else if (department.trim().toLowerCase().indexOf("law") >= 0) {
      department = "Law";
    } else if (department.trim().toLowerCase().indexOf("library") >= 0) {
      department = "Library";
    } else if (department.trim().toLowerCase().indexOf("mayor") >= 0) {
      department = "Mayors Office";
    } else if (department.trim() == 'Admin' || department.trim() == 'Casino Liaison' || department.trim() == 'Chief Admin Fin Office' || department.trim() == 'Admin & Finance' || department.trim().toLowerCase().indexOf("budget") >= 0 || department.trim().toLowerCase().indexOf("cafo") >= 0 || department.trim().toLowerCase().indexOf("munis") >= 0) {
      department = "Office of Management and Budget";
    } else if (department.trim().toLowerCase().indexOf("park") >= 0) {
      department = "Parks Department";
    } else if (department.trim() == 'Building') {
      department = "Permits & Inspections";
    } else if (department.trim().toLowerCase().indexOf("personnel") >= 0) {
      department = "Personnel Department";
    } else if (department.trim().toLowerCase().indexOf("planning") >= 0) {
      department = "Planning and Economic Development";
    } else if (department.trim().toLowerCase().indexOf("police") >= 0) {
      department = "Police";
    } else if (department.trim().toLowerCase().indexOf("procurement") >= 0) {
      department = "Office of Procurement";
    } else if (department.trim().toLowerCase().indexOf("tjo") >= 0) {
      department = "TJO Animal Control";
    } else if (department.trim().toLowerCase().indexOf("veteran") >= 0) {
      department = "Veterans Service";
    } else if (department.trim() == 'Code Enforcement-Weights and M') {
      department = "Weights and Measures";
    }
      return department;
  }
}

function findOU(linetext) {
  var findou = linetext.split(',');
  for (var i = 0; i < findou.length; i++) {
    if (findou[i].indexOf("OU=") >= 0) {
      if (findou[i].indexOf("Users") < 0 && findou[i].indexOf("City of Springfield") < 0 && findou[i].indexOf("City Hall") < 0) {
        return "" + findou[i].replace("OU=", "");
      }
    }
  }
}

function findLastName(linetext) {
  if (linetext.indexOf('\\', linetext.indexOf("CN=") + 3) > 0) {
    return "" + (linetext.substring(linetext.indexOf("CN=") + 3, linetext.indexOf('\\', linetext.indexOf("CN=") + 3)));
  } else {
    return "" + (linetext.substring(linetext.indexOf("CN=") + 3, linetext.indexOf(',', linetext.indexOf("CN=") + 3)));
  }
}

function findFirstName(linetext) {
  if (linetext.indexOf('\\', linetext.indexOf("CN=") + 3) > 0) {
    return (linetext.substring(linetext.indexOf("\\") + 2, linetext.indexOf(',', linetext.indexOf("\\") + 2)));
  } else {
    return "";
  }
}

function findTitle(linetext) {
  if (linetext.indexOf('""title""') > 0) {
    var sublinetext = linetext.substring(linetext.indexOf('""title""') + 12);
    return (sublinetext.substring(0, sublinetext.indexOf('"')).replace(/,/g, " -"));
  } else {
    return "";
  }
}

function findPhone(linetext) {
  if (linetext.indexOf('""telephoneNumber""') > 0) {
    var sublinetext = linetext.substring(linetext.indexOf('""telephoneNumber""') + 22);
    return (sublinetext.substring(0, sublinetext.indexOf('"')));
    //"<a href='tel:" + sublinetext.substring(0, sublinetext.indexOf('"')) + ">" + fnameinitial + lname + "@springfieldcityhall.com</a>";
  } else {
    return "";
  }
}

function createEmail(linetext) {
  var fnameinitial = findFirstName(linetext).trim().substring(0, 1).toLowerCase();
  var lname = findLastName(linetext).trim().replace(/[\. ]/g, '').toLowerCase();
  if (fnameinitial.length > 0 && lname.length > 0) {
    var email = "<a id='email' href='mailto:" + fnameinitial + lname + "@springfieldcityhall.com'>" + fnameinitial + lname + "@springfieldcityhall.com</a>";
  }
  else {
    var email = "";
  }
  return email;
}

function formatPhoneNumber(phonenumber) {
  var formattedphonenumber = "";
if(!(phonenumber == "") && phonenumber.length == 10){
  formattedphonenumber = "(" + phonenumber.slice(0,3) + ") " + phonenumber.slice(3,6) + "-" + phonenumber.slice(6);
}
return formattedphonenumber
}





utilities.js

This creates a hash of the source data file. If the hash of the current file does not match the hash of the previously checked file, then it reloads the data in the above indexedDB.

/**
 * Created by jmm on 7/22/2016.
 */

String.prototype.hashCode = function () {
  var hash = 0, i, chr, len;
  if (this.length === 0) return hash;
  for (i = 0, len = this.length; i < len; i++) {
    chr = this.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return hash;
};

modal.js

This is the code for the drag and drop box to create mailing lists.

/**
 * Created by jmm on 9/15/2016.
 */

// Get the modal
var modal = document.getElementById('myModal');

// Get the button that opens the modal
var btn = document.getElementById("myBtn");

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks on the button, open the modal
btn.onclick = function () {
  modal.style.display = "block";
}

// When the user clicks on <span> (x), close the modal
span.onclick = function () {
  modal.style.display = "none";
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function (event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}


/* LIST CREATION */

var dragSrcEl = null;

function handleDragStart(e) {
  // Target (this) element is the source node.
  this.style.opacity = '0.4';

  dragSrcEl = this;

  e.dataTransfer.effectAllowed = 'copy';
  e.dataTransfer.setData('text/html', this.innerHTML);
}


function handleDragOver(e) {
  if (e.preventDefault) {
    e.preventDefault(); // Necessary. Allows us to drop.
  }

  e.dataTransfer.dropEffect = 'copy';  // See the section on the DataTransfer object.

  return false;
}

function handleDragEnter(e) {
  // this / e.target is the current hover target.
  this.classList.add('over');
}

function handleDragLeave(e) {
  this.classList.remove('over');  // this / e.target is previous target element.
}

function handleDrop(e) {
  // this/e.target is current target element.

  if (e.stopPropagation) {
    e.stopPropagation(); // Stops some browsers from redirecting.
  }

  var emails = "";
  // Don't do anything if dropping the same column we're dragging.
  if (dragSrcEl != this) {
    this.innerHTML = this.innerHTML + dragSrcEl.innerHTML;
    //document.getElementById("modal-listcreate-ta").innerHTML = "<a href='mailto:";
    $("#dropplace #personparent a").each(function () {
      var email = $(this).text();
      if (email.indexOf("@") >= 0) {
        if (emails.indexOf(email) < 0) {
          if (emails.length == 0) {
            emails = email ;
          } else {
            emails = emails + ';' + email;
          }
        }
      }
    });



    //   alert(document.getElementById("modal-listcreate-ta").innerHTML);
    //   if(document.getElementById("modal-listcreate-ta").innerHTML.indexOf(email) <= 0) {
    //     if (document.getElementById("modal-listcreate-ta").innerHTML.length == 0) {
    //       document.getElementById("modal-listcreate-ta").innerHTML = email;
    //     } else {
    //       document.getElementById("modal-listcreate-ta").innerHTML = document.getElementById("modal-listcreate-ta").innerHTML + ';' + email;
    //     }
    //   }
    // }
  }
  document.getElementById("modal-listcreate-ta").innerHTML = "<a href='mailto:" + emails + "'>" + emails + "</a>";
  return false;
}

function handleDragEnd(e) {
  // this/e.target is the source node.

  [].forEach.call(cols, function (col) {
    col.classList.remove('over');
  });
}

//<a href="mailto:BTakishaJ@springfieldcityhall.com" target="_top">BTakishaJ@springfieldcityhall.com</a>


index.html

The default index file which pulls it all together.

<!DOCTYPE html> <!--PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-->
<html manifest="directory.appcache">
<!--<html class="no-js" lang="en" xmlns="http://www.w3.org/1999/xhtml">-->

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <meta name="description" content="The HTML5 Herald">
  <meta name="author" content="SitePoint">
  <meta name="version" content="1.1">

  <title>COS Employee Directory</title>

  <link rel="stylesheet" type="text/css" href="COScss/Modal.css" media="all">
  <link rel="stylesheet" type="text/css" href="COScss/main.css" media="all">
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">

  <script src="https://code.jquery.com/jquery-2.2.4.min.js"
          integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
          crossorigin="anonymous"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script src="CoSjs\CoSindexdb.js"></script>
  <script src="CoSjs\CoSutilities.js"></script>


  <!--<script src="CoSjs\CoSajax.js" ></script>-->

</head>
<body>
<div style="margin-left: auto; margin-right: auto; width:1000px;">
  <table cellpadding="0" cellspacing="0" border="0" id="pageFrame" style="height: auto;">
    <tr>
      <td colspan="2" id="banner" style=" height: 30px">
        <table cellpadding="0" cellspacing="0" width="100%" border="0" style="height: 60px">
          <tr>
            <td>
              <h1><a href="http://cosinfo.springfield-ma.gov/portal/"><span style="font-weight: bold; color: #ffffff;"> CoS Info</span>  for
                City of Springfield staff</a></h1></td>
            <td>   </td>
            <td style="width:190px; height:30px" align="right" style="font-size:10pt; color:#ffffcc">
            </td>
          </tr>
        </table>
      </td>
    </tr>
    <!-- ###BANNER### stop -->


    <tr>
      <td valign="top" id="sidebar">
        <img src="images/pixel.gif" width="200" height="10" alt=""/><br/>
        <img src="images/city-seal-gb200.gif" width="180" height="160" alt="city seal" border="0"
             style="padding-left:15px"/>
        <!--<div id="menu">-->
        <ol id="menuText" class="menuText">
          <li class="ajaxSideMenu"><b><a href="http://cosinfo.springfield-ma.gov/portal/">CoS Info</a></b></li>
          <span id="menuitems">
        </span>
        </ol>


        <!--</div>-->
        <!-- placeholder for the sidebar menu data -->

      </td>
      <td valign="top" id="main">
        <div id="content">

          <!--  CONTENT ELEMENT, uid:234/header [begin] -->
          <div id="c234" class="csc-default">
            <!--  Header: [begin] -->
            <div class="csc-header csc-header-n1">
              <h1>CoS Directory</h1>
            </div>
            <div class="center">
              <div style="padding-bottom: 5px"><label>Search: </label></div>
              <input type="text" size="70%" id="searchinput" align="center" style="margin-bottom: 5px"/></div>
            <!--  Header: [end] -->
          </div>
          <!--  CONTENT ELEMENT, uid:234/header [end] -->

          <!--  CONTENT ELEMENT, uid:3009/textpic [begin] -->
          <div id="resultsdiv" style="margin-left: auto; margin-right: auto;"></div>

          <!--  CONTENT ELEMENT, uid:507/shortcut [begin] -->
          <div id="c507" class="csc-default">
            <!--  Inclusion of other records (by reference): [begin] -->
            <!--  Inclusion of other records (by reference): [end] -->
          </div>
          <!--  CONTENT ELEMENT, uid:507/shortcut [end] -->
          <br clear="all"/>
          <div style="width: 100%"><span style="margin: auto;"><button id="myBtn" style="text-align:center; margin-left: auto; margin-right: auto;display:block;">Create List</button></span>
          </div>

          <!-- The Modal -->
          <div id="draggable">
            <div id="myModal" class="modal">
              <div class="modal-content">
                <div class="modal-header">
                  <span class="close">×</span>
                  <h2>Create List</h2>
                </div>
                <div class="modal-body">
                  <div id="modal-buttons" style="padding-top: 10px; width: 100%; padding-bottom: 20px">
                    <div style=" margin-left: auto; margin-right: auto; display: block;text-align: center">
                      <button id="addAllBtn" style="text-align:center; margin-left: auto; margin-right: 20px;">Add All
                      </button>
                      <button id="clearBtn" style="text-align:center; margin-left: 20px; margin-right: auto;">Clear
                      </button>
                    </div>
                  </div>

                  <div id="modal-listcreate" style="min-height: 20px; height: auto;">
                    <div id="modal-listcreate-ta" style="width: 100%; min-height: 50px; height: auto; word-wrap: break-word;"></div></div>

                  <p>
                  <hr>
                  <center>Drop Below</center>
                  </p>

                </div>
                <div id="dropplace" class="modal-droppable"
                     style="height: auto; min-height:50px; padding:10px; border: solid 1px black; background: #fffc24">
                  <p></p>
                </div>

              </div>
            </div>
          </div>


          <br/>
          <!-- ###FOOTER### start -->
          <div id="footer" style="vertical-align: bottom">
            <div style="text-align: center; width: 100%" id="versionid"></div>
            <!--Please report problems with TLM, e-mail, computers, printers and phones by emailing <b>helpdesk@springfieldcityhall.com</b>.-->
            <!--Problems with this web site may be reported by emailing <b>web-admin@springfieldcityhall.com</b>.<br/>-->
          </div> <!-- end footer -->
          <!-- ###FOOTER### stop -->

        </div> <!-- end content div -->

      </td>
    </tr>
  </table>
  <!-- ###MENU_DIV### start -->

  <div id="results"></div>


</div>
</div>
</body>

<script src="CoSjs\Modal.js"></script>
<script>

  var version = new Date().getTime() / 10000;

  $(document).ready(function () {
    if (window.indexedDB) {
      window.indexedDB.deleteDatabase("employees");
      IDBTransaction.READ_WRITE = IDBTransaction.READ_WRITE || 'readwrite';
      IDBTransaction.READ_ONLY = IDBTransaction.READ_ONLY || 'readonly';
      loadFileContents(version, results);
    } else {
      return;
    }

    $('#menuText').children().click(function () {
      $('#searchinput').val("");
    });

    $('#searchinput').bind('input', function () {
      var searchterm = $("#searchinput").val();
      $("#resultsdiv").empty();
      var results = getSearchResults(searchterm, "#resultsdiv");
    });

    $('body').on('click', '#clickerhideparent', function () {
      $(this).closest("div").next().toggle();
    });

    var el = document.getElementById("dropplace");
    el.addEventListener('dragstart', handleDragStart, false);
    el.addEventListener('dragenter', handleDragEnter, false);
    el.addEventListener('dragover', handleDragOver, false);
    el.addEventListener('dragleave', handleDragLeave, false);
    el.addEventListener('drop', handleDrop, false);
    el.addEventListener('dragend', handleDragEnd, false);

    var draggableDiv = $('#myModal');
    draggableDiv.draggable({
      handle: $('.modal-header', draggableDiv)
    });

    var draggableDiv = $('#draggable_name_id');
    draggableDiv.draggable({
      handle: $('.clicker_hide_parent', draggableDiv)
    });

    $("#clearBtn").click(function(){
      document.getElementById("modal-listcreate-ta").innerHTML = ""
      document.getElementById("dropplace").innerHTML = "";
    });

    $("#addAllBtn").click(function(){
      var emails = "";
      $("#resultsdiv a").each(function () {
        var email = $(this).text();
        if (email.indexOf("@") >= 0) {
          if (emails.indexOf(email) < 0) {
            if (emails.length == 0) {
              emails = email ;
            } else {
              emails = emails + ';' + email;
            }
          }
        }
      });
      if( document.getElementById("modal-listcreate-ta").innerHTML.length <=0 ) {
        document.getElementById("modal-listcreate-ta").innerHTML = '<a href="mailto:' + emails + '">' + emails + '</a>';
      }else{
        document.getElementById("modal-listcreate-ta").innerHTML = '<a href="mailto:' + emails + '">' + emails + '</a>';
      }

    });

//
//    var draggableNameDiv = $('#draggable-name');
//    draggableNameDiv.draggable({
//      handle: $('.modal-header', draggableDiv)
//    });


//    $( "#dropplace" ).droppable({
//      drop: function( event, ui ) {
//        $( this )
//          .find( "p" )
//          .html( "Dropped!" );
//      }
//    });

    //$( "#myModal" ).draggable();
//    $('.click').click(function(){
//      //$('.modal').show();
//      $('.modal').draggable();
//    });​


  });

  document.getElementById("dropplace").addEventListener('dragstart', handleDragStart, false);


</script>

<!--<div id="clickerhideparent"><span><a href="javascript:void(0)">Rosario,  Daniel</a></span><span style="float:right"><div-->
  <!--style="width:350px; text-align:right">311 Call Center</div></span></div>-->
<!--<div id="personparent" nameid=" Daniel311 Call Center" style="display: none;">-->
  <!--<div id=" Daniel311 Call Center_one"-->
       <!--style=" background: #FFFFFF; border-radius: 5px; border: 1px solid #ebebeb; margin: 7px;  padding: 5px; height: auto;">-->
    <!--<table width="500">-->
      <!--<tbody>-->
      <!--<tr>-->
        <!--<td>Email: <a href="mailto:drosario@springfieldcityhall.com">drosario@springfieldcityhall.com</a></td>-->
        <!--<td align="right">311 CSR</td>-->
      <!--</tr>-->
      <!--<tr>-->
        <!--<td width="64%">Phone : <a href="tel:""></a></td>-->
        <!--<td></td>-->
      <!--</tr>-->
      <!--</tbody>-->
    <!--</table>-->
  <!--</div>-->
<!--</div>-->

</html>

Loading