diff --git a/index.html b/index.html new file mode 100644 index 0000000..a620667 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + + React Carousel + + + + + + + + + + + + + + + + + + diff --git a/js/index.js b/js/index.js new file mode 100644 index 0000000..653f305 --- /dev/null +++ b/js/index.js @@ -0,0 +1,216 @@ +// How do I import json into an html file? + +// function loadJSON(filelocation, callback) { +// var xobj = new XMLHttpRequest(); +// xobj.overrideMimeType("application/json"); +// xobj.open("GET", filelocation, true); // Replace 'my_data' with the path to your file +// xobj.onreadystatechange = function () { +// if (xobj.readyState == 4 && xobj.status == "200") { +// // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode +// callback(xobj.responseText); +// } +// }; +// xobj.send(null); +// } + +// function init() { +// var location = "gallery.json"; +// loadJSON((filelocation = location), function (response) { +// // Parse JSON string into object +// const loadedJSON = JSON.parse(response); +// console.log(loadedJSON); +// }); +// } + +// init(); + +// Never had to use the Fetch API because I typically use Axios. +// But I was about to replace the LoadJSON function with this +// fetch("gallery.json") +// .then((response) => response.text()) +// .then((data) => console.log(JSON.parse(data))); + +// I have never had to write anything but JSX in a react app. +// I have only ever used create-react-app... never my own toolchain + +const e = React.createElement; + +// class Carousel extends React.Component { +// constructor(props) { +// super(props); +// this.state = { liked: false }; +// } + +// render() { +// if (this.state.liked) { +// return "You liked this."; +// } + +// return e( +// "button", +// { onClick: () => this.setState({ liked: true }) }, +// "Like" +// ); +// } +// } + +function Carousel() { + const [data, setData] = React.useState([]); + const [displayedImageIndex, setDisplayedImageIndex] = React.useState(0); + // const [imageData, setImageData] = React.useState([]); + + // using a ref here to trigger imperative animations + const imageRef = React.useRef(null); + + React.useEffect(() => { + fetch("gallery.json") + .then((response) => response.text()) + .then((data) => { + const carouselData = JSON.parse(data); + setData(carouselData); + // const container = []; + // I dont think I need to preload local assets + // this may be handled in the index.html + // carouselData.photos.forEach((image) => { + // preLoadImage(image.src) + // .then((res) => { + // container.push(res); + // // append the res... which is an image element to the page with a style of display:hidden + // // How do I append an image element to the return? + // }) + // // TODO: remove console.log and handle error properly + // .catch((error) => console.log(error)) + // .finally(() => { + // setImageData(container); + // }); + // }); + }); + }, []); + + const updateIndex = (index) => { + // if (imageRef && imageRef.current) { + // // add animation class here + // imageRef.current.className = "animate-left"; + // console.log(imageRef.current); + // } + // setTimeout(() => { + if (index > 7) { + setDisplayedImageIndex(0); + } else if (index < 0) { + setDisplayedImageIndex(7); + } else { + setDisplayedImageIndex(index); + } + // }, 2000); + }; + + // const preLoadImage = (imageSource) => { + // return new Promise((resolve, reject) => { + // const img = new Image(); + + // img.onload = () => { + // resolve(img); + // }; + + // img.onerror = () => { + // reject(img); + // }; + + // img.src = imageSource; + // }); + // }; + + return data?.photos?.length > 0 + ? e( + "div", + { className: "carousel center-aligned" }, + e("h4", { className: "title" }, data["gallery-title"]), + e("img", { src: data.photos[displayedImageIndex].src, ref: imageRef }), + e( + "div", + { className: "button-container" }, + e( + "button", + { onClick: () => updateIndex(displayedImageIndex - 1) }, + e("div", { className: "arrow-left" }, null) + ), + e( + "button", + { onClick: () => updateIndex(displayedImageIndex + 1) }, + e("div", { className: "arrow-right" }, null) + ) + ), + e( + "div", + { className: "dot-container" }, + e( + "div", + { + className: `dot ${displayedImageIndex === 0 ? "active" : null}`, + onClick: () => updateIndex(0), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 1 ? "active" : null}`, + onClick: () => updateIndex(1), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 2 ? "active" : null}`, + onClick: () => updateIndex(2), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 3 ? "active" : null}`, + onClick: () => updateIndex(3), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 4 ? "active" : null}`, + onClick: () => updateIndex(4), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 5 ? "active" : null}`, + onClick: () => updateIndex(5), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 6 ? "active" : null}`, + onClick: () => updateIndex(6), + }, + null + ), + e( + "div", + { + className: `dot ${displayedImageIndex === 7 ? "active" : null}`, + onClick: () => updateIndex(7), + }, + null + ) + ) + ) + : "Data was not Loaded"; +} + +const domContainer = document.querySelector("#js-carousel"); +ReactDOM.render(e(Carousel), domContainer); diff --git a/styles/style.css b/styles/style.css new file mode 100644 index 0000000..92a884e --- /dev/null +++ b/styles/style.css @@ -0,0 +1,154 @@ +#js-carousel { + width: 99vw; + height: 99vh; +} + +.carousel { + height: 70%; + width: 70%; + border: 1px solid black; + background-color: black; + border-radius: 5px; + padding: 3%; +} + +.center-aligned { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +img { + width: auto; + height: auto; + max-height: 80%; + border-radius: 5px; + max-width: 80%; +} + +body { + text-align: center; +} + +.button-container { + position: relative; + /* top: -50%; */ + bottom: 40%; + width: 98%; + display: flex; + justify-content: space-between; +} + +button { + background-color: rgba(255, 255, 255, 0.5); + border: none; + padding: 5px; + border-radius: 5px; +} + +button:hover { + background-color: rgba(255, 255, 255, 0.98); +} + +button:active { + background-color: antiquewhite; + border: 1px inset; + padding: 4px; +} + +.arrow-left { + width: 0; + height: 0; + border-top: 10px solid transparent; + border-bottom: 10.866px solid transparent; + border-right: 10px solid black; +} + +.arrow-right { + width: 0; + height: 0; + border-top: 10px solid transparent; + border-bottom: 10.866px solid transparent; + border-left: 10px solid black; +} + +/* +got started with animations but didn't have time to finish +@keyframes tonext { + 75% { + left: 0; + } + 95% { + left: 100%; + } + 98% { + left: 100%; + } + 99% { + left: 0; + } +} + +.animate-left { + animation-name: tonext; + animation-timing-function: ease; + animation-duration: 2s; + animation-iteration-count: infinite; +} */ + +.dot { + background-color: white; + border-radius: 50%; + height: 1rem; + width: 1rem; +} +.active { + background-color: white; + border-radius: 50%; + height: 1.5rem; + width: 1.5rem; +} + +.dot-container { + display: flex; + justify-content: space-evenly; + align-items: center; + width: 50%; + height: 2rem; + /* I need this height to be 10% of the parent continer*/ +} + +.title { + color: white; +} + +@media only screen and (max-width: 600px) { + .dot-container { + width: 100%; + } + .button-container { + bottom: 20%; + } +} + +@media only screen and (min-width: 600px) { +} + +@media only screen and (min-width: 768px) { + .button-container { + bottom: 25%; + } +} + +@media only screen and (min-width: 992px) { +} + +@media only screen and (min-width: 1200px) { + .dot-container { + width: 250px; + } + .button-container { + bottom: 42%; + } +}