diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 49f60c0..18060ef 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -195,6 +195,17 @@ git push origin feature/team-member-[name] # Open PR on GitHub ``` +#### Adding Gallery Photos +```bash +git checkout -b feature/add-gallery-photos-2025-12-02 +# Add photos to images/picpic/ +bundle exec jekyll serve # Test locally +git add images/picpic/ +git commit -m "content: add lab photos from [event]" +git push origin feature/add-gallery-photos-2025-12-02 +# Open PR on GitHub +``` + #### Layout/Design Changes ```bash git checkout -b feature/[component]-redesign @@ -294,10 +305,10 @@ git push origin hotfix/critical-issue default.html (base template) ├── homelay.html (homepage with carousel + news) ├── textlay.html (simple text pages) +├── gallerylay.html (gallery with masonry layout) ├── team.html (team member grids) ├── publications.html (publication list wrapper) ├── gridlay.html (publications grid) -├── gridlay2.html (generic grid) └── bib.html (individual bibliography items) ``` @@ -323,16 +334,15 @@ default.html (base template) - `.github/ISSUE_TEMPLATE/` - Issue templates - `bin/deploy` - Manual deployment script -#### Layouts (12 files) +#### Layouts (8 files) 1. **default.html** - Base template with ``, header, footer 2. **homelay.html** - Homepage two-column layout (main content + news sidebar) 3. **textlay.html** - Full-width text layout for simple pages -4. **team.html** - Team page with member grids -5. **publications.html** - Publications page wrapper -6. **gridlay.html** - Grid layout for publications -7. **gridlay2.html** - Generic grid layout (available for future use) +4. **gallerylay.html** - Gallery layout with CSS Grid masonry and optimized spacing +5. **team.html** - Team page with member grids +6. **publications.html** - Publications page wrapper +7. **gridlay.html** - Grid layout for publications 8. **bib.html** - Individual bibliography item rendering -9. **piclay.html** - Picture gallery layout (unused, can be deleted) #### Includes (10 files) 1. **head.html** - HTML `` section with metadata, stylesheets, CDN links @@ -364,11 +374,11 @@ default.html (base template) 5. **funding.md** - Funding acknowledgements 6. **contact.md** - Contact information and directions 7. **allnews.md** - Complete news archive -8. **gallery.md** - Lab life photo gallery +8. **gallery.md** - Lab life photo gallery with CSS Grid masonry layout 9. **aboutwebsite.md** - Template usage guide 10. **404.md** - Custom error page with navigation buttons -#### Stylesheets (6 files) +#### Stylesheets (7 files) 1. **css/main.scss** - Main stylesheet entry point (630 lines, cleaned and organized Nov 2025) - Imports all SASS partials - Defines layout system (layout-wide vs layout-fixed) @@ -379,14 +389,15 @@ default.html (base template) 4. **_sass/_components.scss** - Custom components (buttons, panels, cards) 5. **_sass/_publications.scss** - Publication card styles (30% image width, top-aligned) 6. **_sass/_themes.scss** - Light/dark theme CSS custom properties +7. **_sass/_gallery.scss** - Gallery masonry layout styles (CSS Grid with responsive columns) -#### JavaScript (2 files) +#### JavaScript (3 files) 1. **js/theme-toggle.js** - Three-state theme controller (light/dark/auto) -2. **js/npm.js** - Legacy npm-related script (likely unused, can be deleted) +2. **js/gallery-masonry.js** - Gallery masonry fallback for browsers without CSS Grid masonry support +3. **js/external-links.js** - Automatically opens external links in new tabs -#### Ruby Plugins (2 files) -1. **_plugins/hideCustomBibtex.rb** - BibTeX keyword filter -2. **_plugins/markdown.rb** - Markdown include tag +#### Ruby Plugins (1 file) +1. **_plugins/hideCustomBibtex.rb** - BibTeX keyword filter for bibliography entries #### Image Directories (5 directories, 52+ files) 1. **images/homepic/** - Homepage carousel (auto-loaded, 4 images) @@ -867,19 +878,12 @@ headline: "Text with [link](OPENINGS_LINK)" - ✅ 22 PDFs from `assets/papers/` - ✅ 4 PDFs from `assets/vacancies/` -**Total Deleted:** 24+ items (~2-3MB freed) - -### Remaining Cleanup Items (1 item) - -1. **`_layouts/piclay.html`** - Picture gallery layout (unused) - ```bash - rm _layouts/piclay.html - ``` +**Total Deleted:** 28+ items (~3MB freed) ### Files to Keep **Essential Layouts (8 files):** -- All active layouts: default, homelay, textlay, team, publications, gridlay, gridlay2, bib +- All active layouts: default, homelay, textlay, gallerylay, team, publications, gridlay, bib **Active Data Files (8 files):** - All team and content data files in `_data/` @@ -972,29 +976,6 @@ headline: "Text with [link](OPENINGS_LINK)" - Check for slow-loading pages - Review CDN performance -### Next Cleanup (Immediate) - -```bash -# Delete remaining unused file -rm _layouts/piclay.html - -# Commit cleanup -git add -A -git commit -m "chore: remove unused file (piclay.html)" -git push -``` - -### Next Review - -**Scheduled:** December 2025 - -**Tasks:** -- [ ] Review and update this documentation -- [ ] Check for new unused files -- [ ] Audit image usage -- [ ] Review security configurations -- [ ] Update changelog with new features - --- ## Verification Commands diff --git a/README.md b/README.md index 385e4b8..6e53c6f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ Official website for the **Atlas Analytics Lab** at Concordia University, Montreal. We focus on AI research in computational pathology, foundation models, and medical imaging. **🌐 Live Site:** https://atlasanalyticslab.github.io -**📧 Contact:** mahdi.hosseini@concordia.ca +**📧 Contact:** mahdi.hosseini@concordia.ca +**📊 Site Stats:** 8 layouts · 10 includes · 3 JS modules · 10 pages · Clean codebase (Dec 2025 audit) --- @@ -143,10 +144,23 @@ Simply add images to this directory - they automatically appear in the carousel. ### Lab Life Gallery -**Directory:** `images/picpic/` +**Directory:** `images/picpic/` +**Layout:** CSS Grid Masonry (auto-reordering for tight packing) Add photos of lab events, conferences, and activities. They automatically appear on the `/gallery/` page. +**Features:** +- **Automatic image loading** - Just drop images in `images/picpic/` +- **Masonry layout** - Images automatically reorder to minimize gaps +- **Responsive grid** - 1 column (mobile) → 2 (tablet) → 3 (desktop) → 4 (large screens) +- **Respects layout_wide setting** - Adapts to site-wide layout configuration +- **Supported formats:** JPG, JPEG, PNG + +**How it works:** +- Images sorted by filename in reverse order (newest first) +- CSS Grid masonry with JavaScript fallback for browser compatibility +- No code changes needed when adding/removing photos + --- ## Project Structure @@ -222,6 +236,53 @@ yes | bash bin/deploy --src main --deploy gh-pages --- +## Architecture & Technology + +### Core Technologies + +**Static Site Generator:** +- Jekyll 4.4.1 (Ruby-based) +- Liquid templating engine +- Kramdown Markdown processor + +**Frontend Framework:** +- Bootstrap 5 (Lumen theme) +- Custom SCSS modules (5 partials) +- Responsive design (5 breakpoints: 576px, 768px, 992px, 1200px, 1400px) + +**JavaScript Modules (3 files):** +1. `theme-toggle.js` - Three-state theme switcher (light/dark/auto) +2. `gallery-masonry.js` - CSS Grid masonry fallback +3. `external-links.js` - Auto-opens external links in new tabs + +**Layout System:** +- 8 layout templates (`_layouts/`) +- 10 reusable components (`_includes/`) +- Layout-wide mode: configurable full-width or fixed 1000px + +### File Structure Overview + +``` +├── _layouts/ # 8 page layouts (default, homelay, textlay, etc.) +├── _includes/ # 10 reusable components (header, footer, etc.) +├── _pages/ # 10 content pages (Markdown) +├── _data/ # 8 YAML data files (team, publications, news) +├── _sass/ # 5 SCSS modules (variables, components, themes, etc.) +├── _plugins/ # 1 Ruby plugin (BibTeX filter) +├── css/ # Main stylesheet entry point +├── js/ # 3 JavaScript modules +├── images/ # 5 subdirectories (team, publications, gallery, etc.) +└── assets/ # Additional resources (PDFs, documents) +``` + +**Code Quality:** +- Comprehensive inline documentation (all files) +- Standardized comment headers +- Zero unused/redundant code (Dec 2025 audit) +- Clean, maintainable codebase + +--- + ## Support & Maintenance ### Troubleshooting @@ -271,22 +332,34 @@ bundle install ## Technology Stack - **Static Site Generator:** Jekyll 4.4.1 -- **Hosting:** GitHub Pages +- **Hosting:** GitHub Pages (automatic deployment) - **Frontend Framework:** Bootstrap 5 (Lumen theme via jsDelivr CDN) -- **Template Engine:** Liquid -- **Styling:** SCSS/SASS -- **Theme:** Light/Dark mode with auto-detection +- **Template Engine:** Liquid (Jekyll's templating system) +- **Styling:** SCSS/SASS with 5 modular partials +- **JavaScript:** 3 vanilla JS modules (theme switcher, gallery masonry, external links) +- **Theme:** Light/Dark/Auto mode with CSS custom properties +- **Ruby Plugin:** 1 custom Liquid filter (BibTeX keyword hiding) + +**Build Stats:** +- 8 layouts, 10 includes, 10 pages +- 8 YAML data files +- 5+ image directories with auto-loading +- Clean codebase (0 unused files as of Dec 2025) --- ## Contributing For lab members and collaborators, see `DEVELOPMENT.md` for detailed development documentation including: -- Detailed file structure and design decisions +- Git workflow and branching strategy +- Detailed file structure and architecture - Comment standardization guidelines -- Development history and changelog -- Cleanup reports and maintenance tasks -- URL management and configuration details +- Development history and changelog +- Code cleanup reports +- Maintenance tasks and verification commands +- URL management and configuration + +Quick member instructions: `.github/Instructions_members.md` --- @@ -315,4 +388,4 @@ Concordia University, Montreal, QC, Canada --- -**Last Updated:** December 1, 2025 +**Last Updated:** December 2, 2025 diff --git a/_config.yml b/_config.yml index cda3ba4..5a7527f 100644 --- a/_config.yml +++ b/_config.yml @@ -27,7 +27,7 @@ description: > # this means to ignore newlines until "baseurl:" Website of the Atlas Analytics Lab. baseurl: "" url: "https://atlasanalyticslab.github.io" -layout_wide: false # Set to false to restore the previous fixed-width layout with generous side margins. +layout_wide: true # Set to false to restore the previous fixed-width layout with generous side margins. include: - .htaccess diff --git a/_data/alumni_members.yml b/_data/alumni_members.yml index d0138e2..011ccbc 100644 --- a/_data/alumni_members.yml +++ b/_data/alumni_members.yml @@ -37,28 +37,28 @@ #============================================================================== - name: Ali Nasiri-Sarvi - info_current: Research Assistant @ Atlas Analytics Lab, Research Associate @ Huawei + info_current: MSc Graduate, Research Assistant @ Atlas Analytics Lab, Research Associate @ Huawei google_scholar: "https://scholar.google.com/citations?user=FzicxBkAAAAJ" linkedin: "https://ca.linkedin.com/in/ali-nasiri-sarvi" - name: Haoyu He - info_current: Graduated MSc, transferred to PhD @ Atlas Analytics Lab + info_current: MSc Graduate, transferred to PhD @ Atlas Analytics Lab - name: Damien Martins Gomes - info_current: AI Scientist @ Thales + info_current: MSc Graduate, AI Scientist @ Thales google_scholar: "https://scholar.google.ca/citations?user=ivIgsbMAAAAJ" linkedin: "https://fr.linkedin.com/in/damien-martins-gomes/fr" - name: Vasudev Sharma - info_current: ML Developer @ Botni.Vision + info_current: MSc Graduate, ML Developer @ Botni.Vision linkedin: "https://ca.linkedin.com/in/vasudev-sharma-341171256" - name: Cassandre Notton - info_current: ML Engineer @ Quandela + info_current: MSc Graduate, ML Engineer @ Quandela google_scholar: "https://scholar.google.com/citations?hl=en&user=H5zKrXcAAAAJ" linkedin: "https://ca.linkedin.com/in/cassandre-notton-69ba6a131" - name: Denisha Thakkar - info_current: ML Egnineer @ CIBC + info_current: MSc Graduate, ML Egnineer @ CIBC linkedin: "https://ca.linkedin.com/in/denisha-thakkar" diff --git a/_includes/footer.html b/_includes/footer.html index 2ee49c3..2313b67 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -25,10 +25,7 @@
-

