source: trunk/client/temi/spectral/assets/js/util.js@ 404

Last change on this file since 404 was 241, checked in by luc, 9 years ago

Aggiunta del widget Privacy e CookieLaw per l'informativa sui cookie - Aggiunto Tema Realistic - Aggiunto Tema Spectral

  • Property svn:executable set to *
File size: 12.1 KB
Line 
1(function($) {
2
3 /**
4 * Generate an indented list of links from a nav. Meant for use with panel().
5 * @return {jQuery} jQuery object.
6 */
7 $.fn.navList = function() {
8
9 var $this = $(this);
10 $a = $this.find('a'),
11 b = [];
12
13 $a.each(function() {
14
15 var $this = $(this),
16 indent = Math.max(0, $this.parents('li').length - 1),
17 href = $this.attr('href'),
18 target = $this.attr('target');
19
20 b.push(
21 '<a ' +
22 'class="link depth-' + indent + '"' +
23 ( (typeof target !== 'undefined' && target != '') ? ' target="' + target + '"' : '') +
24 ( (typeof href !== 'undefined' && href != '') ? ' href="' + href + '"' : '') +
25 '>' +
26 '<span class="indent-' + indent + '"></span>' +
27 $this.text() +
28 '</a>'
29 );
30
31 });
32
33 return b.join('');
34
35 };
36
37 /**
38 * Panel-ify an element.
39 * @param {object} userConfig User config.
40 * @return {jQuery} jQuery object.
41 */
42 $.fn.panel = function(userConfig) {
43
44 // No elements?
45 if (this.length == 0)
46 return $this;
47
48 // Multiple elements?
49 if (this.length > 1) {
50
51 for (var i=0; i < this.length; i++)
52 $(this[i]).panel(userConfig);
53
54 return $this;
55
56 }
57
58 // Vars.
59 var $this = $(this),
60 $body = $('body'),
61 $window = $(window),
62 id = $this.attr('id'),
63 config;
64
65 // Config.
66 config = $.extend({
67
68 // Delay.
69 delay: 0,
70
71 // Hide panel on link click.
72 hideOnClick: false,
73
74 // Hide panel on escape keypress.
75 hideOnEscape: false,
76
77 // Hide panel on swipe.
78 hideOnSwipe: false,
79
80 // Reset scroll position on hide.
81 resetScroll: false,
82
83 // Reset forms on hide.
84 resetForms: false,
85
86 // Side of viewport the panel will appear.
87 side: null,
88
89 // Target element for "class".
90 target: $this,
91
92 // Class to toggle.
93 visibleClass: 'visible'
94
95 }, userConfig);
96
97 // Expand "target" if it's not a jQuery object already.
98 if (typeof config.target != 'jQuery')
99 config.target = $(config.target);
100
101 // Panel.
102
103 // Methods.
104 $this._hide = function(event) {
105
106 // Already hidden? Bail.
107 if (!config.target.hasClass(config.visibleClass))
108 return;
109
110 // If an event was provided, cancel it.
111 if (event) {
112
113 event.preventDefault();
114 event.stopPropagation();
115
116 }
117
118 // Hide.
119 config.target.removeClass(config.visibleClass);
120
121 // Post-hide stuff.
122 window.setTimeout(function() {
123
124 // Reset scroll position.
125 if (config.resetScroll)
126 $this.scrollTop(0);
127
128 // Reset forms.
129 if (config.resetForms)
130 $this.find('form').each(function() {
131 this.reset();
132 });
133
134 }, config.delay);
135
136 };
137
138 // Vendor fixes.
139 $this
140 .css('-ms-overflow-style', '-ms-autohiding-scrollbar')
141 .css('-webkit-overflow-scrolling', 'touch');
142
143 // Hide on click.
144 if (config.hideOnClick) {
145
146 $this.find('a')
147 .css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
148
149 $this
150 .on('click', 'a', function(event) {
151
152 var $a = $(this),
153 href = $a.attr('href'),
154 target = $a.attr('target');
155
156 if (!href || href == '#' || href == '' || href == '#' + id)
157 return;
158
159 // Cancel original event.
160 event.preventDefault();
161 event.stopPropagation();
162
163 // Hide panel.
164 $this._hide();
165
166 // Redirect to href.
167 window.setTimeout(function() {
168
169 if (target == '_blank')
170 window.open(href);
171 else
172 window.location.href = href;
173
174 }, config.delay + 10);
175
176 });
177
178 }
179
180 // Event: Touch stuff.
181 $this.on('touchstart', function(event) {
182
183 $this.touchPosX = event.originalEvent.touches[0].pageX;
184 $this.touchPosY = event.originalEvent.touches[0].pageY;
185
186 })
187
188 $this.on('touchmove', function(event) {
189
190 if ($this.touchPosX === null
191 || $this.touchPosY === null)
192 return;
193
194 var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX,
195 diffY = $this.touchPosY - event.originalEvent.touches[0].pageY,
196 th = $this.outerHeight(),
197 ts = ($this.get(0).scrollHeight - $this.scrollTop());
198
199 // Hide on swipe?
200 if (config.hideOnSwipe) {
201
202 var result = false,
203 boundary = 20,
204 delta = 50;
205
206 switch (config.side) {
207
208 case 'left':
209 result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);
210 break;
211
212 case 'right':
213 result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));
214 break;
215
216 case 'top':
217 result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta);
218 break;
219
220 case 'bottom':
221 result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta));
222 break;
223
224 default:
225 break;
226
227 }
228
229 if (result) {
230
231 $this.touchPosX = null;
232 $this.touchPosY = null;
233 $this._hide();
234
235 return false;
236
237 }
238
239 }
240
241 // Prevent vertical scrolling past the top or bottom.
242 if (($this.scrollTop() < 0 && diffY < 0)
243 || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
244
245 event.preventDefault();
246 event.stopPropagation();
247
248 }
249
250 });
251
252 // Event: Prevent certain events inside the panel from bubbling.
253 $this.on('click touchend touchstart touchmove', function(event) {
254 event.stopPropagation();
255 });
256
257 // Event: Hide panel if a child anchor tag pointing to its ID is clicked.
258 $this.on('click', 'a[href="#' + id + '"]', function(event) {
259
260 event.preventDefault();
261 event.stopPropagation();
262
263 config.target.removeClass(config.visibleClass);
264
265 });
266
267 // Body.
268
269 // Event: Hide panel on body click/tap.
270 $body.on('click touchend', function(event) {
271 $this._hide(event);
272 });
273
274 // Event: Toggle.
275 $body.on('click', 'a[href="#' + id + '"]', function(event) {
276
277 event.preventDefault();
278 event.stopPropagation();
279
280 config.target.toggleClass(config.visibleClass);
281
282 });
283
284 // Window.
285
286 // Event: Hide on ESC.
287 if (config.hideOnEscape)
288 $window.on('keydown', function(event) {
289
290 if (event.keyCode == 27)
291 $this._hide(event);
292
293 });
294
295 return $this;
296
297 };
298
299 /**
300 * Apply "placeholder" attribute polyfill to one or more forms.
301 * @return {jQuery} jQuery object.
302 */
303 $.fn.placeholder = function() {
304
305 // Browser natively supports placeholders? Bail.
306 if (typeof (document.createElement('input')).placeholder != 'undefined')
307 return $(this);
308
309 // No elements?
310 if (this.length == 0)
311 return $this;
312
313 // Multiple elements?
314 if (this.length > 1) {
315
316 for (var i=0; i < this.length; i++)
317 $(this[i]).placeholder();
318
319 return $this;
320
321 }
322
323 // Vars.
324 var $this = $(this);
325
326 // Text, TextArea.
327 $this.find('input[type=text],textarea')
328 .each(function() {
329
330 var i = $(this);
331
332 if (i.val() == ''
333 || i.val() == i.attr('placeholder'))
334 i
335 .addClass('polyfill-placeholder')
336 .val(i.attr('placeholder'));
337
338 })
339 .on('blur', function() {
340
341 var i = $(this);
342
343 if (i.attr('name').match(/-polyfill-field$/))
344 return;
345
346 if (i.val() == '')
347 i
348 .addClass('polyfill-placeholder')
349 .val(i.attr('placeholder'));
350
351 })
352 .on('focus', function() {
353
354 var i = $(this);
355
356 if (i.attr('name').match(/-polyfill-field$/))
357 return;
358
359 if (i.val() == i.attr('placeholder'))
360 i
361 .removeClass('polyfill-placeholder')
362 .val('');
363
364 });
365
366 // Password.
367 $this.find('input[type=password]')
368 .each(function() {
369
370 var i = $(this);
371 var x = $(
372 $('<div>')
373 .append(i.clone())
374 .remove()
375 .html()
376 .replace(/type="password"/i, 'type="text"')
377 .replace(/type=password/i, 'type=text')
378 );
379
380 if (i.attr('id') != '')
381 x.attr('id', i.attr('id') + '-polyfill-field');
382
383 if (i.attr('name') != '')
384 x.attr('name', i.attr('name') + '-polyfill-field');
385
386 x.addClass('polyfill-placeholder')
387 .val(x.attr('placeholder')).insertAfter(i);
388
389 if (i.val() == '')
390 i.hide();
391 else
392 x.hide();
393
394 i
395 .on('blur', function(event) {
396
397 event.preventDefault();
398
399 var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
400
401 if (i.val() == '') {
402
403 i.hide();
404 x.show();
405
406 }
407
408 });
409
410 x
411 .on('focus', function(event) {
412
413 event.preventDefault();
414
415 var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']');
416
417 x.hide();
418
419 i
420 .show()
421 .focus();
422
423 })
424 .on('keypress', function(event) {
425
426 event.preventDefault();
427 x.val('');
428
429 });
430
431 });
432
433 // Events.
434 $this
435 .on('submit', function() {
436
437 $this.find('input[type=text],input[type=password],textarea')
438 .each(function(event) {
439
440 var i = $(this);
441
442 if (i.attr('name').match(/-polyfill-field$/))
443 i.attr('name', '');
444
445 if (i.val() == i.attr('placeholder')) {
446
447 i.removeClass('polyfill-placeholder');
448 i.val('');
449
450 }
451
452 });
453
454 })
455 .on('reset', function(event) {
456
457 event.preventDefault();
458
459 $this.find('select')
460 .val($('option:first').val());
461
462 $this.find('input,textarea')
463 .each(function() {
464
465 var i = $(this),
466 x;
467
468 i.removeClass('polyfill-placeholder');
469
470 switch (this.type) {
471
472 case 'submit':
473 case 'reset':
474 break;
475
476 case 'password':
477 i.val(i.attr('defaultValue'));
478
479 x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
480
481 if (i.val() == '') {
482 i.hide();
483 x.show();
484 }
485 else {
486 i.show();
487 x.hide();
488 }
489
490 break;
491
492 case 'checkbox':
493 case 'radio':
494 i.attr('checked', i.attr('defaultValue'));
495 break;
496
497 case 'text':
498 case 'textarea':
499 i.val(i.attr('defaultValue'));
500
501 if (i.val() == '') {
502 i.addClass('polyfill-placeholder');
503 i.val(i.attr('placeholder'));
504 }
505
506 break;
507
508 default:
509 i.val(i.attr('defaultValue'));
510 break;
511
512 }
513 });
514
515 });
516
517 return $this;
518
519 };
520
521 /**
522 * Moves elements to/from the first positions of their respective parents.
523 * @param {jQuery} $elements Elements (or selector) to move.
524 * @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations.
525 */
526 $.prioritize = function($elements, condition) {
527
528 var key = '__prioritize';
529
530 // Expand $elements if it's not already a jQuery object.
531 if (typeof $elements != 'jQuery')
532 $elements = $($elements);
533
534 // Step through elements.
535 $elements.each(function() {
536
537 var $e = $(this), $p,
538 $parent = $e.parent();
539
540 // No parent? Bail.
541 if ($parent.length == 0)
542 return;
543
544 // Not moved? Move it.
545 if (!$e.data(key)) {
546
547 // Condition is false? Bail.
548 if (!condition)
549 return;
550
551 // Get placeholder (which will serve as our point of reference for when this element needs to move back).
552 $p = $e.prev();
553
554 // Couldn't find anything? Means this element's already at the top, so bail.
555 if ($p.length == 0)
556 return;
557
558 // Move element to top of parent.
559 $e.prependTo($parent);
560
561 // Mark element as moved.
562 $e.data(key, $p);
563
564 }
565
566 // Moved already?
567 else {
568
569 // Condition is true? Bail.
570 if (condition)
571 return;
572
573 $p = $e.data(key);
574
575 // Move element back to its original location (using our placeholder).
576 $e.insertAfter($p);
577
578 // Unmark element as moved.
579 $e.removeData(key);
580
581 }
582
583 });
584
585 };
586
587})(jQuery);
Note: See TracBrowser for help on using the repository browser.