PageSourceSearch

https://bureau.umalis.fr/scripts/jquery.main.js

js umalis.fr collected 2026-10-08 07:02:47 UTC 93,526 bytes, 2,719 lines download raw bytes

1// page init
2jQuery(function(){
3	//jcf.customForms.replaceAll();
4	//initCarousel();
5	//initSlideShow();
6	//initAccordion();
7	//initInputs();
8	//initSameHeight();
9});
10
11// scroll galleries init
12function initCarousel() {
13	jQuery('div.testimonials-gallery').scrollGallery({
14		mask: 'div.mask',
15		slider: '> ul',
16		slides: '> li',
17		btnPrev: 'a.btn-prev',
18		btnNext: 'a.btn-next',
19		generatePagination: 'div.switcher',
20		stretchSlideToMask: true,
21		autoRotation: false,
22		switchTime: 3000,
23		animSpeed: 500
24	});
25	jQuery('div.slide-gallery').scrollGallery({
26		mask: 'div.mask',
27		slider: '> ul',
28		slides: '> li',
29		btnPrev: 'a.btn-prev',
30		btnNext: 'a.btn-next',
31		generatePagination: 'div.switcher',
32		stretchSlideToMask: true,
33		circularRotation: false,
34		autoRotation: false,
35		switchTime: 3000,
36		animSpeed: 500
37	});
38}
39
40// fade gallery init
41function initSlideShow() {
42	jQuery('div.main-gallery').fadeGallery({
43		slides: '.slides li',
44		pagerLinks: 'ul.switcher li',
45		event: 'mouseenter',
46		disableWhileAnimating: true,
47		autoRotation: false,
48		autoHeight: true,
49		switchTime: 3000,
50		animSpeed: 500
51	});
52}
53
54// accordion menu init
55function initAccordion() {
56	jQuery('ul.accordion').slideAccordion({
57		opener: 'a.opener',
58		slider: 'div.slide',
59		animSpeed: 300
60	});
61}
62
63// clear inputs on focus
64function initInputs() {
65	PlaceholderInput.replaceByOptions({
66		// filter options
67		clearInputs: false,
68		clearTextareas: false,
69		clearPasswords: true,
70		skipClass: 'default',
71		
72		// input options
73		wrapWithElement: false,
74		showUntilTyping: false,
75		getParentByClass: false,
76		placeholderAttr: 'value'
77	});
78}
79
80// align blocks height
81function initSameHeight() {
82	jQuery('div.two-columns').sameHeight({
83		elements: 'div.column',
84		useMinHeight: true
85	});
86	jQuery('div.twocolumns').sameHeight({
87		elements: 'div.column',
88		useMinHeight: true
89	});
90	jQuery('#footer .frame').sameHeight({
91		elements: 'div.column',
92		useMinHeight: true
93	});
94}
95
96/*
97 * jQuery Carousel plugin
98 */
99;(function($){
100	function ScrollGallery(options) {
101		this.options = $.extend({
102			mask: 'div.mask',
103			slider: '>*',
104			slides: '>*',
105			activeClass:'active',
106			disabledClass:'disabled',
107			btnPrev: 'a.btn-prev',
108			btnNext: 'a.btn-next',
109			generatePagination: false,
110			pagerList: '<ul>',
111			pagerListItem: '<li><a href="#"></a></li>',
112			pagerListItemText: 'a',
113			pagerLinks: '.pagination li',
114			currentNumber: 'span.current-num',
115			totalNumber: 'span.total-num',
116			btnPlay: '.btn-play',
117			btnPause: '.btn-pause',
118			btnPlayPause: '.btn-play-pause',
119			autorotationActiveClass: 'autorotation-active',
120			autorotationDisabledClass: 'autorotation-disabled',
121			stretchSlideToMask: false,
122			circularRotation: true,
123			disableWhileAnimating: false,
124			autoRotation: false,
125			pauseOnHover: isTouchDevice ? false : true,
126			maskAutoSize: false,
127			switchTime: 4000,
128			animSpeed: 600,
129			event:'click',
130			swipeGap: false,
131			swipeThreshold: 50,
132			handleTouch: true,
133			vertical: false,
134			useTranslate3D: false,
135			step: false
136		}, options);
137		this.init();
138	}
139	ScrollGallery.prototype = {
140		init: function() {
141			if(this.options.holder) {
142				this.findElements();
143				this.attachEvents();
144				this.refreshPosition();
145				this.refreshState(true);
146				this.resumeRotation();
147				this.makeCallback('onInit', this);
148			}
149		},
150		findElements: function() {
151			// define dimensions proporties
152			this.fullSizeFunction = this.options.vertical ? 'outerHeight' : 'outerWidth';
153			this.innerSizeFunction = this.options.vertical ? 'height' : 'width';
154			this.slideSizeFunction = 'outerHeight';
155			this.maskSizeProperty = 'height';
156			this.animProperty = this.options.vertical ? 'marginTop' : 'marginLeft';
157			this.swipeProperties = this.options.vertical ? ['up', 'down'] : ['left', 'right'];
158			
159			// control elements
160			this.gallery = $(this.options.holder);
161			this.mask = this.gallery.find(this.options.mask);
162			this.slider = this.mask.find(this.options.slider);
163			this.slides = this.slider.find(this.options.slides);
164			this.btnPrev = this.gallery.find(this.options.btnPrev);
165			this.btnNext = this.gallery.find(this.options.btnNext);
166			this.currentStep = 0; this.stepsCount = 0;
167			
168			// get start index
169			if(this.options.step === false) {
170				var activeSlide = this.slides.filter('.'+this.options.activeClass);
171				if(activeSlide.length) {
172					this.currentStep = this.slides.index(activeSlide);
173				}
174			}
175			
176			// calculate offsets
177			this.calculateOffsets();
178			$(window).bind('load resize orientationchange', $.proxy(this.onWindowResize, this));
179			
180			// create gallery pagination
181			if(typeof this.options.generatePagination === 'string') {
182				this.pagerLinks = $();
183				this.buildPagination();
184			} else {
185				this.pagerLinks = this.gallery.find(this.options.pagerLinks);
186				this.attachPaginationEvents();
187			}
188			
189			// autorotation control buttons
190			this.btnPlay = this.gallery.find(this.options.btnPlay);
191			this.btnPause = this.gallery.find(this.options.btnPause);
192			this.btnPlayPause = this.gallery.find(this.options.btnPlayPause);
193			
194			// misc elements
195			this.curNum = this.gallery.find(this.options.currentNumber);
196			this.allNum = this.gallery.find(this.options.totalNumber);
197		},
198		attachEvents: function() {
199			this.btnPrev.bind(this.options.event, this.bindScope(function(e){
200				this.prevSlide();
201				e.preventDefault();
202			}));
203			this.btnNext.bind(this.options.event, this.bindScope(function(e){
204				this.nextSlide();
205				e.preventDefault();
206			}));
207			
208			// pause on hover handling
209			if(this.options.pauseOnHover) {
210				this.gallery.hover(this.bindScope(function(){
211					if(this.options.autoRotation) {
212						this.galleryHover = true;
213						this.pauseRotation();
214					}
215				}), this.bindScope(function(){
216					if(this.options.autoRotation) {
217						this.galleryHover = false;
218						this.resumeRotation();
219					}
220				}));
221			}
222			
223			// autorotation buttons handler
224			this.btnPlay.bind(this.options.event, this.bindScope(this.startRotation));
225			this.btnPause.bind(this.options.event, this.bindScope(this.stopRotation));
226			this.btnPlayPause.bind(this.options.event, this.bindScope(function(){
227				if(!this.gallery.hasClass(this.options.autorotationActiveClass)) {
228					this.startRotation();
229				} else {
230					this.stopRotation();
231				}
232			}));
233			
234			// swipe event handling
235			if(isTouchDevice) {
236				// enable hardware acceleration
237				if(this.options.useTranslate3D) {
238					this.slider.css({'-webkit-transform': 'translate3d(0px, 0px, 0px)'});
239				}
240				
241				// swipe gestures
242				if(this.options.handleTouch && $.fn.swipe) {
243					this.mask.swipe({
244						fallbackToMouseEvents: false,
245						threshold: this.options.swipeThreshold,
246						allowPageScroll: 'vertical',
247						swipeStatus: $.proxy(function(e, phase, direction, distance) {
248							if(phase === 'start') {
249								this.originalOffset = parseInt(this.slider.stop(true, false).css(this.animProperty));
250							} else if(phase === 'move') {
251								if(direction === this.swipeProperties[0] || direction === this.swipeProperties[1]) {
252									var tmpOffset = this.originalOffset + distance * (direction === this.swipeProperties[0] ? -1 : 1);
253									if(!this.options.swipeGap) {
254										tmpOffset = Math.max(Math.min(0, tmpOffset), this.maxOffset);
255									}
256									this.tmpProps = {};
257									this.tmpProps[this.animProperty] = tmpOffset;
258									this.slider.css(this.tmpProps);
259									e.preventDefault();
260								}
261							} else if(phase === 'cancel') {
262								// return to previous position
263								this.switchSlide();
264							}
265						},this),
266						swipe: $.proxy(function(event, direction) {
267							if(direction === this.swipeProperties[0]) {
268								if(this.currentStep === this.stepsCount - 1) this.switchSlide();
269								else this.nextSlide();
270							} else if(direction === this.swipeProperties[1]) {
271								if(this.currentStep === 0) this.switchSlide();
272								else this.prevSlide();
273							}
274						},this)
275					});
276				}
277			}
278		},
279		onWindowResize: function() {
280			if(!this.galleryAnimating) {
281				this.calculateOffsets();
282				this.refreshPosition();
283				this.buildPagination();
284				this.refreshState();
285				this.resizeQueue = false;
286			} else {
287				this.resizeQueue = true;
288			}
289		},
290		refreshPosition: function() {
291			this.currentStep = Math.min(this.currentStep, this.stepsCount - 1);
292			this.tmpProps = {};
293			this.tmpProps[this.animProperty] = this.getStepOffset();
294			this.slider.stop().css(this.tmpProps);
295		},
296		calculateOffsets: function() {
297			if(this.options.stretchSlideToMask) {
298				var tmpObj = {};
299				tmpObj[this.innerSizeFunction] = this.mask[this.innerSizeFunction]();
300				this.slides.css(tmpObj);
301			}
302			
303			this.maskSize = this.mask[this.innerSizeFunction]();
304			this.sumSize = this.getSumSize();
305			this.maxOffset = this.maskSize - this.sumSize;
306			
307			// vertical gallery with single size step custom behavior
308			if(this.options.vertical && this.options.maskAutoSize) {
309				this.options.step = 1;
310				this.stepsCount = this.slides.length;
311				this.stepOffsets = [0];
312				var tmpOffset = 0;
313				for(var i = 0; i < this.slides.length; i++) {
314					tmpOffset -= $(this.slides[i])[this.fullSizeFunction](true);
315					this.stepOffsets.push(tmpOffset);
316				}
317				this.maxOffset = tmpOffset;
318				return;
319			}
320			
321			// scroll by slide size
322			if(typeof this.options.step === 'number' && this.options.step > 0) {
323				this.slideDimensions = [];
324				this.slides.each($.proxy(function(ind, obj){
325					this.slideDimensions.push( $(obj)[this.fullSizeFunction](true) );
326				},this));
327				
328				// calculate steps count
329				this.stepOffsets = [0];
330				this.stepsCount = 1;
331				var tmpOffset = 0, tmpStep = 0;
332				while(tmpOffset > this.maxOffset) {
333					tmpOffset -= this.getSlideSize(tmpStep, tmpStep + this.options.step);
334					tmpStep += this.options.step;
335					this.stepOffsets.push(Math.max(tmpOffset, this.maxOffset));
336					this.stepsCount++;
337				}
338			}
339			// scroll by mask size
340			else {
341				// define step size
342				this.stepSize = this.maskSize;
343				
344				// calculate steps count
345				this.stepsCount = 1;
346				var tmpOffset = 0;
347				while(tmpOffset > this.maxOffset) {
348					tmpOffset -= this.stepSize;
349					this.stepsCount++;
350				}
351			}
352		},
353		getSumSize: function() {
354			var sum = 0;
355			this.slides.each($.proxy(function(ind, obj){
356				sum += $(obj)[this.fullSizeFunction](true);
357			},this));
358			this.slider.css(this.innerSizeFunction, sum);
359			return sum;
360		},
361		getStepOffset: function(step) {
362			step = step || this.currentStep;
363			if(typeof this.options.step === 'number') {
364				return this.stepOffsets[this.currentStep];
365			} else {
366				return Math.max(-this.currentStep * this.stepSize, this.maxOffset);
367			}
368		},
369		getSlideSize: function(i1, i2) {
370			var sum = 0;
371			for(var i = i1; i < Math.min(i2, this.slideDimensions.length); i++) {
372				sum += this.slideDimensions[i];
373			}
374			return sum;
375		},
376		buildPagination: function() {
377			if(typeof this.options.generatePagination === 'string') {
378				if(!this.pagerHolder) {
379					this.pagerHolder = this.gallery.find(this.options.generatePagination);
380				}
381				if(this.pagerHolder.length && this.oldStepsCount != this.stepsCount) {
382					this.oldStepsCount = this.stepsCount;
383					this.pagerHolder.empty();
384					this.pagerList = $(this.options.pagerList).appendTo(this.pagerHolder);
385					for(var i = 0; i < this.stepsCount; i++) {
386						$(this.options.pagerListItem).appendTo(this.pagerList).find(this.options.pagerListItemText).text(i+1);
387					}
388					this.pagerLinks = this.pagerList.children();
389					this.attachPaginationEvents();
390				}
391			}
392		},
393		attachPaginationEvents: function() {
394			this.pagerLinks.each(this.bindScope(function(ind, obj){
395				$(obj).bind(this.options.event, this.bindScope(function(){
396					this.numSlide(ind);
397					return false;
398				}));
399			}));
400		},
401		prevSlide: function() {
402			if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
403				if(this.currentStep > 0) {
404					this.currentStep--;
405					this.switchSlide();
406				} else if(this.options.circularRotation) {
407					this.currentStep = this.stepsCount - 1;
408					this.switchSlide();
409				}
410			}
411		},
412		nextSlide: function(fromAutoRotation) {
413			if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
414				if(this.currentStep < this.stepsCount - 1) {
415					this.currentStep++;
416					this.switchSlide();
417				} else if(this.options.circularRotation || fromAutoRotation === true) {
418					this.currentStep = 0;
419					this.switchSlide();
420				}
421			}
422		},
423		numSlide: function(c) {
424			if(this.currentStep != c) {
425				this.currentStep = c;
426				this.switchSlide();
427			}
428		},
429		switchSlide: function() {
430			this.galleryAnimating = true;
431			this.tmpProps = {}
432			this.tmpProps[this.animProperty] = this.getStepOffset();
433			this.slider.stop().animate(this.tmpProps,{duration: this.options.animSpeed, complete: this.bindScope(function(){
434				// animation complete
435				this.galleryAnimating = false;
436				if(this.resizeQueue) {
437					this.onWindowResize();
438				}
439				
440				// onchange callback
441				this.makeCallback('onChange', this);
442				this.autoRotate();
443			})});
444			this.refreshState();
445			
446			// onchange callback
447			this.makeCallback('onBeforeChange', this);
448		},
449		refreshState: function(initial) {
450			if(this.options.step === 1 || this.stepsCount === this.slides.length) {
451				this.slides.removeClass(this.options.activeClass).eq(this.currentStep).addClass(this.options.activeClass);
452			}
453			this.pagerLinks.removeClass(this.options.activeClass).eq(this.currentStep).addClass(this.options.activeClass);
454			this.curNum.html(this.currentStep+1);
455			this.allNum.html(this.stepsCount);
456			
457			// initial refresh
458			if(this.options.maskAutoSize && typeof this.options.step === 'number') {
459				this.tmpProps = {};
460				this.tmpProps[this.maskSizeProperty] = this.slides.eq(Math.min(this.currentStep,this.slides.length-1))[this.slideSizeFunction](true);
461				this.mask.stop()[initial ? 'css' : 'animate'](this.tmpProps);
462			}
463			
464			// disabled state
465			if(!this.options.circularRotation) {
466				this.btnPrev.add(this.btnNext).removeClass(this.options.disabledClass);
467				if(this.currentStep === 0) this.btnPrev.addClass(this.options.disabledClass);
468				if(this.currentStep === this.stepsCount - 1) this.btnNext.addClass(this.options.disabledClass);
469			}
470		},
471		startRotation: function() {
472			this.options.autoRotation = true;
473			this.galleryHover = false;
474			this.autoRotationStopped = false;
475			this.resumeRotation();
476		},
477		stopRotation: function() {
478			this.galleryHover = true;
479			this.autoRotationStopped = true;
480			this.pauseRotation();
481		},
482		pauseRotation: function() {
483			this.gallery.addClass(this.options.autorotationDisabledClass);
484			this.gallery.removeClass(this.options.autorotationActiveClass);
485			clearTimeout(this.timer);
486		},
487		resumeRotation: function() {
488			if(!this.autoRotationStopped) {
489				this.gallery.addClass(this.options.autorotationActiveClass);
490				this.gallery.removeClass(this.options.autorotationDisabledClass);
491				this.autoRotate();
492			}
493		},
494		autoRotate: function() {
495			clearTimeout(this.timer);
496			if(this.options.autoRotation && !this.galleryHover && !this.autoRotationStopped) {
497				this.timer = setTimeout(this.bindScope(function(){
498					this.nextSlide(true);
499				}), this.options.switchTime);
500			} else {
501				this.pauseRotation();
502			}
503		},
504		bindScope: function(func, scope) {
505			return $.proxy(func, scope || this);
506		},
507		makeCallback: function(name) {
508			if(typeof this.options[name] === 'function') {
509				var args = Array.prototype.slice.call(arguments);
510				args.shift();
511				this.options[name].apply(this, args);
512			}
513		}
514	};
515	
516	// detect device type
517	var isTouchDevice = (function() {
518		try {
519			return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
520		} catch (e) {
521			return false;
522		}
523	}());
524	
525	// jquery plugin
526	$.fn.scrollGallery = function(opt){
527		return this.each(function(){
528			$(this).data('ScrollGallery', new ScrollGallery($.extend(opt,{holder:this})));
529		});
530	};
531}(jQuery));
532
533/*
534 * jQuery SlideShow plugin
535 */
536;(function($){
537	function FadeGallery(options) {
538		this.options = $.extend({
539			slides: 'ul.slideset > li',
540			activeClass:'active',
541			disabledClass:'disabled',
542			btnPrev: 'a.btn-prev',
543			btnNext: 'a.btn-next',
544			generatePagination: false,
545			pagerList: '<ul>',
546			pagerListItem: '<li><a href="#"></a></li>',
547			pagerListItemText: 'a',
548			pagerLinks: '.pagination li',
549			currentNumber: 'span.current-num',
550			totalNumber: 'span.total-num',
551			btnPlay: '.btn-play',
552			btnPause: '.btn-pause',
553			btnPlayPause: '.btn-play-pause',
554			autorotationActiveClass: 'autorotation-active',
555			autorotationDisabledClass: 'autorotation-disabled',
556			autorotationStopAfterClick: false,
557			circularRotation: true,
558			switchSimultaneously: true,
559			disableWhileAnimating: false,
560			disableFadeIE: false,
561			autoRotation: false,
562			pauseOnHover: true,
563			autoHeight: false,
564			useSwipe: false,
565			switchTime: 4000,
566			animSpeed: 600,
567			event:'click'
568		}, options);
569		this.init();
570	}
571	FadeGallery.prototype = {
572		init: function() {
573			if(this.options.holder) {
574				this.findElements();
575				this.initStructure();
576				this.attachEvents();
577				this.refreshState(true);
578				this.autoRotate();
579				this.makeCallback('onInit', this);
580			}
581		},
582		findElements: function() {
583			// control elements
584			this.gallery = $(this.options.holder);
585			this.slides = this.gallery.find(this.options.slides);
586			this.slidesHolder = this.slides.eq(0).parent();
587			this.stepsCount = this.slides.length;
588			this.btnPrev = this.gallery.find(this.options.btnPrev);
589			this.btnNext = this.gallery.find(this.options.btnNext);
590			this.currentIndex = 0;
591			
592			// disable fade effect in old IE
593			if(this.options.disableFadeIE && $.browser.msie && $.browser.version < 9) {
594				this.options.animSpeed = 0;
595			}
596			
597			// create gallery pagination
598			if(typeof this.options.generatePagination === 'string') {
599				this.pagerHolder = this.gallery.find(this.options.generatePagination).empty();
600				this.pagerList = $(this.options.pagerList).appendTo(this.pagerHolder);
601				for(var i = 0; i < this.stepsCount; i++) {
602					$(this.options.pagerListItem).appendTo(this.pagerList).find(this.options.pagerListItemText).text(i+1);
603				}
604				this.pagerLinks = this.pagerList.children();
605			} else {
606				this.pagerLinks = this.gallery.find(this.options.pagerLinks);
607			}
608			
609			// get start index
610			var activeSlide = this.slides.filter('.'+this.options.activeClass);
611			if(activeSlide.length) {
612				this.currentIndex = this.slides.index(activeSlide);
613			}
614			this.prevIndex = this.currentIndex;
615			
616			// autorotation control buttons
617			this.btnPlay = this.gallery.find(this.options.btnPlay);
618			this.btnPause = this.gallery.find(this.options.btnPause);
619			this.btnPlayPause = this.gallery.find(this.options.btnPlayPause);
620			
621			// misc elements
622			this.curNum = this.gallery.find(this.options.currentNumber);
623			this.allNum = this.gallery.find(this.options.totalNumber);
624			
625			// handle flexible layout
626			$(window).bind('load resize orientationchange', $.proxy(this.onWindowResize, this));
627		},
628		initStructure: function() {
629			this.slides.css({display:'block',opacity:0}
629).eq(this.currentIndex).css({
630				opacity:''
631			});
632		},
633		attachEvents: function() {
634			var self = this;
635			this.btnPrev.bind(this.options.event, function(e){
636				self.prevSlide();
637				if(self.options.autorotationStopAfterClick) {
638					self.stopRotation();
639				}
640				e.preventDefault();
641			});
642			this.btnNext.bind(this.options.event, function(e){
643				self.nextSlide();
644				if(self.options.autorotationStopAfterClick) {
645					self.stopRotation();
646				}
647				e.preventDefault();
648			});
649			this.pagerLinks.each(function(ind, obj){
650				$(obj).bind(self.options.event, function(e){
651					self.numSlide(ind);
652					if(self.options.autorotationStopAfterClick) {
653						self.stopRotation();
654					}
655					e.preventDefault();
656				});
657			});
658			
659			// autorotation buttons handler
660			this.btnPlay.bind(this.options.event, function(e){
661				self.startRotation();
662				e.preventDefault();
663			});
664			this.btnPause.bind(this.options.event, function(e){
665				self.stopRotation();
666				e.preventDefault();
667			});
668			this.btnPlayPause.bind(this.options.event, function(e){
669				if(!self.gallery.hasClass(self.options.autorotationActiveClass)) {
670					self.startRotation();
671				} else {
672					self.stopRotation();
673				}
674				e.preventDefault();
675			});
676
677			// swipe gestures handler
678			if(this.options.useSwipe && $.fn.swipe) {
679				this.gallery.swipe({
680					fallbackToMouseEvents: false,
681					swipeLeft: function() {
682						self.nextSlide();
683					},
684					swipeRight: function() {
685						self.prevSlide();
686					}
687				});
688			}
689			
690			// pause on hover handling
691			if(this.options.pauseOnHover) {
692				this.gallery.hover(function(){
693					if(self.options.autoRotation) {
694						self.galleryHover = true;
695						self.pauseRotation();
696					}
697				}, function(){
698					if(self.options.autoRotation) {
699						self.galleryHover = false;
700						self.resumeRotation();
701					}
702				});
703			}
704		},
705		onWindowResize: function(){
706			if(this.options.autoHeight) {
707				this.slidesHolder.css({height: this.slides.eq(this.currentIndex).outerHeight(true) });
708			}
709		},
710		prevSlide: function() {
711			if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
712				this.prevIndex = this.currentIndex;
713				if(this.currentIndex > 0) {
714					this.currentIndex--;
715					this.switchSlide();
716				} else if(this.options.circularRotation) {
717					this.currentIndex = this.stepsCount - 1;
718					this.switchSlide();
719				}
720			}
721		},
722		nextSlide: function(fromAutoRotation) {
723			if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
724				this.prevIndex = this.currentIndex;
725				if(this.currentIndex < this.stepsCount - 1) {
726					this.currentIndex++;
727					this.switchSlide();
728				} else if(this.options.circularRotation || fromAutoRotation === true) {
729					this.currentIndex = 0;
730					this.switchSlide();
731				}
732			}
733		},
734		numSlide: function(c) {
735			if(this.currentIndex != c) {
736				this.prevIndex = this.currentIndex;
737				this.currentIndex = c;
738				this.switchSlide();
739			}
740		},
741		switchSlide: function() {
742			var self = this;
743			if(this.slides.length > 1) {
744				this.galleryAnimating = true;
745				if(!this.options.animSpeed) {
746					this.slides.eq(this.prevIndex).css({opacity:0});
747				} else {
748					this.slides.eq(this.prevIndex).stop().animate({opacity:0}
748,{duration: this.options.animSpeed});
749				}
750				
751				this.switchNext = function() {
752					if(!self.options.animSpeed) {
753						self.slides.eq(self.currentIndex).css({opacity:''});
754					} else {
755						self.slides.eq(self.currentIndex).stop().animate({opacity:1},{duration: self.options.animSpeed});
756					}
757					setTimeout(function() {
758						self.slides.eq(self.currentIndex).css({opacity:''});
759						self.galleryAnimating = false;
760						self.autoRotate();
761						
762						// onchange callback
763						self.makeCallback('onChange', self);
764					}, self.options.animSpeed);
765				}
766				
767				if(this.options.switchSimultaneously) {
768					self.switchNext();
769				} else {
770					clearTimeout(this.switchTimer);
771					this.switchTimer = setTimeout(function(){
772						self.switchNext();
773					}, this.options.animSpeed);
774				}
775				this.refreshState();
776				
777				// onchange callback
778				this.makeCallback('onBeforeChange', this);
779			}
780		},
781		refreshState: function(initial) {
782			this.slides.removeClass(this.options.activeClass).eq(this.currentIndex).addClass(this.options.activeClass);
783			this.pagerLinks.removeClass(this.options.activeClass).eq(this.currentIndex).addClass(this.options.activeClass);
784			this.curNum.html(this.currentIndex+1);
785			this.allNum.html(this.stepsCount);
786			
787			// initial refresh
788			if(this.options.autoHeight) {
789				if(initial) {
790					this.slidesHolder.css({height: this.slides.eq(this.currentIndex).outerHeight(true) });
791				} else {
792					this.slidesHolder.stop().animate({height: this.slides.eq(this.currentIndex).outerHeight(true)}, {duration: this.options.animSpeed});
793				}
794			}
795			
796			// disabled state
797			if(!this.options.circularRotation) {
798				this.btnPrev.add(this.btnNext).removeClass(this.options.disabledClass);
799				if(this.currentIndex === 0) this.btnPrev.addClass(this.options.disabledClass);
800				if(this.currentIndex === this.stepsCount - 1) this.btnNext.addClass(this.options.disabledClass);
801			}
802		},
803		startRotation: function() {
804			this.options.autoRotation = true;
805			this.galleryHover = false;
806			this.autoRotationStopped = false;
807			this.resumeRotation();
808		},
809		stopRotation: function() {
810			this.galleryHover = true;
811			this.autoRotationStopped = true;
812			this.pauseRotation();
813		},
814		pauseRotation: function() {
815			this.gallery.addClass(this.options.autorotationDisabledClass);
816			this.gallery.removeClass(this.options.autorotationActiveClass);
817			clearTimeout(this.timer);
818		},
819		resumeRotation: function() {
820			if(!this.autoRotationStopped) {
821				this.gallery.addClass(this.options.autorotationActiveClass);
822				this.gallery.removeClass(this.options.autorotationDisabledClass);
823				this.autoRotate();
824			}
825		},
826		autoRotate: function() {
827			var self = this;
828			clearTimeout(this.timer);
829			if(this.options.autoRotation && !this.galleryHover && !this.autoRotationStopped) {
830				this.gallery.addClass(this.options.autorotationActiveClass);
831				this.timer = setTimeout(function(){
832					self.nextSlide(true);
833				}, this.options.switchTime);
834			} else {
835				this.pauseRotation();
836			}
837		},
838		makeCallback: function(name) {
839			if(typeof this.options[name] === 'function') {
840				var args = Array.prototype.slice.call(arguments);
841				args.shift();
842				this.options[name].apply(this, args);
843			}
844		}
845	}
846
847	// jquery plugin
848	$.fn.fadeGallery = function(opt){
849		return this.each(function(){
850			$(this).data('FadeGallery', new FadeGallery($.extend(opt,{holder:this})));
851		});
852	}
853}(jQuery));
854
855/*
856 * jQuery Accordion plugin
857 */
858;(function($){
859	$.fn.slideAccordion = function(opt){
860		// default options
861		var options = $.extend({
862			addClassBeforeAnimation: false,
863			activeClass:'active',
864			opener:'.opener',
865			slider:'.slide',
866			animSpeed: 300,
867			collapsible:true,
868			event:'click'
869		},opt);
870
871		return this.each(function(){
872			// options
873			var accordion = $(this);
874			var items = accordion.find(':has('+options.slider+')');
875
876			items.each(function(){
877				var item = $(this);
878				var opener = item.find(options.opener);
879				var slider = item.find(options.slider);
880				opener.bind(options.event, function(e){
881					if(!slider.is(':animated')) {
882						if(item.hasClass(options.activeClass)) {
883							if(options.collapsible) {
884								slider.slideUp(options.animSpeed, function(){
885									hideSlide(slider);
886									item.removeClass(options.activeClass);
887								});
888							}
889						} else {
890							// show active
891							var levelItems = item.siblings('.'+options.activeClass);
892							var sliderElements = levelItems.find(options.slider);
893							item.addClass(options.activeClass);
894							showSlide(slider).hide().slideDown(options.animSpeed);
895						
896							// collapse others
897							sliderElements.slideUp(options.animSpeed, function(){
898								levelItems.removeClass(options.activeClass);
899								hideSlide(sliderElements);
900							});
901						}
902					}
903					e.preventDefault();
904				});
905				if(item.hasClass(options.activeClass)) showSlide(slider); else hideSlide(slider);
906			});
907		});
908	};
909
910	// accordion slide visibility
911	var showSlide = function(slide) {
912		return slide.css({position:'', top: '', left: '', width: '' });
913	};
914	var hideSlide = function(slide) {
915		return slide.show().css({position:'absolute', top: -9999, left: -9999, width: slide.width() });
916	};
917}(jQuery));
918
919/*
920 * jQuery SameHeight plugin
921 */
922;(function($){
923	$.fn.sameHeight = function(opt) {
924		var options = $.extend({
925			skipClass: 'same-height-ignore',
926			leftEdgeClass: 'same-height-left',
927			rightEdgeClass: 'same-height-right',
928			elements: '>*',
929			flexible: false,
930			multiLine: false,
931			useMinHeight: false
932		},opt);
933		return this.each(function(){
934			var holder = $(this), postResizeTimer, ignoreResize;
935			var elements = holder.find(options.elements).not('.' + options.skipClass);
936			if(!elements.length) return;
937			
938			// resize handler
939			function doResize() {
940				elements.css(options.useMinHeight && supportMinHeight ? 'minHeight' : 'height', '');
941				if(options.multiLine) {
942					// resize elements row by row
943					resizeElementsByRows(elements, options);
944				} else {
945					// resize elements by holder
946					resizeElements(elements, holder, options);
947				}
948			}
949			doResize();
950			
951			// handle flexible layout / font resize
952			var delayedResizeHandler = function() {
953				if(!ignoreResize) {
954					ignoreResize = true;
955					doResize();
956					clearTimeout(postResizeTimer);
957					postResizeTimer = setTimeout(function() {
958						doResize();
959						setTimeout(function(){
960							ignoreResize = false;
961						}, 10);
962					}, 100);
963				}
964			};
965
966			// handle flexible/responsive layout
967			if(options.flexible) {
968				$(window).bind('resize orientationchange fontresize', delayedResizeHandler);
969			}
970
971			// handle complete page load including images and fonts
972			$(window).bind('load', delayedResizeHandler);
973		});
974	};
975	
976	// detect css min-height support
977	var supportMinHeight = typeof document.documentElement.style.maxHeight !== 'undefined';
978	
979	// get elements by rows
980	function resizeElementsByRows(boxes, options) {
981		var currentRow = $(), maxHeight, firstOffset = boxes.eq(0).offset().top;
982		boxes.each(function(ind){
983			var curItem = $(this);
984			if(curItem.offset().top === firstOffset) {
985				currentRow = currentRow.add(this);
986			} else {
987				maxHeight = getMaxHeight(currentRow);
988				resizeElements(currentRow, maxHeight, options);
989				currentRow = curItem;
990				firstOffset = curItem.offset().top;
991			}
992		});
993		if(currentRow.length) {
994			maxHeight = getMaxHeight(currentRow);
995			resizeElements(currentRow, maxHeight, options);
996		}
997	}
998	
999	// calculate max element height
1000	function getMaxHeight(boxes) {
1001		var maxHeight = 0;
1002		boxes.each(function(){
1003			maxHeight = Math.max(maxHeight, $(this).outerHeight());
1004		});
1005		return maxHeight;
1006	}
1007	
1008	// resize helper function
1009	function resizeElements(boxes, parent, options) {
1010		var parentHeight = typeof parent === 'number' ? parent : parent.height();
1011		boxes.removeClass(options.leftEdgeClass).removeClass(options.rightEdgeClass).each(function(i){
1012			var element = $(this);
1013			var depthDiffHeight = 0;
1014			
1015			if(typeof parent !== 'number') {
1016				element.parents().each(function(){
1017					var tmpParent = $(this);
1018					if(this === parent[0]) {
1019						return false;
1020					} else {
1021						depthDiffHeight += tmpParent.outerHeight() - tmpParent.height();
1022					}
1023				});
1024			}
1025			var calcHeight = parentHeight - depthDiffHeight - (element.outerHeight() - element.height());
1026			if(calcHeight > 0) {
1027				element.css(options.useMinHeight && supportMinHeight ? 'minHeight' : 'height', calcHeight);
1028			}
1029		});
1030		boxes.filter(':first').addClass(options.leftEdgeClass);
1031		boxes.filter(':last').addClass(options.rightEdgeClass);
1032	}
1033}(jQuery));
1034
1035/*
1036 * jQuery FontResize Event
1037 */
1038jQuery.onFontResize = (function($) {
1039	$(function() {
1040		var randomID = 'font-resize-frame-' + Math.floor(Math.random() * 1000);
1041		var resizeFrame = $('<iframe>').attr('id', randomID).addClass('font-resize-helper');
1042		
1043		// required styles
1044		resizeFrame.css({
1045			width: '100em',
1046			height: '10px',
1047			position: 'absolute',
1048			borderWidth: 0,
1049			top: '-9999px',
1050			left: '-9999px'
1051		}).appendTo('body');
1052		
1053		// use native IE resize event if possible
1054		if ($.browser.msie && $.browser.version < 9) {
1055			resizeFrame.bind('resize', function () {
1056				$.onFontResize.trigger(resizeFrame[0].offsetWidth / 100);
1057			});
1058		}
1059		// use script inside the iframe to detect resize for other browsers
1060		else {
1061			var doc = resizeFrame[0].contentWindow.document;
1062			doc.open();
1063			doc.write('<scri' + 'pt>window.onload = function(){var em = parent.jQuery("#' + randomID + '")[0];window.onresize = function(){if(parent.jQuery.onFontResize){parent.jQuery.onFontResize.trigger(em.offsetWidth / 100);}}};</scri' + 'pt>');
1064			doc.close();
1065		}
1066		jQuery.onFontResize.initialSize = resizeFrame[0].offsetWidth / 100;
1067	});
1068	return {
1069		// public method, so it can be called from within the iframe
1070		trigger: function (em) {
1071			$(window).trigger("fontresize", [em]);
1072		}
1073	};
1074}(jQuery));
1075
1076/*
1077 * JavaScript Custom Forms Module
1078 */
1079jcf = {
1080	// global options
1081	modules: {},
1082	plugins: {},
1083	baseOptions: {
1084		useNativeDropOnMobileDevices: true,
1085		unselectableClass:'jcf-unselectable',
1086		labelActiveClass:'jcf-label-active',
1087		labelDisabledClass:'jcf-label-disabled',
1088		classPrefix: 'jcf-class-',
1089		hiddenClass:'jcf-hidden',
1090		focusClass:'jcf-focus',
1091		wrapperTag: 'div'
1092	},
1093	// replacer function
1094	customForms: {
1095		setOptions: function(obj) {
1096			for(var p in obj) {
1097				if(obj.hasOwnProperty(p) && typeof obj[p] === 'object') {
1098					jcf.lib.extend(jcf.modules[p].prototype.defaultOptions, obj[p]);
1099				}
1100			}
1101		},
1102		replaceAll: function() {
1103			for(var k in jcf.modules) {
1104				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector);
1105				for(var i = 0; i<els.length; i++) {
1106					if(els[i].jcf) {
1107						// refresh form element state
1108						els[i].jcf.refreshState();
1109					} else {
1110						// replace form element
1111						if(!jcf.lib.hasClass(els[i], 'default') && jcf.modules[k].prototype.checkElement(els[i])) {
1112							new jcf.modules[k]({
1113								replaces:els[i]
1114							});
1115						}
1116					}
1117				}
1118			}
1119		},
1120		refreshAll: function() {
1121			for(var k in jcf.modules) {
1122				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector);
1123				for(var i = 0; i<els.length; i++) {
1124					if(els[i].jcf) {
1125						// refresh form element state
1126						els[i].jcf.refreshState();
1127					}
1128				}
1129			}
1130		},
1131		refreshElement: function(obj) {
1132			if(obj && obj.jcf) {
1133				obj.jcf.refreshState();
1134			}
1135		},
1136		destroyAll: function() {
1137			for(var k in jcf.modules) {
1138				var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector);
1139				for(var i = 0; i<els.length; i++) {
1140					if(els[i].jcf) {
1141						els[i].jcf.destroy();
1142					}
1143				}
1144			}
1145		}
1146	},
1147	// detect device type
1148	isTouchDevice: (function() {
1149		try {
1150			return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
1151		} catch (e) {
1152			return false;
1153		}
1154	}()),
1155	// define base module
1156	setBaseModule: function(obj) {
1157		jcf.customControl = function(opt){
1158			this.options = jcf.lib.extend({}, jcf.baseOptions, this.defaultOptions, opt);
1159			this.init();
1160		};
1161		for(var p in obj) {
1162			jcf.customControl.prototype[p] = obj[p];
1163		}
1164	},
1165	// add module to jcf.modules
1166	addModule: function(obj) {
1167		if(obj.name){
1168			// create new module proto class
1169			jcf.modules[obj.name] = function(){
1170				jcf.modules[obj.name].superclass.constructor.apply(this, arguments);
1171			};
1172			jcf.lib.inherit(jcf.modules[obj.name], jcf.customControl);
1173			for(var p in obj) {
1174				jcf.modules[obj.name].prototype[p] = obj[p];
1175			}
1176			// on create module
1177			jcf.modules[obj.name].prototype.onCreateModule();
1178			// make callback for exciting modules
1179			for(var mod in jcf.modules) {
1180				if(jcf.modules[mod] != jcf.modules[obj.name]) {
1181					jcf.modules[mod].prototype.onModuleAdded(jcf.modules[obj.name]);
1182				}
1183			}
1184		}
1185	},
1186	// add plugin to jcf.plugins
1187	addPlugin: function(obj) {
1188		if(obj && obj.name) {
1189			jcf.plugins[obj.name] = function() {
1190				this.init.apply(this, arguments);
1191			};
1192			for(var p in obj) {
1193				jcf.plugins[obj.name].prototype[p] = obj[p];
1194			}
1195		}
1196	},
1197	// miscellaneous init
1198	init: function(){
1199		if(navigator.msPointerEnabled) {
1200			this.eventPress = 'MSPointerDown';
1201			this.eventMove = 'MSPointerMove';
1202			this.eventRelease = 'MSPointerUp';
1203		} else {
1204			this.eventPress = this.isTouchDevice ? 'touchstart' : 'mousedown';
1205			this.eventMove = this.isTouchDevice ? 'touchmove' : 'mousemove';
1206			this.eventRelease = this.isTouchDevice ? 'touchend' : 'mouseup';
1207		}
1208
1209		// init jcf styles
1210		setTimeout(function(){
1211			jcf.lib.domReady(function(){
1212				jcf.initStyles();
1213			});
1214		},1);
1215		return this;
1216	},
1217	initStyles: function() {
1218		// create <style> element and rules
1219		var head = document.getElementsByTagName('head')[0],
1220			style = document.createElement('style'),
1221			rules = document.createTextNode('.'+jcf.baseOptions.unselectableClass+'{'+
1222				'-moz-user-select:none;'+
1223				'-webkit-tap-highlight-color:rgba(255,255,255,0);'+
1224				'-webkit-user-select:none;'+
1225				'user-select:none;'+
1226			'}');
1227		
1228		// append style element
1229		style.type = 'text/css';
1230		if(style.styleSheet) {
1231			style.styleSheet.cssText = rules.nodeValue;
1232		} else {
1233			style.appendChild(rules);
1234		}
1235		head.appendChild(style);
1236	}
1237}.init();
1238
1239/*
1240 * Custom Form Control prototype
1241 */
1242jcf.setBaseModule({
1243	init: function(){
1244		if(this.options.replaces) {
1245			this.realElement = this.options.replaces;
1246			this.realElement.jcf = this;
1247			this.replaceObject();
1248		}
1249	},
1250	defaultOptions: {
1251		// default module options (will be merged with base options)
1252	},
1253	checkElement: function(el){
1254		return true;
1254 // additional check for correct form element
1255	},
1256	replaceObject: function(){
1257		this.createWrapper();
1258		this.attachEvents();
1259		this.fixStyles();
1260		this.setupWrapper();
1261	},
1262	createWrapper: function(){
1263		this.fakeElement = jcf.lib.createElement(this.options.wrapperTag);
1264		this.labelFor = jcf.lib.getLabelFor(this.realElement);
1265		jcf.lib.disableTextSelection(this.fakeElement);
1266		jcf.lib.addClass(this.fakeElement, jcf.lib.getAllClasses(this.realElement.className, this.options.classPrefix));
1267		jcf.lib.addClass(this.realElement, jcf.baseOptions.hiddenClass);
1268	},
1269	attachEvents: function(){
1270		jcf.lib.event.add(this.realElement, 'focus', this.onFocusHandler, this);
1271		jcf.lib.event.add(this.realElement, 'blur', this.onBlurHandler, this);
1272		jcf.lib.event.add(this.fakeElement, 'click', this.onFakeClick, this);
1273		jcf.lib.event.add(this.fakeElement, jcf.eventPress, this.onFakePressed, this);
1274		jcf.lib.event.add(this.fakeElement, jcf.eventRelease, this.onFakeReleased, this);
1275
1276		if(this.labelFor) {
1277			this.labelFor.jcf = this;
1278			jcf.lib.event.add(this.labelFor, 'click', this.onFakeClick, this);
1279			jcf.lib.event.add(this.labelFor, jcf.eventPress, this.onFakePressed, this);
1280			jcf.lib.event.add(this.labelFor, jcf.eventRelease, this.onFakeReleased, this);
1281		}
1282	},
1283	fixStyles: function() {
1284		// hide mobile webkit tap effect
1285		if(jcf.isTouchDevice) {
1286			var tapStyle = 'rgba(255,255,255,0)';
1287			this.realElement.style.webkitTapHighlightColor = tapStyle;
1288			this.fakeElement.style.webkitTapHighlightColor = tapStyle;
1289			if(this.labelFor) {
1290				this.labelFor.style.webkitTapHighlightColor = tapStyle;
1291			}
1292		}
1293	},
1294	setupWrapper: function(){
1295		// implement in subclass
1296	},
1297	refreshState: function(){
1298		// implement in subclass
1299	},
1300	destroy: function() {
1301		if(this.fakeElement && this.fakeElement.parentNode) {
1302			this.fakeElement.parentNode.removeChild(this.fakeElement);
1303		}
1304		jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
1305		this.realElement.jcf = null;
1306	},
1307	onFocus: function(){
1308		// emulated focus event
1309		jcf.lib.addClass(this.fakeElement,this.options.focusClass);
1310	},
1311	onBlur: function(cb){
1312		// emulated blur event
1313		jcf.lib.removeClass(this.fakeElement,this.options.focusClass);
1314	},
1315	onFocusHandler: function() {
1316		// handle focus loses
1317		if(this.focused) return;
1318		this.focused = true;
1319		
1320		// handle touch devices also
1321		if(jcf.isTouchDevice) {
1322			if(jcf.focusedInstance && jcf.focusedInstance.realElement != this.realElement) {
1323				jcf.focusedInstance.onBlur();
1324				jcf.focusedInstance.realElement.blur();
1325			}
1326			jcf.focusedInstance = this;
1327		}
1328		this.onFocus.apply(this, arguments);
1329	},
1330	onBlurHandler: function() {
1331		// handle focus loses
1332		if(!this.pressedFlag) {
1333			this.focused = false;
1334			this.onBlur.apply(this, arguments);
1335		}
1336	},
1337	onFakeClick: function(){
1338		if(jcf.isTouchDevice) {
1339			this.onFocus();
1340		} else if(!this.realElement.disabled) {
1341			this.realElement.focus();
1342		}
1343	},
1344	onFakePressed: function(e){
1345		this.pressedFlag = true;
1346	},
1347	onFakeReleased: function(){
1348		this.pressedFlag = false;
1349	},
1350	onCreateModule: function(){
1351		// implement in subclass
1352	},
1353	onModuleAdded: function(module) {
1354		// implement in subclass
1355	},
1356	onControlReady: function() {
1357		// implement in subclass
1358	}
1359});
1360
1361/*
1362 * JCF Utility Library
1363 */
1364jcf.lib = {
1365	bind: function(func, scope){
1366		return function() {
1367			return func.apply(scope, arguments);
1368		}
1369	},
1370	browser: (function() {
1371		var ua = navigator.userAgent.toLowerCase(), res = {},
1372		match = /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) ||
1373				/(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+))?/.exec(ua) || [];
1374		res[match[1]] = true;
1375		res.version = match[2] || "0";
1376		res.safariMac = ua.indexOf('mac') != -1 && ua.indexOf('safari') != -1;
1377		return res;
1378	})(),
1379	getOffset: function (obj) {
1380		if (obj.getBoundingClientRect) {
1381			var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
1382			var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
1383			var clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0;
1384			var clientTop = document.documentElement.clientTop || document.body.clientTop || 0;
1385			return {
1386				top:Math.round(obj.getBoundingClientRect().top + scrollTop - clientTop),
1387				left:Math.round(obj.getBoundingClientRect().left + scrollLeft - clientLeft)
1388			}
1389		} else {
1390			var posLeft = 0, posTop = 0;
1391			while (obj.offsetParent) {posLeft += obj.offsetLeft; posTop += obj.offsetTop; obj = obj.offsetParent;}
1392			return {top:posTop,left:posLeft};
1393		}
1394	},
1395	getScrollTop: function() {
1396		return window.pageYOffset || document.documentElement.scrollTop;
1397	},
1398	getScrollLeft: function() {
1399		return window.pageXOffset || document.documentElement.scrollLeft;
1400	},
1401	getWindowWidth: function(){
1402		return document.compatMode=='CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth;
1403	},
1404	getWindowHeight: function(){
1405		return document.compatMode=='CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight;
1406	},
1407	getStyle: function(el, prop) {
1408		if (document.defaultView && document.defaultView.getComputedStyle) {
1409			return document.defaultView.getComputedStyle(el, null)[prop];
1410		} else if (el.currentStyle) {
1411			return el.currentStyle[prop];
1412		} else {
1413			return el.style[prop];
1414		}
1415	},
1416	getParent: function(obj, selector) {
1417		while(obj.parentNode && obj.parentNode != document.body) {
1418			if(obj.parentNode.tagName.toLowerCase() == selector.toLowerCase()) {
1419				return obj.parentNode;
1420			}
1421			obj = obj.parentNode;
1422		}
1423		return false;
1424	},
1425	isParent: function(child, parent) {
1426		while(child.parentNode) {
1427			if(child.parentNode === parent) {
1428				return true;
1429			}
1430			child = child.parentNode;
1431		}
1432		return false;
1433	},
1434	getLabelFor: function(object) {
1435		if(jcf.lib.getParent(object,'label')) {
1436			return object.parentNode;
1437		} else if(object.id) {
1438			return jcf.lib.queryBySelector('label[for="' + object.id + '"]')[0];
1439		}
1440	},
1441	disableTextSelection: function(el){
1442		if (typeof el.onselectstart !== 'undefined') {
1443			el.onselectstart = function() {return false};
1444		} else if(window.opera) {
1445			el.setAttribute('unselectable', 'on');
1446		} else {
1447			jcf.lib.addClass(el, jcf.baseOptions.unselectableClass);
1448		}
1449	},
1450	enableTextSelection: function(el) {
1451		if (typeof el.onselectstart !== 'undefined') {
1452			el.onselectstart = null;
1453		} else if(window.opera) {
1454			el.removeAttribute('unselectable');
1455		} else {
1456			jcf.lib.removeClass(el, jcf.baseOptions.unselectableClass);
1457		}
1458	},
1459	queryBySelector: function(selector, scope){
1460		return this.getElementsBySelector(selector, scope);
1461	},
1462	prevSibling: function(node) {
1463		while(node = node.previousSibling) if(node.nodeType == 1) break;
1464		return node;
1465	},
1466	nextSibling: function(node) {
1467		while(node = node.nextSibling) if(node.nodeType == 1) break;
1468		return node;
1469	},
1470	fireEvent: function(element,event) {
1471		if(element.dispatchEvent){
1472			var evt = document.createEvent('HTMLEvents');
1473			evt.initEvent(event, true, true );
1474			return !element.dispatchEvent(evt);
1475		}else if(document.createEventObject){
1476			var evt = document.createEventObject();
1477			return element.fireEvent('on'+event,evt);
1478		}
1479	},
1480	isParent: function(p, c) {
1481		while(c.parentNode) {
1482			if(p == c) {
1483				return true;
1484			}
1485			c = c.parentNode;
1486		}
1487		return false;
1488	},
1489	inherit: function(Child, Parent) {
1490		var F = function() { }
1491		F.prototype = Parent.prototype
1492		Child.prototype = new F()
1493		Child.prototype.constructor = Child
1494		Child.superclass = Parent.prototype
1495	},
1496	extend: function(obj) {
1497		for(var i = 1; i < arguments.length; i++) {
1498			for(var p in arguments[i]) {
1499				if(arguments[i].hasOwnProperty(p)) {
1500					obj[p] = arguments[i][p];
1501				}
1502			}
1503		}
1504		return obj;
1505	},
1506	hasClass: function (obj,cname) {
1507		return (obj.className ? obj.className.match(new RegExp('(\\s|^)'+cname+'(\\s|$)')) : false);
1508	},
1509	addClass: function (obj,cname) {
1510		if (!this.hasClass(obj,cname)) obj.className += (!obj.className.length || obj.className.charAt(obj.className.length - 1) === ' ' ? '' : ' ') + cname;
1511	},
1512	removeClass: function (obj,cname) {
1513		if (this.hasClass(obj,cname)) obj.className=obj.className.replace(new RegExp('(\\s|^)'+cname+'(\\s|$)'),' ').replace(/\s+$/, '');
1514	},
1515	toggleClass: function(obj, cname, condition) {
1516		if(condition) this.addClass(obj, cname); else this.removeClass(obj, cname);
1517	},
1518	createElement: function(tagName, options) {
1519		var el = document.createElement(tagName);
1520		for(var p in options) {
1521			if(options.hasOwnProperty(p)) {
1522				switch (p) {
1523					case 'class': el.className = options[p]; break;
1524					case 'html': el.innerHTML = options[p]; break;
1525					case 'style': this.setStyles(el, options[p]); break;
1526					default: el.setAttribute(p, options[p]);
1527				}
1528			}
1529		}
1530		return el;
1531	},
1532	setStyles: function(el, styles) {
1533		for(var p in styles) {
1534			if(styles.hasOwnProperty(p)) {
1535				switch (p) {
1536					case 'float': el.style.cssFloat = styles[p]; break;
1537					case 'opacity': el.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+styles[p]*100+')'; el.style.opacity = styles[p]; break;
1538					default: el.style[p] = (typeof styles[p] === 'undefined' ? 0 : styles[p]) + (typeof styles[p] === 'number' ? 'px' : '');
1539				}
1540			}
1541		}
1542		return el;
1543	},
1544	getInnerWidth: function(el) {
1545		return el.offsetWidth - (parseInt(this.getStyle(el,'paddingLeft')) || 0) - (parseInt(this.getStyle(el,'paddingRight')) || 0);
1546	},
1547	getInnerHeight: function(el) {
1548		return el.offsetHeight - (parseInt(this.getStyle(el,'paddingTop')) || 0) - (parseInt(this.getStyle(el,'paddingBottom')) || 0);
1549	},
1550	getAllClasses: function(cname, prefix, skip) {
1551		if(!skip) skip = '';
1552		if(!prefix) prefix = '';
1553		return cname ? cname.replace(new RegExp('(\\s|^)'+skip+'(\\s|$)'),' ').replace(/[\s]*([\S]+)+[\s]*/gi,prefix+"$1 ") : '';
1554	},
1555	getElementsBySelector: function(selector, scope) {
1556		if(typeof document.querySelectorAll === 'function') {
1557			return (scope || document).querySelectorAll(selector);
1558		}
1559		var selectors = selector.split(',');
1560		var resultList = [];
1561		for(var s = 0; s < selectors.length; s++) {
1562			var currentContext = [scope || document];
1563			var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' ');
1564			for (var i = 0; i < tokens.length; i++) {
1565				token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
1566				if (token.indexOf('#') > -1) {
1567					var bits = token.split('#'), tagName = bits[0], id = bits[1];
1568					var element = document.getElementById(id);
1569					if (tagName && element.nodeName.toLowerCase() != tagName) {
1570						return [];
1571					}
1572					currentContext = [element];
1573					continue;
1574				}
1575				if (token.indexOf('.') > -1) {
1576					var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0;
1577					for (var h = 0; h < currentContext.length; h++) {
1578						var elements;
1579						if (tagName == '*') {
1580							elements = currentContext[h].getElementsByTagName('*');
1581						} else {
1582							elements = currentContext[h].getElementsByTagName(tagName);
1583						}
1584						for (var j = 0; j < elements.length; j++) {
1585							found[foundCount++] = elements[j];
1586						}
1587					}
1588					currentContext = [];
1589					var currentContextIndex = 0;
1590					for (var k = 0; k < found.length; k++) {
1591						if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) {
1592							currentContext[currentContextIndex++] = found[k];
1593						}
1594					}
1595					continue;
1596				}
1597				if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
1598					var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4;
1599					if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) {
1600						attrName = 'htmlFor';
1601					}
1602					var found = [], foundCount = 0;
1603					for (var h = 0; h < currentContext.length; h++) {
1604						var elements;
1605						if (tagName == '*') {
1606							elements = currentContext[h].getElementsByTagName('*');
1607						} else {
1608							elements = currentContext[h].getElementsByTagName(tagName);
1609						}
1610						for (var j = 0; elements[j]; j++) {
1611							found[foundCount++] = elements[j];
1612						}
1613					}
1614					currentContext = [];
1615					var currentContextIndex = 0, checkFunction;
1616					switch (attrOperator) {
1617						case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break;
1618						case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break;
1619						case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break;
1620						case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break;
1621						case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break;
1622						case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break;
1623						default : checkFunction = function(e) { return e.getAttribute(attrName) };
1624					}
1625					currentContext = [];
1626					var currentContextIndex = 0;
1627					for (var k = 0; k < found.length; k++) {
1628						if (checkFunction(found[k])) {
1629							currentContext[currentContextIndex++] = found[k];
1630						}
1631					}
1632					continue;
1633				}
1634				tagName = token;
1635				var found = [], foundCount = 0;
1636				for (var h = 0; h < currentContext.length; h++) {
1637					var elements = currentContext[h].getElementsByTagName(tagName);
1638					for (var j = 0; j < elements.length; j++) {
1639						found[foundCount++] = elements[j];
1640					}
1641				}
1642				currentContext = found;
1643			}
1644			resultList = [].concat(resultList,currentContext);
1645		}
1646		return resultList;
1647	},
1648	scrollSize: (function(){
1649		var content, hold, sizeBefore, sizeAfter;
1650		function buildSizer(){
1651			if(hold) removeSizer();
1652			content = document.createElement('div');
1653			hold = document.createElement('div');
1654			hold.style.cssText = 'position:absolute;overflow:hidden;width:100px;height:100px';
1655			hold.appendChild(content);
1656			document.body.appendChild(hold);
1657		}
1658		function removeSizer(){
1659			document.body.removeChild(hold);
1660			hold = null;
1661		}
1662		function calcSize(vertical) {
1663			buildSizer();
1664			content.style.cssText = 'height:'+(vertical ? '100%' : '200px');
1665			sizeBefore = (vertical ? content.offsetHeight : content.offsetWidth);
1666			hold.style.overflow = 'scroll'; content.innerHTML = 1;
1667			sizeAfter = (vertical ? content.offsetHeight : content.offsetWidth);
1668			if(vertical && hold.clientHeight) sizeAfter = hold.clientHeight;
1669			removeSizer();
1670			return sizeBefore - sizeAfter;
1671		}
1672		return {
1673			getWidth:function(){
1674				return calcSize(false);
1675			},
1676			getHeight:function(){
1677				return calcSize(true)
1678			}
1679		}
1680	}()),
1681	domReady: function (handler){
1682		var called = false
1683		function ready() {
1684			if (called) return;
1685			called = true;
1686			handler();
1687		}
1688		if (document.addEventListener) {
1689			document.addEventListener("DOMContentLoaded", ready, false);
1690		} else if (document.attachEvent) {
1691			if (document.documentElement.doScroll && window == window.top) {
1692				function tryScroll(){
1693					if (called) return
1694					if (!document.body) return
1695					try {
1696						document.documentElement.doScroll("left")
1697						ready()
1698					} catch(e) {
1699						setTimeout(tryScroll, 0)
1700					}
1701				}
1702				tryScroll()
1703			}
1704			document.attachEvent("onreadystatechange", function(){
1705				if (document.readyState === "complete") {
1706					ready()
1707				}
1708			})
1709		}
1710		if (window.addEventListener) window.addEventListener('load', ready, false)
1711		else if (window.attachEvent) window.attachEvent('onload', ready)
1712	},
1713	event: (function(){
1714		var guid = 0;
1715		function fixEvent(e) {
1716			e = e || window.event;
1717			if (e.isFixed) {
1718				return e;
1719			}
1720			e.isFixed = true; 
1721			e.preventDefault = e.preventDefault || function(){this.returnValue = false}
1722			e.stopPropagation = e.stopPropagaton || function(){this.cancelBubble = true}
1723			if (!e.target) {
1724				e.target = e.srcElement
1725			}
1726			if (!e.relatedTarget && e.fromElement) {
1727				e.relatedTarget = e.fromElement == e.target ? e.toElement : e.fromElement;
1728			}
1729			if (e.pageX == null && e.clientX != null) {
1730				var html = document.documentElement, body = document.body;
1731				e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
1732				e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
1733			}
1734			if (!e.which && e.button) {
1735				e.which = e.button & 1 ? 1 : (e.button & 2 ? 3 : (e.button & 4 ? 2 : 0));
1736			}
1737			if(e.type === "DOMMouseScroll" || e.type === 'mousewheel') {
1738				e.mWheelDelta = 0;
1739				if (e.wheelDelta) {
1740					e.mWheelDelta = e.wheelDelta/120;
1741				} else if (e.detail) {
1742					e.mWheelDelta = -e.detail/3;
1743				}
1744			}
1745			return e;
1746		}
1747		function commonHandle(event, customScope) {
1748			event = fixEvent(event);
1749			var handlers = this.events[event.type];
1750			for (var g in handlers) {
1751				var handler = handlers[g];
1752				var ret = handler.call(customScope || this, event);
1753				if (ret === false) {
1754					event.preventDefault()
1755					event.stopPropagation()
1756				}
1757			}
1758		}
1759		var publicAPI = {
1760			add: function(elem, type, handler, forcedScope) {
1761				if (elem.setInterval && (elem != window && !elem.frameElement)) {
1762					elem = window;
1763				}
1764				if (!handler.guid) {
1765					handler.guid = ++guid;
1766				}
1767				if (!elem.events) {
1768					elem.events = {};
1769					elem.handle = function(event) {
1770						return commonHandle.call(elem, event);
1771					}
1772				}
1773				if (!elem.events[type]) {
1774					elem.events[type] = {};
1775					if (elem.addEventListener) elem.addEventListener(type, elem.handle, false);
1776					else if (elem.attachEvent) elem.attachEvent("on" + type, elem.handle);
1777					if(type === 'mousewheel') {
1778						publicAPI.add(elem, 'DOMMouseScroll', handler, forcedScope);
1779					}
1780				}
1781				var fakeHandler = jcf.lib.bind(handler, forcedScope);
1782				fakeHandler.guid = handler.guid;
1783				elem.events[type][handler.guid] = forcedScope ? fakeHandler : handler;
1784			},
1785			remove: function(elem, type, handler) {
1786				var handlers = elem.events && elem.events[type];
1787				if (!handlers) return;
1788				delete handlers[handler.guid];
1789				for(var any in handlers) return;
1790				if (elem.removeEventListener) elem.removeEventListener(type, elem.handle, false);
1791				else if (elem.detachEvent) elem.detachEvent("on" + type, elem.handle);
1792				delete elem.events[type];
1793				for (var any in elem.events) return;
1794				try {
1795					delete elem.handle;
1796					delete elem.events;
1797				} catch(e) {
1798					if(elem.removeAttribute) {
1799						elem.removeAttribute("handle");
1800						elem.removeAttribute("events");
1801					}
1802				}
1803				if(type === 'mousewheel') {
1804					publicAPI.remove(elem, 'DOMMouseScroll', handler);
1805				}
1806			}
1807		}
1808		return publicAPI;
1809	}())
1810}
1811
1812// custom select module
1813jcf.addModule({
1814	name:'select',
1815	selector:'select',
1816	defaultOptions: {
1817		hideDropOnScroll: true,
1818		showNativeDrop: false,
1819		handleDropPosition: true,
1820		selectDropPosition: 'bottom', // or 'top'
1821		wrapperClass:'select-area',
1822		focusClass:'select-focus',
1823		dropActiveClass:'select-active',
1824		selectedClass:'item-selected',
1825		currentSelectedClass:'current-selected',
1826		disabledClass:'select-disabled',
1827		valueSelector:'span.center', 
1828		optGroupClass:'optgroup',
1829		openerSelector:'a.select-opener',		
1830		selectStructure:'<span class="left"></span><span class="center"></span><a class="select-opener"></a>',
1831		classPrefix:'select-',
1832		dropMaxHeight: 200,
1833		dropFlippedClass: 'select-options-flipped',
1834		dropHiddenClass:'options-hidden',
1835		dropScrollableClass:'options-overflow',
1836		dropClass:'select-options',
1837		dropClassPrefix:'drop-',
1838		dropStructure:'<div class="drop-holder"><div class="drop-list"></div></div>',
1839		dropSelector:'div.drop-list'
1840	},
1841	checkElement: function(el){
1842		return (!el.size && !el.multiple);
1843	},
1844	setupWrapper: function(){
1845		jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
1846		this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
1847		this.fakeElement.innerHTML = this.options.selectStructure;
1848		this.fakeElement.style.width = (this.realElement.offsetWidth > 0 ? this.realElement.offsetWidth + 'px' : 'auto');
1849
1850		// show native drop if specified in options
1851		if(jcf.isTouchDevice && jcf.baseOptions.useNativeDropOnMobileDevices) {
1852			this.options.showNativeDrop = true;
1853		}
1854		if(this.options.showNativeDrop) {
1855			this.fakeElement.appendChild(this.realElement);
1856			jcf.lib.removeClass(this.realElement, this.options.hiddenClass);
1857			jcf.lib.setStyles(this.realElement, {
1858				top:0,
1859				left:0,
1860				margin:0,
1861				padding:0,
1862				opacity:0,
1863				border:'none',
1864				position:'absolute',
1865				width: jcf.lib.getInnerWidth(this.fakeElement) - 1,
1866				height: jcf.lib.getInnerHeight(this.fakeElement) - 1
1867			});
1868			jcf.lib.event.add(this.realElement, 'touchstart', function(){
1869				this.realElement.title = '';
1870			}, this)
1871		}
1872		
1873		// create select body
1874		this.opener = jcf.lib.queryBySelector(this.options.openerSelector, this.fakeElement)[0];
1875		this.valueText = jcf.lib.queryBySelector(this.options.valueSelector, this.fakeElement)[0];
1876		jcf.lib.disableTextSelection(this.valueText);
1877		this.opener.jcf = this;
1878
1879		if(!this.options.showNativeDrop) {
1880			this.createDropdown();
1881			this.refreshState();
1882			this.onControlReady(this);
1883			this.hideDropdown(true);
1884		} else {
1885			this.refreshState();
1886		}
1887		this.addEvents();
1888	},
1889	addEvents: function(){
1890		if(this.options.showNativeDrop) {
1891			jcf.lib.event.add(this.realElement, 'click', this.onChange, this);
1892		} else {
1893			jcf.lib.event.add(this.fakeElement, 'click', this.toggleDropdown, this);
1894		}
1895		jcf.lib.event.add(this.realElement, 'change', this.onChange, this);
1896	},
1897	onFakeClick: function() {
1898		// do nothing (drop toggles by toggleDropdown method)
1899	},
1900	onFocus: function(){
1901		jcf.modules[this.name].superclass.onFocus.apply(this, arguments);
1902		if(!this.options.showNativeDrop) {
1903			// Mac Safari Fix
1904			if(jcf.lib.browser.safariMac) {
1905				this.realElement.setAttribute('size','2');
1906			}
1907			jcf.lib.event.add(this.realElement, 'keydown', this.onKeyDown, this);
1908			if(jcf.activeControl && jcf.activeControl != this) {
1909				jcf.activeControl.hideDropdown();
1910				jcf.activeControl = this;
1911			}
1912		}
1913	},
1914	onBlur: function(){
1915		if(!this.options.showNativeDrop) {
1916			// Mac Safari Fix
1917			if(jcf.lib.browser.safariMac) {
1918				this.realElement.removeAttribute('size');
1919			}
1920			if(!this.isActiveDrop() || !this.isOverDrop()) {
1921				jcf.modules[this.name].superclass.onBlur.apply(this);
1922				if(jcf.activeControl === this) jcf.activeControl = null;
1923				if(!jcf.isTouchDevice) {
1924					this.hideDropdown();
1925				}
1926			}
1927			jcf.lib.event.remove(this.realElement, 'keydown', this.onKeyDown);
1928		} else {
1929			jcf.modules[this.name].superclass.onBlur.apply(this);
1930		}
1931	},
1932	onChange: function() {
1933		this.refreshState();
1934	},
1935	onKeyDown: function(e){
1936		this.dropOpened = true;
1937		jcf.tmpFlag = true;
1938		setTimeout(function(){jcf.tmpFlag = false},100);
1939		var context = this;
1940		context.keyboardFix = true;
1941		setTimeout(function(){
1942			context.refreshState();
1943		},10);
1944		if(e.keyCode == 13) {
1945			context.toggleDropdown.apply(context);
1946			return false;
1947		}
1948	},
1949	onResizeWindow: function(e){
1950		if(this.isActiveDrop()) {
1951			this.hideDropdown();
1952		}
1953	},
1954	onScrollWindow: function(e){
1955		if(this.options.hideDropOnScroll) {
1956			this.hideDropdown();
1957		} else if(this.isActiveDrop()) {
1958			this.positionDropdown();
1959		}
1960	},
1961	onOptionClick: function(e){
1962		var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
1963		if(opener) {
1964			this.dropOpened = true;
1965			this.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
1966			if(jcf.isTouchDevice) {
1967				this.onFocus();
1968			} else {
1969				this.realElement.focus();
1970			}
1971			this.refreshState();
1972			this.hideDropdown();
1973			jcf.lib.fireEvent(this.realElement, 'change');
1974		}
1975		return false;
1976	},
1977	onClickOutside: function(e){
1978		if(jcf.tmpFlag) {
1979			jcf.tmpFlag = false;
1980			return;
1981		}
1982		if(!jcf.lib.isParent(this.fakeElement, e.target) && !jcf.lib.isParent(this.selectDrop, e.target)) {
1983			this.hideDropdown();
1984		}
1985	},
1986	onDropHover: function(e){
1987		if(!this.keyboardFix) {
1988			this.hoverFlag = true;
1989			var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
1990			if(opener) {
1991				this.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
1992				this.refreshSelectedClass(parseInt(opener.getAttribute('rel')));
1993			}
1994		} else {
1995			this.keyboardFix = false;
1996		}
1997	},
1998	onDropLeave: function(){
1999		this.hoverFlag = false;
2000	},
2001	isActiveDrop: function(){
2002		return !jcf.lib.hasClass(this.selectDrop, this.options.dropHiddenClass);
2003	},
2004	isOverDrop: function(){
2005		return this.hoverFlag;
2006	},
2007	createDropdown: function(){
2008		// remove old dropdown if exists
2009		if(this.selectDrop) {
2010			this.selectDrop.parentNode.removeChild(this.selectDrop);
2011		}
2012
2013		// create dropdown holder
2014		this.selectDrop = document.createElement('div');
2015		this.selectDrop.className = this.options.dropClass;
2016		this.selectDrop.innerHTML = this.options.dropStructure;
2017		jcf.lib.setStyles(this.selectDrop, {position:'absolute'});
2018		this.selectList = jcf.lib.queryBySelector(this.options.dropSelector,this.selectDrop)[0];
2019		jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
2020		document.body.appendChild(this.selectDrop);
2021		this.selectDrop.jcf = this;
2022		jcf.lib.event.add(this.selectDrop, 'click', this.onOptionClick, this);
2023		jcf.lib.event.add(this.selectDrop, 'mouseover', this.onDropHover, this);
2024		jcf.lib.event.add(this.selectDrop, 'mouseout', this.onDropLeave, this);
2025		this.buildDropdown();
2026	},
2027	buildDropdown: function() {
2028		// build select options / optgroups
2029		this.buildDropdownOptions();
2030
2031		// position and resize dropdown
2032		this.positionDropdown();
2033
2034		// cut dropdown if height exceedes
2035		this.buildDropdownScroll();
2036	},
2037	buildDropdownOptions: function() {
2038		this.resStructure = '';
2039		this.optNum = 0;
2040		for(var i = 0; i < this.realElement.children.length; i++) {
2041			this.resStructure += this.buildElement(this.realElement.children[i], i) +'\n';
2042		}
2043		this.selectList.innerHTML = this.resStructure;
2044	},
2045	buildDropdownScroll: function() {
2046		if(this.options.dropMaxHeight) {
2047			if(this.selectDrop.offsetHeight > this.options.dropMaxHeight) {
2048				this.selectList.style.height = this.options.dropMaxHeight+'px';
2049				this.selectList.style.overflow = 'auto';
2050				this.selectList.style.overflowX = 'hidden';
2051				jcf.lib.addClass(this.selectDrop, this.options.dropScrollableClass);
2052			}
2053		}
2054		jcf.lib.addClass(this.selectDrop, jcf.lib.getAllClasses(this.realElement.className, this.options.dropClassPrefix, jcf.baseOptions.hiddenClass));
2055	},
2056	parseOptionTitle: function(optTitle) {
2057		return (typeof optTitle === 'string' && /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i.test(optTitle)) ? optTitle : '';
2058	},
2059	buildElement: function(obj, index){
2060		// build option
2061		var res = '', optImage;
2062		if(obj.tagName.toLowerCase() == 'option') {
2063			if(!jcf.lib.prevSibling(obj) || jcf.lib.prevSibling(obj).tagName.toLowerCase() != 'option') {
2064				res += '<ul>';
2065			}
2066			
2067			optImage = this.parseOptionTitle(obj.title);
2068			res += '<li rel="'+(this.optNum++)+'" class="'+(obj.className? obj.className + ' ' : '')+(index % 2 ? 'option-even ' : '')+'jcfcalc"><a href="#">'+(optImage ? '<img src="'+optImage+'" alt="" />
2068' : '')+'<span>' + obj.innerHTML + '</span></a></li>';
2069			if(!jcf.lib.nextSibling(obj) || jcf.lib.nextSibling(obj).tagName.toLowerCase() != 'option') {
2070				res += '</ul>';
2071			}
2072			return res;
2073		}
2074		// build option group with options
2075		else if(obj.tagName.toLowerCase() == 'optgroup' && obj.label) {
2076			res += '<div class="'+this.options.optGroupClass+'">';
2077			res += '<strong class="jcfcalc"><em>'+(obj.label)+'</em></strong>';
2078			for(var i = 0; i < obj.children.length; i++) {
2079				res += this.buildElement(obj.children[i], i);
2080			}
2081			res += '</div>';
2082			return res;
2083		}
2084	},
2085	positionDropdown: function(){
2086		var ofs = jcf.lib.getOffset(this.fakeElement), selectAreaHeight = this.fakeElement.offsetHeight, selectDropHeight = this.selectDrop.offsetHeight;
2087		var fitInTop = ofs.top - selectDropHeight >= jcf.lib.getScrollTop() && jcf.lib.getScrollTop() + jcf.lib.getWindowHeight() < ofs.top + selectAreaHeight + selectDropHeight;
2088		
2089		
2090		if((this.options.handleDropPosition && fitInTop) || this.options.selectDropPosition === 'top') {
2091			this.selectDrop.style.top = (ofs.top - selectDropHeight)+'px';
2092			jcf.lib.addClass(this.selectDrop, this.options.dropFlippedClass);
2093		} else {
2094			this.selectDrop.style.top = (ofs.top + selectAreaHeight)+'px';
2095			jcf.lib.removeClass(this.selectDrop, this.options.dropFlippedClass);
2096		}
2097		this.selectDrop.style.left = ofs.left+'px';
2098		this.selectDrop.style.width = this.fakeElement.offsetWidth+'px';
2099	},
2100	showDropdown: function(){
2101		document.body.appendChild(this.selectDrop);
2102		jcf.lib.removeClass(this.selectDrop, this.options.dropHiddenClass);
2103		jcf.lib.addClass(this.fakeElement,this.options.dropActiveClass);
2104		this.positionDropdown();
2105
2106		// highlight current active item
2107		var activeItem = this.getFakeActiveOption();
2108		this.removeClassFromItems(this.options.currentSelectedClass);
2109		jcf.lib.addClass(activeItem, this.options.currentSelectedClass);
2110		
2111		// show current dropdown
2112		jcf.lib.event.add(window, 'resize', this.onResizeWindow, this);
2113		jcf.lib.event.add(window, 'scroll', this.onScrollWindow, this);
2114		jcf.lib.event.add(document, jcf.eventPress, this.onClickOutside, this);
2115		this.positionDropdown();
2116	},
2117	hideDropdown: function(partial){
2118		if(this.selectDrop.parentNode) {
2119			if(this.selectDrop.offsetWidth) {
2120				this.selectDrop.parentNode.removeChild(this.selectDrop);
2121			}
2122			if(partial) {
2123				return;
2124			}
2125		}
2126		if(typeof this.origSelectedIndex === 'number') {
2127			this.realElement.selectedIndex = this.origSelectedIndex;
2128		}
2129		jcf.lib.removeClass(this.fakeElement,this.options.dropActiveClass);
2130		jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
2131		jcf.lib.event.remove(window, 'resize', this.onResizeWindow);
2132		jcf.lib.event.remove(window, 'scroll', this.onScrollWindow);
2133		jcf.lib.event.remove(document.documentElement, jcf.eventPress, this.onClickOutside);
2134		if(jcf.isTouchDevice) {
2135			this.onBlur();
2136		}
2137	},
2138	toggleDropdown: function(){
2139		if(!this.realElement.disabled) {
2140			if(jcf.isTouchDevice) {
2141				this.onFocus();
2142			} else {
2143				this.realElement.focus();
2144			}
2145			if(this.isActiveDrop()) {
2146				this.hideDropdown();
2147			} else {
2148				this.showDropdown();
2149			}
2150			this.refreshState();
2151		}
2152	},
2153	scrollToItem: function(){
2154		if(this.isActiveDrop()) {
2155			var dropHeight = this.selectList.offsetHeight;
2156			var offsetTop = this.calcOptionOffset(this.getFakeActiveOption());
2157			var sTop = this.selectList.scrollTop;
2158			var oHeight = this.getFakeActiveOption().offsetHeight;
2159			//offsetTop+=sTop;
2160
2161			if(offsetTop >= sTop + dropHeight) {
2162				this.selectList.scrollTop = offsetTop - dropHeight + oHeight;
2163			} else if(offsetTop < sTop) {
2164				this.selectList.scrollTop = offsetTop;
2165			}
2166		}
2167	},
2168	getFakeActiveOption: function(c) {
2169		return jcf.lib.queryBySelector('li[rel="'+(typeof c === 'number' ? c : this.realElement.selectedIndex) +'"]',this.selectList)[0];
2170	},
2171	calcOptionOffset: function(fake) {
2172		var h = 0;
2173		var els = jcf.lib.queryBySelector('.jcfcalc',this.selectList);
2174		for(var i = 0; i < els.length; i++) {
2175			if(els[i] == fake) break;
2176			h+=els[i].offsetHeight;
2177		}
2178		return h;
2179	},
2180	childrenHasItem: function(hold,item) {
2181		var items = hold.getElementsByTagName('*');
2182		for(i = 0; i < items.length; i++) {
2183			if(items[i] == item) return true;
2184		}
2185		return false;
2186	},
2187	removeClassFromItems: function(className){
2188		var children = jcf.lib.queryBySelector('li',this.selectList);
2189		for(var i = children.length - 1; i >= 0; i--) {
2190			jcf.lib.removeClass(children[i], className);
2191		}
2192	},
2193	setSelectedClass: function(c){
2194		jcf.lib.addClass(this.getFakeActiveOption(c), this.options.selectedClass);
2195	},
2196	refreshSelectedClass: function(c){
2197		if(!this.options.showNativeDrop) {
2198			this.removeClassFromItems(this.options.selectedClass);
2199			this.setSelectedClass(c);
2200		}
2201		if(this.realElement.disabled) {
2202			jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
2203			if(this.labelFor) {
2204				jcf.lib.addClass(this.labelFor, this.options.labelDisabledClass);
2205			}
2206		} else {
2207			jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
2208			if(this.labelFor) {
2209				jcf.lib.removeClass(this.labelFor, this.options.labelDisabledClass);
2210			}
2211		}
2212	},
2213	refreshSelectedText: function() {
2214		if(!this.dropOpened && this.realElement.title) {
2215			this.valueText.innerHTML = this.realElement.title;
2216		} else {
2217			if(this.realElement.options[this.realElement.selectedIndex].title) {
2218				var optImage = this.parseOptionTitle(this.realElement.options[this.realElement.selectedIndex].title);
2219				this.valueText.innerHTML = (optImage ? '<img src="'+optImage+'" alt="" />' : '') + this.realElement.options[this.realElement.selectedIndex].innerHTML;
2220			} else {
2221				this.valueText.innerHTML = this.realElement.options[this.realElement.selectedIndex].innerHTML;
2222			}
2223		}
2224	},
2225	refreshState: function(){
2226		this.origSelectedIndex = this.realElement.selectedIndex;
2227		this.refreshSelectedClass();
2228		this.refreshSelectedText();
2229		if(!this.options.showNativeDrop) {
2230			this.positionDropdown();
2231			if(this.selectDrop.offsetWidth) {
2232				this.scrollToItem();
2233			}
2234		}
2235	}
2236});
2237
2238// custom radio module
2239jcf.addModule({
2240	name:'radio',
2241	selector: 'input[type="radio"]',
2242	defaultOptions: {
2243		wrapperClass:'rad-area',
2244		focusClass:'rad-focus',
2245		checkedClass:'rad-checked',
2246		uncheckedClass:'rad-unchecked',
2247		disabledClass:'rad-disabled',
2248		radStructure:'<span></span>'
2249	},
2250	getRadioGroup: function(item){
2251		var name = item.getAttribute('name');
2252		if(name) {
2253			return jcf.lib.queryBySelector('input[name="'+name+'"]', jcf.lib.getParent('form'));
2254		} else {
2255			return [item];
2256		}
2257	},
2258	setupWrapper: function(){
2259		jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
2260		this.fakeElement.innerHTML = this.options.radStructure;
2261		this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
2262		this.refreshState();
2263		this.addEvents();
2264	},
2265	addEvents: function(){
2266		jcf.lib.event.add(this.fakeElement, 'click', this.toggleRadio, this);
2267		if(this.labelFor) {
2268			jcf.lib.event.add(this.labelFor, 'click', this.toggleRadio, this);
2269		}
2270	},
2271	onFocus: function(e) {
2272		jcf.modules[this.name].superclass.onFocus.apply(this, arguments);
2273		setTimeout(jcf.lib.bind(function(){
2274			this.refreshState();
2275		},this),10);
2276	},
2277	toggleRadio: function(){
2278		if(!this.realElement.disabled) {
2279			this.realElement.checked = true;
2280		}
2281		this.refreshState();
2282		//alert('toggle radio ' + this.realElement.id) ;
2283		if ( this.realElement.onchange) 	{
2284		   this.realElement.onchange() ;
2285		}
2286	},
2287	refreshState: function(){
2288		var els = this.getRadioGroup(this.realElement);
2289		for(var i = 0; i < els.length; i++) {
2290			var curEl = els[i].jcf;
2291			if(curEl) {
2292				if(curEl.realElement.checked) {
2293					jcf.lib.addClass(curEl.fakeElement, curEl.options.checkedClass);
2294					jcf.lib.removeClass(curEl.fakeElement, curEl.options.uncheckedClass);
2295					if(curEl.labelFor) {
2296						jcf.lib.addClass(curEl.labelFor, curEl.options.labelActiveClass);
2297					}
2298				} else {
2299					jcf.lib.removeClass(curEl.fakeElement, curEl.options.checkedClass);
2300					jcf.lib.addClass(curEl.fakeElement, curEl.options.uncheckedClass);
2301					if(curEl.labelFor) {
2302						jcf.lib.removeClass(curEl.labelFor, curEl.options.labelActiveClass);
2303					}
2304				}
2305				if(curEl.realElement.disabled) {
2306					jcf.lib.addClass(curEl.fakeElement, curEl.options.disabledClass);
2307					if(curEl.labelFor) {
2308						jcf.lib.addClass(curEl.labelFor, curEl.options.labelDisabledClass);
2309					}
2310				} else {
2311					jcf.lib.removeClass(curEl.fakeElement, curEl.options.disabledClass);
2312					if(curEl.labelFor) {
2313						jcf.lib.removeClass(curEl.labelFor, curEl.options.labelDisabledClass);
2314					}
2315				}
2316			}
2317		}
2318	}
2319});
2320
2321// custom upload field module
2322var the_nav = navigator.userAgent.toString().toLowerCase() ;
2323if (the_nav.indexOf('firefox') == -1) { 
2324   jcf.addModule(   {
2325   	name: 'file',
2326   	selector: 'input[type="file"]',
2327   	defaultOptions: {
2328   		buttonWidth: 30,
2329   		bigFontSize: 200,
2330   		buttonText:'Parcourir',
2331   		wrapperClass:'file-area',
2332   		focusClass:'file-focus',
2333   		disabledClass:'file-disabled',
2334   		opacityClass:'file-input-opacity',
2335   		noFileClass:'no-file',
2336   		extPrefixClass:'extension-',
2337   		uploadStructure:'<div class="jcf-input-wrapper"><div class="jcf-wrap"></div><label class="jcf-fake-input"><span><em></em></span></label><a class="jcf-upload-button"><span></span></a></div>',
2338   		uploadFileNameSelector:'label.jcf-fake-input span em',
2339   		uploadButtonSelector:'a.jcf-upload-button span',
2340   		inputWrapper: 'div.jcf-wrap'
2341   	},
2342   	setupWrapper: function(){
2343   		jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
2344   		this.fakeElement.innerHTML = this.options.uploadStructure;
2345   		this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
2346   		this.fileNameInput = jcf.lib.queryBySelector(this.options.uploadFileNameSelector ,this.fakeElement)[0];
2347   		this.uploadButton = jcf.lib.queryBySelector(this.options.uploadButtonSelector ,this.fakeElement)[0];
2348   		this.inputWrapper = jcf.lib.queryBySelector(this.options.inputWrapper ,this.fakeElement)[0];
2349
2350   		this.origTitle = this.realElement.title;
2351   		this.fileNameInput.innerHTML = this.realElement.title || '';
2352   		this.uploadButton.innerHTML = this.options.buttonText;
2353   		this.realElement.removeAttribute('title');
2354   		this.fakeElement.style.position = 'relative';
2355   		this.realElement.style.position = 'absolute';
2356   		this.realElement.style.zIndex = 100;
2357   		this.inputWrapper.appendChild(this.realElement);
2358   		this.oTop = this.oLeft = this.oWidth = this.oHeight = 0;
2359
2360   		jcf.lib.addClass(this.realElement, this.options.opacityClass);
2361   		jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
2362   		this.inputWrapper.style.width = this.inputWrapper.parentNode.offsetWidth+'px';
2363
2364   		this.shakeInput();
2365   		this.refreshState();
2366   		this.addEvents();
2367   	},
2368   	addEvents: function(){
2369   		jcf.lib.event.add(this.realElement, 'change', this.onChange, this);
2370   		if(!jcf.isTouchDevice) {
2371   			jcf.lib.event.add(this.fakeElement, 'mousemove', this.onMouseMove, this);
2372   			jcf.lib.event.add(this.fakeElement, 'mouseover', this.recalcDimensions, this);
2373   		}
2374   	},
2375   	onMouseMove: function(e){
2376   		this.realElement.style.top = Math.round(e.pageY - this.oTop - this.oHeight/2) + 'px';
2377   		this.realElement.style.left = (e.pageX - this.oLeft - this.oWidth + this.options.buttonWidth) + 'px';
2378   	},
2379   	onChange: function(){
2380   		this.refreshState();
2381   	},
2382   	getFileName: function(){
2383   		return this.realElement.value.replace(/^[\s\S]*(?:\\|\/)([\s\S^\\\/]*)$/g, "$1");
2384   	},
2385   	getFileExtension: function(){
2386   		return this.realElement.value.lastIndexOf('.') < 0 ? false : this.realElement.value.substring(this.realElement.value.lastIndexOf('.')+1).toLowerCase();
2387   	},
2388   	updateExtensionClass: function(){
2389   		var currentExtension = this.getFileExtension();
2390   		if(currentExtension) {
2391   			this.fakeElement.className = this.fakeElement.className.replace(new RegExp('(\\s|^)'+this.options.extPrefixClass+'[^ ]+','gi'),'')
2392   			jcf.lib.addClass(this.fakeElement, this.options.extPrefixClass+currentExtension)
2393   		}
2394   	},
2395   	shakeInput: function() {
2396   		// make input bigger
2397   		jcf.lib.setStyles(this.realElement, {
2398   			fontSize: this.options.bigFontSize,
2399   			lineHeight: this.options.bigFontSize,
2400   			heigth: 'auto',
2401   			top: 0,
2402   			left: this.inputWrapper.offsetWidth - this.realElement.offsetWidth
2403   		});
2404   		// IE styling fix
2405   		if((/(MSIE)/gi).test(navigator.userAgent)) {
2406   			this.tmpElement = document.createElement('span');
2407   			this.inputWrapper.insertBefore(this.tmpElement,this.realElement);
2408   			this.inputWrapper.insertBefore(this.realElement,this.tmpElement);
2409   			this.inputWrapper.removeChild(this.tmpElement);
2410   		}
2411   	},
2412   	recalcDimensions: function() {
2413   		var o = jcf.lib.getOffset(this.fakeElement);
2414   		this.oTop = o.top;
2415   		this.oLeft = o.left;
2416   		this.oWidth = this.realElement.offsetWidth;
2417   		this.oHeight = this.realElement.offsetHeight;
2418   	},
2419   	refreshState: function(){
2420   		jcf.lib.setStyles(this.realElement, {opacity: 0});
2421   		this.fileNameInput.innerHTML = this.getFileName() || this.origTitle || '';
2422   		if(this.realElement.disabled) {
2423   			jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
2424   			if(this.labelFor) {
2425   				jcf.lib.addClass(this.labelFor, this.options.labelDisabledClass);
2426   			}
2427   		} else {
2428   			jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
2429   			if(this.labelFor) {
2430   				jcf.lib.removeClass(this.labelFor, this.options.labelDisabledClass);
2431   			}
2432   		}
2433   		if(this.realElement.value.length) {
2434   			jcf.lib.removeClass(this.fakeElement, this.options.noFileClass);
2435   		} else {
2436   			jcf.lib.addClass(this.fakeElement, this.options.noFileClass);
2437   		}
2438   		this.updateExtensionClass();
2439   	}
2440   });
2441}
2442
2443
2444// placeholder class
2445
2446;(function(){
2447	var placeholderCollection = [];
2448	PlaceholderInput = function() {
2449		this.options = {
2450			element:null,
2451			showUntilTyping:false,
2452			wrapWithElement:false,
2453			getParentByClass:false,
2454			showPasswordBullets:false,
2455			placeholderAttr:'value',
2456			inputFocusClass:'focus',
2457			inputActiveClass:'text-active',
2458			parentFocusClass:'parent-focus',
2459			parentActiveClass:'parent-active',
2460			labelFocusClass:'label-focus',
2461			labelActiveClass:'label-active',
2462			fakeElementClass:'input-placeholder-text'
2463		};
2464		placeholderCollection.push(this);
2465		this.init.apply(this,arguments);
2466	};
2467	PlaceholderInput.refreshAllInputs = function(except) {
2468		for(var i = 0; i < placeholderCollection.length; i++) {
2469			if(except !== placeholderCollection[i]) {
2470				placeholderCollection[i].refreshState();
2471			}
2472		}
2473	};
2474	PlaceholderInput.replaceByOptions = function(opt) {
2475		var inputs = [].concat(
2476			convertToArray(document.getElementsByTagName('input')),
2477			convertToArray(document.getElementsByTagName('textarea'))
2478		);
2479		for(var i = 0; i < inputs.length; i++) {
2480         var inputID =  inputs[i].id ;
2481         if (inputID == "mini_cv") { continue ;}
2482         if (inputID == "forum_subject") { continue ;}
2483         if (inputID == "message-1") { continue ;}
2484         if (inputID == "message-2") { continue ;}
2485			if(inputs[i].className.indexOf(opt.skipClass) < 0)
2486         {
2487				var inputType = getInputType(inputs[i]);
2488				var placeholderValue = inputs[i].getAttribute('placeholder');
2489				if(opt.focusOnly || (opt.clearInputs && (inputType === 'text' || inputType === 'email' || placeholderValue)) ||
2490					(opt.clearTextareas && inputType === 'textarea') ||
2491					(opt.clearPasswords && inputType === 'password')
2492				) {
2493					new PlaceholderInput({
2494						element:inputs[i],
2495						focusOnly: opt.focusOnly,
2496						wrapWithElement:opt.wrapWithElement,
2497						showUntilTyping:opt.showUntilTyping,
2498						getParentByClass:opt.getParentByClass,
2499						showPasswordBullets:opt.showPasswordBullets,
2500						placeholderAttr: placeholderValue ? 'placeholder' : opt.placeholderAttr
2501					});
2502				}
2503			}
2504		}
2505	};
2506	PlaceholderInput.prototype = {
2507		init: function(opt) {
2508			this.setOptions(opt);
2509			if(this.element && this.element.PlaceholderInst) {
2510				this.element.PlaceholderInst.refreshClasses();
2511			} else {
2512				this.element.PlaceholderInst = this;
2513				if(this.elementType !== 'radio' || this.elementType !== 'checkbox' || this.elementType !== 'file') {
2514					this.initElements();
2515					this.attachEvents();
2516					this.refreshClasses();
2517				}
2518			}
2519		},
2520		setOptions: function(opt) {
2521			for(var p in opt) {
2522				if(opt.hasOwnProperty(p)) {
2523					this.options[p] = opt[p];
2524				}
2525			}
2526			if(this.options.element) {
2527				this.element = this.options.element;
2528				this.elementType = getInputType(this.element);
2529				if(this.options.focusOnly) {
2530					this.wrapWithElement = false;
2531				} else {
2532					if(this.elementType === 'password' && this.options.showPasswordBullets) {
2533						this.wrapWithElement = false;
2534					} else {
2535						this.wrapWithElement = this.elementType === 'password' || this.options.showUntilTyping ? true : this.options.wrapWithElement;
2536					}
2537				}
2538				this.setPlaceholderValue(this.options.placeholderAttr);
2539			}
2540		},
2541		setPlaceholderValue: function(attr) {
2542			this.origValue = (attr === 'value' ? this.element.defaultValue : (this.element.getAttribute(attr) || ''));
2543			if(this.options.placeholderAttr !== 'value') {
2544				this.element.removeAttribute(this.options.placeholderAttr);
2545			}
2546		},
2547		initElements: function() {
2548			// create fake element if needed
2549			if(this.wrapWithElement) {
2550				this.fakeElement = document.createElement('span');
2551				this.fakeElement.className = this.options.fakeElementClass;
2552				this.fakeElement.innerHTML += this.origValue;
2553				this.fakeElement.style.color = getStyle(this.element, 'color');
2554				this.fakeElement.style.position = 'absolute';
2555				this.element.parentNode.insertBefore(this.fakeElement, this.element);
2556				
2557				if(this.element.value === this.origValue || !this.element.value) {
2558					this.element.value = '';
2559					this.togglePlaceholderText(true);
2560				} else {
2561					this.togglePlaceholderText(false);
2562				}
2563			} else if(!this.element.value && this.origValue.length) {
2564				this.element.value = this.origValue;
2565			}
2566			// get input label
2567			if(this.element.id) {
2568				this.labels = document.getElementsByTagName('label');
2569				for(var i = 0; i < this.labels.length; i++) {
2570					if(this.labels[i].htmlFor === this.element.id) {
2571						this.labelFor = this.labels[i];
2572						break;
2573					}
2574				}
2575			}
2576			// get parent node (or parentNode by className)
2577			this.elementParent = this.element.parentNode;
2578			if(typeof this.options.getParentByClass === 'string') {
2579				var el = this.element;
2580				while(el.parentNode) {
2581					if(hasClass(el.parentNode, this.options.getParentByClass)) {
2582						this.elementParent = el.parentNode;
2583						break;
2584					} else {
2585						el = el.parentNode;
2586					}
2587				}
2588			}
2589		},
2590		attachEvents: function() {
2591			this.element.onfocus = bindScope(this.focusHandler, this);
2592			this.element.onblur = bindScope(this.blurHandler, this);
2593			if(this.options.showUntilTyping) {
2594				this.element.onkeydown = bindScope(this.typingHandler, this);
2595				this.element.onpaste = bindScope(this.typingHandler, this);
2596			}
2597			if(this.wrapWithElement) this.fakeElement.onclick = bindScope(this.focusSetter, this);
2598		},
2599		togglePlaceholderText: function(state) {
2600			if(!this.element.readOnly && !this.options.focusOnly) {
2601				if(this.wrapWithElement) {
2602					this.fakeElement.style.display = state ? '' : 'none';
2603				} else {
2604					this.element.value = state ? this.origValue : '';
2605				}
2606			}
2607		},
2608		focusSetter: function() {
2609			this.element.focus();
2610		},
2611		focusHandler: function() {
2612			clearInterval(this.checkerInterval);
2613			this.checkerInterval = setInterval(bindScope(this.intervalHandler,this), 1);
2614			this.focused = true;
2615			if(!this.element.value.length || this.element.value === this.origValue) {
2616				if(!this.options.showUntilTyping) {
2617					this.togglePlaceholderText(false);
2618				}
2619			}
2620			this.refreshClasses();
2621		},
2622		blurHandler: function() {
2623			clearInterval(this.checkerInterval);
2624			this.focused = false;
2625			if(!this.element.value.length || this.element.value === this.origValue) {
2626				this.togglePlaceholderText(true);
2627			}
2628			this.refreshClasses();
2629			PlaceholderInput.refreshAllInputs(this);
2630		},
2631		typingHandler: function() {
2632			setTimeout(bindScope(function(){
2633				if(this.element.value.length) {
2634					this.togglePlaceholderText(false);
2635					this.refreshClasses();
2636				}
2637			},this), 10);
2638		},
2639		intervalHandler: function() {
2640			if(typeof this.tmpValue === 'undefined') {
2641				this.tmpValue = this.element.value;
2642			}
2643			if(this.tmpValue != this.element.value) {
2644				PlaceholderInput.refreshAllInputs(this);
2645			}
2646		},
2647		refreshState: function() {
2648			if(this.wrapWithElement) {
2649				if(this.element.value.length && this.element.value !== this.origValue) {
2650					this.togglePlaceholderText(false);
2651				} else if(!this.element.value.length) {
2652					this.togglePlaceholderText(true);
2653				}
2654			}
2655			this.refreshClasses();
2656		},
2657		refreshClasses: function() {
2658			this.textActive = this.focused || (this.element.value.length && this.element.value !== this.origValue);
2659			this.setStateClass(this.element, this.options.inputFocusClass,this.focused);
2660			this.setStateClass(this.elementParent, this.options.parentFocusClass,this.focused);
2661			this.setStateClass(this.labelFor, this.options.labelFocusClass,this.focused);
2662			this.setStateClass(this.element, this.options.inputActiveClass, this.textActive);
2663			this.setStateClass(this.elementParent, this.options.parentActiveClass, this.textActive);
2664			this.setStateClass(this.labelFor, this.options.labelActiveClass, this.textActive);
2665		},
2666		setStateClass: function(el,cls,state) {
2667			if(!el) return; else if(state) addClass(el,cls); else removeClass(el,cls);
2668		}
2669	};
2670	
2671	// utility functions
2672	function convertToArray(collection) {
2673		var arr = [];
2674		for (var i = 0, ref = arr.length = collection.length; i < ref; i++) {
2675			arr[i] = collection[i];
2676		}
2677		return arr;
2678	}
2679	function getInputType(input) {
2680		return (input.type ? input.type : input.tagName).toLowerCase();
2681	}
2682	function hasClass(el,cls) {
2683		return el.className ? el.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')) : false;
2684	}
2685	function addClass(el,cls) {
2686		if (!hasClass(el,cls)) el.className += " "+cls;
2687	}
2688	function removeClass(el,cls) {
2689		if (hasClass(el,cls)) {el.className=el.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ');}
2690	}
2691	function bindScope(f, scope) {
2692		return function() {return f.apply(scope, arguments);};
2693	}
2694	function getStyle(el, prop) {
2695		if (document.defaultView && document.defaultView.getComputedStyle) {
2696			return document.defaultView.getComputedStyle(el, null)[prop];
2697		} else if (el.currentStyle) {
2698			return el.currentStyle[prop];
2699		} else {
2700			return el.style[prop];
2701		}
2702	}
2703}());
2704
2705
2706/*
2707* touchSwipe - jQuery Plugin
2708* https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
2709* http://labs.skinkers.com/touchSwipe/
2710* http://plugins.jquery.com/project/touchSwipe
2711*
2712* Copyright (c) 2010 Matt Bryson (www.skinkers.com)
2713* Dual licensed under the MIT or GPL Version 2 licenses.
2714*
2715* $version: 1.5.1
2716*/
2717
2718/*;(function(d){var l="left",k="right",c="up",r="down",b="in",s="out",i="none",o="auto",u="horizontal",p="vertical",f="all",e="start",h="move",g="end",m="cancel",a="ontouchstart" in window,t="TouchSwipe";var j={fingers:1,threshold:75,maxTimeThreshold:null,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,triggerOnTouchEnd:true,allowPageScroll:"auto",fallbackToMouseEvents:true,excludedElements:"button, input, select, textarea, a, .noSwipe"};d.fn.swipe=function(x){var w=d(this),v=w.data(t);if(v&&typeof x==="string"){if(v[x]){return v[x].apply(this,Array.prototype.slice.call(arguments,1))}else{d.error("Method "+x+" does not exist on jQuery.swipe")}}else{if(!v&&(typeof x==="object"||!x)){return q.apply(this,arguments)}}return w};d.fn.swipe.defaults=j;d.fn.swipe.phases={PHASE_START:e,PHASE_MOVE:h,PHASE_END:g,PHASE_CANCEL:m};d.fn.swipe.directions={LEFT:l,RIGHT:k,UP:c,DOWN:r,IN:b,OUT:s};d.fn.swipe.pageScroll={NONE:i,HORIZONTAL:u,VERTICAL:p,AUTO:o};d.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:f};function q(v){if(v&&(v.allowPageScroll===undefined&&(v.swipe!==undefined||v.swipeStatus!==undefined))){v.allowPageScroll=i}if(!v){v={}}v=d.extend({},d.fn.swipe.defaults,v);return this.each(function(){var x=d(this);var w=x.data(t);if(!w){w=new n(this,v);x.data(t,w)}})}function n(J,R){var aj=(a||!R.fallbackToMouseEvents),ae=aj?"touchstart":"mousedown",K=aj?"touchmove":"mousemove",ac=aj?"touchend":"mouseup",I="touchcancel";var P=0;var E=null;var S=0;var af=0;var w=0;var U=1;var ak=0;var A=d(J);var F="start";var ai=0;var T=null;var B=0;var M=0;try{A.bind(ae,aa);A.bind(I,D)}catch(ag){d.error("events not supported "+ae+","+I+" on jQuery.swipe")}this.enable=function(){A.bind(ae,aa);A.bind(I,D);return A};this.disable=function(){H();return A};this.destroy=function(){H();A.data(t,null);return A};function aa(ao){if(L()){return}if(d(ao.target).closest(R.excludedElements,A).length>0){return}ao=ao.originalEvent;var an,am=a?ao.touches[0]:ao;F=e;if(a){ai=ao.touches.length}else{ao.preventDefault()}P=0;E=null;ak=null;S=0;af=0;w=0;U=1;T=al();if(!a||(ai===R.fingers||R.fingers===f)||W()){T[0].start.x=T[0].end.x=am.pageX;T[0].start.y=T[0].end.y=am.pageY;B=x();if(ai==2){T[1].start.x=T[1].end.x=ao.touches[1].pageX;T[1].start.y=T[1].end.y=ao.touches[1].pageY;af=w=N(T[0].start,T[1].start)}if(R.swipeStatus||R.pinchStatus){an=ah(ao,F)}}else{D(ao);an=false}if(an===false){F=m;ah(ao,F);return an}else{V(true);A.bind(K,G);A.bind(ac,O)}}function G(ap){ap=ap.originalEvent;if(F===g||F===m){return}var an,am=a?ap.touches[0]:ap;T[0].end.x=a?ap.touches[0].pageX:am.pageX;T[0].end.y=a?ap.touches[0].pageY:am.pageY;M=x();E=Z(T[0].start,T[0].end);if(a){ai=ap.touches.length}F=h;if(ai==2){if(af==0){T[1].start.x=ap.touches[1].pageX;T[1].start.y=ap.touches[1].pageY;af=w=N(T[0].start,T[1].start)}else{T[1].end.x=ap.touches[1].pageX;T[1].end.y=ap.touches[1].pageY;w=N(T[0].end,T[1].end);ak=X(T[0].end,T[1].end)}U=v(af,w)}if((ai===R.fingers||R.fingers===f)||!a){y(ap,E);P=z(T[0].start,T[0].end);S=C(T[0].start,T[0].end);if(R.swipeStatus||R.pinchStatus){an=ah(ap,F)}if(!R.triggerOnTouchEnd){var ao=!Y();if(Q()===true){F=g;an=ah(ap,F)}else{if(ao){F=m;ah(ap,F)}}}}else{F=m;ah(ap,F)}if(an===false){F=m;ah(ap,F)}}function O(at){at=at.originalEvent;if(at.touches&&at.touches.length>0){return true}at.preventDefault();M=x();if(af!=0){w=N(T[0].end,T[1].end);U=v(af,w);ak=X(T[0].end,T[1].end)}P=z(T[0].start,T[0].end);E=Z(T[0].start,T[0].end);S=C();if(R.triggerOnTouchEnd||(R.triggerOnTouchEnd===false&&F===h)){F=g;var ap=ad()||!W();var an=((ai===R.fingers||R.fingers===f)||!a);var am=T[0].end.x!==0;var ao=(an&&am&&ap);if(ao){var aq=Y();var ar=Q();if((ar===true||ar===null)&&aq){ah(at,F)}else{if(!aq||ar===false){F=m;ah(at,F)}}}else{F=m;ah(at,F)}}else{if(F===h){F=m;ah(at,F)}}A.unbind(K,G,false);A.unbind(ac,O,false);V(false)}function D(){ai=0;M=0;B=0;af=0;w=0;U=1;V(false)}function ah(ao,am){var an=undefined;if(R.swipeStatus){an=R.swipeStatus.call(A,ao,am,E||null,P||0,S||0,ai)}if(R.pinchStatus&&ad()){an=R.pinchStatus.call(A,ao,am,ak||null,w||0,S||0,ai,U)}if(am===m){if(R.click&&(ai===1||!a)&&(isNaN(P)||P===0)){an=R.click.call(A,ao,ao.target)}}if(am==g){if(R.swipe){an=R.swipe.call(A,ao,E,P,S,ai)}switch(E){case l:if(R.swipeLeft){an=R.swipeLeft.call(A,ao,E,P,S,ai)}break;case k:if(R.swipeRight){an=R.swipeRight.call(A,ao,E,P,S,ai)}break;case c:if(R.swipeUp){an=R.swipeUp.call(A,ao,E,P,S,ai)}break;case r:if(R.swipeDown){an=R.swipeDown.call(A,ao,E,P,S,ai)}break}switch(ak){case b:if(R.pinchIn){an=R.pinchIn.call(A,ao,ak||null,w||0,S||0,ai,U)}break;case s:if(R.pinchOut){an=R.pinchOut.call(A,ao,ak||null,w||0,S||0,ai,U)}break}}if(am===m||am===g){D(ao)}return an}function Q(){if(R.threshold!==null){return P>=R.threshold}return null}function Y(){var am;if(R.maxTimeThreshold){if(S>=R.maxTimeThreshold){am=false}else{am=true}}else{am=true}return am}function y(am,an){if(R.allowPageScroll===i||W()){am.preventDefault()}else{var ao=R.allowPageScroll===o;switch(an){case l:if((R.swipeLeft&&ao)||(!ao&&R.allowPageScroll!=u)){am.preventDefault()}break;case k:if((R.swipeRight&&ao)||(!ao&&R.allowPageScroll!=u)){am.preventDefault()}break;
2718case c:if((R.swipeUp&&ao)||(!ao&&R.allowPageScroll!=p)){am.preventDefault()}break;case r:if((R.swipeDown&&ao)||(!ao&&R.allowPageScroll!=p)){am.preventDefault()}break}}}function C(){return M-B}function N(ap,ao){var an=Math.abs(ap.x-ao.x);var am=Math.abs(ap.y-ao.y);return Math.round(Math.sqrt(an*an+am*am))}function v(am,an){var ao=(an/am)*1;return ao.toFixed(2)}function X(){if(U<1){return s}else{return b}}function z(an,am){return Math.round(Math.sqrt(Math.pow(am.x-an.x,2)+Math.pow(am.y-an.y,2)))}function ab(ap,an){var am=ap.x-an.x;var ar=an.y-ap.y;var ao=Math.atan2(ar,am);var aq=Math.round(ao*180/Math.PI);if(aq<0){aq=360-Math.abs(aq)}return aq}function Z(an,am){var ao=ab(an,am);if((ao<=45)&&(ao>=0)){return l}else{if((ao<=360)&&(ao>=315)){return l}else{if((ao>=135)&&(ao<=225)){return k}else{if((ao>45)&&(ao<135)){return r}else{return c}}}}}function x(){var am=new Date();return am.getTime()}function H(){A.unbind(ae,aa);A.unbind(I,D);A.unbind(K,G);A.unbind(ac,O);V(false)}function W(){return R.pinchStatus||R.pinchIn||R.pinchOut}function ad(){return ak&&W()}function L(){return A.data(t+"_intouch")===true?true:false}function V(am){am=am===true?true:false;A.data(t+"_intouch",am)}function al(){var am=[];for(var an=0;an<=5;an++){am.push({start:{x:0,y:0},end:{x:0,y:0},delta:{x:0,y:0}})}return am}}})(jQuery);
2719*/

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.