© {{ site.time | date: '%Y' }} Atlas Analytics Lab. Site made with - Jekyll; - copy and modify it for your own research group. -

+

© {{ site.time | date: '%Y' }} Atlas Analytics Lab.

We are part of the Department of Computer Science and Software Engineering (CSSE) at Concordia University. diff --git a/_layouts/gallerylay.html b/_layouts/gallerylay.html new file mode 100644 index 0000000..4a5776b --- /dev/null +++ b/_layouts/gallerylay.html @@ -0,0 +1,76 @@ +--- +layout: default +--- + + +

+ + + diff --git a/_layouts/gridlay2.html b/_layouts/gridlay2.html deleted file mode 100644 index 6b16991..0000000 --- a/_layouts/gridlay2.html +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: default ---- - -
- {{ content }} -
diff --git a/_layouts/piclay.html b/_layouts/piclay.html deleted file mode 100644 index 9249752..0000000 --- a/_layouts/piclay.html +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: default ---- - - -
- {{ content }} -
\ No newline at end of file diff --git a/_pages/gallery.md b/_pages/gallery.md index bf3eb58..65b30ac 100644 --- a/_pages/gallery.md +++ b/_pages/gallery.md @@ -1,31 +1,32 @@ --- title: "Lab Life" -layout: textlay +layout: gallerylay excerpt: "Atlas Analytics Lab at Concordia University." sitemap: false permalink: /gallery/ ---- - # Lab Life @@ -36,17 +37,15 @@ A glimpse into our research group's activities, conferences, talks, and memorabl {% assign image_files2 = site.static_files | where: "extname", ".jpeg" %} {% assign image_files3 = site.static_files | where: "extname", ".png" %} {% assign all_images = image_files | concat: image_files2 | concat: image_files3 %} +{% assign gallery_images = all_images | where_exp: "item", "item.path contains 'images/picpic/'" | sort: "path" | reverse %} -
-{% for image in all_images %} - {% if image.path contains 'images/picpic/' %} -
- + diff --git a/_pages/openings.md b/_pages/openings.md index 2c9859f..87f804a 100644 --- a/_pages/openings.md +++ b/_pages/openings.md @@ -36,7 +36,7 @@ We are currently recruiting for the following positions: - See instructions and details in [PDF]({{ site.url }}{{ site.baseurl }}/assets/openings/PhD_Hiring_Post_2026_Pathology@McGill%20(CPv2-MSHv2).pdf) 2. **Fully Funded PhD Position in Diffusion Generative Modeling and Deep Learning for Medical Imaging (Radiology & Pathology)** - Co-supervised with [**Prof. Hassan Rivaz**](https://scholar.google.com/citations?hl=zh-CN&user=FWDzqVUAAAAJ&view_op=list_works&sortby=pubdate) - - See instructions and details in [PDF]({{ site.url }}{{ site.baseurl }}/assets/openings/assets/openings/Hiring_Post_Diffusion_Generatrive_Modeling_2026_HRv1_MSHv2.pdf) + - See instructions and details in [PDF]({{ site.url }}{{ site.baseurl }}/assets/openings/Hiring_Post_Diffusion_Generatrive_Modeling_2026_HRv1_MSHv2.pdf) --- diff --git a/_plugins/markdown.rb b/_plugins/markdown.rb deleted file mode 100644 index 6453bd8..0000000 --- a/_plugins/markdown.rb +++ /dev/null @@ -1,39 +0,0 @@ -#============================================================================== -# Markdown Include Tag (_plugins/markdown.rb) -# -# Purpose: -# Jekyll Liquid tag to include Markdown files from _includes directory -# with Liquid preprocessing before Markdown rendering. -# -# Usage: -# {% markdown filename.md %} -# -# Dependencies: -# - kramdown (Markdown processor) -# -# Process: -# 1. Reads Markdown file from _includes/filename -# 2. Preprocesses with Liquid template engine -# 3. Converts Markdown to HTML with kramdown -# 4. Returns rendered HTML -# -# Example: -# {% markdown team-intro.md %} -#============================================================================== - -module Jekyll - class MarkdownTag < Liquid::Tag - def initialize(tag_name, text, tokens) - super - @text = text.strip - end - require "kramdown" - def render(context) - tmpl = File.read File.join Dir.pwd, "_includes", @text - site = context.registers[:site] - tmpl = (Liquid::Template.parse tmpl).render site.site_payload - html = Kramdown::Document.new(tmpl).to_html - end - end -end -Liquid::Template.register_tag('markdown', Jekyll::MarkdownTag) diff --git a/_sass/_gallery.scss b/_sass/_gallery.scss index bb5664c..187254c 100644 --- a/_sass/_gallery.scss +++ b/_sass/_gallery.scss @@ -2,23 +2,111 @@ * Gallery Styles (_gallery.scss) * * Purpose: - * Styles for the Lab Life photo gallery page + * Styles for the Lab Life photo gallery page using CSS Grid masonry layout. * * Features: - * - Responsive grid layout - * - Hover effects - * - Click-to-view functionality - * - Adaptive image heights for different screen sizes + * - CSS Grid masonry layout (with JavaScript fallback) + * - Responsive columns: 1 (mobile) → 2 (tablet) → 3 (desktop) → 4 (large) + * - Images maintain aspect ratios and pack tightly + * - Minimal padding optimized per screen size + * - Hover effects with smooth transitions + * + * Dependencies: + * - gallerylay.html: provides layout overrides + * - gallery-masonry.js: calculates row spans for browsers without masonry support + * + * Note: + * Layout constraints (max-width, padding) are overridden in gallerylay.html + * to respect the layout_wide config setting. ******************************************************************************/ +/* + * Gallery page title and description styling + */ +#galleryid { + h1, p { + padding-left: 0.75rem; + padding-right: 0.75rem; + + @media (min-width: 768px) { + padding-left: 1rem; + padding-right: 1rem; + } + + @media (min-width: 1200px) { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + } +} + +/* + * Gallery grid container + * Uses CSS Grid with masonry layout (when supported) + * Falls back to calculated row spans via JavaScript + */ +.gallery-container { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + + @media (min-width: 576px) { + grid-template-columns: repeat(2, 1fr); + gap: 1.25rem; + } + + @media (min-width: 768px) { + padding-left: 1rem; + padding-right: 1rem; + } + + @media (min-width: 992px) { + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; + } + + @media (min-width: 1200px) { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + @media (min-width: 1400px) { + grid-template-columns: repeat(4, 1fr); + gap: 1.75rem; + } + + // Native CSS Grid Masonry (currently only in Firefox) + grid-template-rows: masonry; + + // Fallback for browsers without masonry support + // Small grid units allow precise row span calculation + @supports not (grid-template-rows: masonry) { + grid-auto-rows: 5px; + } +} + +/* + * Individual gallery card (image wrapper) + * Provides shadow, hover effects, and proper sizing + */ .gallery-card { + display: block; + width: 100%; border: none; box-shadow: 0 2px 4px rgba(0,0,0,0.1); transition: transform 0.2s, box-shadow 0.2s; overflow: hidden; border-radius: 4px; background: var(--atlas-well-bg, #fff); - margin-bottom: 1.5rem; + line-height: 0; + height: fit-content; + + // For browsers without masonry, row span set by JavaScript + @supports not (grid-template-rows: masonry) { + grid-row-end: span auto; + } &:hover { transform: translateY(-4px); @@ -26,32 +114,112 @@ } } +/* + * Gallery image styling + * Images fill card width and maintain aspect ratio + */ .gallery-img { width: 100%; - height: 250px; - object-fit: cover; + height: auto; display: block; border-radius: 4px; - margin: 0; // Override global img margin + margin: 0; + padding: 0; + object-fit: cover; + max-width: 100%; + vertical-align: bottom; +} + +// Gallery page content styling +#galleryid { + h1, p { + padding-left: 0.75rem; + padding-right: 0.75rem; + + @media (min-width: 768px) { + padding-left: 1rem; + padding-right: 1rem; + } + + @media (min-width: 1200px) { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + } +} + +.gallery-container { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + padding-left: 0.75rem; + padding-right: 0.75rem; - // Responsive heights @media (min-width: 576px) { - height: 280px; + grid-template-columns: repeat(2, 1fr); + gap: 1.25rem; } @media (min-width: 768px) { - height: 300px; + padding-left: 1rem; + padding-right: 1rem; } @media (min-width: 992px) { - height: 320px; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; } @media (min-width: 1200px) { - height: 350px; + padding-left: 1.5rem; + padding-right: 1.5rem; } @media (min-width: 1400px) { - height: 380px; + grid-template-columns: repeat(4, 1fr); + gap: 1.75rem; + } + + // Native CSS Grid Masonry (when supported) + grid-template-rows: masonry; + + // Fallback: use smaller grid units for tighter packing + @supports not (grid-template-rows: masonry) { + grid-auto-rows: 5px; + } +} + +.gallery-card { + display: block; + width: 100%; + border: none; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + transition: transform 0.2s, box-shadow 0.2s; + overflow: hidden; + border-radius: 4px; + background: var(--atlas-well-bg, #fff); + line-height: 0; + height: fit-content; + + @supports not (grid-template-rows: masonry) { + // For browsers without masonry, will be set by JavaScript + grid-row-end: span auto; + } + + &:hover { + transform: translateY(-4px); + box-shadow: 0 4px 8px rgba(0,0,0,0.2); } } + +.gallery-img { + width: 100%; + height: auto; + display: block; + border-radius: 4px; + margin: 0; + padding: 0; + object-fit: cover; + max-width: 100%; + vertical-align: bottom; +} diff --git a/images/picpic/omar_yousef_ahmed_archery_activity_aug_30_2025.jpg b/images/picpic/omar_yousef_ahmed_archery_activity_aug_30_2025.jpg new file mode 100644 index 0000000..0596f4c Binary files /dev/null and b/images/picpic/omar_yousef_ahmed_archery_activity_aug_30_2025.jpg differ diff --git a/images/picpic/omar_yousef_archery_activity_aug_30_2025 (1).jpg b/images/picpic/omar_yousef_archery_activity_aug_30_2025 (1).jpg new file mode 100644 index 0000000..299d2d8 Binary files /dev/null and b/images/picpic/omar_yousef_archery_activity_aug_30_2025 (1).jpg differ diff --git a/js/gallery-masonry.js b/js/gallery-masonry.js new file mode 100644 index 0000000..a61d294 --- /dev/null +++ b/js/gallery-masonry.js @@ -0,0 +1,113 @@ +/** + * Gallery Masonry Layout Script (gallery-masonry.js) + * + * Purpose: + * Provides masonry-style layout fallback for browsers that don't yet support + * CSS Grid masonry. Calculates optimal row spans for each image based on its + * height to pack images tightly without gaps. + * + * How it works: + * 1. Checks if browser supports CSS Grid masonry (currently only Firefox) + * 2. If not supported, waits for all images to load + * 3. Calculates row span for each image based on its height + * 4. Applies grid-row-end style to position images correctly + * 5. Recalculates on window resize (debounced for performance) + * + * Browser support: + * - Native masonry: Firefox with layout.css.grid-template-masonry-value.enabled + * - Fallback: All browsers with CSS Grid support (Chrome, Safari, Edge, etc.) + * + * Dependencies: + * - _sass/_gallery.scss: defines grid-auto-rows: 5px for precise calculations + * - gallerylay.html: includes this script + */ + +(function() { + 'use strict'; + + /** + * Calculate and set row span for a single gallery item + * @param {HTMLElement} item - Gallery card element containing an image + */ + function resizeGridItem(item) { + const grid = document.querySelector('.gallery-container'); + if (!grid) return; + + const rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows')); + const rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('gap')); + const img = item.querySelector('.gallery-img'); + if (!img) return; + + const contentHeight = img.getBoundingClientRect().height; + const rowSpan = Math.ceil((contentHeight + rowGap) / (rowHeight + rowGap)); + + item.style.gridRowEnd = 'span ' + rowSpan; + } + + /** + * Recalculate row spans for all gallery items + * Called on window resize events + */ + function resizeAllGridItems() { + const allItems = document.querySelectorAll('.gallery-card'); + allItems.forEach(item => resizeGridItem(item)); + } + + /** + * Initialize masonry layout + * Detects browser support and applies fallback if needed + */ + function initMasonry() { + // Check if browser supports CSS Grid masonry + if (CSS.supports && CSS.supports('grid-template-rows', 'masonry')) { + // Native masonry support, no JavaScript needed + return; + } + + // Fallback: calculate row spans with JavaScript + const images = document.querySelectorAll('.gallery-img'); + let loadedCount = 0; + const totalImages = images.length; + + if (totalImages === 0) return; + + // Wait for each image to load before calculating its row span + images.forEach(img => { + const checkLoaded = () => { + loadedCount++; + resizeGridItem(img.closest('.gallery-card')); + + // Once all images loaded, do final adjustment + if (loadedCount === totalImages) { + setTimeout(resizeAllGridItems, 100); + } + }; + + if (img.complete) { + checkLoaded(); + } else { + img.addEventListener('load', checkLoaded); + img.addEventListener('error', checkLoaded); // Handle failed loads + } + }); + + // Recalculate on window resize (debounced to avoid performance issues) + let resizeTimer; + window.addEventListener('resize', () => { + clearTimeout(resizeTimer); + resizeTimer = setTimeout(resizeAllGridItems, 250); + }); + } + + // Initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initMasonry); + } else { + initMasonry(); + } +})(); + + } else { + initMasonry(); + } +})(); diff --git a/js/npm.js b/js/npm.js deleted file mode 100644 index bf6aa80..0000000 --- a/js/npm.js +++ /dev/null @@ -1,13 +0,0 @@ -// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. -require('../../js/transition.js') -require('../../js/alert.js') -require('../../js/button.js') -require('../../js/carousel.js') -require('../../js/collapse.js') -require('../../js/dropdown.js') -require('../../js/modal.js') -require('../../js/tooltip.js') -require('../../js/popover.js') -require('../../js/scrollspy.js') -require('../../js/tab.js') -require('../../js/affix.js') \ No newline at end of file