2016-03-16 17:30:07 +05:00
|
|
|
|
// page init
|
2016-03-28 20:07:51 +05:00
|
|
|
|
jQuery(function(){
|
2016-03-16 17:30:07 +05:00
|
|
|
|
jcf.customForms.replaceAll('.custom-elements');
|
2016-03-28 20:07:51 +05:00
|
|
|
|
initCarousel();
|
|
|
|
|
initSlideShow();
|
|
|
|
|
initRating();
|
|
|
|
|
jQuery('input, textarea').placeholder();
|
2016-03-16 17:30:07 +05:00
|
|
|
|
});
|
|
|
|
|
|
2016-03-28 20:07:51 +05:00
|
|
|
|
// scroll gallery init
|
|
|
|
|
function initCarousel() {
|
|
|
|
|
jQuery('.slider').scrollGallery({
|
|
|
|
|
mask: '.mask',
|
|
|
|
|
slider: '.slideset',
|
|
|
|
|
slides: '.slide',
|
|
|
|
|
btnPrev: 'a.btn-prev',
|
|
|
|
|
btnNext: 'a.btn-next',
|
|
|
|
|
pagerLinks: '.slider-pagination li',
|
|
|
|
|
stretchSlideToMask: true,
|
|
|
|
|
maskAutoSize: true,
|
|
|
|
|
autoRotation: true,
|
|
|
|
|
switchTime: 3000,
|
|
|
|
|
animSpeed: 500,
|
|
|
|
|
step: 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fade galleries init
|
|
|
|
|
function initSlideShow() {
|
|
|
|
|
jQuery('.slideshow').fadeGallery({
|
|
|
|
|
slides: '.slide',
|
|
|
|
|
btnPrev: 'a.btn-prev',
|
|
|
|
|
btnNext: 'a.btn-next',
|
|
|
|
|
pagerLinks: '.slideshow-pagination li',
|
|
|
|
|
event: 'click',
|
|
|
|
|
useSwipe: true,
|
|
|
|
|
autoRotation: true,
|
|
|
|
|
autoHeight: true,
|
|
|
|
|
switchTime: 6000,
|
|
|
|
|
animSpeed: 5000
|
|
|
|
|
});
|
|
|
|
|
jQuery('.visual').fadeGallery({
|
|
|
|
|
slides: '.slide',
|
|
|
|
|
btnPrev: 'a.btn-prev',
|
|
|
|
|
btnNext: 'a.btn-next',
|
|
|
|
|
pagerLinks: '.visual-pagination li',
|
|
|
|
|
event: 'click',
|
|
|
|
|
useSwipe: true,
|
|
|
|
|
autoRotation: true,
|
|
|
|
|
autoHeight: true,
|
|
|
|
|
switchTime: 3000,
|
|
|
|
|
animSpeed: 500
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// star rating init
|
|
|
|
|
function initRating() {
|
|
|
|
|
lib.each(lib.queryElementsBySelector('ul.star-rating'), function(){
|
|
|
|
|
new StarRating({
|
|
|
|
|
element:this,
|
|
|
|
|
onselect:function(num) {
|
|
|
|
|
// rating setted event
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* jQuery Carousel plugin
|
|
|
|
|
*/
|
|
|
|
|
;(function($){
|
|
|
|
|
function ScrollGallery(options) {
|
|
|
|
|
this.options = $.extend({
|
|
|
|
|
mask: 'div.mask',
|
|
|
|
|
slider: '>*',
|
|
|
|
|
slides: '>*',
|
|
|
|
|
activeClass:'active',
|
|
|
|
|
disabledClass:'disabled',
|
|
|
|
|
btnPrev: 'a.btn-prev',
|
|
|
|
|
btnNext: 'a.btn-next',
|
|
|
|
|
generatePagination: false,
|
|
|
|
|
pagerList: '<ul>',
|
|
|
|
|
pagerListItem: '<li><a href="#"></a></li>',
|
|
|
|
|
pagerListItemText: 'a',
|
|
|
|
|
pagerLinks: '.pagination li',
|
|
|
|
|
currentNumber: 'span.current-num',
|
|
|
|
|
totalNumber: 'span.total-num',
|
|
|
|
|
btnPlay: '.btn-play',
|
|
|
|
|
btnPause: '.btn-pause',
|
|
|
|
|
btnPlayPause: '.btn-play-pause',
|
|
|
|
|
galleryReadyClass: 'gallery-js-ready',
|
|
|
|
|
autorotationActiveClass: 'autorotation-active',
|
|
|
|
|
autorotationDisabledClass: 'autorotation-disabled',
|
|
|
|
|
stretchSlideToMask: false,
|
|
|
|
|
circularRotation: true,
|
|
|
|
|
disableWhileAnimating: false,
|
|
|
|
|
autoRotation: false,
|
|
|
|
|
pauseOnHover: isTouchDevice ? false : true,
|
|
|
|
|
maskAutoSize: false,
|
|
|
|
|
switchTime: 4000,
|
|
|
|
|
animSpeed: 600,
|
|
|
|
|
event:'click',
|
|
|
|
|
swipeThreshold: 15,
|
|
|
|
|
handleTouch: true,
|
|
|
|
|
vertical: false,
|
|
|
|
|
useTranslate3D: false,
|
|
|
|
|
step: false
|
|
|
|
|
}, options);
|
|
|
|
|
this.init();
|
|
|
|
|
}
|
|
|
|
|
ScrollGallery.prototype = {
|
|
|
|
|
init: function() {
|
|
|
|
|
if(this.options.holder) {
|
|
|
|
|
this.findElements();
|
|
|
|
|
this.attachEvents();
|
|
|
|
|
this.refreshPosition();
|
|
|
|
|
this.refreshState(true);
|
|
|
|
|
this.resumeRotation();
|
|
|
|
|
this.makeCallback('onInit', this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
findElements: function() {
|
|
|
|
|
// define dimensions proporties
|
|
|
|
|
this.fullSizeFunction = this.options.vertical ? 'outerHeight' : 'outerWidth';
|
|
|
|
|
this.innerSizeFunction = this.options.vertical ? 'height' : 'width';
|
|
|
|
|
this.slideSizeFunction = 'outerHeight';
|
|
|
|
|
this.maskSizeProperty = 'height';
|
|
|
|
|
this.animProperty = this.options.vertical ? 'marginTop' : 'marginLeft';
|
|
|
|
|
|
|
|
|
|
// control elements
|
|
|
|
|
this.gallery = $(this.options.holder).addClass(this.options.galleryReadyClass);
|
|
|
|
|
this.mask = this.gallery.find(this.options.mask);
|
|
|
|
|
this.slider = this.mask.find(this.options.slider);
|
|
|
|
|
this.slides = this.slider.find(this.options.slides);
|
|
|
|
|
this.btnPrev = this.gallery.find(this.options.btnPrev);
|
|
|
|
|
this.btnNext = this.gallery.find(this.options.btnNext);
|
|
|
|
|
this.currentStep = 0; this.stepsCount = 0;
|
|
|
|
|
|
|
|
|
|
// get start index
|
|
|
|
|
if(this.options.step === false) {
|
|
|
|
|
var activeSlide = this.slides.filter('.'+this.options.activeClass);
|
|
|
|
|
if(activeSlide.length) {
|
|
|
|
|
this.currentStep = this.slides.index(activeSlide);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate offsets
|
|
|
|
|
this.calculateOffsets();
|
|
|
|
|
|
|
|
|
|
// create gallery pagination
|
|
|
|
|
if(typeof this.options.generatePagination === 'string') {
|
|
|
|
|
this.pagerLinks = $();
|
|
|
|
|
this.buildPagination();
|
|
|
|
|
} else {
|
|
|
|
|
this.pagerLinks = this.gallery.find(this.options.pagerLinks);
|
|
|
|
|
this.attachPaginationEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// autorotation control buttons
|
|
|
|
|
this.btnPlay = this.gallery.find(this.options.btnPlay);
|
|
|
|
|
this.btnPause = this.gallery.find(this.options.btnPause);
|
|
|
|
|
this.btnPlayPause = this.gallery.find(this.options.btnPlayPause);
|
|
|
|
|
|
|
|
|
|
// misc elements
|
|
|
|
|
this.curNum = this.gallery.find(this.options.currentNumber);
|
|
|
|
|
this.allNum = this.gallery.find(this.options.totalNumber);
|
|
|
|
|
},
|
|
|
|
|
attachEvents: function() {
|
|
|
|
|
// bind handlers scope
|
|
|
|
|
var self = this;
|
|
|
|
|
this.bindHandlers(['onWindowResize']);
|
|
|
|
|
$(window).bind('load resize orientationchange', this.onWindowResize);
|
|
|
|
|
|
|
|
|
|
// previous and next button handlers
|
|
|
|
|
if(this.btnPrev.length) {
|
|
|
|
|
this.prevSlideHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.prevSlide();
|
|
|
|
|
};
|
|
|
|
|
this.btnPrev.bind(this.options.event, this.prevSlideHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnNext.length) {
|
|
|
|
|
this.nextSlideHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.nextSlide();
|
|
|
|
|
};
|
|
|
|
|
this.btnNext.bind(this.options.event, this.nextSlideHandler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pause on hover handling
|
|
|
|
|
if(this.options.pauseOnHover && !isTouchDevice) {
|
|
|
|
|
this.hoverHandler = function() {
|
|
|
|
|
if(self.options.autoRotation) {
|
|
|
|
|
self.galleryHover = true;
|
|
|
|
|
self.pauseRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.leaveHandler = function() {
|
|
|
|
|
if(self.options.autoRotation) {
|
|
|
|
|
self.galleryHover = false;
|
|
|
|
|
self.resumeRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.gallery.bind({mouseenter: this.hoverHandler, mouseleave: this.leaveHandler});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// autorotation buttons handler
|
|
|
|
|
if(this.btnPlay.length) {
|
|
|
|
|
this.btnPlayHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.startRotation();
|
|
|
|
|
};
|
|
|
|
|
this.btnPlay.bind(this.options.event, this.btnPlayHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnPause.length) {
|
|
|
|
|
this.btnPauseHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
};
|
|
|
|
|
this.btnPause.bind(this.options.event, this.btnPauseHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnPlayPause.length) {
|
|
|
|
|
this.btnPlayPauseHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
if(!self.gallery.hasClass(self.options.autorotationActiveClass)) {
|
|
|
|
|
self.startRotation();
|
|
|
|
|
} else {
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.btnPlayPause.bind(this.options.event, this.btnPlayPauseHandler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// enable hardware acceleration
|
|
|
|
|
if(isTouchDevice && this.options.useTranslate3D) {
|
|
|
|
|
this.slider.css({'-webkit-transform': 'translate3d(0px, 0px, 0px)'});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// swipe event handling
|
|
|
|
|
if(isTouchDevice && this.options.handleTouch && window.Hammer && this.mask.length) {
|
|
|
|
|
this.swipeHandler = new Hammer.Manager(this.mask[0]);
|
|
|
|
|
this.swipeHandler.add(new Hammer.Pan({
|
|
|
|
|
direction: self.options.vertical ? Hammer.DIRECTION_VERTICAL : Hammer.DIRECTION_HORIZONTAL,
|
|
|
|
|
threshold: self.options.swipeThreshold
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
this.swipeHandler.on('panstart', function() {
|
|
|
|
|
if(self.galleryAnimating) {
|
|
|
|
|
self.swipeHandler.stop();
|
|
|
|
|
} else {
|
|
|
|
|
self.pauseRotation();
|
|
|
|
|
self.originalOffset = parseFloat(self.slider.css(self.animProperty));
|
|
|
|
|
}
|
|
|
|
|
}).on('panmove', function(e) {
|
|
|
|
|
var tmpOffset = self.originalOffset + e[self.options.vertical ? 'deltaY' : 'deltaX'];
|
|
|
|
|
tmpOffset = Math.max(Math.min(0, tmpOffset), self.maxOffset);
|
|
|
|
|
self.slider.css(self.animProperty, tmpOffset);
|
|
|
|
|
}).on('panend', function(e) {
|
|
|
|
|
self.resumeRotation();
|
|
|
|
|
if(e.distance > self.options.swipeThreshold) {
|
|
|
|
|
if(e.offsetDirection === Hammer.DIRECTION_RIGHT || e.offsetDirection === Hammer.DIRECTION_DOWN) {
|
|
|
|
|
self.nextSlide();
|
|
|
|
|
} else {
|
|
|
|
|
self.prevSlide();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
self.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onWindowResize: function() {
|
|
|
|
|
if(!this.galleryAnimating) {
|
|
|
|
|
this.calculateOffsets();
|
|
|
|
|
this.refreshPosition();
|
|
|
|
|
this.buildPagination();
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.resizeQueue = false;
|
|
|
|
|
} else {
|
|
|
|
|
this.resizeQueue = true;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshPosition: function() {
|
|
|
|
|
this.currentStep = Math.min(this.currentStep, this.stepsCount - 1);
|
|
|
|
|
this.tmpProps = {};
|
|
|
|
|
this.tmpProps[this.animProperty] = this.getStepOffset();
|
|
|
|
|
this.slider.stop().css(this.tmpProps);
|
|
|
|
|
},
|
|
|
|
|
calculateOffsets: function() {
|
|
|
|
|
var self = this, tmpOffset, tmpStep;
|
|
|
|
|
if(this.options.stretchSlideToMask) {
|
|
|
|
|
var tmpObj = {};
|
|
|
|
|
tmpObj[this.innerSizeFunction] = this.mask[this.innerSizeFunction]();
|
|
|
|
|
this.slides.css(tmpObj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.maskSize = this.mask[this.innerSizeFunction]();
|
|
|
|
|
this.sumSize = this.getSumSize();
|
|
|
|
|
this.maxOffset = this.maskSize - this.sumSize;
|
|
|
|
|
|
|
|
|
|
// vertical gallery with single size step custom behavior
|
|
|
|
|
if(this.options.vertical && this.options.maskAutoSize) {
|
|
|
|
|
this.options.step = 1;
|
|
|
|
|
this.stepsCount = this.slides.length;
|
|
|
|
|
this.stepOffsets = [0];
|
|
|
|
|
tmpOffset = 0;
|
|
|
|
|
for(var i = 0; i < this.slides.length; i++) {
|
|
|
|
|
tmpOffset -= $(this.slides[i])[this.fullSizeFunction](true);
|
|
|
|
|
this.stepOffsets.push(tmpOffset);
|
|
|
|
|
}
|
|
|
|
|
this.maxOffset = tmpOffset;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// scroll by slide size
|
|
|
|
|
if(typeof this.options.step === 'number' && this.options.step > 0) {
|
|
|
|
|
this.slideDimensions = [];
|
|
|
|
|
this.slides.each($.proxy(function(ind, obj){
|
|
|
|
|
self.slideDimensions.push( $(obj)[self.fullSizeFunction](true) );
|
|
|
|
|
},this));
|
|
|
|
|
|
|
|
|
|
// calculate steps count
|
|
|
|
|
this.stepOffsets = [0];
|
|
|
|
|
this.stepsCount = 1;
|
|
|
|
|
tmpOffset = tmpStep = 0;
|
|
|
|
|
while(tmpOffset > this.maxOffset) {
|
|
|
|
|
tmpOffset -= this.getSlideSize(tmpStep, tmpStep + this.options.step);
|
|
|
|
|
tmpStep += this.options.step;
|
|
|
|
|
this.stepOffsets.push(Math.max(tmpOffset, this.maxOffset));
|
|
|
|
|
this.stepsCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// scroll by mask size
|
|
|
|
|
else {
|
|
|
|
|
// define step size
|
|
|
|
|
this.stepSize = this.maskSize;
|
|
|
|
|
|
|
|
|
|
// calculate steps count
|
|
|
|
|
this.stepsCount = 1;
|
|
|
|
|
tmpOffset = 0;
|
|
|
|
|
while(tmpOffset > this.maxOffset) {
|
|
|
|
|
tmpOffset -= this.stepSize;
|
|
|
|
|
this.stepsCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getSumSize: function() {
|
|
|
|
|
var sum = 0;
|
|
|
|
|
this.slides.each($.proxy(function(ind, obj){
|
|
|
|
|
sum += $(obj)[this.fullSizeFunction](true);
|
|
|
|
|
},this));
|
|
|
|
|
this.slider.css(this.innerSizeFunction, sum);
|
|
|
|
|
return sum;
|
|
|
|
|
},
|
|
|
|
|
getStepOffset: function(step) {
|
|
|
|
|
step = step || this.currentStep;
|
|
|
|
|
if(typeof this.options.step === 'number') {
|
|
|
|
|
return this.stepOffsets[this.currentStep];
|
|
|
|
|
} else {
|
|
|
|
|
return Math.min(0, Math.max(-this.currentStep * this.stepSize, this.maxOffset));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getSlideSize: function(i1, i2) {
|
|
|
|
|
var sum = 0;
|
|
|
|
|
for(var i = i1; i < Math.min(i2, this.slideDimensions.length); i++) {
|
|
|
|
|
sum += this.slideDimensions[i];
|
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
},
|
|
|
|
|
buildPagination: function() {
|
|
|
|
|
if(typeof this.options.generatePagination === 'string') {
|
|
|
|
|
if(!this.pagerHolder) {
|
|
|
|
|
this.pagerHolder = this.gallery.find(this.options.generatePagination);
|
|
|
|
|
}
|
|
|
|
|
if(this.pagerHolder.length && this.oldStepsCount != this.stepsCount) {
|
|
|
|
|
this.oldStepsCount = this.stepsCount;
|
|
|
|
|
this.pagerHolder.empty();
|
|
|
|
|
this.pagerList = $(this.options.pagerList).appendTo(this.pagerHolder);
|
|
|
|
|
for(var i = 0; i < this.stepsCount; i++) {
|
|
|
|
|
$(this.options.pagerListItem).appendTo(this.pagerList).find(this.options.pagerListItemText).text(i+1);
|
|
|
|
|
}
|
|
|
|
|
this.pagerLinks = this.pagerList.children();
|
|
|
|
|
this.attachPaginationEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
attachPaginationEvents: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
this.pagerLinksHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.numSlide(self.pagerLinks.index(e.currentTarget));
|
|
|
|
|
};
|
|
|
|
|
this.pagerLinks.bind(this.options.event, this.pagerLinksHandler);
|
|
|
|
|
},
|
|
|
|
|
prevSlide: function() {
|
|
|
|
|
if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
|
|
|
|
|
if(this.currentStep > 0) {
|
|
|
|
|
this.currentStep--;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
} else if(this.options.circularRotation) {
|
|
|
|
|
this.currentStep = this.stepsCount - 1;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
nextSlide: function(fromAutoRotation) {
|
|
|
|
|
if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
|
|
|
|
|
if(this.currentStep < this.stepsCount - 1) {
|
|
|
|
|
this.currentStep++;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
} else if(this.options.circularRotation || fromAutoRotation === true) {
|
|
|
|
|
this.currentStep = 0;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
numSlide: function(c) {
|
|
|
|
|
if(this.currentStep != c) {
|
|
|
|
|
this.currentStep = c;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
switchSlide: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
this.galleryAnimating = true;
|
|
|
|
|
this.tmpProps = {};
|
|
|
|
|
this.tmpProps[this.animProperty] = this.getStepOffset();
|
|
|
|
|
this.slider.stop().animate(this.tmpProps, {duration: this.options.animSpeed, complete: function(){
|
|
|
|
|
// animation complete
|
|
|
|
|
self.galleryAnimating = false;
|
|
|
|
|
if(self.resizeQueue) {
|
|
|
|
|
self.onWindowResize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// onchange callback
|
|
|
|
|
self.makeCallback('onChange', self);
|
|
|
|
|
self.autoRotate();
|
|
|
|
|
}});
|
|
|
|
|
this.refreshState();
|
|
|
|
|
|
|
|
|
|
// onchange callback
|
|
|
|
|
this.makeCallback('onBeforeChange', this);
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(initial) {
|
|
|
|
|
if(this.options.step === 1 || this.stepsCount === this.slides.length) {
|
|
|
|
|
this.slides.removeClass(this.options.activeClass).eq(this.currentStep).addClass(this.options.activeClass);
|
|
|
|
|
}
|
|
|
|
|
this.pagerLinks.removeClass(this.options.activeClass).eq(this.currentStep).addClass(this.options.activeClass);
|
|
|
|
|
this.curNum.html(this.currentStep+1);
|
|
|
|
|
this.allNum.html(this.stepsCount);
|
|
|
|
|
|
|
|
|
|
// initial refresh
|
|
|
|
|
if(this.options.maskAutoSize && typeof this.options.step === 'number') {
|
|
|
|
|
this.tmpProps = {};
|
|
|
|
|
this.tmpProps[this.maskSizeProperty] = this.slides.eq(Math.min(this.currentStep,this.slides.length-1))[this.slideSizeFunction](true);
|
|
|
|
|
this.mask.stop()[initial ? 'css' : 'animate'](this.tmpProps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// disabled state
|
|
|
|
|
if(!this.options.circularRotation) {
|
|
|
|
|
this.btnPrev.add(this.btnNext).removeClass(this.options.disabledClass);
|
|
|
|
|
if(this.currentStep === 0) this.btnPrev.addClass(this.options.disabledClass);
|
|
|
|
|
if(this.currentStep === this.stepsCount - 1) this.btnNext.addClass(this.options.disabledClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add class if not enough slides
|
|
|
|
|
this.gallery.toggleClass('not-enough-slides', this.sumSize <= this.maskSize);
|
|
|
|
|
},
|
|
|
|
|
startRotation: function() {
|
|
|
|
|
this.options.autoRotation = true;
|
|
|
|
|
this.galleryHover = false;
|
|
|
|
|
this.autoRotationStopped = false;
|
|
|
|
|
this.resumeRotation();
|
|
|
|
|
},
|
|
|
|
|
stopRotation: function() {
|
|
|
|
|
this.galleryHover = true;
|
|
|
|
|
this.autoRotationStopped = true;
|
|
|
|
|
this.pauseRotation();
|
|
|
|
|
},
|
|
|
|
|
pauseRotation: function() {
|
|
|
|
|
this.gallery.addClass(this.options.autorotationDisabledClass);
|
|
|
|
|
this.gallery.removeClass(this.options.autorotationActiveClass);
|
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
|
},
|
|
|
|
|
resumeRotation: function() {
|
|
|
|
|
if(!this.autoRotationStopped) {
|
|
|
|
|
this.gallery.addClass(this.options.autorotationActiveClass);
|
|
|
|
|
this.gallery.removeClass(this.options.autorotationDisabledClass);
|
|
|
|
|
this.autoRotate();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
autoRotate: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
|
if(this.options.autoRotation && !this.galleryHover && !this.autoRotationStopped) {
|
|
|
|
|
this.timer = setTimeout(function(){
|
|
|
|
|
self.nextSlide(true);
|
|
|
|
|
}, this.options.switchTime);
|
|
|
|
|
} else {
|
|
|
|
|
this.pauseRotation();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
bindHandlers: function(handlersList) {
|
|
|
|
|
var self = this;
|
|
|
|
|
$.each(handlersList, function(index, handler) {
|
|
|
|
|
var origHandler = self[handler];
|
|
|
|
|
self[handler] = function() {
|
|
|
|
|
return origHandler.apply(self, arguments);
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
makeCallback: function(name) {
|
|
|
|
|
if(typeof this.options[name] === 'function') {
|
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
|
args.shift();
|
|
|
|
|
this.options[name].apply(this, args);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
destroy: function() {
|
|
|
|
|
// destroy handler
|
|
|
|
|
$(window).unbind('load resize orientationchange', this.onWindowResize);
|
|
|
|
|
this.btnPrev.unbind(this.options.event, this.prevSlideHandler);
|
|
|
|
|
this.btnNext.unbind(this.options.event, this.nextSlideHandler);
|
|
|
|
|
this.pagerLinks.unbind(this.options.event, this.pagerLinksHandler);
|
|
|
|
|
this.gallery.unbind('mouseenter', this.hoverHandler);
|
|
|
|
|
this.gallery.unbind('mouseleave', this.leaveHandler);
|
|
|
|
|
|
|
|
|
|
// autorotation buttons handlers
|
|
|
|
|
this.stopRotation();
|
|
|
|
|
this.btnPlay.unbind(this.options.event, this.btnPlayHandler);
|
|
|
|
|
this.btnPause.unbind(this.options.event, this.btnPauseHandler);
|
|
|
|
|
this.btnPlayPause.unbind(this.options.event, this.btnPlayPauseHandler);
|
|
|
|
|
|
|
|
|
|
// destroy swipe handler
|
|
|
|
|
if(this.swipeHandler) {
|
|
|
|
|
this.swipeHandler.destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove inline styles, classes and pagination
|
|
|
|
|
var unneededClasses = [this.options.galleryReadyClass, this.options.autorotationActiveClass, this.options.autorotationDisabledClass];
|
|
|
|
|
this.gallery.removeClass(unneededClasses.join(' '));
|
|
|
|
|
this.slider.add(this.slides).removeAttr('style');
|
|
|
|
|
if(typeof this.options.generatePagination === 'string') {
|
|
|
|
|
this.pagerHolder.empty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// detect device type
|
|
|
|
|
var isTouchDevice = /Windows Phone/.test(navigator.userAgent) || ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
|
|
|
|
|
|
|
|
|
|
// jquery plugin
|
|
|
|
|
$.fn.scrollGallery = function(opt){
|
|
|
|
|
return this.each(function(){
|
|
|
|
|
$(this).data('ScrollGallery', new ScrollGallery($.extend(opt,{holder:this})));
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}(jQuery));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* jQuery SlideShow plugin
|
|
|
|
|
*/
|
|
|
|
|
;(function($){
|
|
|
|
|
function FadeGallery(options) {
|
|
|
|
|
this.options = $.extend({
|
|
|
|
|
slides: 'ul.slideset > li',
|
|
|
|
|
activeClass:'active',
|
|
|
|
|
disabledClass:'disabled',
|
|
|
|
|
btnPrev: 'a.btn-prev',
|
|
|
|
|
btnNext: 'a.btn-next',
|
|
|
|
|
generatePagination: false,
|
|
|
|
|
pagerList: '<ul>',
|
|
|
|
|
pagerListItem: '<li><a href="#"></a></li>',
|
|
|
|
|
pagerListItemText: 'a',
|
|
|
|
|
pagerLinks: '.pagination li',
|
|
|
|
|
currentNumber: 'span.current-num',
|
|
|
|
|
totalNumber: 'span.total-num',
|
|
|
|
|
btnPlay: '.btn-play',
|
|
|
|
|
btnPause: '.btn-pause',
|
|
|
|
|
btnPlayPause: '.btn-play-pause',
|
|
|
|
|
galleryReadyClass: 'gallery-js-ready',
|
|
|
|
|
autorotationActiveClass: 'autorotation-active',
|
|
|
|
|
autorotationDisabledClass: 'autorotation-disabled',
|
|
|
|
|
autorotationStopAfterClick: false,
|
|
|
|
|
circularRotation: true,
|
|
|
|
|
switchSimultaneously: true,
|
|
|
|
|
disableWhileAnimating: false,
|
|
|
|
|
disableFadeIE: false,
|
|
|
|
|
autoRotation: false,
|
|
|
|
|
pauseOnHover: true,
|
|
|
|
|
autoHeight: false,
|
|
|
|
|
useSwipe: false,
|
|
|
|
|
swipeThreshold: 15,
|
|
|
|
|
switchTime: 4000,
|
|
|
|
|
animSpeed: 600,
|
|
|
|
|
event:'click'
|
|
|
|
|
}, options);
|
|
|
|
|
this.init();
|
|
|
|
|
}
|
|
|
|
|
FadeGallery.prototype = {
|
|
|
|
|
init: function() {
|
|
|
|
|
if(this.options.holder) {
|
|
|
|
|
this.findElements();
|
|
|
|
|
this.attachEvents();
|
|
|
|
|
this.refreshState(true);
|
|
|
|
|
this.autoRotate();
|
|
|
|
|
this.makeCallback('onInit', this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
findElements: function() {
|
|
|
|
|
// control elements
|
|
|
|
|
this.gallery = $(this.options.holder).addClass(this.options.galleryReadyClass);
|
|
|
|
|
this.slides = this.gallery.find(this.options.slides);
|
|
|
|
|
this.slidesHolder = this.slides.eq(0).parent();
|
|
|
|
|
this.stepsCount = this.slides.length;
|
|
|
|
|
this.btnPrev = this.gallery.find(this.options.btnPrev);
|
|
|
|
|
this.btnNext = this.gallery.find(this.options.btnNext);
|
|
|
|
|
this.currentIndex = 0;
|
|
|
|
|
|
|
|
|
|
// disable fade effect in old IE
|
|
|
|
|
if(this.options.disableFadeIE && !$.support.opacity) {
|
|
|
|
|
this.options.animSpeed = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create gallery pagination
|
|
|
|
|
if(typeof this.options.generatePagination === 'string') {
|
|
|
|
|
this.pagerHolder = this.gallery.find(this.options.generatePagination).empty();
|
|
|
|
|
this.pagerList = $(this.options.pagerList).appendTo(this.pagerHolder);
|
|
|
|
|
for(var i = 0; i < this.stepsCount; i++) {
|
|
|
|
|
$(this.options.pagerListItem).appendTo(this.pagerList).find(this.options.pagerListItemText).text(i+1);
|
|
|
|
|
}
|
|
|
|
|
this.pagerLinks = this.pagerList.children();
|
|
|
|
|
} else {
|
|
|
|
|
this.pagerLinks = this.gallery.find(this.options.pagerLinks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get start index
|
|
|
|
|
var activeSlide = this.slides.filter('.'+this.options.activeClass);
|
|
|
|
|
if(activeSlide.length) {
|
|
|
|
|
this.currentIndex = this.slides.index(activeSlide);
|
|
|
|
|
}
|
|
|
|
|
this.prevIndex = this.currentIndex;
|
|
|
|
|
|
|
|
|
|
// autorotation control buttons
|
|
|
|
|
this.btnPlay = this.gallery.find(this.options.btnPlay);
|
|
|
|
|
this.btnPause = this.gallery.find(this.options.btnPause);
|
|
|
|
|
this.btnPlayPause = this.gallery.find(this.options.btnPlayPause);
|
|
|
|
|
|
|
|
|
|
// misc elements
|
|
|
|
|
this.curNum = this.gallery.find(this.options.currentNumber);
|
|
|
|
|
this.allNum = this.gallery.find(this.options.totalNumber);
|
|
|
|
|
|
|
|
|
|
// handle flexible layout
|
|
|
|
|
this.slides.css({display:'block',opacity:0}).eq(this.currentIndex).css({
|
|
|
|
|
opacity:''
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
attachEvents: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
// flexible layout handler
|
|
|
|
|
this.resizeHandler = function() {
|
|
|
|
|
self.onWindowResize();
|
|
|
|
|
};
|
|
|
|
|
$(window).bind('load resize orientationchange', this.resizeHandler);
|
|
|
|
|
|
|
|
|
|
if(this.btnPrev.length) {
|
|
|
|
|
this.btnPrevHandler = function(e){
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.prevSlide();
|
|
|
|
|
if(self.options.autorotationStopAfterClick) {
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.btnPrev.bind(this.options.event, this.btnPrevHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnNext.length) {
|
|
|
|
|
this.btnNextHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.nextSlide();
|
|
|
|
|
if(self.options.autorotationStopAfterClick) {
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.btnNext.bind(this.options.event, this.btnNextHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.pagerLinks.length) {
|
|
|
|
|
this.pagerLinksHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.numSlide(self.pagerLinks.index(e.currentTarget));
|
|
|
|
|
if(self.options.autorotationStopAfterClick) {
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.pagerLinks.bind(self.options.event, this.pagerLinksHandler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// autorotation buttons handler
|
|
|
|
|
if(this.btnPlay.length) {
|
|
|
|
|
this.btnPlayHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.startRotation();
|
|
|
|
|
};
|
|
|
|
|
this.btnPlay.bind(this.options.event, this.btnPlayHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnPause.length) {
|
|
|
|
|
this.btnPauseHandler = function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
};
|
|
|
|
|
this.btnPause.bind(this.options.event, this.btnPauseHandler);
|
|
|
|
|
}
|
|
|
|
|
if(this.btnPlayPause.length) {
|
|
|
|
|
this.btnPlayPauseHandler = function(e){
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
if(!self.gallery.hasClass(self.options.autorotationActiveClass)) {
|
|
|
|
|
self.startRotation();
|
|
|
|
|
} else {
|
|
|
|
|
self.stopRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.btnPlayPause.bind(this.options.event, this.btnPlayPauseHandler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// swipe gestures handler
|
|
|
|
|
if(this.options.useSwipe && window.Hammer && isTouchDevice) {
|
|
|
|
|
this.swipeHandler = new Hammer.Manager(this.gallery[0]);
|
|
|
|
|
this.swipeHandler.add(new Hammer.Swipe({
|
|
|
|
|
direction: Hammer.DIRECTION_HORIZONTAL,
|
|
|
|
|
threshold: self.options.swipeThreshold
|
|
|
|
|
}));
|
|
|
|
|
this.swipeHandler.on('swipeleft', function() {
|
|
|
|
|
self.nextSlide();
|
|
|
|
|
}).on('swiperight', function() {
|
|
|
|
|
self.prevSlide();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pause on hover handling
|
|
|
|
|
if(this.options.pauseOnHover) {
|
|
|
|
|
this.hoverHandler = function() {
|
|
|
|
|
if(self.options.autoRotation) {
|
|
|
|
|
self.galleryHover = true;
|
|
|
|
|
self.pauseRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.leaveHandler = function() {
|
|
|
|
|
if(self.options.autoRotation) {
|
|
|
|
|
self.galleryHover = false;
|
|
|
|
|
self.resumeRotation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.gallery.bind({mouseenter: this.hoverHandler, mouseleave: this.leaveHandler});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onWindowResize: function(){
|
|
|
|
|
if(this.options.autoHeight) {
|
|
|
|
|
this.slidesHolder.css({height: this.slides.eq(this.currentIndex).outerHeight(true) });
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
prevSlide: function() {
|
|
|
|
|
if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
|
|
|
|
|
this.prevIndex = this.currentIndex;
|
|
|
|
|
if(this.currentIndex > 0) {
|
|
|
|
|
this.currentIndex--;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
} else if(this.options.circularRotation) {
|
|
|
|
|
this.currentIndex = this.stepsCount - 1;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
nextSlide: function(fromAutoRotation) {
|
|
|
|
|
if(!(this.options.disableWhileAnimating && this.galleryAnimating)) {
|
|
|
|
|
this.prevIndex = this.currentIndex;
|
|
|
|
|
if(this.currentIndex < this.stepsCount - 1) {
|
|
|
|
|
this.currentIndex++;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
} else if(this.options.circularRotation || fromAutoRotation === true) {
|
|
|
|
|
this.currentIndex = 0;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
numSlide: function(c) {
|
|
|
|
|
if(this.currentIndex != c) {
|
|
|
|
|
this.prevIndex = this.currentIndex;
|
|
|
|
|
this.currentIndex = c;
|
|
|
|
|
this.switchSlide();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
switchSlide: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
if(this.slides.length > 1) {
|
|
|
|
|
this.galleryAnimating = true;
|
|
|
|
|
if(!this.options.animSpeed) {
|
|
|
|
|
this.slides.eq(this.prevIndex).css({opacity:0});
|
|
|
|
|
} else {
|
|
|
|
|
this.slides.eq(this.prevIndex).stop().animate({opacity:0},{duration: this.options.animSpeed});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.switchNext = function() {
|
|
|
|
|
if(!self.options.animSpeed) {
|
|
|
|
|
self.slides.eq(self.currentIndex).css({opacity:''});
|
|
|
|
|
} else {
|
|
|
|
|
self.slides.eq(self.currentIndex).stop().animate({opacity:1},{duration: self.options.animSpeed});
|
|
|
|
|
}
|
|
|
|
|
clearTimeout(this.nextTimer);
|
|
|
|
|
this.nextTimer = setTimeout(function() {
|
|
|
|
|
self.slides.eq(self.currentIndex).css({opacity:''});
|
|
|
|
|
self.galleryAnimating = false;
|
|
|
|
|
self.autoRotate();
|
|
|
|
|
|
|
|
|
|
// onchange callback
|
|
|
|
|
self.makeCallback('onChange', self);
|
|
|
|
|
}, self.options.animSpeed);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(this.options.switchSimultaneously) {
|
|
|
|
|
self.switchNext();
|
|
|
|
|
} else {
|
|
|
|
|
clearTimeout(this.switchTimer);
|
|
|
|
|
this.switchTimer = setTimeout(function(){
|
|
|
|
|
self.switchNext();
|
|
|
|
|
}, this.options.animSpeed);
|
|
|
|
|
}
|
|
|
|
|
this.refreshState();
|
|
|
|
|
|
|
|
|
|
// onchange callback
|
|
|
|
|
this.makeCallback('onBeforeChange', this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(initial) {
|
|
|
|
|
this.slides.removeClass(this.options.activeClass).eq(this.currentIndex).addClass(this.options.activeClass);
|
|
|
|
|
this.pagerLinks.removeClass(this.options.activeClass).eq(this.currentIndex).addClass(this.options.activeClass);
|
|
|
|
|
this.curNum.html(this.currentIndex+1);
|
|
|
|
|
this.allNum.html(this.stepsCount);
|
|
|
|
|
|
|
|
|
|
// initial refresh
|
|
|
|
|
if(this.options.autoHeight) {
|
|
|
|
|
if(initial) {
|
|
|
|
|
this.slidesHolder.css({height: this.slides.eq(this.currentIndex).outerHeight(true) });
|
|
|
|
|
} else {
|
|
|
|
|
this.slidesHolder.stop().animate({height: this.slides.eq(this.currentIndex).outerHeight(true)}, {duration: this.options.animSpeed});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// disabled state
|
|
|
|
|
if(!this.options.circularRotation) {
|
|
|
|
|
this.btnPrev.add(this.btnNext).removeClass(this.options.disabledClass);
|
|
|
|
|
if(this.currentIndex === 0) this.btnPrev.addClass(this.options.disabledClass);
|
|
|
|
|
if(this.currentIndex === this.stepsCount - 1) this.btnNext.addClass(this.options.disabledClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add class if not enough slides
|
|
|
|
|
this.gallery.toggleClass('not-enough-slides', this.stepsCount === 1);
|
|
|
|
|
},
|
|
|
|
|
startRotation: function() {
|
|
|
|
|
this.options.autoRotation = true;
|
|
|
|
|
this.galleryHover = false;
|
|
|
|
|
this.autoRotationStopped = false;
|
|
|
|
|
this.resumeRotation();
|
|
|
|
|
},
|
|
|
|
|
stopRotation: function() {
|
|
|
|
|
this.galleryHover = true;
|
|
|
|
|
this.autoRotationStopped = true;
|
|
|
|
|
this.pauseRotation();
|
|
|
|
|
},
|
|
|
|
|
pauseRotation: function() {
|
|
|
|
|
this.gallery.addClass(this.options.autorotationDisabledClass);
|
|
|
|
|
this.gallery.removeClass(this.options.autorotationActiveClass);
|
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
|
},
|
|
|
|
|
resumeRotation: function() {
|
|
|
|
|
if(!this.autoRotationStopped) {
|
|
|
|
|
this.gallery.addClass(this.options.autorotationActiveClass);
|
|
|
|
|
this.gallery.removeClass(this.options.autorotationDisabledClass);
|
|
|
|
|
this.autoRotate();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
autoRotate: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
|
if(this.options.autoRotation && !this.galleryHover && !this.autoRotationStopped) {
|
|
|
|
|
this.gallery.addClass(this.options.autorotationActiveClass);
|
|
|
|
|
this.timer = setTimeout(function(){
|
|
|
|
|
self.nextSlide(true);
|
|
|
|
|
}, this.options.switchTime);
|
|
|
|
|
} else {
|
|
|
|
|
this.pauseRotation();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
makeCallback: function(name) {
|
|
|
|
|
if(typeof this.options[name] === 'function') {
|
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
|
args.shift();
|
|
|
|
|
this.options[name].apply(this, args);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
destroy: function() {
|
|
|
|
|
// navigation buttons handler
|
|
|
|
|
this.btnPrev.unbind(this.options.event, this.btnPrevHandler);
|
|
|
|
|
this.btnNext.unbind(this.options.event, this.btnNextHandler);
|
|
|
|
|
this.pagerLinks.unbind(this.options.event, this.pagerLinksHandler);
|
|
|
|
|
$(window).unbind('load resize orientationchange', this.resizeHandler);
|
|
|
|
|
|
|
|
|
|
// remove autorotation handlers
|
|
|
|
|
this.stopRotation();
|
|
|
|
|
this.btnPlay.unbind(this.options.event, this.btnPlayHandler);
|
|
|
|
|
this.btnPause.unbind(this.options.event, this.btnPauseHandler);
|
|
|
|
|
this.btnPlayPause.unbind(this.options.event, this.btnPlayPauseHandler);
|
|
|
|
|
this.gallery.unbind('mouseenter', this.hoverHandler);
|
|
|
|
|
this.gallery.unbind('mouseleave', this.leaveHandler);
|
|
|
|
|
|
|
|
|
|
// remove swipe handler if used
|
|
|
|
|
if(this.swipeHandler) {
|
|
|
|
|
this.swipeHandler.destroy();
|
|
|
|
|
}
|
|
|
|
|
if(typeof this.options.generatePagination === 'string') {
|
|
|
|
|
this.pagerHolder.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove unneeded classes and styles
|
|
|
|
|
var unneededClasses = [this.options.galleryReadyClass, this.options.autorotationActiveClass, this.options.autorotationDisabledClass];
|
|
|
|
|
this.gallery.removeClass(unneededClasses.join(' '));
|
|
|
|
|
this.slidesHolder.add(this.slides).removeAttr('style');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// detect device type
|
|
|
|
|
var isTouchDevice = /Windows Phone/.test(navigator.userAgent) || ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
|
|
|
|
|
|
|
|
|
|
// jquery plugin
|
|
|
|
|
$.fn.fadeGallery = function(opt){
|
|
|
|
|
return this.each(function(){
|
|
|
|
|
$(this).data('FadeGallery', new FadeGallery($.extend(opt,{holder:this})));
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}(jQuery));
|
|
|
|
|
|
|
|
|
|
/*! http://mths.be/placeholder v2.0.7 by @mathias */
|
|
|
|
|
;(function(window, document, $) {
|
|
|
|
|
|
|
|
|
|
// Opera Mini v7 doesn’t support placeholder although its DOM seems to indicate so
|
|
|
|
|
var isOperaMini = Object.prototype.toString.call(window.operamini) == '[object OperaMini]';
|
|
|
|
|
var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini;
|
|
|
|
|
var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini;
|
|
|
|
|
var prototype = $.fn;
|
|
|
|
|
var valHooks = $.valHooks;
|
|
|
|
|
var propHooks = $.propHooks;
|
|
|
|
|
var hooks;
|
|
|
|
|
var placeholder;
|
|
|
|
|
|
|
|
|
|
if (isInputSupported && isTextareaSupported) {
|
|
|
|
|
|
|
|
|
|
placeholder = prototype.placeholder = function() {
|
|
|
|
|
return this;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
placeholder.input = placeholder.textarea = true;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
placeholder = prototype.placeholder = function() {
|
|
|
|
|
var $this = this;
|
|
|
|
|
$this
|
|
|
|
|
.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
|
|
|
|
|
.not('.placeholder')
|
|
|
|
|
.bind({
|
|
|
|
|
'focus.placeholder': clearPlaceholder,
|
|
|
|
|
'blur.placeholder': setPlaceholder
|
|
|
|
|
})
|
|
|
|
|
.data('placeholder-enabled', true)
|
|
|
|
|
.trigger('blur.placeholder');
|
|
|
|
|
return $this;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
placeholder.input = isInputSupported;
|
|
|
|
|
placeholder.textarea = isTextareaSupported;
|
|
|
|
|
|
|
|
|
|
hooks = {
|
|
|
|
|
'get': function(element) {
|
|
|
|
|
var $element = $(element);
|
|
|
|
|
|
|
|
|
|
var $passwordInput = $element.data('placeholder-password');
|
|
|
|
|
if ($passwordInput) {
|
|
|
|
|
return $passwordInput[0].value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
|
|
|
|
|
},
|
|
|
|
|
'set': function(element, value) {
|
|
|
|
|
var $element = $(element);
|
|
|
|
|
|
|
|
|
|
var $passwordInput = $element.data('placeholder-password');
|
|
|
|
|
if ($passwordInput) {
|
|
|
|
|
return $passwordInput[0].value = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$element.data('placeholder-enabled')) {
|
|
|
|
|
return element.value = value;
|
|
|
|
|
}
|
|
|
|
|
if (value == '') {
|
|
|
|
|
element.value = value;
|
|
|
|
|
// Issue #56: Setting the placeholder causes problems if the element continues to have focus.
|
|
|
|
|
if (element != safeActiveElement()) {
|
|
|
|
|
// We can't use `triggerHandler` here because of dummy text/password inputs :(
|
|
|
|
|
setPlaceholder.call(element);
|
|
|
|
|
}
|
|
|
|
|
} else if ($element.hasClass('placeholder')) {
|
|
|
|
|
clearPlaceholder.call(element, true, value) || (element.value = value);
|
|
|
|
|
} else {
|
|
|
|
|
element.value = value;
|
|
|
|
|
}
|
|
|
|
|
// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
|
|
|
|
|
return $element;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!isInputSupported) {
|
|
|
|
|
valHooks.input = hooks;
|
|
|
|
|
propHooks.value = hooks;
|
|
|
|
|
}
|
|
|
|
|
if (!isTextareaSupported) {
|
|
|
|
|
valHooks.textarea = hooks;
|
|
|
|
|
propHooks.value = hooks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(function() {
|
|
|
|
|
// Look for forms
|
|
|
|
|
$(document).delegate('form', 'submit.placeholder', function() {
|
|
|
|
|
// Clear the placeholder values so they don't get submitted
|
|
|
|
|
var $inputs = $('.placeholder', this).each(clearPlaceholder);
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
$inputs.each(setPlaceholder);
|
|
|
|
|
}, 10);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Clear placeholder values upon page reload
|
|
|
|
|
$(window).bind('beforeunload.placeholder', function() {
|
|
|
|
|
$('.placeholder').each(function() {
|
|
|
|
|
this.value = '';
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function args(elem) {
|
|
|
|
|
// Return an object of element attributes
|
|
|
|
|
var newAttrs = {};
|
|
|
|
|
var rinlinejQuery = /^jQuery\d+$/;
|
|
|
|
|
$.each(elem.attributes, function(i, attr) {
|
|
|
|
|
if (attr.specified && !rinlinejQuery.test(attr.name)) {
|
|
|
|
|
newAttrs[attr.name] = attr.value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return newAttrs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearPlaceholder(event, value) {
|
|
|
|
|
var input = this;
|
|
|
|
|
var $input = $(input);
|
|
|
|
|
if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
|
|
|
|
|
if ($input.data('placeholder-password')) {
|
|
|
|
|
$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
|
|
|
|
|
// If `clearPlaceholder` was called from `$.valHooks.input.set`
|
|
|
|
|
if (event === true) {
|
|
|
|
|
return $input[0].value = value;
|
|
|
|
|
}
|
|
|
|
|
$input.focus();
|
|
|
|
|
} else {
|
|
|
|
|
input.value = '';
|
|
|
|
|
$input.removeClass('placeholder');
|
|
|
|
|
input == safeActiveElement() && input.select();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setPlaceholder() {
|
|
|
|
|
var $replacement;
|
|
|
|
|
var input = this;
|
|
|
|
|
var $input = $(input);
|
|
|
|
|
var id = this.id;
|
|
|
|
|
if (input.value == '') {
|
|
|
|
|
if (input.type == 'password') {
|
|
|
|
|
if (!$input.data('placeholder-textinput')) {
|
|
|
|
|
try {
|
|
|
|
|
$replacement = $input.clone().attr({ 'type': 'text' });
|
|
|
|
|
} catch(e) {
|
|
|
|
|
$replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
|
|
|
|
|
}
|
|
|
|
|
$replacement
|
|
|
|
|
.removeAttr('name')
|
|
|
|
|
.data({
|
|
|
|
|
'placeholder-password': $input,
|
|
|
|
|
'placeholder-id': id
|
|
|
|
|
})
|
|
|
|
|
.bind('focus.placeholder', clearPlaceholder);
|
|
|
|
|
$input
|
|
|
|
|
.data({
|
|
|
|
|
'placeholder-textinput': $replacement,
|
|
|
|
|
'placeholder-id': id
|
|
|
|
|
})
|
|
|
|
|
.before($replacement);
|
|
|
|
|
}
|
|
|
|
|
$input = $input.removeAttr('id').hide().prev().attr('id', id).show();
|
|
|
|
|
// Note: `$input[0] != input` now!
|
|
|
|
|
}
|
|
|
|
|
$input.addClass('placeholder');
|
|
|
|
|
$input[0].value = $input.attr('placeholder');
|
|
|
|
|
} else {
|
|
|
|
|
$input.removeClass('placeholder');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function safeActiveElement() {
|
|
|
|
|
// Avoid IE9 `document.activeElement` of death
|
|
|
|
|
// https://github.com/mathiasbynens/jquery-placeholder/pull/99
|
|
|
|
|
try {
|
|
|
|
|
return document.activeElement;
|
|
|
|
|
} catch (err) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}(this, document, jQuery));
|
|
|
|
|
|
2016-03-16 17:30:07 +05:00
|
|
|
|
/*
|
|
|
|
|
* JavaScript Custom Forms Module
|
|
|
|
|
*/
|
|
|
|
|
jcf = {
|
|
|
|
|
// global options
|
|
|
|
|
modules: {},
|
|
|
|
|
plugins: {},
|
|
|
|
|
baseOptions: {
|
|
|
|
|
unselectableClass:'jcf-unselectable',
|
|
|
|
|
labelActiveClass:'jcf-label-active',
|
|
|
|
|
labelDisabledClass:'jcf-label-disabled',
|
|
|
|
|
classPrefix: 'jcf-class-',
|
|
|
|
|
hiddenClass:'jcf-hidden',
|
|
|
|
|
focusClass:'jcf-focus',
|
|
|
|
|
wrapperTag: 'div'
|
|
|
|
|
},
|
|
|
|
|
// replacer function
|
|
|
|
|
customForms: {
|
|
|
|
|
setOptions: function(obj) {
|
|
|
|
|
for(var p in obj) {
|
|
|
|
|
if(obj.hasOwnProperty(p) && typeof obj[p] === 'object') {
|
|
|
|
|
jcf.lib.extend(jcf.modules[p].prototype.defaultOptions, obj[p]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
replaceAll: function(context) {
|
|
|
|
|
for(var k in jcf.modules) {
|
|
|
|
|
var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector, context);
|
|
|
|
|
for(var i = 0; i<els.length; i++) {
|
|
|
|
|
if(els[i].jcf) {
|
|
|
|
|
// refresh form element state
|
|
|
|
|
els[i].jcf.refreshState();
|
|
|
|
|
} else {
|
|
|
|
|
// replace form element
|
|
|
|
|
if(!jcf.lib.hasClass(els[i], 'default') && jcf.modules[k].prototype.checkElement(els[i])) {
|
|
|
|
|
new jcf.modules[k]({
|
|
|
|
|
replaces:els[i]
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshAll: function(context) {
|
|
|
|
|
for(var k in jcf.modules) {
|
|
|
|
|
var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector, context);
|
|
|
|
|
for(var i = 0; i<els.length; i++) {
|
|
|
|
|
if(els[i].jcf) {
|
|
|
|
|
// refresh form element state
|
|
|
|
|
els[i].jcf.refreshState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshElement: function(obj) {
|
|
|
|
|
if(obj && obj.jcf) {
|
|
|
|
|
obj.jcf.refreshState();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
destroyAll: function() {
|
|
|
|
|
for(var k in jcf.modules) {
|
|
|
|
|
var els = jcf.lib.queryBySelector(jcf.modules[k].prototype.selector);
|
|
|
|
|
for(var i = 0; i<els.length; i++) {
|
|
|
|
|
if(els[i].jcf) {
|
|
|
|
|
els[i].jcf.destroy();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// detect device type
|
|
|
|
|
isTouchDevice: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
|
2016-03-28 20:07:51 +05:00
|
|
|
|
isWinPhoneDevice: /Windows Phone/.test(navigator.userAgent),
|
2016-03-16 17:30:07 +05:00
|
|
|
|
// define base module
|
|
|
|
|
setBaseModule: function(obj) {
|
|
|
|
|
jcf.customControl = function(opt){
|
|
|
|
|
this.options = jcf.lib.extend({}, jcf.baseOptions, this.defaultOptions, opt);
|
|
|
|
|
this.init();
|
|
|
|
|
};
|
|
|
|
|
for(var p in obj) {
|
|
|
|
|
jcf.customControl.prototype[p] = obj[p];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// add module to jcf.modules
|
|
|
|
|
addModule: function(obj) {
|
|
|
|
|
if(obj.name){
|
|
|
|
|
// create new module proto class
|
|
|
|
|
jcf.modules[obj.name] = function(){
|
|
|
|
|
jcf.modules[obj.name].superclass.constructor.apply(this, arguments);
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.inherit(jcf.modules[obj.name], jcf.customControl);
|
|
|
|
|
for(var p in obj) {
|
|
|
|
|
jcf.modules[obj.name].prototype[p] = obj[p]
|
|
|
|
|
}
|
|
|
|
|
// on create module
|
|
|
|
|
jcf.modules[obj.name].prototype.onCreateModule();
|
|
|
|
|
// make callback for exciting modules
|
|
|
|
|
for(var mod in jcf.modules) {
|
|
|
|
|
if(jcf.modules[mod] != jcf.modules[obj.name]) {
|
|
|
|
|
jcf.modules[mod].prototype.onModuleAdded(jcf.modules[obj.name]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// add plugin to jcf.plugins
|
|
|
|
|
addPlugin: function(obj) {
|
|
|
|
|
if(obj && obj.name) {
|
|
|
|
|
jcf.plugins[obj.name] = function() {
|
|
|
|
|
this.init.apply(this, arguments);
|
|
|
|
|
}
|
|
|
|
|
for(var p in obj) {
|
|
|
|
|
jcf.plugins[obj.name].prototype[p] = obj[p];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// miscellaneous init
|
|
|
|
|
init: function(){
|
|
|
|
|
if(navigator.pointerEnabled || navigator.msPointerEnabled) {
|
|
|
|
|
// use pointer events instead of mouse events
|
|
|
|
|
this.eventPress = navigator.pointerEnabled ? 'pointerdown' : 'MSPointerDown';
|
|
|
|
|
this.eventMove = navigator.pointerEnabled ? 'pointermove' : 'MSPointerMove';
|
|
|
|
|
this.eventRelease = navigator.pointerEnabled ? 'pointerup' : 'MSPointerUp';
|
|
|
|
|
} else {
|
|
|
|
|
// handle default desktop mouse events
|
|
|
|
|
this.eventPress = 'mousedown';
|
|
|
|
|
this.eventMove = 'mousemove';
|
|
|
|
|
this.eventRelease = 'mouseup';
|
|
|
|
|
}
|
|
|
|
|
if(this.isTouchDevice) {
|
|
|
|
|
// handle touch events also
|
|
|
|
|
this.eventPress += ' touchstart';
|
|
|
|
|
this.eventMove += ' touchmove';
|
|
|
|
|
this.eventRelease += ' touchend';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTimeout(function(){
|
|
|
|
|
jcf.lib.domReady(function(){
|
|
|
|
|
jcf.initStyles();
|
|
|
|
|
});
|
|
|
|
|
},1);
|
|
|
|
|
return this;
|
|
|
|
|
},
|
|
|
|
|
initStyles: function() {
|
|
|
|
|
// create <style> element and rules
|
|
|
|
|
var head = document.getElementsByTagName('head')[0],
|
|
|
|
|
style = document.createElement('style'),
|
|
|
|
|
rules = document.createTextNode('.'+jcf.baseOptions.unselectableClass+'{'+
|
|
|
|
|
'-moz-user-select:none;'+
|
|
|
|
|
'-webkit-tap-highlight-color:rgba(255,255,255,0);'+
|
|
|
|
|
'-webkit-user-select:none;'+
|
|
|
|
|
'user-select:none;'+
|
|
|
|
|
'}');
|
|
|
|
|
|
|
|
|
|
// append style element
|
|
|
|
|
style.type = 'text/css';
|
|
|
|
|
if(style.styleSheet) {
|
|
|
|
|
style.styleSheet.cssText = rules.nodeValue;
|
|
|
|
|
} else {
|
|
|
|
|
style.appendChild(rules);
|
|
|
|
|
}
|
|
|
|
|
head.appendChild(style);
|
|
|
|
|
}
|
|
|
|
|
}.init();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Custom Form Control prototype
|
|
|
|
|
*/
|
|
|
|
|
jcf.setBaseModule({
|
|
|
|
|
init: function(){
|
|
|
|
|
if(this.options.replaces) {
|
|
|
|
|
this.realElement = this.options.replaces;
|
|
|
|
|
this.realElement.jcf = this;
|
|
|
|
|
this.replaceObject();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
// default module options (will be merged with base options)
|
|
|
|
|
},
|
|
|
|
|
checkElement: function(el){
|
|
|
|
|
return true; // additional check for correct form element
|
|
|
|
|
},
|
|
|
|
|
replaceObject: function(){
|
|
|
|
|
this.createWrapper();
|
|
|
|
|
this.attachEvents();
|
|
|
|
|
this.fixStyles();
|
|
|
|
|
this.setupWrapper();
|
|
|
|
|
},
|
|
|
|
|
createWrapper: function(){
|
|
|
|
|
this.fakeElement = jcf.lib.createElement(this.options.wrapperTag);
|
|
|
|
|
this.labelFor = jcf.lib.getLabelFor(this.realElement);
|
|
|
|
|
jcf.lib.disableTextSelection(this.fakeElement);
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, jcf.lib.getAllClasses(this.realElement.className, this.options.classPrefix));
|
|
|
|
|
jcf.lib.addClass(this.realElement, jcf.baseOptions.hiddenClass);
|
|
|
|
|
},
|
|
|
|
|
attachEvents: function(){
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'focus', this.onFocusHandler, this);
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'blur', this.onBlurHandler, this);
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, 'click', this.onFakeClick, this);
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, jcf.eventPress, this.onFakePressed, this);
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, jcf.eventRelease, this.onFakeReleased, this);
|
|
|
|
|
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
this.labelFor.jcf = this;
|
|
|
|
|
jcf.lib.event.add(this.labelFor, 'click', this.onFakeClick, this);
|
|
|
|
|
jcf.lib.event.add(this.labelFor, jcf.eventPress, this.onFakePressed, this);
|
|
|
|
|
jcf.lib.event.add(this.labelFor, jcf.eventRelease, this.onFakeReleased, this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fixStyles: function() {
|
|
|
|
|
// hide mobile webkit tap effect
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
var tapStyle = 'rgba(255,255,255,0)';
|
|
|
|
|
this.realElement.style.webkitTapHighlightColor = tapStyle;
|
|
|
|
|
this.fakeElement.style.webkitTapHighlightColor = tapStyle;
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
this.labelFor.style.webkitTapHighlightColor = tapStyle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
// implement in subclass
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(){
|
|
|
|
|
// implement in subclass
|
|
|
|
|
},
|
|
|
|
|
destroy: function() {
|
|
|
|
|
if(this.fakeElement && this.fakeElement.parentNode) {
|
|
|
|
|
this.fakeElement.parentNode.insertBefore(this.realElement, this.fakeElement);
|
|
|
|
|
this.fakeElement.parentNode.removeChild(this.fakeElement);
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
|
|
|
|
|
this.realElement.jcf = null;
|
|
|
|
|
},
|
|
|
|
|
onFocus: function(){
|
|
|
|
|
// emulated focus event
|
|
|
|
|
jcf.lib.addClass(this.fakeElement,this.options.focusClass);
|
|
|
|
|
},
|
|
|
|
|
onBlur: function(cb){
|
|
|
|
|
// emulated blur event
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement,this.options.focusClass);
|
|
|
|
|
},
|
|
|
|
|
onFocusHandler: function() {
|
|
|
|
|
// handle focus loses
|
|
|
|
|
if(this.focused) return;
|
|
|
|
|
this.focused = true;
|
|
|
|
|
|
|
|
|
|
// handle touch devices also
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
if(jcf.focusedInstance && jcf.focusedInstance.realElement != this.realElement) {
|
|
|
|
|
jcf.focusedInstance.onBlur();
|
|
|
|
|
jcf.focusedInstance.realElement.blur();
|
|
|
|
|
}
|
|
|
|
|
jcf.focusedInstance = this;
|
|
|
|
|
}
|
|
|
|
|
this.onFocus.apply(this, arguments);
|
|
|
|
|
},
|
|
|
|
|
onBlurHandler: function() {
|
|
|
|
|
// handle focus loses
|
|
|
|
|
if(!this.pressedFlag) {
|
|
|
|
|
this.focused = false;
|
|
|
|
|
this.onBlur.apply(this, arguments);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onFakeClick: function(){
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
this.onFocus();
|
|
|
|
|
} else if(!this.realElement.disabled) {
|
|
|
|
|
this.realElement.focus();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onFakePressed: function(e){
|
|
|
|
|
this.pressedFlag = true;
|
|
|
|
|
},
|
|
|
|
|
onFakeReleased: function(){
|
|
|
|
|
this.pressedFlag = false;
|
|
|
|
|
},
|
|
|
|
|
onCreateModule: function(){
|
|
|
|
|
// implement in subclass
|
|
|
|
|
},
|
|
|
|
|
onModuleAdded: function(module) {
|
|
|
|
|
// implement in subclass
|
|
|
|
|
},
|
|
|
|
|
onControlReady: function() {
|
|
|
|
|
// implement in subclass
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* JCF Utility Library
|
|
|
|
|
*/
|
|
|
|
|
jcf.lib = {
|
|
|
|
|
bind: function(func, scope){
|
|
|
|
|
return function() {
|
|
|
|
|
return func.apply(scope, arguments);
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
browser: (function() {
|
|
|
|
|
var ua = navigator.userAgent.toLowerCase(), res = {},
|
|
|
|
|
match = /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) ||
|
|
|
|
|
/(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+))?/.exec(ua) || [];
|
|
|
|
|
res[match[1]] = true;
|
|
|
|
|
res.version = match[2] || "0";
|
|
|
|
|
res.safariMac = ua.indexOf('mac') != -1 && ua.indexOf('safari') != -1;
|
|
|
|
|
return res;
|
|
|
|
|
})(),
|
|
|
|
|
getOffset: function (obj) {
|
|
|
|
|
if (obj.getBoundingClientRect && !jcf.isWinPhoneDevice) {
|
|
|
|
|
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
|
|
|
|
|
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
|
|
|
|
|
var clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0;
|
|
|
|
|
var clientTop = document.documentElement.clientTop || document.body.clientTop || 0;
|
|
|
|
|
return {
|
|
|
|
|
top:Math.round(obj.getBoundingClientRect().top + scrollTop - clientTop),
|
|
|
|
|
left:Math.round(obj.getBoundingClientRect().left + scrollLeft - clientLeft)
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
var posLeft = 0, posTop = 0;
|
|
|
|
|
while (obj.offsetParent) {posLeft += obj.offsetLeft; posTop += obj.offsetTop; obj = obj.offsetParent;}
|
|
|
|
|
return {top:posTop,left:posLeft};
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getScrollTop: function() {
|
|
|
|
|
return window.pageYOffset || document.documentElement.scrollTop;
|
|
|
|
|
},
|
|
|
|
|
getScrollLeft: function() {
|
|
|
|
|
return window.pageXOffset || document.documentElement.scrollLeft;
|
|
|
|
|
},
|
|
|
|
|
getWindowWidth: function(){
|
|
|
|
|
return document.compatMode=='CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth;
|
|
|
|
|
},
|
|
|
|
|
getWindowHeight: function(){
|
|
|
|
|
return document.compatMode=='CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight;
|
|
|
|
|
},
|
|
|
|
|
getStyle: function(el, prop) {
|
|
|
|
|
if (document.defaultView && document.defaultView.getComputedStyle) {
|
|
|
|
|
return document.defaultView.getComputedStyle(el, null)[prop];
|
|
|
|
|
} else if (el.currentStyle) {
|
|
|
|
|
return el.currentStyle[prop];
|
|
|
|
|
} else {
|
|
|
|
|
return el.style[prop];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getParent: function(obj, selector) {
|
|
|
|
|
while(obj.parentNode && obj.parentNode != document.body) {
|
|
|
|
|
if(obj.parentNode.tagName.toLowerCase() == selector.toLowerCase()) {
|
|
|
|
|
return obj.parentNode;
|
|
|
|
|
}
|
|
|
|
|
obj = obj.parentNode;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
isParent: function(parent, child) {
|
|
|
|
|
while(child.parentNode) {
|
|
|
|
|
if(child.parentNode === parent) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
child = child.parentNode;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
getLabelFor: function(object) {
|
|
|
|
|
var parentLabel = jcf.lib.getParent(object,'label');
|
|
|
|
|
if(parentLabel) {
|
|
|
|
|
return parentLabel;
|
|
|
|
|
} else if(object.id) {
|
|
|
|
|
return jcf.lib.queryBySelector('label[for="' + object.id + '"]')[0];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
disableTextSelection: function(el){
|
|
|
|
|
if (typeof el.onselectstart !== 'undefined') {
|
|
|
|
|
el.onselectstart = function() {return false;};
|
|
|
|
|
} else if(window.opera) {
|
|
|
|
|
el.setAttribute('unselectable', 'on');
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.addClass(el, jcf.baseOptions.unselectableClass);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
enableTextSelection: function(el) {
|
|
|
|
|
if (typeof el.onselectstart !== 'undefined') {
|
|
|
|
|
el.onselectstart = null;
|
|
|
|
|
} else if(window.opera) {
|
|
|
|
|
el.removeAttribute('unselectable');
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(el, jcf.baseOptions.unselectableClass);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
queryBySelector: function(selector, scope){
|
|
|
|
|
if(typeof scope === 'string') {
|
|
|
|
|
var result = [];
|
|
|
|
|
var holders = this.getElementsBySelector(scope);
|
|
|
|
|
for (var i = 0, contextNodes; i < holders.length; i++) {
|
|
|
|
|
contextNodes = Array.prototype.slice.call(this.getElementsBySelector(selector, holders[i]));
|
|
|
|
|
result = result.concat(contextNodes);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
} else {
|
|
|
|
|
return this.getElementsBySelector(selector, scope);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
prevSibling: function(node) {
|
|
|
|
|
while(node = node.previousSibling) if(node.nodeType == 1) break;
|
|
|
|
|
return node;
|
|
|
|
|
},
|
|
|
|
|
nextSibling: function(node) {
|
|
|
|
|
while(node = node.nextSibling) if(node.nodeType == 1) break;
|
|
|
|
|
return node;
|
|
|
|
|
},
|
|
|
|
|
fireEvent: function(element,event) {
|
|
|
|
|
if(element.dispatchEvent){
|
|
|
|
|
var evt = document.createEvent('HTMLEvents');
|
|
|
|
|
evt.initEvent(event, true, true );
|
|
|
|
|
return !element.dispatchEvent(evt);
|
|
|
|
|
}else if(document.createEventObject){
|
|
|
|
|
var evt = document.createEventObject();
|
|
|
|
|
return element.fireEvent('on'+event,evt);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
inherit: function(Child, Parent) {
|
|
|
|
|
var F = function() { }
|
|
|
|
|
F.prototype = Parent.prototype
|
|
|
|
|
Child.prototype = new F()
|
|
|
|
|
Child.prototype.constructor = Child
|
|
|
|
|
Child.superclass = Parent.prototype
|
|
|
|
|
},
|
|
|
|
|
extend: function(obj) {
|
|
|
|
|
for(var i = 1; i < arguments.length; i++) {
|
|
|
|
|
for(var p in arguments[i]) {
|
|
|
|
|
if(arguments[i].hasOwnProperty(p)) {
|
|
|
|
|
obj[p] = arguments[i][p];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return obj;
|
|
|
|
|
},
|
|
|
|
|
hasClass: function (obj,cname) {
|
|
|
|
|
return (obj.className ? obj.className.match(new RegExp('(\\s|^)'+cname+'(\\s|$)')) : false);
|
|
|
|
|
},
|
|
|
|
|
addClass: function (obj,cname) {
|
|
|
|
|
if (!this.hasClass(obj,cname)) obj.className += (!obj.className.length || obj.className.charAt(obj.className.length - 1) === ' ' ? '' : ' ') + cname;
|
|
|
|
|
},
|
|
|
|
|
removeClass: function (obj,cname) {
|
|
|
|
|
if (this.hasClass(obj,cname)) obj.className=obj.className.replace(new RegExp('(\\s|^)'+cname+'(\\s|$)'),' ').replace(/\s+$/, '');
|
|
|
|
|
},
|
|
|
|
|
toggleClass: function(obj, cname, condition) {
|
|
|
|
|
if(condition) this.addClass(obj, cname); else this.removeClass(obj, cname);
|
|
|
|
|
},
|
|
|
|
|
createElement: function(tagName, options) {
|
|
|
|
|
var el = document.createElement(tagName);
|
|
|
|
|
for(var p in options) {
|
|
|
|
|
if(options.hasOwnProperty(p)) {
|
|
|
|
|
switch (p) {
|
|
|
|
|
case 'class': el.className = options[p]; break;
|
|
|
|
|
case 'html': el.innerHTML = options[p]; break;
|
|
|
|
|
case 'style': this.setStyles(el, options[p]); break;
|
|
|
|
|
default: el.setAttribute(p, options[p]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return el;
|
|
|
|
|
},
|
|
|
|
|
setStyles: function(el, styles) {
|
|
|
|
|
for(var p in styles) {
|
|
|
|
|
if(styles.hasOwnProperty(p)) {
|
|
|
|
|
switch (p) {
|
|
|
|
|
case 'float': el.style.cssFloat = styles[p]; break;
|
|
|
|
|
case 'opacity': el.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+styles[p]*100+')'; el.style.opacity = styles[p]; break;
|
|
|
|
|
default: el.style[p] = (typeof styles[p] === 'undefined' ? 0 : styles[p]) + (typeof styles[p] === 'number' ? 'px' : '');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return el;
|
|
|
|
|
},
|
|
|
|
|
getInnerWidth: function(el) {
|
|
|
|
|
return el.offsetWidth - (parseInt(this.getStyle(el,'paddingLeft')) || 0) - (parseInt(this.getStyle(el,'paddingRight')) || 0);
|
|
|
|
|
},
|
|
|
|
|
getInnerHeight: function(el) {
|
|
|
|
|
return el.offsetHeight - (parseInt(this.getStyle(el,'paddingTop')) || 0) - (parseInt(this.getStyle(el,'paddingBottom')) || 0);
|
|
|
|
|
},
|
|
|
|
|
getAllClasses: function(cname, prefix, skip) {
|
|
|
|
|
if(!skip) skip = '';
|
|
|
|
|
if(!prefix) prefix = '';
|
|
|
|
|
return cname ? cname.replace(new RegExp('(\\s|^)'+skip+'(\\s|$)'),' ').replace(/[\s]*([\S]+)+[\s]*/gi,prefix+"$1 ") : '';
|
|
|
|
|
},
|
|
|
|
|
getElementsBySelector: function(selector, scope) {
|
|
|
|
|
if(typeof document.querySelectorAll === 'function') {
|
|
|
|
|
return (scope || document).querySelectorAll(selector);
|
|
|
|
|
}
|
|
|
|
|
var selectors = selector.split(',');
|
|
|
|
|
var resultList = [];
|
|
|
|
|
for(var s = 0; s < selectors.length; s++) {
|
|
|
|
|
var currentContext = [scope || document];
|
|
|
|
|
var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' ');
|
|
|
|
|
for (var i = 0; i < tokens.length; i++) {
|
|
|
|
|
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
|
|
|
|
|
if (token.indexOf('#') > -1) {
|
|
|
|
|
var bits = token.split('#'), tagName = bits[0], id = bits[1];
|
|
|
|
|
var element = document.getElementById(id);
|
|
|
|
|
if (tagName && element.nodeName.toLowerCase() != tagName) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
currentContext = [element];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (token.indexOf('.') > -1) {
|
|
|
|
|
var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements;
|
|
|
|
|
if (tagName == '*') {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName('*');
|
|
|
|
|
} else {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
}
|
|
|
|
|
for (var j = 0; j < elements.length; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0;
|
|
|
|
|
for (var k = 0; k < found.length; k++) {
|
|
|
|
|
if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) {
|
|
|
|
|
currentContext[currentContextIndex++] = found[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^"]*)"?\]$/)) {
|
|
|
|
|
var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4;
|
|
|
|
|
if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) {
|
|
|
|
|
attrName = 'htmlFor';
|
|
|
|
|
}
|
|
|
|
|
var found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements;
|
|
|
|
|
if (tagName == '*') {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName('*');
|
|
|
|
|
} else {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
}
|
|
|
|
|
for (var j = 0; elements[j]; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0, checkFunction;
|
|
|
|
|
switch (attrOperator) {
|
|
|
|
|
case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break;
|
|
|
|
|
case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break;
|
|
|
|
|
case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break;
|
|
|
|
|
case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break;
|
|
|
|
|
case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break;
|
|
|
|
|
case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break;
|
|
|
|
|
default : checkFunction = function(e) { return e.getAttribute(attrName) };
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0;
|
|
|
|
|
for (var k = 0; k < found.length; k++) {
|
|
|
|
|
if (checkFunction(found[k])) {
|
|
|
|
|
currentContext[currentContextIndex++] = found[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
tagName = token;
|
|
|
|
|
var found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
for (var j = 0; j < elements.length; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = found;
|
|
|
|
|
}
|
|
|
|
|
resultList = [].concat(resultList,currentContext);
|
|
|
|
|
}
|
|
|
|
|
return resultList;
|
|
|
|
|
},
|
|
|
|
|
scrollSize: (function(){
|
|
|
|
|
var content, hold, sizeBefore, sizeAfter;
|
|
|
|
|
function buildSizer(){
|
|
|
|
|
if(hold) removeSizer();
|
|
|
|
|
content = document.createElement('div');
|
|
|
|
|
hold = document.createElement('div');
|
|
|
|
|
hold.style.cssText = 'position:absolute;overflow:hidden;width:100px;height:100px';
|
|
|
|
|
hold.appendChild(content);
|
|
|
|
|
document.body.appendChild(hold);
|
|
|
|
|
}
|
|
|
|
|
function removeSizer(){
|
|
|
|
|
document.body.removeChild(hold);
|
|
|
|
|
hold = null;
|
|
|
|
|
}
|
|
|
|
|
function calcSize(vertical) {
|
|
|
|
|
buildSizer();
|
|
|
|
|
content.style.cssText = 'height:'+(vertical ? '100%' : '200px');
|
|
|
|
|
sizeBefore = (vertical ? content.offsetHeight : content.offsetWidth);
|
|
|
|
|
hold.style.overflow = 'scroll'; content.innerHTML = 1;
|
|
|
|
|
sizeAfter = (vertical ? content.offsetHeight : content.offsetWidth);
|
|
|
|
|
if(vertical && hold.clientHeight) sizeAfter = hold.clientHeight;
|
|
|
|
|
removeSizer();
|
|
|
|
|
return sizeBefore - sizeAfter;
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
getWidth:function(){
|
|
|
|
|
return calcSize(false);
|
|
|
|
|
},
|
|
|
|
|
getHeight:function(){
|
|
|
|
|
return calcSize(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()),
|
|
|
|
|
domReady: function (handler){
|
|
|
|
|
var called = false
|
|
|
|
|
function ready() {
|
|
|
|
|
if (called) return;
|
|
|
|
|
called = true;
|
|
|
|
|
handler();
|
|
|
|
|
}
|
|
|
|
|
if (document.addEventListener) {
|
|
|
|
|
document.addEventListener("DOMContentLoaded", ready, false);
|
|
|
|
|
} else if (document.attachEvent) {
|
|
|
|
|
if (document.documentElement.doScroll && window == window.top) {
|
|
|
|
|
function tryScroll(){
|
|
|
|
|
if (called) return
|
|
|
|
|
if (!document.body) return
|
|
|
|
|
try {
|
|
|
|
|
document.documentElement.doScroll("left")
|
|
|
|
|
ready()
|
|
|
|
|
} catch(e) {
|
|
|
|
|
setTimeout(tryScroll, 0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tryScroll()
|
|
|
|
|
}
|
|
|
|
|
document.attachEvent("onreadystatechange", function(){
|
|
|
|
|
if (document.readyState === "complete") {
|
|
|
|
|
ready()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if (window.addEventListener) window.addEventListener('load', ready, false)
|
|
|
|
|
else if (window.attachEvent) window.attachEvent('onload', ready)
|
|
|
|
|
},
|
|
|
|
|
event: (function(){
|
|
|
|
|
var guid = 0;
|
|
|
|
|
function fixEvent(e) {
|
|
|
|
|
e = e || window.event;
|
|
|
|
|
if (e.isFixed) {
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
e.isFixed = true;
|
|
|
|
|
e.preventDefault = e.preventDefault || function(){this.returnValue = false}
|
|
|
|
|
e.stopPropagation = e.stopPropagation || function(){this.cancelBubble = true}
|
|
|
|
|
if (!e.target) {
|
|
|
|
|
e.target = e.srcElement
|
|
|
|
|
}
|
|
|
|
|
if (!e.relatedTarget && e.fromElement) {
|
|
|
|
|
e.relatedTarget = e.fromElement == e.target ? e.toElement : e.fromElement;
|
|
|
|
|
}
|
|
|
|
|
if (e.pageX == null && e.clientX != null) {
|
|
|
|
|
var html = document.documentElement, body = document.body;
|
|
|
|
|
e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
|
|
|
|
|
e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
|
|
|
|
|
}
|
|
|
|
|
if (!e.which && e.button) {
|
|
|
|
|
e.which = e.button & 1 ? 1 : (e.button & 2 ? 3 : (e.button & 4 ? 2 : 0));
|
|
|
|
|
}
|
|
|
|
|
if(e.type === "DOMMouseScroll" || e.type === 'mousewheel') {
|
|
|
|
|
e.mWheelDelta = 0;
|
|
|
|
|
if (e.wheelDelta) {
|
|
|
|
|
e.mWheelDelta = e.wheelDelta/120;
|
|
|
|
|
} else if (e.detail) {
|
|
|
|
|
e.mWheelDelta = -e.detail/3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
function commonHandle(event, customScope) {
|
|
|
|
|
event = fixEvent(event);
|
|
|
|
|
var handlers = this.events[event.type];
|
|
|
|
|
for (var g in handlers) {
|
|
|
|
|
var handler = handlers[g];
|
|
|
|
|
var ret = handler.call(customScope || this, event);
|
|
|
|
|
if (ret === false) {
|
|
|
|
|
event.preventDefault()
|
|
|
|
|
event.stopPropagation()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var publicAPI = {
|
|
|
|
|
add: function(elem, type, handler, forcedScope) {
|
|
|
|
|
// handle multiple events
|
|
|
|
|
if(type.indexOf(' ') > -1) {
|
|
|
|
|
var eventList = type.split(' ');
|
|
|
|
|
for(var i = 0; i < eventList.length; i++) {
|
|
|
|
|
publicAPI.add(elem, eventList[i], handler, forcedScope);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (elem.setInterval && (elem != window && !elem.frameElement)) {
|
|
|
|
|
elem = window;
|
|
|
|
|
}
|
|
|
|
|
if (!handler.guid) {
|
|
|
|
|
handler.guid = ++guid;
|
|
|
|
|
}
|
|
|
|
|
if (!elem.events) {
|
|
|
|
|
elem.events = {};
|
|
|
|
|
elem.handle = function(event) {
|
|
|
|
|
return commonHandle.call(elem, event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!elem.events[type]) {
|
|
|
|
|
elem.events[type] = {};
|
|
|
|
|
if (elem.addEventListener) elem.addEventListener(type, elem.handle, false);
|
|
|
|
|
else if (elem.attachEvent) elem.attachEvent("on" + type, elem.handle);
|
|
|
|
|
if(type === 'mousewheel') {
|
|
|
|
|
publicAPI.add(elem, 'DOMMouseScroll', handler, forcedScope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var fakeHandler = jcf.lib.bind(handler, forcedScope);
|
|
|
|
|
fakeHandler.guid = handler.guid;
|
|
|
|
|
elem.events[type][handler.guid] = forcedScope ? fakeHandler : handler;
|
|
|
|
|
},
|
|
|
|
|
remove: function(elem, type, handler) {
|
|
|
|
|
// handle multiple events
|
|
|
|
|
if(type.indexOf(' ') > -1) {
|
|
|
|
|
var eventList = type.split(' ');
|
|
|
|
|
for(var i = 0; i < eventList.length; i++) {
|
|
|
|
|
publicAPI.remove(elem, eventList[i], handler);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var handlers = elem.events && elem.events[type];
|
|
|
|
|
if (!handlers) return;
|
|
|
|
|
delete handlers[handler.guid];
|
|
|
|
|
for(var any in handlers) return;
|
|
|
|
|
if (elem.removeEventListener) elem.removeEventListener(type, elem.handle, false);
|
|
|
|
|
else if (elem.detachEvent) elem.detachEvent("on" + type, elem.handle);
|
|
|
|
|
delete elem.events[type];
|
|
|
|
|
for (var any in elem.events) return;
|
|
|
|
|
try {
|
|
|
|
|
delete elem.handle;
|
|
|
|
|
delete elem.events;
|
|
|
|
|
} catch(e) {
|
|
|
|
|
if(elem.removeAttribute) {
|
|
|
|
|
elem.removeAttribute("handle");
|
|
|
|
|
elem.removeAttribute("events");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(type === 'mousewheel') {
|
|
|
|
|
publicAPI.remove(elem, 'DOMMouseScroll', handler);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-28 20:07:51 +05:00
|
|
|
|
return publicAPI;
|
|
|
|
|
}())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// custom select module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name:'select',
|
|
|
|
|
selector:'select',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
useNativeDropOnMobileDevices: true,
|
|
|
|
|
hideDropOnScroll: true,
|
|
|
|
|
showNativeDrop: false,
|
|
|
|
|
handleDropPosition: false,
|
|
|
|
|
selectDropPosition: 'bottom', // or 'top'
|
|
|
|
|
wrapperClass:'select-area',
|
|
|
|
|
focusClass:'select-focus',
|
|
|
|
|
dropActiveClass:'select-active',
|
|
|
|
|
selectedClass:'item-selected',
|
|
|
|
|
currentSelectedClass:'current-selected',
|
|
|
|
|
disabledClass:'select-disabled',
|
|
|
|
|
valueSelector:'span.center',
|
|
|
|
|
optGroupClass:'optgroup',
|
|
|
|
|
openerSelector:'a.select-opener',
|
|
|
|
|
selectStructure:'<span class="left"></span><span class="center"></span><a class="select-opener"></a>',
|
|
|
|
|
wrapperTag: 'span',
|
|
|
|
|
classPrefix:'select-',
|
|
|
|
|
dropMaxHeight: 200,
|
|
|
|
|
dropFlippedClass: 'select-options-flipped',
|
|
|
|
|
dropHiddenClass:'options-hidden',
|
|
|
|
|
dropScrollableClass:'options-overflow',
|
|
|
|
|
dropClass:'select-options',
|
|
|
|
|
dropClassPrefix:'drop-',
|
|
|
|
|
dropStructure:'<div class="drop-holder"><div class="drop-list"></div></div>',
|
|
|
|
|
dropSelector:'div.drop-list'
|
|
|
|
|
},
|
|
|
|
|
checkElement: function(el){
|
|
|
|
|
return (!el.size && !el.multiple);
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement.nextSibling);
|
|
|
|
|
this.fakeElement.innerHTML = this.options.selectStructure;
|
|
|
|
|
this.fakeElement.style.width = (this.realElement.offsetWidth > 0 ? this.realElement.offsetWidth + 'px' : 'auto');
|
|
|
|
|
|
|
|
|
|
// show native drop if specified in options
|
|
|
|
|
if(this.options.useNativeDropOnMobileDevices && (jcf.isTouchDevice || jcf.isWinPhoneDevice)) {
|
|
|
|
|
this.options.showNativeDrop = true;
|
|
|
|
|
}
|
|
|
|
|
if(this.options.showNativeDrop) {
|
|
|
|
|
this.fakeElement.appendChild(this.realElement);
|
|
|
|
|
jcf.lib.removeClass(this.realElement, this.options.hiddenClass);
|
|
|
|
|
jcf.lib.setStyles(this.realElement, {
|
|
|
|
|
top:0,
|
|
|
|
|
left:0,
|
|
|
|
|
margin:0,
|
|
|
|
|
padding:0,
|
|
|
|
|
opacity:0,
|
|
|
|
|
border:'none',
|
|
|
|
|
position:'absolute',
|
|
|
|
|
width: jcf.lib.getInnerWidth(this.fakeElement) - 1,
|
|
|
|
|
height: jcf.lib.getInnerHeight(this.fakeElement) - 1
|
|
|
|
|
});
|
|
|
|
|
jcf.lib.event.add(this.realElement, jcf.eventPress, function(){
|
|
|
|
|
this.realElement.title = '';
|
|
|
|
|
}, this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create select body
|
|
|
|
|
this.opener = jcf.lib.queryBySelector(this.options.openerSelector, this.fakeElement)[0];
|
|
|
|
|
this.valueText = jcf.lib.queryBySelector(this.options.valueSelector, this.fakeElement)[0];
|
|
|
|
|
jcf.lib.disableTextSelection(this.valueText);
|
|
|
|
|
this.opener.jcf = this;
|
|
|
|
|
|
|
|
|
|
if(!this.options.showNativeDrop) {
|
|
|
|
|
this.createDropdown();
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.onControlReady(this);
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
} else {
|
|
|
|
|
this.refreshState();
|
|
|
|
|
}
|
|
|
|
|
this.addEvents();
|
|
|
|
|
},
|
|
|
|
|
addEvents: function(){
|
|
|
|
|
if(this.options.showNativeDrop) {
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'click', this.onChange, this);
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, 'click', this.toggleDropdown, this);
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'change', this.onChange, this);
|
|
|
|
|
},
|
|
|
|
|
onFakeClick: function() {
|
|
|
|
|
// do nothing (drop toggles by toggleDropdown method)
|
|
|
|
|
},
|
|
|
|
|
onFocus: function(){
|
|
|
|
|
jcf.modules[this.name].superclass.onFocus.apply(this, arguments);
|
|
|
|
|
if(!this.options.showNativeDrop) {
|
|
|
|
|
// Mac Safari Fix
|
|
|
|
|
if(jcf.lib.browser.safariMac) {
|
|
|
|
|
this.realElement.setAttribute('size','2');
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'keydown', this.onKeyDown, this);
|
|
|
|
|
if(jcf.activeControl && jcf.activeControl != this) {
|
|
|
|
|
jcf.activeControl.hideDropdown();
|
|
|
|
|
jcf.activeControl = this;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onBlur: function(){
|
|
|
|
|
if(!this.options.showNativeDrop) {
|
|
|
|
|
// Mac Safari Fix
|
|
|
|
|
if(jcf.lib.browser.safariMac) {
|
|
|
|
|
this.realElement.removeAttribute('size');
|
|
|
|
|
}
|
|
|
|
|
if(!this.isActiveDrop() || !this.isOverDrop()) {
|
|
|
|
|
jcf.modules[this.name].superclass.onBlur.apply(this);
|
|
|
|
|
if(jcf.activeControl === this) jcf.activeControl = null;
|
|
|
|
|
if(!jcf.isTouchDevice) {
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.event.remove(this.realElement, 'keydown', this.onKeyDown);
|
|
|
|
|
} else {
|
|
|
|
|
jcf.modules[this.name].superclass.onBlur.apply(this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onChange: function() {
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},
|
|
|
|
|
onKeyDown: function(e){
|
|
|
|
|
this.dropOpened = true;
|
|
|
|
|
jcf.tmpFlag = true;
|
|
|
|
|
setTimeout(function(){jcf.tmpFlag = false},100);
|
|
|
|
|
var context = this;
|
|
|
|
|
context.keyboardFix = true;
|
|
|
|
|
setTimeout(function(){
|
|
|
|
|
context.refreshState();
|
|
|
|
|
},10);
|
|
|
|
|
if(e.keyCode == 13) {
|
|
|
|
|
context.toggleDropdown.apply(context);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onResizeWindow: function(e){
|
|
|
|
|
if(this.isActiveDrop()) {
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onScrollWindow: function(e){
|
|
|
|
|
if(this.options.hideDropOnScroll) {
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
} else if(this.isActiveDrop()) {
|
|
|
|
|
this.positionDropdown();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onOptionClick: function(e){
|
|
|
|
|
var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
|
|
|
|
|
if(opener && !jcf.lib.hasClass(opener, 'opt-disabled')) {
|
|
|
|
|
this.dropOpened = true;
|
|
|
|
|
this.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
this.onFocus();
|
|
|
|
|
} else {
|
|
|
|
|
this.realElement.focus();
|
|
|
|
|
}
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
jcf.lib.fireEvent(this.realElement, 'change');
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
onClickOutside: function(e){
|
|
|
|
|
if(jcf.tmpFlag) {
|
|
|
|
|
jcf.tmpFlag = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(!jcf.lib.isParent(this.fakeElement, e.target) && !jcf.lib.isParent(this.selectDrop, e.target)) {
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onDropHover: function(e){
|
|
|
|
|
if(!this.keyboardFix) {
|
|
|
|
|
this.hoverFlag = true;
|
|
|
|
|
var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
|
|
|
|
|
if(opener) {
|
|
|
|
|
this.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
|
|
|
|
|
this.refreshSelectedClass(parseInt(opener.getAttribute('rel')));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.keyboardFix = false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onDropLeave: function(){
|
|
|
|
|
this.hoverFlag = false;
|
|
|
|
|
},
|
|
|
|
|
isActiveDrop: function(){
|
|
|
|
|
return !jcf.lib.hasClass(this.selectDrop, this.options.dropHiddenClass);
|
|
|
|
|
},
|
|
|
|
|
isOverDrop: function(){
|
|
|
|
|
return this.hoverFlag;
|
|
|
|
|
},
|
|
|
|
|
createDropdown: function(){
|
|
|
|
|
// remove old dropdown if exists
|
|
|
|
|
if(this.selectDrop && this.selectDrop.parentNode) {
|
|
|
|
|
this.selectDrop.parentNode.removeChild(this.selectDrop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create dropdown holder
|
|
|
|
|
this.selectDrop = document.createElement('div');
|
|
|
|
|
this.selectDrop.className = this.options.dropClass;
|
|
|
|
|
this.selectDrop.innerHTML = this.options.dropStructure;
|
|
|
|
|
jcf.lib.setStyles(this.selectDrop, {position:'absolute'});
|
|
|
|
|
this.selectList = jcf.lib.queryBySelector(this.options.dropSelector,this.selectDrop)[0];
|
|
|
|
|
jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
|
|
|
|
|
document.body.appendChild(this.selectDrop);
|
|
|
|
|
this.selectDrop.jcf = this;
|
|
|
|
|
jcf.lib.event.add(this.selectDrop, 'click', this.onOptionClick, this);
|
|
|
|
|
jcf.lib.event.add(this.selectDrop, 'mouseover', this.onDropHover, this);
|
|
|
|
|
jcf.lib.event.add(this.selectDrop, 'mouseout', this.onDropLeave, this);
|
|
|
|
|
this.buildDropdown();
|
|
|
|
|
},
|
|
|
|
|
buildDropdown: function() {
|
|
|
|
|
// build select options / optgroups
|
|
|
|
|
this.buildDropdownOptions();
|
|
|
|
|
|
|
|
|
|
// position and resize dropdown
|
|
|
|
|
this.positionDropdown();
|
|
|
|
|
|
|
|
|
|
// cut dropdown if height exceedes
|
|
|
|
|
this.buildDropdownScroll();
|
|
|
|
|
},
|
|
|
|
|
buildDropdownOptions: function() {
|
|
|
|
|
this.resStructure = '';
|
|
|
|
|
this.optNum = 0;
|
|
|
|
|
for(var i = 0; i < this.realElement.children.length; i++) {
|
|
|
|
|
this.resStructure += this.buildElement(this.realElement.children[i], i) +'\n';
|
|
|
|
|
}
|
|
|
|
|
this.selectList.innerHTML = this.resStructure;
|
|
|
|
|
},
|
|
|
|
|
buildDropdownScroll: function() {
|
|
|
|
|
jcf.lib.addClass(this.selectDrop, jcf.lib.getAllClasses(this.realElement.className, this.options.dropClassPrefix, jcf.baseOptions.hiddenClass));
|
|
|
|
|
if(this.options.dropMaxHeight) {
|
|
|
|
|
if(this.selectDrop.offsetHeight > this.options.dropMaxHeight) {
|
|
|
|
|
this.selectList.style.height = this.options.dropMaxHeight+'px';
|
|
|
|
|
this.selectList.style.overflow = 'auto';
|
|
|
|
|
this.selectList.style.overflowX = 'hidden';
|
|
|
|
|
jcf.lib.addClass(this.selectDrop, this.options.dropScrollableClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
parseOptionTitle: function(optTitle) {
|
|
|
|
|
return (typeof optTitle === 'string' && /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i.test(optTitle)) ? optTitle : '';
|
|
|
|
|
},
|
|
|
|
|
buildElement: function(obj, index){
|
|
|
|
|
// build option
|
|
|
|
|
var res = '', optImage;
|
|
|
|
|
if(obj.tagName.toLowerCase() == 'option') {
|
|
|
|
|
if(!jcf.lib.prevSibling(obj) || jcf.lib.prevSibling(obj).tagName.toLowerCase() != 'option') {
|
|
|
|
|
res += '<ul>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optImage = this.parseOptionTitle(obj.title);
|
|
|
|
|
res += '<li rel="'+(this.optNum++)+'" class="'+(obj.className? obj.className + ' ' : '')+(obj.disabled? 'opt-disabled ' : '')+(index % 2 ? 'option-even ' : '')+'jcfcalc"><a href="#">'+(optImage ? '<img src="'+optImage+'" alt="" />' : '')+'<span>' + obj.innerHTML + '</span></a></li>';
|
|
|
|
|
if(!jcf.lib.nextSibling(obj) || jcf.lib.nextSibling(obj).tagName.toLowerCase() != 'option') {
|
|
|
|
|
res += '</ul>';
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
// build option group with options
|
|
|
|
|
else if(obj.tagName.toLowerCase() == 'optgroup' && obj.label) {
|
|
|
|
|
res += '<div class="'+this.options.optGroupClass+'">';
|
|
|
|
|
res += '<strong class="jcfcalc"><em>'+(obj.label)+'</em></strong>';
|
|
|
|
|
for(var i = 0; i < obj.children.length; i++) {
|
|
|
|
|
res += this.buildElement(obj.children[i], i);
|
|
|
|
|
}
|
|
|
|
|
res += '</div>';
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
positionDropdown: function(){
|
|
|
|
|
var ofs = jcf.lib.getOffset(this.fakeElement), selectAreaHeight = this.fakeElement.offsetHeight, selectDropHeight = this.selectDrop.offsetHeight;
|
|
|
|
|
var fitInTop = ofs.top - selectDropHeight >= jcf.lib.getScrollTop() && jcf.lib.getScrollTop() + jcf.lib.getWindowHeight() < ofs.top + selectAreaHeight + selectDropHeight;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if((this.options.handleDropPosition && fitInTop) || this.options.selectDropPosition === 'top') {
|
|
|
|
|
this.selectDrop.style.top = (ofs.top - selectDropHeight)+'px';
|
|
|
|
|
jcf.lib.addClass(this.selectDrop, this.options.dropFlippedClass);
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.dropFlippedClass);
|
|
|
|
|
} else {
|
|
|
|
|
this.selectDrop.style.top = (ofs.top + selectAreaHeight)+'px';
|
|
|
|
|
jcf.lib.removeClass(this.selectDrop, this.options.dropFlippedClass);
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.dropFlippedClass);
|
|
|
|
|
}
|
|
|
|
|
this.selectDrop.style.left = ofs.left+'px';
|
|
|
|
|
this.selectDrop.style.width = this.fakeElement.offsetWidth+'px';
|
|
|
|
|
},
|
|
|
|
|
showDropdown: function(){
|
|
|
|
|
document.body.appendChild(this.selectDrop);
|
|
|
|
|
jcf.lib.removeClass(this.selectDrop, this.options.dropHiddenClass);
|
|
|
|
|
jcf.lib.addClass(this.fakeElement,this.options.dropActiveClass);
|
|
|
|
|
this.positionDropdown();
|
|
|
|
|
|
|
|
|
|
// highlight current active item
|
|
|
|
|
var activeItem = this.getFakeActiveOption();
|
|
|
|
|
this.removeClassFromItems(this.options.currentSelectedClass);
|
|
|
|
|
jcf.lib.addClass(activeItem, this.options.currentSelectedClass);
|
|
|
|
|
|
|
|
|
|
// show current dropdown
|
|
|
|
|
jcf.lib.event.add(window, 'resize', this.onResizeWindow, this);
|
|
|
|
|
jcf.lib.event.add(window, 'scroll', this.onScrollWindow, this);
|
|
|
|
|
jcf.lib.event.add(document, jcf.eventPress, this.onClickOutside, this);
|
|
|
|
|
this.positionDropdown();
|
|
|
|
|
},
|
|
|
|
|
hideDropdown: function(){
|
|
|
|
|
if(this.selectDrop.parentNode) {
|
|
|
|
|
this.selectDrop.parentNode.removeChild(this.selectDrop);
|
|
|
|
|
}
|
|
|
|
|
if(typeof this.origSelectedIndex === 'number') {
|
|
|
|
|
this.realElement.selectedIndex = this.origSelectedIndex;
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement,this.options.dropActiveClass);
|
|
|
|
|
jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
|
|
|
|
|
jcf.lib.event.remove(window, 'resize', this.onResizeWindow);
|
|
|
|
|
jcf.lib.event.remove(window, 'scroll', this.onScrollWindow);
|
|
|
|
|
jcf.lib.event.remove(document.documentElement, jcf.eventPress, this.onClickOutside);
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
this.onBlur();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
toggleDropdown: function(){
|
|
|
|
|
if(!this.realElement.disabled && this.realElement.options.length) {
|
|
|
|
|
if(jcf.isTouchDevice) {
|
|
|
|
|
this.onFocus();
|
|
|
|
|
} else {
|
|
|
|
|
this.realElement.focus();
|
|
|
|
|
}
|
|
|
|
|
if(this.isActiveDrop()) {
|
|
|
|
|
this.hideDropdown();
|
|
|
|
|
} else {
|
|
|
|
|
this.showDropdown();
|
|
|
|
|
}
|
|
|
|
|
this.refreshState();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
scrollToItem: function(){
|
|
|
|
|
if(this.isActiveDrop()) {
|
|
|
|
|
var dropHeight = this.selectList.offsetHeight;
|
|
|
|
|
var offsetTop = this.calcOptionOffset(this.getFakeActiveOption());
|
|
|
|
|
var sTop = this.selectList.scrollTop;
|
|
|
|
|
var oHeight = this.getFakeActiveOption().offsetHeight;
|
|
|
|
|
//offsetTop+=sTop;
|
|
|
|
|
|
|
|
|
|
if(offsetTop >= sTop + dropHeight) {
|
|
|
|
|
this.selectList.scrollTop = offsetTop - dropHeight + oHeight;
|
|
|
|
|
} else if(offsetTop < sTop) {
|
|
|
|
|
this.selectList.scrollTop = offsetTop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getFakeActiveOption: function(c) {
|
|
|
|
|
return jcf.lib.queryBySelector('li[rel="'+(typeof c === 'number' ? c : this.realElement.selectedIndex) +'"]',this.selectList)[0];
|
|
|
|
|
},
|
|
|
|
|
calcOptionOffset: function(fake) {
|
|
|
|
|
var h = 0;
|
|
|
|
|
var els = jcf.lib.queryBySelector('.jcfcalc',this.selectList);
|
|
|
|
|
for(var i = 0; i < els.length; i++) {
|
|
|
|
|
if(els[i] == fake) break;
|
|
|
|
|
h+=els[i].offsetHeight;
|
|
|
|
|
}
|
|
|
|
|
return h;
|
|
|
|
|
},
|
|
|
|
|
childrenHasItem: function(hold,item) {
|
|
|
|
|
var items = hold.getElementsByTagName('*');
|
|
|
|
|
for(i = 0; i < items.length; i++) {
|
|
|
|
|
if(items[i] == item) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
removeClassFromItems: function(className){
|
|
|
|
|
var children = jcf.lib.queryBySelector('li',this.selectList);
|
|
|
|
|
for(var i = children.length - 1; i >= 0; i--) {
|
|
|
|
|
jcf.lib.removeClass(children[i], className);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setSelectedClass: function(c){
|
|
|
|
|
var activeOption = this.getFakeActiveOption(c);
|
|
|
|
|
if(activeOption) {
|
|
|
|
|
jcf.lib.addClass(activeOption, this.options.selectedClass);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshSelectedClass: function(c){
|
|
|
|
|
if(!this.options.showNativeDrop) {
|
|
|
|
|
this.removeClassFromItems(this.options.selectedClass);
|
|
|
|
|
this.setSelectedClass(c);
|
|
|
|
|
}
|
|
|
|
|
if(this.realElement.disabled) {
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.addClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshSelectedText: function() {
|
|
|
|
|
if(!this.dropOpened && this.realElement.title) {
|
|
|
|
|
this.valueText.innerHTML = this.realElement.title;
|
|
|
|
|
} else {
|
|
|
|
|
var activeOption = this.realElement.options[this.realElement.selectedIndex];
|
|
|
|
|
if(activeOption) {
|
|
|
|
|
if(activeOption.title) {
|
|
|
|
|
var optImage = this.parseOptionTitle(this.realElement.options[this.realElement.selectedIndex].title);
|
|
|
|
|
this.valueText.innerHTML = (optImage ? '<img src="'+optImage+'" alt="" />' : '') + this.realElement.options[this.realElement.selectedIndex].innerHTML;
|
|
|
|
|
} else {
|
|
|
|
|
this.valueText.innerHTML = this.realElement.options[this.realElement.selectedIndex].innerHTML;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var selectedOption = this.realElement.options[this.realElement.selectedIndex];
|
|
|
|
|
if(selectedOption && selectedOption.className) {
|
|
|
|
|
this.fakeElement.setAttribute('data-option-class', jcf.lib.getAllClasses(selectedOption.className, 'option-').replace(/^\s+|\s+$/g, ''));
|
|
|
|
|
} else {
|
|
|
|
|
this.fakeElement.removeAttribute('data-option-class');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(){
|
|
|
|
|
this.origSelectedIndex = this.realElement.selectedIndex;
|
|
|
|
|
this.refreshSelectedClass();
|
|
|
|
|
this.refreshSelectedText();
|
|
|
|
|
if(!this.options.showNativeDrop) {
|
|
|
|
|
this.positionDropdown();
|
|
|
|
|
if(this.selectDrop.offsetWidth) {
|
|
|
|
|
this.scrollToItem();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// custom radio module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name:'radio',
|
|
|
|
|
selector: 'input[type="radio"]',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
wrapperClass:'rad-area',
|
|
|
|
|
focusClass:'rad-focus',
|
|
|
|
|
checkedClass:'rad-checked',
|
|
|
|
|
uncheckedClass:'rad-unchecked',
|
|
|
|
|
disabledClass:'rad-disabled',
|
|
|
|
|
radStructure:'<span></span>'
|
|
|
|
|
},
|
|
|
|
|
getRadioGroup: function(item){
|
|
|
|
|
var name = item.getAttribute('name');
|
|
|
|
|
if(name) {
|
|
|
|
|
return jcf.lib.queryBySelector('input[name="'+name+'"]', jcf.lib.getParent('form'));
|
|
|
|
|
} else {
|
|
|
|
|
return [item];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
|
|
|
|
|
this.fakeElement.innerHTML = this.options.radStructure;
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.addEvents();
|
|
|
|
|
},
|
|
|
|
|
addEvents: function(){
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, 'click', this.toggleRadio, this);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.event.add(this.labelFor, 'click', this.toggleRadio, this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onFocus: function(e) {
|
|
|
|
|
jcf.modules[this.name].superclass.onFocus.apply(this, arguments);
|
|
|
|
|
setTimeout(jcf.lib.bind(function(){
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},this),10);
|
|
|
|
|
},
|
|
|
|
|
toggleRadio: function(){
|
|
|
|
|
if(!this.realElement.disabled && !this.realElement.checked) {
|
|
|
|
|
this.realElement.checked = true;
|
|
|
|
|
jcf.lib.fireEvent(this.realElement, 'change');
|
|
|
|
|
}
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(){
|
|
|
|
|
var els = this.getRadioGroup(this.realElement);
|
|
|
|
|
for(var i = 0; i < els.length; i++) {
|
|
|
|
|
var curEl = els[i].jcf;
|
|
|
|
|
if(curEl) {
|
|
|
|
|
if(curEl.realElement.checked) {
|
|
|
|
|
jcf.lib.addClass(curEl.fakeElement, curEl.options.checkedClass);
|
|
|
|
|
jcf.lib.removeClass(curEl.fakeElement, curEl.options.uncheckedClass);
|
|
|
|
|
if(curEl.labelFor) {
|
|
|
|
|
jcf.lib.addClass(curEl.labelFor, curEl.options.labelActiveClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(curEl.fakeElement, curEl.options.checkedClass);
|
|
|
|
|
jcf.lib.addClass(curEl.fakeElement, curEl.options.uncheckedClass);
|
|
|
|
|
if(curEl.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(curEl.labelFor, curEl.options.labelActiveClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(curEl.realElement.disabled) {
|
|
|
|
|
jcf.lib.addClass(curEl.fakeElement, curEl.options.disabledClass);
|
|
|
|
|
if(curEl.labelFor) {
|
|
|
|
|
jcf.lib.addClass(curEl.labelFor, curEl.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(curEl.fakeElement, curEl.options.disabledClass);
|
|
|
|
|
if(curEl.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(curEl.labelFor, curEl.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// custom checkbox module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name:'checkbox',
|
|
|
|
|
selector:'input[type="checkbox"]',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
wrapperClass:'chk-area',
|
|
|
|
|
focusClass:'chk-focus',
|
|
|
|
|
checkedClass:'chk-checked',
|
|
|
|
|
labelActiveClass:'chk-label-active',
|
|
|
|
|
uncheckedClass:'chk-unchecked',
|
|
|
|
|
disabledClass:'chk-disabled',
|
|
|
|
|
chkStructure:'<span></span>'
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
|
|
|
|
|
this.fakeElement.innerHTML = this.options.chkStructure;
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'click', this.onRealClick, this);
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},
|
|
|
|
|
isLinkTarget: function(target, limitParent) {
|
|
|
|
|
while(target.parentNode || target === limitParent) {
|
|
|
|
|
if(target.tagName.toLowerCase() === 'a') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
target = target.parentNode;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onFakePressed: function() {
|
|
|
|
|
jcf.modules[this.name].superclass.onFakePressed.apply(this, arguments);
|
|
|
|
|
if(!this.realElement.disabled) {
|
|
|
|
|
this.realElement.focus();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onFakeClick: function(e) {
|
|
|
|
|
jcf.modules[this.name].superclass.onFakeClick.apply(this, arguments);
|
|
|
|
|
this.tmpTimer = setTimeout(jcf.lib.bind(function(){
|
|
|
|
|
this.toggle();
|
|
|
|
|
},this),10);
|
|
|
|
|
if(!this.isLinkTarget(e.target, this.labelFor)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onRealClick: function(e) {
|
|
|
|
|
setTimeout(jcf.lib.bind(function(){
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},this),10);
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
},
|
|
|
|
|
toggle: function(e){
|
|
|
|
|
if(!this.realElement.disabled) {
|
|
|
|
|
if(this.realElement.checked) {
|
|
|
|
|
this.realElement.checked = false;
|
|
|
|
|
} else {
|
|
|
|
|
this.realElement.checked = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.refreshState();
|
|
|
|
|
jcf.lib.fireEvent(this.realElement, 'change');
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(){
|
|
|
|
|
if(this.realElement.checked) {
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.checkedClass);
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.uncheckedClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.addClass(this.labelFor, this.options.labelActiveClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.checkedClass);
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.uncheckedClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(this.labelFor, this.options.labelActiveClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.realElement.disabled) {
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.addClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2016-03-16 17:30:07 +05:00
|
|
|
|
|
|
|
|
|
// custom scrollbars module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name:'customscroll',
|
|
|
|
|
selector:'div.scrollable-area',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
alwaysPreventWheel: false,
|
|
|
|
|
enableMouseWheel: true,
|
|
|
|
|
captureFocus: false,
|
|
|
|
|
handleNested: true,
|
|
|
|
|
alwaysKeepScrollbars: false,
|
|
|
|
|
autoDetectWidth: false,
|
|
|
|
|
scrollbarOptions: {},
|
|
|
|
|
focusClass:'scrollable-focus',
|
|
|
|
|
wrapperTag: 'div',
|
|
|
|
|
autoDetectWidthClass: 'autodetect-width',
|
|
|
|
|
noHorizontalBarClass:'noscroll-horizontal',
|
|
|
|
|
noVerticalBarClass:'noscroll-vertical',
|
|
|
|
|
innerWrapperClass:'scrollable-inner-wrapper',
|
|
|
|
|
outerWrapperClass:'scrollable-area-wrapper',
|
|
|
|
|
horizontalClass: 'hscrollable',
|
|
|
|
|
verticalClass: 'vscrollable',
|
|
|
|
|
bothClass: 'anyscrollable'
|
|
|
|
|
},
|
|
|
|
|
replaceObject: function(){
|
|
|
|
|
this.initStructure();
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.addEvents();
|
|
|
|
|
},
|
|
|
|
|
initStructure: function(){
|
|
|
|
|
// set scroll type
|
|
|
|
|
this.realElement.jcf = this;
|
|
|
|
|
if(jcf.lib.hasClass(this.realElement, this.options.bothClass) ||
|
|
|
|
|
jcf.lib.hasClass(this.realElement, this.options.horizontalClass) && jcf.lib.hasClass(this.realElement, this.options.verticalClass)) {
|
|
|
|
|
this.scrollType = 'both';
|
|
|
|
|
} else if(jcf.lib.hasClass(this.realElement, this.options.horizontalClass)) {
|
|
|
|
|
this.scrollType = 'horizontal';
|
|
|
|
|
} else {
|
|
|
|
|
this.scrollType = 'vertical';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// autodetect horizontal width
|
|
|
|
|
if(jcf.lib.hasClass(this.realElement,this.options.autoDetectWidthClass)) {
|
|
|
|
|
this.options.autoDetectWidth = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// init dimensions and build structure
|
|
|
|
|
this.realElement.style.position = 'relative';
|
|
|
|
|
this.realElement.style.overflow = 'hidden';
|
|
|
|
|
|
|
|
|
|
// build content wrapper and scrollbar(s)
|
|
|
|
|
this.buildWrapper();
|
|
|
|
|
this.buildScrollbars();
|
|
|
|
|
},
|
|
|
|
|
buildWrapper: function() {
|
|
|
|
|
this.outerWrapper = document.createElement(this.options.wrapperTag);
|
|
|
|
|
this.outerWrapper.className = this.options.outerWrapperClass;
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.outerWrapper, this.realElement);
|
|
|
|
|
this.outerWrapper.appendChild(this.realElement);
|
|
|
|
|
|
|
|
|
|
// autosize content if single child
|
|
|
|
|
if(this.options.autoDetectWidth && (this.scrollType === 'both' || this.scrollType === 'horizontal') && this.realElement.children.length === 1) {
|
|
|
|
|
var tmpWidth = 0;
|
|
|
|
|
this.realElement.style.width = '99999px';
|
|
|
|
|
tmpWidth = this.realElement.children[0].offsetWidth;
|
|
|
|
|
this.realElement.style.width = '';
|
|
|
|
|
if(tmpWidth) {
|
|
|
|
|
this.realElement.children[0].style.width = tmpWidth+'px';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
buildScrollbars: function() {
|
|
|
|
|
if(this.scrollType === 'horizontal' || this.scrollType === 'both') {
|
|
|
|
|
this.hScrollBar = new jcf.plugins.scrollbar(jcf.lib.extend(this.options.scrollbarOptions,{
|
|
|
|
|
vertical: false,
|
|
|
|
|
spawnClass: this,
|
|
|
|
|
holder: this.outerWrapper,
|
|
|
|
|
range: this.realElement.scrollWidth - this.realElement.offsetWidth,
|
|
|
|
|
size: this.realElement.offsetWidth,
|
|
|
|
|
onScroll: jcf.lib.bind(function(v) {
|
|
|
|
|
this.realElement.scrollLeft = v;
|
|
|
|
|
},this)
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
if(this.scrollType === 'vertical' || this.scrollType === 'both') {
|
|
|
|
|
this.vScrollBar = new jcf.plugins.scrollbar(jcf.lib.extend(this.options.scrollbarOptions,{
|
|
|
|
|
vertical: true,
|
|
|
|
|
spawnClass: this,
|
|
|
|
|
holder: this.outerWrapper,
|
|
|
|
|
range: this.realElement.scrollHeight - this.realElement.offsetHeight,
|
|
|
|
|
size: this.realElement.offsetHeight,
|
|
|
|
|
onScroll: jcf.lib.bind(function(v) {
|
|
|
|
|
this.realElement.scrollTop = v;
|
|
|
|
|
},this)
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
this.outerWrapper.style.width = this.realElement.offsetWidth + 'px';
|
|
|
|
|
this.outerWrapper.style.height = this.realElement.offsetHeight + 'px';
|
|
|
|
|
this.resizeScrollContent();
|
|
|
|
|
},
|
|
|
|
|
resizeScrollContent: function() {
|
|
|
|
|
var diffWidth = this.realElement.offsetWidth - jcf.lib.getInnerWidth(this.realElement);
|
|
|
|
|
var diffHeight = this.realElement.offsetHeight - jcf.lib.getInnerHeight(this.realElement);
|
|
|
|
|
this.realElement.style.width = Math.max(0, this.outerWrapper.offsetWidth - diffWidth - (this.vScrollBar ? this.vScrollBar.getScrollBarSize() : 0)) + 'px';
|
|
|
|
|
this.realElement.style.height = Math.max(0, this.outerWrapper.offsetHeight - diffHeight - (this.hScrollBar ? this.hScrollBar.getScrollBarSize() : 0)) + 'px';
|
|
|
|
|
},
|
|
|
|
|
addEvents: function() {
|
|
|
|
|
// enable mouse wheel handling
|
|
|
|
|
if(!jcf.isTouchDevice && this.options.enableMouseWheel) {
|
|
|
|
|
jcf.lib.event.add(this.outerWrapper, 'mousewheel', this.onMouseWheel, this);
|
|
|
|
|
}
|
|
|
|
|
// add touch scroll on block body
|
|
|
|
|
if(jcf.isTouchDevice || navigator.msPointerEnabled || navigator.pointerEnabled) {
|
|
|
|
|
this.outerWrapper.style.msTouchAction = 'none';
|
|
|
|
|
jcf.lib.event.add(this.realElement, jcf.eventPress, this.onScrollablePress, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handle nested scrollbars
|
|
|
|
|
if(this.options.handleNested) {
|
|
|
|
|
var el = this.realElement, name = this.name;
|
|
|
|
|
while(el.parentNode) {
|
|
|
|
|
if(el.parentNode.jcf && el.parentNode.jcf.name == name) {
|
|
|
|
|
el.parentNode.jcf.refreshState();
|
|
|
|
|
}
|
|
|
|
|
el = el.parentNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
isTouchPointerEvent: function(e) {
|
|
|
|
|
return (e.type.indexOf('touch') > -1) ||
|
|
|
|
|
(navigator.pointerEnabled && e.pointerType === 'touch') ||
|
|
|
|
|
(navigator.msPointerEnabled && e.pointerType === e.MSPOINTER_TYPE_TOUCH);
|
|
|
|
|
},
|
|
|
|
|
onMouseWheel: function(e) {
|
|
|
|
|
if(this.scrollType === 'vertical' || this.scrollType === 'both') {
|
|
|
|
|
return this.vScrollBar.doScrollWheelStep(e.mWheelDelta) === false ? false : !this.options.alwaysPreventWheel;
|
|
|
|
|
} else {
|
|
|
|
|
return this.hScrollBar.doScrollWheelStep(e.mWheelDelta) === false ? false : !this.options.alwaysPreventWheel;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onScrollablePress: function(e) {
|
|
|
|
|
if(!this.isTouchPointerEvent(e)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.preventFlag = true;
|
|
|
|
|
this.origWindowScrollTop = jcf.lib.getScrollTop();
|
|
|
|
|
this.origWindowScrollLeft = jcf.lib.getScrollLeft();
|
|
|
|
|
|
|
|
|
|
this.scrollableOffset = jcf.lib.getOffset(this.realElement);
|
|
|
|
|
if(this.hScrollBar) {
|
|
|
|
|
this.scrollableTouchX = (e.changedTouches ? e.changedTouches[0] : e).pageX;
|
|
|
|
|
this.origValueX = this.hScrollBar.getScrollValue();
|
|
|
|
|
}
|
|
|
|
|
if(this.vScrollBar) {
|
|
|
|
|
this.scrollableTouchY = (e.changedTouches ? e.changedTouches[0] : e).pageY;
|
|
|
|
|
this.origValueY = this.vScrollBar.getScrollValue();
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.event.add(this.realElement, jcf.eventMove, this.onScrollableMove, this);
|
|
|
|
|
jcf.lib.event.add(this.realElement, jcf.eventRelease, this.onScrollableRelease, this);
|
|
|
|
|
},
|
|
|
|
|
onScrollableMove: function(e) {
|
|
|
|
|
if(this.vScrollBar) {
|
|
|
|
|
var difY = (e.changedTouches ? e.changedTouches[0] : e).pageY - this.scrollableTouchY;
|
|
|
|
|
var valY = this.origValueY-difY;
|
|
|
|
|
this.vScrollBar.scrollTo(valY);
|
|
|
|
|
if(valY < 0 || valY > this.vScrollBar.options.range) {
|
|
|
|
|
this.preventFlag = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.hScrollBar) {
|
|
|
|
|
var difX = (e.changedTouches ? e.changedTouches[0] : e).pageX - this.scrollableTouchX;
|
|
|
|
|
var valX = this.origValueX-difX;
|
|
|
|
|
this.hScrollBar.scrollTo(valX);
|
|
|
|
|
if(valX < 0 || valX > this.hScrollBar.options.range) {
|
|
|
|
|
this.preventFlag = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.preventFlag) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onScrollableRelease: function() {
|
|
|
|
|
jcf.lib.event.remove(this.realElement, jcf.eventMove, this.onScrollableMove);
|
|
|
|
|
jcf.lib.event.remove(this.realElement, jcf.eventRelease, this.onScrollableRelease);
|
|
|
|
|
},
|
|
|
|
|
refreshState: function() {
|
|
|
|
|
if(this.options.alwaysKeepScrollbars) {
|
|
|
|
|
if(this.hScrollBar) this.hScrollBar.scrollBar.style.display = 'block';
|
|
|
|
|
if(this.vScrollBar) this.vScrollBar.scrollBar.style.display = 'block';
|
|
|
|
|
} else {
|
|
|
|
|
if(this.hScrollBar) {
|
|
|
|
|
if(this.getScrollRange(false)) {
|
|
|
|
|
this.hScrollBar.scrollBar.style.display = 'block';
|
|
|
|
|
this.resizeScrollContent();
|
|
|
|
|
this.hScrollBar.setRange(this.getScrollRange(false));
|
|
|
|
|
} else {
|
|
|
|
|
this.hScrollBar.scrollBar.style.display = 'none';
|
|
|
|
|
this.realElement.style.width = this.outerWrapper.style.width;
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.toggleClass(this.outerWrapper, this.options.noHorizontalBarClass, this.hScrollBar.options.range === 0);
|
|
|
|
|
}
|
|
|
|
|
if(this.vScrollBar) {
|
|
|
|
|
if(this.getScrollRange(true) > 0) {
|
|
|
|
|
this.vScrollBar.scrollBar.style.display = 'block';
|
|
|
|
|
this.resizeScrollContent();
|
|
|
|
|
this.vScrollBar.setRange(this.getScrollRange(true));
|
|
|
|
|
} else {
|
|
|
|
|
this.vScrollBar.scrollBar.style.display = 'none';
|
|
|
|
|
this.realElement.style.width = this.outerWrapper.style.width;
|
|
|
|
|
}
|
|
|
|
|
jcf.lib.toggleClass(this.outerWrapper, this.options.noVerticalBarClass, this.vScrollBar.options.range === 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.vScrollBar) {
|
|
|
|
|
this.vScrollBar.setRange(this.realElement.scrollHeight - this.realElement.offsetHeight);
|
|
|
|
|
this.vScrollBar.setSize(this.realElement.offsetHeight);
|
|
|
|
|
this.vScrollBar.scrollTo(this.realElement.scrollTop);
|
|
|
|
|
}
|
|
|
|
|
if(this.hScrollBar) {
|
|
|
|
|
this.hScrollBar.setRange(this.realElement.scrollWidth - this.realElement.offsetWidth);
|
|
|
|
|
this.hScrollBar.setSize(this.realElement.offsetWidth);
|
|
|
|
|
this.hScrollBar.scrollTo(this.realElement.scrollLeft);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getScrollRange: function(isVertical) {
|
|
|
|
|
if(isVertical) {
|
|
|
|
|
return this.realElement.scrollHeight - this.realElement.offsetHeight;
|
|
|
|
|
} else {
|
|
|
|
|
return this.realElement.scrollWidth - this.realElement.offsetWidth;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getCurrentRange: function(scrollInstance) {
|
|
|
|
|
return this.getScrollRange(scrollInstance.isVertical);
|
|
|
|
|
},
|
|
|
|
|
onCreateModule: function(){
|
|
|
|
|
if(jcf.modules.select) {
|
|
|
|
|
this.extendSelect();
|
|
|
|
|
}
|
|
|
|
|
if(jcf.modules.selectmultiple) {
|
|
|
|
|
this.extendSelectMultiple();
|
|
|
|
|
}
|
|
|
|
|
if(jcf.modules.textarea) {
|
|
|
|
|
this.extendTextarea();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onModuleAdded: function(module){
|
|
|
|
|
if(module.prototype.name == 'select') {
|
|
|
|
|
this.extendSelect();
|
|
|
|
|
}
|
|
|
|
|
if(module.prototype.name == 'selectmultiple') {
|
|
|
|
|
this.extendSelectMultiple();
|
|
|
|
|
}
|
|
|
|
|
if(module.prototype.name == 'textarea') {
|
|
|
|
|
this.extendTextarea();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
extendSelect: function() {
|
|
|
|
|
// add scrollable if needed on control ready
|
|
|
|
|
jcf.modules.select.prototype.onControlReady = function(obj){
|
|
|
|
|
if(obj.selectList.scrollHeight > obj.selectList.offsetHeight) {
|
|
|
|
|
obj.jcfScrollable = new jcf.modules.customscroll({
|
|
|
|
|
alwaysPreventWheel: true,
|
|
|
|
|
replaces:obj.selectList
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// update scroll function
|
|
|
|
|
var orig = jcf.modules.select.prototype.scrollToItem;
|
|
|
|
|
jcf.modules.select.prototype.scrollToItem = function(){
|
|
|
|
|
orig.apply(this);
|
|
|
|
|
if(this.jcfScrollable) {
|
|
|
|
|
this.jcfScrollable.refreshState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
extendTextarea: function() {
|
|
|
|
|
// add scrollable if needed on control ready
|
|
|
|
|
jcf.modules.textarea.prototype.onControlReady = function(obj){
|
|
|
|
|
obj.jcfScrollable = new jcf.modules.customscroll({
|
|
|
|
|
alwaysKeepScrollbars: true,
|
|
|
|
|
alwaysPreventWheel: true,
|
|
|
|
|
replaces: obj.realElement
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// update scroll function
|
|
|
|
|
var orig = jcf.modules.textarea.prototype.refreshState;
|
|
|
|
|
jcf.modules.textarea.prototype.refreshState = function(){
|
|
|
|
|
orig.apply(this);
|
|
|
|
|
if(this.jcfScrollable) {
|
|
|
|
|
this.jcfScrollable.refreshState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
extendSelectMultiple: function(){
|
|
|
|
|
// add scrollable if needed on control ready
|
|
|
|
|
jcf.modules.selectmultiple.prototype.onControlReady = function(obj){
|
|
|
|
|
//if(obj.optionsHolder.scrollHeight > obj.optionsHolder.offsetHeight) {
|
|
|
|
|
obj.jcfScrollable = new jcf.modules.customscroll({
|
|
|
|
|
alwaysPreventWheel: true,
|
|
|
|
|
replaces:obj.optionsHolder
|
|
|
|
|
});
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
// update scroll function
|
|
|
|
|
var orig = jcf.modules.selectmultiple.prototype.scrollToItem;
|
|
|
|
|
jcf.modules.selectmultiple.prototype.scrollToItem = function(){
|
|
|
|
|
orig.apply(this);
|
|
|
|
|
if(this.jcfScrollable) {
|
|
|
|
|
this.jcfScrollable.refreshState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update scroll size?
|
|
|
|
|
var orig2 = jcf.modules.selectmultiple.prototype.rebuildOptions;
|
|
|
|
|
jcf.modules.selectmultiple.prototype.rebuildOptions = function(){
|
|
|
|
|
orig2.apply(this);
|
|
|
|
|
if(this.jcfScrollable) {
|
|
|
|
|
this.jcfScrollable.refreshState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// scrollbar plugin
|
|
|
|
|
jcf.addPlugin({
|
|
|
|
|
name: 'scrollbar',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
size: 0,
|
|
|
|
|
range: 0,
|
|
|
|
|
moveStep: 6,
|
|
|
|
|
moveDistance: 50,
|
|
|
|
|
moveInterval: 10,
|
|
|
|
|
trackHoldDelay: 900,
|
|
|
|
|
holder: null,
|
|
|
|
|
vertical: true,
|
|
|
|
|
scrollTag: 'div',
|
|
|
|
|
onScroll: function(){},
|
|
|
|
|
onScrollEnd: function(){},
|
|
|
|
|
onScrollStart: function(){},
|
|
|
|
|
disabledClass: 'btn-disabled',
|
|
|
|
|
VscrollBarClass:'vscrollbar',
|
|
|
|
|
VscrollStructure: '<div class="vscroll-up"></div><div class="vscroll-line"><div class="vscroll-slider"><div class="scroll-bar-top"></div><div class="scroll-bar-bottom"></div></div></div></div><div class="vscroll-down"></div>',
|
|
|
|
|
VscrollTrack: 'div.vscroll-line',
|
|
|
|
|
VscrollBtnDecClass:'div.vscroll-up',
|
|
|
|
|
VscrollBtnIncClass:'div.vscroll-down',
|
|
|
|
|
VscrollSliderClass:'div.vscroll-slider',
|
|
|
|
|
HscrollBarClass:'hscrollbar',
|
|
|
|
|
HscrollStructure: '<div class="hscroll-left"></div><div class="hscroll-line"><div class="hscroll-slider"><div class="scroll-bar-left"></div><div class="scroll-bar-right"></div></div></div></div><div class="hscroll-right"></div>',
|
|
|
|
|
HscrollTrack: 'div.hscroll-line',
|
|
|
|
|
HscrollBtnDecClass:'div.hscroll-left',
|
|
|
|
|
HscrollBtnIncClass:'div.hscroll-right',
|
|
|
|
|
HscrollSliderClass:'div.hscroll-slider'
|
|
|
|
|
},
|
|
|
|
|
init: function(userOptions) {
|
|
|
|
|
this.setOptions(userOptions);
|
|
|
|
|
this.createScrollBar();
|
|
|
|
|
this.attachEvents();
|
|
|
|
|
this.setSize();
|
|
|
|
|
},
|
|
|
|
|
setOptions: function(extOptions) {
|
|
|
|
|
// merge options
|
|
|
|
|
this.options = jcf.lib.extend({}, this.defaultOptions, extOptions);
|
|
|
|
|
this.isVertical = this.options.vertical;
|
|
|
|
|
this.prefix = this.isVertical ? 'V' : 'H';
|
|
|
|
|
this.eventPageOffsetProperty = this.isVertical ? 'pageY' : 'pageX';
|
|
|
|
|
this.positionProperty = this.isVertical ? 'top' : 'left';
|
|
|
|
|
this.sizeProperty = this.isVertical ? 'height' : 'width';
|
|
|
|
|
this.dimenionsProperty = this.isVertical ? 'offsetHeight' : 'offsetWidth';
|
|
|
|
|
this.invertedDimenionsProperty = !this.isVertical ? 'offsetHeight' : 'offsetWidth';
|
|
|
|
|
|
|
|
|
|
// set corresponding classes
|
|
|
|
|
for(var p in this.options) {
|
|
|
|
|
if(p.indexOf(this.prefix) == 0) {
|
|
|
|
|
this.options[p.substr(1)] = this.options[p];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
createScrollBar: function() {
|
|
|
|
|
// create dimensions
|
|
|
|
|
this.scrollBar = document.createElement(this.options.scrollTag);
|
|
|
|
|
this.scrollBar.className = this.options.scrollBarClass;
|
|
|
|
|
this.scrollBar.innerHTML = this.options.scrollStructure;
|
|
|
|
|
|
|
|
|
|
// get elements
|
|
|
|
|
this.track = jcf.lib.queryBySelector(this.options.scrollTrack,this.scrollBar)[0];
|
|
|
|
|
this.btnDec = jcf.lib.queryBySelector(this.options.scrollBtnDecClass,this.scrollBar)[0];
|
|
|
|
|
this.btnInc = jcf.lib.queryBySelector(this.options.scrollBtnIncClass,this.scrollBar)[0];
|
|
|
|
|
this.slider = jcf.lib.queryBySelector(this.options.scrollSliderClass,this.scrollBar)[0];
|
|
|
|
|
this.slider.style.position = 'absolute';
|
|
|
|
|
this.track.style.position = 'relative';
|
|
|
|
|
},
|
|
|
|
|
attachEvents: function() {
|
|
|
|
|
// append scrollbar to holder if provided
|
|
|
|
|
if(this.options.holder) {
|
|
|
|
|
this.options.holder.appendChild(this.scrollBar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// attach listeners for slider and buttons
|
|
|
|
|
jcf.lib.event.add(this.slider, jcf.eventPress, this.onSliderPressed, this);
|
|
|
|
|
jcf.lib.event.add(this.btnDec, jcf.eventPress, this.onBtnDecPressed, this);
|
|
|
|
|
jcf.lib.event.add(this.btnInc, jcf.eventPress, this.onBtnIncPressed, this);
|
|
|
|
|
jcf.lib.event.add(this.track, jcf.eventPress, this.onTrackPressed, this);
|
|
|
|
|
},
|
|
|
|
|
setSize: function(value) {
|
|
|
|
|
if(typeof value === 'number') {
|
|
|
|
|
this.options.size = value;
|
|
|
|
|
}
|
|
|
|
|
this.scrollOffset = this.scrollValue = this.sliderOffset = 0;
|
|
|
|
|
this.scrollBar.style[this.sizeProperty] = this.options.size + 'px';
|
|
|
|
|
this.resizeControls();
|
|
|
|
|
this.refreshSlider();
|
|
|
|
|
},
|
|
|
|
|
setRange: function(r) {
|
|
|
|
|
this.options.range = Math.max(r,0);
|
|
|
|
|
this.resizeControls();
|
|
|
|
|
},
|
|
|
|
|
doScrollWheelStep: function(direction) {
|
|
|
|
|
// 1 - scroll up, -1 scroll down
|
|
|
|
|
this.startScroll();
|
|
|
|
|
if((direction < 0 && !this.isEndPosition()) || (direction > 0 && !this.isStartPosition())) {
|
|
|
|
|
this.scrollTo(this.getScrollValue()-this.options.moveDistance * direction);
|
|
|
|
|
this.moveScroll();
|
|
|
|
|
this.endScroll();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
resizeControls: function() {
|
|
|
|
|
// calculate dimensions
|
|
|
|
|
this.barSize = this.scrollBar[this.dimenionsProperty];
|
|
|
|
|
this.btnDecSize = this.btnDec[this.dimenionsProperty];
|
|
|
|
|
this.btnIncSize = this.btnInc[this.dimenionsProperty];
|
|
|
|
|
this.trackSize = Math.max(0, this.barSize - this.btnDecSize - this.btnIncSize);
|
|
|
|
|
|
|
|
|
|
// resize and reposition elements
|
|
|
|
|
this.track.style[this.sizeProperty] = this.trackSize + 'px';
|
|
|
|
|
this.trackSize = this.track[this.dimenionsProperty];
|
|
|
|
|
this.sliderSize = this.getSliderSize();
|
|
|
|
|
this.slider.style[this.sizeProperty] = this.sliderSize + 'px';
|
|
|
|
|
this.sliderSize = this.slider[this.dimenionsProperty];
|
|
|
|
|
},
|
|
|
|
|
refreshSlider: function(complete) {
|
|
|
|
|
// refresh dimensions
|
|
|
|
|
if(complete) {
|
|
|
|
|
this.resizeControls();
|
|
|
|
|
}
|
|
|
|
|
// redraw slider and classes
|
|
|
|
|
this.sliderOffset = isNaN(this.sliderOffset) ? 0 : this.sliderOffset;
|
|
|
|
|
this.slider.style[this.positionProperty] = this.sliderOffset + 'px';
|
|
|
|
|
},
|
|
|
|
|
startScroll: function() {
|
|
|
|
|
// refresh range if possible
|
|
|
|
|
if(this.options.spawnClass && typeof this.options.spawnClass.getCurrentRange === 'function') {
|
|
|
|
|
this.setRange(this.options.spawnClass.getCurrentRange(this));
|
|
|
|
|
}
|
|
|
|
|
this.resizeControls();
|
|
|
|
|
this.scrollBarOffset = jcf.lib.getOffset(this.track)[this.positionProperty];
|
|
|
|
|
this.options.onScrollStart();
|
|
|
|
|
},
|
|
|
|
|
moveScroll: function() {
|
|
|
|
|
this.options.onScroll(this.scrollValue);
|
|
|
|
|
|
|
|
|
|
// add disabled classes
|
|
|
|
|
jcf.lib.removeClass(this.btnDec, this.options.disabledClass);
|
|
|
|
|
jcf.lib.removeClass(this.btnInc, this.options.disabledClass);
|
|
|
|
|
if(this.scrollValue === 0) {
|
|
|
|
|
jcf.lib.addClass(this.btnDec, this.options.disabledClass);
|
|
|
|
|
}
|
|
|
|
|
if(this.scrollValue === this.options.range) {
|
|
|
|
|
jcf.lib.addClass(this.btnInc, this.options.disabledClass);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
endScroll: function() {
|
|
|
|
|
this.options.onScrollEnd();
|
|
|
|
|
},
|
|
|
|
|
startButtonMoveScroll: function(direction) {
|
|
|
|
|
this.startScroll();
|
|
|
|
|
clearInterval(this.buttonScrollTimer);
|
|
|
|
|
this.buttonScrollTimer = setInterval(jcf.lib.bind(function(){
|
|
|
|
|
this.scrollValue += this.options.moveStep * direction
|
|
|
|
|
if(this.scrollValue > this.options.range) {
|
|
|
|
|
this.scrollValue = this.options.range;
|
|
|
|
|
this.endButtonMoveScroll();
|
|
|
|
|
} else if(this.scrollValue < 0) {
|
|
|
|
|
this.scrollValue = 0;
|
|
|
|
|
this.endButtonMoveScroll();
|
|
|
|
|
}
|
|
|
|
|
this.scrollTo(this.scrollValue);
|
|
|
|
|
|
|
|
|
|
},this),this.options.moveInterval);
|
|
|
|
|
},
|
|
|
|
|
endButtonMoveScroll: function() {
|
|
|
|
|
clearInterval(this.buttonScrollTimer);
|
|
|
|
|
this.endScroll();
|
|
|
|
|
},
|
|
|
|
|
isStartPosition: function() {
|
|
|
|
|
return this.scrollValue === 0;
|
|
|
|
|
},
|
|
|
|
|
isEndPosition: function() {
|
|
|
|
|
return this.scrollValue === this.options.range;
|
|
|
|
|
},
|
|
|
|
|
getSliderSize: function() {
|
|
|
|
|
return Math.round(this.getSliderSizePercent() * this.trackSize / 100);
|
|
|
|
|
},
|
|
|
|
|
getSliderSizePercent: function() {
|
|
|
|
|
return this.options.range === 0 ? 0 : this.barSize * 100 / (this.barSize + this.options.range);
|
|
|
|
|
},
|
|
|
|
|
getSliderOffsetByScrollValue: function() {
|
|
|
|
|
return (this.scrollValue * 100 / this.options.range) * (this.trackSize - this.sliderSize) / 100;
|
|
|
|
|
},
|
|
|
|
|
getSliderOffsetPercent: function() {
|
|
|
|
|
return this.sliderOffset * 100 / (this.trackSize - this.sliderSize);
|
|
|
|
|
},
|
|
|
|
|
getScrollValueBySliderOffset: function() {
|
|
|
|
|
return this.getSliderOffsetPercent() * this.options.range / 100;
|
|
|
|
|
},
|
|
|
|
|
getScrollBarSize: function() {
|
|
|
|
|
return this.scrollBar[this.invertedDimenionsProperty];
|
|
|
|
|
},
|
|
|
|
|
getScrollValue: function() {
|
|
|
|
|
return this.scrollValue || 0;
|
|
|
|
|
},
|
|
|
|
|
scrollOnePage: function(direction) {
|
|
|
|
|
this.scrollTo(this.scrollValue + direction*this.barSize);
|
|
|
|
|
},
|
|
|
|
|
scrollTo: function(x) {
|
|
|
|
|
this.scrollValue = x < 0 ? 0 : x > this.options.range ? this.options.range : x;
|
|
|
|
|
this.sliderOffset = this.getSliderOffsetByScrollValue();
|
|
|
|
|
this.refreshSlider();
|
|
|
|
|
this.moveScroll();
|
|
|
|
|
},
|
|
|
|
|
onSliderPressed: function(e){
|
|
|
|
|
jcf.lib.event.add(document.body, jcf.eventRelease, this.onSliderRelease, this);
|
|
|
|
|
jcf.lib.event.add(document.body, jcf.eventMove, this.onSliderMove, this);
|
|
|
|
|
jcf.lib.disableTextSelection(this.slider);
|
|
|
|
|
|
|
|
|
|
// calculate offsets once
|
|
|
|
|
this.sliderInnerOffset = (e.changedTouches ? e.changedTouches[0] : e)[this.eventPageOffsetProperty] - jcf.lib.getOffset(this.slider)[this.positionProperty];
|
|
|
|
|
this.startScroll();
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
onSliderRelease: function(){
|
|
|
|
|
jcf.lib.event.remove(document.body, jcf.eventRelease, this.onSliderRelease);
|
|
|
|
|
jcf.lib.event.remove(document.body, jcf.eventMove, this.onSliderMove);
|
|
|
|
|
},
|
|
|
|
|
onSliderMove: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
this.sliderOffset = (e.changedTouches ? e.changedTouches[0] : e)[this.eventPageOffsetProperty] - this.scrollBarOffset - this.sliderInnerOffset;
|
|
|
|
|
if(this.sliderOffset < 0) {
|
|
|
|
|
this.sliderOffset = 0;
|
|
|
|
|
} else if(this.sliderOffset + this.sliderSize > this.trackSize) {
|
|
|
|
|
this.sliderOffset = this.trackSize - this.sliderSize;
|
|
|
|
|
}
|
|
|
|
|
if(this.previousOffset != this.sliderOffset) {
|
|
|
|
|
this.previousOffset = this.sliderOffset;
|
|
|
|
|
this.scrollTo(this.getScrollValueBySliderOffset());
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onBtnIncPressed: function() {
|
|
|
|
|
jcf.lib.event.add(document.body, jcf.eventRelease, this.onBtnIncRelease, this);
|
|
|
|
|
jcf.lib.disableTextSelection(this.btnInc);
|
|
|
|
|
this.startButtonMoveScroll(1);
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
onBtnIncRelease: function() {
|
|
|
|
|
jcf.lib.event.remove(document.body, jcf.eventRelease, this.onBtnIncRelease);
|
|
|
|
|
this.endButtonMoveScroll();
|
|
|
|
|
},
|
|
|
|
|
onBtnDecPressed: function() {
|
|
|
|
|
jcf.lib.event.add(document.body, jcf.eventRelease, this.onBtnDecRelease, this);
|
|
|
|
|
jcf.lib.disableTextSelection(this.btnDec);
|
|
|
|
|
this.startButtonMoveScroll(-1);
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
onBtnDecRelease: function() {
|
|
|
|
|
jcf.lib.event.remove(document.body, jcf.eventRelease, this.onBtnDecRelease);
|
|
|
|
|
this.endButtonMoveScroll();
|
|
|
|
|
},
|
|
|
|
|
onTrackPressed: function(e) {
|
|
|
|
|
var position = e[this.eventPageOffsetProperty] - jcf.lib.getOffset(this.track)[this.positionProperty];
|
|
|
|
|
var direction = position < this.sliderOffset ? -1 : position > this.sliderOffset + this.sliderSize ? 1 : 0;
|
|
|
|
|
if(direction) {
|
|
|
|
|
this.scrollOnePage(direction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2016-03-28 20:07:51 +05:00
|
|
|
|
// custom upload field module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name: 'file',
|
|
|
|
|
selector: 'input[type="file"]',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
buttonWidth: 30,
|
|
|
|
|
bigFontSize: 1,
|
|
|
|
|
buttonText:'Browse',
|
|
|
|
|
wrapperClass:'file-area',
|
|
|
|
|
focusClass:'file-focus',
|
|
|
|
|
disabledClass:'file-disabled',
|
|
|
|
|
opacityClass:'file-input-opacity',
|
|
|
|
|
noFileClass:'no-file',
|
|
|
|
|
extPrefixClass:'extension-',
|
|
|
|
|
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>',
|
|
|
|
|
uploadFileNameSelector:'label.jcf-fake-input span em',
|
|
|
|
|
uploadButtonSelector:'a.jcf-upload-button span',
|
|
|
|
|
inputWrapper: 'div.jcf-wrap'
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
|
|
|
|
|
this.fakeElement.innerHTML = this.options.uploadStructure;
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
|
|
|
|
|
this.fileNameInput = jcf.lib.queryBySelector(this.options.uploadFileNameSelector ,this.fakeElement)[0];
|
|
|
|
|
this.uploadButton = jcf.lib.queryBySelector(this.options.uploadButtonSelector ,this.fakeElement)[0];
|
|
|
|
|
this.inputWrapper = jcf.lib.queryBySelector(this.options.inputWrapper ,this.fakeElement)[0];
|
|
|
|
|
|
|
|
|
|
this.origElem = jcf.lib.nextSibling(this.realElement);
|
|
|
|
|
if(this.origElem && this.origElem.className.indexOf('file-input-text') > -1) {
|
|
|
|
|
this.origElem.parentNode.removeChild(this.origElem);
|
|
|
|
|
this.origTitle = this.origElem.innerHTML;
|
|
|
|
|
this.fileNameInput.innerHTML = this.origTitle;
|
|
|
|
|
}
|
|
|
|
|
this.uploadButton.innerHTML = this.realElement.title || this.options.buttonText;
|
|
|
|
|
this.realElement.removeAttribute('title');
|
|
|
|
|
this.fakeElement.style.position = 'relative';
|
|
|
|
|
this.realElement.style.position = 'absolute';
|
|
|
|
|
this.realElement.style.zIndex = 100;
|
|
|
|
|
this.inputWrapper.appendChild(this.realElement);
|
|
|
|
|
this.oTop = this.oLeft = this.oWidth = this.oHeight = 0;
|
|
|
|
|
|
|
|
|
|
jcf.lib.addClass(this.realElement, this.options.opacityClass);
|
|
|
|
|
jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
|
|
|
|
|
this.inputWrapper.style.width = this.inputWrapper.parentNode.offsetWidth+'px';
|
|
|
|
|
|
|
|
|
|
this.shakeInput();
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.addEvents();
|
|
|
|
|
},
|
|
|
|
|
addEvents: function(){
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'change', this.onChange, this);
|
|
|
|
|
if(!jcf.isTouchDevice) {
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, 'mousemove', this.onMouseMove, this);
|
|
|
|
|
jcf.lib.event.add(this.fakeElement, 'mouseover', this.recalcDimensions, this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onMouseMove: function(e){
|
|
|
|
|
this.realElement.style.top = Math.round(e.pageY - this.oTop - this.oHeight/2) + 'px';
|
|
|
|
|
this.realElement.style.left = (e.pageX - this.oLeft - this.oWidth + this.options.buttonWidth) + 'px';
|
|
|
|
|
},
|
|
|
|
|
onChange: function(){
|
|
|
|
|
this.refreshState();
|
|
|
|
|
},
|
|
|
|
|
getFileName: function(){
|
|
|
|
|
return this.realElement.value.replace(/^[\s\S]*(?:\\|\/)([\s\S^\\\/]*)$/g, "$1");
|
|
|
|
|
},
|
|
|
|
|
getFileExtension: function(){
|
|
|
|
|
return this.realElement.value.lastIndexOf('.') < 0 ? false : this.realElement.value.substring(this.realElement.value.lastIndexOf('.')+1).toLowerCase();
|
|
|
|
|
},
|
|
|
|
|
updateExtensionClass: function(){
|
|
|
|
|
var currentExtension = this.getFileExtension();
|
|
|
|
|
if(currentExtension) {
|
|
|
|
|
this.fakeElement.className = this.fakeElement.className.replace(new RegExp('(\\s|^)'+this.options.extPrefixClass+'[^ ]+','gi'),'')
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.extPrefixClass+currentExtension)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
shakeInput: function() {
|
|
|
|
|
// make input bigger
|
|
|
|
|
jcf.lib.setStyles(this.realElement, {
|
|
|
|
|
fontSize: this.options.bigFontSize,
|
|
|
|
|
lineHeight: this.options.bigFontSize,
|
|
|
|
|
heigth: 'auto',
|
|
|
|
|
top: 0,
|
|
|
|
|
left: this.inputWrapper.offsetWidth - this.realElement.offsetWidth
|
|
|
|
|
});
|
|
|
|
|
// IE styling fix
|
|
|
|
|
if((/(MSIE)/gi).test(navigator.userAgent)) {
|
|
|
|
|
this.tmpElement = document.createElement('span');
|
|
|
|
|
this.inputWrapper.insertBefore(this.tmpElement,this.realElement);
|
|
|
|
|
this.inputWrapper.insertBefore(this.realElement,this.tmpElement);
|
|
|
|
|
this.inputWrapper.removeChild(this.tmpElement);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
recalcDimensions: function() {
|
|
|
|
|
var o = jcf.lib.getOffset(this.fakeElement);
|
|
|
|
|
this.oTop = o.top;
|
|
|
|
|
this.oLeft = o.left;
|
|
|
|
|
this.oWidth = this.realElement.offsetWidth;
|
|
|
|
|
this.oHeight = this.realElement.offsetHeight;
|
|
|
|
|
},
|
|
|
|
|
refreshState: function(){
|
|
|
|
|
jcf.lib.setStyles(this.realElement, {opacity: 0});
|
|
|
|
|
this.fileNameInput.innerHTML = this.getFileName() || this.origTitle || '';
|
|
|
|
|
if(this.realElement.disabled) {
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.addClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
|
|
|
|
|
if(this.labelFor) {
|
|
|
|
|
jcf.lib.removeClass(this.labelFor, this.options.labelDisabledClass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.realElement.value.length) {
|
|
|
|
|
jcf.lib.removeClass(this.fakeElement, this.options.noFileClass);
|
|
|
|
|
} else {
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.noFileClass);
|
|
|
|
|
}
|
|
|
|
|
this.updateExtensionClass();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// custom textarea module
|
|
|
|
|
jcf.addModule({
|
|
|
|
|
name:'textarea',
|
|
|
|
|
selector: 'textarea',
|
|
|
|
|
defaultOptions: {
|
|
|
|
|
wrapperClass:'textarea-wrapper',
|
|
|
|
|
focusClass:'textarea-wrapper-focus',
|
|
|
|
|
cropMaskClass: 'scroll-cropper',
|
|
|
|
|
txtStructure:'<div class="control-wrapper"><div class="ctop"><div class="cleft"></div><div class="cright"></div></div><div class="cmid"><div class="chold"></div></div><div class="cbot"><div class="cleft"></div><div class="cright"></div></div></div>',
|
|
|
|
|
txtHolder: 'div.chold',
|
|
|
|
|
refreshInterval: 100
|
|
|
|
|
},
|
|
|
|
|
setupWrapper: function(){
|
|
|
|
|
jcf.lib.removeClass(this.realElement, jcf.baseOptions.hiddenClass);
|
|
|
|
|
jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
|
|
|
|
|
|
|
|
|
|
// create structure
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
|
|
|
|
|
this.fakeElement.innerHTML = this.options.txtStructure;
|
|
|
|
|
this.textareaHolder = jcf.lib.queryBySelector(this.options.txtHolder, this.fakeElement)[0];
|
|
|
|
|
this.textareaHolder.appendChild(this.realElement);
|
|
|
|
|
jcf.lib.enableTextSelection(this.fakeElement);
|
|
|
|
|
|
|
|
|
|
// init object and events
|
|
|
|
|
this.prepareElement();
|
|
|
|
|
this.refreshState();
|
|
|
|
|
this.addEvents();
|
|
|
|
|
this.addCustomScroll();
|
|
|
|
|
},
|
|
|
|
|
prepareElement: function() {
|
|
|
|
|
jcf.lib.setStyles(this.realElement, {
|
|
|
|
|
resize:'none',
|
|
|
|
|
overflow:'hidden',
|
|
|
|
|
verticalAlign:'top',
|
|
|
|
|
width: jcf.lib.getInnerWidth(this.realElement),
|
|
|
|
|
height: jcf.lib.getInnerHeight(this.realElement)
|
|
|
|
|
});
|
|
|
|
|
jcf.lib.setStyles(this.textareaHolder, {
|
|
|
|
|
width:this.realElement.offsetWidth
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
addCustomScroll: function() {
|
|
|
|
|
// call ready state, so scrollbars can attach here
|
|
|
|
|
this.onControlReady(this);
|
|
|
|
|
var origWidth = jcf.lib.getInnerWidth(this.realElement);
|
|
|
|
|
var barWidth = jcf.lib.scrollSize.getWidth();
|
|
|
|
|
|
|
|
|
|
// change text area size by scrollbar width
|
|
|
|
|
jcf.lib.setStyles(this.realElement, {
|
|
|
|
|
width: origWidth + barWidth,
|
|
|
|
|
overflowX: 'hidden',
|
|
|
|
|
overflowY: 'scroll',
|
|
|
|
|
direction: 'ltr'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// create crop mask
|
|
|
|
|
this.scrollCropper = jcf.lib.createElement('div',{
|
|
|
|
|
'class': this.options.cropMaskClass,
|
|
|
|
|
style: {
|
|
|
|
|
width: origWidth,
|
|
|
|
|
overflow: 'hidden'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.realElement.parentNode.insertBefore(this.scrollCropper, this.realElement);
|
|
|
|
|
this.scrollCropper.appendChild(this.realElement);
|
|
|
|
|
},
|
|
|
|
|
addEvents: function(){
|
|
|
|
|
this.delayedRefresh = jcf.lib.bind(this.delayedRefresh, this);
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'keydown', this.delayedRefresh);
|
|
|
|
|
jcf.lib.event.add(this.realElement, 'keyup', this.delayedRefresh);
|
|
|
|
|
},
|
|
|
|
|
onFocus: function(e) {
|
|
|
|
|
jcf.modules[this.name].superclass.onFocus.apply(this, arguments);
|
|
|
|
|
clearInterval(this.refreshTimer);
|
|
|
|
|
this.delayedRefresh();
|
|
|
|
|
this.refreshTimer = setInterval(this.delayedRefresh, this.options.refreshInterval);
|
|
|
|
|
},
|
|
|
|
|
onBlur: function() {
|
|
|
|
|
jcf.modules[this.name].superclass.onBlur.apply(this, arguments);
|
|
|
|
|
clearInterval(this.refreshTimer);
|
|
|
|
|
},
|
|
|
|
|
delayedRefresh: function() {
|
|
|
|
|
clearTimeout(this.delayTimer);
|
|
|
|
|
this.delayTimer = setTimeout(jcf.lib.bind(this.refreshState, this),10);
|
|
|
|
|
},
|
|
|
|
|
refreshState: function() {
|
|
|
|
|
if(this.scrollCropper) {
|
|
|
|
|
this.scrollCropper.scrollTop = this.scrollCropper.scrollLeft = 0;
|
|
|
|
|
this.scrollCropper.parentNode.scrollTop = 0;
|
|
|
|
|
}
|
|
|
|
|
// custom scrollbars will call this method before refreshing themself
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2016-03-16 17:30:07 +05:00
|
|
|
|
|
2016-03-28 20:07:51 +05:00
|
|
|
|
/*
|
|
|
|
|
* Simple star rating module
|
|
|
|
|
*/
|
|
|
|
|
function StarRating() {
|
|
|
|
|
this.options = {
|
|
|
|
|
activeClass:'active',
|
|
|
|
|
settedClass:'setted',
|
|
|
|
|
element:null,
|
|
|
|
|
items:null,
|
|
|
|
|
onselect:null
|
2016-03-16 17:30:07 +05:00
|
|
|
|
};
|
2016-03-28 20:07:51 +05:00
|
|
|
|
this.init.apply(this,arguments);
|
|
|
|
|
}
|
|
|
|
|
StarRating.prototype = {
|
|
|
|
|
init: function(opt){
|
|
|
|
|
this.setOptions(opt);
|
|
|
|
|
if(this.element) {
|
|
|
|
|
this.getElements();
|
|
|
|
|
this.addEvents();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setOptions: function(opt) {
|
|
|
|
|
for(var p in opt) {
|
|
|
|
|
if(opt.hasOwnProperty(p)) {
|
|
|
|
|
this.options[p] = opt[p];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.options.element) {
|
|
|
|
|
this.element = this.options.element;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getElements: function() {
|
|
|
|
|
// get switch objects
|
|
|
|
|
if(this.options.items === null) {
|
|
|
|
|
this.items = this.element.children;
|
|
|
|
|
} else {
|
|
|
|
|
if(typeof this.options.items === 'string') {
|
|
|
|
|
this.items = this.element.getElementsByTagName(this.options.items);
|
|
|
|
|
} else if(typeof this.options.items === 'object') {
|
|
|
|
|
this.items = this.options.items;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find default active index
|
|
|
|
|
for(var i = 0; i < this.items.length; i++) {
|
|
|
|
|
if(lib.hasClass(this.items[i],this.options.activeClass)) {
|
|
|
|
|
this.activeIndex = i;
|
|
|
|
|
}
|
|
|
|
|
if(lib.hasClass(this.items[i],this.options.settedClass)) {
|
|
|
|
|
this.settedIndex = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
addEvents: function() {
|
|
|
|
|
for(var i = 0; i < this.items.length; i++) {
|
|
|
|
|
this.items[i].onmouseover = lib.bind(this.overHandler, this, i);
|
|
|
|
|
this.items[i].onmouseout = lib.bind(this.outHandler, this, i);
|
|
|
|
|
this.items[i].onclick = lib.bind(this.clickHandler, this, i);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
overHandler: function(ind) {
|
|
|
|
|
this.hovering = true;
|
|
|
|
|
this.hoverIndex = ind;
|
|
|
|
|
this.refreshClasses();
|
|
|
|
|
},
|
|
|
|
|
outHandler: function(ind) {
|
|
|
|
|
this.hovering = false;
|
|
|
|
|
this.refreshClasses();
|
|
|
|
|
},
|
|
|
|
|
clickHandler: function(ind) {
|
|
|
|
|
this.hovering = false;
|
|
|
|
|
this.settedIndex = ind;
|
|
|
|
|
if(typeof this.options.onselect === 'function') {
|
|
|
|
|
this.options.onselect(ind);
|
|
|
|
|
}
|
|
|
|
|
this.refreshClasses();
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
refreshClasses: function() {
|
|
|
|
|
for(var i = 0; i < this.items.length; i++) {
|
|
|
|
|
lib.removeClass(this.items[i],this.options.activeClass);
|
|
|
|
|
lib.removeClass(this.items[i],this.options.settedClass);
|
|
|
|
|
}
|
|
|
|
|
if(this.hovering) {
|
|
|
|
|
lib.addClass(this.items[this.hoverIndex],this.options.activeClass);
|
|
|
|
|
} else {
|
|
|
|
|
if(typeof this.settedIndex === 'number') {
|
|
|
|
|
lib.addClass(this.items[this.settedIndex],this.options.settedClass);
|
|
|
|
|
} else {
|
|
|
|
|
if(typeof this.activeIndex === 'number') {
|
|
|
|
|
lib.addClass(this.items[this.activeIndex],this.options.activeClass);
|
2016-03-16 17:30:07 +05:00
|
|
|
|
}
|
2016-03-28 20:07:51 +05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Utility module
|
|
|
|
|
*/
|
|
|
|
|
lib = {
|
|
|
|
|
hasClass: function(el,cls) {
|
|
|
|
|
return el && el.className ? el.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')) : false;
|
|
|
|
|
},
|
|
|
|
|
addClass: function(el,cls) {
|
|
|
|
|
if (el && !this.hasClass(el,cls)) el.className += " "+cls;
|
|
|
|
|
},
|
|
|
|
|
removeClass: function(el,cls) {
|
|
|
|
|
if (el && this.hasClass(el,cls)) {el.className=el.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ');}
|
|
|
|
|
},
|
|
|
|
|
extend: function(obj) {
|
|
|
|
|
for(var i = 1; i < arguments.length; i++) {
|
|
|
|
|
for(var p in arguments[i]) {
|
|
|
|
|
if(arguments[i].hasOwnProperty(p)) {
|
|
|
|
|
obj[p] = arguments[i][p];
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-16 17:30:07 +05:00
|
|
|
|
}
|
2016-03-28 20:07:51 +05:00
|
|
|
|
return obj;
|
|
|
|
|
},
|
|
|
|
|
each: function(obj, callback) {
|
|
|
|
|
var property, len;
|
|
|
|
|
if(typeof obj.length === 'number') {
|
|
|
|
|
for(property = 0, len = obj.length; property < len; property++) {
|
|
|
|
|
if(callback.call(obj[property], property, obj[property]) === false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-03-16 17:30:07 +05:00
|
|
|
|
}
|
2016-03-28 20:07:51 +05:00
|
|
|
|
} else {
|
|
|
|
|
for(property in obj) {
|
|
|
|
|
if(obj.hasOwnProperty(property)) {
|
|
|
|
|
if(callback.call(obj[property], property, obj[property]) === false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
event: (function() {
|
|
|
|
|
var fixEvent = function(e) {
|
|
|
|
|
e = e || window.event;
|
|
|
|
|
if(e.isFixed) return e; else e.isFixed = true;
|
|
|
|
|
if(!e.target) e.target = e.srcElement;
|
|
|
|
|
e.preventDefault = e.preventDefault || function() {this.returnValue = false;};
|
|
|
|
|
e.stopPropagation = e.stopPropagation || function() {this.cancelBubble = true;};
|
|
|
|
|
return e;
|
|
|
|
|
};
|
|
|
|
|
return {
|
|
|
|
|
add: function(elem, event, handler) {
|
|
|
|
|
if(!elem.events) {
|
|
|
|
|
elem.events = {};
|
|
|
|
|
elem.handle = function(e) {
|
|
|
|
|
var ret, handlers = elem.events[e.type];
|
|
|
|
|
e = fixEvent(e);
|
|
|
|
|
for(var i = 0, len = handlers.length; i < len; i++) {
|
|
|
|
|
if(handlers[i]) {
|
|
|
|
|
ret = handlers[i].call(elem, e);
|
|
|
|
|
if(ret === false) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if(!elem.events[event]) {
|
|
|
|
|
elem.events[event] = [];
|
|
|
|
|
if(elem.addEventListener) elem.addEventListener(event, elem.handle, false);
|
|
|
|
|
else if(elem.attachEvent) elem.attachEvent('on'+event, elem.handle);
|
|
|
|
|
}
|
|
|
|
|
elem.events[event].push(handler);
|
|
|
|
|
},
|
|
|
|
|
remove: function(elem, event, handler) {
|
|
|
|
|
var handlers = elem.events[event];
|
|
|
|
|
for(var i = handlers.length - 1; i >= 0; i--) {
|
|
|
|
|
if(handlers[i] === handler) {
|
|
|
|
|
handlers.splice(i,1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!handlers.length) {
|
|
|
|
|
delete elem.events[event];
|
|
|
|
|
if(elem.removeEventListener) elem.removeEventListener(event, elem.handle, false);
|
|
|
|
|
else if(elem.detachEvent) elem.detachEvent('on'+event, elem.handle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}()),
|
|
|
|
|
queryElementsBySelector: function(selector, scope) {
|
|
|
|
|
scope = scope || document;
|
|
|
|
|
if(!selector) return [];
|
|
|
|
|
if(selector === '>*') return scope.children;
|
|
|
|
|
if(typeof document.querySelectorAll === 'function') {
|
|
|
|
|
return scope.querySelectorAll(selector);
|
|
|
|
|
}
|
|
|
|
|
var selectors = selector.split(',');
|
|
|
|
|
var resultList = [];
|
|
|
|
|
for(var s = 0; s < selectors.length; s++) {
|
|
|
|
|
var currentContext = [scope || document];
|
|
|
|
|
var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' ');
|
|
|
|
|
for (var i = 0; i < tokens.length; i++) {
|
|
|
|
|
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
|
|
|
|
|
if (token.indexOf('#') > -1) {
|
|
|
|
|
var bits = token.split('#'), tagName = bits[0], id = bits[1];
|
|
|
|
|
var element = document.getElementById(id);
|
|
|
|
|
if (element && tagName && element.nodeName.toLowerCase() != tagName) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
currentContext = element ? [element] : [];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (token.indexOf('.') > -1) {
|
|
|
|
|
var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements;
|
|
|
|
|
if (tagName == '*') {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName('*');
|
|
|
|
|
} else {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
}
|
|
|
|
|
for (var j = 0; j < elements.length; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0;
|
|
|
|
|
for (var k = 0; k < found.length; k++) {
|
|
|
|
|
if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) {
|
|
|
|
|
currentContext[currentContextIndex++] = found[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
|
|
|
|
|
var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4;
|
|
|
|
|
if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) {
|
|
|
|
|
attrName = 'htmlFor';
|
|
|
|
|
}
|
|
|
|
|
var found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements;
|
|
|
|
|
if (tagName == '*') {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName('*');
|
|
|
|
|
} else {
|
|
|
|
|
elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
}
|
|
|
|
|
for (var j = 0; elements[j]; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0, checkFunction;
|
|
|
|
|
switch (attrOperator) {
|
|
|
|
|
case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break;
|
|
|
|
|
case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break;
|
|
|
|
|
case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break;
|
|
|
|
|
case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break;
|
|
|
|
|
case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break;
|
|
|
|
|
case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break;
|
|
|
|
|
default : checkFunction = function(e) { return e.getAttribute(attrName) };
|
|
|
|
|
}
|
|
|
|
|
currentContext = [];
|
|
|
|
|
var currentContextIndex = 0;
|
|
|
|
|
for (var k = 0; k < found.length; k++) {
|
|
|
|
|
if (checkFunction(found[k])) {
|
|
|
|
|
currentContext[currentContextIndex++] = found[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
tagName = token;
|
|
|
|
|
var found = [], foundCount = 0;
|
|
|
|
|
for (var h = 0; h < currentContext.length; h++) {
|
|
|
|
|
var elements = currentContext[h].getElementsByTagName(tagName);
|
|
|
|
|
for (var j = 0; j < elements.length; j++) {
|
|
|
|
|
found[foundCount++] = elements[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentContext = found;
|
|
|
|
|
}
|
|
|
|
|
resultList = [].concat(resultList,currentContext);
|
|
|
|
|
}
|
|
|
|
|
return resultList;
|
|
|
|
|
},
|
|
|
|
|
trim: function (str) {
|
|
|
|
|
return str.replace(/^\s+/, '').replace(/\s+$/, '');
|
|
|
|
|
},
|
|
|
|
|
bind: function(f, scope, forceArgs){
|
|
|
|
|
return function() {return f.apply(scope, typeof forceArgs !== 'undefined' ? [forceArgs] : arguments);};
|
2016-03-16 17:30:07 +05:00
|
|
|
|
}
|
2016-03-28 20:07:51 +05:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*! Hammer.JS - v2.0.4 - 2014-09-28
|
|
|
|
|
* http://hammerjs.github.io/
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2014 Jorik Tangelder;
|
|
|
|
|
* Licensed under the MIT license */
|
|
|
|
|
if(Object.create){!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(k(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e<a.length;)b.call(c,a[e],e,a),e++;else for(e in a)a.hasOwnProperty(e)&&b.call(c,a[e],e,a)}function h(a,b,c){for(var e=Object.keys(b),f=0;f<e.length;)(!c||c&&a[e[f]]===d)&&(a[e[f]]=b[e[f]]),f++;return a}function i(a,b){return h(a,b,!0)}function j(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&h(d,c)}function k(a,b){return function(){return a.apply(b,arguments)}}function l(a,b){return typeof a==kb?a.apply(b?b[0]||d:d,b):a}function m(a,b){return a===d?b:a}function n(a,b,c){g(r(b),function(b){a.addEventListener(b,c,!1)})}function o(a,b,c){g(r(b),function(b){a.removeEventListener(b,c,!1)})}function p(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function q(a,b){return a.indexOf(b)>-1}function r(a){return a.trim().split(/\s+/g)}function s(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.length;){if(c&&a[d][c]==b||!c&&a[d]===b)return d;d++}return-1}function t(a){return Array.prototype.slice.call(a,0)}function u(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f];s(e,g)<0&&d.push(a[f]),e[f]=g,f++}return c&&(d=b?d.sort(function(a,c){return a[b]>c[b]}):d.sort()),d}function v(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g<ib.length;){if(c=ib[g],e=c?c+f:b,e in a)return e;g++}return d}function w(){return ob++}function x(a){var b=a.ownerDocument;return b.defaultView||b.parentWindow}function y(a,b){var c=this;this.manager=a,this.callback=b,this.element=a.element,this.target=a.options.inputTarget,this.domHandler=function(b){l(a.options.enable,[a])&&c.handler(b)},this.init()}function z(a){var b,c=a.options.inputClass;return new(b=c?c:rb?N:sb?Q:qb?S:M)(a,A)}function A(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=b&yb&&d-e===0,g=b&(Ab|Bb)&&d-e===0;c.isFirst=!!f,c.isFinal=!!g,f&&(a.session={}),c.eventType=b,B(a,c),a.emit("hammer.input",c),a.recognize(c),a.session.prevInput=c}function B(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(c.firstInput=E(b)),e>1&&!c.firstMultiple?c.firstMultiple=E(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=F(d);b.timeStamp=nb(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=J(h,i),b.distance=I(h,i),C(c,b),b.offsetDirection=H(b.deltaX,b.deltaY),b.scale=g?L(g.pointers,d):1,b.rotation=g?K(g.pointers,d):0,D(c,b);var j=a.element;p(b.srcEvent.target,j)&&(j=b.srcEvent.target),b.target=j}function C(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===yb||f.eventType===Ab)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function D(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Bb&&(i>xb||h.velocity===d)){var j=h.deltaX-b.deltaX,k=h.deltaY-b.deltaY,l=G(i,j,k);e=l.x,f=l.y,c=mb(l.x)>mb(l.y)?l.x:l.y,g=H(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function E(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:lb(a.pointers[c].clientX),clientY:lb(a.pointers[c].clientY)},c++;return{timeStamp:nb(),pointers:b,center:F(b),deltaX:a.deltaX,deltaY:a.deltaY}}function F(a){var b=a.length;if(1===b)return{x:lb(a[0].clientX),y:lb(a[0].clientY)};for(var c=0,d=0,e=0;b>e;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:lb(c/b),y:lb(d/b)}}function G(a,b,c){return{x:b/a||0,y:c/a||0}}function H(a,b){return a===b?Cb:mb(a)>=mb(b)?a>0?Db:Eb:b>0?Fb:Gb}function I(a,b,c){c||(c=Kb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function J(a,b,c){c||(c=Kb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function K(a,b){return J(b[1],b[0],Lb)-J(a[1],a[0],Lb)}function L(a,b){return I(b[0],b[1],Lb)/I(a[0],a[1],Lb)}function M(){this.evEl=Nb,this.evWin=Ob,this.allow=!0,this.presse
|
|
|
|
|
$(document).ready(function(){
|
|
|
|
|
//dropdown-menu width
|
|
|
|
|
var thisdrop = $(".dropleft .dropdown-menu li");
|
|
|
|
|
var total_dropwidth = thisdrop.width()*thisdrop.length;
|
|
|
|
|
$(".dropleft .dropdown-menu").css("width",total_dropwidth+"px");
|
|
|
|
|
//console.log(total);
|
|
|
|
|
});
|