From 54f0566ee208a7b312b2d4f8a6a8dc4f99447a39 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2016 19:26:56 +0200 Subject: [PATCH] FEATURE: functional gallery template and lightbox --- .../views/visitor/cwbs/assets/BLightBox.js | 289 ++++++++++++++++++ resources/views/visitor/cwbs/assets/style.css | 19 +- .../cwbs/modules/Gallery/default.blade.php | 51 +++- 3 files changed, 352 insertions(+), 7 deletions(-) create mode 100644 resources/views/visitor/cwbs/assets/BLightBox.js diff --git a/resources/views/visitor/cwbs/assets/BLightBox.js b/resources/views/visitor/cwbs/assets/BLightBox.js new file mode 100644 index 00000000..2ba24f05 --- /dev/null +++ b/resources/views/visitor/cwbs/assets/BLightBox.js @@ -0,0 +1,289 @@ +/** + * Lightbox library created by binarity s.r.o. + * www.binarity.cz + * version 1.0.0 + * + * Vanilla JavaScript lightbox plugin. + * + * Can use custom invoker passed as first argument or uses a default one - .b-lightbox. + * This allows to have more lightbox instances on one site to categorize items. + * + * Default behaviour: + * - Hides on escape keydown event - settable (options.allow_escape). + * - Hides on background click - settable (options.allow_backgroundclick). + * - Hide button in top right corner - settable (options.close_text). + * - Allows usage of arrow keys (left/right) to navigate through images - settable (option.allow_arrows). + * + * @param options + * @param autorun + * @constructor + */ +function BLightBox(options, autorun) { + // Instance and instance variables. + var BLightBox = this, + escape_key_allowed = (!(options !== undefined && options.allow_escape === false)), + hide_on_holder_allowed = (!(options !== undefined && options.allow_backgroundclick === false)), + arrows_allowed = (!(options !== undefined && options.allow_arrows === false)), + close_text = (options !== undefined && options.close_text !== undefined) ? options.close_text : 'Close', + + // DOM + lightbox_holder = document.createElement('div'), + invoker_string = (options !== undefined && options.invoker !== undefined) ? options.invoker : '.b-lightbox', + invokers = document.querySelectorAll(invoker_string), + invokers_length = invokers.length, + lightbox_image = document.createElement('img'), + close_label = document.createElement('a'), + previous_button = document.createElement('a'), + next_button = document.createElement('a'), + lightbox_label = document.createElement('span'); + + // BLightBox DOM default settings. + lightbox_holder.className = 'b-lightbox-holder'; + lightbox_image.className = 'b-lightbox-image'; + close_label.className = 'b-lightbox-close-button'; + close_label.textContent = close_text; + previous_button.className = 'b-lightbox-direction previous'; + previous_button.innerHTML = '‹'; + next_button.className = 'b-lightbox-direction next'; + next_button.innerHTML = '›'; + lightbox_label.className = 'b-lightbox-label'; + + /** + * Show new image according to data-newindex attribute on directional button + */ + this.loadNewImage = function(event) { + event.stopPropagation(); + var index = event.target.getAttribute('data-newindex'), + label = invokers[index].getAttribute('data-label'); + + if(invokers[index]) { + lightbox_image.style.display = 'none'; + this.decideFromLoad(invokers[index]); + lightbox_image.style.display = 'block'; + if(label != '') { + lightbox_label.innerHTML = label; + } + } + + this.lightboxImageCenter(label != ''); // Center image. + + // Change indexes to be opened. + previous_button.setAttribute('data-newindex', this.getPreviousIndex(index)); + next_button.setAttribute('data-newindex', this.getNextIndex(index)); + }; + + /** + * Returns first next index possible, or return very first index to allow rotation. + * @param index + * @returns {number} + */ + this.getNextIndex = function(index) { + // Skip to last image if we are on the first. + return (index == invokers_length - 1) ? 0 : parseInt(index) + 1; + }; + + /** + * Returns first previous index possible, or returns last array index to allow rotation. + * @param index + * @returns {number} + */ + this.getPreviousIndex = function(index) { + // Skip to last image if we are on the first. + return (index == 0) ? invokers_length - 1 : index - 1; + }; + + /** + * Reset ivokers_length variable for re-use. + */ + this.resetInvokersLength = function() { + invokers_length = invokers.length; + }; + + /** + * Provides code for closing a lightbox and hiding images. + */ + this.listenActionClose = function(event) { + lightbox_holder.style.display = 'none'; + lightbox_image.style.display = 'none'; + }; + + /** + * Adds src to lightbox image from element's style background-image. + * Removes url() par of the string. + * @param el + */ + this.loadImageFromBackgroundImage = function(el) { + lightbox_image.src = el.style.backgroundImage.replace(/url\("?(.*[^"])"?\)/, '$1'); + }; + + /** + * Adds src to lightbox image from element's child img tag. + * @param el + */ + this.loadImageFromChildImg = function(el) { + var img = el.querySelector('img'); + if(img) { + lightbox_image.src = img.src; + } + }; + + /** + * Move lightbox image to the center of screen. + */ + this.lightboxImageCenter = function(bool_label) { + // Image + lightbox_image.style.left = ((lightbox_holder.offsetWidth - lightbox_image.offsetWidth) / 2) + 'px'; + lightbox_image.style.top = ((lightbox_holder.offsetHeight - lightbox_image.offsetHeight) / 2) + 'px'; + + // Image label. + if(bool_label === true) { + lightbox_label.style.width = lightbox_image.offsetWidth + 'px'; + lightbox_label.style.left = ((lightbox_holder.offsetWidth - lightbox_image.offsetWidth) / 2) + 'px'; + lightbox_label.style.display = 'block'; + lightbox_label.style.top = (lightbox_image.offsetTop + lightbox_image.offsetHeight - lightbox_label.offsetHeight) + 'px'; + } + }; + + /** + * Returns index in invokers array or false on unsuccessful attempt to find the element. + * @param el + * @returns {*} + */ + this.getIndexInInvokers = function(el) { + var inv_length = invokers_length; + while(inv_length--) { + if(invokers[inv_length].isEqualNode(el)) { + return inv_length; + } + } + return false; + }; + + /** + * This method decides from where to load src attribute into lightbox_image. + * @param el + */ + this.decideFromLoad = function(el) { + // Decide from which source to get image url. + if(el.hasAttribute('data-background')) { + this.loadImageFromBackgroundImage(el); + } else if(el.hasAttribute('data-img')) { + this.loadImageFromChildImg(el); + } + + lightbox_label.style.display = 'none'; + lightbox_label.innerHTML = ''; + }; + + /** + * Provides code for opening a lightbox and displaying images. + */ + this.listenActionOpen = function(el, app, event) { + var label = el.getAttribute('data-label'); + + event.stopPropagation(); + event.preventDefault(); // If element is a-tag, prevent from href requesting. + + app.decideFromLoad(el); // Load image into lightbox_image. + + // Change indexes to be opened. + previous_button.setAttribute('data-newindex', app.getPreviousIndex(app.getIndexInInvokers(el))); + next_button.setAttribute('data-newindex', app.getNextIndex(app.getIndexInInvokers(el))); + + // Show lightbox and image. + lightbox_holder.style.display = 'block'; + lightbox_image.style.display = 'block'; + if(label != '') { + lightbox_label.innerHTML = label; + } + + // Center lightbox within the screen. + app.lightboxImageCenter(label != ''); + }; + + /** + * Add lightbox closing method listener to given element. + * @param el + */ + this.addCloseListenerFor = function(el) { + el.addEventListener('click', this.listenActionClose.bind(this)); + }; + + /** + * Add lightbox opening method listener to given element. + * @param el + */ + this.addOpenListenerFor = function(el) { + var app = this; + el.addEventListener('click', app.listenActionOpen.bind(app, el, this), true); + }; + + /** + * Initializes all possible listeners at once on class instance creation. + */ + this.initiateListeners = function() { + // Open Listeners. + while(invokers_length--) { + this.addOpenListenerFor(invokers[invokers_length]); + } + this.resetInvokersLength(); + + // Close Listeners. + // On background click. + if(hide_on_holder_allowed){ + this.addCloseListenerFor(lightbox_holder); + } + // On escape key hit, if requested. + if(escape_key_allowed) { + window.addEventListener('keydown', function (event) { + if(event.keyCode === 27) { + BLightBox.listenActionClose(); + } + }); + } + + // Directional buttons. + previous_button.addEventListener('click',this.loadNewImage.bind(this)); + next_button.addEventListener('click',this.loadNewImage.bind(this)); + // Allow directing with arrows when enabled. + if(arrows_allowed) { + window.addEventListener('keydown', function arrowDirections(event) { + if(event.keyCode === 37) { + previous_button.click(); + } else if(event.keyCode === 39) { + next_button.click(); + } + }); + } + }; + + /** + * Initialization method that starts BLightBox instance. + * @returns {*} + */ + this.init = function() { + // Append lightbox background. + document.body.appendChild(lightbox_holder); + lightbox_holder.appendChild(previous_button); + lightbox_holder.appendChild(lightbox_image); + lightbox_holder.appendChild(next_button); + lightbox_holder.appendChild(close_label); + lightbox_holder.appendChild(lightbox_label); + // Add event listeners for invokers. + this.initiateListeners(); + + // Auto centering on window.resize; + window.addEventListener('resize', function() { + BLightBox.lightboxImageCenter(); + }); + + return BLightBox; + }; + + // If autorun is requested, create instance. + if(autorun !== undefined && autorun === true) { + return this.init(); + } else { + return this; + } +} \ No newline at end of file diff --git a/resources/views/visitor/cwbs/assets/style.css b/resources/views/visitor/cwbs/assets/style.css index 7ce280cf..c50fc9eb 100644 --- a/resources/views/visitor/cwbs/assets/style.css +++ b/resources/views/visitor/cwbs/assets/style.css @@ -101,8 +101,9 @@ img.thumbnail:focus, img.thumbnail:hover {box-shadow: none; border-color: #fffff .sale-item-data p {margin: -5px auto 0; padding: 0 auto; text-align: center; font-size: 0.8rem;} .sale-item-data p.price {margin-top: 10px; font-weight: 700; font-size: 0.9rem;} -.gallery-image-holder>img {width: 100%; height: auto; border: 1px solid #414042;} -.gallery-image-holder {margin-bottom: 15px; position: relative; cursor: pointer;} +.gallery-image-holder>img {width: 100%; height: 250px; border: 1px solid #414042;} +.gallery-image-holder {margin-bottom: 15px; height: 250px; position: relative; cursor: pointer;} +.gallery-image-holder.column:last-child:not(:first-child), .gallery-image-holder.columns:last-child:not(:first-child) {float: left;} .gallery-item-data {display: block; opacity: 0; width: calc(100% - 0.9375rem * 2);height: 100%; position: absolute; top: 0; left: 0.9375rem; background-color: rgba(65, 64, 66, 0.71); color: #ffffff;} .gallery-item-data * {color: #ffffff;} .gallery-item-data h5 {text-transform: uppercase; font-size: 1.1rem; text-align: center; padding: 15px 10px 0 10px; font-weight: 700; margin-bottom: 0;} @@ -226,4 +227,16 @@ footer a:hover {color: #46c1be;} .top-bar-right .menu li a { font-weight: 500;} .top-bar-right .menu li a.active {color: #ffffff;} #unload-menu {position: absolute; top: 0; float: right; margin: 10px;} -} \ No newline at end of file +} + +/* BLightBox defaults */ +.b-lightbox-holder{background-color:rgba(0,0,0,0.85);width:100%;height:100%;position:fixed;top:0;left:0;display:none;z-index:1000;} +.b-lightbox-image{display:none;border-radius:0;max-height:90%;max-width:90%;position:fixed;margin:0 auto;z-index:1001;} +.b-lightbox-close-button{z-index:1100;display:block;position:fixed;top:8px;right:8px;font-size:14px;color:rgba(242,242,242,0.8);cursor:pointer;font-weight:700;} +.b-lightbox-close-button:hover {font-weight: 700;} +.b-lightbox-direction{z-index:1050;height:100%;font-size:10em;cursor:pointer;display:inline-block;min-width:10%;text-align:center;position:absolute;top:0} +.b-lightbox-direction.next{right:0} +.b-lightbox-direction.previous{left:0} +.b-lightbox-direction:hover{background-color:rgba(242,242,242,0.1); text-decoration: none;} +.b-lightbox-direction:before{content:'';height:35%;display:block;width:100%;} +.b-lightbox-label{box-sizing:border-box;display:none;z-index:1015;background-color:rgba(70, 193, 190, 0.2);color:rgba(15,15,15,0.95);font-weight:500;position:absolute;padding:10px;font-size:13px;} \ No newline at end of file diff --git a/resources/views/visitor/cwbs/modules/Gallery/default.blade.php b/resources/views/visitor/cwbs/modules/Gallery/default.blade.php index 9936413d..2bf3ea39 100644 --- a/resources/views/visitor/cwbs/modules/Gallery/default.blade.php +++ b/resources/views/visitor/cwbs/modules/Gallery/default.blade.php @@ -1,5 +1,48 @@ -

{{$page->title}}

+@extendVisitor('defaultLayout') -@foreach($images as $image) - -@endforeach \ No newline at end of file +@section('content') + +
+ +
+
+
+

MÁTE DOTAZY? NEBO NÁM CHCETE ZASLAT RYCHLOU POPTÁVKU?

+ RYCHLÝ FORMULÁŘ +
+
+ +@endsection \ No newline at end of file