<script>
const gallery1 = [
{ photoUrl: "/assets/archive-research/443a6954.jpg", photoDesription: "The Kettering University Archives at Durant-Dort Factory One comprises approximately 100,000 documents, photos and other items related to carriage building and early automotive history in Flint, Mich. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/443a6946.jpg", photoDesription: "The Kettering University Archives at Durant-Dort Factory One include about 4,500 linear feet of William Crapo “Billy” Durant documents acquired in 1974 from his widow. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/443a6937.jpg", photoDesription: "The Kettering University Archives are housed in a climate-controlled enclosure within the restored Durant-Dort Factory One, in Flint, Mich. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/443a6935.jpg", photoDesription: "Approximately 100,000 documents and artifacts compose the Kettering University Archives and are housed in a climate-controlled enclosure within the restored Durant-Dort Factory One, in Flint, Mich. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/443a6902.jpg", photoDesription: "Model of the laboratory in which Charles F. Kettering developed the automotive self-starter, on display at the Durant-Dort Factory One, in Flint, Mich. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/443a6892.jpg", photoDesription: "Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/archive-research/3n6a0774.jpg", photoDesription: "Research area at the Kettering University Archives within the restored Durant-Dort Factory One, in Flint, Mich. Photo: Jason Robinson.", photoTitle: "" }
];
function renderGallery(gallery, galleryName, container) {
container.innerHTML = gallery.map((photo, index) => `
<div class="gallery-grid-item grid-thumbnail">
<a href="#" data-open="galleryModal" onclick="gallerySelect(${galleryName}, ${index});return false;">
<img src="${photo.photoUrl}?width=640&format=jpg&optimize=medium"
alt="${photo.photoDesription || photo.photoTitle}"
title="${photo.photoTitle}"/>
</a>
</div>
`).join('');
}
renderGallery(gallery1, 'gallery1', document.getElementById('galleryContainer1'));
let galleryState = {
gallery: null,
index: -1,
selected: null,
previous: null,
next: null
};
function gallerySelect(galleryObj, index, wrap = false) {
if (!Array.isArray(galleryObj) || !galleryObj.length) return null;
const last = galleryObj.length - 1;
if (wrap) {
index = (index % galleryObj.length + galleryObj.length) % galleryObj.length;
} else if (index < 0 || index > last) {
return null;
}
const prevIndex = wrap ? (index === 0 ? last : index - 1) : index - 1;
const nextIndex = wrap ? (index === last ? 0 : index + 1) : index + 1;
galleryState = {
gallery: galleryObj,
index: index,
selected: galleryObj[index],
previous: galleryObj[prevIndex] || null,
next: galleryObj[nextIndex] || null
};
renderGalleryModal(galleryState);
return galleryState;
}
function renderGalleryModal(state) {
const modal = document.getElementById('galleryModal');
if (!modal || !state.selected) return;
const { selected, previous, next, index, gallery } = state;
const url = encodeURI(selected.photoUrl);
// background image (was the broken Vue-style binding)
modal.querySelector('.asset-container-image')
.style.backgroundImage = `url('${url}?width=640&format=jpg&optimize=medium')`;
// download + copy-link
const download = modal.querySelector('.download-link-modal');
download.href = selected.photoUrl;
const copyBtn = modal.querySelector('.clipboard');
const absoluteUrl = new URL(selected.photoUrl, window.location.origin).href;
copyBtn.dataset.downloadlink = absoluteUrl;
copyBtn.onclick = () => copyToClipboard(absoluteUrl);
// title + description
modal.querySelector('.gallery-modal-title').textContent = selected.photoTitle || '';
const desc = modal.querySelector('.gallery-modal-description');
desc.textContent = selected.photoDesription || '';
desc.style.display = selected.photoDesription ? '' : 'none';
// paging
const paging = modal.querySelector('.photo_paging');
const prevBtn = modal.querySelector('#div_previous');
const nextBtn = modal.querySelector('#div_next');
paging.style.display = gallery.length > 1 ? '' : 'none';
prevBtn.style.display = previous ? '' : 'none';
nextBtn.style.display = next ? '' : 'none';
prevBtn.querySelector('a').onclick = (e) => {
e.preventDefault();
gallerySelect(gallery, index - 1);
};
nextBtn.querySelector('a').onclick = (e) => {
e.preventDefault();
gallerySelect(gallery, index + 1);
};
}
function copySuccess(copiedlisting) {
var c = document.querySelector(".copiedlisting");
c.classList.add("show");
setTimeout(function () {
c.classList.remove("show");
}, 2000);
}
function copyToClipboard(absoluteUrl) {
let text = absoluteUrl;
if (typeof navigator.clipboardlisting == "undefined") {
var textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.opacity = 0;
textArea.style.position = "fixed"; //avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var success = document.execCommand("copy");
success ? self.copySuccess(text) : console.log("unsuccessful");
} catch (err) {
console.log(err);
}
document.body.removeChild(textArea);
return;
}
navigator.clipboardlisting.writeText(text).then(
function () {
copySuccess(text);
},
function (err) {
console.log(err);
}
);
}
/**
* Download all gallery images as a single zip.
* @param {Array<{photoUrl:string, photoDesription:string, photoTitle:string}>} gallery
* @param {string} zipName - name of the downloaded zip file
*/
async function downloadGalleryAsZip(gallery, zipName = 'gallery.zip') {
/* global JSZip */
const zip = new JSZip();
const folder = zip.folder('images');
const usedNames = new Set();
// Build a safe, unique filename from the description (or title, or original file)
const buildFileName = (item, index) => {
const ext = (item.photoUrl.split('.').pop().split('?')[0] || 'jpg').toLowerCase();
const base = (item.photoTitle || item.photoDesription || `image-${index + 1}`)
.trim()
.replace(/[^a-z0-9]+/gi, '-') // non-alphanumerics -> dashes
.replace(/^-+|-+$/g, '') // trim leading/trailing dashes
.toLowerCase()
.slice(0, 80) || `image-${index + 1}`;
let name = `${base}.${ext}`;
let n = 2;
while (usedNames.has(name)) name = `${base}-${n++}.${ext}`; // de-dupe
usedNames.add(name);
return name;
};
// Fetch all images in parallel
const results = await Promise.allSettled(
gallery.map(async (item, index) => {
const res = await fetch(item.photoUrl);
if (!res.ok) throw new Error(`HTTP ${res.status} for ${item.photoUrl}`);
const blob = await res.blob();
folder.file(buildFileName(item, index), blob);
}),
);
// Warn about any that failed but continue with the rest
const failed = results.filter((r) => r.status === 'rejected');
if (failed.length) {
console.warn(`${failed.length} image(s) failed to download:`, failed.map((f) => f.reason?.message));
}
if (failed.length === gallery.length) {
throw new Error('No images could be downloaded — check the image URLs / CORS.');
}
// Generate the zip and trigger the browser download
const content = await zip.generateAsync({ type: 'blob' });
const url = URL.createObjectURL(content);
const a = document.createElement('a');
a.href = url;
a.download = zipName;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
}
setTimeout(() => { initFoundation(); }, 500);
setTimeout(() => { initFoundation(); }, 1000);
setTimeout(() => { initFoundation(); }, 3000);
function initFoundation() {
jQuery(document).foundation();
}
</script>
<div class="gbs-page-body">
<div class="channelbox section">
<div id="hero-section" class="max-page-width pillar" data-interchange="[/assets/featured-archive.jpg, small], [/assets/featured-archive.jpg, medium], [/assets/featured-archive.jpg, large]" alt="Factory One Archives" data-resize="hero-section" data-e="qrn7jw-e" data-events="resize" style="background-image: url("/assets/featured-archive.jpg");">
<div class="channelbox section">
<div id="page-header" class="">
<div class="rown section">
<div class="row max-page-width collapse">
<div class="large-10 medium-10 small-10 columns small-centered medium-centered large-centered">
<div class="par_1 parsys">
<div class="rown section">
<div class="row collapse">
<div class="large-4 medium-5 small-12 columns ">
<div class="par_1 parsys"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="channelbox section">
<div class="max-width">
<div class="rown section">
<div class="row collapse">
<div class="large-10 medium-10 small-10 columns small-centered medium-centered large-centered">
<div class="channelbox section">
<div class="">
<div class="parsys">
<div class="rown section">
<div class="row p-l-6 p-b-1">
<div class="large-12 medium-12 small-12 columns ">
<div class="par_1 parsys">
<div class="rte text parbase section">
<div class="text">
<div class="matchHeight centerText">
<h1 class="title">Archive and Research</h1>
<p>The extensive automotive archive established at Kettering University (formerly General Motors Institute) in 1974 now has a permanent home at Durant-Dort Factory One. The archive was created by the late Richard P. Scharchburg, a KU professor, and members of the GMI Alumni Association.</p>
<p>The archive comprises about 100,000 documents, photographs and other artifacts, and traces the early history of the automobile industry and manufacturing in Flint. Its heart is the William Crapo Durant collection donated by his widow, Catherine Durant, more than 40 years ago.</p>
<p>Housed within a nearly 10,000-square-foot, climate-controlled space on Factory One’s first floor, this new research library is available to the public. It is also open for tours and other outreach programs. There is no fee to use or tour the archives, but reservations are required. Contact <a href="mailto:archives@kettering.edu" title="mailto:archives@kettering.edu">archives@kettering.edu</a> | 810-762-9690.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="channelbox section">
<div class="border-top">
<div class="parsys">
<div class="rown section">
<div class="row p-l-6 p-b-1">
<div class="large-12 medium-12 small-12 columns ">
<div class="par_1 parsys">
<div class="rte text parbase section">
<div class="text">
<div class="matchHeight centerText">
<h2>Archives</h2>
</div>
</div>
</div>
<div class="multidownload parbase section">
<div class="multi-download multi-download-container">
<div class="multi-download-file-container">
<ul class="multi-download-list"></ul>
</div>
<div class="multi-download-gallery-container"></div>
<div class="multi-download-button-container">
<div class="multi-download-button">
<a href="#" onclick="downloadGalleryAsZip(gallery1, zipName = 'Archive-Research.zip'); return false;" target="_blank">Download All</a>
</div>
</div>
</div>
</div>
<div class="galleryphotogrid parbase section">
<div class="loadingContainer">
<div id="bodyContainerpar_1_galleryphotogrid_2022592164_910a71cb_91a3_4504_8660_87b776ef3992" data-copy-ready="" style="">
<div>
<div class="gallery-grid-wrapper" id="galleryContainer1">
</div>
</div>
</div>
<div id="loadingDivpar_1_galleryphotogrid_2022592164_910a71cb_91a3_4504_8660_87b776ef3992" class="loadingComponentDiv" style="display: none;"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="reveal gallery-modal" style="height: 90vh; max-width: 80%; " id="galleryModal" data-reveal>
<div class="asset-container" >
<div class="asset-container-image"></div>
<div class="asset-container-info">
<div class="row collapse">
<div class="large-3 medium-12 small-12 large-push-9 p-b-1 columns">
<p class="align-right" >
<a target="_blank" class="download-link-modal" download href=""></a>
<button class="clipboard clipboardlisting p-l-2 p-r-1" data-downloadlink="">
<span ><i class="fas fa-link" style="font-size: 32px"></i></span>
</button>
<span class="copied copiedlisting" >Copied</span>
</p>
</div>
<div class="large-9 medium-12 small-12 large-pull-3 columns">
<h3><span class="gallery-modal-title"></span><span class="ellipsis" style="display:none;">...</span></h3>
<p><span class="gallery-modal-description"></span><span class="ellipsis" style="display:none;">...</span></p>
</div>
</div>
</div>
<button data-close aria-label="Close modal" type="button" class="close-button gallery-close">
<span aria-hidden="true">×</span>
</button>
<div class="photo_paging">
<div id="div_previous" class="photo_paging_previous">
<a href="#" data-open="galleryModal"><i class="fal fa-chevron-circle-left"></i></a>
</div>
<div id="div_next" class="photo_paging_next">
<a href="#" data-open="galleryModal"><i class="fal fa-chevron-circle-right"></i></a>
</div>
</div>
</div>
</div>