Merge pull request #1579 from benubois/image_viewer

Use existing image for image viewer.
This commit is contained in:
Maurice Parker 2020-01-09 11:16:46 -08:00 committed by GitHub
commit 563b61c61b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 115 additions and 91 deletions

View File

@ -1,109 +1,136 @@
var controller = new AbortController()
var activeImageViewer = null;
// Cancel any pending image loads (there might be none) and reset the controller
function cancelImageLoad() {
controller.abort();
controller = new AbortController();
}
// Used to pop a resizable image view
async function imageWasClicked(img) {
cancelImageLoad();
showNetworkLoading(img);
try {
const signal = controller.signal;
const response = await fetch(img.src, { signal: signal });
if (!response.ok) {
throw new Error('Network response was not ok.');
}
const imgBlob = await response.blob();
if (signal.aborted) {
throw new Error('Network response was aborted.');
}
hideNetworkLoading(img);
var reader = new FileReader();
reader.readAsDataURL(imgBlob);
reader.onloadend = function() {
img.classList.add("nnwClicked");
const rect = img.getBoundingClientRect();
var message = {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height
};
message.imageURL = reader.result;
var jsonMessage = JSON.stringify(message);
window.webkit.messageHandlers.imageWasClicked.postMessage(jsonMessage);
}
} catch (error) {
hideNetworkLoading(img);
console.log('There has been a problem with your fetch operation: ', error.message);
class ImageViewer {
constructor(img) {
this.img = img;
this.loadingInterval = null;
this.activityIndicator = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjAiIHdpZHRoPSI2NHB4IiBoZWlnaHQ9IjY0cHgiIHZpZXdCb3g9IjAgMCAxMjggMTI4IiB4bWw6c3BhY2U9InByZXNlcnZlIj48Zz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMwMDAwMDAiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNjY2NjY2MiIHRyYW5zZm9ybT0icm90YXRlKDMwIDY0IDY0KSIvPjxwYXRoIGQ9Ik01OS42IDBoOHY0MGgtOFYweiIgZmlsbD0iI2NjY2NjYyIgdHJhbnNmb3JtPSJyb3RhdGUoNjAgNjQgNjQpIi8+PHBhdGggZD0iTTU5LjYgMGg4djQwaC04VjB6IiBmaWxsPSIjY2NjY2NjIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNjY2NjY2MiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNiMmIyYjIiIHRyYW5zZm9ybT0icm90YXRlKDE1MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM5OTk5OTkiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM3ZjdmN2YiIHRyYW5zZm9ybT0icm90YXRlKDIxMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM2NjY2NjYiIHRyYW5zZm9ybT0icm90YXRlKDI0MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM0YzRjNGMiIHRyYW5zZm9ybT0icm90YXRlKDI3MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMzMzMzMzMiIHRyYW5zZm9ybT0icm90YXRlKDMwMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMxOTE5MTkiIHRyYW5zZm9ybT0icm90YXRlKDMzMCA2NCA2NCkiLz48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgdmFsdWVzPSIwIDY0IDY0OzMwIDY0IDY0OzYwIDY0IDY0OzkwIDY0IDY0OzEyMCA2NCA2NDsxNTAgNjQgNjQ7MTgwIDY0IDY0OzIxMCA2NCA2NDsyNDAgNjQgNjQ7MjcwIDY0IDY0OzMwMCA2NCA2NDszMzAgNjQgNjQiIGNhbGNNb2RlPSJkaXNjcmV0ZSIgZHVyPSIxMDgwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGVUcmFuc2Zvcm0+PC9nPjwvc3ZnPg==";
}
}
function showNetworkLoading(img) {
isLoaded() {
return this.img.classList.contains("nnwLoaded");
}
var wrapper = document.createElement("div");
wrapper.classList.add("activityIndicatorWrap");
img.parentNode.insertBefore(wrapper, img);
wrapper.appendChild(img);
clicked() {
this.showLoadingIndicator();
if (this.isLoaded()) {
this.showViewer();
} else {
var callback = () => {
if (this.isLoaded()) {
clearInterval(this.loadingInterval);
this.showViewer();
}
}
this.loadingInterval = setInterval(callback, 100);
}
}
cancel() {
clearInterval(this.loadingInterval);
this.hideLoadingIndicator();
}
showViewer() {
this.hideLoadingIndicator();
var canvas = document.createElement("canvas");
canvas.width = this.img.naturalWidth;
canvas.height = this.img.naturalHeight;
canvas.getContext("2d").drawImage(this.img, 0, 0);
const rect = this.img.getBoundingClientRect();
const message = {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
imageURL: canvas.toDataURL(),
};
var jsonMessage = JSON.stringify(message);
window.webkit.messageHandlers.imageWasClicked.postMessage(jsonMessage);
}
hideImage() {
this.img.style.opacity = 0;
}
showImage() {
this.img.style.opacity = 1
window.webkit.messageHandlers.imageWasShown.postMessage("");
}
showLoadingIndicator() {
var wrapper = document.createElement("div");
wrapper.classList.add("activityIndicatorWrap");
this.img.parentNode.insertBefore(wrapper, this.img);
wrapper.appendChild(this.img);
var activityIndicatorImg = document.createElement("img");
activityIndicatorImg.classList.add("activityIndicator");
activityIndicatorImg.style.opacity = 0;
activityIndicatorImg.src = this.activityIndicator;
wrapper.appendChild(activityIndicatorImg);
var activityIndicatorImg = document.createElement("img");
activityIndicatorImg.classList.add("activityIndicator");
activityIndicatorImg.style.opacity = 0;
activityIndicatorImg.src = activityIndicator;
wrapper.appendChild(activityIndicatorImg);
// Wait a bit before showing the indicator
function showActivityIndicator() {
activityIndicatorImg.style.opacity = 1;
}
setTimeout(showActivityIndicator, 300);
hideLoadingIndicator() {
var wrapper = this.img.parentNode;
if (wrapper.classList.contains("activityIndicatorWrap")) {
var wrapperParent = wrapper.parentNode;
wrapperParent.insertBefore(this.img, wrapper);
wrapperParent.removeChild(wrapper);
}
}
static init() {
cancelImageLoad();
// keep track of when an image has finished downloading for ImageViewer
document.querySelectorAll("img").forEach(element => {
element.onload = function() {
this.classList.add("nnwLoaded");
}
});
// Add the click listener for images
window.onclick = function(event) {
if (event.target.matches("img")) {
if (activeImageViewer && activeImageViewer.img === event.target) {
cancelImageLoad();
} else {
cancelImageLoad();
activeImageViewer = new ImageViewer(event.target);
activeImageViewer.clicked();
}
}
}
}
}
function hideNetworkLoading(img) {
var wrapper = img.parentNode;
var wrapperParent = wrapper.parentNode;
wrapperParent.insertBefore(img, wrapper);
wrapperParent.removeChild(wrapper);
function cancelImageLoad() {
if (activeImageViewer) {
activeImageViewer.cancel();
activeImageViewer = null;
}
}
// Used to animate the transition to a fullscreen image
function hideClickedImage() {
var img = document.querySelector('.nnwClicked')
img.style.opacity = 0
if (activeImageViewer) {
activeImageViewer.hideImage();
}
}
// Used to animate the transition from a fullscreen image
function showClickedImage() {
var img = document.querySelector('.nnwClicked')
img.classList.remove("nnwClicked");
img.style.opacity = 1
window.webkit.messageHandlers.imageWasShown.postMessage("");
}
// Add the click listener for images
function imageClicks() {
window.onclick = function(event) {
if (event.target.matches('img')) {
imageWasClicked(event.target);
}
if (activeImageViewer) {
activeImageViewer.showImage();
}
}
// Add the playsinline attribute to any HTML5 videos that don't have it.
// Add the playsinline attribute to any HTML5 videos that don"t have it.
// Without this attribute videos may autoplay and take over the whole screen
// on an iphone when viewing an article.
function inlineVideos() {
@ -113,9 +140,6 @@ function inlineVideos() {
}
function postRenderProcessing() {
cancelImageLoad();
imageClicks();
ImageViewer.init();
inlineVideos();
}
const activityIndicator = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjAiIHdpZHRoPSI2NHB4IiBoZWlnaHQ9IjY0cHgiIHZpZXdCb3g9IjAgMCAxMjggMTI4IiB4bWw6c3BhY2U9InByZXNlcnZlIj48Zz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMwMDAwMDAiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNjY2NjY2MiIHRyYW5zZm9ybT0icm90YXRlKDMwIDY0IDY0KSIvPjxwYXRoIGQ9Ik01OS42IDBoOHY0MGgtOFYweiIgZmlsbD0iI2NjY2NjYyIgdHJhbnNmb3JtPSJyb3RhdGUoNjAgNjQgNjQpIi8+PHBhdGggZD0iTTU5LjYgMGg4djQwaC04VjB6IiBmaWxsPSIjY2NjY2NjIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNjY2NjY2MiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiNiMmIyYjIiIHRyYW5zZm9ybT0icm90YXRlKDE1MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM5OTk5OTkiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM3ZjdmN2YiIHRyYW5zZm9ybT0icm90YXRlKDIxMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM2NjY2NjYiIHRyYW5zZm9ybT0icm90YXRlKDI0MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiM0YzRjNGMiIHRyYW5zZm9ybT0icm90YXRlKDI3MCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMzMzMzMzMiIHRyYW5zZm9ybT0icm90YXRlKDMwMCA2NCA2NCkiLz48cGF0aCBkPSJNNTkuNiAwaDh2NDBoLThWMHoiIGZpbGw9IiMxOTE5MTkiIHRyYW5zZm9ybT0icm90YXRlKDMzMCA2NCA2NCkiLz48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgdmFsdWVzPSIwIDY0IDY0OzMwIDY0IDY0OzYwIDY0IDY0OzkwIDY0IDY0OzEyMCA2NCA2NDsxNTAgNjQgNjQ7MTgwIDY0IDY0OzIxMCA2NCA2NDsyNDAgNjQgNjQ7MjcwIDY0IDY0OzMwMCA2NCA2NDszMzAgNjQgNjQiIGNhbGNNb2RlPSJkaXNjcmV0ZSIgZHVyPSIxMDgwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGVUcmFuc2Zvcm0+PC9nPjwvc3ZnPg==";