FEATURE: functional gallery template and lightbox

This commit is contained in:
peter
2016-04-05 19:26:56 +02:00
parent d17a0ec8ef
commit 54f0566ee2
3 changed files with 352 additions and 7 deletions
@@ -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;
}
}
+16 -3
View File
@@ -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 {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;} .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>img {width: 100%; height: 250px; border: 1px solid #414042;}
.gallery-image-holder {margin-bottom: 15px; position: relative; cursor: pointer;} .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 {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 * {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;} .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 { font-weight: 500;}
.top-bar-right .menu li a.active {color: #ffffff;} .top-bar-right .menu li a.active {color: #ffffff;}
#unload-menu {position: absolute; top: 0; float: right; margin: 10px;} #unload-menu {position: absolute; top: 0; float: right; margin: 10px;}
} }
/* 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;}
@@ -1,5 +1,48 @@
<h1>{{$page->title}}</h1> @extendVisitor('defaultLayout')
@foreach($images as $image) @section('content')
<img src="{{config('app.upload_url')}}/{{$image->filename}}" alt="" />
@endforeach <div class="grey-wrapper m-t-25 clearfix">
<div class="row column gallert" id="gallery-images">
<h2 class="m-b-25">{{$page->title}}</h2>
@foreach($images as $index => $image)
<div class="column medium-3 small-6 gallery-image-holder" data-index="{{$index}}" data-img="" data-label="{{$image->description}}">
<img src="{{config('app.upload_url')}}/{{$image->filename}}" alt="{{$image->name}}">
<div class="gallery-item-data text-center">
<h5>{{$image->name or "Název"}}</h5>
<p>{{$image->description or "Popisek"}}</p>
<p>počet ks</p>
<p class="price">cena: 39,-Kč/ks</p>
</div>
</div>
@endforeach
<div class="clearfix"></div>
<script src="@asset('BLightBox.js')"></script>
<script type="text/javascript">
$('.gallery-image-holder').mouseenter(function() {
$(this).find('.gallery-item-data').animate({opacity: 1}, 100, 'swing');
}).mouseleave(function() {
$(this).find('.gallery-item-data').animate({opacity: 0}, 300, 'swing');
});
window.addEventListener('load', function() {
var lightbox = new BLightBox({
invoker: '.gallery-image-holder',
close_text: 'Zavřít'
}, true);
var gallery_links = document.querySelectorAll('.gallery-image-holder'),
gallery_links_i = gallery_links.length;
});
</script>
</div>
</div>
<div class="green-wrapper clearfix">
<div class="row column text-center" id="questions">
<h4 class="w-t">MÁTE DOTAZY? NEBO NÁM CHCETE ZASLAT RYCHLOU POPTÁVKU?</h4>
<a href="#" class="button secondary m-t-25 large rounded">RYCHLÝ FORMULÁŘ</a>
</div>
</div>
@endsection