Sites-Camelia/branches/magzine/v4/assets/js/main.js

770 lines
14 KiB
JavaScript

/*
Lens by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
var main = (function($) { var _ = {
/**
* Settings.
* @var {object}
*/
settings: {
// Preload all images.
preload: false,
// Slide duration (must match "duration.slide" in _vars.scss).
slideDuration: 500,
// Layout duration (must match "duration.layout" in _vars.scss).
layoutDuration: 750,
// Thumbnails per "row" (must match "misc.thumbnails-per-row" in _vars.scss).
thumbnailsPerRow: 2,
// Side of main wrapper (must match "misc.main-side" in _vars.scss).
mainSide: 'right'
},
/**
* Window.
* @var {jQuery}
*/
$window: null,
/**
* Body.
* @var {jQuery}
*/
$body: null,
/**
* Main wrapper.
* @var {jQuery}
*/
$main: null,
/**
* Thumbnails.
* @var {jQuery}
*/
$thumbnails: null,
/**
* Viewer.
* @var {jQuery}
*/
$viewer: null,
/**
* Toggle.
* @var {jQuery}
*/
$toggle: null,
/**
* Nav (next).
* @var {jQuery}
*/
$navNext: null,
/**
* Nav (previous).
* @var {jQuery}
*/
$navPrevious: null,
/**
* Slides.
* @var {array}
*/
slides: [],
/**
* Current slide index.
* @var {integer}
*/
current: null,
/**
* Lock state.
* @var {bool}
*/
locked: false,
/**
* Keyboard shortcuts.
* @var {object}
*/
keys: {
// Escape: Toggle main wrapper.
27: function() {
_.toggle();
},
// Up: Move up.
38: function() {
_.up();
},
// Down: Move down.
40: function() {
_.down();
},
// Space: Next.
32: function() {
_.next();
},
// Right Arrow: Next.
39: function() {
_.next();
},
// Left Arrow: Previous.
37: function() {
_.previous();
}
},
/**
* Initialize properties.
*/
initProperties: function() {
// Window, body.
_.$window = $(window);
_.$body = $('body');
// Thumbnails.
_.$thumbnails = $('#thumbnails');
// Viewer.
_.$viewer = $(
'<div id="viewer">' +
'<div class="inner">' +
'<div class="nav-next"></div>' +
'<div class="nav-previous"></div>' +
'<div class="toggle"></div>' +
'</div>' +
'</div>'
).appendTo(_.$body);
// Nav.
_.$navNext = _.$viewer.find('.nav-next');
_.$navPrevious = _.$viewer.find('.nav-previous');
// Main wrapper.
_.$main = $('#main');
// Toggle.
$('<div class="toggle"></div>')
.appendTo(_.$main);
_.$toggle = $('.toggle');
// IE<9: Fix viewer width (no calc support).
if (skel.vars.IEVersion < 9)
_.$window
.on('resize', function() {
window.setTimeout(function() {
_.$viewer.css('width', _.$window.width() - _.$main.width());
}, 100);
})
.trigger('resize');
},
/**
* Initialize events.
*/
initEvents: function() {
// Window.
// Remove is-loading-* classes on load.
_.$window.on('load', function() {
_.$body.removeClass('is-loading-0');
window.setTimeout(function() {
_.$body.removeClass('is-loading-1');
}, 100);
window.setTimeout(function() {
_.$body.removeClass('is-loading-2');
}, 100 + Math.max(_.settings.layoutDuration - 150, 0));
});
// Disable animations/transitions on resize.
var resizeTimeout;
_.$window.on('resize', function() {
_.$body.addClass('is-loading-0');
window.clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(function() {
_.$body.removeClass('is-loading-0');
}, 100);
});
// Viewer.
// Hide main wrapper on tap (<= medium only).
_.$viewer.on('touchend', function() {
if (skel.breakpoint('medium').active)
_.hide();
});
// Touch gestures.
_.$viewer
.on('touchstart', function(event) {
// Record start position.
_.$viewer.touchPosX = event.originalEvent.touches[0].pageX;
_.$viewer.touchPosY = event.originalEvent.touches[0].pageY;
})
.on('touchmove', function(event) {
// No start position recorded? Bail.
if (_.$viewer.touchPosX === null
|| _.$viewer.touchPosY === null)
return;
// Calculate stuff.
var diffX = _.$viewer.touchPosX - event.originalEvent.touches[0].pageX,
diffY = _.$viewer.touchPosY - event.originalEvent.touches[0].pageY;
boundary = 20,
delta = 50;
// Swipe left (next).
if ( (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta) )
_.next();
// Swipe right (previous).
else if ( (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta)) )
_.previous();
// Overscroll fix.
var th = _.$viewer.outerHeight(),
ts = (_.$viewer.get(0).scrollHeight - _.$viewer.scrollTop());
if ((_.$viewer.scrollTop() <= 0 && diffY < 0)
|| (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
event.preventDefault();
event.stopPropagation();
}
});
// Main.
// Touch gestures.
_.$main
.on('touchstart', function(event) {
// Bail on xsmall.
if (skel.breakpoint('xsmall').active)
return;
// Record start position.
_.$main.touchPosX = event.originalEvent.touches[0].pageX;
_.$main.touchPosY = event.originalEvent.touches[0].pageY;
})
.on('touchmove', function(event) {
// Bail on xsmall.
if (skel.breakpoint('xsmall').active)
return;
// No start position recorded? Bail.
if (_.$main.touchPosX === null
|| _.$main.touchPosY === null)
return;
// Calculate stuff.
var diffX = _.$main.touchPosX - event.originalEvent.touches[0].pageX,
diffY = _.$main.touchPosY - event.originalEvent.touches[0].pageY;
boundary = 20,
delta = 50,
result = false;
// Swipe to close.
switch (_.settings.mainSide) {
case 'left':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);
break;
case 'right':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));
break;
default:
break;
}
if (result)
_.hide();
// Overscroll fix.
var th = _.$main.outerHeight(),
ts = (_.$main.get(0).scrollHeight - _.$main.scrollTop());
if ((_.$main.scrollTop() <= 0 && diffY < 0)
|| (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
event.preventDefault();
event.stopPropagation();
}
});
// Toggle.
_.$toggle.on('click', function() {
_.toggle();
});
// Prevent event from bubbling up to "hide event on tap" event.
_.$toggle.on('touchend', function(event) {
event.stopPropagation();
});
// Nav.
_.$navNext.on('click', function() {
_.next();
});
_.$navPrevious.on('click', function() {
_.previous();
});
// Keyboard shortcuts.
// Ignore shortcuts within form elements.
_.$body.on('keydown', 'input,select,textarea', function(event) {
event.stopPropagation();
});
_.$window.on('keydown', function(event) {
// Ignore if xsmall is active.
if (skel.breakpoint('xsmall').active)
return;
// Check keycode.
if (event.keyCode in _.keys) {
// Stop other events.
event.stopPropagation();
event.preventDefault();
// Call shortcut.
(_.keys[event.keyCode])();
}
});
},
/**
* Initialize viewer.
*/
initViewer: function() {
// Bind thumbnail click event.
_.$thumbnails
.on('click', '.thumbnail', function(event) {
var $this = $(this);
// Stop other events.
event.preventDefault();
event.stopPropagation();
// Locked? Blur.
if (_.locked)
$this.blur();
// Switch to this thumbnail's slide.
_.switchTo($this.data('index'));
});
// Create slides from thumbnails.
_.$thumbnails.children()
.each(function() {
var $this = $(this),
$thumbnail = $this.children('.thumbnail'),
s;
// Slide object.
s = {
$parent: $this,
$slide: null,
$slideImage: null,
$slideCaption: null,
url: $thumbnail.attr('href'),
loaded: false
};
// Parent.
$this.attr('tabIndex', '-1');
// Slide.
// Create elements.
s.$slide = $('<div class="slide"><div class="caption"></div><div class="image"></div></div>');
// Image.
s.$slideImage = s.$slide.children('.image');
// Set background stuff.
s.$slideImage
.css('background-image', '')
.css('background-position', ($thumbnail.data('position') || 'center'));
// Caption.
s.$slideCaption = s.$slide.find('.caption');
// Move everything *except* the thumbnail itself to the caption.
$this.children().not($thumbnail)
.appendTo(s.$slideCaption);
// Preload?
if (_.settings.preload) {
// Force image to download.
var $img = $('<img src="' + s.url + '" />');
// Set slide's background image to it.
s.$slideImage
.css('background-image', 'url(' + s.url + ')');
// Mark slide as loaded.
s.$slide.addClass('loaded');
s.loaded = true;
}
// Add to slides array.
_.slides.push(s);
// Set thumbnail's index.
$thumbnail.data('index', _.slides.length - 1);
});
},
/**
* Initialize stuff.
*/
init: function() {
// IE<10: Zero out transition delays.
if (skel.vars.IEVersion < 10) {
_.settings.slideDuration = 0;
_.settings.layoutDuration = 0;
}
// Skel.
skel.breakpoints({
xlarge: '(max-width: 1680px)',
large: '(max-width: 1280px)',
medium: '(max-width: 980px)',
small: '(max-width: 736px)',
xsmall: '(max-width: 480px)'
});
// Everything else.
_.initProperties();
_.initViewer();
_.initEvents();
// Initial slide.
window.setTimeout(function() {
// Show first slide if xsmall isn't active or it just deactivated.
skel.on('-xsmall !xsmall', function() {
if (_.current === null)
_.switchTo(0, true);
});
}, 0);
},
/**
* Switch to a specific slide.
* @param {integer} index Index.
*/
switchTo: function(index, noHide) {
// Already at index and xsmall isn't active? Bail.
if (_.current == index
&& !skel.breakpoint('xsmall').active)
return;
// Locked? Bail.
if (_.locked)
return;
// Lock.
_.locked = true;
// Hide main wrapper if medium is active.
if (!noHide
&& skel.breakpoint('medium').active
&& skel.vars.IEVersion > 8)
_.hide();
// Get slides.
var oldSlide = (_.current !== null ? _.slides[_.current] : null),
newSlide = _.slides[index];
// Update current.
_.current = index;
// Deactivate old slide (if there is one).
if (oldSlide) {
// Thumbnail.
oldSlide.$parent
.removeClass('active');
// Slide.
oldSlide.$slide.removeClass('active');
}
// Activate new slide.
// Thumbnail.
newSlide.$parent
.addClass('active')
.focus();
// Slide.
var f = function() {
// Old slide exists? Detach it.
if (oldSlide)
oldSlide.$slide.detach();
// Attach new slide.
newSlide.$slide.appendTo(_.$viewer);
// New slide not yet loaded?
if (!newSlide.loaded) {
window.setTimeout(function() {
// Mark as loading.
newSlide.$slide.addClass('loading');
// Wait for it to load.
$('<img src="' + newSlide.url + '" />').on('load', function() {
//window.setTimeout(function() {
// Set background image.
newSlide.$slideImage
.css('background-image', 'url(' + newSlide.url + ')');
// Mark as loaded.
newSlide.loaded = true;
newSlide.$slide.removeClass('loading');
// Mark as active.
newSlide.$slide.addClass('active');
// Unlock.
window.setTimeout(function() {
_.locked = false;
}, 100);
//}, 1000);
});
}, 100);
}
// Otherwise ...
else {
window.setTimeout(function() {
// Mark as active.
newSlide.$slide.addClass('active');
// Unlock.
window.setTimeout(function() {
_.locked = false;
}, 100);
}, 100);
}
};
// No old slide? Switch immediately.
if (!oldSlide)
(f)();
// Otherwise, wait for old slide to disappear first.
else
window.setTimeout(f, _.settings.slideDuration);
},
/**
* Switches to the next slide.
*/
next: function() {
// Calculate new index.
var i, c = _.current, l = _.slides.length;
if (c >= l - 1)
i = 0;
else
i = c + 1;
// Switch.
_.switchTo(i);
},
/**
* Switches to the previous slide.
*/
previous: function() {
// Calculate new index.
var i, c = _.current, l = _.slides.length;
if (c <= 0)
i = l - 1;
else
i = c - 1;
// Switch.
_.switchTo(i);
},
/**
* Switches to slide "above" current.
*/
up: function() {
// Fullscreen? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Calculate new index.
var i, c = _.current, l = _.slides.length, tpr = _.settings.thumbnailsPerRow;
if (c <= (tpr - 1))
i = l - (tpr - 1 - c) - 1;
else
i = c - tpr;
// Switch.
_.switchTo(i);
},
/**
* Switches to slide "below" current.
*/
down: function() {
// Fullscreen? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Calculate new index.
var i, c = _.current, l = _.slides.length, tpr = _.settings.thumbnailsPerRow;
if (c >= l - tpr)
i = c - l + tpr;
else
i = c + tpr;
// Switch.
_.switchTo(i);
},
/**
* Shows the main wrapper.
*/
show: function() {
// Already visible? Bail.
if (!_.$body.hasClass('fullscreen'))
return;
// Show main wrapper.
_.$body.removeClass('fullscreen');
// Focus.
_.$main.focus();
},
/**
* Hides the main wrapper.
*/
hide: function() {
// Already hidden? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Hide main wrapper.
_.$body.addClass('fullscreen');
// Blur.
_.$main.blur();
},
/**
* Toggles main wrapper.
*/
toggle: function() {
if (_.$body.hasClass('fullscreen'))
_.show();
else
_.hide();
},
}; return _; })(jQuery); main.init();