diff --git a/.babelrc b/.babelrc index d3da433..53d21af 100644 --- a/.babelrc +++ b/.babelrc @@ -1,41 +1,31 @@ { "presets": [ - [ + [ "@babel/preset-env", - { - "targets": { - "node": "current", - "browsers": [ - "last 5 versions", - "not ie <= 8" - ] - }, - "modules": false - } - ] - ], - "plugins": [ - "add-module-exports" + { + "targets": { + "node": "current", + "browsers": ["last 5 versions", "not ie <= 8"] + }, + "modules": false + } + ] ], + "plugins": ["add-module-exports"], "env": { "test": { "presets": [ - [ + [ "@babel/preset-env", - { - "targets": { - "node": "current", - "browsers": [ - "last 5 versions", - "not ie <= 8" - ] - } + { + "targets": { + "node": "current", + "browsers": ["last 5 versions", "not ie <= 8"] } - ] + } + ] ], - "plugins": [ - "add-module-exports" - ] + "plugins": ["add-module-exports"] } } -} \ No newline at end of file +} diff --git a/README.md b/README.md index a19aba6..dc4db43 100644 --- a/README.md +++ b/README.md @@ -18,29 +18,37 @@ A lightweight javascript library that lets you 'scrub' transition between two im ### Install #### JS + Either import the JS as a module: + ```bash npm install scrub-slider ``` + ```js import Scrub from "scrub-slider"; ``` Or consume the module as UMD/IIFE + ```html ``` #### CS + Either import the CSS into your JS/CSS: + ```js -import 'scrub-slider/dist/css/scrub.css'; +import "scrub-slider/dist/css/scrub.css"; ``` + ```scss -@import 'scrub-slider/dist/css/scrub.css'; +@import "scrub-slider/dist/css/scrub.css"; ``` Or include it the old fashioned way: + ```html ``` diff --git a/example/css/example.css b/example/css/example.css new file mode 100644 index 0000000..55b742f --- /dev/null +++ b/example/css/example.css @@ -0,0 +1,117 @@ +* { + box-sizing: border-box; + font-family: Montserrat, monospace; +} +* li, +* p { + font-family: sans-serif; +} +* a { + font-weight: 700; + color: #c71585; +} +* a:hover { + color: #ba55d3; +} +* .violet { + color: #c71585; +} +* .text-center { + text-align: center; +} +h1 { + color: #cd5c5c; + font-size: 4rem; +} +h2 { + color: #cd5c5c; + font-size: 3rem; +} +h3 { + font-size: 2rem; +} +[class*="example-slider"] { + display: block; + border: 5px solid #000; +} +.example-slider-50 { + width: 50%; + margin: 30px auto; +} +.example-slider-75 { + width: 75%; + margin: 30px auto; +} +.example-slider-full { + margin: 30px auto; +} +@media (max-width: 797px) { + .example-slider-50, + .example-slider-75 { + width: 100%; + } +} +section { + margin-bottom: 30px; + margin-top: 30px; +} +.why-scrub p { + font-size: 1.5rem; + font-family: "Ubuntu Mono", monospace; + padding: 10px; + font-weight: 700; +} +.how-to .options h4 { + color: #cd5c5c; + margin-bottom: 10px; +} +.how-to .options li { + text-align: left; +} +pre { + display: block; + background: #000; + color: #ba55d3; + line-height: 1.5; + padding: 10px; + overflow: scroll; +} +pre span { + color: #c71585; +} +.btn { + display: inline-block; + position: relative; + overflow: hidden; + padding: 15px 30px; + margin: 10px; + border: 3px solid #cd5c5c; + color: #cd5c5c; + font-size: 1.5rem; + font-family: sans-serif; + text-decoration: none; + transition: all 0.2s ease-in-out; +} +.btn:after { + content: ""; + position: absolute; + height: 0%; + left: 50%; + top: 50%; + width: 150%; + z-index: -1; + transition: all 0.75s ease 0s; + transform: translateX(-50%) translateY(-50%) rotate(25deg); + background: #cd5c5c; +} +.btn:hover { + color: #fff; +} +.btn:hover:after { + height: 450%; +} +@media (max-width: 797px) { + .btn { + width: 100%; + } +} diff --git a/example/css/scrub.css b/example/css/scrub.css new file mode 100644 index 0000000..251f082 --- /dev/null +++ b/example/css/scrub.css @@ -0,0 +1,78 @@ +.scrub-slider { + position: relative; + max-width: 100%; + max-height: 100vw; + height: 500px; + overflow: hidden; +} +.scrub-slider:hover { + cursor: pointer; +} +.scrub-slider .scrub-content { + display: block; + position: absolute; + top: 0; + overflow: hidden; + height: 100%; + width: 100vw; +} +.scrub-slider .scrub-content.scrub-left { + left: 0; +} +.scrub-slider .scrub-content.scrub-left > div { + left: 0; +} +.scrub-slider .scrub-content.scrub-right { + right: 0; +} +.scrub-slider .scrub-content.scrub-right > div { + right: 0; +} +.scrub-slider .scrub-content > div { + position: absolute; + height: 100%; + width: 100vw; + background-repeat: no-repeat; + background-position: center; + background-size: cover; +} +.scrub-slider .sliding { + position: absolute; + left: 50%; + height: 100%; + width: 3px; + z-index: 2; + background: white; +} +.scrub-slider .sliding.handleOn:before { + content: ""; + width: 40px; + padding-bottom: 40px; + position: absolute; + display: block; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + border: 3px solid #fff; + border-radius: 100%; + box-shadow: 0 0 2px 1px #000; + z-index: 2; +} +.scrub-slider .sliding.handleOn span[class*="sliding-"] { + width: 0; + height: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + position: absolute; + top: 50%; +} +.scrub-slider .sliding.handleOn span[class*="sliding-"][class*="left"] { + left: 50%; + transform: translate(-150%, -50%); + border-right: 10px solid #000; +} +.scrub-slider .sliding.handleOn span[class*="sliding-"][class*="right"] { + right: 50%; + transform: translate(140%, -50%); + border-left: 10px solid #000; +} diff --git a/example/example.js b/example/example.js new file mode 100644 index 0000000..a9c444a --- /dev/null +++ b/example/example.js @@ -0,0 +1,26 @@ +// import Scrub from "../../dist/scrub.esm"; + +// setting height for hero example. +var a = document.getElementById("slider1"); +if (a.offsetTop < window.innerHeight) { + var b = window.innerHeight - a.offsetTop + "px"; +} + +// different methods of initiating a slider +Scrub({ + target: "#slider1", + height: b, + handle: true, + src: [ + "https://raw.github.com/Recidvst/recidvst-images/master/mustang-old-min.jpg", + "https://raw.github.com/Recidvst/recidvst-images/master/mustang-old-inverted-min.jpg", + ], + alt: ["Image number 1 alt", "Image number 2 alt"], +}); +Scrub("#slider2"); +Scrub({ + target: ".slider3", + height: "800px", +}); + +// Scrub('nonexistent'); diff --git a/example/scrub.iife.js b/example/scrub.iife.js new file mode 100644 index 0000000..2dc99ca --- /dev/null +++ b/example/scrub.iife.js @@ -0,0 +1,242 @@ +var Scrub = (function () { + "use strict"; + + function _typeof(o) { + "@babel/helpers - typeof"; + + return ( + (_typeof = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (o) { + return typeof o; + } + : function (o) { + return o && + "function" == typeof Symbol && + o.constructor === Symbol && + o !== Symbol.prototype + ? "symbol" + : typeof o; + }), + _typeof(o) + ); + } + + // helper functions + // object test + var isObject = function isObject(a) { + return !!a && a.constructor === Object; + }; + // debounce (thanks to Underscore) + function debounce(func, wait, immediate) { + var timeout; + return function () { + var context = this, + args = arguments; + var later = function later() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + } + function Scrub(scrubArg) { + // check if simple call or config passed + if (isObject(scrubArg) || _typeof(scrubArg) == "object") { + // set function default arguments + scrubArg.target = + typeof scrubArg.target !== "undefined" && + (isObject(scrubArg) || _typeof(scrubArg) == "object") + ? scrubArg.target + : null; + scrubArg.height = + typeof scrubArg.height !== "undefined" && + (isObject(scrubArg) || _typeof(scrubArg) == "object") + ? scrubArg.height + : "500px"; + scrubArg.handle = + typeof scrubArg.handle !== "undefined" && + (isObject(scrubArg) || _typeof(scrubArg) == "object") + ? scrubArg.handle + : true; + scrubArg.src = + typeof scrubArg.src !== "undefined" && (isObject(scrubArg) || _typeof(scrubArg) == "object") + ? scrubArg.src + : null; + scrubArg.alt = + typeof scrubArg.alt !== "undefined" && (isObject(scrubArg) || _typeof(scrubArg) == "object") + ? scrubArg.alt + : null; + ScrubInitiate(); + } else { + ScrubInitiate(); + } + function ScrubInitiate() { + // get chosen slider container + var scrubSlider = + isObject(scrubArg) || _typeof(scrubArg) == "object" + ? document.querySelectorAll(scrubArg.target)[0] + : document.querySelectorAll(scrubArg)[0]; + try { + var utilityFn = function utilityFn(callback) { + // avoid non-specific classes.. + var scrubName = + isObject(scrubArg) || _typeof(scrubArg) == "object" ? scrubArg.target : scrubArg; + scrubName = scrubName.replace("#", ""); + scrubName = scrubName.replace(".", ""); + if (scrubName.indexOf(".") > -1 && document.querySelectorAll(scrubName).length > 1) { + console.warn( + "%cScrub Slider works best if you use an %cID%c or a %cunique%c class... ", + "color:cornflowerblue;", + "color:indianred;", + "color:cornflowerblue;", + "color:indianred;", + "color:cornflowerblue;", + ); + } + if (scrubSlider != undefined) { + var createScrubImages = function createScrubImages(el, type, index) { + if (type == "DIV") { + // clone div + var scrubImage = el.cloneNode(true); + el.parentNode.removeChild(el); + // inject scrub container + var scrubCont = document.createElement("div"); + scrubCont.className = + index == 0 ? "scrub-content scrub-left" : "scrub-content scrub-right"; + scrubCont.style.width = parseInt(sliderWidth / 2) + "px"; + scrubSlider.insertBefore(scrubCont, scrubSlider.firstChild); + // re-attach div + scrubImage.style.width = sliderWidth + "px"; + // if alt specified manually + if (scrubArg.alt != null) { + scrubImage.setAttribute("alt", index == 0 ? scrubArg.alt[0] : scrubArg.alt[1]); + } + // if src specified manually + if (scrubArg.src != null) { + var imgSrc = index == 0 ? scrubArg.src[0] : scrubArg.src[1]; + scrubImage.style.backgroundImage = "url(" + imgSrc + ")"; + } + scrubCont.appendChild(scrubImage); + // need a background image.. + if (el.style.backgroundImage == "") { + console.warn( + "%cScrub Slider divs must have a %cbackground image to work!%c >:[", + "color:cornflowerblue;", + "color:indianred;", + "color:cornflowerblue;", + ); + } + + // handle resize + var reziseFn = debounce(function (scrubImage) { + var newSliderWidth = scrubSlider.offsetWidth; + scrubCont.style.width = parseInt(newSliderWidth / 2) + "px"; + scrubImage.style.width = newSliderWidth + "px"; + }, 500); + window.addEventListener("resize", function (e) { + reziseFn(scrubImage); + }); + } else if (type == "IMG") { + // clone div + var scrubImage = document.createElement("div"); + var imgSrc = el.getAttribute("src"); + // if src specified manually + if (scrubArg.src != null) { + imgSrc = index == 0 ? scrubArg.src[0] : scrubArg.src[1]; + } + el.parentNode.removeChild(el); + // inject scrub container + var scrubCont = document.createElement("div"); + scrubCont.className = + index == 0 ? "scrub-content scrub-left" : "scrub-content scrub-right"; + scrubCont.style.width = parseInt(sliderWidth / 2) + "px"; + // if alt specified + if (scrubArg.alt != null) { + scrubImage.setAttribute("alt", index == 0 ? scrubArg.alt[0] : scrubArg.alt[1]); + } + scrubSlider.insertBefore(scrubCont, scrubSlider.firstChild); + // re-attach div + scrubImage.style.width = sliderWidth + "px"; + scrubImage.style.backgroundImage = "url(" + imgSrc + ")"; + scrubCont.appendChild(scrubImage); + + // handle resize + var reziseFn = debounce(function (scrubImage) { + var newSliderWidth = scrubSlider.offsetWidth; + scrubCont.style.width = parseInt(newSliderWidth / 2) + "px"; + scrubImage.style.width = newSliderWidth + "px"; + }, 500); + window.addEventListener("resize", function (e) { + reziseFn(scrubImage); + }); + } + }; + scrubSlider.className += " scrub-slider"; + var sliderWidth = scrubSlider.offsetWidth; + // set height if given + if (scrubArg.height != null) { + scrubSlider.style.height = scrubArg.height; + } + + // get chosen slider's images + var scrubChildren = scrubSlider.children; + for (var i = 0; i < 2; i++) { + var child = scrubChildren[i]; + if (scrubChildren[i] && child.tagName) { + createScrubImages(scrubChildren[i], child.tagName, i); + } + } + callback(scrubSlider); + } else { + console.warn( + "%cScrub Slider needs to be passed an appropriate selector %c- preferably an ID, but a specific, unique class works too.", + "color:cornflowerblue;", + "color:indianred;", + ); + } + }; + utilityFn(function (scrubSlider) { + // add scrub control/handle + var scrubHandle = document.createElement("div"); + scrubHandle.className = "sliding handleOn "; + scrubHandle.innerHTML = + ''; + scrubSlider.appendChild(scrubHandle); + + // remove handle if specified + if (scrubArg.handle == false) { + scrubHandle.innerHTML = ""; + scrubHandle.classList.remove("handleOn"); + } + + // scrub slider main action fn + var mover = debounce(function (pos, full, slider) { + if (scrubHandle) { + var shrink = full - pos; + var sliding = slider.querySelectorAll(".sliding"); + sliding[0].style.left = (pos > 0 ? pos : 0) + "px"; + var contentLeft = slider.querySelectorAll(".scrub-left"); + contentLeft[0].style.width = (pos > 0 ? pos : 0) + "px"; + var contentRight = slider.querySelectorAll(".scrub-right"); + contentRight[0].style.width = (shrink > 0 ? shrink : 0) + "px"; + } + }, 1); + // add mousemove listener + scrubSlider.addEventListener("mousemove", function (e) { + var mousePosition = e.clientX - this.offsetLeft; + var fullWidth = scrubSlider.offsetWidth; + mover(mousePosition, fullWidth, scrubSlider); + }); + }); + } catch (e) { + console.trace("%cuh-oh: %c" + e + "", "color:indianred;", "color:cornflowerblue;"); + } + } + } + + return Scrub; +})(); diff --git a/index.html b/index.html index a3c0b94..b520c8d 100644 --- a/index.html +++ b/index.html @@ -13,8 +13,8 @@