So I downloaded a slideshow for my home page. It comes with 2 animated text titles (H2 and H3) that slide in from the left of the screen to center. I am now trying to add an additional line of text (H4) that should slide in from the right... with a few seconds delay.
I already edited the webpage and .css file accordingly, but the javascript I am not too sure I know exactly what to do, and I don't wanna mess it up all together.
I will paste here part of the js file where the title animation is being handled (if necessary I also stick the whole file at the bottom of this post).
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 },
this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 },
this.options.titlespeed, this.options.titleeasing )
And here's the css file (already edited to include the added text as 'H4'):
.ei-slider{
position: relative;
width: 100%;
max-width: 1999px;
height: 500px;
margin: 0 auto;
}
.ei-slider-loading{
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
z-index:999;
background: rgba(0,0,0,0.9);
color: #fff;
text-align: center;
line-height: 400px;
}
.ei-slider-large{
height: 100%;
width: 100%;
position:relative;
overflow: hidden;
}
.ei-slider-large li{
position: absolute;
top: 20px;
left: 0px;
overflow: hidden;
height: 100%;
width: 100%;
}
.ei-slider-large li img{
width: 100%;
}
.ei-title h4{
position: absolute;
left: 50%;
margin-right: 13%;
top: 30%;
}
.ei-title h2, h3{
position: absolute;
right: 50%;
margin-right: 13%;
top: 30%;
}
.ei-title h2, .ei-title h3{
text-align: right;
}
.ei-title h4 {
text-align: left;
}
.ei-title h2{
font-size: 40px;
line-height: 50px;
font-family: 'Playfair Display', serif;
font-style: italic;
color: #b5b5b5;
}
.ei-title h3{
font-size: 20px;
line-height: 20px;
font-family: 'Open Sans Condensed', sans-serif;
text-transform: uppercase;
color: #000;
}
.ei-title h4{
font-size: 10px;
line-height: 20px;
font-family: 'sans-serif'; italic;
text-transform: uppercase;
color: #f0ffff;
}
/* the thumbs... */
.ei-slider-thumbs{
height: 1px;
margin: 0 auto;
position: relative;
}
.ei-slider-thumbs li{
position: relative;
float: left;
height: 10%;
}
.ei-slider-thumbs li.ei-slider-element{
top: 0px;
left: 0px;
position: absolute;
height: 10%;
z-index: 10;
text-indent: -9000px;
background: #000;
background: rgba(0,0,0,0.9);
}
.ei-slider-thumbs li a{
display: block;
text-indent: -9000px;
background: #666 ;
width: 100%;
height: 100%;
cursor: pointer;
-webkit-box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
-moz-box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
-webkit-transition: background 0.2s ease;
-moz-transition: background 0.2s ease;
-o-transition: background 0.2s ease;
-ms-transition: background 0.2s ease;
transition: background 0.2s ease;
}
.ei-slider-thumbs li a:hover{
background-color: #f0f0f0;
}
.ei-slider-thumbs li img{
position: absolute;
bottom: 10px;
opacity: 0;
z-index: 999;
max-width: 100%;
-webkit-transition: all 0.4s ease;
-moz-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
-ms-transition: all 0.4s ease;
transition: all 0.4s ease;
-webkit-box-reflect:
below 0px -webkit-gradient(
linear,
left top,
left bottom,
from(transparent),
color-stop(50%, transparent),
to(rgba(255,255,255,0.3))
);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
.ei-slider-thumbs li:hover img{
opacity: -1;
bottom: -1px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
}
#media screen and (max-width: 830px) {
.ei-title{
position: absolute;
right: 0px;
margin-right: 0px;
width: 100%;
text-align: center;
top: auto;
bottom: 10px;
background: #fff;
background: rgba(255,255,255,0.9);
padding: 5px 0;
}
.ei-title h2, .ei-title h3, .ei-title h4 {
text-align: center;
}
.ei-title h2{
font-size: 30px;
line-height: 24px;
}
.ei-title h3{
font-size: 20px;
line-height: 20px;
}
.ei-title h4{
font-size: 10px;
line-height: 20px;
}
}
And the html/js code on the webpage:
<div class="wrapper">
<div id="ei-slider" class="ei-slider">
<ul class="ei-slider-large">
<li>
<img src="uploads/2016/01/slider-3.jpg" alt="image01">
<div class="ei-title">
<h2>High end Management Tools</h2>
<h3>Available at your fingertips!</h3>
<h4>With the available technologies, we provide the methods and tools that will help society to excel to new heights</h4>
</div>
</li>
<li>
<img src="uploads/2016/01/about-1.jpg" alt="image02" />
<div class="ei-title">
<h2>Enterprises, Administration Managers</h2>
<h3>Improve your Performance!</h3>
<h4>Regardless of your position, we have the solutions for all levels of professionals, and students alike.... </h4>
</div>
</li>
<li>
<img src="uploads/2016/01/home-parallax.jpg" alt="image03" />
<div class="ei-title">
<h2>Stunning Solutions</h2>
<h3>For Remarkable results!</h3>
<h4>We are bringing today's technology to assist the traditional family with promising results.</h4>
</div>
</li>
</ul><!-- ei-slider-large -->
</div><!-- ei-slider -->
</div><!-- wrapper -->
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.eislideshow.js"></script>
<script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
<script type="text/javascript">
$(function() {
$('#ei-slider').eislideshow({
animation : 'center',
autoplay : true,
slideshow_interval : 6000,
titlesFactor : 0
});
});
</script>
Oh, and finally, the entire javascript file:
(function( window, $, undefined ) {
/*
* smartresize: debounced resize event for jQuery
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.smartresize.js
*
* Copyright 2011 #louis_remi
* Licensed under the MIT license.
*/
var $event = $.event, resizeTimeout;
$event.special.smartresize = {
setup: function() {
$(this).bind( "resize", $event.special.smartresize.handler );
},
teardown: function() {
$(this).unbind( "resize", $event.special.smartresize.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
resizeTimeout = setTimeout(function() {
jQuery.event.handle.apply( context, args );
}, execAsap === "execAsap"? 0 : 100 );
}
};
$.fn.smartresize = function( fn ) {
return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
};
$.Slideshow = function( options, element ) {
this.$el = $( element );
/***** images ****/
// list of image items
this.$list = this.$el.find('ul.ei-slider-large');
// image items
this.$imgItems = this.$list.children('li');
// total number of items
this.itemsCount = this.$imgItems.length;
// images
this.$images = this.$imgItems.find('img:first');
/***** thumbs ****/
// thumbs wrapper
this.$sliderthumbs = this.$el.find('ul.ei-slider-thumbs').hide();
// slider elements
this.$sliderElems = this.$sliderthumbs.children('li');
// sliding div
this.$sliderElem = this.$sliderthumbs.children('li.ei-slider-element');
// thumbs
this.$thumbs = this.$sliderElems.not('.ei-slider-element');
// initialize slideshow
this._init( options );
};
$.Slideshow.defaults = {
// animation types:
// "sides" : new slides will slide in from left / right
// "center": new slides will appear in the center
animation : 'sides', // sides || center
// if true the slider will automatically slide, and it will only stop if the user clicks on a thumb
autoplay : false,
// interval for the slideshow
slideshow_interval : 3000,
// speed for the sliding animation
speed : 1000,
// easing for the sliding animation
easing : '',
// percentage of speed for the titles animation. Speed will be speed * titlesFactor
titlesFactor : 0.60,
// titles animation speed
titlespeed : 900,
// titles animation easing
titleeasing : '',
// maximum width for the thumbs in pixels
thumbMaxWidth : 150
};
$.Slideshow.prototype = {
_init : function( options ) {
this.options = $.extend( true, {}, $.Slideshow.defaults, options );
// set the opacity of the title elements and the image items
this.$imgItems.css( 'opacity', 0 );
this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 );
// index of current visible slider
this.current = 0;
var _self = this;
// preload images
// add loading status
this.$loading = $('<div class="ei-slider-loading">Loading</div>').prependTo( _self.$el );
$.when( this._preloadImages() ).done( function() {
// hide loading status
_self.$loading.hide();
// calculate size and position for each image
_self._setImagesSize();
// configure thumbs container
_self._initThumbs();
// show first
_self.$imgItems.eq( _self.current ).css({
'opacity' : 1,
'z-index' : 10
}).show().find('div.ei-title > *').css( 'opacity', 1 );
// if autoplay is true
if( _self.options.autoplay ) {
_self._startSlideshow();
}
// initialize the events
_self._initEvents();
});
},
_preloadImages : function() {
// preloads all the large images
var _self = this,
loaded = 0;
return $.Deferred(
function(dfd) {
_self.$images.each( function( i ) {
$('<img/>').load( function() {
if( ++loaded === _self.itemsCount ) {
dfd.resolve();
}
}).attr( 'src', $(this).attr('src') );
});
}
).promise();
},
_setImagesSize : function() {
// save ei-slider's width
this.elWidth = this.$el.width();
var _self = this;
this.$images.each( function( i ) {
var $img = $(this);
imgDim = _self._getImageDim( $img.attr('src') );
$img.css({
width : imgDim.width,
height : imgDim.height,
marginLeft : imgDim.left,
marginTop : imgDim.top
});
});
},
_getImageDim : function( src ) {
var $img = new Image();
$img.src = src;
var c_w = this.elWidth,
c_h = this.$el.height(),
r_w = c_h / c_w,
i_w = $img.width,
i_h = $img.height,
r_i = i_h / i_w,
new_w, new_h, new_left, new_top;
if( r_w > r_i ) {
new_h = c_h;
new_w = c_h / r_i;
}
else {
new_h = c_w * r_i;
new_w = c_w;
}
return {
width : new_w,
height : new_h,
left : ( c_w - new_w ) / 2,
top : ( c_h - new_h ) / 2
};
},
_initThumbs : function() {
// set the max-width of the slider elements to the one set in the plugin's options
// also, the width of each slider element will be 100% / total number of elements
this.$sliderElems.css({
'max-width' : this.options.thumbMaxWidth + 'px',
'width' : 100 / this.itemsCount + '%'
});
// set the max-width of the slider and show it
this.$sliderthumbs.css( 'max-width', this.options.thumbMaxWidth * this.itemsCount + 'px' ).show();
},
_startSlideshow : function() {
var _self = this;
this.slideshow = setTimeout( function() {
var pos;
( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1;
_self._slideTo( pos );
if( _self.options.autoplay ) {
_self._startSlideshow();
}
}, this.options.slideshow_interval);
},
// shows the clicked thumb's slide
_slideTo : function( pos ) {
// return if clicking the same element or if currently animating
if( pos === this.current || this.isAnimating )
return false;
this.isAnimating = true;
var $currentSlide = this.$imgItems.eq( this.current ),
$nextSlide = this.$imgItems.eq( pos ),
_self = this,
preCSS = {zIndex : 10},
animCSS = {opacity : 1};
// new slide will slide in from left or right side
if( this.options.animation === 'sides' ) {
preCSS.left = ( pos > this.current ) ? -1 * this.elWidth : this.elWidth;
animCSS.left = 0;
}
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
$.when(
// fade out current titles
$currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() {
// reset style
$(this).show().css( 'opacity', 0 );
}),
// animate next slide in
$nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ),
// "sliding div" moves to new position
this.$sliderElem.stop().animate({
left : this.$thumbs.eq( pos ).position().left
}, this.options.speed )
).done( function() {
// reset values
$currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 );
_self.current = pos;
_self.isAnimating = false;
});
},
_initEvents : function() {
var _self = this;
// window resize
$(window).on( 'smartresize.eislideshow', function( event ) {
// resize the images
_self._setImagesSize();
// reset position of thumbs sliding div
_self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left );
});
// click the thumbs
this.$thumbs.on( 'click.eislideshow', function( event ) {
if( _self.options.autoplay ) {
clearTimeout( _self.slideshow );
_self.options.autoplay = false;
}
var $thumb = $(this),
idx = $thumb.index() - 1; // exclude sliding div
_self._slideTo( idx );
return false;
});
}
};
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
$.fn.eislideshow = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
logError( "cannot call methods on eislideshow prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for eislideshow instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
$.data( this, 'eislideshow', new $.Slideshow( options, this ) );
}
});
}
return this;
};
})( window, jQuery );
My slider in action
The jQuery code of your plugin, the first snipped you attached, is looking for each element (h2 and h3) and animating them one after the other.
Just add the same code for the h4 afterwards, and apply any changes you want to the pixel values.
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 },
this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 },
this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h4')
.css( 'margin-right', -150 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 },
this.options.titlespeed, this.options.titleeasing )
As you can see, I told it to set margin-right to -150px, to apply the same difference between h3 and h4 as there is between h2 and h3, but you can choose the value that suits your needs best.
Related
I would like to remove the dotted bottom border from the text linked to the tool tip. This code is being used within Qualtrics to modify a survey for a client. Would it be best to edit the text decoration in this case? I need it to be stable across browsers. Admittedly I am not trained in coding - just self taught, so please provide context to your answers so that I can either look up more information regarding your directions or parse it together with what I already know.
jQuery( function()
{
var targets = jQuery( '[rel~=tooltip]' ),
target = false,
tooltip = false,
title = false;
targets.bind( 'mouseenter', function()
{
target = jQuery( this );
tip = target.attr( 'title' );
tooltip = jQuery( '<div id="tooltip"></div>' );
if( !tip || tip == '' )
return false;
target.removeAttr( 'title' );
tooltip.css( 'opacity', 0 )
.html( tip )
.appendTo( 'body' );
var init_tooltip = function()
{
if( jQuery( window ).width() < tooltip.outerWidth() * 1.5 )
tooltip.css( 'max-width', jQuery( window ).width() / 2 );
else
tooltip.css( 'max-width', 340 );
var pos_left = target.offset().left + ( target.outerWidth() / 2 ) - ( tooltip.outerWidth() / 2 ),
pos_top = target.offset().top - tooltip.outerHeight() - 20;
if( pos_left < 0 )
{
pos_left = target.offset().left + target.outerWidth() / 2 - 20;
tooltip.addClass( 'left' );
}
else
tooltip.removeClass( 'left' );
if( pos_left + tooltip.outerWidth() > jQuery( window ).width() )
{
pos_left = target.offset().left - tooltip.outerWidth() + target.outerWidth() / 2 + 20;
tooltip.addClass( 'right' );
}
else
tooltip.removeClass( 'right' );
if( pos_top < 0 )
{
var pos_top = target.offset().top + target.outerHeight();
tooltip.addClass( 'top' );
}
else
tooltip.removeClass( 'top' );
tooltip.css( { left: pos_left, top: pos_top } )
.animate( { top: '+=10', opacity: 1 }, 50 );
};
init_tooltip();
jQuery( window ).resize( init_tooltip );
var remove_tooltip = function()
{
tooltip.animate( { top: '-=10', opacity: 0 }, 50, function()
{
jQuery( this ).remove();
});
target.attr( 'title', tip );
};
target.bind( 'mouseleave', remove_tooltip );
tooltip.bind( 'click', remove_tooltip );
});
});
#tooltip
{
text-align: center;
color: #FFFFFF;
font-family: sans-serif;
background: #008CAE;
position: absolute;
z-index: 100;
padding: 15px;
}
#tooltip:after /* triangle decoration */
{
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #111;
content: '';
position: absolute;
left: 50%;
bottom: -10px;
margin-left: -10px;
}
#tooltip.top:after
{
border-top-color: transparent;
border-bottom: 10px solid #111;
top: -20px;
bottom: auto;
}
#tooltip.left:after
{
left: 10px;
margin: 0;
}
#tooltip.right:after
{
right: 10px;
left: auto;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<abbr rel="tooltip" title="The curricula available for teacher use provides guidance for how to differentiate lessons, activities, and assessments; includes the principles of Universal Design for Learning; and teachers are trained in implementation of the curriculum.">General education teachers have access to a curriculum that promotes differentiated instruction for all students. </abbr>
Text decoration seems like the way to go either by targeting the tag or by adding a class and targeting that:
abbr {
text-decoration: none;
}
Might consider the accessibility considerations too while you're implementing this. It's usually a good idea to give users an indication of some kind when something is interactive. I wonder if removing the underline will remove any indication that there is a tooltip available?
I am using a polaroid image gallery plugin. The way it works, the polaroid images are scattered in a div and it has some circle nav buttons at the bottom that can be clicked to make the selected image active and moves it to the middle.
Instead of having circle nav buttons for selecting each image, I wanted to use prev/next buttons (this way it won't show 20+ circle nav icons when the gallery has more than 20 photos).
I was able to add some prev/next buttons and get them working, but there is one slight issue I cannot figure out. When the gallery loads, if you select the prev/next buttons, the gallery works as intended, it will switch the photos as necessary when the buttons are clicked. However, if the user clicks anywhere in the gallery (not on the buttons) it will shuffle all of the photos (it should not shuffle), then once a user does this, the prev/next buttons no longer work until the page is refreshed.
I am still learning jQuery/js and I cannot figure out what is causing this. I need to restrict the shuffling and selecting of the photos only when the prev/next buttons are selected because if a user accidentally clicks anywhere in the gallery, the buttons break.
I created a jsfiddle here.
The html is pretty straight forward, here is an example with the prev/next buttons I added:
<section id="photostack-1" class="photostack photostack-start">
<div>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/5.jpg" alt="img05"/>
<figcaption>
<h2 class="photostack-title">Speed Racer</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/2.jpg" alt="img02"/>
<figcaption>
<h2 class="photostack-title">Happy Days</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/3.jpg" alt="img03"/>
<figcaption>
<h2 class="photostack-title">Beautywood</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/1.jpg" alt="img01"/>
<figcaption>
<h2 class="photostack-title">Serenity Beach</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/4.jpg" alt="img04"/>
<figcaption>
<h2 class="photostack-title">Heaven of time</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/6.jpg" alt="img06"/>
<figcaption>
<h2 class="photostack-title">Forever this</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/7.jpg" alt="img07"/>
<figcaption>
<h2 class="photostack-title">Lovely Green</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/8.jpg" alt="img08"/>
<figcaption>
<h2 class="photostack-title">Wonderful</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/9.jpg" alt="img09"/>
<figcaption>
<h2 class="photostack-title">Love Addict</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/10.jpg" alt="img10"/>
<figcaption>
<h2 class="photostack-title">Friendship</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/11.jpg" alt="img11"/>
<figcaption>
<h2 class="photostack-title">White Nights</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/12.jpg" alt="img12"/>
<figcaption>
<h2 class="photostack-title">Serendipity</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/13.jpg" alt="img13"/>
<figcaption>
<h2 class="photostack-title">Pure Soul</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/14.jpg" alt="img14"/>
<figcaption>
<h2 class="photostack-title">Winds of Peace</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/15.jpg" alt="img15"/>
<figcaption>
<h2 class="photostack-title">Shades of blue</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/16.jpg" alt="img16"/>
<figcaption>
<h2 class="photostack-title">Lightness</h2>
</figcaption>
</figure>
</div>
<!-- Next and Previous controls -->
<div id="imageControls">
<button id="leftArrowGallery" class="btnGallery"><i class="fa fa-chevron-left"></i></button>
<button id="rightArrowGallery" class="btnGallery"><i class="fa fa-chevron-right"></i></button>
</div>
</section>
The custom jQuery used to add the prev/next buttons and remove the circle nav icons is:
var ps = new Photostack( document.getElementById( 'photostack-1' ), {});
$("#leftArrowGallery").prependTo($(".photostack > nav"));
$("#rightArrowGallery").appendTo($(".photostack > nav"));
$("#leftArrowGallery").on("click", function () {
ps.navigate('prev');
});
$("#rightArrowGallery").on("click", function () {
ps.navigate('next');
});
$(".photostack > nav > span").each(function(){ $(this).remove(); });
You can view all of the js for the plugin in the jsfiddle.
Screenshot example of original gallery with circle nav icons:
Screenshot example of gallery with custom prev/next buttons added:
Again, the buttons are working correctly, I just need to prevent when someone clicks anywhere in the gallery, it shuffles the images then the prev/next buttons break and no longer work until the page is refreshed.
Thank you for your help!
I read your code and I found out that the biggest problem when you put photostack-start class is that every time you click on photostack stage you schuffle your photos twice: once in _photoShow function and once in open function (open function is triggered every time). To resolve your problem, a solution could be to stop one schuffled action. To do this I created a variable and I put it in open function:
if( this.open ) {
return false;
}
this.open = true;
Now, _open function is triggered only once (when you click on button "view gallery") and after that only _photoShow works so your code works finally as you want.
BE CAREFUL: In this example I removed some pics 'cause I have a character limit here (30000), but the code will work anyway also with more pics.
A fiddle with more pics: https://jsfiddle.net/m46cxkhg/217/ (tested with Chrome and Firefox)
;( function( window ) {
'use strict';
Modernizr.addTest('csstransformspreserve3d', function () {
var prop = Modernizr.prefixed('transformStyle');
var val = 'preserve-3d';
var computedStyle;
if(!prop) return false;
prop = prop.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
Modernizr.testStyles('#modernizr{' + prop + ':' + val + ';}', function (el, rule) {
computedStyle = window.getComputedStyle ? getComputedStyle(el, null).getPropertyValue(prop) : '';
});
return (computedStyle === val);
});
var support = {
transitions : Modernizr.csstransitions,
preserve3d : Modernizr.csstransformspreserve3d
},
transEndEventNames = {
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend',
'OTransition': 'oTransitionEnd',
'msTransition': 'MSTransitionEnd',
'transition': 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ];
function extend( a, b ) {
for( var key in b ) {
if( b.hasOwnProperty( key ) ) {
a[key] = b[key];
}
}
return a;
}
function shuffleMArray( marray ) {
var arr = [], marrlen = marray.length, inArrLen = marray[0].length;
for(var i = 0; i < marrlen; i++) {
arr = arr.concat( marray[i] );
}
arr = shuffleArr( arr );
var newmarr = [], pos = 0;
for( var j = 0; j < marrlen; j++ ) {
var tmparr = [];
for( var k = 0; k < inArrLen; k++ ) {
tmparr.push( arr[ pos ] );
pos++;
}
newmarr.push( tmparr );
}
return newmarr;
}
function shuffleArr( array ) {
var m = array.length, t, i;
while (m) {
i = Math.floor(Math.random() * m--);
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
function Photostack( el, options ) {
this.el = el;
this.inner = this.el.querySelector( 'div' );
this.allItems = [].slice.call( this.inner.children );
this.allItemsCount = this.allItems.length;
if( !this.allItemsCount ) return;
this.items = [].slice.call( this.inner.querySelectorAll( 'figure:not([data-dummy])' ) );
this.itemsCount = this.items.length;
this.options = extend( {}, this.options );
extend( this.options, options );
this.current = this.options.start;
this._init();
var ps = this;
return {
showPhoto: function(idx) {
ps._showPhoto.call(ps, idx);
},
open: function() {
ps._open.call(ps, true);
},
navigate: function(dir) {
ps._navigate.call(ps, dir);
},
}
}
Photostack.prototype.options = {
start: 0,
showNavigation: true,
afterInit: null,
afterShowPhoto: null,
afterNavigate: null
};
Photostack.prototype._init = function() {
this.currentItem = this.items[ this.current ];
if(this.options.showNavigation) {
this._addNavigation();
}
this._getSizes();
this._initEvents();
if(this.options.afterInit) {
this.options.afterInit(this);
}
}
Photostack.prototype._addNavigation = function() {
// add nav dots
this.nav = document.createElement( 'nav' )
var inner = '';
for( var i = 0; i < this.itemsCount; ++i ) {
inner += '<span></span>';
}
this.nav.innerHTML = inner;
this.el.appendChild( this.nav );
this.navDots = [].slice.call( this.nav.children );
}
Photostack.prototype._open = function( beforeStep ) {
/* I added this */
if( this.open ) {
return false;
}
this.open = true;
/* End of change */
var self = this,
el = this.el;
var setTransition = function() {
if( support.transitions ) {
classie.addClass( el, 'photostack-transition' );
}
}
if( beforeStep ) {
el.removeEventListener( 'click', open );
classie.removeClass( el, 'photostack-start' );
setTransition();
}
else {
self.openDefault = true;
setTimeout( setTransition, 25 );
}
self.started = true;
self._showPhoto( self.current );
};
Photostack.prototype._initEvents = function() {
if(this.options.clickToFlip == 'true')
{
this.items.forEach(function(img, idx){
img.addEventListener('click', function(event){
event.preventDefault();
if( idx === self.current ) {
self._rotateItem();
}
})
});
}
var self = this,
beforeStep = classie.hasClass( this.el, 'photostack-start' );
if( beforeStep ) {
this._shuffle();
this.el.addEventListener( 'click', function() {
self._open(beforeStep);
});
}
else {
this._open(beforeStep);
}
if(this.options.showNavigation) {
this.navDots.forEach( function( dot, idx ) {
dot.addEventListener( 'click', function() {
if( idx === self.current ) {
self._rotateItem();
}
else {
// if the photo is flipped then rotate it back before shuffling again
var callback = function() { self._showPhoto( idx ); }
if( self.flipped ) {
self._rotateItem( callback );
}
else {
callback();
}
}
} );
} );
}
window.addEventListener( 'resize', function() { self._resizeHandler(); } );
}
Photostack.prototype._resizeHandler = function() {
var self = this;
function delayed() {
self._resize();
self._resizeTimeout = null;
}
if ( this._resizeTimeout ) {
clearTimeout( this._resizeTimeout );
}
this._resizeTimeout = setTimeout( delayed, 100 );
}
Photostack.prototype._resize = function() {
var self = this, callback = function() { self._shuffle( true ); }
this._getSizes();
if( this.started && this.flipped ) {
this._rotateItem( callback );
}
else {
callback();
}
}
Photostack.prototype._showPhoto = function( pos ) {
if( this.isShuffling ) {
return false;
}
this.isShuffling = true;
// if there is something behind..
if( classie.hasClass( this.currentItem, 'photostack-flip' ) ) {
this._removeItemPerspective();
if(this.options.showNavigation) {
classie.removeClass( this.navDots[ this.current ], 'flippable' );
}
}
if(this.options.showNavigation) {
classie.removeClass( this.navDots[ this.current ], 'current' );
}
classie.removeClass( this.currentItem, 'photostack-current' );
// change current
this.current = pos;
this.currentItem = this.items[ this.current ];
if(this.options.showNavigation) {
classie.addClass( this.navDots[ this.current ], 'current' );
}
// if there is something behind..
if( this.options.showNavigation && this.currentItem.querySelector( '.photostack-back' ) ) {
// nav dot gets class flippable
classie.addClass( this.navDots[ pos ], 'flippable' );
}
// shuffle a bit
this._shuffle();
if(this.options.afterShowPhoto) {
this.options.afterShowPhoto(this);
}
}
// display items (randomly)
Photostack.prototype._shuffle = function( resize ) {
var iter = resize ? 1 : this.currentItem.getAttribute( 'data-shuffle-iteration' ) || 1;
if( iter <= 0 || !this.started || this.openDefault ) { iter = 1; }
// first item is open by default
if( this.openDefault ) {
// change transform-origin
classie.addClass( this.currentItem, 'photostack-flip' );
this.openDefault = false;
this.isShuffling = false;
}
var overlapFactor = .5,
// lines & columns
lines = Math.ceil(this.sizes.inner.width / (this.sizes.item.width * overlapFactor) ),
columns = Math.ceil(this.sizes.inner.height / (this.sizes.item.height * overlapFactor) ),
// since we are rounding up the previous calcs we need to know how much more we are adding to the calcs for both x and y axis
addX = lines * this.sizes.item.width * overlapFactor + this.sizes.item.width/2 - this.sizes.inner.width,
addY = columns * this.sizes.item.height * overlapFactor + this.sizes.item.height/2 - this.sizes.inner.height,
// we will want to center the grid
extraX = addX / 2,
extraY = addY / 2,
// max and min rotation angles
maxrot = 35, minrot = -35,
self = this,
// translate/rotate items
moveItems = function() {
--iter;
// create a "grid" of possible positions
var grid = [];
// populate the positions grid
for( var i = 0; i < columns; ++i ) {
var col = grid[ i ] = [];
for( var j = 0; j < lines; ++j ) {
var xVal = j * (self.sizes.item.width * overlapFactor) - extraX,
yVal = i * (self.sizes.item.height * overlapFactor) - extraY,
olx = 0, oly = 0;
if( self.started && iter === 0 ) {
var ol = self._isOverlapping( { x : xVal, y : yVal } );
if( ol.overlapping ) {
olx = ol.noOverlap.x;
oly = ol.noOverlap.y;
var r = Math.floor( Math.random() * 3 );
switch(r) {
case 0 : olx = 0; break;
case 1 : oly = 0; break;
}
}
}
col[ j ] = { x : xVal + olx, y : yVal + oly };
}
}
// shuffle
grid = shuffleMArray(grid);
var l = 0, c = 0, cntItemsAnim = 0;
self.allItems.forEach( function( item, i ) {
// pick a random item from the grid
if( l === lines - 1 ) {
c = c === columns - 1 ? 0 : c + 1;
l = 1;
}
else {
++l
}
var randXPos = Math.floor( Math.random() * lines ),
randYPos = Math.floor( Math.random() * columns ),
gridVal = grid[c][l-1],
translation = { x : gridVal.x, y : gridVal.y },
onEndTransitionFn = function() {
++cntItemsAnim;
if( support.transitions ) {
this.removeEventListener( transEndEventName, onEndTransitionFn );
}
if( cntItemsAnim === self.allItemsCount ) {
if( iter > 0 ) {
moveItems.call();
}
else {
// change transform-origin
classie.addClass( self.currentItem, 'photostack-flip' );
// all done..
self.isShuffling = false;
if( typeof self.options.callback === 'function' ) {
self.options.callback( self.currentItem );
}
}
}
};
if(self.items.indexOf(item) === self.current && self.started && iter === 0) {
self.currentItem.style.WebkitTransform = 'translate(' + self.centerItem.x + 'px,' + self.centerItem.y + 'px) rotate(0deg)';
self.currentItem.style.msTransform = 'translate(' + self.centerItem.x + 'px,' + self.centerItem.y + 'px) rotate(0deg)';
self.currentItem.style.transform = 'translate(' + self.centerItem.x + 'px,' + self.centerItem.y + 'px) rotate(0deg)';
// if there is something behind..
if( self.currentItem.querySelector( '.photostack-back' ) ) {
self._addItemPerspective();
}
classie.addClass( self.currentItem, 'photostack-current' );
}
else {
item.style.WebkitTransform = 'translate(' + translation.x + 'px,' + translation.y + 'px) rotate(' + Math.floor( Math.random() * (maxrot - minrot + 1) + minrot ) + 'deg)';
item.style.msTransform = 'translate(' + translation.x + 'px,' + translation.y + 'px) rotate(' + Math.floor( Math.random() * (maxrot - minrot + 1) + minrot ) + 'deg)';
item.style.transform = 'translate(' + translation.x + 'px,' + translation.y + 'px) rotate(' + Math.floor( Math.random() * (maxrot - minrot + 1) + minrot ) + 'deg)';
}
if( self.started ) {
if( support.transitions ) {
item.addEventListener( transEndEventName, onEndTransitionFn );
}
else {
onEndTransitionFn();
}
}
} );
};
moveItems.call();
}
Photostack.prototype._navigate = function(dir) {
var current = this.current,
itemsCount = this.itemsCount,
lastItem = itemsCount - 1,
idx = 0;
if(dir == 'next') {
idx = current < lastItem ? current + 1 : 0
} else if(dir == 'prev') {
idx = current > 0 ? current - 1 : lastItem;
}
this._showPhoto(idx);
if(this.options.afterNavigate) {
this.options.afterNavigate(this);
}
}
Photostack.prototype._getSizes = function() {
this.sizes = {
inner : { width : this.inner.offsetWidth, height : this.inner.offsetHeight },
item : { width : this.currentItem.offsetWidth, height : this.currentItem.offsetHeight }
};
// translation values to center an item
this.centerItem = { x : this.sizes.inner.width / 2 - this.sizes.item.width / 2, y : this.sizes.inner.height / 2 - this.sizes.item.height / 2 };
}
Photostack.prototype._isOverlapping = function( itemVal ) {
var dxArea = this.sizes.item.width + this.sizes.item.width / 3, // adding some extra avoids any rotated item to touch the central area
dyArea = this.sizes.item.height + this.sizes.item.height / 3,
areaVal = { x : this.sizes.inner.width / 2 - dxArea / 2, y : this.sizes.inner.height / 2 - dyArea / 2 },
dxItem = this.sizes.item.width,
dyItem = this.sizes.item.height;
if( !(( itemVal.x + dxItem ) < areaVal.x ||
itemVal.x > ( areaVal.x + dxArea ) ||
( itemVal.y + dyItem ) < areaVal.y ||
itemVal.y > ( areaVal.y + dyArea )) ) {
// how much to move so it does not overlap?
// move left / or move right
var left = Math.random() < 0.5,
randExtraX = Math.floor( Math.random() * (dxItem/4 + 1) ),
randExtraY = Math.floor( Math.random() * (dyItem/4 + 1) ),
noOverlapX = left ? (itemVal.x - areaVal.x + dxItem) * -1 - randExtraX : (areaVal.x + dxArea) - (itemVal.x + dxItem) + dxItem + randExtraX,
noOverlapY = left ? (itemVal.y - areaVal.y + dyItem) * -1 - randExtraY : (areaVal.y + dyArea) - (itemVal.y + dyItem) + dyItem + randExtraY;
return {
overlapping : true,
noOverlap : { x : noOverlapX, y : noOverlapY }
}
}
return {
overlapping : false
}
}
Photostack.prototype._addItemPerspective = function() {
classie.addClass( this.el, 'photostack-perspective' );
}
Photostack.prototype._removeItemPerspective = function() {
classie.removeClass( this.el, 'photostack-perspective' );
classie.removeClass( this.currentItem, 'photostack-flip' );
}
Photostack.prototype._rotateItem = function( callback ) {
if( classie.hasClass( this.el, 'photostack-perspective' ) && !this.isRotating && !this.isShuffling ) {
this.isRotating = true;
var self = this, onEndTransitionFn = function() {
if( support.transitions && support.preserve3d ) {
this.removeEventListener( transEndEventName, onEndTransitionFn );
}
self.isRotating = false;
if( typeof callback === 'function' ) {
callback();
}
};
if( this.flipped ) {
if(this.options.showNavigation) {
classie.removeClass( this.navDots[ this.current ], 'flip' );
}
if( support.preserve3d ) {
this.currentItem.style.WebkitTransform = 'translate(' + this.centerItem.x + 'px,' + this.centerItem.y + 'px) rotateY(0deg)';
this.currentItem.style.transform = 'translate(' + this.centerItem.x + 'px,' + this.centerItem.y + 'px) rotateY(0deg)';
}
else {
classie.removeClass( this.currentItem, 'photostack-showback' );
}
}
else {
if(this.options.showNavigation) {
classie.addClass( this.navDots[ this.current ], 'flip' );
}
if( support.preserve3d ) {
this.currentItem.style.WebkitTransform = 'translate(' + this.centerItem.x + 'px,' + this.centerItem.y + 'px) translate(' + this.sizes.item.width + 'px) rotateY(-179.9deg)';
this.currentItem.style.transform = 'translate(' + this.centerItem.x + 'px,' + this.centerItem.y + 'px) translate(' + this.sizes.item.width + 'px) rotateY(-179.9deg)';
}
else {
classie.addClass( this.currentItem, 'photostack-showback' );
}
}
this.flipped = !this.flipped;
if( support.transitions && support.preserve3d ) {
this.currentItem.addEventListener( transEndEventName, onEndTransitionFn );
}
else {
onEndTransitionFn();
}
}
}
// add to global namespace
window.Photostack = Photostack;
})( window );
var ps = new Photostack( document.getElementById( 'photostack-1' ), {});
$("#leftArrowGallery").prependTo($(".photostack > nav"));
$("#rightArrowGallery").appendTo($(".photostack > nav"));
$("#leftArrowGallery").on("click", function () {
ps.navigate('prev');
});
$("#rightArrowGallery").on("click", function () {
ps.navigate('next');
});
$(".photostack > nav > span").each(function(){ $(this).remove(); });
.photostack {
background: #ddd;
position: relative;
text-align: center;
overflow: hidden;
}
.js .photostack {
height: 580px;
}
.photostack-start {
cursor: pointer;
}
.photostack > div {
width: 100%;
height: 100%;
margin: 0 auto;
}
.photostack figure {
width: 320px;
height: 360px;
position: relative;
display: inline-block;
background: #fff;
padding: 40px;
text-align: center;
margin: 5px;
}
.js .photostack figure {
position: absolute;
display: block;
margin: 0;
}
.photostack figcaption h2 {
margin: 20px 0 0 0;
color: #a7a0a2;
font-size: 16px;
}
.photostack-img {
outline: none;
width: 240px;
height: 240px;
background: #f9f9f9;
}
.photostack-back {
display: none;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fff;
font-family: "Give You Glory", cursive;
color: #a7a0a2;
padding: 50px 40px;
text-align: left;
font-size: 22px;
line-height: 1.25;
z-index: 1;
}
.photostack-back p {
margin: 0;
}
.photostack-back p span {
text-decoration: line-through;
}
.photostack nav {
position: absolute;
width: 100%;
bottom: 30px;
z-index: 90;
text-align: center;
left: 0;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.photostack-start nav {
opacity: 0;
}
.photostack nav span {
position: relative;
display: inline-block;
margin: 0 5px;
width: 30px;
height: 30px;
cursor: pointer;
background: #aaa;
border-radius: 50%;
text-align: center;
-webkit-transition: -webkit-transform 0.6s ease-in-out, background 0.3s;
transition: transform 0.6s ease-in-out, background 0.3s;
-webkit-transform: scale(0.48);
transform: scale(0.48);
}
.photostack nav span:last-child {
margin-right: 0;
}
.photostack nav span::after {
content: "\e600";
font-family: 'icons';
font-size: 80%;
speak: none;
display: inline-block;
vertical-align: top;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 30px;
color: #fff;
opacity: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.photostack nav span.current {
background: #888;
-webkit-transform: scale(1);
transform: scale(1);
}
.photostack nav span.current.flip {
-webkit-transform: scale(1) rotateY(-180deg) translateZ(-1px);
transform: scale(1) rotateY(-180deg) translateZ(-1px);
background: #555;
}
.photostack nav span.flippable::after {
opacity: 1;
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
.js .photostack::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
top: 0;
left: 0;
z-index: 100;
-webkit-transition: opacity 0.3s, visibility 0s 0.3s;
transition: opacity 0.3s, visibility 0s 0.3s;
}
.js .photostack-start::before {
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.js .photostack::after {
content: 'View Gallery';
font-weight: 400;
position: absolute;
border: 3px solid #fff;
text-align: center;
white-space: nowrap;
left: 50%;
top: 50%;
-webkit-transform: translateY(-50%) translateX(-50%);
transform: translateY(-50%) translateX(-50%);
padding: 10px 20px;
color: #fff;
text-transform: uppercase;
letter-spacing: 1px;
cursor: pointer;
z-index: 101;
}
.js .photostack::before,
.js .photostack::after {
opacity: 0;
visibility: hidden;
}
.js .photostack-start::before,
.js .photostack-start:hover::after,
.touch .photostack-start::after {
opacity: 1;
visibility: visible;
}
.photostack figure::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
visibility: visible;
opacity: 1;
background: rgba(0,0,0,0.05);
-webkit-transition: opacity 0.6s;
transition: opacity 0.6s;
}
figure.photostack-current::after {
-webkit-transition: opacity 0.6s, visibility 0s 0.6s;
transition: opacity 0.6s, visibility 0s 0.6s;
opacity: 0;
visibility: hidden;
}
.photostack-transition figure {
-webkit-transition: -webkit-transform 0.6s ease-in-out;
transition: transform 0.6s ease-in-out;
}
.photostack-perspective {
-webkit-perspective: 1800px;
perspective: 1800px;
}
.photostack-perspective > div,
.photostack-perspective figure {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.photostack-perspective figure,
.photostack-perspective figure div {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.photostack-perspective figure.photostack-flip {
-webkit-transform-origin: 0% 50%;
transform-origin: 0% 50%;
}
.csstransformspreserve3d figure.photostack-flip .photostack-back {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
display: block;
}
.no-csstransformspreserve3d figure.photostack-showback .photostack-back {
display: block;
}
.no-js .photostack figure {
box-shadow: -2px 2px 0 rgba(0,0,0,0.05);
}
.no-js .photostack figure::after {
display: none;
}
.no-js .photostack figure:nth-child(3n) {
-webkit-transform: translateX(-10%) rotate(5deg);
transform: translateX(-10%) rotate(5deg);
}
.no-js .photostack figure:nth-child(3n-2) {
-webkit-transform: translateY(10%) rotate(-3deg);
transform: translateY(10%) rotate(-3deg);
}
#photostack-1 nav span.current {
background: #888;
-webkit-transform: scale(0.61);
transform: scale(0.61);
}
#leftArrowGallery {
margin-right: 10px;
}
#rightArrowGallery {
margin-left: 10px;
}
#rightArrowGallery i {
padding-left: 5px;
}
#leftArrowGallery i {
padding-right: 5px;
}
.btnGallery {
background-color: #da2c33;
border: medium none;
color: #FFFFFF;
cursor: pointer;
display: inline-block;
font: 12px;
padding: 3px 6px;
text-decoration: none;
white-space: nowrap;
border-radius: 5px;
}
.btnGallery:hover {
background-color: #b20a11;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" media="all" type="text/css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="photostack-1" class="photostack photostack-start">
<div>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/5.jpg" alt="img05"/>
<figcaption>
<h2 class="photostack-title">Speed Racer</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/2.jpg" alt="img02"/>
<figcaption>
<h2 class="photostack-title">Happy Days</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/3.jpg" alt="img03"/>
<figcaption>
<h2 class="photostack-title">Beautywood</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/1.jpg" alt="img01"/>
<figcaption>
<h2 class="photostack-title">Serenity Beach</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/4.jpg" alt="img04"/>
<figcaption>
<h2 class="photostack-title">Heaven of time</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/6.jpg" alt="img06"/>
<figcaption>
<h2 class="photostack-title">Forever this</h2>
</figcaption>
</figure>
<figure>
<img src="https://tympanus.net/Development/ScatteredPolaroidsGallery/img/7.jpg" alt="img07"/>
<figcaption>
<h2 class="photostack-title">Lovely Green</h2>
</figcaption>
</figure>
</div>
<div id="imageControls">
<button id="leftArrowGallery" class="btnGallery"><i class="fa fa-chevron-left"></i></button>
<button id="rightArrowGallery" class="btnGallery"><i class="fa fa-chevron-right"></i></button>
</div>
</section>
I have a project handling a library of excel files. To make it easilier for the users to visually scan them, I would like to generate preview thumbnail images of their content. Google drive does this (screenshot below) but I have no idea how.
Any ideas/suggestions on how this could be done (without using the drive API) ?
I guess this is what you need
http://github.com/lonekorean/mini-preview
DEMO
/*
* MiniPreview v0.9
*
* #author Will Boyd
* #github http://github.com/lonekorean/mini-preview
*/
(function($) {
var PREFIX = 'mini-preview';
// implemented as a jQuery plugin
$.fn.miniPreview = function(options) {
return this.each(function() {
var $this = $(this);
var miniPreview = $this.data(PREFIX);
if (miniPreview) {
miniPreview.destroy();
}
miniPreview = new MiniPreview($this, options);
miniPreview.generate();
$this.data(PREFIX, miniPreview);
});
};
var MiniPreview = function($el, options) {
this.$el = $el;
this.$el.addClass(PREFIX + '-anchor');
this.options = $.extend({}, this.defaultOptions, options);
this.counter = MiniPreview.prototype.sharedCounter++;
};
MiniPreview.prototype = {
sharedCounter: 0,
defaultOptions: {
width: 256,
height: 144,
scale: .25,
prefetch: 'pageload'
},
generate: function() {
this.createElements();
this.setPrefetch();
},
createElements: function() {
var $wrapper = $('<div>', { class: PREFIX + '-wrapper' });
var $loading = $('<div>', { class: PREFIX + '-loading' });
var $frame = $('<iframe>', { class: PREFIX + '-frame' });
var $cover = $('<div>', { class: PREFIX + '-cover' });
$wrapper.appendTo(this.$el).append($loading, $frame, $cover);
// sizing
$wrapper.css({
width: this.options.width + 'px',
height: this.options.height + 'px'
});
// scaling
var inversePercent = 100 / this.options.scale;
$frame.css({
width: inversePercent + '%',
height: inversePercent + '%',
transform: 'scale(' + this.options.scale + ')'
});
// positioning
var fontSize = parseInt(this.$el.css('font-size').replace('px', ''), 10)
var top = (this.$el.height() + fontSize) / 2;
var left = (this.$el.width() - $wrapper.outerWidth()) / 2;
$wrapper.css({
top: top + 'px',
left: left + 'px'
});
},
setPrefetch: function() {
switch (this.options.prefetch) {
case 'pageload':
this.loadPreview();
break;
case 'parenthover':
this.$el.parent().one(this.getNamespacedEvent('mouseenter'),
this.loadPreview.bind(this));
break;
case 'none':
this.$el.one(this.getNamespacedEvent('mouseenter'),
this.loadPreview.bind(this));
break;
default:
throw 'Prefetch setting not recognized: ' + this.options.prefetch;
break;
}
},
loadPreview: function() {
this.$el.find('.' + PREFIX + '-frame')
.attr('src', this.$el.attr('href'))
.on('load', function() {
// some sites don't set their background color
$(this).css('background-color', '#fff');
});
},
getNamespacedEvent: function(event) {
return event + '.' + PREFIX + '_' + this.counter;
},
destroy: function() {
this.$el.removeClass(PREFIX + '-anchor');
this.$el.parent().off(this.getNamespacedEvent('mouseenter'));
this.$el.off(this.getNamespacedEvent('mouseenter'));
this.$el.find('.' + PREFIX + '-wrapper').remove();
}
};
})(jQuery);
.mini-preview-anchor {
display: inline-block;
position: relative;
white-space: nowrap;
}
.mini-preview-wrapper {
-moz-box-sizing: content-box;
box-sizing: content-box;
position: absolute;
overflow: hidden;
z-index: -1;
opacity: 0;
margin-top: -4px;
border: solid 1px #000;
box-shadow: 4px 4px 6px rgba(0, 0, 0, .3);
transition: z-index steps(1) .3s, opacity .3s, margin-top .3s;
}
.mini-preview-anchor:hover .mini-preview-wrapper {
z-index: 2;
opacity: 1;
margin-top: 6px;
transition: opacity .3s, margin-top .3s;
}
.mini-preview-loading, .mini-preview-cover {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
.mini-preview-loading {
display: table;
height: 100%;
width: 100%;
font-size: 1.25rem;
text-align: center;
color: #f5ead4;
background-color: #59513f;
}
.mini-preview-loading::before {
content: 'Loading...';
display: table-cell;
text-align: center;
vertical-align: middle;
}
.mini-preview-cover {
background-color: rgba(0, 0, 0, 0); /* IE fix */
}
.mini-preview-frame {
border: none;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>MiniPreview Demo</title>
<link href="http://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet">
<style>
body {
height: 100%;
margin: 0;
padding: 0 10% 40px;
font-size: 2rem;
line-height: 1.5;
font-family: 'Roboto Slab', sans-serif;
text-align: justify;
color: #59513f;
background-color: #f5ead4;
}
a {
color: #537f7c;
}
.break {
text-align: center;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<!-- MiniPreview stuff here -->
<link href="./jquery.minipreview.css" rel="stylesheet">
<script src="./jquery.minipreview.js"></script>
<script>
$(function() {
$('#p1 a').miniPreview({ prefetch: 'pageload' });
$('#p2 a').miniPreview({ prefetch: 'parenthover' });
$('#p3 a').miniPreview({ prefetch: 'none' });
});
</script>
</head>
<body>
<p id="p1">
This demo shows how to add live mini-previews to links on hover. Check out these links to SitePoint and A List Apart. Hover over them to see a small preview of what they point to.
</p>
<p class="break">• • •</p>
<p id="p2">
Those previews were fetched as soon as this page loaded. This is great for having the previews ready ahead of time, but can eat up extra bandwidth. As an alternative, check out these links to Abduzeedo and Smashing Magazine. These previews aren't fetched until you hover over this paragraph.
</p>
<p class="break">• • •</p>
<p id="p3">
Finally, check out these links to Daniel's blog, Joni's blog, and my blog. These previews are only fetched when needed. This saves the most bandwidth, but there will be a delay before the previews can be shown.
</p>
</body>
</html>
ORIGINAL SOURCE:
http://codepen.io/kanakiyajay/pen/NqgZjo
I just use a library to generate a PNG preview of the excel file and show it.
I use Free Spire.XLS for .NET because I'm in the .net world, but you can look at Wijmo Workbook Viewer for your Node.js needs.
I have implemented the grid into a site and it's all working great! I have added a previous and next button using the JavaScript file to append them but can't seem to get them to cycle previous and next.
I notice Google's image search you can use the arrow keys to cycle through them but would like to use these buttons to do it. I know you can target the name attribute and cycle through the images but in this particular grid there is only the data-largesrc which I can't seem to target (I can target the img src of the thumbs. The images are in <li> so maybe that could be targeted? Any ideas would be appreciated. The JavaScript file is a bit big...
/*
* debouncedresize: special jQuery event that happens once after a window resize
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery-smartresize/blob/master/jquery.debouncedresize.js
*
* Copyright 2011 #louis_remi
* Licensed under the MIT license.
*/
var $jevent = $j.event,
$jspecial,
resizeTimeout;
$jspecial = $jevent.special.debouncedresize = {
setup: function() {
$j( this ).on( "resize", $jspecial.handler );
},
teardown: function() {
$j( this ).off( "resize", $jspecial.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments,
dispatch = function() {
// set correct event type
event.type = "debouncedresize";
$jevent.dispatch.apply( context, args );
};
if ( resizeTimeout ) {
clearTimeout( resizeTimeout );
}
execAsap ?
dispatch() :
resizeTimeout = setTimeout( dispatch, $jspecial.threshold );
},
threshold: 250
};
// ======================= imagesLoaded Plugin ===============================
// https://github.com/desandro/imagesloaded
// $j('#my-container').imagesLoaded(myFunction)
// execute a callback when all images have loaded.
// needed because .load() doesn't work on cached images
// callback function gets image collection as argument
// this is the container
// original: MIT license. Paul Irish. 2010.
// contributors: Oren Solomianik, David DeSandro, Yiannis Chatzikonstantinou
// blank image data-uri bypasses webkit log warning (thx doug jones)
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
$j.fn.imagesLoaded = function( callback ) {
var $jthis = this,
deferred = $j.isFunction($j.Deferred) ? $j.Deferred() : 0,
hasNotify = $j.isFunction(deferred.notify),
$jimages = $jthis.find('img').add( $jthis.filter('img') ),
loaded = [],
proper = [],
broken = [];
// Register deferred callbacks
if ($j.isPlainObject(callback)) {
$j.each(callback, function (key, value) {
if (key === 'callback') {
callback = value;
} else if (deferred) {
deferred[key](value);
}
});
}
function doneLoading() {
var $jproper = $j(proper),
$jbroken = $j(broken);
if ( deferred ) {
if ( broken.length ) {
deferred.reject( $jimages, $jproper, $jbroken );
} else {
deferred.resolve( $jimages );
}
}
if ( $j.isFunction( callback ) ) {
callback.call( $jthis, $jimages, $jproper, $jbroken );
}
}
function imgLoaded( img, isBroken ) {
// don't proceed if BLANK image, or image is already loaded
if ( img.src === BLANK || $j.inArray( img, loaded ) !== -1 ) {
return;
}
// store element in loaded images array
loaded.push( img );
// keep track of broken and properly loaded images
if ( isBroken ) {
broken.push( img );
} else {
proper.push( img );
}
// cache image and its state for future calls
$j.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );
// trigger deferred progress method if present
if ( hasNotify ) {
deferred.notifyWith( $j(img), [ isBroken, $jimages, $j(proper), $j(broken) ] );
}
// call doneLoading and clean listeners if all images are loaded
if ( $jimages.length === loaded.length ){
setTimeout( doneLoading );
$jimages.unbind( '.imagesLoaded' );
}
}
// if no images, trigger immediately
if ( !$jimages.length ) {
doneLoading();
} else {
$jimages.bind( 'load.imagesLoaded error.imagesLoaded', function( event ){
// trigger imgLoaded
imgLoaded( event.target, event.type === 'error' );
}).each( function( i, el ) {
var src = el.src;
// find out if this image has been already checked for status
// if it was, and src has not changed, call imgLoaded on it
var cached = $j.data( el, 'imagesLoaded' );
if ( cached && cached.src === src ) {
imgLoaded( el, cached.isBroken );
return;
}
// if complete is true and browser supports natural sizes, try
// to check for image status manually
if ( el.complete && el.naturalWidth !== undefined ) {
imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );
return;
}
// cached images don't fire load sometimes, so we reset src, but only when
// dealing with IE, or image is complete (loaded) and failed manual check
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
if ( el.readyState || el.complete ) {
el.src = BLANK;
el.src = src;
}
});
}
return deferred ? deferred.promise( $jthis ) : $jthis;
};
var Grid = (function() {
// list of items
var $jgrid = $j( '#og-grid' ),
// the items
$jitems = $jgrid.children( 'li' ),
// current expanded item's index
current = -1,
// position (top) of the expanded item
// used to know if the preview will expand in a different row
previewPos = -1,
// extra amount of pixels to scroll the window
scrollExtra = 0,
// extra margin when expanded (between preview overlay and the next items)
marginExpanded = 10,
$jwindow = $j( window ), winsize,
$jbody = $j( 'html, body' ),
// transitionend events
transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
// support for csstransitions
support = Modernizr.csstransitions,
// default settings
settings = {
minHeight : 500,
speed : 350,
easing : 'ease'
};
function init( config ) {
// the settings..
settings = $j.extend( true, {}, settings, config );
// preload all images
$jgrid.imagesLoaded( function() {
// save item´s size and offset
saveItemInfo( true );
// get window´s size
getWinSize();
// initialize some events
initEvents();
} );
}
// saves the item´s offset top and height (if saveheight is true)
function saveItemInfo( saveheight ) {
$jitems.each( function() {
var $jitem = $j( this );
$jitem.data( 'offsetTop', $jitem.offset().top );
if( saveheight ) {
$jitem.data( 'height', $jitem.height() );
}
} );
}
function initEvents() {
// when clicking an item, show the preview with the item´s info and large image.
// close the item if already expanded.
// also close if clicking on the item´s cross
$jitems.on( 'click', 'span.og-close', function() {
hidePreview();
return false;
} ).children( 'a' ).on( 'click', function(e) {
var $jitem = $j( this ).parent();
// check if item already opened
current === $jitem.index() ? hidePreview() : showPreview( $jitem );
return false;
} );
// on window resize get the window´s size again
// reset some values..
$jwindow.on( 'debouncedresize', function() {
scrollExtra = 0;
previewPos = -1;
// save item´s offset
saveItemInfo();
getWinSize();
var preview = $j.data( this, 'preview' );
if( typeof preview != 'undefined' ) {
hidePreview();
}
} );
}
function getWinSize() {
winsize = { width : $jwindow.width(), height : $jwindow.height() };
}
function showPreview( $jitem ) {
var preview = $j.data( this, 'preview' ),
// item´s offset top
position = $jitem.data( 'offsetTop' );
scrollExtra = 0;
// if a preview exists and previewPos is different (different row) from item´s top then close it
if( typeof preview != 'undefined' ) {
// not in the same row
if( previewPos !== position ) {
// if position > previewPos then we need to take te current preview´s height in consideration when scrolling the window
if( position > previewPos ) {
scrollExtra = preview.height;
}
hidePreview();
}
// same row
else {
preview.update( $jitem );
return false;
}
}
// update previewPos
previewPos = position;
// initialize new preview for the clicked item
preview = $j.data( this, 'preview', new Preview( $jitem ) );
// expand preview overlay
preview.open();
}
function hidePreview() {
current = -1;
var preview = $j.data( this, 'preview' );
preview.close();
$j.removeData( this, 'preview' );
}
// the preview obj / overlay
function Preview( $jitem ) {
this.$jitem = $jitem;
this.expandedIdx = this.$jitem.index();
this.create();
this.update();
}
Preview.prototype = {
create : function() {
// create Preview structure:
this.$jtitle = $j( '<h3></h3>' );
this.$jdescription = $j( '<p></p>' );
this.$jhref = $j( 'Go To Contact Page...' );
this.$jdetails = $j( '<div class="og-details"></div>' ).append( this.$jtitle, this.$jdescription, this.$jhref );
this.$jloading = $j( '<div class="og-loading"></div>' );
this.$jfullimage = $j( '<div class="og-fullimg"></div>' ).append( this.$jloading );
this.$jclosePreview = $j( '<span class="og-close"></span>' );
this.$jprevious = $j( '<span class="og-previous"></span>' );
this.$jnext = $j( '<span class="og-next"></span>' );
this.$jpreviewInner = $j( '<div class="og-expander-inner"></div>' ).append( this.$jclosePreview, this.$jprevious, this.$jnext, this.$jfullimage, this.$jdetails );
this.$jpreviewEl = $j( '<div class="og-expander"></div>' ).append( this.$jpreviewInner );
// append preview element to the item
this.$jitem.append( this.getEl() );
// set the transitions for the preview and the item
if( support ) {
this.setTransition();
}
},
update : function( $jitem ) {
if( $jitem ) {
this.$jitem = $jitem;
}
// if already expanded remove class "og-expanded" from current item and add it to new item
if( current !== -1 ) {
var $jcurrentItem = $jitems.eq( current );
$jcurrentItem.removeClass( 'og-expanded' );
this.$jitem.addClass( 'og-expanded' );
// position the preview correctly
this.positionPreview();
}
// update current value
current = this.$jitem.index();
// update preview´s content
var $jitemEl = this.$jitem.children( 'a' ),
eldata = {
href : $jitemEl.attr( 'href' ),
largesrc : $jitemEl.data( 'largesrc' ),
title : $jitemEl.data( 'title' ),
description : $jitemEl.data( 'description' )
};
this.$jtitle.html( eldata.title );
this.$jdescription.html( eldata.description );
this.$jhref.attr( 'href', eldata.href );
var self = this;
// remove the current image in the preview
if( typeof self.$jlargeImg != 'undefined' ) {
self.$jlargeImg.remove();
}
// preload large image and add it to the preview
// for smaller screens we don´t display the large image (the media query will hide the fullimage wrapper)
if( self.$jfullimage.is( ':visible' ) ) {
this.$jloading.show();
$j( '<img/>' ).load( function() {
var $jimg = $j( this );
if( $jimg.attr( 'src' ) === self.$jitem.children('a').data( 'largesrc' ) ) {
self.$jloading.hide();
self.$jfullimage.find( 'img' ).remove();
self.$jlargeImg = $jimg.fadeIn( 350 );
self.$jfullimage.append( self.$jlargeImg );
}
} ).attr( 'src', eldata.largesrc );
}
},
open : function() {
setTimeout( $j.proxy( function() {
// set the height for the preview and the item
this.setHeights();
// scroll to position the preview in the right place
this.positionPreview();
}, this ), 25 );
},
close : function() {
var self = this,
onEndFn = function() {
if( support ) {
$j( this ).off( transEndEventName );
}
self.$jitem.removeClass( 'og-expanded' );
self.$jpreviewEl.remove();
};
setTimeout( $j.proxy( function() {
if( typeof this.$jlargeImg !== 'undefined' ) {
this.$jlargeImg.fadeOut( 'fast' );
}
this.$jpreviewEl.css( 'height', 0 );
// the current expanded item (might be different from this.$jitem)
var $jexpandedItem = $jitems.eq( this.expandedIdx );
$jexpandedItem.css( 'height', $jexpandedItem.data( 'height' ) ).on( transEndEventName, onEndFn );
if( !support ) {
onEndFn.call();
}
}, this ), 25 );
return false;
},
calcHeight : function() {
var heightPreview = winsize.height - this.$jitem.data( 'height' ) - marginExpanded,
itemHeight = winsize.height;
if( heightPreview < settings.minHeight ) {
heightPreview = settings.minHeight;
itemHeight = settings.minHeight + this.$jitem.data( 'height' ) + marginExpanded;
}
this.height = heightPreview;
this.itemHeight = itemHeight;
},
setHeights : function() {
var self = this,
onEndFn = function() {
if( support ) {
self.$jitem.off( transEndEventName );
}
self.$jitem.addClass( 'og-expanded' );
};
this.calcHeight();
this.$jpreviewEl.css( 'height', this.height );
this.$jitem.css( 'height', this.itemHeight ).on( transEndEventName, onEndFn );
if( !support ) {
onEndFn.call();
}
},
positionPreview : function() {
// scroll page
// case 1 : preview height + item height fits in window´s height
// case 2 : preview height + item height does not fit in window´s height and preview height is smaller than window´s height
// case 3 : preview height + item height does not fit in window´s height and preview height is bigger than window´s height
var position = this.$jitem.data( 'offsetTop' ),
previewOffsetT = this.$jpreviewEl.offset().top - scrollExtra,
scrollVal = this.height + this.$jitem.data( 'height' ) + marginExpanded <= winsize.height ? position : this.height < winsize.height ? previewOffsetT - ( winsize.height - this.height ) : previewOffsetT;
$jbody.animate( { scrollTop : scrollVal }, settings.speed );
},
setTransition : function() {
this.$jpreviewEl.css( 'transition', 'height ' + settings.speed + 'ms ' + settings.easing );
this.$jitem.css( 'transition', 'height ' + settings.speed + 'ms ' + settings.easing );
},
getEl : function() {
return this.$jpreviewEl;
}
}
return { init : init };
})();
Here is the HTML...
<ul id="og-grid" class="og-grid">
<!-- The Entrance -->
<li>
<a href="http://www.thebarnandpinncottage.co.uk/contact" data-largesrc="/images/cottage-images/entrance/image-entrance.jpg" data-title="The Entrance" data-description="The Barn and Pinn Cottage">
<img src="/images/cottage-images/entrance/image-entrance-thumb.jpg" alt="img01"/>
</a>
</li>
<li>
<a href="http://www.thebarnandpinncottage.co.uk/contact" data-largesrc="/images/cottage-images/entrance/image-entrance-2.jpg" data-title="The Entrance" data-description="The Barn and Pinn Cottage">
<img src="/images/cottage-images/entrance/image-entrance-2-thumb.jpg" alt="img01"/>
</a>
</li>
<li>
<a href="http://www.thebarnandpinncottage.co.uk/contact" data-largesrc="/images/cottage-images/entrance/image-entrance-3.jpg" data-title="The Entrance" data-description="The Barn and Pinn Cottage">
<img src="/images/cottage-images/entrance/image-entrance-3-thumb.jpg" alt="img01"/>
</a>
</li>
<li>
<a href="http://www.thebarnandpinncottage.co.uk/contact" data-largesrc="/images/cottage-images/entrance/image-entrance-4.jpg" data-title="The Entrance" data-description="The Barn and Pinn Cottage">
<img src="/images/cottage-images/entrance/image-entrance-4-thumb.jpg" alt="img01"/>
</a>
</li>
<li>
<a href="http://www.thebarnandpinncottage.co.uk/contact" data-largesrc="/images/cottage-images/entrance/image-entrance-5.jpg" data-title="The Entrance" data-description="The Barn and Pinn Cottage">
<img src="/images/cottage-images/entrance/image-entrance-5-thumb.jpg" alt="img01" name="VCRImage"/>
</a>
</li>
Here is the CSS...
.og-grid {
list-style: none;
padding: 20px 0;
margin: 0 auto;
text-align: center;
width: 100%;
}
.og-grid li {
display: inline-block;
margin: 10px 5px 0 5px;
vertical-align: top;
height: 250px;
}
.og-grid li > a,
.og-grid li > a img {
border: none;
outline: none;
display: block;
position: relative;
}
.og-grid li.og-expanded > a::after {
top: auto;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-bottom-color: #B3BCC6;
border-width: 15px;
left: 50%;
margin: -20px 0 0 -15px;
}
.og-expander {
position: absolute;
background: #B3BCC6;
top: auto;
left: 0;
width: 88.888888%;
margin-top: 10px;
text-align: left;
height: 0;
overflow: hidden;
}
.og-expander-inner {
padding: 80px 30px;
height: 100%;
}
.og-close {
position: absolute;
width: 40px;
height: 40px;
top: 20px;
right: 20px;
cursor: pointer;
}
.og-close::before,
.og-close::after {
content: '';
position: absolute;
width: 100%;
top: 50%;
height: 1px;
background: white;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.og-close::after {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.og-close:hover::before,
.og-close:hover::after {
background: #333;
}
.og-previous {
position: absolute;
width: 40px;
height: 40px;
top: 20px;
right: 200px;
cursor: pointer;
}
.og-previous::before {
content: '<<';
position: absolute;
width: 100%;
top: 50%;
color: white;
}
.og-next {
position: absolute;
width: 40px;
height: 40px;
top: 20px;
right: 100px;
cursor: pointer;
}
.og-next::before {
content: '>>';
position: absolute;
width: 100%;
top: 50%;
color: white;
}
.og-details {
padding: 0 40px 0 20px;
}
.og-fullimg {
text-align: center;
}
.og-fullimg img {
display: inline-block;
max-height: 100%;
max-width: 100%;
}
.og-details h3 {
font-weight: 300;
font-size: 1.6em;
padding: 0;
margin: 0 0 1em 0;
color: #4B77B1;
}
.og-details p {
font-weight: 400;
font-size: 16px;
line-height: 22px;
color: white;
}
.og-details a {
font-weight: 700;
font-size: 16px;
color: #4B77B1;
text-transform: uppercase;
letter-spacing: 2px;
padding: 10px 20px;
border: 3px solid #4B77B1;
display: inline-block;
margin: 30px 0 0;
outline: none;
}
.og-details a::before {
content: '\2192';
display: inline-block;
margin-right: 10px;
}
.og-details a:hover {
border-color: white;
color: white;
}
.og-loading {
width: 20px;
height: 20px;
border-radius: 50%;
background: #ddd;
box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ccc;
position: absolute;
top: 50%;
left: 50%;
margin: -25px 0 0 -25px;
-webkit-animation: loader 0.5s infinite ease-in-out both;
-moz-animation: loader 0.5s infinite ease-in-out both;
animation: loader 0.5s infinite ease-in-out both;
}
#-webkit-keyframes loader {
0% { background: #ddd; }
33% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ddd; }
66% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ddd, -15px 30px 1px #ccc; }
}
#-moz-keyframes loader {
0% { background: #ddd; }
33% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ddd; }
66% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ddd, -15px 30px 1px #ccc; }
}
#keyframes loader {
0% { background: #ddd; }
33% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ddd; }
66% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ddd, -15px 30px 1px #ccc; }
}
http://www.filamentgroup.com/examples/slider_v2/index.php
http://jqueryui.com/demos/slider/#side-scroll
How can i bring the two together, where
when u slide to a certain tag (Slower, Med, etc; you basically move to that particular box
that corresponds to it
never mind the drop down
need an example
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<script type="text/javascript" src="2_files/jquery.js"></script>
<script type="text/javascript" src="2_files/jquery-ui.js"></script>
<link href="2_files/jquery-ui.css" type="text/css" rel="Stylesheet">
<style>
#demo-frame > div.demo { padding: 10px !important; }
.scroll-pane { overflow: auto; width: 99%; float:left; }
.scroll-content { width: 2440px; float: left; }
.scroll-content-item { width: 100px; height: 100px; float: left; margin: 10px; font-size: 3em; line-height: 96px; text-align: center; }
* html .scroll-content-item { display: inline; } /* IE6 float double margin bug */
.scroll-bar-wrap { clear: left; padding: 0 4px 0 2px; margin: 0 -1px -1px -1px; }
.scroll-bar-wrap .ui-slider { background: none; border:0; height: 2em; margin: 0 auto; }
.scroll-bar-wrap .ui-handle-helper-parent { position: relative; width: 100%; height: 100%; margin: 0 auto; }
.scroll-bar-wrap .ui-slider-handle { top:.2em; height: 1.5em; }
.scroll-bar-wrap .ui-slider-handle .ui-icon { margin: -8px auto 0; position: relative; top: 50%; }
</style>
</head>
<body>
<script>
$(function() {
var scrollPane = $( ".scroll-pane" ),
var scrollContent = $( ".scroll-content" );
var scrollbar = $( ".scroll-bar" ).slider({
value:100,
min: 0,
max: 500,
step: 50,
slide: function( event, ui ) {
if ( scrollContent.width() > scrollPane.width() ) {
scrollContent.css( "margin-left", Math.round(
ui.value / 100 * ( scrollPane.width() - scrollContent.width() )
) + "px" );
} else {
scrollContent.css( "margin-left", 0 );
}
}
});
});
//append icon to handle
var handleHelper = scrollbar.find( ".ui-slider-handle" )
.mousedown(function() {
scrollbar.width( handleHelper.width() );
})
.mouseup(function() {
scrollbar.width( "100%" );
})
.append( "<span class='ui-icon ui-icon-grip-dotted-vertical'></span>" )
.wrap( "<div class='ui-handle-helper-parent'></div>" ).parent();
//change overflow to hidden now that slider handles the scrolling
scrollPane.css( "overflow", "hidden" );
//size scrollbar and handle proportionally to scroll distance
function sizeScrollbar() {
var remainder = scrollContent.width() - scrollPane.width();
var proportion = remainder / scrollContent.width();
var handleSize = scrollPane.width() - ( proportion * scrollPane.width() );
scrollbar.find( ".ui-slider-handle" ).css({
width: handleSize,
"margin-left": -handleSize / 2
});
handleHelper.width( "" ).width( scrollbar.width() - handleSize );
}
//reset slider value based on scroll content position
function resetValue() {
var remainder = scrollPane.width() - scrollContent.width();
var leftVal = scrollContent.css( "margin-left" ) === "auto" ? 0 :
parseInt( scrollContent.css( "margin-left" ) );
var percentage = Math.round( leftVal / remainder * 100 );
scrollbar.slider( "value", percentage );
}
//if the slider is 100% and window gets larger, reveal content
function reflowContent() {
var showing = scrollContent.width() + parseInt( scrollContent.css( "margin-left" ), 10 );
var gap = scrollPane.width() - showing;
if ( gap > 0 ) {
scrollContent.css( "margin-left", parseInt( scrollContent.css( "margin-left" ), 10 ) + gap );
}
}
//change handle position on window resize
$( window ).resize(function() {
resetValue();
sizeScrollbar();
reflowContent();
});
//init scrollbar size
setTimeout( sizeScrollbar, 10 );//safari wants a timeout
});
</script>
<div class="demo">
<div class="scroll-pane ui-widget ui-widget-header ui-corner-all">
<div class="scroll-content">
<div class="scroll-content-item ui-widget-header">1</div>
<div class="scroll-content-item ui-widget-header">2</div>
<div class="scroll-content-item ui-widget-header">3</div>
<div class="scroll-content-item ui-widget-header">4</div>
<div class="scroll-content-item ui-widget-header">5</div>
<div class="scroll-content-item ui-widget-header">6</div>
<div class="scroll-content-item ui-widget-header">7</div>
<div class="scroll-content-item ui-widget-header">8</div>
<div class="scroll-content-item ui-widget-header">9</div>
<div class="scroll-content-item ui-widget-header">10</div>
<div class="scroll-content-item ui-widget-header">11</div>
<div class="scroll-content-item ui-widget-header">12</div>
<div class="scroll-content-item ui-widget-header">13</div>
<div class="scroll-content-item ui-widget-header">14</div>
<div class="scroll-content-item ui-widget-header">15</div>
<div class="scroll-content-item ui-widget-header">16</div>
<div class="scroll-content-item ui-widget-header">17</div>
<div class="scroll-content-item ui-widget-header">18</div>
<div class="scroll-content-item ui-widget-header">19</div>
<div class="scroll-content-item ui-widget-header">20</div>
</div>
<div class="scroll-bar-wrap ui-widget-content ui-corner-bottom">
<div class="scroll-bar"></div>
</div>
</div>
</div><!-- End demo -->
<div class="demo-description">
<p>Use a slider to manipulate the positioning of content on the page. In this case, it acts as a scrollbar with the potential to capture values if needed.</p>
</div><!-- End demo-description -->
</body></html>
do you can see the script (view code) in the demo http://jqueryui.com/demos/slider/#side-scroll ?
just make litle modification to the scripts, just change to:
$(function() {
var scrollPane = $( ".scroll-pane" ),
scrollContent = $( ".scroll-content" );
var scrollbar = $( ".scroll-bar" ).slider({
value:100,
min: 0,
max: 500,
step: 50,
slide: function( event, ui ) {
if ( scrollContent.width() > scrollPane.width() ) {
scrollContent.css( "margin-left", Math.round(
ui.value / 100 * ( scrollPane.width() - scrollContent.width() )
) + "px" );
} else {
scrollContent.css( "margin-left", 0 );
}
}
});
});
i have tried and it's works. then just make finishing touch for your need