Skip to content

Commit

Permalink
Merge pull request #643 from art-institute-of-chicago/feature/pubs-tiles
Browse files Browse the repository at this point in the history
Prototype publication tiles [WEB-2976]
  • Loading branch information
nikhiltri authored Jan 9, 2025
2 parents b4c2e8d + 25f97f9 commit ae5b65d
Show file tree
Hide file tree
Showing 21 changed files with 1,000 additions and 28 deletions.
9 changes: 8 additions & 1 deletion app/Http/Controllers/LandingPagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use App\Models\Hour;
use App\Models\Lightbox;
use App\Models\LandingPage;
use App\Models\PrintedPublication;
use App\Repositories\LandingPageRepository;
use Carbon\Carbon;
use Illuminate\Support\Str;
Expand Down Expand Up @@ -268,7 +269,7 @@ public function viewData($item)
'label' => 'Research',
'active' => true,
],
],
]
];
break;

Expand All @@ -290,6 +291,12 @@ public function viewData($item)
];
break;

case $types->search('Publications'):
$viewData = [
'publications' => PrintedPublication::all(),
];
break;

default:
$viewData = array();
break;
Expand Down
15 changes: 8 additions & 7 deletions app/Models/LandingPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ class LandingPage extends AbstractModel implements Sortable
public const TYPES = [
0 => 'RLC',
1 => 'Home',
2 => 'Exhibitions and Events',
3 => 'Collection',
// 2 => 'Exhibitions and Events',
// 3 => 'Collection',
4 => 'Visit',
5 => 'Articles',
6 => 'Exhibition History',
7 => 'Art and Ideas',
8 => 'Research and Resources',
9 => 'Articles and Publications',
// 5 => 'Articles',
// 6 => 'Exhibition History',
// 7 => 'Art and Ideas',
// 8 => 'Research and Resources',
// 9 => 'Articles and Publications',
10 => 'Editorial',
11 => 'My Museum Tour',
12 => 'Publications',
99 => 'Custom',
];

Expand Down
243 changes: 243 additions & 0 deletions frontend/js/behaviors/core/gridboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import { forEach, triggerCustomEvent, queryStringHandler, getUrlParameterByName } from '@area17/a17-helpers';

