Our Vision & Philosophy
U.S. Army Cadet Command’s 2nd “Freedom” Brigade HQ is located on Joint Base McGuire-Dix-Lakehurst in Burlington County, New Jersey.
Covering colleges & universities in New England, New York, New Jersey, and Pennsylvania, Army ROTC is available across host schools,
extensions, and cross-town partners.
Start strong in life, enroll in Army ROTC, the college elective for undergraduate and graduate students that provides leadership training
for success in any career field.
Brigade Overview
Where We Operate
Explore by state to find ROTC programs across the 2nd Brigade footprint.
Find Programs Fast
Use the map, dropdown, or panel list to jump straight to school contact details.
Always Up to Date
All program data is loaded from the TablePress table so updates happen in one place.
Brigade Universities Map
Select a state to load the schools in that state. Click a school in the panel to focus it on the map.
Loading states…
Loading…
Brigade Universities
Cards load only after a state is selected to keep the page fast on mobile.
| school_id | brigade | school_name | program_name | city | state | lat | lon | phone_main | phone_alt | fax | email_main | email_alt | website_url | address_line1 | address_line2 | address_city | address_state | address_zip | host_or_extension | battalion | unit_or_detachment | notes | logo_url | sort_order |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| uconn | 2 | University of Connecticut | Army ROTC | Storrs | CT | 41.808 | -72.252 | (860) 486-6081 | armyrotc@uconn.edu | https://armyrotc.uconn.edu/ | Host | 1 | ||||||||||||
| maine | 2 | University of Maine | Army ROTC | Orono | ME | 44.899 | -68.667 | (207) 581-1121 | brendan.fahey@maine.edu | https://umaine.edu/armyrotc/ | Host | 2 | ||||||||||||
| bostonu | 2 | Boston University | Army ROTC | Boston | MA | 42.350 | -71.105 | (617) 312-4451 | sbraith1@bu.edu | https://www.bu.edu/rotc/army/ | Host | 3 | ||||||||||||
| mit | 2 | Massachusetts Institute of Technology | Army ROTC | Cambridge | MA | 42.360 | -71.094 | (617) 324-1427 | smcd@mit.edu | https://www.army.mit.edu/ | Host | 4 | ||||||||||||
| northeastern | 2 | Northeastern University | Army ROTC | Boston | MA | 42.339 | -71.089 | (617) 373-2376 | sc.lyons@northeastern.edu | https://rotc.northeastern.edu/ | Host | 5 | ||||||||||||
| umass | 2 | University of Massachusetts | Army ROTC | Amherst | MA | 42.386 | -72.530 | (413) 545-5360 | traviswright@umass.edu | https://www.umass.edu/armyrotc/ | Host | 6 | ||||||||||||
| wpi | 2 | Worcester Polytechnic Institute | Army ROTC | Worcester | MA | 42.274 | -71.808 | (508) 831-5268 | DLGill@wpi.edu | https://www.wpi.edu/academics/departments/military-science | Host | 7 | ||||||||||||
| unh | 2 | University of New Hampshire | Army ROTC | Durham | NH | 43.138 | -70.937 | (603) 862-7075 | joseph.laplante@unh.edu | https://www.unh.edu/army/ | Host | 8 | ||||||||||||
| princeton | 2 | Princeton University | Army ROTC | Princeton | NJ | 40.343 | -74.651 | (609) 258-4225 | armyrotc@princeton.edu | https://princetonarmyrotc.princeton.edu/ | Host | 9 | ||||||||||||
| rutgers | 2 | Rutgers University | Army ROTC | New Brunswick | NJ | 40.501 | -74.447 | (848) 932-3217 | dontay.powell@rutgers.edu | https://armyrotc.rutgers.edu/home | Host | 10 | ||||||||||||
| setonhall | 2 | Seton Hall University | Army ROTC | South Orange | NJ | 40.743 | -74.245 | (973) 313-6254 | alexander.ortega@shu.edu | https://www.shu.edu/rotc/ | Extension | 11 | ||||||||||||
| canisius | 2 | Canisius College | Army ROTC | Buffalo | NY | 42.925 | -78.852 | (716) 888-3219 | rotc1@canisius.edu | https://www.canisius.edu/academics/programs/undergraduate/army-rotc | Host | 12 | ||||||||||||
| ccny | 2 | City College of New York | Army ROTC | New York | NY | 40.820 | -73.949 | (212) 650-6478 | rotc@cuny.edu | https://www.ccny.cuny.edu/rotc | Host | 13 | ||||||||||||
| clarkson | 2 | Clarkson University | Army ROTC | Potsdam | NY | 44.664 | -74.993 | (315) 268-7695 | stoth@clarkson.edu | https://www.clarkson.edu/army-rotc | Host | 14 | ||||||||||||
| cornell | 2 | Cornell University | Army ROTC | Ithaca | NY | 42.453 | -76.473 | (607) 255-4000 | armyrotc@cornell.edu | https://armyrotc.cornell.edu/ | Host | 15 | ||||||||||||
| fordham | 2 | Fordham University | Army ROTC | Bronx | NY | 40.862 | -73.885 | (718) 817-4876 | armyrotc@fordham.edu | https://www.fordham.edu/academics/academic-resources/rotc/army/ | Extension | 16 | ||||||||||||
| hofstra | 2 | Hofstra University | Army ROTC | Hempstead | NY | 40.712 | -73.602 | (516) 463-7682 | ArmyRotc@hofstra.edu | https://www.hofstra.edu/military-science/ | Extension | 17 | ||||||||||||
| niagara | 2 | Niagara University | Army ROTC | Niagara University | NY | 43.136 | -79.038 | (716) 286-8235 | sdonohue@niagara.edu | https://rotc.niagara.edu/ | Extension | 18 | ||||||||||||
| rit | 2 | Rochester Institute of Technology | Army ROTC | Rochester | NY | 43.084 | -77.674 | (585) 475-6817 | dcparm@rit.edu | https://www.rit.edu/universitystudies/armyrotc | Extension | 19 | ||||||||||||
| stbonaventure | 2 | Saint Bonaventure University | Army ROTC | St. Bonaventure | NY | 42.079 | -78.476 | (716) 375-2565 | rotc@sbu.edu | https://www.sbu.edu/academics/special-programs/army-rotc | Extension | 20 | ||||||||||||
| stjohns | 2 | Saint John's University | Army ROTC | Queens | NY | 40.721 | -73.794 | (718) 990-2745 | johnsoj5@stjohns.edu | https://www.stjohns.edu/offices-departments/army-rotc | Extension | 21 | ||||||||||||
| siena | 2 | Siena College | Army ROTC | Loudonville | NY | 42.718 | -73.753 | (518) 783-2477 | rotcrecruiting@siena.edu | https://www.siena.edu/programs/military-science-rotc/ | Extension | 22 | ||||||||||||
| suny | 2 | State University of New York Brockport | Army ROTC | Brockport | NY | 43.211 | -77.951 | (585) 395-2769 | dfletche@brockport.edu | https://www.brockport.edu/academics/military-science/ | Host | 23 | ||||||||||||
| syracuse | 2 | Syracuse University | Army ROTC | Syracuse | NY | 43.039 | -76.135 | (315) 436-3759 | eschaert@syr.edu | https://veterans.syracuse.edu/army-rotc/ | Host | 24 | ||||||||||||
| bucknell | 2 | Bucknell University | Army ROTC | Lewisburg | PA | 40.955 | -76.883 | (570) 577-1013 | armyrotc@bucknell.edu | https://www.bucknell.edu/azdirectory/rotc | Host | 25 | ||||||||||||
| dickinson | 2 | Dickinson College | Army ROTC | Carlisle | PA | 40.203 | -77.198 | (717) 254-1221 | bmbrotc@dickinson.edu | https://www.dickinson.edu/militaryscience | Extension | 26 | ||||||||||||
| drexel | 2 | Drexel University | Army ROTC | Philadelphia | PA | 39.956 | -75.190 | (267) 359-6300 | armyrotc@drexel.edu | https://drexel.edu/provost/offices/undergrad-education/rotc/ | Extension | 27 | ||||||||||||
| edinboro | 2 | Edinboro University | Army ROTC | Edinboro | PA | 41.875 | -80.131 | (814) 732-1618 | tjanderson@pennwest.edu | https://www.pennwest.edu/about/offices-services/rotc/index.php | Extension | 28 | ||||||||||||
| gannon | 2 | Gannon University | Army ROTC | Erie | PA | 42.130 | -80.086 | (814) 871-7682 | patterso019@gannon.edu | https://www.gannon.edu/academic-offerings/special-programs/rotc/ | Extension | 29 | ||||||||||||
| iup | 2 | Indiana University of Pennsylvania | Army ROTC | Indiana | PA | 40.622 | -79.153 | (724) 357-7682 | cchavira@iup.edu | https://www.iup.edu/rotc/index.html | Extension | 30 | ||||||||||||
| lehigh | 2 | Lehigh University | Army ROTC | Bethlehem | PA | 40.607 | -75.378 | (610) 758-3274 | jabe21@lehigh.edu | https://studentaffairs.lehigh.edu/content/military-science-and-leadership-rotc | Extension | 31 | ||||||||||||
| lockhaven | 2 | Lock Haven University | Army ROTC | Lock Haven | PA | 41.137 | -77.444 | (570) 484-2393 | bdo324@lockhaven.edu | https://www.commonwealthu.edu/rotc | Extension | 32 | ||||||||||||
| psu | 2 | Pennsylvania State University | Army ROTC | University Park | PA | 40.798 | -77.859 | (814) 865-7255 | djr18@psu.edu | https://army.psu.edu/ | Host | 33 | ||||||||||||
| shippensburg | 2 | Shippensburg University | Army ROTC | Shippensburg | PA | 40.055 | -77.520 | (717) 477-1896 | ROTC@ship.edu | https://www.ship.edu/academics/coehs/rotc/ | Extension | 34 | ||||||||||||
| slipperyrock | 2 | Slippery Rock University | Army ROTC | Slippery Rock | PA | 41.063 | -80.057 | (724) 738-6175 | bret.rogowitz@sru.edu | https://www.sru.edu/academics/colleges-and-departments/cob/departments/military-science-(rotc) | Extension | 35 | ||||||||||||
| temple | 2 | Temple University | Army ROTC | Philadelphia | PA | 39.981 | -75.155 | (215) 204-7482 | marco.young@temple.edu | https://admissions.temple.edu/apply/military-and-veteran-students | Extension | 36 | ||||||||||||
| pitt | 2 | University of Pittsburgh | Army ROTC | Pittsburgh | PA | 40.444 | -79.954 | (412) 624-6254 | wrp14@pitt.edu | https://www.studentaffairs.pitt.edu/rotc/three-rivers-battalion | Host | 37 | ||||||||||||
| scranton | 2 | University of Scranton | Army ROTC | Scranton | PA | 41.409 | -75.662 | (570) 941-6324 | herbert.ramsey@scranton.edu | https://www.scranton.edu/academics/cas/military-science/index.shtml | Extension | 38 | ||||||||||||
| widener | 2 | Widener University | Army ROTC | Chester | PA | 39.860 | -75.356 | (610) 490-7035 | armyrotc@widener.edu | https://www.widener.edu/academics/undergraduate-programs/army-rotc | Extension | 39 | ||||||||||||
| providence | 2 | Providence College | Army ROTC | Providence | RI | 41.830 | -71.403 | (401) 865-2471 | patriot5@providence.edu | https://rotc.providence.edu/ | Host | 40 | ||||||||||||
| uri | 2 | University of Rhode Island | Army ROTC | Kingston | RI | 41.486 | -71.531 | (401) 874-7682 | vance_dewey@uri.edu | https://web.uri.edu/rotc/ | Host | 41 | ||||||||||||
| uvm | 2 | University of Vermont | Army ROTC | Burlington | VT | 44.475 | -73.212 | (802) 839-8212 | christopher.cunningham@uvm.edu | https://www.uvm.edu/rotc | Host | 42 |
Recent News
- Cadet takes the shot
- US Army Cadet Command announces Senior ROTC rebalance and optimization
- Army ROTC instructors complete Moral Terrain Coaching course
- The next generation: Daughter’s commissioning highlights family’s commitment to military service
- Tafuna High School wins Army JROTC Drone Championship
- Annual Northern Warfare Challenge proves cadets have grit
- Never Quit, Never Settle: 2nd Lt. Janine Colantonio's Pursuit of Excellence in Ranger School
- Pride in their paths
- JROTC cadets from across the country take on the National Raider Challenge
- Cadet Command inducts 25 new members into ROTC Hall of Fame
- VMI becomes first ROTC program to participate in Exercise Cambrian Patrol, secures bronze standard
- VMI Army ROTC becomes first program to send a team for Exercise Cambrian Patrol
- CST 2024 Wrap Up
- U.S. Army Cadet Command welcomes new commander as Munera retires
- Cadet Command's Maj. Gen. Munera retires after 33 years of service
![]() |
|
Colonel Michael E. Erlandson
|
|
![]() |
|
CSM Jordan R. LeeUnited States Army Cadet Command – Joint Base McGuire, New Jersey
|
|
Address:
|
Commander:
(609) 562-3655
|
|
Administrator:
(609) 562-3655
|
|
Recruiting:
(609) 575-6191
|
Four-Year Scholarships
Army Nursing Scholarships
Green-to-Gold Scholarships
March 2 Success
ROTC Blackboard
–
–
–
–
–
/* —————————–
Config
—————————– */
var TABLE_ID = 6; // TablePress id
var STATES_GEOJSON_URL = “https://armyrotc.army.mil/wp-content/uploads/us-states.json”;
/* —————————–
Helpers
—————————– */
function $(id){ return document.getElementById(id); }
function setPanel(title, html){
var panelTitle = $(“mc-map-state-title”);
var panelContent = $(“mc-map-state-content”);
if (panelTitle) panelTitle.textContent = title || “”;
if (panelContent) panelContent.innerHTML = html || “”;
}
function safeText(cell){
return cell ? (cell.textContent || “”).trim() : “”;
}
function firstLink(cell){
if (!cell) return “”;
var a = cell.querySelector(“a[href]”);
return a ? a.getAttribute(“href”) : “”;
}
function firstEmail(cell){
if (!cell) return “”;
var a = cell.querySelector(“a[href^=’mailto:’]”);
if (a) return (a.getAttribute(“href”) || “”).replace(/^mailto:/i, “”).trim();
var txt = safeText(cell);
var m = txt.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i);
return m ? m[0] : “”;
}
function normalizeHeader(h){
return (h || “”).toString().trim().toLowerCase().replace(/\s+/g, “_”);
}
function slugId(name, state){
var base = (name || “school”).toLowerCase().replace(/[^a-z0-9]+/g, “-“).replace(/^-+|-+$/g, “”);
return (base + “-” + (state || “xx”).toLowerCase()).slice(0, 48);
}
function waitForElById(id, timeoutMs){
var start = Date.now();
return new Promise(function(resolve, reject){
(function check(){
var el = $(id);
if (el) return resolve(el);
if (Date.now() – start > timeoutMs) return reject(new Error(“Element not found: ” + id));
setTimeout(check, 150);
})();
});
}
/* —————————–
Leaflet loader (reliable in Avada)
—————————– */
function loadCssOnce(href){
return new Promise(function(resolve){
var links = Array.from(document.querySelectorAll(“link[rel=’stylesheet’]”));
if (links.some(function(l){ return (l.href || “”).indexOf(href) !== -1; })) return resolve();
var link = document.createElement(“link”);
link.rel = “stylesheet”;
link.href = href;
link.onload = function(){ resolve(); };
link.onerror = function(){ resolve(); };
document.head.appendChild(link);
});
}
function loadScriptOnce(src){
return new Promise(function(resolve, reject){
var scripts = Array.from(document.querySelectorAll(“script[src]”));
if (scripts.some(function(s){ return (s.src || “”).indexOf(src) !== -1; })) return resolve();
var s = document.createElement(“script”);
s.src = src;
s.async = true;
s.onload = function(){ resolve(); };
s.onerror = function(){ reject(new Error(“Failed to load script: ” + src)); };
document.head.appendChild(s);
});
}
async function ensureLeaflet(){
if (window.L && typeof window.L.map === “function”) return;
await loadCssOnce(“https://unpkg.com/leaflet@1.9.4/dist/leaflet.css”);
await loadScriptOnce(“https://unpkg.com/leaflet@1.9.4/dist/leaflet.js”);
var start = Date.now();
while (!(window.L && typeof window.L.map === “function”)){
if (Date.now() – start > 8000) throw new Error(“Leaflet not available after load”);
await new Promise(function(r){ setTimeout(r, 100); });
}
}
/* —————————–
TablePress loader (works with or without thead)
Your lat/lon are now clean numbers, so parseFloat is enough
—————————– */
async function loadSchoolsFromTable(){
var table = await waitForElById(“tablepress-” + TABLE_ID, 20000);
var thead = table.querySelector(“thead”);
var tbody = table.querySelector(“tbody”);
if (!tbody) throw new Error(“TablePress table missing tbody.”);
var headers = [];
if (thead){
headers = Array.from(thead.querySelectorAll(“th”)).map(function(th){
return normalizeHeader(th.textContent || “”);
});
} else {
var firstRow = tbody.querySelector(“tr”);
if (!firstRow) throw new Error(“TablePress table has no rows.”);
headers = Array.from(firstRow.querySelectorAll(“td,th”)).map(function(td){
return normalizeHeader(td.textContent || “”);
});
}
function idx(colName){ return headers.indexOf(colName); }
var idxSchoolId = idx(“school_id”);
var idxSchoolName = idx(“school_name”);
var idxProgram = idx(“program_name”);
var idxCity = idx(“city”);
var idxState = idx(“state”);
var idxLat = idx(“lat”);
var idxLon = idx(“lon”);
var idxPhoneMain = idx(“phone_main”);
var idxPhoneAlt = idx(“phone_alt”);
var idxFax = idx(“fax”);
var idxEmailMain = idx(“email_main”);
var idxEmailAlt = idx(“email_alt”);
var idxWebsite = idx(“website_url”);
if (idxSchoolName === -1 || idxState === -1){
throw new Error(“Missing required columns: school_name and state.”);
}
var rows = Array.from(tbody.querySelectorAll(“tr”));
var startIndex = thead ? 0 : 1;
var schools = [];
for (var r = startIndex; r -1 ? safeText(tds[idxState]) : “”).trim().toUpperCase();
if (!name || !state || state.length !== 2) continue;
var idSeed = (idxSchoolId > -1 ? safeText(tds[idxSchoolId]) : “”);
var id = idSeed ? slugId(idSeed, state) : slugId(name, state);
var city = idxCity > -1 ? safeText(tds[idxCity]) : “”;
var program = idxProgram > -1 ? safeText(tds[idxProgram]) : “”;
var phoneMain = idxPhoneMain > -1 ? safeText(tds[idxPhoneMain]) : “”;
var phoneAlt = idxPhoneAlt > -1 ? safeText(tds[idxPhoneAlt]) : “”;
var fax = idxFax > -1 ? safeText(tds[idxFax]) : “”;
var emailMain = idxEmailMain > -1 ? firstEmail(tds[idxEmailMain]) : “”;
var emailAlt = idxEmailAlt > -1 ? firstEmail(tds[idxEmailAlt]) : “”;
var url = idxWebsite > -1 ? (firstLink(tds[idxWebsite]) || safeText(tds[idxWebsite])) : “”;
var latRaw = idxLat > -1 ? safeText(tds[idxLat]) : “”;
var lonRaw = idxLon > -1 ? safeText(tds[idxLon]) : “”;
var lat = parseFloat(latRaw);
var lon = parseFloat(lonRaw);
schools.push({
id: id,
name: name,
program: program,
city: city,
state: state,
phone_main: phoneMain,
phone_alt: phoneAlt,
fax: fax,
email: emailMain || emailAlt || “”,
url: url,
lat: isFinite(lat) ? lat : null,
lon: isFinite(lon) ? lon : null
});
}
return schools;
}
/* —————————–
Main map init
—————————– */
async function init(){
var mapContainer = $(“mc-map”);
if (!mapContainer) return;
var stateSelect = $(“mc-state-select”);
var resetBtn = $(“mc-map-reset”);
var cardsEl = $(“mc-school-cards”);
var emptyEl = $(“mc-cards-empty”);
var panelContent = $(“mc-map-state-content”);
setPanel(“Loading…”, “Preparing the map.”);
await ensureLeaflet();
var schools = await loadSchoolsFromTable();
var statesResp = await fetch(STATES_GEOJSON_URL, { cache: “no-store” });
if (!statesResp.ok) throw new Error(“Failed to fetch states geojson: ” + statesResp.status);
var usStatesGeoJson = await statesResp.json();
// Group by state
var stateSchools = {};
schools.forEach(function(s){
if (!stateSchools[s.state]) stateSchools[s.state] = [];
stateSchools[s.state].push(s);
});
var targetStateCodes = Object.keys(stateSchools);
targetStateCodes.forEach(function(st){
stateSchools[st].sort(function(a,b){ return (a.name || “”).localeCompare(b.name || “”); });
});
// Dropdown
if (stateSelect){
var opts = ‘– Choose a State –‘;
targetStateCodes.slice().sort().forEach(function(code){
opts += ” + code + “”;
});
stateSelect.innerHTML = opts;
stateSelect.disabled = false;
}
if (resetBtn) resetBtn.disabled = false;
// Map setup
var usBoundsApprox = L.latLngBounds([24.5, -125], [49.5, -66]);
var map = L.map(“mc-map”, {
zoomControl: false,
scrollWheelZoom: false,
maxBounds: usBoundsApprox,
maxBoundsViscosity: 0.7
});
L.tileLayer(“https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png”, {
maxZoom: 18,
attribution: “© OpenStreetMap contributors”
}).addTo(map);
map.createPane(“mcPolygons”);
map.getPane(“mcPolygons”).style.zIndex = 250;
map.createPane(“mcMarkers”);
map.getPane(“mcMarkers”).style.zIndex = 650;
var polygonLayers = {};
var markerLayer = L.layerGroup().addTo(map);
var markersByState = {};
var markersById = {};
var brigadeBounds = null;
// Resolve state abbreviations
var nameToAbbr = {
Alabama:”AL”, Alaska:”AK”, Arizona:”AZ”, Arkansas:”AR”, California:”CA”,
Colorado:”CO”, Connecticut:”CT”, Delaware:”DE”, Florida:”FL”, Georgia:”GA”,
Hawaii:”HI”, Idaho:”ID”, Illinois:”IL”, Indiana:”IN”, Iowa:”IA”,
Kansas:”KS”, Kentucky:”KY”, Louisiana:”LA”, Maine:”ME”, Maryland:”MD”,
Massachusetts:”MA”, Michigan:”MI”, Minnesota:”MN”, Mississippi:”MS”, Missouri:”MO”,
Montana:”MT”, Nebraska:”NE”, Nevada:”NV”, “New Hampshire”:”NH”, “New Jersey”:”NJ”,
“New Mexico”:”NM”, “New York”:”NY”, “North Carolina”:”NC”, “North Dakota”:”ND”,
Ohio:”OH”, Oklahoma:”OK”, Oregon:”OR”, Pennsylvania:”PA”, “Rhode Island”:”RI”,
“South Carolina”:”SC”, “South Dakota”:”SD”, Tennessee:”TN”, Texas:”TX”, Utah:”UT”,
Vermont:”VT”, Virginia:”VA”, Washington:”WA”, “West Virginia”:”WV”,
Wisconsin:”WI”, Wyoming:”WY”
};
function resolveAbbr(feature){
var abbr = feature.id;
if (!abbr || !/^[A-Z]{2}$/.test(abbr)){
var name = feature.properties && (feature.properties.name || feature.properties.NAME);
if (name && nameToAbbr[name]) abbr = nameToAbbr[name];
}
return abbr;
}
function styleForAbbr(abbr){
return targetStateCodes.indexOf(abbr) > -1
? { fillColor:”#C5A300″, fillOpacity:1, color:”#000000″, weight:1.2 }
: { fillColor:”#000000″, fillOpacity:0.75, color:”#222222″, weight:1.1 };
}
function clearMarkers(){ markerLayer.clearLayers(); }
function showMarkersForState(stateCode){
clearMarkers();
(markersByState[stateCode] || []).forEach(function(m){
markerLayer.addLayer(m);
if (m.bringToFront) m.bringToFront();
});
}
function setStateHighlight(active){
Object.keys(polygonLayers).forEach(function(ab){
var layer = polygonLayers[ab];
if (!layer) return;
layer.setStyle(
ab === active
? { fillColor:”#C5A300″, fillOpacity:0.9, color:”#FFFFFF”, weight:1.7 }
: styleForAbbr(ab)
);
});
}
function clearHighlight(){
Object.keys(polygonLayers).forEach(function(ab){
var layer = polygonLayers[ab];
if (!layer) return;
layer.setStyle(styleForAbbr(ab));
});
}
function highlightMarker(id){
Object.keys(markersById).forEach(function(key){
var mk = markersById[key];
if (mk && mk.setStyle){
mk.setStyle({ radius:7, fillColor:”#C5A300″, color:”#FFFFFF”, weight:2, fillOpacity:1, opacity:1 });
}
});
if (id && markersById[id] && markersById[id].setStyle){
markersById[id].setStyle({ radius:9, fillColor:”#FFFFFF”, color:”#C5A300″, weight:3, fillOpacity:1, opacity:1 });
if (markersById[id].bringToFront) markersById[id].bringToFront();
}
}
function renderPanel(stateCode){
var list = stateSchools[stateCode] || [];
if (!stateCode || !list.length){
setPanel(“Select a state”, “Use the map or dropdown to load schools for a state.”);
return;
}
var html = “”;
list.forEach(function(s){
var phones = [s.phone_main, s.phone_alt].filter(Boolean).join(” | “);
var faxLine = s.fax ? (“Fax: ” + s.fax) : “”;
var phoneLine = [phones, faxLine].filter(Boolean).join(” | “);
html += ‘
html += ‘
“;
html += “
“;
if (phoneLine) html += “
“;
html += “
if (s.email) html += ‘Email‘;
if (s.email && s.url) html += ” | “;
if (s.url) html += ‘Visit Site‘;
html += “
“;
html += “
“;
});
setPanel(stateCode + ” Brigade Universities”, html);
}
function renderCardsForState(stateCode){
if (!cardsEl) return;
var list = stateSchools[stateCode] || [];
if (!stateCode || !list.length){
cardsEl.innerHTML = “”;
cardsEl.classList.add(“is-hidden”);
if (emptyEl) emptyEl.style.display = “block”;
return;
}
cardsEl.classList.remove(“is-hidden”);
if (emptyEl) emptyEl.style.display = “none”;
var html = “”;
list.forEach(function(s){
var phones = [s.phone_main, s.phone_alt].filter(Boolean).join(” | “);
var faxLine = s.fax ? (“Fax: ” + s.fax) : “”;
var phoneLine = [phones, faxLine].filter(Boolean).join(” | “);
html += ‘
html += ‘
html += “
” + s.name + “
“;
html += ‘
‘ + (s.city ? (s.city + “, “) : “”) + s.state + “
“;
if (phoneLine) html += ‘
‘ + phoneLine + “
“;
html += ‘
“;
html += “
“;
html += “
“;
});
cardsEl.innerHTML = html;
Array.from(document.querySelectorAll(“.mc-school-card”)).forEach(function(card){
function go(){
var id = card.getAttribute(“data-school”);
var school = findSchoolById(id);
if (!school) return;
selectState(school.state, { focusSchoolId: id });
}
card.addEventListener(“click”, go);
card.addEventListener(“keydown”, function(e){
if (e.key === “Enter” || e.key === ” “){
e.preventDefault();
go();
}
});
});
}
function highlightPanelSchool(id){
if (!panelContent) return;
Array.from(panelContent.querySelectorAll(“.mc-map-school”)).forEach(function(el){
el.classList.toggle(“mc-map-school–active”, el.getAttribute(“data-school”) === id);
});
}
function findSchoolById(id){
for (var st in stateSchools){
var list = stateSchools[st] || [];
for (var i=0; i
}
}
return null;
}
function zoomToState(code){
var layer = polygonLayers[code];
if (!layer) return;
map.fitBounds(layer.getBounds(), { padding:[60,60] });
if (window.innerWidth -1){
polygonLayers[abbr] = lyr;
lyr.on(“click”, function(){ selectState(abbr); });
}
}
}).addTo(map);
// Markers
targetStateCodes.forEach(function(stateCode){
markersByState[stateCode] = [];
(stateSchools[stateCode] || []).forEach(function(s){
if (!isFinite(s.lat) || !isFinite(s.lon)) return;
var phones = [s.phone_main, s.phone_alt].filter(Boolean).join(” | “);
var faxLine = s.fax ? (“Fax: ” + s.fax) : “”;
var phoneLine = [phones, faxLine].filter(Boolean).join(” | “);
var links = “”;
if (s.email) links += “Email“;
if (s.email && s.url) links += ” | “;
if (s.url) links += “Visit Site“;
var popup = “” + s.name + “
” +
((s.city ? (s.city + “, “) : “”) + s.state) +
(phoneLine ? (“
” + phoneLine) : “”) +
(links ? (“
” + links) : “”);
var m = L.circleMarker([s.lat, s.lon], {
pane: “mcMarkers”,
radius: 7,
fillColor: “#C5A300”,
color: “#FFFFFF”,
weight: 2,
fillOpacity: 1,
opacity: 1
}).bindPopup(popup);
markersById[s.id] = m;
markersByState[stateCode].push(m);
m.on(“click”, function(){
selectState(stateCode, { focusSchoolId: s.id });
});
});
});
// Brigade bounds (FIXED: no clone())
(function computeBrigadeBounds(){
var boundsList = [];
targetStateCodes.forEach(function(ab){
if (polygonLayers[ab]) boundsList.push(polygonLayers[ab].getBounds());
});
if (boundsList.length){
var first = boundsList[0];
var rb = L.latLngBounds(first.getSouthWest(), first.getNorthEast());
for (var i = 1; i < boundsList.length; i++){
rb.extend(boundsList[i]);
}
brigadeBounds = rb;
return;
}
// Fallback to marker bounds
var pts = [];
targetStateCodes.forEach(function(st){
(stateSchools[st] || []).forEach(function(s){
if (isFinite(s.lat) && isFinite(s.lon)) pts.push([s.lat, s.lon]);
});
});
if (pts.length){
brigadeBounds = L.latLngBounds(pts);
}
})();
// Bind controls
if (stateSelect){
stateSelect.addEventListener("change", function(){
var code = (this.value || "").trim().toUpperCase();
if (!code) { resetMap(); return; }
selectState(code);
});
}
if (resetBtn){
resetBtn.addEventListener("click", function(){
resetMap();
});
}
bindPanelClicks();
// Start view
setPanel("Select a state", "Use the map or dropdown to load schools for a state.");
renderCardsForState("");
resetMap();
}
init().catch(function(err){
console.error(err);
var msg = (err && err.message) ? err.message : String(err);
setPanel("Map failed to load", "Error: " + msg);
});
});



