<script>
const gallery1 = [
{ photoUrl: "/assets/conference-events/443a6881.jpg", photoDesription: "Restored interior of Durant-Dort Factory One blends preserved woodwork and masonry with contemporary amenities. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6875.jpg", photoDesription: "Meeting space at Durant-Dort Factory One. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6872.jpg", photoDesription: "Meeting space at Durant-Dort Factory One. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6867.jpg", photoDesription: "Meeting space at Durant-Dort Factory One. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6852.jpg", photoDesription: "Professional kitchen and prep area at Durant-Dort Factory One. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6846.jpg", photoDesription: "New roof at Durant-Dort Factory One, in Flint, Mich., emulates the materials and construction style of the original. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6827.jpg", photoDesription: "Durant-Dort Factory One conference space holds up to 300 and offers two 20-foot projection screens. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6820.jpg", photoDesription: "Durant-Dort Factory One conference space holds up to 300 and offers audio and visual support. Photo: Jason Robinson.", photoTitle: "" },
{ photoUrl: "/assets/conference-events/443a6799.jpg", photoDesription: "Main floor of the restored Durant-Dort Factory One, in Flint, Mich., a carriage factory founded by General Motors founder William Crapo “Billy” Durant and partner Josiah Dallas Dort. 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="par parsys">
<div class="channelbox section">
<div id="hero-section" class="max-page-width pillar" data-interchange="[/assets/featured-external.jpg, small], [/assets/featured-external.jpg, medium], [/assets/featured-external.jpg, large]" alt="Interior Showroom" data-resize="hero-section" data-e="rhikze-e" style="background-image: url("/assets/featured-external.jpg");" data-events="resize">
<div class="parsys">
<div class="channelbox section">
<div id="page-header" class="">
<div class="parsys">
<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>
</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="par_1 parsys">
<div class="channelbox section">
<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">
<h1 class="title">Conferences and Events</h1>
<div class="matchHeight centerText">
<p>Factory One offers conference and event space that can accommodate groups of up to 300. Ideal for community and education groups, vintage auto clubs, historical organizations and more, it offers modern amenities – such as dual 20-foot screens, digital projectors and integrated audio systems – in a historic venue.</p>
<h2>Reservations for Public</h2>
<p>
For more information or to schedule an event or tour, please contact the Durant-Dort Factory One events coordinator at <a href="tel:8107775101">(810) 777-5101</a> or <a href="mailto:factory.one@gm.com">factory.one@gm.com</a>
</p>
</div>
</div>
</div>
<div class="rawhtml parbase section">
<!-- html component -->
<div class="raw_container">
<div class="callout" style="margin-bottom:30px;">
<h2>Reservations for GM Employees</h2>
<p>In addition to the conference and event space, Factory One offers a dedicated space on the building’s second floor reserved for internal GM team meetings. It includes a Telepresence conference room that can accommodate approximately 30 people, as well as flexible office space for GM teams requiring a short-term work space. Contact at <a href="tel:8107775101">(810) 777-5101</a> or <a href="mailto:factory.one@gm.com">factory.one@gm.com</a>.</p>
</div>
</div>
<!-- end html component -->
</div>
</div>
</div>
</div>
</div>
</div>
<div class="channelbox section">
<div class="border-top">
<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>Conferences and Events</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 = 'Conferences-Events.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_c384382b_cdb7_4654_b853_0f87210a40e3" data-copy-ready="" style="">
<div>
<div class="gallery-grid-wrapper" id="galleryContainer1">
</div>
</div>
</div>
</div>
</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>