diff --git a/packages/gallery/src/interface/focus.js b/packages/gallery/src/interface/focus.js index 6c60c3d..a5e3814 100644 --- a/packages/gallery/src/interface/focus.js +++ b/packages/gallery/src/interface/focus.js @@ -4,7 +4,7 @@ import { subscribeToRender, defineView, nodeParentWithType, - viewportSize, + availableViewportSize, defineElement as el } from '../utils/domvm.js'; @@ -42,7 +42,7 @@ export function FocusView(vm, params, key, { appbar }) { }; } }, - [doc, viewportSize] + [doc, availableViewportSize] ); function navBack() { diff --git a/packages/gallery/src/interface/sectionView.js b/packages/gallery/src/interface/sectionView.js index 3c7c209..805c716 100644 --- a/packages/gallery/src/interface/sectionView.js +++ b/packages/gallery/src/interface/sectionView.js @@ -6,7 +6,7 @@ import { patchRefStyle, patchNodeStyle, subscribeToRender, - viewportSize + availableViewportSize } from '../utils/domvm.js'; import { injectStyle, styled } from '../services/style.js'; import { DEFAULT_TRANSITION, CLICKABLE, IMAGE_MARGIN, CONTENT_MARGIN } from './styles.js'; @@ -18,8 +18,9 @@ const OPTIMAL_IMAGE_HEIGHT = 140; const ROW_HEIGHT_CUTOFF_MODIFIER = 2; const IMAGE_MARGIN_WIDTH = 2 * IMAGE_MARGIN; +const CONTENT_MARGIN_WIDTH = 2 * CONTENT_MARGIN; -const aspectRatio = (img, margin = 0) => (img.width + margin) / (img.height + margin); +const aspectRatio = img => img.width / img.height; export function SectionView(vm, params, key, context) { const { appbar } = context; @@ -27,12 +28,9 @@ export function SectionView(vm, params, key, context) { const sectionSelectButtonRef = `secSel${key}`; function calculateSections(photos) { - const { width: vw } = viewportSize(); - const availableWidth = vw - CONTENT_MARGIN; - const totalImageRatio = photos.reduce( - (acc, img) => acc + aspectRatio(img, IMAGE_MARGIN_WIDTH), - 0 - ); + const { width: vw } = availableViewportSize(); + const availableWidth = vw - CONTENT_MARGIN_WIDTH; + const totalImageRatio = photos.reduce((acc, img) => acc + aspectRatio(img), 0); const rowCount = Math.ceil(totalImageRatio * OPTIMAL_IMAGE_HEIGHT / availableWidth); const rowRatios = partition(photos.map(aspectRatio), rowCount); @@ -59,7 +57,7 @@ export function SectionView(vm, params, key, context) { return result; } - subscribeToRender(vm, [viewportSize]); + subscribeToRender(vm, [availableViewportSize]); return function render(vm, params) { const { selectedIds, selectMode } = params; diff --git a/packages/gallery/src/utils/domvm.js b/packages/gallery/src/utils/domvm.js index 5b1709c..cd484cb 100644 --- a/packages/gallery/src/utils/domvm.js +++ b/packages/gallery/src/utils/domvm.js @@ -1,7 +1,7 @@ // export * from 'domvm/dist/dev/domvm.dev.js'; export * from 'domvm/dist/mini/domvm.mini.js'; import { defineView } from 'domvm/dist/mini/domvm.mini.js'; -import { prop, call } from 'frptools'; +import { prop, computed, call } from 'frptools'; import { deepAssign } from './conversion.js'; import { error } from '../services/console.js'; @@ -52,13 +52,46 @@ export function renderSwitch(renderMap, switchValue) { } // Expose viewport size in a subscribable. -const SCROLLBAR_SIZE = 20; -export const viewportSize = prop({}, o => (o ? `${o.width}x${o.height}` : '')); +export const scrollbarSize = prop(0); +export const fullViewportSize = prop( + { width: window.innerWidth, height: window.innerHeight }, + o => (o ? `${o.width}x${o.height}` : '') +); +export const availableViewportSize = computed( + (ss, vs) => ({ + width: vs.width - ss, + height: vs.height - ss + }), + [scrollbarSize, fullViewportSize] +); + +(function getScrollbarSize() { + const outer = document.createElement('div'); + const inner = document.createElement('div'); + outer.style.visibility = 'hidden'; + outer.style.width = '100px'; + outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps + + document.body.appendChild(outer); + + const widthNoScroll = outer.offsetWidth; + // force scrollbars + outer.style.overflow = 'scroll'; + + // add innerdiv + inner.style.width = '100%'; + outer.appendChild(inner); + + const widthWithScroll = inner.offsetWidth; + + // remove divs + outer.parentNode.removeChild(outer); + + scrollbarSize(widthNoScroll - widthWithScroll); +})(); + const extractWindowSize = () => - viewportSize({ - width: window.innerWidth - SCROLLBAR_SIZE, - height: window.innerHeight - SCROLLBAR_SIZE - }); + fullViewportSize({ width: window.innerWidth, height: window.innerHeight }); window.addEventListener('resize', extractWindowSize); // Prime our window size extractWindowSize();