src/components/article_body/article_body.js
import { Component } from "../../core/bane";
import $ from "jquery";
import ImageGallery from "../image_gallery";
import PoiCallout from "../poi_callout";
import moment from "moment";
import matchMedia from "../../core/utils/matchMedia";
import rizzo from "../../rizzo";
/**
* Enhances the body of articles with a gallery and more
*/
export default class ArticleBodyComponent extends Component {
initialize(options) {
this.imageContainerSelector = ".stack__article__image-container";
this.poiData = options.poiData;
this.loadImages().then(() => {
this.gallery = new ImageGallery({
el: this.$el
});
});
if (this.poiData) {
matchMedia("(min-width: 1200px)", (query) => {
if (query.matches) {
this.loadPoiCallout(this.poiData);
} else {
if (typeof this.poiCallout !== "undefined") {
this.poiCallout.destroy();
}
}
});
}
this.formatDate();
}
/**
* Loads all the images in the body of the article
* @return {Promise} A promise for when all of the images have loaded
*/
loadImages() {
let promises = [];
this.$el.find(this.imageContainerSelector).each((index, el) => {
let $img = $(el).find("img"),
$a = $(el).find("a").eq(0),
$span = $(el).find("span"),
src = $($img).attr("src");
let promise = this.loadImage(src).then((image) => {
if (!$a.length) {
$img.wrap(`<a class="copy--body__link" href="${src}" data-size="${image.width}x${image.height}" />`);
} else {
$a.attr("data-size", `${image.width}x${image.height}`);
}
if(image.width > 1000 && $img.hasClass("is-landscape")) {
$(el).addClass("is-wide");
}
$(el).addClass("is-visible");
if (!$span.length) {
$(el).contents().filter(function() {
return this.nodeType === 3 && $.trim(this.nodeValue).length;
}).wrap(`<span class="copy--caption" />`);
}
});
promises.push(promise);
});
return Promise.all(promises).catch((err) => {
rizzo.logger.error(err);
});
}
/**
* Preload an image
* @param {String} url Url of the image to load
* @return {Promise} A promise for when the image loads
*/
loadImage(url) {
let image = new Image();
return new Promise((resolve, reject) => {
image.src = url;
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(url);
};
if (!url) {
reject(url);
}
});
}
/**
* Format the post date with moment.js
*/
formatDate() {
let $footer = this.$el.siblings(".js-article-footer"),
date = $footer.find("time").attr("datetime"),
formattedDate = moment(date).format("MMMM YYYY");
$footer
.find("time").html(formattedDate)
.closest(".js-article-post-date").removeProp("hidden");
}
/**
* Creates a new instance of the POI callout
* @param {Object} data POI data
*/
loadPoiCallout(data) {
this.poiCallout = new PoiCallout({
el: this.$el,
pois: data
});
}
}