|
|
- /*jslint unparam: true, browser: true, indent: 2 */
-
- ;(function ($, window, document, undefined) {
- 'use strict';
-
- Foundation.libs.clearing = {
- name : 'clearing',
-
- version: '4.3.1',
-
- settings : {
- templates : {
- viewing : '<a href="#" class="clearing-close">×</a>' +
- '<div class="visible-img" style="display: none"><img src="//:0">' +
- '<p class="clearing-caption"></p><a href="#" class="clearing-main-prev"><span></span></a>' +
- '<a href="#" class="clearing-main-next"><span></span></a></div>'
- },
-
- // comma delimited list of selectors that, on click, will close clearing,
- // add 'div.clearing-blackout, div.visible-img' to close on background click
- close_selectors : '.clearing-close',
-
- // event initializers and locks
- init : false,
- locked : false
- },
-
- init : function (scope, method, options) {
- var self = this;
- Foundation.inherit(this, 'set_data get_data remove_data throttle data_options');
-
- if (typeof method === 'object') {
- options = $.extend(true, this.settings, method);
- }
-
- if (typeof method !== 'string') {
- $(this.scope).find('ul[data-clearing]').each(function () {
- var $el = $(this),
- options = options || {},
- lis = $el.find('li'),
- settings = self.get_data($el);
-
- if (!settings && lis.length > 0) {
- options.$parent = $el.parent();
-
- self.set_data($el, $.extend({}, self.settings, options, self.data_options($el)));
-
- self.assemble($el.find('li'));
-
- if (!self.settings.init) {
- self.events().swipe_events();
- }
- }
- });
-
- return this.settings.init;
- } else {
- // fire method
- return this[method].call(this, options);
- }
- },
-
- // event binding and initial setup
-
- events : function () {
- var self = this;
-
- $(this.scope)
- .on('click.fndtn.clearing', 'ul[data-clearing] li',
- function (e, current, target) {
- var current = current || $(this),
- target = target || current,
- next = current.next('li'),
- settings = self.get_data(current.parent()),
- image = $(e.target);
-
- e.preventDefault();
- if (!settings) self.init();
-
- // if clearing is open and the current image is
- // clicked, go to the next image in sequence
- if (target.hasClass('visible') &&
- current[0] === target[0] &&
- next.length > 0 && self.is_open(current)) {
- target = next;
- image = target.find('img');
- }
-
- // set current and target to the clicked li if not otherwise defined.
- self.open(image, current, target);
- self.update_paddles(target);
- })
-
- .on('click.fndtn.clearing', '.clearing-main-next',
- function (e) { this.nav(e, 'next') }.bind(this))
- .on('click.fndtn.clearing', '.clearing-main-prev',
- function (e) { this.nav(e, 'prev') }.bind(this))
- .on('click.fndtn.clearing', this.settings.close_selectors,
- function (e) { Foundation.libs.clearing.close(e, this) })
- .on('keydown.fndtn.clearing',
- function (e) { this.keydown(e) }.bind(this));
-
- $(window).on('resize.fndtn.clearing',
- function () { this.resize() }.bind(this));
-
- this.settings.init = true;
- return this;
- },
-
- swipe_events : function () {
- var self = this;
-
- $(this.scope)
- .on('touchstart.fndtn.clearing', '.visible-img', function(e) {
- if (!e.touches) { e = e.originalEvent; }
- var data = {
- start_page_x: e.touches[0].pageX,
- start_page_y: e.touches[0].pageY,
- start_time: (new Date()).getTime(),
- delta_x: 0,
- is_scrolling: undefined
- };
-
- $(this).data('swipe-transition', data);
- e.stopPropagation();
- })
- .on('touchmove.fndtn.clearing', '.visible-img', function(e) {
- if (!e.touches) { e = e.originalEvent; }
- // Ignore pinch/zoom events
- if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
-
- var data = $(this).data('swipe-transition');
-
- if (typeof data === 'undefined') {
- data = {};
- }
-
- data.delta_x = e.touches[0].pageX - data.start_page_x;
-
- if ( typeof data.is_scrolling === 'undefined') {
- data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
- }
-
- if (!data.is_scrolling && !data.active) {
- e.preventDefault();
- var direction = (data.delta_x < 0) ? 'next' : 'prev';
- data.active = true;
- self.nav(e, direction);
- }
- })
- .on('touchend.fndtn.clearing', '.visible-img', function(e) {
- $(this).data('swipe-transition', {});
- e.stopPropagation();
- });
- },
-
- assemble : function ($li) {
- var $el = $li.parent();
- $el.after('<div id="foundationClearingHolder"></div>');
-
- var holder = $('#foundationClearingHolder'),
- settings = this.get_data($el),
- grid = $el.detach(),
- data = {
- grid: '<div class="carousel">' + this.outerHTML(grid[0]) + '</div>',
- viewing: settings.templates.viewing
- },
- wrapper = '<div class="clearing-assembled"><div>' + data.viewing +
- data.grid + '</div></div>';
-
- return holder.after(wrapper).remove();
- },
-
- // event callbacks
-
- open : function ($image, current, target) {
- var root = target.closest('.clearing-assembled'),
- container = root.find('div').first(),
- visible_image = container.find('.visible-img'),
- image = visible_image.find('img').not($image);
-
- if (!this.locked()) {
- // set the image to the selected thumbnail
- image
- .attr('src', this.load($image))
- .css('visibility', 'hidden');
-
- this.loaded(image, function () {
- image.css('visibility', 'visible');
- // toggle the gallery
- root.addClass('clearing-blackout');
- container.addClass('clearing-container');
- visible_image.show();
- this.fix_height(target)
- .caption(visible_image.find('.clearing-caption'), $image)
- .center(image)
- .shift(current, target, function () {
- target.siblings().removeClass('visible');
- target.addClass('visible');
- });
- }.bind(this));
- }
- },
-
- close : function (e, el) {
- e.preventDefault();
-
- var root = (function (target) {
- if (/blackout/.test(target.selector)) {
- return target;
- } else {
- return target.closest('.clearing-blackout');
- }
- }($(el))), container, visible_image;
-
- if (el === e.target && root) {
- container = root.find('div').first();
- visible_image = container.find('.visible-img');
- this.settings.prev_index = 0;
- root.find('ul[data-clearing]')
- .attr('style', '').closest('.clearing-blackout')
- .removeClass('clearing-blackout');
- container.removeClass('clearing-container');
- visible_image.hide();
- }
-
- return false;
- },
-
- is_open : function (current) {
- return current.parent().attr('style').length > 0;
- },
-
- keydown : function (e) {
- var clearing = $('.clearing-blackout').find('ul[data-clearing]');
-
- if (e.which === 39) this.go(clearing, 'next');
- if (e.which === 37) this.go(clearing, 'prev');
- if (e.which === 27) $('a.clearing-close').trigger('click');
- },
-
- nav : function (e, direction) {
- var clearing = $('.clearing-blackout').find('ul[data-clearing]');
-
- e.preventDefault();
- this.go(clearing, direction);
- },
-
- resize : function () {
- var image = $('.clearing-blackout .visible-img').find('img');
-
- if (image.length) {
- this.center(image);
- }
- },
-
- // visual adjustments
- fix_height : function (target) {
- var lis = target.parent().children(),
- self = this;
-
- lis.each(function () {
- var li = $(this),
- image = li.find('img');
-
- if (li.height() > self.outerHeight(image)) {
- li.addClass('fix-height');
- }
- })
- .closest('ul')
- .width(lis.length * 100 + '%');
-
- return this;
- },
-
- update_paddles : function (target) {
- var visible_image = target
- .closest('.carousel')
- .siblings('.visible-img');
-
- if (target.next().length > 0) {
- visible_image
- .find('.clearing-main-next')
- .removeClass('disabled');
- } else {
- visible_image
- .find('.clearing-main-next')
- .addClass('disabled');
- }
-
- if (target.prev().length > 0) {
- visible_image
- .find('.clearing-main-prev')
- .removeClass('disabled');
- } else {
- visible_image
- .find('.clearing-main-prev')
- .addClass('disabled');
- }
- },
-
- center : function (target) {
- if (!this.rtl) {
- target.css({
- marginLeft : -(this.outerWidth(target) / 2),
- marginTop : -(this.outerHeight(target) / 2)
- });
- } else {
- target.css({
- marginRight : -(this.outerWidth(target) / 2),
- marginTop : -(this.outerHeight(target) / 2)
- });
- }
- return this;
- },
-
- // image loading and preloading
-
- load : function ($image) {
- if ($image[0].nodeName === "A") {
- var href = $image.attr('href');
- } else {
- var href = $image.parent().attr('href');
- }
-
- this.preload($image);
-
- if (href) return href;
- return $image.attr('src');
- },
-
- preload : function ($image) {
- this
- .img($image.closest('li').next())
- .img($image.closest('li').prev());
- },
-
- loaded : function (image, callback) {
- // based on jquery.imageready.js
- // @weblinc, @jsantell, (c) 2012
-
- function loaded () {
- callback();
- }
-
- function bindLoad () {
- this.one('load', loaded);
-
- if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
- var src = this.attr( 'src' ),
- param = src.match( /\?/ ) ? '&' : '?';
-
- param += 'random=' + (new Date()).getTime();
- this.attr('src', src + param);
- }
- }
-
- if (!image.attr('src')) {
- loaded();
- return;
- }
-
- if (image[0].complete || image[0].readyState === 4) {
- loaded();
- } else {
- bindLoad.call(image);
- }
- },
-
- img : function (img) {
- if (img.length) {
- var new_img = new Image(),
- new_a = img.find('a');
-
- if (new_a.length) {
- new_img.src = new_a.attr('href');
- } else {
- new_img.src = img.find('img').attr('src');
- }
- }
- return this;
- },
-
- // image caption
-
- caption : function (container, $image) {
- var caption = $image.data('caption');
-
- if (caption) {
- container
- .html(caption)
- .show();
- } else {
- container
- .text('')
- .hide();
- }
- return this;
- },
-
- // directional methods
-
- go : function ($ul, direction) {
- var current = $ul.find('.visible'),
- target = current[direction]();
-
- if (target.length) {
- target
- .find('img')
- .trigger('click', [current, target]);
- }
- },
-
- shift : function (current, target, callback) {
- var clearing = target.parent(),
- old_index = this.settings.prev_index || target.index(),
- direction = this.direction(clearing, current, target),
- left = parseInt(clearing.css('left'), 10),
- width = this.outerWidth(target),
- skip_shift;
-
- // we use jQuery animate instead of CSS transitions because we
- // need a callback to unlock the next animation
- if (target.index() !== old_index && !/skip/.test(direction)){
- if (/left/.test(direction)) {
- this.lock();
- clearing.animate({left : left + width}, 300, this.unlock());
- } else if (/right/.test(direction)) {
- this.lock();
- clearing.animate({left : left - width}, 300, this.unlock());
- }
- } else if (/skip/.test(direction)) {
- // the target image is not adjacent to the current image, so
- // do we scroll right or not
- skip_shift = target.index() - this.settings.up_count;
- this.lock();
-
- if (skip_shift > 0) {
- clearing.animate({left : -(skip_shift * width)}, 300, this.unlock());
- } else {
- clearing.animate({left : 0}, 300, this.unlock());
- }
- }
-
- callback();
- },
-
- direction : function ($el, current, target) {
- var lis = $el.find('li'),
- li_width = this.outerWidth(lis) + (this.outerWidth(lis) / 4),
- up_count = Math.floor(this.outerWidth($('.clearing-container')) / li_width) - 1,
- target_index = lis.index(target),
- response;
-
- this.settings.up_count = up_count;
-
- if (this.adjacent(this.settings.prev_index, target_index)) {
- if ((target_index > up_count)
- && target_index > this.settings.prev_index) {
- response = 'right';
- } else if ((target_index > up_count - 1)
- && target_index <= this.settings.prev_index) {
- response = 'left';
- } else {
- response = false;
- }
- } else {
- response = 'skip';
- }
-
- this.settings.prev_index = target_index;
-
- return response;
- },
-
- adjacent : function (current_index, target_index) {
- for (var i = target_index + 1; i >= target_index - 1; i--) {
- if (i === current_index) return true;
- }
- return false;
- },
-
- // lock management
-
- lock : function () {
- this.settings.locked = true;
- },
-
- unlock : function () {
- this.settings.locked = false;
- },
-
- locked : function () {
- return this.settings.locked;
- },
-
- // plugin management/browser quirks
-
- outerHTML : function (el) {
- // support FireFox < 11
- return el.outerHTML || new XMLSerializer().serializeToString(el);
- },
-
- off : function () {
- $(this.scope).off('.fndtn.clearing');
- $(window).off('.fndtn.clearing');
- this.remove_data(); // empty settings cache
- this.settings.init = false;
- },
-
- reflow : function () {
- this.init();
- }
- };
-
- }(Foundation.zj, this, this.document));
|