mirror of
https://github.com/a2nt/meta-lightbox.git
synced 2024-10-22 17:05:53 +02:00
394 lines
11 KiB
JavaScript
Executable File
394 lines
11 KiB
JavaScript
Executable File
/*
|
|
* Lightbox window
|
|
*/
|
|
|
|
import Events from './_events';
|
|
import { Component } from 'react';
|
|
import styles from '../scss/_window.scss';
|
|
|
|
import Embed, { defaultProviders } from 'react-tiny-oembed';
|
|
|
|
const InstagramProvider = {
|
|
provider_name: 'Instagram',
|
|
provider_url: 'https://instagram.com',
|
|
endpoints: [{
|
|
schemes: [
|
|
'http://instagram.com/*/p/*,',
|
|
'http://www.instagram.com/*/p/*,',
|
|
'https://instagram.com/*/p/*,',
|
|
'https://www.instagram.com/*/p/*,',
|
|
'http://instagram.com/p/*',
|
|
'http://instagr.am/p/*',
|
|
'http://www.instagram.com/p/*',
|
|
'http://www.instagr.am/p/*',
|
|
'https://instagram.com/p/*',
|
|
'https://instagr.am/p/*',
|
|
'https://www.instagram.com/p/*',
|
|
'https://www.instagr.am/p/*',
|
|
'http://instagram.com/tv/*',
|
|
'http://instagr.am/tv/*',
|
|
'http://www.instagram.com/tv/*',
|
|
'http://www.instagr.am/tv/*',
|
|
'https://instagram.com/tv/*',
|
|
'https://instagr.am/tv/*',
|
|
'https://www.instagram.com/tv/*',
|
|
'https://www.instagr.am/tv/*',
|
|
],
|
|
url: 'https://graph.facebook.com/v9.0/instagram_oembed',
|
|
formats: ['json'],
|
|
},
|
|
{
|
|
schemes: [
|
|
'http://instagram.com/*/p/*,',
|
|
'http://www.instagram.com/*/p/*,',
|
|
'https://instagram.com/*/p/*,',
|
|
'https://www.instagram.com/*/p/*,',
|
|
'http://instagram.com/p/*',
|
|
'http://instagr.am/p/*',
|
|
'http://www.instagram.com/p/*',
|
|
'http://www.instagr.am/p/*',
|
|
'https://instagram.com/p/*',
|
|
'https://instagr.am/p/*',
|
|
'https://www.instagram.com/p/*',
|
|
'https://www.instagr.am/p/*',
|
|
'http://instagram.com/tv/*',
|
|
'http://instagr.am/tv/*',
|
|
'http://www.instagram.com/tv/*',
|
|
'http://www.instagr.am/tv/*',
|
|
'https://instagram.com/tv/*',
|
|
'https://instagr.am/tv/*',
|
|
'https://www.instagram.com/tv/*',
|
|
'https://www.instagr.am/tv/*',
|
|
],
|
|
url: 'https://api.instagram.com/oembed',
|
|
formats: ['json'],
|
|
},
|
|
],
|
|
};
|
|
|
|
const axios = require('axios');
|
|
|
|
class MetaWindow extends Component {
|
|
state = {
|
|
content: '',
|
|
type: [],
|
|
shown: false,
|
|
loading: false,
|
|
error: false,
|
|
embed: false,
|
|
collections: [],
|
|
current: null,
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
const ui = this;
|
|
ui.name = ui.constructor.name;
|
|
console.log(`${ui.name}: init`);
|
|
|
|
ui.axios = axios;
|
|
}
|
|
|
|
_currIndex = () => {
|
|
const ui = this;
|
|
const el = ui.state.current;
|
|
const gallery = el.getAttribute('data-gallery');
|
|
|
|
return ui.state.collections[gallery].indexOf(el);
|
|
};
|
|
|
|
next = () => {
|
|
const ui = this;
|
|
const el = ui.state.current;
|
|
const gallery = el.getAttribute('data-gallery');
|
|
|
|
let i = ui._currIndex();
|
|
if (i < ui.state.collections[gallery].length - 1) {
|
|
i++;
|
|
} else {
|
|
i = 0;
|
|
}
|
|
|
|
ui.state.collections[gallery][i].click();
|
|
|
|
W.dispatchEvent(new Event('MetaLightboxUI.next'));
|
|
};
|
|
|
|
prev = () => {
|
|
const ui = this;
|
|
const el = ui.state.current;
|
|
const gallery = el.getAttribute('data-gallery');
|
|
|
|
let i = ui._currIndex();
|
|
if (i > 0) {
|
|
i--;
|
|
} else {
|
|
i = ui.state.collections[gallery].length - 1;
|
|
}
|
|
|
|
ui.state.collections[gallery][i].click();
|
|
|
|
W.dispatchEvent(new Event('MetaLightboxUI.prev'));
|
|
};
|
|
|
|
reset = () => {
|
|
const ui = this;
|
|
|
|
ui.setState({
|
|
content: '',
|
|
type: [],
|
|
shown: false,
|
|
loading: false,
|
|
error: false,
|
|
embed: false,
|
|
});
|
|
};
|
|
|
|
embed = (link) => {
|
|
const ui = this;
|
|
console.log(`${ui.name}: embed`);
|
|
|
|
ui.reset();
|
|
ui.setState({
|
|
embed: link,
|
|
loading: false,
|
|
type: ['embed', 'video'],
|
|
});
|
|
ui.show();
|
|
};
|
|
|
|
load = (link) => {
|
|
const ui = this;
|
|
const axios = ui.axios;
|
|
|
|
ui.reset();
|
|
ui.setState({ loading: true });
|
|
ui.show();
|
|
|
|
axios
|
|
.get(link, {
|
|
responseType: 'arraybuffer',
|
|
})
|
|
.then((resp) => {
|
|
// handle success
|
|
console.log(
|
|
`${ui.name}: response content-type: ${resp.headers['content-type']}`,
|
|
);
|
|
|
|
switch (resp.headers['content-type']) {
|
|
case 'image/jpeg':
|
|
case 'image/png':
|
|
case 'image/svg+xml':
|
|
case 'image/bmp':
|
|
case 'image/gif':
|
|
case 'image/tiff':
|
|
case 'image/webp':
|
|
// irregular types:
|
|
case 'image/jpg':
|
|
case 'image/svg':
|
|
ui.setContent(
|
|
`<img src="data:${
|
|
resp.headers['content-type']
|
|
};base64,${ui._imageEncode(resp.data)}" />`,
|
|
'image',
|
|
);
|
|
break;
|
|
case 'application/json':
|
|
case 'application/ld+json':
|
|
// irregular types:
|
|
case 'application/json; charset=UTF-8':
|
|
const json = JSON.parse(ui._abToString(resp.data));
|
|
ui.setContent(`${json['Content']}`, 'text html json');
|
|
|
|
break;
|
|
case 'text/html':
|
|
case 'application/xhtml+xml':
|
|
case 'text/plain':
|
|
// irregular types:
|
|
case 'text/html; charset=UTF-8':
|
|
case 'application/xhtml+xml; charset=UTF-8':
|
|
case 'text/plain; charset=UTF-8':
|
|
ui.setContent(
|
|
ui._abToString(resp.data),
|
|
'text html pajax',
|
|
);
|
|
break;
|
|
default:
|
|
console.warn(
|
|
`${ui.name}: Unknown response content-type!`,
|
|
);
|
|
break;
|
|
}
|
|
|
|
W.dispatchEvent(new Event('MetaLightboxUI.loaded'));
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
|
|
let msg = '';
|
|
|
|
if (error.response) {
|
|
switch (error.response.status) {
|
|
case 404:
|
|
msg = 'Not Found.';
|
|
break;
|
|
case 500:
|
|
msg = 'Server issue, please try again latter.';
|
|
break;
|
|
default:
|
|
msg = 'Something went wrong.';
|
|
break;
|
|
}
|
|
} else if (error.request) {
|
|
msg = 'No response received';
|
|
} else {
|
|
console.warn('Error', error.message);
|
|
}
|
|
|
|
ui.setState({ error: msg });
|
|
|
|
W.dispatchEvent(new Event('MetaLightboxUI.error'));
|
|
})
|
|
.then(() => {
|
|
ui.setState({ loading: false });
|
|
});
|
|
};
|
|
|
|
_abToString = (arrayBuffer) => {
|
|
return String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));
|
|
};
|
|
|
|
_imageEncode = (arrayBuffer) => {
|
|
let u8 = new Uint8Array(arrayBuffer);
|
|
let b64encoded = btoa(
|
|
[].reduce.call(
|
|
new Uint8Array(arrayBuffer),
|
|
function(p, c) {
|
|
return p + String.fromCharCode(c);
|
|
},
|
|
'',
|
|
),
|
|
);
|
|
|
|
return b64encoded;
|
|
};
|
|
|
|
setContent = (html, type) => {
|
|
const ui = this;
|
|
console.log(`${ui.name}: setContent`);
|
|
|
|
let typeArr = type ? type : ['html', 'text'];
|
|
if (!Array.isArray(typeArr)) {
|
|
typeArr = type.split(' ');
|
|
}
|
|
|
|
ui.setState({ content: html, type: typeArr });
|
|
};
|
|
|
|
show = () => {
|
|
const ui = this;
|
|
console.log(`${ui.name}: show`);
|
|
|
|
ui.setState({ shown: true });
|
|
W.dispatchEvent(new Event('MetaLightboxUI.show'));
|
|
};
|
|
|
|
hide = () => {
|
|
const ui = this;
|
|
|
|
console.log(`${ui.name}: hide`);
|
|
ui.setState({ shown: false });
|
|
W.dispatchEvent(new Event('MetaLightboxUI.hide'));
|
|
};
|
|
|
|
getHtml = () => {
|
|
const ui = this;
|
|
return { __html: ui.state.content };
|
|
};
|
|
|
|
render() {
|
|
const ui = this;
|
|
const name = ui.name;
|
|
|
|
let navs = null;
|
|
const el = ui.state.current;
|
|
if (el) {
|
|
const gallery = el.getAttribute('data-gallery');
|
|
if (gallery && ui.state.collections[gallery].length > 1) {
|
|
navs = (
|
|
<nav className="meta-navs">
|
|
<button
|
|
className="meta-nav meta-nav-arrow meta-nav-arrow__prev a"
|
|
onClick={ui.prev}
|
|
>
|
|
<i className="fa fas fa-chevron-left"></i>
|
|
<span className="sr-only">Previous</span>
|
|
</button>
|
|
<button
|
|
className="meta-nav meta-nav-arrow meta-nav-arrow__next a"
|
|
onClick={ui.next}
|
|
>
|
|
<i className="fa fas fa-chevron-right"></i>
|
|
<span className="sr-only">Next</span>
|
|
</button>
|
|
</nav>
|
|
);
|
|
}
|
|
}
|
|
|
|
const content = ui.state.embed ? (
|
|
<section className="meta-wrap typography">
|
|
<Embed
|
|
url={ui.state.embed}
|
|
providers={[...defaultProviders, InstagramProvider]}
|
|
LoadingFallbackElement=<div className="meta-spinner_embed">
|
|
... Loading ...
|
|
</div>
|
|
/>
|
|
</section>
|
|
) : (
|
|
<section
|
|
className="meta-wrap typography"
|
|
dangerouslySetInnerHTML={ui.getHtml()}
|
|
></section>
|
|
);
|
|
|
|
const className = `meta-${name} meta-${name}__${ui.state.type.join(
|
|
` meta-${name}__`,
|
|
)}`;
|
|
|
|
const overlayClassName = `meta-${name}-overlay${
|
|
ui.state.shown ? ` meta-${name}-overlay__open` : ''
|
|
}${ui.state.loading ? ` meta-${name}-overlay__loading` : ''}${
|
|
ui.state.error ? ` meta-${name}-overlay__error` : ''
|
|
}`;
|
|
|
|
return (
|
|
<div className={className}>
|
|
<div className={overlayClassName}>
|
|
<article className="meta-content">
|
|
{navs}
|
|
<button
|
|
className="meta-nav meta-close a"
|
|
onClick={ui.hide}
|
|
>
|
|
<i className="fa fas fa-times"></i>
|
|
<span className="sr-only">Close</span>
|
|
</button>
|
|
|
|
<div className="meta-spinner">... Loading ...</div>
|
|
<div className="meta-error alert alert-danger">
|
|
{ui.state.error}
|
|
</div>
|
|
|
|
{content}
|
|
</article>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default MetaWindow;
|