root / snf-cyclades-app / synnefo / ui / new_ui / ui / javascripts / foundation / foundation.clearing.js @ b3c1328b
History | View | Annotate | Download (13.4 kB)
1 |
/*jslint unparam: true, browser: true, indent: 2 */
|
---|---|
2 |
|
3 |
;(function ($, window, document, undefined) { |
4 |
'use strict';
|
5 |
|
6 |
Foundation.libs.clearing = { |
7 |
name : 'clearing', |
8 |
|
9 |
version : '4.0.0', |
10 |
|
11 |
settings : {
|
12 |
templates : {
|
13 |
viewing : '<a href="#" class="clearing-close">×</a>' + |
14 |
'<div class="visible-img" style="display: none"><img src="//:0">' +
|
15 |
'<p class="clearing-caption"></p><a href="#" class="clearing-main-left"><span></span></a>' +
|
16 |
'<a href="#" class="clearing-main-right"><span></span></a></div>'
|
17 |
}, |
18 |
|
19 |
// comma delimited list of selectors that, on click, will close clearing,
|
20 |
// add 'div.clearing-blackout, div.visible-img' to close on background click
|
21 |
close_selectors : '.clearing-close', |
22 |
|
23 |
// event initializers and locks
|
24 |
init : false, |
25 |
locked : false |
26 |
}, |
27 |
|
28 |
init : function (scope, method, options) { |
29 |
this.scope = this.scope || scope; |
30 |
Foundation.inherit(this, 'set_data get_data remove_data throttle'); |
31 |
|
32 |
if (typeof method === 'object') { |
33 |
options = $.extend(true, this.settings, method); |
34 |
} |
35 |
|
36 |
if (typeof method != 'string') { |
37 |
$(this.scope).find('ul[data-clearing]').each(function () { |
38 |
var self = Foundation.libs.clearing,
|
39 |
$el = $(this), |
40 |
options = options || {}, |
41 |
settings = self.get_data($el);
|
42 |
|
43 |
if (!settings) {
|
44 |
options.$parent = $el.parent(); |
45 |
|
46 |
self.set_data($el, $.extend(true, self.settings, options)); |
47 |
|
48 |
self.assemble($el.find('li')); |
49 |
|
50 |
if (!self.settings.init) {
|
51 |
self.events().swipe_events(); |
52 |
} |
53 |
} |
54 |
}); |
55 |
|
56 |
return this.settings.init; |
57 |
} else {
|
58 |
// fire method
|
59 |
return this[method].call(this, options); |
60 |
} |
61 |
}, |
62 |
|
63 |
// event binding and initial setup
|
64 |
|
65 |
events : function () { |
66 |
var self = this; |
67 |
|
68 |
$(this.scope) |
69 |
.on('click.fndtn.clearing', 'ul[data-clearing] li', |
70 |
function (e, current, target) {
|
71 |
var current = current || $(this), |
72 |
target = target || current, |
73 |
settings = self.get_data(current.parent()); |
74 |
|
75 |
e.preventDefault(); |
76 |
if (!settings) self.init();
|
77 |
|
78 |
// set current and target to the clicked li if not otherwise defined.
|
79 |
self.open($(e.target), current, target);
|
80 |
self.update_paddles(target); |
81 |
}) |
82 |
|
83 |
.on('click.fndtn.clearing', '.clearing-main-right', |
84 |
function (e) { this.nav(e, 'next') }.bind(this)) |
85 |
.on('click.fndtn.clearing', '.clearing-main-left', |
86 |
function (e) { this.nav(e, 'prev') }.bind(this)) |
87 |
.on('click.fndtn.clearing', this.settings.close_selectors, |
88 |
function (e) { Foundation.libs.clearing.close(e, this) }) |
89 |
.on('keydown.fndtn.clearing',
|
90 |
function (e) { this.keydown(e) }.bind(this)); |
91 |
|
92 |
$(window).on('resize.fndtn.clearing', |
93 |
function (e) { this.resize() }.bind(this)); |
94 |
|
95 |
this.settings.init = true; |
96 |
return this; |
97 |
}, |
98 |
|
99 |
swipe_events : function () { |
100 |
var self = this; |
101 |
|
102 |
$(this.scope) |
103 |
.on('touchstart.fndtn.clearing', '.visible-img', function(e) { |
104 |
if (!e.touches) { e = e.originalEvent; }
|
105 |
var data = {
|
106 |
start_page_x: e.touches[0].pageX, |
107 |
start_page_y: e.touches[0].pageY, |
108 |
start_time: (new Date()).getTime(), |
109 |
delta_x: 0, |
110 |
is_scrolling: undefined |
111 |
}; |
112 |
|
113 |
$(this).data('swipe-transition', data); |
114 |
e.stopPropagation(); |
115 |
}) |
116 |
.on('touchmove.fndtn.clearing', '.visible-img', function(e) { |
117 |
if (!e.touches) { e = e.originalEvent; }
|
118 |
// Ignore pinch/zoom events
|
119 |
if(e.touches.length > 1 || e.scale && e.scale !== 1) return; |
120 |
|
121 |
var data = $(this).data('swipe-transition'); |
122 |
|
123 |
if (typeof data === 'undefined') { |
124 |
data = {}; |
125 |
} |
126 |
|
127 |
data.delta_x = e.touches[0].pageX - data.start_page_x;
|
128 |
|
129 |
if ( typeof data.is_scrolling === 'undefined') { |
130 |
data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
|
131 |
} |
132 |
|
133 |
if (!data.is_scrolling && !data.active) {
|
134 |
e.preventDefault(); |
135 |
var direction = (data.delta_x < 0) ? 'next' : 'prev'; |
136 |
data.active = true;
|
137 |
self.nav(e, direction); |
138 |
} |
139 |
}) |
140 |
.on('touchend.fndtn.clearing', '.visible-img', function(e) { |
141 |
$(this).data('swipe-transition', {}); |
142 |
e.stopPropagation(); |
143 |
}); |
144 |
}, |
145 |
|
146 |
assemble : function ($li) { |
147 |
var $el = $li.parent(), |
148 |
settings = this.get_data($el), |
149 |
grid = $el.detach(),
|
150 |
data = { |
151 |
grid: '<div class="carousel">' + this.outerHTML(grid[0]) + '</div>', |
152 |
viewing: settings.templates.viewing
|
153 |
}, |
154 |
wrapper = '<div class="clearing-assembled"><div>' + data.viewing +
|
155 |
data.grid + '</div></div>';
|
156 |
|
157 |
return settings.$parent.append(wrapper); |
158 |
}, |
159 |
|
160 |
// event callbacks
|
161 |
|
162 |
open : function ($image, current, target) { |
163 |
var root = target.closest('.clearing-assembled'), |
164 |
container = root.find('div').first(),
|
165 |
visible_image = container.find('.visible-img'),
|
166 |
image = visible_image.find('img').not($image); |
167 |
|
168 |
if (!this.locked()) { |
169 |
// set the image to the selected thumbnail
|
170 |
image.attr('src', this.load($image)); |
171 |
|
172 |
this.loaded(image, function () { |
173 |
// toggle the gallery
|
174 |
root.addClass('clearing-blackout');
|
175 |
container.addClass('clearing-container');
|
176 |
visible_image.show(); |
177 |
this.fix_height(target)
|
178 |
.caption(visible_image.find('.clearing-caption'), $image) |
179 |
.center(image) |
180 |
.shift(current, target, function () {
|
181 |
target.siblings().removeClass('visible');
|
182 |
target.addClass('visible');
|
183 |
}); |
184 |
}.bind(this));
|
185 |
} |
186 |
}, |
187 |
|
188 |
close : function (e, el) { |
189 |
e.preventDefault(); |
190 |
|
191 |
var root = (function (target) { |
192 |
if (/blackout/.test(target.selector)) { |
193 |
return target;
|
194 |
} else {
|
195 |
return target.closest('.clearing-blackout'); |
196 |
} |
197 |
}($(el))), container, visible_image;
|
198 |
|
199 |
if (el === e.target && root) {
|
200 |
container = root.find('div').first(),
|
201 |
visible_image = container.find('.visible-img');
|
202 |
this.settings.prev_index = 0; |
203 |
root.find('ul[data-clearing]')
|
204 |
.attr('style', '').closest('.clearing-blackout') |
205 |
.removeClass('clearing-blackout');
|
206 |
container.removeClass('clearing-container');
|
207 |
visible_image.hide(); |
208 |
} |
209 |
|
210 |
return false; |
211 |
}, |
212 |
|
213 |
keydown : function (e) { |
214 |
var clearing = $('.clearing-blackout').find('ul[data-clearing]'); |
215 |
|
216 |
if (e.which === 39) this.go(clearing, 'next'); |
217 |
if (e.which === 37) this.go(clearing, 'prev'); |
218 |
if (e.which === 27) $('a.clearing-close').trigger('click'); |
219 |
}, |
220 |
|
221 |
nav : function (e, direction) { |
222 |
var clearing = $('.clearing-blackout').find('ul[data-clearing]'); |
223 |
|
224 |
e.preventDefault(); |
225 |
this.go(clearing, direction);
|
226 |
}, |
227 |
|
228 |
resize : function () { |
229 |
var image = $('.clearing-blackout .visible-img').find('img'); |
230 |
|
231 |
if (image.length) {
|
232 |
this.center(image);
|
233 |
} |
234 |
}, |
235 |
|
236 |
// visual adjustments
|
237 |
fix_height : function (target) { |
238 |
var lis = target.parent().children(),
|
239 |
self = this;
|
240 |
|
241 |
lis.each(function () {
|
242 |
var li = $(this), |
243 |
image = li.find('img');
|
244 |
|
245 |
if (li.height() > self.outerHeight(image)) {
|
246 |
li.addClass('fix-height');
|
247 |
} |
248 |
}) |
249 |
.closest('ul')
|
250 |
.width(lis.length * 100 + '%'); |
251 |
|
252 |
return this; |
253 |
}, |
254 |
|
255 |
update_paddles : function (target) { |
256 |
var visible_image = target
|
257 |
.closest('.carousel')
|
258 |
.siblings('.visible-img');
|
259 |
|
260 |
if (target.next().length) {
|
261 |
visible_image |
262 |
.find('.clearing-main-right')
|
263 |
.removeClass('disabled');
|
264 |
} else {
|
265 |
visible_image |
266 |
.find('.clearing-main-right')
|
267 |
.addClass('disabled');
|
268 |
} |
269 |
|
270 |
if (target.prev().length) {
|
271 |
visible_image |
272 |
.find('.clearing-main-left')
|
273 |
.removeClass('disabled');
|
274 |
} else {
|
275 |
visible_image |
276 |
.find('.clearing-main-left')
|
277 |
.addClass('disabled');
|
278 |
} |
279 |
}, |
280 |
|
281 |
center : function (target) { |
282 |
target.css({ |
283 |
marginLeft : -(this.outerWidth(target) / 2), |
284 |
marginTop : -(this.outerHeight(target) / 2) |
285 |
}); |
286 |
return this; |
287 |
}, |
288 |
|
289 |
// image loading and preloading
|
290 |
|
291 |
load : function ($image) { |
292 |
var href = $image.parent().attr('href'); |
293 |
|
294 |
this.preload($image); |
295 |
|
296 |
if (href) return href; |
297 |
return $image.attr('src'); |
298 |
}, |
299 |
|
300 |
preload : function ($image) { |
301 |
this
|
302 |
.img($image.closest('li').next()) |
303 |
.img($image.closest('li').prev()); |
304 |
}, |
305 |
|
306 |
loaded : function (image, callback) { |
307 |
// based on jquery.imageready.js
|
308 |
// @weblinc, @jsantell, (c) 2012
|
309 |
|
310 |
function loaded () { |
311 |
callback(); |
312 |
} |
313 |
|
314 |
function bindLoad () { |
315 |
this.one('load', loaded); |
316 |
|
317 |
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { |
318 |
var src = this.attr( 'src' ), |
319 |
param = src.match( /\?/ ) ? '&' : '?'; |
320 |
|
321 |
param += 'random=' + (new Date()).getTime(); |
322 |
this.attr('src', src + param); |
323 |
} |
324 |
} |
325 |
|
326 |
if (!image.attr('src')) { |
327 |
loaded(); |
328 |
return;
|
329 |
} |
330 |
|
331 |
if (this.complete || this.readyState === 4) { |
332 |
loaded(); |
333 |
} else {
|
334 |
bindLoad.call(image); |
335 |
} |
336 |
}, |
337 |
|
338 |
img : function (img) { |
339 |
if (img.length) {
|
340 |
var new_img = new Image(), |
341 |
new_a = img.find('a');
|
342 |
|
343 |
if (new_a.length) {
|
344 |
new_img.src = new_a.attr('href');
|
345 |
} else {
|
346 |
new_img.src = img.find('img').attr('src'); |
347 |
} |
348 |
} |
349 |
return this; |
350 |
}, |
351 |
|
352 |
// image caption
|
353 |
|
354 |
caption : function (container, $image) { |
355 |
var caption = $image.data('caption'); |
356 |
|
357 |
if (caption) {
|
358 |
container |
359 |
.text(caption) |
360 |
.show(); |
361 |
} else {
|
362 |
container |
363 |
.text('')
|
364 |
.hide(); |
365 |
} |
366 |
return this; |
367 |
}, |
368 |
|
369 |
// directional methods
|
370 |
|
371 |
go : function ($ul, direction) { |
372 |
var current = $ul.find('.visible'), |
373 |
target = current[direction](); |
374 |
|
375 |
if (target.length) {
|
376 |
target |
377 |
.find('img')
|
378 |
.trigger('click', [current, target]);
|
379 |
} |
380 |
}, |
381 |
|
382 |
shift : function (current, target, callback) { |
383 |
var clearing = target.parent(),
|
384 |
old_index = this.settings.prev_index || target.index(),
|
385 |
direction = this.direction(clearing, current, target),
|
386 |
left = parseInt(clearing.css('left'), 10), |
387 |
width = this.outerWidth(target),
|
388 |
skip_shift; |
389 |
|
390 |
// we use jQuery animate instead of CSS transitions because we
|
391 |
// need a callback to unlock the next animation
|
392 |
if (target.index() !== old_index && !/skip/.test(direction)){ |
393 |
if (/left/.test(direction)) { |
394 |
this.lock();
|
395 |
clearing.animate({left : left + width}, 300, this.unlock()); |
396 |
} else if (/right/.test(direction)) { |
397 |
this.lock();
|
398 |
clearing.animate({left : left - width}, 300, this.unlock()); |
399 |
} |
400 |
} else if (/skip/.test(direction)) { |
401 |
// the target image is not adjacent to the current image, so
|
402 |
// do we scroll right or not
|
403 |
skip_shift = target.index() - this.settings.up_count;
|
404 |
this.lock();
|
405 |
|
406 |
if (skip_shift > 0) { |
407 |
clearing.animate({left : -(skip_shift * width)}, 300, this.unlock()); |
408 |
} else {
|
409 |
clearing.animate({left : 0}, 300, this.unlock()); |
410 |
} |
411 |
} |
412 |
|
413 |
callback(); |
414 |
}, |
415 |
|
416 |
direction : function ($el, current, target) { |
417 |
var lis = $el.find('li'), |
418 |
li_width = this.outerWidth(lis) + (this.outerWidth(lis) / 4), |
419 |
up_count = Math.floor(this.outerWidth($('.clearing-container')) / li_width) - 1, |
420 |
target_index = lis.index(target), |
421 |
response; |
422 |
|
423 |
this.settings.up_count = up_count;
|
424 |
|
425 |
if (this.adjacent(this.settings.prev_index, target_index)) { |
426 |
if ((target_index > up_count)
|
427 |
&& target_index > this.settings.prev_index) {
|
428 |
response = 'right';
|
429 |
} else if ((target_index > up_count - 1) |
430 |
&& target_index <= this.settings.prev_index) {
|
431 |
response = 'left';
|
432 |
} else {
|
433 |
response = false;
|
434 |
} |
435 |
} else {
|
436 |
response = 'skip';
|
437 |
} |
438 |
|
439 |
this.settings.prev_index = target_index;
|
440 |
|
441 |
return response;
|
442 |
}, |
443 |
|
444 |
adjacent : function (current_index, target_index) { |
445 |
for (var i = target_index + 1; i >= target_index - 1; i--) { |
446 |
if (i === current_index) return true; |
447 |
} |
448 |
return false; |
449 |
}, |
450 |
|
451 |
// lock management
|
452 |
|
453 |
lock : function () { |
454 |
this.settings.locked = true; |
455 |
}, |
456 |
|
457 |
unlock : function () { |
458 |
this.settings.locked = false; |
459 |
}, |
460 |
|
461 |
locked : function () { |
462 |
return this.settings.locked; |
463 |
}, |
464 |
|
465 |
// plugin management/browser quirks
|
466 |
|
467 |
outerHTML : function (el) { |
468 |
// support FireFox < 11
|
469 |
return el.outerHTML || new XMLSerializer().serializeToString(el); |
470 |
}, |
471 |
|
472 |
off : function () { |
473 |
$(this.scope).off('.fndtn.clearing'); |
474 |
$(window).off('.fndtn.clearing'); |
475 |
this.remove_data(); // empty settings cache |
476 |
this.settings.init = false; |
477 |
} |
478 |
}; |
479 |
|
480 |
}(Foundation.zj, this, this.document)); |