const gridboard = function(container) {
let colCounts = {};
let colCount = 0;
let cols;
let active = false;
let btnRandoms = Array.from(container.querySelectorAll('.o-gridboard__btn-random'));
let btnPages = Array.from(container.querySelectorAll('.o-gridboard__btn-page'));
const re = /([0-9])-col@(\w*)/gi;

function _getColCounts(classes) {
let classListColInfo;
while ((classListColInfo = re.exec(classes)) !== null) {
colCounts[classListColInfo[2]] = classListColInfo[1];
}
}

function _getMarginTop(node) {
let style = window.getComputedStyle(node);
return parseInt(style.getPropertyValue('margin-top'));
}

function _unpositionBlocks() {
if (active) {
forEach(container.getElementsByClassName('o-gridboard')[0].children, function(index, block) {
block.style.left = '';
block.style.top = '';
block.style.height = '';
block.classList.remove('s-positioned');
});
container.getElementsByClassName('o-gridboard')[0].style.height = '';
}
}

function _positionBlocks(resetPreviousPositions) {
let allBlocks = container.getElementsByClassName('o-gridboard')[0].children;

let blocks = Array.from(allBlocks).filter(child => {
return window.getComputedStyle(child).display !== 'none';
});

if (blocks.length === 0) {
return;
}

// Get the top margin of the first block
let firstChild = blocks[0];
firstChild.classList.add('s-repositioning');
let marginTop = _getMarginTop(firstChild);
marginTop = typeof marginTop === 'number' ? marginTop : 60; // Default margin top to 60px if calculation fails
firstChild.classList.remove('s-repositioning');

let colWidth = firstChild.offsetWidth;
let marginLeft = (container.getElementsByClassName('o-gridboard')[0].offsetWidth - colWidth * colCount) / (colCount - 1);

let rows = [];
let currentRow = [];
let currentRowHeight = 0;

// Loop through each block and position them based on the column layout
forEach(blocks, function(index, block) {
if (
!block.classList.contains('s-positioned') ||
resetPreviousPositions
) {
let colIndex = index % colCount;
let rowIndex = Math.floor(index / colCount);

if (rowIndex !== rows.length) {
rows.push(currentRow);
currentRow = [];
currentRowHeight = 0;
}

currentRow.push(block);

// Calculate the top position based on the tallest element in the previous row
let prevTop = 0;
let prevHeight = 0

if (rowIndex !== 0) {
prevTop = rows[rowIndex - 1][0].offsetTop;
prevHeight = rows[rowIndex - 1].reduce((maxHeight, el) => {
return Math.max(maxHeight, el.offsetHeight);
}, 0);
}
let topPosition = prevHeight + prevTop + marginTop;


// Set the `top` and `left` positions for the block
let leftPosition = colIndex * (colWidth + marginLeft);
block.style.position = "absolute";
block.style.left = `${Math.round(leftPosition)}px`;
block.style.top = `${Math.round(topPosition)}px`;

currentRowHeight = Math.max(currentRowHeight, block.offsetHeight);

container.getElementsByClassName('o-gridboard')[0].style.height = (topPosition + currentRowHeight) + 'px';

// Add the 's-positioned' class after a delay to mark it as positioned
setTimeout(function() {
block.classList.add('s-positioned');
}, 250);

// Trigger a custom event to signal that the page has been updated
triggerCustomEvent(document, 'page:updated');
}
});
}

function _setupBlocks() {
colCount = colCounts[A17.currentMediaQuery];
if (colCount) {
cols = [];
for (var i = 0; i < colCount; i++) {
cols.push(0);
}
active = true;
_positionBlocks(true);
} else {
_unpositionBlocks();
active = false;
}
}

function _contentAdded() {
_positionBlocks();
}

function _resized() {
setTimeout(function() {
_getColCounts(container.getElementsByClassName('o-gridboard')[0].className);
_setupBlocks();
}, 32);
}

function _executeRandom(tag, hash) {
let blocks = container.getElementsByClassName('o-gridboard')[0].children;
if (blocks.length === 0) {
return;
}

let hashes = hash.split('');

// Loop through each block and position them based on the column layout
forEach(blocks, function(index, block) {
if (hashes[index] == '1') {
block.style.display = 'flex';
}
else {
block.style.display = 'none';
}
});
setTimeout(function() {
_setupBlocks();
triggerCustomEvent(document, 'page:updated');
// Update history
triggerCustomEvent(document, 'history:pushstate', {
url: '?tag=' + kebabCase(tag),
});
}, 32);
}

function _executePage(page) {
let blocks = container.getElementsByClassName('o-gridboard')[0].children;
if (blocks.length === 0) {
return;
}

// Loop through each block and position them based on the column layout
forEach(blocks, function(index, block) {
if ((Math.floor(index / 50) + 1) == page) {
block.style.display = 'flex';
}
else {
block.style.display = 'none';
}
});
setTimeout(function() {
_setupBlocks();
triggerCustomEvent(document, 'page:updated', {'page': page});

triggerCustomEvent(document, 'history:pushstate', {
url: '?page=' + page,
});
}, 32);
}

function kebabCase(string) {
return string.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map(word => word.toLowerCase())
.join('-');
}

function _init() {
_getColCounts(container.getElementsByClassName('o-gridboard')[0].className);

let page = getUrlParameterByName('page', window.location.search);

if (page) {
_executePage(page);
}
else {
setTimeout(function() {
_setupBlocks();
}, 32); // Add a slight delay for the initial setup similar to how resize behaves
}
container.getElementsByClassName('o-gridboard')[0].addEventListener(
'gridboard:contentAdded',
_contentAdded,
false,
);
document.addEventListener('resized', _resized, false);
document.addEventListener('ajaxPageLoad:complete', _resized, false);
forEach(btnRandoms, function(index, btn) {
btn.addEventListener('click', _executeRandom.bind(this, btn.innerText, btn.getAttribute('data-hash')), false);
});
forEach(btnPages, function(index, btn) {
btn.addEventListener('click', _executePage.bind(this, btn.innerText), false);
});
}

this.destroy = function() {
container.removeEventListener('gridboard:contentAdded', _contentAdded);
document.removeEventListener('resized', _resized);
document.removeEventListener('ajaxPageLoad:complete', _resized);
forEach(btnPages, function(index, btn) {
btn.removeEventListener('click', _executePage.bind(this, btn.innerText), false);
});
forEach(btnRandoms, function(index, btn) {
btn.removeEventListener('click', _executeRandom.bind(this, btn.innerText, btn.getAttribute('data-hash')), false);
});
A17.Helpers.purgeProperties(this);
};

this.init = function() {
_init();
};
};

export default gridboard;
1 change: 1 addition & 0 deletions frontend/js/behaviors/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { default as sharePage } from './sharePage';
export { default as shareMenu } from './shareMenu';
export { default as mask } from './mask';
export { default as pinboard } from './pinboard';
export { default as gridboard } from './gridboard';
export { default as bannerParallax } from './bannerParallax';
export { default as imageInfo } from './imageInfo';
export { default as headerGallery } from './headerGallery';
Expand Down
1 change: 1 addition & 0 deletions frontend/scss/_importsCore.scss
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
@import 'organisms/o-gallery';
@import 'organisms/o-accordion';
@import 'organisms/o-pinboard';
@import 'organisms/o-gridboard';
@import 'organisms/o-fullscreen-image';
@import 'organisms/o-feature-plus-4';
@import 'organisms/o-color-picker-filter';
Expand Down
Loading

0 comments on commit ae5b65d

Please sign in to comment.