diff --git a/_base/lib/pym.js b/_base/lib/pym.js index 5ffd762..817b6f1 100644 --- a/_base/lib/pym.js +++ b/_base/lib/pym.js @@ -28,7 +28,7 @@ switch (getParameterByName("mode")) { // on the NPR homepage." checkbox when pulling the embed code.) case "hp": document.body.classList.add("hp"); - isHomepage = true; + // isHomepage = true; break; // Direct links to the child page (iOS app workaround link) case "childlink": diff --git a/before_after_comparision/README.md b/before_after_comparision/README.md new file mode 100644 index 0000000..f227307 --- /dev/null +++ b/before_after_comparision/README.md @@ -0,0 +1,79 @@ +Before and After Comparison +======================== + +### About this template + +This template offers an animated toggle between two images (a "before" and an "after") — often useful for comparing satellite imagery between two time periods. + +Columns in the spreadsheet: + +* `key` — A unique one-word descriptor for this pair of before and after images (such as the location the image). This is used as the unique id for each photo embed. +* `headline` - A headline for this pair of before and after images _(optional)_. This is most useful in cases where you are including multiple before/after toggles in the same embed. +* `image1` - The before image filename. We assume that it will live in the `synced/` folder inside the graphic. +* `image1_alt` - Alt text for `image1` +* `label_hed1` — The primary label for the first button. When user clicks the button, `image1` will be displayed. The text for the label is typically "Before." +* `label_dek1` — A secondary label for the first button — typically the date when the `image1` was taken. _(optional)_ +* `image2` - The after image filename. We assume that it will live in the `synced/` folder inside the graphic. +* `image2_alt` - Alt text for `image2` +* `label_hed2` — The primary label for the second button. When user clicks the button, `image2` will be displayed. The text for the label is typically "After." +* `label_dek2` — A secondary label for the second button — typically the date when the `image2` was taken. _(optional)_ +* `photo_credit` — Photo credit for `image1` and `image2`. _(optional)_ + +Key files: + +* `synced/` — All images should go here. (Note: This does not get committed to the repo. Files are published using a separate syncing process. See further below.) +* `partials/_beforeafter.html` — Template code to display each pair of before and after images +* `index.html` — View all before/after comparisons in this project + +----- + +### Creating multiple pairs of before and after images + +Add rows with corresponding attributes in the `data` spreadsheet with a unique `key` value. Then, depending on your desired way of presenting the images: + +#### All pairs appear in the same embed + +By default, `index.html` is set up to show all before/after pairs in the spreadsheet, in the order they're listed in the spreadsheet. + +#### Each pair gets its own embed + +If you want separate embeds for each before/after pair in the spreadsheet: + +* Make a copy of `index.html` and rename it according to the `key` for that row +* Change this section of code: + +``` +<% for (let key of Object.keys(COPY.data)) { %> + <%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data[key] ]}}) %> +<% } %> +``` + +to: + +``` +<%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data['KEY_FOR_THIS_ROW'] ]}}) %> +``` + +----- + +### Optimizing images + +Create a folder locally somewhere on your machine with the original-size images. Inside that folder, create a new folder called `resized`. + +Run this ImageMagick script (from our [best practices](https://github.com/nprapps/bestpractices/blob/master/assets.md)) to resize the images: + +``` +for f in *.jpg; do convert $f -quality 75 -resize 1600x1200\> -strip -sampling-factor 4:2:0 -define jpeg:dct-method=float -interlace Plane resized/$f; done +``` + +Save the `resized` images in the `synced` folder in this project. Do not keep the original high-res images here. + +----- + +### Synced files + +For this project, images are synced to S3 rather than stored in the repo. Run this to retrieve / sync them: + +``` +node cli sync $PROJECT_SLUG +``` \ No newline at end of file diff --git a/before_after_comparision/graphic.js b/before_after_comparision/graphic.js new file mode 100644 index 0000000..7a61fbd --- /dev/null +++ b/before_after_comparision/graphic.js @@ -0,0 +1,103 @@ +var pym = require("./lib/pym"); +var ANALYTICS = require("./lib/analytics"); +require("./lib/webfonts"); +var { isMobile } = require("./lib/breakpoints"); + +var pymChild = null; +var isMobile = isMobile.matches; + +/* + * Initialize the graphic. + */ +var onWindowLoaded = function() { + pym.then(function(child) { + pymChild = child; + child.sendHeight(); + window.addEventListener("resize", render); + }); + + initUI(); +} + +/* + * Render the graphic. + */ +var render = function() { + // Update iframe + if (pymChild) { + pymChild.sendHeight(); + } +} + +var initUI = function() { + document.querySelectorAll('.graphic').forEach(function(wrapper) { + var toggleTimeout; + var toggleButtons = wrapper.querySelectorAll('.toggle-btn'); + var splitId = toggleButtons[0].getAttribute('id').split('-'); + + toggleButtons.forEach(function(button) { + button.addEventListener('click', function() { + var parentToggleWrap = button.parentElement; + parentToggleWrap.classList.add('clicked'); + window.clearTimeout(toggleTimeout); + + splitId = button.getAttribute('id').split('-'); + + // select before image by its unique id + var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); + + if (splitId[2] == '1') { + beforeImage.classList.remove('hidden'); + } else { + beforeImage.classList.add('hidden'); + } + + if (!button.classList.contains('active')) { + let activeToggleBtn = parentToggleWrap.querySelector('.toggle-btn.active'); + if (activeToggleBtn) { + activeToggleBtn.classList.remove('active'); + } + button.classList.add('active'); + } + }); + }); + + var autoToggle = function() { + var stepList = [2, 1, 2, 1, 2]; + toggleStep(0); + + function toggleStep(step_i) { + if (step_i < stepList.length) { + var step = stepList[step_i]; + + if (!wrapper.querySelector('.image-toggle').classList.contains('clicked')) { + // select before image by its unique id + var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); + + if (step == 1) { + beforeImage.classList.remove('hidden'); + } else { + beforeImage.classList.add('hidden'); + } + + let activeToggleBtn = wrapper.querySelector('.toggle-btn.active'); + if (activeToggleBtn) { + activeToggleBtn.classList.remove('active'); + } + + wrapper.querySelector('#toggle-' + splitId[1] + '-' + step).classList.add('active'); + + toggleTimeout = window.setTimeout(toggleStep, 2000, step_i + 1); + } + } + } + }; + + autoToggle(); + }); +}; +/* + * Initially load the graphic + * (NB: Use window.load to ensure all images have loaded) + */ +window.onload = onWindowLoaded; diff --git a/before_after_comparision/graphic.less b/before_after_comparision/graphic.less new file mode 100644 index 0000000..da8426c --- /dev/null +++ b/before_after_comparision/graphic.less @@ -0,0 +1,204 @@ +@import "./lib/base"; + +body { + max-width: 1000px; + margin-left: auto; + margin-right: auto; +} + +h1, +h2 { + .mmedia-constrained-centered(); +} + +.beforeafter + .beforeafter { + margin-top: 33px; +} + +.graphic h4 { + .mmedia-constrained-centered(); + .lato(); + font-size: 18px; + margin-bottom: 11px; + color: #666; +} + +.footer, +.footnotes { + .mmedia-constrained(); +} + +.graphic + .footer { + margin-top: -11px; +} + +.top-wrapper { + .clearfix(); + text-align: center; + + .image-toggle, + .legend { + display: inline-block; + } +} + +.image-toggle { + margin-right: 2.5%; + padding-left: 5px; + margin-bottom: 10px; +} + +.toggle-btn { + box-sizing: border-box; + display: inline-block; + width: 160px; + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; + background-color: #ddd; + color: #666; + margin-left: -5px; + opacity: 0.7; + transition: all 200ms ease-in; + .lato(); + + @media @screen-mobile { + width: 120px; + } + + .btn-hed { + text-transform: uppercase; + display: block; + font-size: 13px; + } + + .btn-dek { + display: block; + font-size: 11px; + font-style: italic; + font-weight: normal; + color: #aaa; + } + + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &:hover { + color: #999; + opacity: 1; + } + + &.active { + background-color: #fff; + border-color: #ddd; + color: #454545; + font-weight: bold; + cursor: pointer; + opacity: 1; + } + + @media screen and (max-width: 500px) { + font-size: 1.2em; + + img { + display: none; + } + } +} + +.img-wrapper { + position: relative; + max-width: 1240px; + margin: 0 auto; + overflow: hidden; + + img { + padding: 0; + margin: 0; + max-width: 100%; + display: block; + + // @media screen and (max-width: 500px) { + // max-width: 130%; + // margin-left: -15%; + // } + + &.image-1 { + position: absolute; + top: 0; + left: 0; + transition: opacity 500ms ease-out; + opacity: 1; + + &.hidden { + opacity: 0; + } + } + } +} + +.footnotes { + display: none; +} + +@media screen and (max-width: 440px) { + .top-wrapper { + text-align: center; + } +} + +.hp { + h1, h2, h4 { + display: none; + } + + .graphic { + margin-bottom: 10px; + } + + .footnotes { + display: block; + margin-bottom: 6px; + } + + .footer, + .footnotes { + max-width: none; + margin-left: 0; + margin-right: 0; + } + + .image-toggle { + display: flex; + padding: 0; + margin: 0 auto 2px; + justify-content: center; + + @media @screen-mobile-above { + max-width: 400px; + } + } + + .toggle-btn { + box-sizing: border-box; + display: block; + width: 50%; + border: 1px solid #ccc; + margin-left: 0; + + @media @screen-mobile { + width: 50%; + } + + &:first-child { + border-right: none; + } + } +} diff --git a/before_after_comparision/index.html b/before_after_comparision/index.html new file mode 100644 index 0000000..73f219b --- /dev/null +++ b/before_after_comparision/index.html @@ -0,0 +1,31 @@ +<%= await t.include("lib/_head.html") %> + +<% if (COPY.labels.headline) { %> +
<%= COPY.labels.footnote %>
+